From 8798f3b1e72b071abae5a0100f503e495c3726b7 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Mon, 13 Nov 2023 18:32:02 +0000 Subject: [PATCH] chore: split $.each into $.each_keyed/$.each_indexed (#9422) * Split $.each into $.each_keyed/$.each_indexed * Add changeset * Update .changeset/quiet-camels-mate.md * Fix typo --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> --- .changeset/quiet-camels-mate.md | 5 ++ .../3-transform/client/visitors/template.js | 39 ++++++++++----- .../svelte/src/internal/client/reconciler.js | 6 +-- packages/svelte/src/internal/client/render.js | 49 ++++++++++++------- 4 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 .changeset/quiet-camels-mate.md diff --git a/.changeset/quiet-camels-mate.md b/.changeset/quiet-camels-mate.md new file mode 100644 index 0000000000..6e723bd4ab --- /dev/null +++ b/.changeset/quiet-camels-mate.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: improve keyblock treeshaking diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index c80153a327..b830367776 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -2227,19 +2227,34 @@ export const template_visitors = { declarations.push(b.let(node.index, index)); } - context.state.after_update.push( - b.stmt( - b.call( - '$.each', - context.state.node, - each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection), - b.literal(each_type), - key_function, - b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children))), - else_block + if ((each_type & EACH_KEYED) !== 0) { + context.state.after_update.push( + b.stmt( + b.call( + '$.each_keyed', + context.state.node, + each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection), + b.literal(each_type), + key_function, + b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children))), + else_block + ) ) - ) - ); + ); + } else { + context.state.after_update.push( + b.stmt( + b.call( + '$.each_indexed', + context.state.node, + each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection), + b.literal(each_type), + b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children))), + else_block + ) + ) + ); + } }, IfBlock(node, context) { context.state.template.push(''); diff --git a/packages/svelte/src/internal/client/reconciler.js b/packages/svelte/src/internal/client/reconciler.js index f0b0fce7c2..ded5c7ec23 100644 --- a/packages/svelte/src/internal/client/reconciler.js +++ b/packages/svelte/src/internal/client/reconciler.js @@ -260,9 +260,9 @@ export function reconcile_indexed_array( * @param {Element | Comment | Text} dom * @param {boolean} is_controlled * @param {(anchor: null, item: V, index: number | import('./types.js').Signal) => void} render_fn - * @param {Array | null} keys * @param {number} flags * @param {boolean} apply_transitions + * @param {Array | null} keys * @returns {void} */ export function reconcile_tracked_array( @@ -271,9 +271,9 @@ export function reconcile_tracked_array( dom, is_controlled, render_fn, - keys, flags, - apply_transitions + apply_transitions, + keys ) { var a_blocks = each_block.items; const is_computed_key = keys !== null; diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 5c1ce1181d..135b99b0c6 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -68,7 +68,7 @@ import { hydrate_block_anchor, set_current_hydration_fragment } from './hydration.js'; -import { array_from, define_property, get_descriptor, get_descriptors, is_array } from './utils.js'; +import { array_from, define_property, get_descriptor, is_array } from './utils.js'; import { is_promise } from '../common.js'; import { bind_transition } from './transitions.js'; @@ -2262,9 +2262,10 @@ export function each_item_block(item, key, index, render_fn, flags) { * @param {null | ((item: V) => string)} key_fn * @param {(anchor: null, item: V, index: import('./types.js').MaybeSignal) => void} render_fn * @param {null | ((anchor: Node) => void)} fallback_fn + * @param {typeof reconcile_indexed_array | reconcile_tracked_array} reconcile_fn * @returns {void} */ -export function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn) { +function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, reconcile_fn) { const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0; const block = create_each_block(flags, anchor_node); @@ -2384,20 +2385,7 @@ export function each(anchor_node, collection, flags, key_fn, render_fn, fallback const flags = block.flags; const is_controlled = (flags & EACH_IS_CONTROLLED) !== 0; const anchor_node = block.anchor; - if ((flags & EACH_KEYED) !== 0) { - reconcile_tracked_array( - array, - block, - anchor_node, - is_controlled, - render_fn, - keys, - flags, - true - ); - } else { - reconcile_indexed_array(array, block, anchor_node, is_controlled, render_fn, flags, true); - } + reconcile_fn(array, block, anchor_node, is_controlled, render_fn, flags, true, keys); }, block, true @@ -2419,12 +2407,39 @@ export function each(anchor_node, collection, flags, key_fn, render_fn, fallback fallback = fallback.prev; } // Clear the array - reconcile_indexed_array([], block, anchor_node, is_controlled, render_fn, flags, false); + reconcile_fn([], block, anchor_node, is_controlled, render_fn, flags, false, keys); destroy_signal(/** @type {import('./types.js').EffectSignal} */ (render)); }); block.effect = each; } +/** + * @template V + * @param {Element | Comment} anchor_node + * @param {() => V[]} collection + * @param {number} flags + * @param {null | ((item: V) => string)} key_fn + * @param {(anchor: null, item: V, index: import('./types.js').MaybeSignal) => void} render_fn + * @param {null | ((anchor: Node) => void)} fallback_fn + * @returns {void} + */ +export function each_keyed(anchor_node, collection, flags, key_fn, render_fn, fallback_fn) { + each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, reconcile_tracked_array); +} + +/** + * @template V + * @param {Element | Comment} anchor_node + * @param {() => V[]} collection + * @param {number} flags + * @param {(anchor: null, item: V, index: import('./types.js').MaybeSignal) => void} render_fn + * @param {null | ((anchor: Node) => void)} fallback_fn + * @returns {void} + */ +export function each_indexed(anchor_node, collection, flags, render_fn, fallback_fn) { + each(anchor_node, collection, flags, null, render_fn, fallback_fn, reconcile_indexed_array); +} + /** * @param {Element | Text | Comment} anchor * @param {boolean} is_html