Make root() return destructor automatically

This commit is contained in:
aaron 2024-10-06 15:37:05 +01:00
parent 8142acd1c1
commit 82eec61c45
8 changed files with 26 additions and 30 deletions

View file

@ -10,7 +10,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- `context()`
- `context()`.
### Changed
- `root()` now returns its destructor as the first value by default.
### Fixed

View file

@ -14,18 +14,15 @@ Creates and runs a function in a new stable scope.
- **Type**
```lua
function root<T...>(fn: (destroy: () -> ()) -> T...): T...
function root<T...>(fn: (() -> ()) -> T...): (() -> (), T...)
```
- **Details**
Returns the result of the given function.
Returns a function to destroy the root scope. Also passes this function as
the first argument into its callback.
Creates a new stable scope, where creation of effects can be tracked and
properly disposed of.
A function to destroy the root is passed into the callback, which will run
any cleanups and allow derived sources created to garbage collect.
All values returned by the callback are also returned following the destructor.
## source()

View file

@ -81,9 +81,8 @@ mount(function()
effect(function()
if toggled() then
local destroy = root(function(destroy)
local destroy = root(function()
Counter()
return destroy
end)
cleanup(destroy)
end

View file

@ -13,15 +13,13 @@ local effect = vide.effect
local count = source(0)
local destroy = root(function(destroy)
local destroy = root(function()
effect(function()
local x = count()
cleanup(function() print(x) end)
end)
cleanup(function() print "root destroyed" end)
return destroy
end)
count(1) -- prints "0"

View file

@ -43,21 +43,20 @@ local count = root(setup) -- ok since effect() was called within a stable scope
count(1) -- prints "1"
```
The scope created by `root()` can be destroyed by calling the function it passes
into the given function.
The scope created by `root()` can be destroyed.
```lua
local function setup(destroy)
local function setup()
local count = source(0)
effect(function()
print(count())
end)
return count, destroy
return count
end
local count, destroy = root(setup)
local destroy, count = root(setup)
count(1) -- prints "1"

View file

@ -4,10 +4,9 @@ local root = require(script.Parent.root)
local apply = require(script.Parent.apply)
local function mount<T>(component: () -> T, target: Instance?): () -> ()
return root(function(destroy)
return root(function()
local result = component()
if target then apply(target, { result }) end
return destroy
end)
end

View file

@ -10,7 +10,7 @@ local destroy = graph.destroy
local refs = {}
local function root<T...>(fn: (destroy: () -> ()) -> T...): T...
local function root<T...>(fn: (destroy: () -> ()) -> T...): (() -> (), T...)
local node = create_node(false, false, false)
refs[node] = true -- prevent gc of root node
@ -33,7 +33,7 @@ local function root<T...>(fn: (destroy: () -> ()) -> T...): T...
throw(`error while running root():\n\n{result[2]}`)
end
return unpack(result :: any, 2)
return destroy, unpack(result :: any, 2)
end
return root :: (<T...>(fn: (destroy: () -> ()) -> T...) -> T...) & ((fn: (destroy: () -> ()) -> ()) -> ())
return root :: <T...>(fn: (destroy: () -> ()) -> T...) -> (() -> (), T...)

View file

@ -892,7 +892,7 @@ TEST("create()", wrap_root(function()
end
do CASE "parent bound to source"
local wref, destroy = vide.root(function(destroy)
local _, wref, destroy = vide.root(function(destroy)
local frame = create "Frame" { Name = "Parent" }
local parent = source(frame :: Frame?)
@ -1228,7 +1228,7 @@ TEST("indexes()", wrap_root(function()
local count = table.create(3, 0)
local output = vide.root(function()
local _, output = vide.root(function()
local output = indexes(input, function(v, i)
count[i] += 1
return v
@ -1690,7 +1690,7 @@ TEST("untrack()", wrap_root(function()
local input = source(0)
local output, destroy = root(function(destroy)
local _, output, destroy = root(function(destroy)
local output = derive(function()
outer_count += 1
@ -1820,7 +1820,7 @@ TEST("changed()", wrap_root(function()
end
do CASE "connection disconnected"
local text, destroy = root(function(destroy)
local _, text, destroy = root(function(destroy)
local output = source(nil)
return create "TextLabel" {
@ -2397,7 +2397,7 @@ TEST("graph edge cases", wrap_root(function()
do CASE "do not destroy children"
local parent = source(0)
local
local _,
destroy,
parent_to_destroy,
update_parent_to_destroy
@ -2440,7 +2440,7 @@ TEST("graph edge cases", wrap_root(function()
-- child B reevaluates due to already being queued
-- parent destroys, destroys child B - uh oh
local
local _,
destroy_parent,
parent,
update_parent
@ -2452,7 +2452,7 @@ TEST("graph edge cases", wrap_root(function()
src
end)
local destroy_child, _child_B = function() end, nil
local _, destroy_child, _child_B = nil, function() end, nil
local count_A = 0