From 437509915c0916b9c1b3eaf9af081e34c0e09f06 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Sat, 17 Aug 2024 00:11:31 +0100 Subject: [PATCH] Revert "chore: bring back recursive processing of effects" (#12880) * Revert "chore: bring back recursive processing of effects (#12861)" This reverts commit cb124315be03a47710672eb661b57d714d01fd52. * apply tweak --- .../svelte/src/internal/client/runtime.js | 110 ++++++++++-------- 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 2ab833fc25..6a32095b6d 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -571,53 +571,6 @@ export function schedule_effect(signal) { current_queued_root_effects.push(effect); } -/** - * @param {Effect} effect - * @param {Effect[]} effects - */ -function process_effect_children(effect, effects) { - var current = effect.first; - - while (current !== null) { - var next = current.next; - process_effect(current, effects); - current = next; - } -} - -/** - * @param {Effect} effect - * @param {Effect[]} effects - */ -function process_effect(effect, effects) { - var flags = effect.f; - // TODO: we probably don't need to check for destroyed as it shouldn't be encountered? - var is_active = (flags & (DESTROYED | INERT)) === 0; - var is_branch = (flags & BRANCH_EFFECT) !== 0; - var is_clean = (flags & CLEAN) !== 0; - - // Skip this branch if it's clean - if (is_active && (!is_branch || !is_clean)) { - if (is_branch) { - set_signal_status(effect, CLEAN); - } - - if ((flags & RENDER_EFFECT) !== 0) { - if (!is_branch && check_dirtiness(effect)) { - update_effect(effect); - } - - process_effect_children(effect, effects); - } else if ((flags & EFFECT) !== 0) { - if (is_branch || is_clean) { - process_effect_children(effect, effects); - } else { - effects.push(effect); - } - } - } -} - /** * * This function both runs render effects and collects user effects in topological order @@ -630,13 +583,70 @@ function process_effect(effect, effects) { * @returns {void} */ function process_effects(effect, collected_effects) { - /** @type {Effect[]} */ + var current_effect = effect.first; var effects = []; - process_effect_children(effect, effects); + + main_loop: while (current_effect !== null) { + var flags = current_effect.f; + // TODO: we probably don't need to check for destroyed as it shouldn't be encountered? + var is_active = (flags & (DESTROYED | INERT)) === 0; + var is_branch = (flags & BRANCH_EFFECT) !== 0; + var is_clean = (flags & CLEAN) !== 0; + var child = current_effect.first; + + // Skip this branch if it's clean + if (is_active && (!is_branch || !is_clean)) { + if (is_branch) { + set_signal_status(current_effect, CLEAN); + } + + if ((flags & RENDER_EFFECT) !== 0) { + if (!is_branch && check_dirtiness(current_effect)) { + update_effect(current_effect); + // Child might have been mutated since running the effect + child = current_effect.first; + } + + if (child !== null) { + current_effect = child; + continue; + } + } else if ((flags & EFFECT) !== 0) { + if (is_branch || is_clean) { + if (child !== null) { + current_effect = child; + continue; + } + } else { + effects.push(current_effect); + } + } + } + var sibling = current_effect.next; + + if (sibling === null) { + let parent = current_effect.parent; + + while (parent !== null) { + if (effect === parent) { + break main_loop; + } + var parent_sibling = parent.next; + if (parent_sibling !== null) { + current_effect = parent_sibling; + continue main_loop; + } + parent = parent.parent; + } + } + + current_effect = sibling; + } + // We might be dealing with many effects here, far more than can be spread into // an array push call (callstack overflow). So let's deal with each effect in a loop. for (var i = 0; i < effects.length; i++) { - var child = effects[i]; + child = effects[i]; collected_effects.push(child); process_effects(child, collected_effects); }