pull/17004/head
Rich Harris 5 days ago
parent 54cd91f055
commit 1aa3db4641

@ -850,65 +850,62 @@ export function clear() {
/** /**
* @param {() => void} fn * @param {() => void} fn
* @returns {Promise<{ commit: () => void, discard: () => void }>} * @returns {{ commit: () => void, discard: () => void }}
*/ */
export function fork(fn) { export function fork(fn) {
/** @type {Promise<{ commit: () => void, discard: () => void }>} */ if (current_batch !== null) {
const promise = new Promise((fulfil) => { throw new Error('cannot fork here'); // TODO better error
// TODO does qmt guarantee this will run outside a batch? }
// because it needs to
queue_micro_task(async () => {
const batch = Batch.ensure();
batch.is_fork = true;
flushSync(fn);
const deferred_inspect_effects = inspect_effects;
// revert state changes
for (const [source, value] of batch.previous) {
source.v = value;
}
await batch.fork_settled(); const batch = Batch.ensure();
batch.is_fork = true;
fulfil({ const promise = batch.fork_settled();
commit: () => {
if (!batches.has(batch)) {
throw new Error('Cannot commit this batch'); // TODO better error
}
// delete all other forks flushSync(fn);
for (const b of batches) { const deferred_inspect_effects = inspect_effects;
if (b !== batch && b.is_fork) {
batches.delete(b);
}
}
for (const [source, value] of batch.current) { // revert state changes
source.v = value; for (const [source, value] of batch.previous) {
} source.v = value;
}
const previous_inspect_effects = inspect_effects; return {
commit: async () => {
if (!batches.has(batch)) {
throw new Error('Cannot commit this batch'); // TODO better error
}
try { // delete all other forks
if (DEV && deferred_inspect_effects.size > 0) { for (const b of batches) {
set_inspect_effects(deferred_inspect_effects); if (b !== batch && b.is_fork) {
flush_inspect_effects(); batches.delete(b);
} }
}
batch.is_fork = false; await promise;
batch.activate();
batch.revive(); for (const [source, value] of batch.current) {
} finally { source.v = value;
set_inspect_effects(previous_inspect_effects); }
}
}, const previous_inspect_effects = inspect_effects;
discard: () => {
batches.delete(batch); try {
if (DEV && deferred_inspect_effects.size > 0) {
set_inspect_effects(deferred_inspect_effects);
flush_inspect_effects();
} }
});
});
});
return promise; batch.is_fork = false;
batch.activate();
batch.revive();
} finally {
set_inspect_effects(previous_inspect_effects);
}
},
discard: () => {
batches.delete(batch);
}
};
} }

Loading…
Cancel
Save