From 4512462b6622406d03695f298efa603f4da04250 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Sat, 17 Aug 2024 14:32:49 +0100 Subject: [PATCH] chore: tweak each block logic (#12884) * chore: tweak each block logic to avoid Array.from * more tweaks * lint * Update packages/svelte/src/internal/client/dom/blocks/each.js Co-authored-by: Rich Harris * Update packages/svelte/src/internal/client/dom/blocks/each.js Co-authored-by: Rich Harris * Update packages/svelte/src/internal/client/dom/blocks/each.js Co-authored-by: Rich Harris --------- Co-authored-by: Rich Harris --- .../src/internal/client/dom/blocks/each.js | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 18785f7114..5788154db2 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -32,8 +32,8 @@ import { resume_effect } from '../../reactivity/effects.js'; import { source, mutable_source, set } from '../../reactivity/sources.js'; -import { is_array, is_frozen } from '../../../shared/utils.js'; -import { INERT, STATE_SYMBOL } from '../../constants.js'; +import { array_from, is_array } from '../../../shared/utils.js'; +import { INERT } from '../../constants.js'; import { queue_micro_task } from '../task.js'; import { current_effect } from '../../runtime.js'; @@ -139,7 +139,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f ? collection : collection == null ? [] - : Array.from(collection); + : array_from(collection); var length = array.length; @@ -242,14 +242,14 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { var first = state.first; var current = first; - /** @type {Set} */ - var seen = new Set(); + /** @type {undefined | Set} */ + var seen; /** @type {EachItem | null} */ var prev = null; - /** @type {Set} */ - var to_animate = new Set(); + /** @type {undefined | Set} */ + var to_animate; /** @type {EachItem[]} */ var matched = []; @@ -277,7 +277,7 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { if (item !== undefined) { item.a?.measure(); - to_animate.add(item); + (to_animate ??= new Set()).add(item); } } } @@ -319,12 +319,12 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { resume_effect(item.e); if (is_animated) { item.a?.unfix(); - to_animate.delete(item); + (to_animate ??= new Set()).delete(item); } } if (item !== current) { - if (seen.has(item)) { + if (seen !== undefined && seen.has(item)) { if (matched.length < stashed.length) { // more efficient to move later items to the front var start = stashed[0]; @@ -372,7 +372,7 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { stashed = []; while (current !== null && current.k !== key) { - seen.add(current); + (seen ??= new Set()).add(current); stashed.push(current); current = current.next; } @@ -389,32 +389,36 @@ function reconcile(array, state, anchor, render_fn, flags, get_key) { current = item.next; } - const to_destroy = Array.from(seen); + if (current !== null || seen !== undefined) { + var to_destroy = seen === undefined ? [] : array_from(seen); - while (current !== null) { - to_destroy.push(current); - current = current.next; - } - var destroy_length = to_destroy.length; + while (current !== null) { + to_destroy.push(current); + current = current.next; + } - if (destroy_length > 0) { - var controlled_anchor = (flags & EACH_IS_CONTROLLED) !== 0 && length === 0 ? anchor : null; + var destroy_length = to_destroy.length; - if (is_animated) { - for (i = 0; i < destroy_length; i += 1) { - to_destroy[i].a?.measure(); - } + if (destroy_length > 0) { + var controlled_anchor = (flags & EACH_IS_CONTROLLED) !== 0 && length === 0 ? anchor : null; - for (i = 0; i < destroy_length; i += 1) { - to_destroy[i].a?.fix(); + if (is_animated) { + for (i = 0; i < destroy_length; i += 1) { + to_destroy[i].a?.measure(); + } + + for (i = 0; i < destroy_length; i += 1) { + to_destroy[i].a?.fix(); + } } - } - pause_effects(state, to_destroy, controlled_anchor, items); + pause_effects(state, to_destroy, controlled_anchor, items); + } } if (is_animated) { queue_micro_task(() => { + if (to_animate === undefined) return; for (item of to_animate) { item.a?.apply(); }