mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
fix: allow dispose in observers
This commit is contained in:
parent
d890f4fc2c
commit
fdc598f6e6
2 changed files with 53 additions and 4 deletions
|
|
@ -132,4 +132,40 @@ test("should handle self removal", function()
|
|||
assert(table.concat(edits) == "+1+2+3+4-1-2-3-4", `bad edits: {table.concat(edits)}`)
|
||||
end)
|
||||
|
||||
test("should allow disposal during addition", function()
|
||||
local items, setItems = signal({})
|
||||
local edits = {}
|
||||
local dispose
|
||||
|
||||
dispose = observe(items, function(item)
|
||||
if item == 1 then
|
||||
dispose()
|
||||
end
|
||||
table.insert(edits, `+{item}`)
|
||||
return function()
|
||||
table.insert(edits, `-{item}`)
|
||||
end
|
||||
end)
|
||||
|
||||
setItems({ 1, 2, 3, 4 })
|
||||
assert(table.concat(edits) == "+1-1", `bad edits: {table.concat(edits)}`)
|
||||
end)
|
||||
|
||||
test("should allow disposal during removal", function()
|
||||
local items, setItems = signal({ 1, 2, 3, 4 })
|
||||
local edits = {}
|
||||
local dispose
|
||||
|
||||
dispose = observe(items, function(item)
|
||||
table.insert(edits, `+{item}`)
|
||||
return function()
|
||||
dispose()
|
||||
table.insert(edits, `-{item}`)
|
||||
end
|
||||
end)
|
||||
|
||||
setItems({ 1, 2, 3, nil :: any, 5 })
|
||||
assert(table.concat(edits) == "+1+2+3+4-1-2-3-4", `bad edits: {table.concat(edits)}`)
|
||||
end)
|
||||
|
||||
return {}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ local recursive = core.recursive
|
|||
--- @see https://github.com/littensy/charm?tab=readme-ov-file#observegetter-callback
|
||||
local function observe<K, V>(getter: () -> { [K]: V }, callback: (item: V, key: K) -> ...(() -> ())?): () -> ()
|
||||
local innerScopes: { [K]: () -> () } = {}
|
||||
local disposed = false
|
||||
|
||||
local function updateScopes(data: { [K]: V })
|
||||
for key, dispose in innerScopes do
|
||||
if data[key] == nil then
|
||||
innerScopes[key] = nil
|
||||
dispose()
|
||||
if disposed then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -32,9 +36,15 @@ local function observe<K, V>(getter: () -> { [K]: V }, callback: (item: V, key:
|
|||
if innerScopes[key] == nil then
|
||||
-- Detach the inner scope from the parent effect to prevent
|
||||
-- disposing when the effect re-runs.
|
||||
innerScopes[key] = effectScope(function()
|
||||
local stopScope = effectScope(function()
|
||||
return callback(value, key)
|
||||
end, true)
|
||||
|
||||
if disposed then
|
||||
return stopScope()
|
||||
else
|
||||
innerScopes[key] = stopScope
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -51,10 +61,13 @@ local function observe<K, V>(getter: () -> { [K]: V }, callback: (item: V, key:
|
|||
end)
|
||||
|
||||
return function()
|
||||
for _, dispose in innerScopes do
|
||||
dispose()
|
||||
if not disposed then
|
||||
disposed = true
|
||||
for key, dispose in innerScopes do
|
||||
innerScopes[key] = nil
|
||||
dispose()
|
||||
end
|
||||
end
|
||||
table.clear(innerScopes)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue