From 9eefe34b2a83335917f52f94389f448f446095a8 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 28 Jul 2024 13:48:03 -0400 Subject: [PATCH] add each.metadata.keyed --- .../svelte/src/compiler/phases/2-analyze/index.js | 7 +++++++ .../phases/3-transform/client/visitors/template.js | 14 +++++++------- packages/svelte/src/compiler/phases/scope.js | 1 + packages/svelte/src/compiler/types/template.d.ts | 1 + 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index aa1e43196f..aac76faa60 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -1547,6 +1547,13 @@ const common_visitors = { }, RenderTag(node, context) { context.next({ ...context.state, render_tag: node }); + }, + EachBlock(node) { + if (node.key) { + // treat `{#each items as item, i (i)}` as a normal indexed block, everything else as keyed + node.metadata.keyed = + node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index; + } } }; 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 cf0fd231e5..7fe24c1013 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 @@ -2409,10 +2409,7 @@ export const template_visitors = { let flags = 0; - if ( - node.key && - (node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index) - ) { + if (node.metadata.keyed) { flags |= EACH_KEYED; if (node.index) { @@ -2421,7 +2418,7 @@ export const template_visitors = { // In runes mode, if key === item, we don't need to wrap the item in a source const key_is_item = - node.key.type === 'Identifier' && + /** @type {Expression} */ (node.key).type === 'Identifier' && node.context.type === 'Identifier' && node.context.name === node.key.name; @@ -2614,8 +2611,11 @@ export const template_visitors = { /** @type {Expression} */ let key_function = b.id('$.index'); - if (node.key) { - const expression = /** @type {Expression} */ (context.visit(node.key, key_state)); + if (node.metadata.keyed) { + const expression = /** @type {Expression} */ ( + context.visit(/** @type {Expression} */ (node.key), key_state) + ); + key_function = b.arrow([node.context, index], expression); } diff --git a/packages/svelte/src/compiler/phases/scope.js b/packages/svelte/src/compiler/phases/scope.js index 1ba9851ee3..167f61e034 100644 --- a/packages/svelte/src/compiler/phases/scope.js +++ b/packages/svelte/src/compiler/phases/scope.js @@ -592,6 +592,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) { } node.metadata = { + keyed: false, contains_group_binding: false, array_name: needs_array_deduplication ? state.scope.root.unique('$$array') : null, index: scope.root.unique('$$index'), diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index ec35a08227..e5bc072c1a 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -393,6 +393,7 @@ export interface EachBlock extends BaseNode { index?: string; key?: Expression; metadata: { + keyed: boolean; contains_group_binding: boolean; /** Set if something in the array expression is shadowed within the each block */ array_name: Identifier | null;