diff --git a/.changeset/loud-cheetahs-flow.md b/.changeset/loud-cheetahs-flow.md new file mode 100644 index 0000000000..6013f2f4e7 --- /dev/null +++ b/.changeset/loud-cheetahs-flow.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve signal consumer tracking behavior diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 3be0afdb03..8631529e62 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -456,10 +456,14 @@ function remove_consumer(signal, dependency, remove_unowned) { function remove_consumers(signal, start_index, remove_unowned) { const dependencies = signal.d; if (dependencies !== null) { + const active_dependencies = start_index === 0 ? null : dependencies.slice(0, start_index); let i; for (i = start_index; i < dependencies.length; i++) { const dependency = dependencies[i]; - remove_consumer(signal, dependency, remove_unowned); + // Avoid removing a consumer if we know that it is active (start_index will not be 0) + if (active_dependencies === null || !active_dependencies.includes(dependency)) { + remove_consumer(signal, dependency, remove_unowned); + } } } } diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-2/_config.js b/packages/svelte/tests/runtime-runes/samples/each-updates-2/_config.js new file mode 100644 index 0000000000..6dfc9c4bf0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-2/_config.js @@ -0,0 +1,40 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: ``, + + async test({ assert, target }) { + const [btn1] = target.querySelectorAll('button'); + + flushSync(() => { + btn1.click(); + btn1.click(); + }); + + assert.htmlEqual( + target.innerHTML, + `` + ); + + let [btn2, btn3, btn4] = target.querySelectorAll('button'); + + flushSync(() => { + btn4.click(); + btn3.click(); + }); + + assert.htmlEqual(target.innerHTML, ``); + + let [btn5] = target.querySelectorAll('button'); + + flushSync(() => { + btn5.click(); + }); + + assert.htmlEqual( + target.innerHTML, + `` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-updates-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-updates-2/main.svelte new file mode 100644 index 0000000000..5837c47608 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-updates-2/main.svelte @@ -0,0 +1,18 @@ + + + + +{#each arr as item, i} + +{/each}