diff --git a/.changeset/fresh-chicken-itch.md b/.changeset/fresh-chicken-itch.md new file mode 100644 index 0000000000..95120e1591 --- /dev/null +++ b/.changeset/fresh-chicken-itch.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: never mark a child effect root as inert diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index ea8a4b645e..0fad074e6f 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -654,16 +654,22 @@ function pause_children(effect, transitions, local) { while (child !== null) { var sibling = child.next; - var transparent = - (child.f & EFFECT_TRANSPARENT) !== 0 || - // If this is a branch effect without a block effect parent, - // it means the parent block effect was pruned. In that case, - // transparency information was transferred to the branch effect. - ((child.f & BRANCH_EFFECT) !== 0 && (effect.f & BLOCK_EFFECT) !== 0); - // TODO we don't need to call pause_children recursively with a linked list in place - // it's slightly more involved though as we have to account for `transparent` changing - // through the tree. - pause_children(child, transitions, transparent ? local : false); + + // If this child is a root effect, then it will become an independent root when its parent + // is destroyed, it should therefore not become inert nor partake in transitions. + if ((child.f & ROOT_EFFECT) === 0) { + var transparent = + (child.f & EFFECT_TRANSPARENT) !== 0 || + // If this is a branch effect without a block effect parent, + // it means the parent block effect was pruned. In that case, + // transparency information was transferred to the branch effect. + ((child.f & BRANCH_EFFECT) !== 0 && (effect.f & BLOCK_EFFECT) !== 0); + // TODO we don't need to call pause_children recursively with a linked list in place + // it's slightly more involved though as we have to account for `transparent` changing + // through the tree. + pause_children(child, transitions, transparent ? local : false); + } + child = sibling; } } diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root-6/Child.svelte b/packages/svelte/tests/runtime-runes/samples/effect-root-6/Child.svelte new file mode 100644 index 0000000000..110ad82b0d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/effect-root-6/Child.svelte @@ -0,0 +1,14 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root-6/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-root-6/_config.js new file mode 100644 index 0000000000..e4077c6c27 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/effect-root-6/_config.js @@ -0,0 +1,14 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +// Test that $effect.root continues to be operational after its parent effect has been destroyed +export default test({ + test({ assert, target, logs }) { + const [hide, increment] = target.querySelectorAll('button'); + + hide.click(); + flushSync(); + increment.click(); + assert.deepEqual(logs, ['count', 1, 'double', 2]); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root-6/main.svelte b/packages/svelte/tests/runtime-runes/samples/effect-root-6/main.svelte new file mode 100644 index 0000000000..254cddeb5b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/effect-root-6/main.svelte @@ -0,0 +1,15 @@ + + + + +{#if show} + +{/if}