From 0bbb6057ca579adf9a0f800f752825f55641501c Mon Sep 17 00:00:00 2001 From: thribhuvan003 Date: Fri, 10 Jul 2026 12:29:24 +0530 Subject: [PATCH] fix: transform computed keys in keyed each block destructuring patterns --- .changeset/shiny-keys-dance.md | 5 ++++ .../3-transform/client/visitors/EachBlock.js | 7 ++++- .../Child.svelte | 7 +++++ .../_config.js | 29 +++++++++++++++++++ .../main.svelte | 12 ++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 .changeset/shiny-keys-dance.md create mode 100644 packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/main.svelte diff --git a/.changeset/shiny-keys-dance.md b/.changeset/shiny-keys-dance.md new file mode 100644 index 0000000000..20cf754212 --- /dev/null +++ b/.changeset/shiny-keys-dance.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: transform computed keys in keyed `{#each}` destructuring patterns diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js index a1371b516a..45511714a1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/EachBlock.js @@ -294,7 +294,12 @@ export function EachBlock(node, context) { let key_function = b.id('$.index'); if (node.metadata.keyed) { - const pattern = /** @type {Pattern} */ (node.context); // can only be keyed when a context is provided + // the pattern needs to be visited so that expressions inside it (e.g. computed + // keys or default values referencing component scope) are transformed correctly. + // can only be keyed when a context is provided + const pattern = /** @type {Pattern} */ ( + context.visit(/** @type {Pattern} */ (node.context), key_state) + ); const expression = /** @type {Expression} */ ( context.visit(/** @type {Expression} */ (node.key), key_state) ); diff --git a/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/Child.svelte b/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/Child.svelte new file mode 100644 index 0000000000..35544d0a55 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/Child.svelte @@ -0,0 +1,7 @@ + + +{#each options as { [labelKey]: label, [valueKey]: value } (value)} +

{label}: {value}

+{/each} diff --git a/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/_config.js b/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/_config.js new file mode 100644 index 0000000000..8a8789d712 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/_config.js @@ -0,0 +1,29 @@ +import { flushSync } from 'svelte'; +import { ok, test } from '../../test'; + +// https://github.com/sveltejs/svelte/issues/18519 +export default test({ + html: ` + +

1: a1

+

2: a2

+

3: a3

+ `, + + test({ assert, target }) { + const btn = target.querySelector('button'); + ok(btn); + + flushSync(() => btn.click()); + + assert.htmlEqual( + target.innerHTML, + ` + +

3: a3

+

2: a2

+

1: a1

+ ` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/main.svelte b/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/main.svelte new file mode 100644 index 0000000000..6885a6918e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/each-keyed-computed-destructuring-key/main.svelte @@ -0,0 +1,12 @@ + + + +