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

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