mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
This commit is contained in:
parent
bbe634f433
commit
31b1956b5a
6 changed files with 54 additions and 41 deletions
|
|
@ -9,7 +9,7 @@ Creates and runs a function in a new reactive scope.
|
|||
- **Type**
|
||||
|
||||
```lua
|
||||
function root<T>(fn: () -> T): (T, () -> ())
|
||||
function root<T...>(fn: (destroy: () -> ()) -> T...): T...
|
||||
```
|
||||
|
||||
- **Details**
|
||||
|
|
@ -19,8 +19,8 @@ Creates and runs a function in a new reactive scope.
|
|||
|
||||
Returns the result of the given function.
|
||||
|
||||
Also returns a function to destroy the root, which will run any cleanups
|
||||
and allow derived sources created to garbage collect.
|
||||
A function to destroy the root is passed into the callback, which will run
|
||||
any cleanups and allow derived sources created to garbage collect.
|
||||
|
||||
::: warning
|
||||
`fn()` cannot yield.
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ local function destroy<T>(node: Node<T>)
|
|||
run_cleanups(node)
|
||||
unparent(node)
|
||||
|
||||
node.effect = false
|
||||
|
||||
if node.parents.owner then
|
||||
remove_child(node.parents.owner, node)
|
||||
node.parents.owner = nil
|
||||
|
|
|
|||
|
|
@ -3,14 +3,12 @@ if not game then script = require "test/relative-string" end
|
|||
local root = require(script.Parent.root)
|
||||
local apply = require(script.Parent.apply)
|
||||
|
||||
local function mount<T>(app: () -> T, target: Instance?): () -> ()
|
||||
local _, destroy = root(function()
|
||||
local result = app()
|
||||
local function mount<T>(component: () -> T, target: Instance?): () -> ()
|
||||
return root(function(destroy)
|
||||
local result = component()
|
||||
if target then apply(target, { result }) end
|
||||
return nil
|
||||
return destroy
|
||||
end)
|
||||
|
||||
return destroy
|
||||
end
|
||||
|
||||
return mount
|
||||
return mount :: (<T>(component: () -> T, target: Instance) -> () -> ()) & ((component: () -> ()) -> () -> ())
|
||||
|
|
|
|||
|
|
@ -10,25 +10,29 @@ local destroy = graph.destroy
|
|||
|
||||
local refs = {}
|
||||
|
||||
local function root<T>(fn: () -> T): (T, () -> ())
|
||||
local function root<T...>(fn: (destroy: () -> ()) -> T...): T...
|
||||
local node = create_node(false, false)
|
||||
|
||||
open_scope(node)
|
||||
|
||||
local ok, result = pcall(fn)
|
||||
|
||||
close_scope()
|
||||
|
||||
if not ok then
|
||||
throw(`mount error\n{result}`)
|
||||
end
|
||||
|
||||
refs[node] = true -- prevent gc of root node
|
||||
|
||||
return result, function()
|
||||
local destroy = function()
|
||||
if not refs[node] then throw "root already destroyed" end
|
||||
refs[node] = nil
|
||||
destroy(node)
|
||||
end
|
||||
|
||||
open_scope(node)
|
||||
|
||||
local result = { pcall(fn, destroy) }
|
||||
|
||||
close_scope()
|
||||
|
||||
if not result[1] then
|
||||
refs[node] = nil
|
||||
throw(`mount error\n{result}`)
|
||||
end
|
||||
|
||||
return unpack(result :: any, 2)
|
||||
end
|
||||
|
||||
return root :: (<T>(fn: () -> T) -> (T, () -> ())) & ((fn: () -> ()) -> (nil, () -> ()))
|
||||
return root :: (<T...>(fn: (destroy: () -> ()) -> T...) -> T...) & ((fn: (destroy: () -> ()) -> ()) -> ())
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ end
|
|||
local N = 2^18 -- 262144
|
||||
|
||||
local function WRAP_BENCH(name: string, fn: () -> ())
|
||||
local _, destroy = vide.root(function()
|
||||
vide.root(function(destroy)
|
||||
BENCH(name, fn)
|
||||
end)
|
||||
destroy()
|
||||
return destroy
|
||||
end)()
|
||||
end
|
||||
|
||||
TITLE "sources"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ end
|
|||
|
||||
local function wrap_root(fn: () -> ())
|
||||
return function()
|
||||
local _, destroy = vide.root(fn :: any)
|
||||
local destroy = vide.mount(fn :: any)
|
||||
destroy()
|
||||
end
|
||||
end
|
||||
|
|
@ -289,6 +289,20 @@ TEST("mount()", function()
|
|||
CHECK(count == 1)
|
||||
end)
|
||||
|
||||
TEST("root()", function()
|
||||
local root = vide.root
|
||||
local cleanup = vide.cleanup
|
||||
|
||||
local count = 0
|
||||
|
||||
root(function(destroy)
|
||||
cleanup(function() count += 1 end)
|
||||
destroy()
|
||||
end)
|
||||
|
||||
CHECK(count == 1)
|
||||
end)
|
||||
|
||||
TEST("source()", wrap_root(function()
|
||||
local source = vide.source
|
||||
local effect = vide.effect
|
||||
|
|
@ -357,7 +371,6 @@ TEST("source()", wrap_root(function()
|
|||
end))
|
||||
|
||||
TEST("derive()", wrap_root(function()
|
||||
local root = vide.root
|
||||
local source = vide.source
|
||||
local derive = vide.derive
|
||||
local effect = vide.effect
|
||||
|
|
@ -450,7 +463,7 @@ TEST("derive()", wrap_root(function()
|
|||
local count = 0
|
||||
local a = source(0)
|
||||
|
||||
local _, destroy = root(function()
|
||||
local destroy = vide.mount(function()
|
||||
|
||||
local _b = derive(function()
|
||||
cleanup(function()
|
||||
|
|
@ -542,7 +555,6 @@ TEST("effect()", wrap_root(function()
|
|||
end))
|
||||
|
||||
TEST("cleanup()", wrap_root(function()
|
||||
local root = vide.root
|
||||
local source = vide.source
|
||||
local effect = vide.effect
|
||||
local cleanup = vide.cleanup
|
||||
|
|
@ -550,12 +562,10 @@ TEST("cleanup()", wrap_root(function()
|
|||
do CASE "root cleanup"
|
||||
local count = 0
|
||||
|
||||
local _, destroy = root(function()
|
||||
local destroy = vide.mount(function()
|
||||
cleanup(function()
|
||||
count += 1
|
||||
end)
|
||||
|
||||
return nil
|
||||
end)
|
||||
|
||||
CHECK(count == 0)
|
||||
|
|
@ -606,7 +616,6 @@ TEST("cleanup()", wrap_root(function()
|
|||
end))
|
||||
|
||||
TEST("create()", wrap_root(function()
|
||||
local root = vide.root
|
||||
local create = vide.create
|
||||
local source = vide.source
|
||||
local cleanup = vide.cleanup
|
||||
|
|
@ -716,7 +725,7 @@ TEST("create()", wrap_root(function()
|
|||
do CASE "binding destroy"
|
||||
local count = 0
|
||||
|
||||
local _, destroy = root(function()
|
||||
local destroy = vide.mount(function()
|
||||
local src = source(0)
|
||||
|
||||
return create "TextLabel" {
|
||||
|
|
@ -782,7 +791,7 @@ TEST("create()", wrap_root(function()
|
|||
end
|
||||
|
||||
do CASE "parent bound to source"
|
||||
local wref, destroy = root(function()
|
||||
local wref, destroy = vide.root(function(destroy)
|
||||
local frame = create "Frame" { Name = "Parent" }
|
||||
local parent = source(frame :: Frame?)
|
||||
|
||||
|
|
@ -795,7 +804,7 @@ TEST("create()", wrap_root(function()
|
|||
|
||||
parent(nil)
|
||||
|
||||
return wref
|
||||
return wref, destroy
|
||||
end)
|
||||
|
||||
gc()
|
||||
|
|
@ -1373,7 +1382,7 @@ TEST("untrack()", wrap_root(function()
|
|||
|
||||
local input = source(0)
|
||||
|
||||
local output, destroy = root(function()
|
||||
local output, destroy = root(function(destroy)
|
||||
local output = derive(function()
|
||||
outer_count += 1
|
||||
|
||||
|
|
@ -1390,7 +1399,7 @@ TEST("untrack()", wrap_root(function()
|
|||
end)
|
||||
end)
|
||||
|
||||
return output
|
||||
return output, destroy
|
||||
end)
|
||||
|
||||
CHECK(outer_count == 1)
|
||||
|
|
@ -1503,13 +1512,13 @@ TEST("changed()", wrap_root(function()
|
|||
end
|
||||
|
||||
do CASE "connection disconnected"
|
||||
local text, destroy = root(function()
|
||||
local text, destroy = root(function(destroy)
|
||||
local output = source(nil)
|
||||
|
||||
return create "TextLabel" {
|
||||
Text = "a",
|
||||
changed("Text", output)
|
||||
}
|
||||
}, destroy
|
||||
end)
|
||||
|
||||
destroy() -- changed() should of disconnect connection
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue