From 97587c3284f4767a7d8149abe4241aaeeb95554b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 24 Feb 2025 13:46:39 -0500 Subject: [PATCH] WIP --- .../src/internal/client/reactivity/forks.js | 12 +++++-- .../svelte/src/internal/client/runtime.js | 32 ++++++++++++++----- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/forks.js b/packages/svelte/src/internal/client/reactivity/forks.js index 18f94a8119..322c678b6c 100644 --- a/packages/svelte/src/internal/client/reactivity/forks.js +++ b/packages/svelte/src/internal/client/reactivity/forks.js @@ -1,4 +1,5 @@ /** @import { Effect, Source } from '#client' */ +import { noop } from '../../shared/utils.js'; import { DIRTY } from '../constants.js'; import { flushSync } from '../runtime.js'; import { internal_set, mark_reactions } from './sources.js'; @@ -26,6 +27,11 @@ export class Fork { #pending = 0; apply() { + if (forks.size === 1) { + // if this is the latest (and only) fork, we have nothing to do + return noop; + } + var values = new Map(); for (const source of this.previous.keys()) { @@ -53,8 +59,6 @@ export class Fork { for (const [source, value] of values) { source.v = value; } - - active_fork = null; }; } @@ -119,3 +123,7 @@ export class Fork { return active_fork; } } + +export function remove_active_fork() { + active_fork = null; +} diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 41d7810eb7..2c78e90fbe 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -49,7 +49,7 @@ import { import { Boundary } from './dom/blocks/boundary.js'; import * as w from './warnings.js'; import { is_firefox } from './dom/operations.js'; -import { active_fork, Fork } from './reactivity/forks.js'; +import { active_fork, Fork, remove_active_fork } from './reactivity/forks.js'; import { log_effect_tree } from './dev/debug.js'; // Used for DEV time error handling @@ -670,7 +670,7 @@ function flush_queued_root_effects() { return; } - var revert = active_fork.apply(); + var fork = active_fork; try { var flush_count = 0; @@ -692,18 +692,19 @@ function flush_queued_root_effects() { root.f ^= CLEAN; } - process_effects(root, active_fork); + process_effects(root, fork); } } } finally { // TODO this doesn't seem quite right — may run into // interesting cases where there are multiple roots. // it'll do for now though - if (active_fork.settled()) { - active_fork.remove(); + if (fork.settled()) { + fork.remove(); } - revert(); + remove_active_fork(); + is_flushing = false; last_scheduled_effect = null; @@ -787,8 +788,13 @@ export function schedule_effect(signal) { * @param {Fork} fork */ function process_effects(effect, fork) { + var revert = fork.apply(); + var current_effect = effect.first; + /** @type {Effect[]} */ + var async_effects = []; + /** @type {Effect[]} */ var render_effects = []; @@ -807,7 +813,11 @@ function process_effects(effect, fork) { active_fork?.skipped_effects.has(current_effect); if (!skip) { - if ((flags & (BLOCK_EFFECT | EFFECT_ASYNC)) !== 0) { + if ((flags & EFFECT_ASYNC) !== 0) { + if (check_dirtiness(current_effect)) { + async_effects.push(current_effect); + } + } else if ((flags & BLOCK_EFFECT) !== 0) { if (check_dirtiness(current_effect)) { update_effect(current_effect); } @@ -849,10 +859,16 @@ function process_effects(effect, fork) { current_effect = sibling; } - if (fork.settled()) { + if (async_effects.length === 0 && fork.settled()) { flush_queued_effects(render_effects); flush_queued_effects(effects); } + + revert(); + + for (const effect of async_effects) { + update_effect(effect); + } } /**