diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 6f8bfd2064d9..e06474b34dcc 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -1036,7 +1036,7 @@ const common_visitors = { // If the same identifiers in the same order are used in another bind:group, they will be in the same group. // (there's an edge case where `bind:group={a[i]}` will be in a different group than `bind:group={a[j]}` even when i == j, // but this is a limitation of the current static analysis we do; it also never worked in Svelte 4) - const bindings = expression_ids.map((id) => context.state.scope.get(id.name)); + const bindings = expression_ids.map((id) => context.state.scope.get(id.name) ?? id); let group_name; outer: for (const [b, group] of context.state.analysis.binding_groups) { if (b.length !== bindings.length) continue; diff --git a/packages/svelte/src/compiler/phases/types.d.ts b/packages/svelte/src/compiler/phases/types.d.ts index ba1c14788910..cb0039b18bd3 100644 --- a/packages/svelte/src/compiler/phases/types.d.ts +++ b/packages/svelte/src/compiler/phases/types.d.ts @@ -68,7 +68,7 @@ export interface ComponentAnalysis extends Analysis { inject_styles: boolean; reactive_statements: Map; /** Identifiers that make up the `bind:group` expression -> internal group binding name */ - binding_groups: Map, Identifier>; + binding_groups: Map, Identifier>; slot_names: Set; } diff --git a/packages/svelte/src/compiler/utils/ast.js b/packages/svelte/src/compiler/utils/ast.js index 9f16679bc730..ae28ca077eed 100644 --- a/packages/svelte/src/compiler/utils/ast.js +++ b/packages/svelte/src/compiler/utils/ast.js @@ -108,11 +108,8 @@ export function extract_all_identifiers_from_expression(expr) { expr, {}, { - Identifier(node, { path }) { - const parent = path.at(-1); - if (parent?.type !== 'MemberExpression' || parent.property !== node || parent.computed) { - nodes.push(node); - } + Identifier(node) { + nodes.push(node); } } ); diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-input-group-each-16/_config.js b/packages/svelte/tests/runtime-legacy/samples/binding-input-group-each-16/_config.js new file mode 100644 index 000000000000..54ddd20af17d --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/binding-input-group-each-16/_config.js @@ -0,0 +1,23 @@ +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + const checkboxes = /** @type {NodeListOf} */ ( + target.querySelectorAll('input[type="checkbox"]') + ); + + assert.isFalse(checkboxes[0].checked); + assert.isTrue(checkboxes[1].checked); + assert.isFalse(checkboxes[2].checked); + + await checkboxes[1].click(); + + const noChecked = target.querySelector('#output')?.innerHTML; + assert.equal(noChecked, ''); + + await checkboxes[1].click(); + + const oneChecked = target.querySelector('#output')?.innerHTML; + assert.equal(oneChecked, 'Mint choc chip'); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-input-group-each-16/main.svelte b/packages/svelte/tests/runtime-legacy/samples/binding-input-group-each-16/main.svelte new file mode 100644 index 000000000000..56a5465ffe7f --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/binding-input-group-each-16/main.svelte @@ -0,0 +1,17 @@ + + +
+ One scoop + Two scoops + Three scoops + + {#each menu as flavour} + {flavour} + {/each} +
+ +
{$order.flavours.join('+')}
\ No newline at end of file