mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
fix: always return pending value in signal setter
This commit is contained in:
parent
6499a0064f
commit
ccdd539b28
2 changed files with 62 additions and 45 deletions
|
|
@ -226,11 +226,9 @@ local function run(effect: EffectNode)
|
|||
|
||||
purgeDeps(effect)
|
||||
|
||||
if success then
|
||||
if type(result) == "function" then
|
||||
if success and result then
|
||||
table.insert(effect.cleanups, wrapUserSpace(result))
|
||||
end
|
||||
else
|
||||
elseif not success then
|
||||
error(result, 0)
|
||||
end
|
||||
|
||||
|
|
@ -442,6 +440,32 @@ local function signal<T>(initialValue: T, equals: Equals<T>?): (Getter<T>, Sette
|
|||
deepFreeze(initialValue)
|
||||
end
|
||||
|
||||
local function signalGetter(): T
|
||||
-- Check if the signal has a pending update that needs to be applied
|
||||
if bit32.btest(node.flags, DIRTY) then
|
||||
if updateSignal(node) then
|
||||
local subs = node.subs
|
||||
if subs then
|
||||
shallowPropagate(subs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Register this signal as a dependency of the first subscriber in the
|
||||
-- chain that is a computed signal or an effect
|
||||
local sub = activeSub
|
||||
while sub do
|
||||
if bit32.btest(sub.flags, bit32.bor(MUTABLE, WATCHING)) then
|
||||
link(node, sub, cycle)
|
||||
break
|
||||
end
|
||||
local subs = sub.subs
|
||||
sub = if subs then subs.sub else nil
|
||||
end
|
||||
|
||||
return node.currentValue
|
||||
end
|
||||
|
||||
local function signalSetter(update: Update<T>): T
|
||||
local value: T
|
||||
|
||||
|
|
@ -475,37 +499,9 @@ local function signal<T>(initialValue: T, equals: Equals<T>?): (Getter<T>, Sette
|
|||
propagate(subs)
|
||||
flush()
|
||||
end
|
||||
|
||||
return value
|
||||
end
|
||||
|
||||
return node.currentValue
|
||||
end
|
||||
|
||||
local function signalGetter(): T
|
||||
-- Check if the signal has a pending update that needs to be applied
|
||||
if bit32.btest(node.flags, DIRTY) then
|
||||
if updateSignal(node) then
|
||||
local subs = node.subs
|
||||
if subs then
|
||||
shallowPropagate(subs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Register this signal as a dependency of the first subscriber in the
|
||||
-- chain that is a computed signal or an effect
|
||||
local sub = activeSub
|
||||
while sub do
|
||||
if bit32.btest(sub.flags, bit32.bor(MUTABLE, WATCHING)) then
|
||||
link(node, sub, cycle)
|
||||
break
|
||||
end
|
||||
local subs = sub.subs
|
||||
sub = if subs then subs.sub else nil
|
||||
end
|
||||
|
||||
return node.currentValue
|
||||
return node.pendingValue
|
||||
end
|
||||
|
||||
return signalGetter, signalSetter
|
||||
|
|
@ -522,9 +518,11 @@ end
|
|||
]]
|
||||
local function atom<T>(initialValue: T, equals: Equals<T>?): Atom<T>
|
||||
local get, set = signal(initialValue, equals)
|
||||
|
||||
local function atomOper(...)
|
||||
return if select("#", ...) == 0 then get() else set((...))
|
||||
end
|
||||
|
||||
return atomOper
|
||||
end
|
||||
|
||||
|
|
@ -628,16 +626,15 @@ local function effect(fn: () -> ...Cleanup?): Cleanup
|
|||
local success, result = pcall(node.fn)
|
||||
activeSub = prevSub
|
||||
|
||||
if success then
|
||||
if type(result) == "function" then
|
||||
if success and result then
|
||||
table.insert(node.cleanups, wrapUserSpace(result))
|
||||
end
|
||||
endBatch()
|
||||
else
|
||||
elseif not success then
|
||||
endBatch()
|
||||
error(result, 2)
|
||||
end
|
||||
|
||||
endBatch()
|
||||
|
||||
return function()
|
||||
stopEffect(node)
|
||||
end
|
||||
|
|
@ -667,11 +664,9 @@ local function effectScope(fn: () -> ...Cleanup?, detached: boolean?): Cleanup
|
|||
local success, result = pcall(wrapUserSpace(fn))
|
||||
activeSub = prevSub
|
||||
|
||||
if success then
|
||||
if type(result) == "function" then
|
||||
if success and result then
|
||||
table.insert(node.cleanups, wrapUserSpace(result))
|
||||
end
|
||||
else
|
||||
elseif not success then
|
||||
error(result, 2)
|
||||
end
|
||||
|
||||
|
|
@ -750,9 +745,11 @@ local function untracked<Args..., Results...>(fn: (Args...) -> Results..., ...:
|
|||
local prevSub = setActiveSub(nil)
|
||||
local results: { any } = { pcall(wrapUserSpace(fn), ...) }
|
||||
activeSub = prevSub
|
||||
|
||||
if not results[1] then
|
||||
error(results[2], 2)
|
||||
end
|
||||
|
||||
return unpack(results, 2)
|
||||
else
|
||||
return fn(...)
|
||||
|
|
@ -772,9 +769,11 @@ local function batch<Args..., Results...>(fn: (Args...) -> Results..., ...: Args
|
|||
startBatch()
|
||||
local results: { any } = { pcall(wrapUserSpace(fn), ...) }
|
||||
endBatch()
|
||||
|
||||
if not results[1] then
|
||||
error(results[2], 2)
|
||||
end
|
||||
|
||||
return unpack(results, 2)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -46,4 +46,22 @@ test("should not freeze values with metatables", function()
|
|||
)
|
||||
end)
|
||||
|
||||
test("should setter return same value as getter even if equal", function()
|
||||
local src, setSrc = signal(0, function()
|
||||
return true
|
||||
end)
|
||||
assert(setSrc(1) == src(), `setSrc(1) expected 0, got {setSrc(1)}`)
|
||||
end)
|
||||
|
||||
test("should setter return latest value", function()
|
||||
local src, setSrc = signal(0)
|
||||
effect(function()
|
||||
if src() == 1 then
|
||||
setSrc(2)
|
||||
end
|
||||
end)
|
||||
assert(setSrc(1) == 2, `setSrc(1) expected 2, got {setSrc(1)}`)
|
||||
assert(src() == 2, `src() expected 2, got {src()}`)
|
||||
end)
|
||||
|
||||
return {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue