From 7238e1d3ceaaef7b44cc328cebeeb6da5cc671a2 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Mon, 11 Dec 2023 15:18:16 +0000 Subject: [PATCH] fix: improve each block index handling (#9889) --- .changeset/wise-dancers-hang.md | 5 +++++ .../phases/3-transform/client/visitors/template.js | 8 +++++++- packages/svelte/src/internal/client/validate.js | 7 ++++--- .../samples/each-block-keyed-index/_config.js | 5 +++++ .../samples/each-block-keyed-index/main.svelte | 3 +++ 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 .changeset/wise-dancers-hang.md create mode 100644 packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/_config.js create mode 100644 packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/main.svelte diff --git a/.changeset/wise-dancers-hang.md b/.changeset/wise-dancers-hang.md new file mode 100644 index 0000000000..0ed0f40a75 --- /dev/null +++ b/.changeset/wise-dancers-hang.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: improve each block index handling 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 dc420fc805..d62f1fcb49 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 @@ -2236,6 +2236,12 @@ export const template_visitors = { const item = b.id(each_node_meta.item_name); const binding = /** @type {import('#compiler').Binding} */ (context.state.scope.get(item.name)); binding.expression = each_item_is_reactive ? b.call('$.unwrap', item) : item; + if (node.index) { + const index_binding = /** @type {import('#compiler').Binding} */ ( + context.state.scope.get(node.index) + ); + index_binding.expression = each_item_is_reactive ? b.call('$.unwrap', index) : index; + } /** @type {import('estree').Statement[]} */ const declarations = []; @@ -2291,7 +2297,7 @@ export const template_visitors = { const key_function = node.key && ((each_type & EACH_ITEM_REACTIVE) !== 0 || context.state.options.dev) ? b.arrow( - [node.context.type === 'Identifier' ? node.context : b.id('$$item')], + [node.context.type === 'Identifier' ? node.context : b.id('$$item'), index], b.block( declarations.concat( b.return(/** @type {import('estree').Expression} */ (context.visit(node.key))) diff --git a/packages/svelte/src/internal/client/validate.js b/packages/svelte/src/internal/client/validate.js index 084d51d8f5..e3316891eb 100644 --- a/packages/svelte/src/internal/client/validate.js +++ b/packages/svelte/src/internal/client/validate.js @@ -1,4 +1,5 @@ -import { untrack } from './runtime.js'; +import { EACH_INDEX_REACTIVE } from '../../constants.js'; +import { source, untrack } from './runtime.js'; import { is_array } from './utils.js'; /** regex of all html void element names */ @@ -65,7 +66,7 @@ export function validate_dynamic_element_tag(tag_fn) { /** * @param {() => any} collection - * @param {(item: any) => string} key_fn + * @param {(item: any, index: number) => string} key_fn * @returns {void} */ export function validate_each_keys(collection, key_fn) { @@ -78,7 +79,7 @@ export function validate_each_keys(collection, key_fn) { : Array.from(maybe_array); const length = array.length; for (let i = 0; i < length; i++) { - const key = key_fn(array[i]); + const key = key_fn(array[i], i); if (keys.has(key)) { throw new Error( `Cannot have duplicate keys in a keyed each: Keys at index ${keys.get( diff --git a/packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/_config.js b/packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/_config.js new file mode 100644 index 0000000000..9e4c77c8be --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +export default test({ + html: `
0
1
` +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/main.svelte b/packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/main.svelte new file mode 100644 index 0000000000..0bda97bc69 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/each-block-keyed-index/main.svelte @@ -0,0 +1,3 @@ +{#each {length: 2} as item, i (`${i}`)} +
{i}
+{/each}