async-fixes-2
Simon Holthausen 2 months ago
parent 1ca795bd8e
commit 0c0662bbdc

@ -70,7 +70,7 @@ let last_scheduled_effect = null;
let is_flushing = false;
let flushing_sync = false;
export let flushing_sync = false;
export class Batch {
/**
@ -204,9 +204,22 @@ export class Batch {
this.#effects = [];
this.#block_effects = [];
// If sources are written to, then work needs to happen in a separate batch, else prior sources would be mixed with
// newly updated sources, which could lead to infinite loops when effects run over and over again.
current_batch = null;
flush_queued_effects(render_effects);
flush_queued_effects(effects);
// Reinstate the current batch if there was no new one created, as `process()` runs in a loop in `flush_effects()`.
// That method expects `current_batch` to be set, and could run the loop again if effects result in new effects
// being scheduled but without writes happening in which case no new batch is created.
if (current_batch === null) {
current_batch = this;
} else {
batches.delete(this);
}
this.#deferred?.resolve();
} else {
// otherwise mark effects clean so they get scheduled on the next run
@ -551,7 +564,6 @@ function flush_queued_effects(effects) {
if ((effect.f & (DESTROYED | INERT)) === 0 && is_dirty(effect)) {
var wv = write_version;
var current_size = /** @type {Batch} */ (current_batch).current.size;
update_effect(effect);
@ -575,21 +587,6 @@ function flush_queued_effects(effects) {
// if state is written in a user effect, abort and re-schedule, lest we run
// effects that should be removed as a result of the state change
if (write_version > wv && (effect.f & USER_EFFECT) !== 0) {
// Work needs to happen in a separate batch, else prior sources would be mixed with
// newly updated sources, which could lead to infinite loops when effects run over and over again.
// We need to bring over the just written sources though to correctly mark the right reactions as dirty.
var old_batch = /** @type {Batch} */ (current_batch);
batches.delete(old_batch);
current_batch = null;
var new_batch = Batch.ensure(!flushing_sync);
var current_idx = 0;
// We're taking advantage of the spec here which says that entries in a Map are traversed by insertion order
for (const source of old_batch.current) {
if (current_idx >= current_size) {
new_batch.capture(source[0], source[1]);
}
current_idx++;
}
break;
}
}

@ -33,7 +33,7 @@ import * as e from '../errors.js';
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
import { get_stack, tag_proxy } from '../dev/tracing.js';
import { component_context, is_runes } from '../context.js';
import { Batch, schedule_effect } from './batch.js';
import { Batch, flushing_sync, schedule_effect } from './batch.js';
import { proxy } from '../proxy.js';
import { execute_derived } from './deriveds.js';
@ -179,7 +179,7 @@ export function internal_set(source, value) {
source.v = value;
const batch = Batch.ensure();
const batch = Batch.ensure(!flushing_sync);
batch.capture(source, old_value);
if (DEV) {

Loading…
Cancel
Save