mirror of
https://github.com/centau/vide.git
synced 2026-08-20 14:41:37 +00:00
Add context()
This commit is contained in:
parent
83db00a073
commit
8142acd1c1
8 changed files with 303 additions and 1 deletions
75
src/context.luau
Normal file
75
src/context.luau
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
if not game then script = require "test/relative-string" end
|
||||
|
||||
local throw = require(script.Parent.throw)
|
||||
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 push_scope = graph.push_scope
|
||||
local pop_scope = graph.pop_scope
|
||||
local set_context = graph.set_context
|
||||
|
||||
export type Context<T> = (() -> T) & ((T, () -> ()) -> ())
|
||||
|
||||
local nil_symbol = newproxy()
|
||||
local count = 0
|
||||
|
||||
local function context<T>(...: T): Context<T>
|
||||
count += 1
|
||||
local id = count
|
||||
|
||||
local has_default = select("#", ...) > 0
|
||||
local default_value = ...
|
||||
|
||||
return function(...)
|
||||
local scope: Node<unknown>? | false = get_scope()
|
||||
|
||||
if select("#", ...) == 0 then -- get
|
||||
while scope do
|
||||
local ctx = scope.context
|
||||
|
||||
if not ctx then
|
||||
scope = scope.owner
|
||||
continue
|
||||
end
|
||||
|
||||
local value = (ctx :: { unknown })[id]
|
||||
|
||||
if value == nil then
|
||||
scope = scope.owner
|
||||
continue
|
||||
end
|
||||
|
||||
return (if value ~= nil_symbol then value else nil) :: T
|
||||
end
|
||||
|
||||
if has_default ~= nil then
|
||||
return default_value
|
||||
else
|
||||
throw("attempt to get context when no context is set and no default context is set")
|
||||
end
|
||||
else -- set
|
||||
if not scope then return throw("attempt to set context outside of a vide scope") end
|
||||
|
||||
local value, component = ...
|
||||
|
||||
local new_scope = create_node(scope, false, false)
|
||||
set_context(new_scope, id, if value == nil then nil_symbol else value)
|
||||
|
||||
push_scope(new_scope)
|
||||
|
||||
local function efn(err: string) return debug.traceback(err, 3) end
|
||||
local ok, result = xpcall(component, efn)
|
||||
|
||||
pop_scope()
|
||||
|
||||
if not ok then
|
||||
throw(`error while running context:\n\n{result}`)
|
||||
end
|
||||
end
|
||||
|
||||
return nil :: any
|
||||
end
|
||||
end
|
||||
|
||||
return context
|
||||
|
|
@ -13,6 +13,8 @@ export type Node<T> = {
|
|||
effect: ((T) -> T) | false,
|
||||
cleanups: { () -> () } | false,
|
||||
|
||||
context: { [number]: unknown } | false,
|
||||
|
||||
owned: { Node<T> } | false,
|
||||
owner: Node<T> | false,
|
||||
|
||||
|
|
@ -241,6 +243,8 @@ local function create_node<T>(owner: false | Node<any>, effect: false | (T) -> T
|
|||
effect = effect,
|
||||
cleanups = false,
|
||||
|
||||
context = false,
|
||||
|
||||
owner = owner,
|
||||
owned = false,
|
||||
|
||||
|
|
@ -266,6 +270,14 @@ local function get_children<T>(node: Node<T>): { Node<unknown> }
|
|||
return { unpack(node) } :: { Node<any> }
|
||||
end
|
||||
|
||||
local function set_context<T>(node: Node<T>, key: number, value: unknown)
|
||||
if node.context then
|
||||
node.context[key] = value
|
||||
else
|
||||
node.context = { [key] = value }
|
||||
end
|
||||
end
|
||||
|
||||
return table.freeze {
|
||||
push_scope = push_scope,
|
||||
pop_scope = pop_scope,
|
||||
|
|
@ -283,5 +295,6 @@ return table.freeze {
|
|||
get_children = get_children,
|
||||
flush_update_queue = flush_update_queue,
|
||||
get_update_queue_length = get_update_queue_length,
|
||||
set_context = set_context,
|
||||
scopes = scopes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ local cleanup = require(script.cleanup)
|
|||
local untrack = require(script.untrack)
|
||||
local read = require(script.read)
|
||||
local batch = require(script.batch)
|
||||
local context = require(script.context)
|
||||
local switch = require(script.switch)
|
||||
local show = require(script.show)
|
||||
local indexes, values = require(script.maps)()
|
||||
|
|
@ -26,6 +27,9 @@ local throw = require(script.throw)
|
|||
local flags = require(script.flags)
|
||||
|
||||
export type Source<T> = source.Source<T>
|
||||
export type source<T> = Source<T>
|
||||
export type Context<T> = context.Context<T>
|
||||
export type context<T> = Context<T>
|
||||
|
||||
local function step(dt: number)
|
||||
if game then
|
||||
|
|
@ -63,6 +67,7 @@ local vide = {
|
|||
untrack = untrack,
|
||||
read = read,
|
||||
batch = batch,
|
||||
context = context,
|
||||
|
||||
-- animations
|
||||
spring = spring,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue