Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twenty-onions-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ignore fork `discard()` after `commit()`
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ This restriction only applies when using the `experimental.async` option, which
### fork_discarded

```
Cannot commit a fork that was already committed or discarded
Cannot commit a fork that was already discarded
```

### fork_timing
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/messages/client-errors/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ This restriction only applies when using the `experimental.async` option, which

## fork_discarded

> Cannot commit a fork that was already committed or discarded
> Cannot commit a fork that was already discarded
## fork_timing

Expand Down
4 changes: 2 additions & 2 deletions packages/svelte/src/internal/client/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,12 @@ export function flush_sync_in_effect() {
}

/**
* Cannot commit a fork that was already committed or discarded
* Cannot commit a fork that was already discarded
* @returns {never}
*/
export function fork_discarded() {
if (DEV) {
const error = new Error(`fork_discarded\nCannot commit a fork that was already committed or discarded\nhttps://svelte.dev/e/fork_discarded`);
const error = new Error(`fork_discarded\nCannot commit a fork that was already discarded\nhttps://svelte.dev/e/fork_discarded`);

error.name = 'Svelte error';

Expand Down
22 changes: 15 additions & 7 deletions packages/svelte/src/internal/client/reactivity/batch.js
Original file line number Diff line number Diff line change
Expand Up @@ -913,28 +913,36 @@ export function fork(fn) {
e.fork_timing();
}

const batch = Batch.ensure();
var batch = Batch.ensure();
batch.is_fork = true;

const settled = batch.settled();
var committed = false;
var settled = batch.settled();

flushSync(fn);

// revert state changes
for (const [source, value] of batch.previous) {
for (var [source, value] of batch.previous) {
source.v = value;
}

return {
commit: async () => {
if (committed) {
await settled;
return;
}

if (!batches.has(batch)) {
e.fork_discarded();
}

committed = true;

batch.is_fork = false;

// apply changes
for (const [source, value] of batch.current) {
for (var [source, value] of batch.current) {
source.v = value;
}

Expand All @@ -945,9 +953,9 @@ export function fork(fn) {
// TODO maybe there's a better implementation?
flushSync(() => {
/** @type {Set<Effect>} */
const eager_effects = new Set();
var eager_effects = new Set();

for (const source of batch.current.keys()) {
for (var source of batch.current.keys()) {
mark_eager_effects(source, eager_effects);
}

Expand All @@ -959,7 +967,7 @@ export function fork(fn) {
await settled;
},
discard: () => {
if (batches.has(batch)) {
if (!committed && batches.has(batch)) {
batches.delete(batch);
batch.discard();
}
Expand Down
Loading