diff --git a/.changeset/silent-teeth-invent.md b/.changeset/silent-teeth-invent.md
new file mode 100644
index 0000000000..54603cc27e
--- /dev/null
+++ b/.changeset/silent-teeth-invent.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: ensure eager effects don't break reactions chain
diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js
index 8ae406b57b..052ca97dc0 100644
--- a/packages/svelte/src/internal/client/reactivity/sources.js
+++ b/packages/svelte/src/internal/client/reactivity/sources.js
@@ -14,7 +14,9 @@ import {
is_dirty,
untracking,
is_destroying_effect,
- push_reaction_value
+ push_reaction_value,
+ set_is_updating_effect,
+ is_updating_effect
} from '../runtime.js';
import { equals, safe_equals } from './equality.js';
import {
@@ -246,19 +248,25 @@ export function internal_set(source, value) {
export function flush_eager_effects() {
eager_effects_deferred = false;
+ var prev_is_updating_effect = is_updating_effect;
+ set_is_updating_effect(true);
const inspects = Array.from(eager_effects);
- for (const effect of inspects) {
- // Mark clean inspect-effects as maybe dirty and then check their dirtiness
- // instead of just updating the effects - this way we avoid overfiring.
- if ((effect.f & CLEAN) !== 0) {
- set_signal_status(effect, MAYBE_DIRTY);
- }
+ try {
+ for (const effect of inspects) {
+ // Mark clean inspect-effects as maybe dirty and then check their dirtiness
+ // instead of just updating the effects - this way we avoid overfiring.
+ if ((effect.f & CLEAN) !== 0) {
+ set_signal_status(effect, MAYBE_DIRTY);
+ }
- if (is_dirty(effect)) {
- update_effect(effect);
+ if (is_dirty(effect)) {
+ update_effect(effect);
+ }
}
+ } finally {
+ set_is_updating_effect(prev_is_updating_effect);
}
eager_effects.clear();
diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-derived-4/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-derived-4/_config.js
new file mode 100644
index 0000000000..3a3bca7221
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/inspect-derived-4/_config.js
@@ -0,0 +1,35 @@
+import { tick } from 'svelte';
+import { test } from '../../test';
+import { normalise_inspect_logs } from '../../../helpers';
+
+export default test({
+ compileOptions: {
+ dev: true
+ },
+
+ async test({ assert, target, logs }) {
+ const [b] = target.querySelectorAll('button');
+
+ b.click();
+ await tick();
+ assert.htmlEqual(target.innerHTML, ``);
+
+ b.click();
+ await tick();
+ assert.htmlEqual(target.innerHTML, ``);
+
+ b.click();
+ await tick();
+ assert.htmlEqual(target.innerHTML, ``);
+
+ assert.deepEqual(normalise_inspect_logs(logs), [
+ [0, 1, 2],
+ [1, 2],
+ 'at SvelteSet.add',
+ [2],
+ 'at SvelteSet.add',
+ [],
+ 'at SvelteSet.add'
+ ]);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-derived-4/main.svelte b/packages/svelte/tests/runtime-runes/samples/inspect-derived-4/main.svelte
new file mode 100644
index 0000000000..eb4ea891db
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/inspect-derived-4/main.svelte
@@ -0,0 +1,14 @@
+
+
+