Skip to content

Commit 3e25bd6

Browse files
committed
Fix world:get returning nil after root archetype churn and unrelated delete
1 parent 3087601 commit 3e25bd6

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

src/jecs.luau

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2976,6 +2976,10 @@ local function world_new(DEBUG: boolean?)
29762976
-- If there was a previous archetype, then the entity needs to move the archetype
29772977
inner_entity_move(entity, record, to)
29782978
else
2979+
-- An entity moved back to root keeps a real slot in root.entities; remove it before the append, else a later delete of any root entity stomps this record's row.
2980+
if record.row ~= 0 then
2981+
archetype_delete(world, src, record.row)
2982+
end
29792983
new_entity(entity, record, to)
29802984
end
29812985

@@ -3074,6 +3078,10 @@ local function world_new(DEBUG: boolean?)
30743078
if not src_is_root_archetype then
30753079
inner_entity_move(entity, record, to)
30763080
else
3081+
-- An entity moved back to root keeps a real slot in root.entities; remove it before the append, else a later delete of any root entity stomps this record's row.
3082+
if record.row ~= 0 then
3083+
archetype_delete(world, src, record.row)
3084+
end
30773085
if #to.types > 0 then
30783086
new_entity(entity, record, to)
30793087
end

test/tests.luau

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,32 @@ TEST("reproduce idr_t nil archetype bug", function()
268268
end
269269
end)
270270

271+
TEST("get after root archetype churn and unrelated delete", function()
272+
local world = jecs.world(true)
273+
local C3 = world:component()
274+
local C4 = world:component()
275+
276+
-- Entity a churns through root: gains C3, loses it (back to root), gains C4
277+
local a = world:entity()
278+
world:set(a, C3, 490494)
279+
world:remove(a, C3)
280+
world:set(a, C4, 892027)
281+
282+
-- Deleting any root-resident entity used to stomp a's record.row
283+
local b = world:entity()
284+
world:delete(b)
285+
286+
CHECK(world:get(a, C4) == 892027)
287+
CHECK(world:has(a, C4))
288+
local found
289+
for e, v in world:query(C4) do
290+
if e == a then
291+
found = v
292+
end
293+
end
294+
CHECK(found == 892027)
295+
end)
296+
271297
TEST("Ensure archetype edges get cleaned", function()
272298
local A = jecs.component()
273299
local B = jecs.component()

0 commit comments

Comments
 (0)