Hi, the function node.get_properties_table returns a tabe which does not contain the actual node properties and also doesn't allow setting the node properties. See for example \directlua{ node.set_properties_mode(true, true) } \directlua{ local indirectprops = node.get_properties_table() local directprops = node.direct.get_properties_table() local n = node.new'glue' % Type doesn't really matter local p = {} node.setproperty(n, p) assert(node.getproperty(n) == p, "Assert failed: getproperty after setproperty") % works fine local directn = node.direct.todirect(n) assert(node.direct.getproperty(directn) == p, "Assert failed: direct.getproperty after setproperty") % works fine assert(directprops[directn] == p, "Assert failed: direct.get_properties_table after setproperty") % works fine assert(indirectprops[n] == p, "Assert failed: get_properties_table after setproperty") % This breaks node.free(n) } \bye Here a property is set using node.setproperty and then we try to access it through different methods. All of them work, except for node.get_properties_table because this uses a different table which is unrelated to the actual property table returned by e.g. node.direct.get_properties_table. This issue appear because the metatable __index and __newindex functions for node.get_properties_table set the property in the table passed as first parameter, which is the (non-direct) node.get_properties_table table instead of node.direct.get_properties_table(). Here is a possible fix which passes the actual property table as upvalue to the metafunctions: --- source/texk/web2c/luatexdir/lua/lnodelib.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/texk/web2c/luatexdir/lua/lnodelib.c b/source/texk/web2c/luatexdir/lua/lnodelib.c index d5ab00a55..4e713aaa2 100644 --- a/source/texk/web2c/luatexdir/lua/lnodelib.c +++ b/source/texk/web2c/luatexdir/lua/lnodelib.c @@ -8406,7 +8406,7 @@ static int lua_nodelib_get_property_t(lua_State * L) if (n == null) { lua_pushnil(L); } else { - lua_rawgeti(L,1,n); + lua_rawgeti(L,lua_upvalueindex(1),n); } return 1; } @@ -8417,7 +8417,7 @@ static int lua_nodelib_set_property_t(lua_State * L) halfword n = *((halfword *) lua_touserdata(L, 2)); if (n != null) { lua_settop(L,3); - lua_rawseti(L,1,n); + lua_rawseti(L,lua_upvalueindex(1),n); } return 0; } @@ -8831,16 +8831,19 @@ static const struct luaL_Reg nodelib_p[] = { static void lua_new_properties_table(lua_State * L) { - lua_pushstring(L,"node.properties"); lua_newtable(L); + lua_pushstring(L,"node.properties"); + lua_pushvalue(L,-2); lua_settable(L,LUA_REGISTRYINDEX); lua_pushstring(L,"node.properties.indirect"); lua_newtable(L); luaL_newmetatable(L,"node.properties.indirect.meta"); - luaL_openlib(L, NULL, nodelib_p, 0); + lua_pushvalue(L,-4); + luaL_openlib(L, NULL, nodelib_p, 1); lua_setmetatable(L,-2); lua_settable(L,LUA_REGISTRYINDEX); + lua_pop(L,1); } /* node.direct.* */ -- 2.26.0 Best regards, Marcel