diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index 7c051079df..390aa51115 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -134,11 +134,9 @@ export function async_derived(fn, location) { } if (fork !== null) { - fork?.enable(); - flush_sync(() => { + fork.run(() => { internal_set(signal, v); }); - fork?.disable(); } else { internal_set(signal, v); } diff --git a/packages/svelte/src/internal/client/reactivity/forks.js b/packages/svelte/src/internal/client/reactivity/forks.js index 2529772b9c..1c04f3104c 100644 --- a/packages/svelte/src/internal/client/reactivity/forks.js +++ b/packages/svelte/src/internal/client/reactivity/forks.js @@ -1,5 +1,8 @@ /** @import { Effect, Source } from '#client' */ +import { flush_sync } from '../runtime.js'; +import { internal_set } from './sources.js'; + /** @type {Set} */ const forks = new Set(); @@ -29,14 +32,64 @@ export class Fork { } } - enable() { - active_fork = this; - // TODO revert other forks + /** + * + * @param {() => void} fn + */ + flush(fn) { + var values = new Map(); + + for (const fork of forks) { + if (fork === this) continue; + + for (const [source, previous] of fork.previous) { + if (this.previous.has(source)) continue; + + values.set(source, source.v); + source.v = previous; + // internal_set(source, previous); + } + } + + try { + fn(); + } finally { + for (const [source, value] of values) { + // internal_set(source, value); + source.v = value; + } + } } - disable() { + remove() { + forks.delete(this); + + for (var fork of forks) { + if (fork.id < this.id) { + // other fork is older than this + for (var source of this.previous.keys()) { + fork.previous.delete(source); + } + } else { + // other fork is newer than this + for (var source of fork.previous.keys()) { + if (this.previous.has(source)) { + fork.previous.set(source, source.v); + } + } + } + } + } + + /** + * @param {() => void} fn + */ + run(fn) { + active_fork = this; + + flush_sync(fn); + active_fork = null; - // TODO restore state } increment() { @@ -52,7 +105,12 @@ export class Fork { } static ensure() { - return (active_fork ??= new Fork()); + if (active_fork === null) { + active_fork = new Fork(); + forks.add(active_fork); // TODO figure out where we remove this + } + + return active_fork; } static unset() { diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index d738ffe40f..f642d704b4 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -703,10 +703,12 @@ function flush_queued_root_effects(root_effects) { effect.f ^= CLEAN; } + var fork = /** @type {Fork} */ (active_fork); var collected_effects = process_effects(effect); - if (/** @type {Fork} */ (active_fork).settled()) { + if (fork.settled()) { flush_queued_effects(collected_effects); + fork.remove(); } } } finally {