feat: derive no longer run twice

This commit is contained in:
ernisto 2025-04-10 21:06:35 -03:00
parent 7350cf1c54
commit fb30f84596
2 changed files with 31 additions and 56 deletions

View file

@ -163,53 +163,28 @@ local update_queue = { n = 0 } :: { n: number, [number]: Node<any> }
local function evaluate_node<T>(node: Node<T>) local function evaluate_node<T>(node: Node<T>)
if node.higher_parent_update_id == node.last_eval_update_id then return node.needs_queue_children end if node.higher_parent_update_id == node.last_eval_update_id then return node.needs_queue_children end
if flags.strict then local cur_value = node.cache
local initial_value = node.cache
for i = 1, 2 do flush_cleanups(node)
local cur_value = node.cache destroy_owned(node)
flush_cleanups(node) push_scope(node)
destroy_owned(node) local ok, new_value = (if flags.strict then ycall else pcall :: any)(node.effect :: (T) -> T, node.cache)
pop_scope()
push_scope(node) if not ok then
local ok, new_value = ycall(node.effect :: (T) -> T, cur_value) table.clear(update_queue)
pop_scope() update_queue.n = 0
error(`effect error:\n{new_value}`, 0)
if not ok then
table.clear(update_queue)
update_queue.n = 0
error(`effect error stacktrace\n{new_value :: string}`, 0)
end
node.cache = new_value :: T
end
local needs_queue_children = not is_similar(initial_value, node.cache)
node.needs_queue_children = needs_queue_children
node.last_eval_update_id = update_id
return needs_queue_children
else
local cur_value = node.cache
flush_cleanups(node)
destroy_owned(node)
push_scope(node)
local ok, new_value = pcall(node.effect :: (T) -> T, node.cache)
pop_scope()
if not ok then
table.clear(update_queue)
update_queue.n = 0
error(`effect error:\n{new_value}\n`, 0)
end
local needs_queue_children = not is_similar(cur_value, new_value)
node.needs_queue_children = needs_queue_children
node.last_eval_update_id = update_id
node.cache = new_value
return needs_queue_children
end end
local needs_queue_children = not is_similar(cur_value, new_value)
node.needs_queue_children = needs_queue_children
node.last_eval_update_id = update_id
node.cache = new_value
return needs_queue_children
end end
local function queue_children_for_update<T>(node: SourceNode<T>) local function queue_children_for_update<T>(node: SourceNode<T>)

View file

@ -1221,24 +1221,24 @@ TEST("show()", wrap_root(function()
branch = 1 branch = 1
weapon { id = "1", enchant = "fire" } weapon { id = "1", enchant = "fire" }
CHECK(count == 8) CHECK(count == 1)
branch = 2 branch = 2
weapon { id = "1", enchant = "poison" } weapon { id = "1", enchant = "poison" }
CHECK(count == 10) CHECK(count == 2)
weapon { id = "1", enchant = nil } weapon { id = "1", enchant = nil }
CHECK(count == 10) CHECK(count == 2)
branch = 1 branch = 1
weapon { id = "1", enchant = "fire" } weapon { id = "1", enchant = "fire" }
CHECK(count == 14) CHECK(count == 3)
weapon(nil) weapon(nil)
branch = 2 branch = 2
weapon { id = "1", enchant = "poison" } weapon { id = "1", enchant = "poison" }
CHECK(count == 22) CHECK(count == 4)
vide.strict = false vide.strict = false
end end
@ -2763,9 +2763,9 @@ TEST("strict", wrap_root(function()
return src() return src()
end) end)
CHECK(count == 2) CHECK(count == 1)
src(2) src(2)
CHECK(count == 4) CHECK(count == 2)
end end
do CASE "run effect callback twice" do CASE "run effect callback twice"
@ -2777,9 +2777,9 @@ TEST("strict", wrap_root(function()
src() src()
end) end)
CHECK(count == 2) CHECK(count == 1)
src(2) src(2)
CHECK(count == 4) CHECK(count == 2)
end end
do CASE "indexes() error if primitive" do CASE "indexes() error if primitive"
@ -2841,9 +2841,9 @@ TEST("strict", wrap_root(function()
return count return count
end, count) end, count)
CHECK(count == 2) CHECK(count == 1)
src(not src()) src(not src())
CHECK(count == 4) CHECK(count == 2)
end end
do CASE "effect using derived source" do CASE "effect using derived source"
@ -2860,11 +2860,11 @@ TEST("strict", wrap_root(function()
count += 1 count += 1
end) end)
CHECK(count == 2) CHECK(count == 1)
input(false) input(false)
CHECK(count == 4) CHECK(count == 2)
end end
do CASE "destruction of active scope" do CASE "destruction of active scope"