diff --git a/.changeset/poor-pumpkins-exercise.md b/.changeset/poor-pumpkins-exercise.md new file mode 100644 index 000000000000..cd5d08a9b555 --- /dev/null +++ b/.changeset/poor-pumpkins-exercise.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: don't eagerly execute deriveds on resume diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 54994b9bd1cd..625c0d1822a3 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -329,6 +329,7 @@ export function render_effect(fn) { /** * @param {(...expressions: any) => void | (() => void)} fn * @param {Array<() => any>} thunks + * @param {(fn: () => T) => Derived} d * @returns {Effect} */ export function template_effect(fn, thunks = [], d = derived) { @@ -598,15 +599,11 @@ function resume_children(effect, local) { if ((effect.f & INERT) === 0) return; effect.f ^= INERT; - // Ensure the effect is marked as clean again so that any dirty child - // effects can schedule themselves for execution - if ((effect.f & CLEAN) === 0) { - effect.f ^= CLEAN; - } - // If a dependency of this effect changed while it was paused, - // schedule the effect to update - if (check_dirtiness(effect)) { + // schedule the effect to update. we don't use `check_dirtiness` + // here because we don't want to eagerly recompute a derived like + // `{#if foo}{foo.bar()}{/if}` if `foo` is now `undefined + if ((effect.f & CLEAN) !== 0) { set_signal_status(effect, DIRTY); schedule_effect(effect); } diff --git a/packages/svelte/tests/runtime-runes/samples/if-nested-template/Component.svelte b/packages/svelte/tests/runtime-runes/samples/if-nested-template/Component.svelte new file mode 100644 index 000000000000..b4281bbcbd91 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-nested-template/Component.svelte @@ -0,0 +1,7 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/if-nested-template/_config.js b/packages/svelte/tests/runtime-runes/samples/if-nested-template/_config.js new file mode 100644 index 000000000000..673f66891640 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-nested-template/_config.js @@ -0,0 +1,17 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target, logs }) { + const [btn1, btn2] = target.querySelectorAll('button'); + const [div] = target.querySelectorAll('div'); + + flushSync(() => btn1?.click()); + assert.htmlEqual(div.innerHTML, '123 123'); + assert.equal(div.inert, true); + + flushSync(() => btn2?.click()); + assert.htmlEqual(div.innerHTML, ''); + assert.deepEqual(logs, ['123']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/if-nested-template/main.svelte b/packages/svelte/tests/runtime-runes/samples/if-nested-template/main.svelte new file mode 100644 index 000000000000..04afa7d664fe --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-nested-template/main.svelte @@ -0,0 +1,23 @@ + + +{#if outer} +
+ {#if inner} + {@const text = inner.toString()} + {text} {inner.toString()} + + {/if} +
+{/if} + + +