This commit is contained in:
aaron 2023-09-09 18:59:25 +01:00
parent 1f0b734956
commit 866135b152
2 changed files with 65 additions and 16 deletions

View file

@ -5,11 +5,12 @@ local flags = require(script.Parent.flags)
export type StartNode<T> = { export type StartNode<T> = {
cache: T, cache: T,
n: number, children: { [Node<T>]: true } | false
[number]: Node<T>
} }
export type Node<T> = StartNode<T> & { export type Node<T> = {
cache: T,
children: { [Node<T>]: true } | false,
effect: (T) -> (), effect: (T) -> (),
cleanups: { () -> () } | false, cleanups: { () -> () } | false,
} }
@ -50,9 +51,11 @@ local function get_scope(): Node<unknown>
end end
local function add_child<T>(parent: Node<any>, child: Node<any>) local function add_child<T>(parent: Node<any>, child: Node<any>)
local n = parent.n + 1 if parent.children then
parent.n = n parent.children[child] = true
parent[n] = child else
parent.children = { [child] = true :: true }
end
end end
-- local function open_root_scope<T>(node: Node<T>) -- local function open_root_scope<T>(node: Node<T>)
@ -107,15 +110,17 @@ local function destroy<T>(node: Node<T>)
end end
end end
-- runs node effects, recalculates descendants and runs descendant effects -- runs node effects, recalculates descendants and runs descendant effects
local function update<T>(node: StartNode<T>) local function update<T>(node: StartNode<T>)
local children = { unpack(node) } if not node.children then return end
for i = 1, node.n do
node[i] = nil
end
node.n = 0
for _, child in children do local cache = {}
for child in node.children do
table.insert(cache, child)
end
for _, child in next, cache do
open_scope(child) open_scope(child)
run_cleanups(child) run_cleanups(child)
run_effect(child) run_effect(child)
@ -132,17 +137,25 @@ local function create_node<T>(value: T): Node<T>
return { return {
cache = value, cache = value,
effect = function() end, effect = function() end,
cleanups = false :: false, cleanups = false,
n = 0 children = false
} }
end end
local function get_children(node: Node<unknown>): { Node<unknown> } local function get_children(node: Node<unknown>): { Node<unknown> }
return { unpack(node) } if not node.children then return {} end
local children = {}
for child in node.children do
table.insert(children, child)
end
return children
end end
local function create_start_node<T>(value: T): StartNode<T> local function create_start_node<T>(value: T): StartNode<T>
return { cache = value, n = 0 } return { cache = value, children = false }
end end
return table.freeze { return table.freeze {

View file

@ -87,6 +87,42 @@ TEST("graph", function()
CHECK(count == 3) CHECK(count == 3)
end end
do CASE "etst"
--[[
root
Items -> Indexes()
indexes_root
v1 + sel -> bind
v2 + sel -> bind
]]
local items = create_node { 1, 2 }
local count = 0
local function effect()
track(a)
track(b)
count += 1
end
c.effect = effect
open_scope(c)
effect()
close_scope()
CHECK(count == 1)
update(a)
CHECK(count == 2)
update(b)
CHECK(count == 3)
end
-- todo: further tests -- todo: further tests
do CASE "nodes garbage collection" do CASE "nodes garbage collection"