fix settled when awaits occur inside pending boundary

pull/15844/head
Rich Harris 3 months ago
parent 5fda0113b9
commit ea0e269138

@ -1,6 +1,6 @@
/** @import { Effect, TemplateNode, } from '#client' */
import { BOUNDARY_EFFECT, EFFECT_PRESERVED, EFFECT_TRANSPARENT } from '#client/constants';
import { BOUNDARY_EFFECT, EFFECT_PRESERVED, EFFECT_TRANSPARENT, INERT } from '#client/constants';
import { component_context, set_component_context } from '../../context.js';
import { invoke_error_boundary } from '../../error-handling.js';
import { block, branch, destroy_effect, pause_effect } from '../../reactivity/effects.js';
@ -151,6 +151,14 @@ export class Boundary {
return !!this.#props.pending;
}
is_pending() {
if (!this.ran && this.#props.pending) {
return true;
}
return this.#pending_effect !== null && (this.#pending_effect.f & INERT) === 0;
}
/**
* @param {() => Effect | null} fn
*/

@ -51,6 +51,9 @@ export class Batch {
/** @type {Effect[]} */
async_effects = [];
/** @type {Effect[]} */
boundary_async_effects = [];
/** @type {Effect[]} */
render_effects = [];
@ -188,7 +191,12 @@ export class Batch {
update_effect(effect);
}
for (const effect of this.boundary_async_effects) {
update_effect(effect);
}
this.async_effects = [];
this.boundary_async_effects = [];
}
/**

@ -132,7 +132,7 @@ export function async_derived(fn, location) {
prev = promise;
var batch = /** @type {Batch} */ (current_batch);
var ran = boundary.ran;
var ran = !boundary.is_pending();
if (should_suspend) {
(ran ? batch : boundary).increment();

@ -654,8 +654,11 @@ export function process_effects(batch, root) {
if (!skip && effect.fn !== null) {
if ((flags & EFFECT_ASYNC) !== 0) {
const boundary = effect.b;
if (check_dirtiness(effect)) {
batch.async_effects.push(effect);
var effects = boundary?.is_pending() ? batch.boundary_async_effects : batch.async_effects;
effects.push(effect);
}
} else if ((flags & BLOCK_EFFECT) !== 0) {
if (check_dirtiness(effect)) {

@ -1,4 +1,4 @@
import { flushSync, tick } from 'svelte';
import { settled } from 'svelte';
import { test } from '../../test';
export default test({
@ -9,22 +9,17 @@ export default test({
const [reset, resolve] = target.querySelectorAll('button');
flushSync(() => reset.click());
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await tick();
reset.click();
await settled();
assert.deepEqual(logs, ['aborted']);
flushSync(() => resolve.click());
resolve.click();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
await tick();
assert.htmlEqual(
target.innerHTML,
`

Loading…
Cancel
Save