Merge branch 'async' into async-abort-signal

async-abort-signal
Rich Harris 7 months ago
commit 6ab408a2cc

@ -14,7 +14,7 @@ export function async(node, expressions, fn) {
var restore = capture();
var unsuspend = suspend();
Promise.all(expressions.map(async_derived)).then((result) => {
Promise.all(expressions.map((fn) => async_derived(fn))).then((result) => {
restore();
fn(node, ...result);
unsuspend();

@ -138,6 +138,12 @@ export function boundary(node, props, children) {
}
function reset() {
async_count = 0;
if ((boundary.f & BOUNDARY_SUSPENDED) !== 0) {
boundary.f ^= BOUNDARY_SUSPENDED;
}
if (failed_effect !== null) {
pause_effect(failed_effect, () => {
failed_effect = null;
@ -153,6 +159,11 @@ export function boundary(node, props, children) {
reset_is_throwing_error();
}
});
if (async_count > 0) {
boundary.f |= BOUNDARY_SUSPENDED;
show_pending_snippet(true);
}
}
function unsuspend() {
@ -369,12 +380,7 @@ export function boundary(node, props, children) {
});
});
} else {
main_effect = branch(() => children(anchor));
if (async_count > 0) {
boundary.f |= BOUNDARY_SUSPENDED;
show_pending_snippet(true);
}
reset();
}
reset_is_throwing_error();

@ -147,7 +147,9 @@ export function async_derived(fn, detect_waterfall = true) {
}
},
(e) => {
handle_error(e, parent, null, parent.ctx);
if (promise === current) {
handle_error(e, parent, null, parent.ctx);
}
}
);
}, EFFECT_PRESERVED);

@ -0,0 +1,37 @@
import { flushSync, tick } from 'svelte';
import { deferred } from '../../../../src/internal/shared/utils.js';
import { test } from '../../test';
/** @type {ReturnType<typeof deferred>} */
let d;
export default test({
html: `<p>pending</p>`,
get props() {
d = deferred();
return {
promise: d.promise
};
},
async test({ assert, target, component }) {
d.reject(new Error('oops!'));
await Promise.resolve();
await Promise.resolve();
flushSync();
assert.htmlEqual(target.innerHTML, '<p>oops!</p><button>reset</button>');
const button = target.querySelector('button');
component.promise = (d = deferred()).promise;
flushSync(() => button?.click());
assert.htmlEqual(target.innerHTML, '<p>pending</p>');
d.resolve('wheee');
await Promise.resolve();
await tick();
assert.htmlEqual(target.innerHTML, '<h1>wheee</h1>');
}
});

@ -0,0 +1,16 @@
<script>
let { promise } = $props();
</script>
<svelte:boundary>
<h1>{await promise}</h1>
{#snippet pending()}
<p>pending</p>
{/snippet}
{#snippet failed(error, reset)}
<p>{error.message}</p>
<button onclick={reset}>reset</button>
{/snippet}
</svelte:boundary>
Loading…
Cancel
Save