fix: batch resolution of async work (#17511)

* fix: batch resolution of async work

Co-authored-by: David Roizenman <hmnd@users.noreply.github.com>

* fix

* drive-by tidy up — Batch.enqueue is (apparently?) a useless wrapper around queue_micro_task

* 99% sure it's impossible for is_flushing to be true inside a queued task

* add some comments

* return early, reduce indentation

---------

Co-authored-by: David Roizenman <hmnd@users.noreply.github.com>
pull/17517/head
Rich Harris 5 days ago committed by GitHub
parent ac03d27d68
commit 1ff7dd6123
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: batch resolution of async work

@ -102,6 +102,7 @@ export class Boundary {
#local_pending_count = 0;
#pending_count = 0;
#pending_count_update_queued = false;
#is_creating_fallback = false;
@ -202,12 +203,11 @@ export class Boundary {
#hydrate_pending_content() {
const pending = this.#props.pending;
if (!pending) {
return;
}
if (!pending) return;
this.#pending_effect = branch(() => pending(this.#anchor));
Batch.enqueue(() => {
queue_micro_task(() => {
var anchor = this.#get_anchor();
this.#main_effect = this.#run(() => {
@ -359,9 +359,15 @@ export class Boundary {
this.#local_pending_count += d;
if (this.#effect_pending) {
internal_set(this.#effect_pending, this.#local_pending_count);
}
if (!this.#effect_pending || this.#pending_count_update_queued) return;
this.#pending_count_update_queued = true;
queue_micro_task(() => {
this.#pending_count_update_queued = false;
if (this.#effect_pending) {
internal_set(this.#effect_pending, this.#local_pending_count);
}
});
}
get_effect_pending() {

@ -138,6 +138,8 @@ export class Batch {
is_fork = false;
#decrement_queued = false;
is_deferred() {
return this.is_fork || this.#blocking_pending > 0;
}
@ -426,7 +428,22 @@ export class Batch {
this.#pending -= 1;
if (blocking) this.#blocking_pending -= 1;
this.revive();
if (this.#decrement_queued) return;
this.#decrement_queued = true;
queue_micro_task(() => {
this.#decrement_queued = false;
if (!this.is_deferred()) {
// we only reschedule previously-deferred effects if we expect
// to be able to run them after processing the batch
this.revive();
} else if (queued_root_effects.length > 0) {
// if other effects are scheduled, process the batch _without_
// rescheduling the previously-deferred effects
this.flush();
}
});
}
revive() {
@ -464,7 +481,7 @@ export class Batch {
batches.add(current_batch);
if (!is_flushing_sync) {
Batch.enqueue(() => {
queue_micro_task(() => {
if (current_batch !== batch) {
// a flushSync happened in the meantime
return;
@ -478,11 +495,6 @@ export class Batch {
return current_batch;
}
/** @param {() => void} task */
static enqueue(task) {
queue_micro_task(task);
}
apply() {
if (!async_mode_flag || (!this.is_fork && batches.size === 1)) return;

Loading…
Cancel
Save