From f961395b3fd50481840aebc69ea853ac1e4e0238 Mon Sep 17 00:00:00 2001 From: Kaan Date: Mon, 19 Oct 2026 17:44:42 +0300 Subject: [PATCH] Fix destroyed components staying in the output when a delayed cleanup errors --- src/indexes.luau | 3 ++- src/switch.luau | 3 ++- src/values.luau | 3 ++- test/tests.luau | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/indexes.luau b/src/indexes.luau index fe8416e..1189973 100644 --- a/src/indexes.luau +++ b/src/indexes.luau @@ -101,9 +101,10 @@ local function indexes( scope.value = nil -- set to nil for the `scope.value ~= v` check if scope.timeout == nil then scope.timeout = timeout(scope.delay, function() -- todo: possible redundant updates - scope.destroy() + local ok, err = pcall(scope.destroy) scopes[i] = nil update_output() + if not ok then error(err, 0) end end) end end diff --git a/src/switch.luau b/src/switch.luau index 0e74932..bb4a1f1 100644 --- a/src/switch.luau +++ b/src/switch.luau @@ -50,9 +50,10 @@ local function switch_map( else if scope.timeout == nil then scope.timeout = timeout(scope.delay, function() - scope.destroy() + local ok, err = pcall(scope.destroy) scopes[k] = nil update_output() + if not ok then error(err, 0) end end) end end diff --git a/src/values.luau b/src/values.luau index 33bc5e4..b59fd0e 100644 --- a/src/values.luau +++ b/src/values.luau @@ -111,9 +111,10 @@ local function values( scope.index = nil -- set to nil for the `scope.index ~= i` check if scope.timeout == nil then scope.timeout = timeout(scope.delay, function() -- todo: possible redundant updates - scope.destroy() + local ok, err = pcall(scope.destroy) scopes[v] = nil update_output() + if not ok then error(err, 0) end end) end end diff --git a/test/tests.luau b/test/tests.luau index cd9cd1d..75885a7 100644 --- a/test/tests.luau +++ b/test/tests.luau @@ -1539,6 +1539,25 @@ TEST("switch()", wrap_root(function() do CASE "delay" -- probably unneeded because show() uses switch() internally end + + do CASE "delay with cleanup error" + local input = source(1) + local errored = false + + local output = switch(input) { + [1] = function() + cleanup(function() + if not errored then errored = true; error("cleanup error") end + end) + return 1, 1 + end, + [2] = function() return 2 end + } + + input(2) + CHECK(not pcall(step, 1 + 0.01)) + CHECK(output() == 2) + end end)) TEST("indexes()", wrap_root(function() @@ -1809,6 +1828,23 @@ TEST("indexes()", wrap_root(function() CHECK(cleaned_counts[2] == 1) end end + + do CASE "delay with cleanup error" + local input = source { 1 } + local errored = false + + local output = indexes(input, function() + cleanup(function() + if not errored then errored = true; error("cleanup error") end + end) + return {}, 1 + end) + + input {} + CHECK(#output() == 1) + CHECK(not pcall(step, 1 + 0.01)) + CHECK(#output() == 0) + end end)) TEST("values()", wrap_root(function() @@ -2024,6 +2060,23 @@ TEST("values()", wrap_root(function() --CHECK(count == 3) CHECK(count == 5) end + + do CASE "delay with cleanup error" + local input = source { 1 } + local errored = false + + local output = values(input, function() + cleanup(function() + if not errored then errored = true; error("cleanup error") end + end) + return {}, 1 + end) + + input {} + CHECK(#output() == 1) + CHECK(not pcall(step, 1 + 0.01)) + CHECK(#output() == 0) + end end)) TEST("spring()", wrap_root(function()