mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
Improve error messages for derived sources
There seemed to be confusion over reactive-scoping (likely due to incomplete docs), so I've added more explicit error messages when deriving in non-reactive scopes to warn the user to use `root()` or `mount()`.
This commit is contained in:
parent
d13f66a1e1
commit
c4a0180a2f
9 changed files with 31 additions and 42 deletions
|
|
@ -1,12 +1,11 @@
|
|||
if not game then script = require "test/relative-string" end
|
||||
|
||||
local throw = require(script.Parent.throw)
|
||||
local trace = require(script.Parent.trace)
|
||||
local flags = require(script.Parent.flags)
|
||||
local graph = require(script.Parent.graph)
|
||||
type Node<T> = graph.Node<T>
|
||||
local create_node = graph.create_node
|
||||
local get_scope = graph.get_scope
|
||||
local get_owning_scope = graph.get_owning_scope
|
||||
local evaluate_node = graph.evaluate_node
|
||||
local set_owner = graph.set_owner
|
||||
|
||||
|
|
@ -33,10 +32,7 @@ function create_binding<T>(updater: (T) -> T, binding: T)
|
|||
end
|
||||
|
||||
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot bind property in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
local node = create_node(binding, updater)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ local add_cleanup = graph.add_cleanup
|
|||
|
||||
local function cleanup(callback: () -> ())
|
||||
local scope = get_scope()
|
||||
if not scope then
|
||||
throw("cannot cleanup in a non-reactive scope")
|
||||
|
||||
if not scope then
|
||||
throw "cannot cleanup in a non-reactive scope"
|
||||
end; assert(scope)
|
||||
|
||||
add_cleanup(scope, callback)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,14 @@
|
|||
if not game then script = require "test/relative-string" end
|
||||
|
||||
local throw = require(script.Parent.throw)
|
||||
local graph = require(script.Parent.graph)
|
||||
local create_node = graph.create_node
|
||||
local set_owner = graph.set_owner
|
||||
local track = graph.track
|
||||
local get_scope = graph.get_scope
|
||||
local get_owning_scope = graph.get_owning_scope
|
||||
local evaluate_node = graph.evaluate_node
|
||||
|
||||
local function derive<T>(source: () -> T): () -> T
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot derive in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
local node = create_node(false :: any, source)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
if not game then script = require "test/relative-string" end
|
||||
|
||||
local throw = require(script.Parent.throw)
|
||||
local graph = require(script.Parent.graph)
|
||||
local create_node = graph.create_node
|
||||
local get_scope = graph.get_scope
|
||||
local get_owning_scope = graph.get_owning_scope
|
||||
local evaluate_node = graph.evaluate_node
|
||||
local set_owner = graph.set_owner
|
||||
|
||||
local function effect<T>(callback: (T) -> T, initial_value: T)
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot create effect in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
local node = create_node(initial_value, callback)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,17 @@ local function get_scope(): Node<unknown>?
|
|||
return scopes[scopes.n]
|
||||
end
|
||||
|
||||
local function get_owning_scope(): Node<unknown>
|
||||
local scope = get_scope()
|
||||
if not scope then
|
||||
local caller_name = debug.info(2, "n")
|
||||
return throw(`cannot use {caller_name}() in non-reactive scope, must be used within a root() or mount() callback`)
|
||||
elseif scope.effect then
|
||||
throw("owning scope is not stable; are you trying to derive a new source from within a side-effect?")
|
||||
end
|
||||
return scope
|
||||
end
|
||||
|
||||
local function add_child<T>(parent: StartNode<any>, child: Node<any>)
|
||||
table.insert(parent, child)
|
||||
table.insert(child.parents, parent)
|
||||
|
|
@ -149,6 +160,7 @@ local function evaluate_node<T>(node: Node<T>)
|
|||
return cur_value ~= new_value -- node has changed value
|
||||
end
|
||||
|
||||
-- todo: case where owner is set from an untrack call within an effectful node, children clearing
|
||||
local function update_from<T>(node: StartNode<T>, n0: number)
|
||||
if not node[1] then return end
|
||||
|
||||
|
|
@ -169,7 +181,7 @@ local function update_from<T>(node: StartNode<T>, n0: number)
|
|||
|
||||
-- evaluate all queued children
|
||||
for i = n0 + 1, n do
|
||||
local child = update_queue[i]
|
||||
local child = update_queue[i] -- todo: error: index boolean
|
||||
if not child.effect then continue end
|
||||
|
||||
if evaluate_node(child) then
|
||||
|
|
@ -213,6 +225,7 @@ return table.freeze {
|
|||
close_scope = close_scope,
|
||||
evaluate_node = evaluate_node,
|
||||
get_scope = get_scope,
|
||||
get_owning_scope = get_owning_scope,
|
||||
add_cleanup = add_cleanup,
|
||||
set_owner = set_owner,
|
||||
destroy = destroy,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ local create_start_node = graph.create_start_node
|
|||
local set_owner = graph.set_owner
|
||||
local track = graph.track
|
||||
local update = graph.update
|
||||
local get_scope = graph.get_scope
|
||||
local get_owning_scope = graph.get_owning_scope
|
||||
local open_scope = graph.open_scope
|
||||
local close_scope = graph.close_scope
|
||||
local evaluate_node = graph.evaluate_node
|
||||
|
|
@ -28,10 +28,7 @@ local function check_primitives(t: {})
|
|||
end
|
||||
|
||||
local function indexes<K, VI, VO>(input: () -> Map<K, VI>, transform: (() -> VI, K) -> VO): () -> { VO }
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot derive in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
local subowner = create_node(false, false)
|
||||
set_owner(subowner, owner)
|
||||
|
|
@ -125,10 +122,7 @@ local function indexes<K, VI, VO>(input: () -> Map<K, VI>, transform: (() -> VI,
|
|||
end
|
||||
|
||||
local function values<K, VI, VO>(input: () -> Map<K, VI>, transform: (VI, () -> K) -> VO): () -> { VO }
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot derive in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
local subowner = create_node(false, false)
|
||||
set_owner(subowner, owner)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ type Node<T> = graph.Node<T>
|
|||
type StartNode<T> = graph.StartNode<T>
|
||||
local create_node = graph.create_node
|
||||
local create_start_node = graph.create_start_node
|
||||
local get_scope = graph.get_scope
|
||||
local get_owning_scope = graph.get_owning_scope
|
||||
local evaluate_node = graph.evaluate_node
|
||||
local update = graph.update
|
||||
local set_owner = graph.set_owner
|
||||
|
|
@ -150,10 +150,7 @@ local springs: { [SpringData<any>]: StartNode<any> } = {}
|
|||
setmetatable(springs, { __mode = "v" })
|
||||
|
||||
local function spring<T>(source: () -> T, period: number?, damping_ratio: number?): () -> T
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot derive in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
-- https://en.wikipedia.org/wiki/Damping
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,16 @@ local evaluate_node = graph.evaluate_node
|
|||
local set_owner = graph.set_owner
|
||||
local track = graph.track
|
||||
local destroy = graph.destroy
|
||||
local get_scope = graph.get_scope
|
||||
local get_owning_scope = graph.get_owning_scope
|
||||
local open_scope = graph.open_scope
|
||||
local close_scope = graph.close_scope
|
||||
|
||||
type Map<K, V> = { [K]: V }
|
||||
|
||||
local function switch<T, U>(source: () -> T): (map: Map<T, ((() -> U)?)>) -> () -> U?
|
||||
return function(map)
|
||||
local owner = get_scope()
|
||||
if not owner then
|
||||
throw("cannot switch in non-reactive scope")
|
||||
end; assert(owner)
|
||||
local owner = get_owning_scope()
|
||||
|
||||
return function(map)
|
||||
local last_scope: Node<false>?
|
||||
local last_component: (() -> U)?
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue