From 0550bf07176a64a5ea78f96b80f46111d1a4e65f Mon Sep 17 00:00:00 2001 From: Daniel P H Fox Date: Mon, 15 Apr 2024 17:36:49 +0100 Subject: [PATCH] Do not defer property and child assignments anymore --- docs/tutorials/roblox/hydration.md | 6 +++--- src/Instances/Attribute.luau | 16 +++------------- src/Instances/Children.luau | 19 +------------------ src/Instances/applyInstanceProps.luau | 20 ++++---------------- 4 files changed, 11 insertions(+), 50 deletions(-) diff --git a/docs/tutorials/roblox/hydration.md b/docs/tutorials/roblox/hydration.md index 1ce4ce550..bfe615f7e 100644 --- a/docs/tutorials/roblox/hydration.md +++ b/docs/tutorials/roblox/hydration.md @@ -17,8 +17,8 @@ and hiding buttons. Fusion provides a `Hydrate` function for hydrating an instance using a table -of properties. If you pass in Fusion objects, changes will be applied on the -next frame: +of properties. If you pass in Fusion objects, changes will be applied +immediately: ```Lua local showUI = scope:Value(false) @@ -73,7 +73,7 @@ local instance = scope:Hydrate(workspace.Part) { If you pass in constant values for properties, they'll be applied to the instance directly. However, if you pass in a Fusion object (like `Value`), then -changes will be applied on the next frame: +changes will be applied immediately: ```Lua local message = scope:Value("Loading...") diff --git a/src/Instances/Attribute.luau b/src/Instances/Attribute.luau index dc4a7c85c..d42a6b4b5 100644 --- a/src/Instances/Attribute.luau +++ b/src/Instances/Attribute.luau @@ -10,7 +10,6 @@ local task = nil -- Disable usage of Roblox's task scheduler local Package = script.Parent.Parent local Types = require(Package.Types) -local External = require(Package.External) local logError = require(Package.Logging.logError) local logWarn = require(Package.Logging.logWarn) local isState = require(Package.State.isState) @@ -38,18 +37,9 @@ local function Attribute( elseif whichLivesLonger(scope, applyTo, value.scope, value) == "definitely-a" then logWarn("possiblyOutlives", `The {value.kind} object, bound to [Attribute "{attributeName}"],`, `the {applyTo.ClassName} instance`) end - local didDefer = false - local function update() - if not didDefer then - didDefer = true - External.doTaskDeferred(function() - didDefer = false - applyTo:SetAttribute(attributeName, peek(value)) - end) - end - end - applyTo:SetAttribute(attributeName, peek(value)) - table.insert(scope, Observer(scope, value :: any):onChange(update)) + Observer(scope, value :: any):onBind(function() + applyTo:SetAttribute(attributeName, peek(value)) + end) else applyTo:SetAttribute(attributeName, value) end diff --git a/src/Instances/Children.luau b/src/Instances/Children.luau index 693b6c0fd..5f21ffaa6 100644 --- a/src/Instances/Children.luau +++ b/src/Instances/Children.luau @@ -40,18 +40,10 @@ return { local newScopes: {[Types.StateObject]: Types.Scope} = {} local oldScopes: {[Types.StateObject]: Types.Scope} = {} - local updateQueued = false - local queueUpdate: () -> () - -- Rescans this key's value to find new instances to parent and state objects -- to observe for changes; then unparents instances no longer found and -- disconnects observers for state objects no longer present. local function updateChildren() - if not updateQueued then - return -- this update may have been canceled by destruction, etc. - end - updateQueued = false - oldParented, newParented = newParented, oldParented oldScopes, newScopes = newScopes, oldScopes table.clear(newParented) @@ -97,7 +89,7 @@ return { if childScope == nil then -- wasn't previously present childScope = {} - Observer(childScope, child):onChange(queueUpdate) + Observer(childScope, child):onChange(updateChildren) else -- previously here; we want to reuse, so remove from old -- set so we don't encounter it during unparenting @@ -148,21 +140,12 @@ return { end end - queueUpdate = function() - if not updateQueued then - updateQueued = true - External.doTaskDeferred(updateChildren) - end - end - table.insert(scope, function() value = nil - updateQueued = true updateChildren() end) -- perform initial child parenting - updateQueued = true updateChildren() end } :: Types.SpecialKey \ No newline at end of file diff --git a/src/Instances/applyInstanceProps.luau b/src/Instances/applyInstanceProps.luau index 4a2c077f9..b7f3e2934 100644 --- a/src/Instances/applyInstanceProps.luau +++ b/src/Instances/applyInstanceProps.luau @@ -18,7 +18,6 @@ local task = nil -- Disable usage of Roblox's task scheduler local Package = script.Parent.Parent local Types = require(Package.Types) -local External = require(Package.External) local isState = require(Package.State.isState) local logError = require(Package.Logging.logError) local logWarn = require(Package.Logging.logWarn) @@ -81,21 +80,10 @@ local function bindProperty( elseif whichLivesLonger(scope, instance, value.scope, value) == "definitely-a" then logWarn("possiblyOutlives", `The {value.kind} object, bound to {property},`, `the {instance.ClassName} instance`) end - - -- value is a state object - assign and observe for changes - local willUpdate = false - local function updateLater() - if not willUpdate then - willUpdate = true - External.doTaskDeferred(function() - willUpdate = false - setProperty(instance, property, peek(value)) - end) - end - end - - setProperty(instance, property, peek(value)) - table.insert(scope, Observer(scope, value :: any):onChange(updateLater)) + -- value is a state object - bind to changes + Observer(scope, value :: any):onBind(function() + setProperty(instance, property, peek(value)) + end) else -- value is a constant - assign once only setProperty(instance, property, value)