This commit is contained in:
aaron 2023-09-06 23:01:53 +01:00
parent fe3af737be
commit dafdc0739b
10 changed files with 249 additions and 550 deletions

View file

@ -6,9 +6,9 @@ local flags = require(script.Parent.flags)
local graph = require(script.Parent.graph)
type Node<T> = graph.Node<T>
local create = graph.create
local create_and_open_scope = graph.create_and_open_scope
local init_scope = graph.init_scope
local close_scope = graph.close_scope
local set_child = graph.set_child
local add_child = graph.add_child
local capture = graph.capture
--[[
@ -29,14 +29,7 @@ todo: investigate behavior in case B is parented to A, and A has no parent or re
]]
-- holds parented instance proxies in memory
local hold: { Instance? } = {}
-- weakly references instances with properties bound
local weak: { Instance? } = setmetatable({}, { __mode = "v" }) :: any
-- unique binding id
local bind_count = 0
-- todo: replace with throw's method
local root do
@ -74,45 +67,21 @@ function bind(instance: Instance, property: string, setter: (Instance) -> ())
end
end
local node = create(false)
local binding = create(instance)
create_and_open_scope(node)
init_scope(binding)
-- run setter to capture any nodes being depended on
local nodes = (capture(setter :: () -> unknown, instance))
close_scope()
-- get binding id
bind_count += 1
local bind_id = bind_count
node.effect = function()
local instance = weak[bind_id]
if instance == nil then return end
setter(weak[bind_id] :: Instance)
end
binding.effect = setter
-- register the setter as a side-effect of each node
for _, n in next, nodes do
set_child(n, node)
for _, node in next, nodes do
add_child(node, binding)
end
-- store reference of instance proxy without preventing gc
weak[bind_id] = instance
local function ref()
local _ = node -- prevent gc of node being depended on
local instance = weak[bind_id] :: Instance
-- keep proxy in memory if instance is still parented
hold[bind_id] = instance.Parent and instance or nil
end
ref()
instance:GetPropertyChangedSignal("Parent"):Connect(ref)
end
local function bind_property(instance: Instance, property: string, fn: () -> unknown)