Skip to content

Commit 824b3f4

Browse files
committed
feat: add isCommitted/isDiscarded/run to fork
This gives more insight into the state of a fork and also gives you the ability to run another function in the context of the fork. SvelteKit needs this
1 parent 1aafbc4 commit 824b3f4

File tree

4 files changed

+60
-0
lines changed

4 files changed

+60
-0
lines changed

.changeset/lemon-walls-judge.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': minor
3+
---
4+
5+
feat: add `isCommitted/isDiscarded/run` to `fork`

packages/svelte/src/index.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,18 @@ export interface Fork {
366366
* Discard the fork
367367
*/
368368
discard(): void;
369+
/**
370+
* Whether the fork has been committed
371+
*/
372+
isCommitted(): boolean;
373+
/**
374+
* Whether the fork has been discarded
375+
*/
376+
isDiscarded(): boolean;
377+
/**
378+
* Run a function within the forked context.
379+
*/
380+
run(fn: () => void): Promise<void>;
369381
}
370382

371383
export * from './index-client.js';

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,37 @@ export function fork(fn) {
10141014
batches.delete(batch);
10151015
batch.discard();
10161016
}
1017+
},
1018+
isCommitted: () => committed,
1019+
isDiscarded: () => !committed && !batches.has(batch),
1020+
run: async (fn) => {
1021+
if (committed) {
1022+
// TODO error instead?
1023+
await settled;
1024+
fn();
1025+
} else {
1026+
// We want to start with the current state of the world, not the
1027+
// state back when the fork was created. Also important to
1028+
// correctly revert state changes later
1029+
const previous = batch.previous;
1030+
batch.previous = new Map();
1031+
batch.activate();
1032+
1033+
flushSync(fn);
1034+
1035+
// revert state changes
1036+
for (var [source, value] of batch.previous) {
1037+
source.v = value;
1038+
}
1039+
1040+
// merge 'previous' map
1041+
// TODO is this correct?
1042+
for (const [source, value] of previous) {
1043+
if (!batch.previous.has(source)) {
1044+
batch.previous.set(source, value);
1045+
}
1046+
}
1047+
}
10171048
}
10181049
};
10191050
}

packages/svelte/types/index.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,18 @@ declare module 'svelte' {
363363
* Discard the fork
364364
*/
365365
discard(): void;
366+
/**
367+
* Whether the fork has been committed
368+
*/
369+
isCommitted(): boolean;
370+
/**
371+
* Whether the fork has been discarded
372+
*/
373+
isDiscarded(): boolean;
374+
/**
375+
* Run a function within the forked context.
376+
*/
377+
run(fn: () => void): Promise<void>;
366378
}
367379
/**
368380
* Returns an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that aborts when the current [derived](https://svelte.dev/docs/svelte/$derived) or [effect](https://svelte.dev/docs/svelte/$effect) re-runs or is destroyed.

0 commit comments

Comments
 (0)