Skip to content

Commit 4e847cf

Browse files
committed
merge main
2 parents 0b47787 + bd697c1 commit 4e847cf

File tree

9 files changed

+97
-3
lines changed

9 files changed

+97
-3
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

.changeset/slimy-turtles-yell.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: flush pending changes after rendering `failed` snippet

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/dom/blocks/boundary.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
skip_nodes,
3131
set_hydrate_node
3232
} from '../hydration.js';
33-
import { create_text, get_next_sibling } from '../operations.js';
33+
import { create_text } from '../operations.js';
3434
import { queue_micro_task } from '../task.js';
3535
import * as e from '../../errors.js';
3636
import * as w from '../../warnings.js';
@@ -427,6 +427,7 @@ export class Boundary {
427427
if (failed) {
428428
queue_micro_task(() => {
429429
this.#failed_effect = this.#run(() => {
430+
Batch.ensure();
430431
this.#is_creating_fallback = true;
431432

432433
try {

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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target, logs }) {
6+
const btn = target.querySelector('button');
7+
btn?.click();
8+
await tick();
9+
10+
assert.deepEqual(logs, ['attachment']);
11+
}
12+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script>
2+
let fail = $state(false);
3+
4+
function error() {
5+
throw new Error('oops');
6+
}
7+
8+
function attachment() {
9+
console.log('attachment');
10+
}
11+
</script>
12+
13+
<svelte:boundary>
14+
{fail ? error() : 'all good'}
15+
<button onclick={() => fail = true}>fail</button>
16+
17+
{#snippet failed()}
18+
<div {@attach attachment}>oops!</div>
19+
{/snippet}
20+
</svelte:boundary>
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)