fix: take into account static blocks when determining transition locality (#17018)

The "is this a transparent effect we can ignore" logic for determining whether or not to play a local transition didn't account for pruned block effects. This fix marks the child branch as transparent if the block effect was, and during traversal then checks if the branch is the child of a block - if not that means it's the child of a pruned block effect.

fixes #16826
pull/16200/merge
Simon H 1 week ago committed by GitHub
parent 86aedaecf9
commit cd3a11edff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: take into account static blocks when determining transition locality

@ -14,7 +14,10 @@ export const DESTROYED = 1 << 14;
// Flags exclusive to effects
export const EFFECT_RAN = 1 << 15;
/** 'Transparent' effects do not create a transition boundary */
/**
* 'Transparent' effects do not create a transition boundary.
* This is on a block effect 99% of the time but may also be on a branch effect if its parent block effect was pruned
*/
export const EFFECT_TRANSPARENT = 1 << 16;
export const INSPECT_EFFECT = 1 << 17;
export const HEAD_EFFECT = 1 << 18;

@ -149,6 +149,9 @@ function create_effect(type, fn, sync, push = true) {
(e.f & EFFECT_PRESERVED) === 0
) {
e = e.first;
if ((type & BLOCK_EFFECT) !== 0 && (type & EFFECT_TRANSPARENT) !== 0 && e !== null) {
e.f |= EFFECT_TRANSPARENT;
}
}
if (e !== null) {
@ -604,7 +607,12 @@ export function pause_children(effect, transitions, local) {
while (child !== null) {
var sibling = child.next;
var transparent = (child.f & EFFECT_TRANSPARENT) !== 0 || (child.f & BRANCH_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.

@ -0,0 +1,22 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target }) {
const btn = target.querySelector('button');
btn?.click();
flushSync();
assert.htmlEqual(
target.innerHTML,
`
<button>Toggle</button>
<div>Should not transition out</div>
`
);
btn?.click();
flushSync();
assert.htmlEqual(target.innerHTML, '<button>Toggle</button>');
}
});

@ -0,0 +1,18 @@
<script>
import { slide } from 'svelte/transition';
let showText = $state(false);
let show = $state(true);
</script>
<button onclick={() => showText = !showText}>
Toggle
</button>
{#if showText}
{#if show}
<div transition:slide>
Should not transition out
</div>
{/if}
{/if}
Loading…
Cancel
Save