Fix unit tests and debug mode to enforce OnRemove rules

This commit is contained in:
Ukendio 2024-09-21 20:53:12 +02:00
parent 1de93f9185
commit 5d6c2e8d42
2 changed files with 32 additions and 3 deletions

View file

@ -1613,7 +1613,7 @@ if _G.__JECS_DEBUG then
throw(msg) throw(msg)
end end
local function get_name(world, id): string | number local function get_name(world, id): string
local name: string | nil local name: string | nil
if ECS_IS_PAIR(id) then if ECS_IS_PAIR(id) then
name = `pair({get_name(world, ECS_ENTITY_T_HI(id))}, {get_name(world, ECS_ENTITY_T_LO(id))})` name = `pair({get_name(world, ECS_ENTITY_T_HI(id))}, {get_name(world, ECS_ENTITY_T_LO(id))})`
@ -1634,6 +1634,14 @@ if _G.__JECS_DEBUG then
return not world_has_one_inline(world, ECS_ENTITY_T_HI(id), EcsComponent) return not world_has_one_inline(world, ECS_ENTITY_T_HI(id), EcsComponent)
end end
local original_invoke_hook = invoke_hook
local invoked_hook = false
invoke_hook = function(...)
invoked_hook = true
original_invoke_hook(...)
invoked_hook = false
end
World.query = function(world: World, ...) World.query = function(world: World, ...)
ASSERT((...), "Requires at least a single component") ASSERT((...), "Requires at least a single component")
return world_query(world, ...) return world_query(world, ...)
@ -1658,6 +1666,19 @@ if _G.__JECS_DEBUG then
return return
end end
if world_has_one_inline(world, entity, id) then
if invoked_hook then
local file, line = debug.info(2, "sl")
local hook_fn = `{file}::{line}`
throw(
([[cannot call world:set within the
This world:set function invokes a structural change because %s doesn't exist on the entity.\n
call world:add when the hook %s is in process]]):format(get_name(world, id), hook_fn))
end
end
world_set(world, entity, id, value) world_set(world, entity, id, value)
end end
@ -1670,6 +1691,10 @@ if _G.__JECS_DEBUG then
return return
end end
if invoked_hook then
local hook_fn = debug.info(2, "sl")
throw(`Cannot call world:add when the hook {hook_fn} is in process`)
end
world_add(world, entity, id) world_add(world, entity, id)
end end
@ -1704,6 +1729,10 @@ if _G.__JECS_DEBUG then
end end
return world_target(world, entity, relation, index) return world_target(world, entity, relation, index)
end end
World.remove = function()
end
end end
function World.new() function World.new()

View file

@ -1328,14 +1328,14 @@ TEST("Hooks", function()
world:set(A, jecs.OnRemove, function(entity) world:set(A, jecs.OnRemove, function(entity)
world:set(entity, B, true) world:set(entity, B, true)
CHECK(not world:get(entity, A)) CHECK(world:get(entity, A))
CHECK(world:get(entity, B)) CHECK(world:get(entity, B))
end) end)
world:set(e, A, true) world:set(e, A, true)
world:remove(e, A) world:remove(e, A)
CHECK(not world:get(e, A)) CHECK(not world:get(e, A))
CHECK(world:get(e, B)) CHECK(not world:get(e, B))
end end
end end