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}