fix: flush effects scheduled during boundary's pending phase (#16738)

Alternative to #16721, partial alternative to #16709. Closes #16691, closes #16627, closes #16582 and #16651 as well.
pull/16754/head
Rich Harris 1 week ago committed by GitHub
parent 0b5bcc891e
commit 72ce753278
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: flush effects scheduled during boundary's pending phase

@ -23,7 +23,7 @@ import { queue_micro_task } from '../task.js';
import * as e from '../../errors.js'; import * as e from '../../errors.js';
import * as w from '../../warnings.js'; import * as w from '../../warnings.js';
import { DEV } from 'esm-env'; import { DEV } from 'esm-env';
import { Batch, effect_pending_updates } from '../../reactivity/batch.js'; import { Batch, current_batch, effect_pending_updates } from '../../reactivity/batch.js';
import { internal_set, source } from '../../reactivity/sources.js'; import { internal_set, source } from '../../reactivity/sources.js';
import { tag } from '../../dev/tracing.js'; import { tag } from '../../dev/tracing.js';
import { createSubscriber } from '../../../../reactivity/create-subscriber.js'; import { createSubscriber } from '../../../../reactivity/create-subscriber.js';

@ -668,7 +668,7 @@ export function suspend() {
batch.activate(); batch.activate();
batch.decrement(); batch.decrement();
} else { } else {
batch.deactivate(); batch.flush();
} }
unset_context(); unset_context();

@ -0,0 +1,10 @@
<script>
function renderContent(node) {
node.textContent = 'foo';
}
const test = await Promise.resolve('foo');
</script>
<p>{test}</p>
<div {@attach renderContent}></div>

@ -0,0 +1,18 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target }) {
await tick();
assert.htmlEqual(target.innerHTML, '<button>toggle</button> <p>foo</p><div>foo</div>');
const [toggle] = target.querySelectorAll('button');
toggle.click();
await tick();
assert.htmlEqual(target.innerHTML, '<button>toggle</button>');
toggle.click();
await tick();
assert.htmlEqual(target.innerHTML, '<button>toggle</button> <p>foo</p><div>foo</div>');
}
});

@ -0,0 +1,16 @@
<script>
import Inner from './Inner.svelte';
let show = $state(true);
</script>
<svelte:boundary>
<button onclick={() => show = !show}>toggle</button>
{#if show}
<Inner />
{/if}
{#snippet pending()}
<p>pending</p>
{/snippet}
</svelte:boundary>

@ -0,0 +1,7 @@
<script>
await 1;
$effect(() => {
console.log('hello');
});
</script>

@ -0,0 +1,9 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, logs }) {
await tick();
assert.deepEqual(logs, ['hello']);
}
});

@ -0,0 +1,9 @@
<script>
import Child from './Child.svelte';
</script>
<svelte:boundary>
<Child />
{#snippet pending()}{/snippet}
</svelte:boundary>
Loading…
Cancel
Save