From 960badacc52a71fb7bbd794e2a913fcb1b138414 Mon Sep 17 00:00:00 2001 From: Sabine Lim Date: Sun, 14 May 2023 03:12:46 +1000 Subject: [PATCH 1/2] Implement effects --- Basalt/plugins/xml.lua | 55 +++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/Basalt/plugins/xml.lua b/Basalt/plugins/xml.lua index 83500a1..fd77bfd 100644 --- a/Basalt/plugins/xml.lua +++ b/Basalt/plugins/xml.lua @@ -167,27 +167,56 @@ local function registerFunctionEvent(self, data, event, renderContext) end end -local potentialObservers = {} +local clearEffectDependencies = function(effect) + for _, dependency in ipairs(effect.dependencies) do + for index, backlink in ipairs(dependency) do + if (backlink == effect) then + table.remove(dependency, index) + end + end + end + effect.dependencies = {}; +end + +local effectStack = {} return { basalt = function() local object = { reactive = function(initialValue) - local internalValue = initialValue - local observers = {} + local value = initialValue + local observerEffects = {} local getter = function() - if (potentialObservers ~= nil) then - table.insert(observers, potentialObservers[#potentialObservers]) + local invokingEffect = effectStack[#effectStack] + if (invokingEffect ~= nil) then + table.insert(observerEffects, invokingEffect) + table.insert(invokingEffect.dependencies, observerEffects) end - return internalValue + return value end - local setter = function(value) - internalValue = value - for _, updateFn in ipairs(observers) do - updateFn(internalValue) + local setter = function(newValue) + value = newValue + local observerEffectsCopy = {} + for index, effect in ipairs(observerEffects) do + observerEffectsCopy[index] = effect + end + for _, effect in ipairs(observerEffectsCopy) do + effect.execute() end end return getter, setter + end, + + effect = function(effectFn) + local effect = {dependencies = {}} + local execute = function() + clearEffectDependencies(effect) + table.insert(effectStack, effect) + effectFn() + table.remove(effectStack) + end + effect.execute = execute + effect.execute() end } return object @@ -231,9 +260,7 @@ return { local value = load("return " .. expression, nil, "t", renderContext.env)() self:updateValue(prop, value) end - table.insert(potentialObservers, update) - update() - table.remove(potentialObservers) + basalt.effect(update) end self:updateSpecifiedValuesByXMLData(data, { @@ -345,7 +372,6 @@ return { loadLayout = function(self, path, props) if(fs.exists(path))then local renderContext = {} - renderContext.potentialObservers = {} renderContext.env = _ENV renderContext.env.props = props local f = fs.open(path, "r") @@ -475,6 +501,7 @@ return { Button = function(base, basalt) local object = { updateValue = function(self, name, value) + basalt.log("Updating value, " .. name .. " = " .. value) if (value == nil) then return end base.updateValue(self, name, value) if (name == "text") then From 905a1117e1850c678ef900d41a34b0cf76104e06 Mon Sep 17 00:00:00 2001 From: Sabine Lim Date: Sun, 14 May 2023 03:18:39 +1000 Subject: [PATCH 2/2] Derived --- Basalt/plugins/xml.lua | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Basalt/plugins/xml.lua b/Basalt/plugins/xml.lua index fd77bfd..8d35d2a 100644 --- a/Basalt/plugins/xml.lua +++ b/Basalt/plugins/xml.lua @@ -167,6 +167,8 @@ local function registerFunctionEvent(self, data, event, renderContext) end end +local effectStack = {} + local clearEffectDependencies = function(effect) for _, dependency in ipairs(effect.dependencies) do for index, backlink in ipairs(dependency) do @@ -178,10 +180,8 @@ local clearEffectDependencies = function(effect) effect.dependencies = {}; end -local effectStack = {} - return { - basalt = function() + basalt = function(basalt) local object = { reactive = function(initialValue) local value = initialValue @@ -217,6 +217,14 @@ return { end effect.execute = execute effect.execute() + end, + + derived = function(computeFn) + local getValue, setValue = basalt.reactive(); + basalt.effect(function() + setValue(computeFn()) + end) + return getValue; end } return object