Skip to content

Commit 0c0662b

Browse files
committed
better fix
1 parent 1ca795b commit 0c0662b

File tree

2 files changed

+16
-19
lines changed

2 files changed

+16
-19
lines changed

packages/svelte/src/internal/client/reactivity/batch.js

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ let last_scheduled_effect = null;
7070

7171
let is_flushing = false;
7272

73-
let flushing_sync = false;
73+
export let flushing_sync = false;
7474

7575
export class Batch {
7676
/**
@@ -204,9 +204,22 @@ export class Batch {
204204
this.#effects = [];
205205
this.#block_effects = [];
206206

207+
// If sources are written to, then work needs to happen in a separate batch, else prior sources would be mixed with
208+
// newly updated sources, which could lead to infinite loops when effects run over and over again.
209+
current_batch = null;
210+
207211
flush_queued_effects(render_effects);
208212
flush_queued_effects(effects);
209213

214+
// Reinstate the current batch if there was no new one created, as `process()` runs in a loop in `flush_effects()`.
215+
// That method expects `current_batch` to be set, and could run the loop again if effects result in new effects
216+
// being scheduled but without writes happening in which case no new batch is created.
217+
if (current_batch === null) {
218+
current_batch = this;
219+
} else {
220+
batches.delete(this);
221+
}
222+
210223
this.#deferred?.resolve();
211224
} else {
212225
// otherwise mark effects clean so they get scheduled on the next run
@@ -551,7 +564,6 @@ function flush_queued_effects(effects) {
551564

552565
if ((effect.f & (DESTROYED | INERT)) === 0 && is_dirty(effect)) {
553566
var wv = write_version;
554-
var current_size = /** @type {Batch} */ (current_batch).current.size;
555567

556568
update_effect(effect);
557569

@@ -575,21 +587,6 @@ function flush_queued_effects(effects) {
575587
// if state is written in a user effect, abort and re-schedule, lest we run
576588
// effects that should be removed as a result of the state change
577589
if (write_version > wv && (effect.f & USER_EFFECT) !== 0) {
578-
// Work needs to happen in a separate batch, else prior sources would be mixed with
579-
// newly updated sources, which could lead to infinite loops when effects run over and over again.
580-
// We need to bring over the just written sources though to correctly mark the right reactions as dirty.
581-
var old_batch = /** @type {Batch} */ (current_batch);
582-
batches.delete(old_batch);
583-
current_batch = null;
584-
var new_batch = Batch.ensure(!flushing_sync);
585-
var current_idx = 0;
586-
// We're taking advantage of the spec here which says that entries in a Map are traversed by insertion order
587-
for (const source of old_batch.current) {
588-
if (current_idx >= current_size) {
589-
new_batch.capture(source[0], source[1]);
590-
}
591-
current_idx++;
592-
}
593590
break;
594591
}
595592
}

packages/svelte/src/internal/client/reactivity/sources.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import * as e from '../errors.js';
3333
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
3434
import { get_stack, tag_proxy } from '../dev/tracing.js';
3535
import { component_context, is_runes } from '../context.js';
36-
import { Batch, schedule_effect } from './batch.js';
36+
import { Batch, flushing_sync, schedule_effect } from './batch.js';
3737
import { proxy } from '../proxy.js';
3838
import { execute_derived } from './deriveds.js';
3939

@@ -179,7 +179,7 @@ export function internal_set(source, value) {
179179

180180
source.v = value;
181181

182-
const batch = Batch.ensure();
182+
const batch = Batch.ensure(!flushing_sync);
183183
batch.capture(source, old_value);
184184

185185
if (DEV) {

0 commit comments

Comments
 (0)