Skip to content

Commit fb7b05e

Browse files
committed
chore: simplify batch.apply()
1 parent 23e2bb3 commit fb7b05e

File tree

4 files changed

+38
-49
lines changed

4 files changed

+38
-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: 23 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);
@@ -282,6 +287,7 @@ export class Batch {
282287

283288
deactivate() {
284289
current_batch = null;
290+
batch_values = null;
285291
}
286292

287293
flush() {
@@ -352,14 +358,14 @@ export class Batch {
352358

353359
if (queued_root_effects.length > 0) {
354360
current_batch = batch;
355-
const revert = Batch.apply(batch);
361+
batch.apply();
356362

357363
for (const root of queued_root_effects) {
358364
batch.#traverse_effect_tree(root);
359365
}
360366

361367
queued_root_effects = [];
362-
revert();
368+
batch.deactivate();
363369
}
364370
}
365371

@@ -423,49 +429,23 @@ export class Batch {
423429
queue_micro_task(task);
424430
}
425431

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

434435
// 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-
}
436+
// we need to override values with the ones in this batch...
437+
batch_values = new Map(this.current);
446438

439+
// ...and undo changes belonging to other batches
447440
for (const batch of batches) {
448-
if (batch === current_batch) continue;
441+
if (batch === this) continue;
449442

450443
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;
444+
if (!batch_values.has(source)) {
445+
batch_values.set(source, previous);
454446
}
455447
}
456448
}
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-
};
469449
}
470450
}
471451

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

Lines changed: 3 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

@@ -346,8 +346,8 @@ export function update_derived(derived) {
346346
return;
347347
}
348348

349-
if (batch_deriveds !== null) {
350-
batch_deriveds.set(derived, derived.v);
349+
if (batch_values !== null) {
350+
batch_values.set(derived, derived.v);
351351
} else {
352352
var status =
353353
(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)