From 18ecf0138291f4e09a44cfc9a6facd2e683b04d9 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 16 Oct 2025 17:28:35 -0400 Subject: [PATCH] WIP --- .../src/internal/client/reactivity/async.js | 6 ++++-- .../src/internal/client/reactivity/batch.js | 21 ++++++++++++++++--- .../internal/client/reactivity/deriveds.js | 6 ++++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/async.js b/packages/svelte/src/internal/client/reactivity/async.js index b1e8177949..a223d1b5be 100644 --- a/packages/svelte/src/internal/client/reactivity/async.js +++ b/packages/svelte/src/internal/client/reactivity/async.js @@ -203,8 +203,10 @@ export async function async_body(fn) { var boundary = get_boundary(); var batch = /** @type {Batch} */ (current_batch); + var blocking = !boundary.is_pending(); + boundary.update_pending_count(1); - batch.increment(); + batch.increment(blocking); var active = /** @type {Effect} */ (active_effect); @@ -237,7 +239,7 @@ export async function async_body(fn) { } boundary.update_pending_count(-1); - batch.decrement(); + batch.decrement(blocking); unset_context(); } diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index c429b23c98..413cf63284 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -101,6 +101,11 @@ export class Batch { */ #pending = 0; + /** + * The number of async effects that are currently in flight, _not_ inside a pending boundary + */ + #blocking_pending = 0; + /** * A deferred that resolves when the batch is committed, used with `settled()` * TODO replace with Promise.withResolvers once supported widely enough @@ -257,7 +262,7 @@ export class Batch { } } - if (should_defer) { + if (this.#blocking_pending > 0) { this.#defer_effects(target.effects); this.#defer_effects(target.render_effects); this.#defer_effects(target.block_effects); @@ -407,12 +412,22 @@ export class Batch { this.#deferred?.resolve(); } - increment() { + /** + * + * @param {boolean} blocking + */ + increment(blocking) { this.#pending += 1; + if (blocking) this.#blocking_pending += 1; } - decrement() { + /** + * + * @param {boolean} blocking + */ + decrement(blocking) { this.#pending -= 1; + if (blocking) this.#blocking_pending -= 1; for (const e of this.#dirty_effects) { set_signal_status(e, DIRTY); diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index e9d5edca05..1989220abe 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -138,8 +138,10 @@ export function async_derived(fn, location) { var batch = /** @type {Batch} */ (current_batch); if (should_suspend) { + var blocking = !boundary.is_pending(); + boundary.update_pending_count(1); - batch.increment(); + batch.increment(blocking); deferreds.get(batch)?.reject(STALE_REACTION); deferreds.delete(batch); // delete to ensure correct order in Map iteration below @@ -190,7 +192,7 @@ export function async_derived(fn, location) { if (should_suspend) { boundary.update_pending_count(-1); - batch.decrement(); + batch.decrement(blocking); } };