diff --git a/.changeset/spotty-pens-agree.md b/.changeset/spotty-pens-agree.md new file mode 100644 index 0000000000..2b7f76d696 --- /dev/null +++ b/.changeset/spotty-pens-agree.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure nested blocks are inert during outro transitions diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 8631529e62..48612c4ed8 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -10,6 +10,7 @@ import { } from '../../constants.js'; import { readonly } from './proxy/readonly.js'; import { READONLY_SYMBOL, STATE_SYMBOL, proxy, unstate } from './proxy/proxy.js'; +import { EACH_BLOCK, IF_BLOCK } from './block.js'; export const SOURCE = 1; export const DERIVED = 1 << 1; @@ -1019,6 +1020,28 @@ export function mark_subtree_inert(signal, inert) { if (!inert && (flags & IS_EFFECT) !== 0 && (flags & CLEAN) === 0) { schedule_effect(/** @type {import('./types.js').EffectSignal} */ (signal), false); } + // Nested if block effects + const block = signal.b; + if (block !== null) { + const type = block.t; + if (type === IF_BLOCK) { + const consequent_effect = block.ce; + if (consequent_effect !== null) { + mark_subtree_inert(consequent_effect, inert); + } + const alternate_effect = block.ae; + if (alternate_effect !== null) { + mark_subtree_inert(alternate_effect, inert); + } + } else if (type === EACH_BLOCK) { + const items = block.v; + for (let {e: each_item_effect} of items) { + if (each_item_effect !== null) { + mark_subtree_inert(each_item_effect, inert); + } + } + } + } } const references = signal.r; if (references !== null) { diff --git a/packages/svelte/tests/runtime-runes/samples/if-transition-inert/_config.js b/packages/svelte/tests/runtime-runes/samples/if-transition-inert/_config.js new file mode 100644 index 0000000000..7a1673786c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-transition-inert/_config.js @@ -0,0 +1,16 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `
hello
`, + + async test({ assert, target }) { + const [btn1, btn2] = target.querySelectorAll('button'); + + flushSync(() => { + btn1.click(); + }); + + assert.htmlEqual(target.innerHTML, `
hello
`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/if-transition-inert/main.svelte b/packages/svelte/tests/runtime-runes/samples/if-transition-inert/main.svelte new file mode 100644 index 0000000000..0a0cc2bdf6 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/if-transition-inert/main.svelte @@ -0,0 +1,17 @@ + + + + +{#if state} +
+ {#if true} + {state} + {/if} +
+{/if} + +