fix: transform computed keys in keyed each block destructuring patterns

pull/18521/head
thribhuvan003 4 days ago
parent 5edd8b0602
commit 0bbb6057ca

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: transform computed keys in keyed `{#each}` destructuring patterns

@ -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)
);

@ -0,0 +1,7 @@
<script>
let { labelKey, valueKey, options } = $props();
</script>
{#each options as { [labelKey]: label, [valueKey]: value } (value)}
<p>{label}: {value}</p>
{/each}

@ -0,0 +1,29 @@
import { flushSync } from 'svelte';
import { ok, test } from '../../test';
// https://github.com/sveltejs/svelte/issues/18519
export default test({
html: `
<button>reverse</button>
<p>1: a1</p>
<p>2: a2</p>
<p>3: a3</p>
`,
test({ assert, target }) {
const btn = target.querySelector('button');
ok(btn);
flushSync(() => btn.click());
assert.htmlEqual(
target.innerHTML,
`
<button>reverse</button>
<p>3: a3</p>
<p>2: a2</p>
<p>1: a1</p>
`
);
}
});

@ -0,0 +1,12 @@
<script>
import Child from './Child.svelte';
let options = $state([
{ a: 1, v: 'a1' },
{ a: 2, v: 'a2' },
{ a: 3, v: 'a3' }
]);
</script>
<button onclick={() => options.reverse()}>reverse</button>
<Child {options} labelKey="a" valueKey="v" />
Loading…
Cancel
Save