Skip to content

Commit 92cef6e

Browse files
committed
fix: take into account static blocks when determining transition locality
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
1 parent 86aedae commit 92cef6e

File tree

5 files changed

+58
-2
lines changed

5 files changed

+58
-2
lines changed

.changeset/easy-paths-take.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: take into account static blocks when determining transition locality

packages/svelte/src/internal/client/constants.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ export const DESTROYED = 1 << 14;
1414

1515
// Flags exclusive to effects
1616
export const EFFECT_RAN = 1 << 15;
17-
/** 'Transparent' effects do not create a transition boundary */
17+
/**
18+
* 'Transparent' effects do not create a transition boundary.
19+
* 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
20+
*/
1821
export const EFFECT_TRANSPARENT = 1 << 16;
1922
export const INSPECT_EFFECT = 1 << 17;
2023
export const HEAD_EFFECT = 1 << 18;

packages/svelte/src/internal/client/reactivity/effects.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ function create_effect(type, fn, sync, push = true) {
149149
(e.f & EFFECT_PRESERVED) === 0
150150
) {
151151
e = e.first;
152+
if ((type & BLOCK_EFFECT) !== 0 && (type & EFFECT_TRANSPARENT) !== 0 && e !== null) {
153+
e.f |= EFFECT_TRANSPARENT;
154+
}
152155
}
153156

154157
if (e !== null) {
@@ -604,7 +607,12 @@ export function pause_children(effect, transitions, local) {
604607

605608
while (child !== null) {
606609
var sibling = child.next;
607-
var transparent = (child.f & EFFECT_TRANSPARENT) !== 0 || (child.f & BRANCH_EFFECT) !== 0;
610+
var transparent =
611+
(child.f & EFFECT_TRANSPARENT) !== 0 ||
612+
// If this is a branch effect without a block effect parent,
613+
// it means the parent block effect was pruned. In that case,
614+
// transparency information was transferred to the branch effect.
615+
((child.f & BRANCH_EFFECT) !== 0 && (effect.f & BLOCK_EFFECT) !== 0);
608616
// TODO we don't need to call pause_children recursively with a linked list in place
609617
// it's slightly more involved though as we have to account for `transparent` changing
610618
// through the tree.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
const btn = target.querySelector('button');
7+
8+
btn?.click();
9+
flushSync();
10+
assert.htmlEqual(
11+
target.innerHTML,
12+
`
13+
<button>Toggle</button>
14+
<div>Should not transition out</div>
15+
`
16+
);
17+
18+
btn?.click();
19+
flushSync();
20+
assert.htmlEqual(target.innerHTML, '<button>Toggle</button>');
21+
}
22+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
<script>
3+
import { slide } from 'svelte/transition';
4+
let showText = $state(false);
5+
let show = $state(true);
6+
</script>
7+
8+
<button onclick={() => showText = !showText}>
9+
Toggle
10+
</button>
11+
12+
{#if showText}
13+
{#if show}
14+
<div transition:slide>
15+
Should not transition out
16+
</div>
17+
{/if}
18+
{/if}

0 commit comments

Comments
 (0)