fix: ignore fork `discard()` after `commit()` (#17034)

* fix: ignore fork `discard()` after `commit()`

* fix message
pull/17035/head
Rich Harris 1 day ago committed by GitHub
parent 875a04170e
commit 657ec89caa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ignore fork `discard()` after `commit()`

@ -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

@ -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

@ -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';

@ -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;
}
@ -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);
}
@ -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();
}

Loading…
Cancel
Save