Skip to content

Commit fea81ad

Browse files
committed
fix: store forked derived values
1 parent 1aafbc4 commit fea81ad

File tree

6 files changed

+60
-3
lines changed

6 files changed

+60
-3
lines changed

.changeset/strong-berries-fry.md

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+
fix: store forked derived values

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ export let previous_batch = null;
6868
*/
6969
export let batch_values = null;
7070

71+
/**
72+
* When time travelling (i.e. working in one batch, while other batches
73+
* still have ongoing work), we ignore the real values of affected
74+
* signals in favour of their values within the batch
75+
* @type {Map<Value, any> | null}
76+
*/
77+
export let forked_derived_values = null;
78+
7179
// TODO this should really be a property of `batch`
7280
/** @type {Effect[]} */
7381
let queued_root_effects = [];
@@ -962,8 +970,12 @@ export function fork(fn) {
962970
var committed = false;
963971
var settled = batch.settled();
964972

973+
forked_derived_values = new Map();
974+
965975
flushSync(fn);
966976

977+
forked_derived_values = null;
978+
967979
// revert state changes
968980
for (var [source, value] of batch.previous) {
969981
source.v = value;

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { async_mode_flag, tracing_mode_flag } from '../../flags/index.js';
3434
import { Boundary } from '../dom/blocks/boundary.js';
3535
import { component_context } from '../context.js';
3636
import { UNINITIALIZED } from '../../../constants.js';
37-
import { batch_values, current_batch } from './batch.js';
37+
import { batch_values, current_batch, forked_derived_values } from './batch.js';
3838
import { unset_context } from './async.js';
3939
import { deferred } from '../../shared/utils.js';
4040

@@ -360,8 +360,10 @@ export function update_derived(derived) {
360360
// the underlying value will be updated when the fork is committed.
361361
// otherwise, the next time we get here after a 'real world' state
362362
// change, `derived.equals` may incorrectly return `true`
363-
if (!current_batch?.is_fork) {
363+
if (!forked_derived_values) {
364364
derived.v = value;
365+
} else {
366+
forked_derived_values.set(derived, value);
365367
}
366368

367369
derived.wv = increment_write_version();

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ import {
4343
set_dev_stack
4444
} from './context.js';
4545
import * as w from './warnings.js';
46-
import { Batch, batch_values, flushSync, schedule_effect } from './reactivity/batch.js';
46+
import {
47+
Batch,
48+
batch_values,
49+
flushSync,
50+
forked_derived_values,
51+
schedule_effect
52+
} from './reactivity/batch.js';
4753
import { handle_error } from './error-handling.js';
4854
import { UNINITIALIZED } from '../../constants.js';
4955
import { captured_signals } from './legacy.js';
@@ -621,6 +627,10 @@ export function get(signal) {
621627
if (is_updating_effect && effect_tracking() && (derived.f & CONNECTED) === 0) {
622628
reconnect(derived);
623629
}
630+
631+
if (forked_derived_values?.has(derived)) {
632+
return forked_derived_values.get(derived);
633+
}
624634
}
625635

626636
if (batch_values?.has(signal)) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
skip_no_async: true,
6+
async test({ assert, target, logs }) {
7+
const fork = target.querySelector('button');
8+
9+
flushSync(() => {
10+
fork?.click();
11+
});
12+
13+
assert.deepEqual(logs, [1]);
14+
}
15+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import { fork } from "svelte";
3+
4+
let state = $state(0);
5+
let count = $derived(state);
6+
</script>
7+
8+
<button onclick={() => {
9+
fork(() => {
10+
state++;
11+
console.log(count);
12+
});
13+
}}>fork</button>

0 commit comments

Comments
 (0)