diff --git a/lvm.c b/lvm.c index f9e87b61..f83d47d1 100644 --- a/lvm.c +++ b/lvm.c @@ -360,13 +360,19 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, luaT_callTM(L, tm, t, key, val); return; } - t = tm; /* else repeat assignment over 'tm' */ - luaV_fastset(t, key, val, hres, luaH_pset); - if (hres == HOK) { - luaV_finishfastset(L, t, val); - return; /* done */ + t = tm; /* else must repeat assignment over 'tm' */ + /* do the equivalent to 'luaV_fastset', but saving 'h' */ + if (!ttistable(t)) + hres = HNOTATABLE; + else { + Table *h = hvalue(t); /* next call can change the value at 't' */ + hres = luaH_pset(h, key, val); + if (hres == HOK) { + luaC_barrierback(L, obj2gco(h), val); /* luaV_finishfastset */ + return; /* done */ + } } - /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ + /* else 'return luaV_finishset(L, t, key, val, hres)' (loop) */ } luaG_runerror(L, "'__newindex' chain too long; possible loop"); } diff --git a/testes/events.lua b/testes/events.lua index 7e434b1f..fa9966ab 100644 --- a/testes/events.lua +++ b/testes/events.lua @@ -390,6 +390,18 @@ do for i=1, 10 do t[i] = 1 end end + +do -- bug since 5.4 + local parent = {} + parent.__newindex = parent + collectgarbage() + local child = setmetatable({}, parent) + child.__newindex = {x = "hello"} + collectgarbage("step") + assert(parent.__newindex.x == "hello") +end + + -- concat metamethod x numbers (bug in 5.1.1) c = {} local x