From 0897821e1fa3847b43d278fb6a287540ff55c3ea Mon Sep 17 00:00:00 2001 From: aaron <83140718+centau@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:56:22 +0000 Subject: [PATCH] Add check for destruction of active scope --- docs/api/strict-mode.md | 3 ++- src/graph.luau | 8 ++++++- test/tests.luau | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/docs/api/strict-mode.md b/docs/api/strict-mode.md index d3ce5cb..630a7bd 100644 --- a/docs/api/strict-mode.md +++ b/docs/api/strict-mode.md @@ -19,7 +19,8 @@ Currently, strict mode will: 3. Checks for `indexes()` and `values()` outputting primitive values. 4. Checks for `values()` input having duplicate values. 5. Checks for duplicate nested properties at same depth. -6. Better error reporting and stack traces + creation traces of property bindings. +6. Checks for destruction of an active scope. +7. Better error reporting and stack traces + creation traces of property bindings. By rerunning reactive scopes twice each time they update, it helps ensure that computations are pure, and that any cleanup is done correctly. diff --git a/src/graph.luau b/src/graph.luau index 9648180..1495a59 100644 --- a/src/graph.luau +++ b/src/graph.luau @@ -108,6 +108,10 @@ local function unparent(node: Node) end local function destroy(node: Node) + if flags.strict and table.find(scopes, node) then + throw("attempt to destroy an active scope") + end + flush_cleanups(node) unparent(node) @@ -296,5 +300,7 @@ return table.freeze { flush_update_queue = flush_update_queue, get_update_queue_length = get_update_queue_length, set_context = set_context, - scopes = scopes + scopes = scopes, + + q = update_queue } diff --git a/test/tests.luau b/test/tests.luau index 45aa41f..395b568 100644 --- a/test/tests.luau +++ b/test/tests.luau @@ -2483,11 +2483,14 @@ end)) TEST("strict", wrap_root(function() vide.strict = true + local root = vide.root + local show = vide.show local create = vide.create local source = vide.source local derive = vide.derive local effect = vide.effect local indexes, values = vide.indexes, vide.values + local untrack = vide.untrack do CASE "error on derived callback yield" local src = source(1) @@ -2627,6 +2630,56 @@ TEST("strict", wrap_root(function() CHECK(count == 4) end + + do CASE "destruction of active scope" + local src = source(false) + + root(function() + show(src, function() + src(false) + return {} + end) + end) + + local ok = pcall(function() + src(true) + end) + + CHECK(not ok) + end + + -- todo: review intended behavior here + -- do CASE "destruction of active scope in indexes" + -- local src = source {} + + -- local tmp + -- root(function() + -- effect(function() + -- untrack(function() + -- tmp = indexes(src, function() + -- vide.cleanup(function() print "test" end) + -- src {} + -- print "updated" + -- vide.cleanup(function() print "test2" end) + -- print "end" + -- return {} + -- end) + -- return nil + -- end) + -- end) + -- end) + + -- print "setting" + + -- local ok = pcall(function() + -- src { 1 } + -- print "done" + -- end) + + -- print(#tmp()) + + -- CHECK(not ok) + -- end end)) local ok = FINISH()