diff --git a/src/init.luau b/src/init.luau index 1a91ffb..4443f85 100644 --- a/src/init.luau +++ b/src/init.luau @@ -16,6 +16,7 @@ local derive = require(script.derive) local cleanup = require(script.cleanup) local untrack = require(script.untrack) local parent = require(script._parent) +local sibling = require(script.sibling) local read = require(script.read) local batch = require(script.batch) local context = require(script.context) @@ -70,6 +71,7 @@ local vide = { cleanup = cleanup, untrack = untrack, parent = parent, + sibling = sibling, read = read, batch = batch, context = context, diff --git a/src/sibling.luau b/src/sibling.luau new file mode 100644 index 0000000..fb401d1 --- /dev/null +++ b/src/sibling.luau @@ -0,0 +1,32 @@ +if not game then script = require "test/relative-string" end + +local graph = require(script.Parent.graph) +type Node = graph.Node + +export type Source = (() -> T) & ((value: T) -> T) + +local function sibling(fn: () -> T): (() -> (), T) + local node = graph.get_scope() + if not node then error("") end + + local parent_node = node.owner + if not parent_node then error("") end + + local sibling = graph.create_node(parent_node :: Node, false, false) + + graph.push_scope(sibling) + + local ok, result = pcall(fn) + + graph.pop_scope() + + if not ok then error(result, 0) end + + local function destroy() + graph.destroy(sibling) + end + + return destroy, result +end + +return sibling :: ((fn: () -> T) -> (() -> (), T)) & ((fn: () -> ()) -> () -> ()) diff --git a/test/tests.luau b/test/tests.luau index be1c65a..d513452 100644 --- a/test/tests.luau +++ b/test/tests.luau @@ -1825,6 +1825,43 @@ TEST("parent()", function() end end) +TEST("sibling()", function() + local root = vide.root + local source = vide.source + local effect = vide.effect + local sibling = vide.sibling + local context = vide.context + local cleanup = vide.cleanup + local untrack = vide.untrack + + local ctx = context(0) + local src = source(0) + + local cleanup_count = 0 + local ran = false + + local destroy = root(function() + ctx(1, function() + effect(function() + src() + if not ran then ran = true + sibling(function() + effect(function() + cleanup(function() cleanup_count += 1 end) + CHECK(ctx() == 1) + end) + end) + end + end) + end) + end) + + src(1) + CHECK(cleanup_count == 0) + destroy() + CHECK(cleanup_count == 1) +end) + TEST("events", function() local create = vide.create