Skip to content

Commit a7c958a

Browse files
authored
chore: simplify batch.apply() (#16945)
* chore: simplify `batch.apply()` * belt and braces * note to self
1 parent 2a95139 commit a7c958a

File tree

4 files changed

+41
-49
lines changed

4 files changed

+41
-49
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
chore: simplify `batch.apply()`

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

Lines changed: 24 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ export let current_batch = null;
4444
export let previous_batch = null;
4545

4646
/**
47-
* When time travelling, we re-evaluate deriveds based on the temporary
48-
* values of their dependencies rather than their actual values, and cache
49-
* the results in this map rather than on the deriveds themselves
50-
* @type {Map<Derived, any> | null}
47+
* When time travelling (i.e. working in one batch, while other batches
48+
* still have ongoing work), we ignore the real values of affected
49+
* signals in favour of their values within the batch
50+
* @type {Map<Value, any> | null}
5151
*/
52-
export let batch_deriveds = null;
52+
export let batch_values = null;
5353

5454
/** @type {Set<() => void>} */
5555
export let effect_pending_updates = new Set();
@@ -152,7 +152,7 @@ export class Batch {
152152

153153
previous_batch = null;
154154

155-
var revert = Batch.apply(this);
155+
this.apply();
156156

157157
for (const root of root_effects) {
158158
this.#traverse_effect_tree(root);
@@ -161,6 +161,10 @@ export class Batch {
161161
// if we didn't start any new async work, and no async work
162162
// is outstanding from a previous flush, commit
163163
if (this.#pending === 0) {
164+
// TODO we need this because we commit _then_ flush effects...
165+
// maybe there's a way we can reverse the order?
166+
var previous_batch_sources = batch_values;
167+
164168
this.#commit();
165169

166170
var render_effects = this.#render_effects;
@@ -175,6 +179,7 @@ export class Batch {
175179
previous_batch = this;
176180
current_batch = null;
177181

182+
batch_values = previous_batch_sources;
178183
flush_queued_effects(render_effects);
179184
flush_queued_effects(effects);
180185

@@ -187,7 +192,7 @@ export class Batch {
187192
this.#defer_effects(this.#block_effects);
188193
}
189194

190-
revert();
195+
batch_values = null;
191196

192197
for (const effect of this.#boundary_async_effects) {
193198
update_effect(effect);
@@ -274,6 +279,7 @@ export class Batch {
274279
}
275280

276281
this.current.set(source, source.v);
282+
batch_values?.set(source, source.v);
277283
}
278284

279285
activate() {
@@ -282,6 +288,7 @@ export class Batch {
282288

283289
deactivate() {
284290
current_batch = null;
291+
batch_values = null;
285292
}
286293

287294
flush() {
@@ -352,14 +359,14 @@ export class Batch {
352359

353360
if (queued_root_effects.length > 0) {
354361
current_batch = batch;
355-
const revert = Batch.apply(batch);
362+
batch.apply();
356363

357364
for (const root of queued_root_effects) {
358365
batch.#traverse_effect_tree(root);
359366
}
360367

361368
queued_root_effects = [];
362-
revert();
369+
batch.deactivate();
363370
}
364371
}
365372

@@ -423,49 +430,23 @@ export class Batch {
423430
queue_micro_task(task);
424431
}
425432

426-
/**
427-
* @param {Batch} current_batch
428-
*/
429-
static apply(current_batch) {
430-
if (!async_mode_flag || batches.size === 1) {
431-
return noop;
432-
}
433+
apply() {
434+
if (!async_mode_flag || batches.size === 1) return;
433435

434436
// if there are multiple batches, we are 'time travelling' —
435-
// we need to undo the changes belonging to any batch
436-
// other than the current one
437-
438-
/** @type {Map<Source, { v: unknown, wv: number }>} */
439-
var current_values = new Map();
440-
batch_deriveds = new Map();
441-
442-
for (const [source, current] of current_batch.current) {
443-
current_values.set(source, { v: source.v, wv: source.wv });
444-
source.v = current;
445-
}
437+
// we need to override values with the ones in this batch...
438+
batch_values = new Map(this.current);
446439

440+
// ...and undo changes belonging to other batches
447441
for (const batch of batches) {
448-
if (batch === current_batch) continue;
442+
if (batch === this) continue;
449443

450444
for (const [source, previous] of batch.#previous) {
451-
if (!current_values.has(source)) {
452-
current_values.set(source, { v: source.v, wv: source.wv });
453-
source.v = previous;
445+
if (!batch_values.has(source)) {
446+
batch_values.set(source, previous);
454447
}
455448
}
456449
}
457-
458-
return () => {
459-
for (const [source, { v, wv }] of current_values) {
460-
// reset the source to the current value (unless
461-
// it got a newer value as a result of effects running)
462-
if (source.wv <= wv) {
463-
source.v = v;
464-
}
465-
}
466-
467-
batch_deriveds = null;
468-
};
469450
}
470451
}
471452

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { async_mode_flag, tracing_mode_flag } from '../../flags/index.js';
3333
import { Boundary } from '../dom/blocks/boundary.js';
3434
import { component_context } from '../context.js';
3535
import { UNINITIALIZED } from '../../../constants.js';
36-
import { batch_deriveds, current_batch } from './batch.js';
36+
import { batch_values, current_batch } from './batch.js';
3737
import { unset_context } from './async.js';
3838
import { deferred } from '../../shared/utils.js';
3939

@@ -336,6 +336,8 @@ export function update_derived(derived) {
336336
var value = execute_derived(derived);
337337

338338
if (!derived.equals(value)) {
339+
// TODO can we avoid setting `derived.v` when `batch_values !== null`,
340+
// without causing the value to be stale later?
339341
derived.v = value;
340342
derived.wv = increment_write_version();
341343
}
@@ -346,8 +348,8 @@ export function update_derived(derived) {
346348
return;
347349
}
348350

349-
if (batch_deriveds !== null) {
350-
batch_deriveds.set(derived, derived.v);
351+
if (batch_values !== null) {
352+
batch_values.set(derived, derived.v);
351353
} else {
352354
var status =
353355
(skip_reaction || (derived.f & UNOWNED) !== 0) && derived.deps !== null ? MAYBE_DIRTY : CLEAN;

packages/svelte/src/internal/client/runtime.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import {
4242
set_dev_stack
4343
} from './context.js';
4444
import * as w from './warnings.js';
45-
import { Batch, batch_deriveds, flushSync, schedule_effect } from './reactivity/batch.js';
45+
import { Batch, batch_values, flushSync, schedule_effect } from './reactivity/batch.js';
4646
import { handle_error } from './error-handling.js';
4747
import { UNINITIALIZED } from '../../constants.js';
4848
import { captured_signals } from './legacy.js';
@@ -671,15 +671,19 @@ export function get(signal) {
671671
} else if (is_derived) {
672672
derived = /** @type {Derived} */ (signal);
673673

674-
if (batch_deriveds?.has(derived)) {
675-
return batch_deriveds.get(derived);
674+
if (batch_values?.has(derived)) {
675+
return batch_values.get(derived);
676676
}
677677

678678
if (is_dirty(derived)) {
679679
update_derived(derived);
680680
}
681681
}
682682

683+
if (batch_values?.has(signal)) {
684+
return batch_values.get(signal);
685+
}
686+
683687
if ((signal.f & ERROR_VALUE) !== 0) {
684688
throw signal.v;
685689
}

0 commit comments

Comments
 (0)