pull/16200/merge
Rich Harris 1 week ago
commit 4e847cfd14

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

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: flush pending changes after rendering `failed` snippet

@ -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;

@ -30,7 +30,7 @@ import {
skip_nodes,
set_hydrate_node
} from '../hydration.js';
import { create_text, get_next_sibling } from '../operations.js';
import { create_text } from '../operations.js';
import { queue_micro_task } from '../task.js';
import * as e from '../../errors.js';
import * as w from '../../warnings.js';
@ -427,6 +427,7 @@ export class Boundary {
if (failed) {
queue_micro_task(() => {
this.#failed_effect = this.#run(() => {
Batch.ensure();
this.#is_creating_fallback = true;
try {

@ -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,12 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target, logs }) {
const btn = target.querySelector('button');
btn?.click();
await tick();
assert.deepEqual(logs, ['attachment']);
}
});

@ -0,0 +1,20 @@
<script>
let fail = $state(false);
function error() {
throw new Error('oops');
}
function attachment() {
console.log('attachment');
}
</script>
<svelte:boundary>
{fail ? error() : 'all good'}
<button onclick={() => fail = true}>fail</button>
{#snippet failed()}
<div {@attach attachment}>oops!</div>
{/snippet}
</svelte:boundary>

@ -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