Skip to content

Commit 5f3fcaf

Browse files
authored
fix: bail-out event handler referencing each index (#10063)
* fix: bail-out event handler referencing each index * lint * ts * types
1 parent 15d6308 commit 5f3fcaf

File tree

5 files changed

+28
-7
lines changed

5 files changed

+28
-7
lines changed

.changeset/tall-garlics-try.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: bail-out event handler referencing each index

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ function get_delegated_event(node, context) {
183183
) {
184184
return non_hoistable;
185185
}
186+
// If we referebnce the index within an each block, then bail-out.
187+
if (binding !== null && binding.initial?.type === 'EachBlock') {
188+
return non_hoistable;
189+
}
186190

187191
if (
188192
binding !== null &&

packages/svelte/src/compiler/phases/scope.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class Scope {
6565
* @param {import('estree').Identifier} node
6666
* @param {import('#compiler').Binding['kind']} kind
6767
* @param {import('#compiler').DeclarationKind} declaration_kind
68-
* @param {null | import('estree').Expression | import('estree').FunctionDeclaration | import('estree').ClassDeclaration | import('estree').ImportDeclaration} initial
68+
* @param {null | import('estree').Expression | import('estree').FunctionDeclaration | import('estree').ClassDeclaration | import('estree').ImportDeclaration | import('../types/template.js').EachBlock} initial
6969
* @returns {import('#compiler').Binding}
7070
*/
7171
declare(node, kind, declaration_kind, initial = null) {
@@ -523,7 +523,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
523523
const is_keyed =
524524
node.key &&
525525
(node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index);
526-
scope.declare(b.id(node.index), is_keyed ? 'derived' : 'normal', 'const');
526+
scope.declare(b.id(node.index), is_keyed ? 'derived' : 'normal', 'const', node);
527527
}
528528
if (node.key) visit(node.key, { scope });
529529

@@ -680,7 +680,7 @@ export function set_scope(scopes) {
680680

681681
/**
682682
* Returns the name of the rune if the given expression is a `CallExpression` using a rune.
683-
* @param {import('estree').Node | null | undefined} node
683+
* @param {import('estree').Node | import('../types/template.js').EachBlock | null | undefined} node
684684
* @param {Scope} scope
685685
* @returns {Runes[number] | null}
686686
*/

packages/svelte/src/compiler/types/index.d.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { SourceMap } from 'magic-string';
1111
import type { Context } from 'zimmerframe';
1212
import type { Scope } from '../phases/scope.js';
1313
import * as Css from './css.js';
14-
import type { Namespace, SvelteNode } from './template.js';
14+
import type { EachBlock, Namespace, SvelteNode } from './template.js';
1515

1616
/** The return value of `compile` from `svelte/compiler` */
1717
export interface CompileResult {
@@ -269,7 +269,13 @@ export interface Binding {
269269
* What the value was initialized with.
270270
* For destructured props such as `let { foo = 'bar' } = $props()` this is `'bar'` and not `$props()`
271271
*/
272-
initial: null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration;
272+
initial:
273+
| null
274+
| Expression
275+
| FunctionDeclaration
276+
| ClassDeclaration
277+
| ImportDeclaration
278+
| EachBlock;
273279
is_called: boolean;
274280
references: { node: Identifier; path: SvelteNode[] }[];
275281
mutated: boolean;

packages/svelte/types/index.d.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,13 @@ declare module 'svelte/compiler' {
746746
* What the value was initialized with.
747747
* For destructured props such as `let { foo = 'bar' } = $props()` this is `'bar'` and not `$props()`
748748
*/
749-
initial: null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration;
749+
initial:
750+
| null
751+
| Expression
752+
| FunctionDeclaration
753+
| ClassDeclaration
754+
| ImportDeclaration
755+
| EachBlock;
750756
is_called: boolean;
751757
references: { node: Identifier; path: SvelteNode[] }[];
752758
mutated: boolean;
@@ -1021,7 +1027,7 @@ declare module 'svelte/compiler' {
10211027
*/
10221028
function_depth: number;
10231029

1024-
declare(node: import('estree').Identifier, kind: Binding['kind'], declaration_kind: DeclarationKind, initial?: null | import('estree').Expression | import('estree').FunctionDeclaration | import('estree').ClassDeclaration | import('estree').ImportDeclaration): Binding;
1030+
declare(node: import('estree').Identifier, kind: Binding['kind'], declaration_kind: DeclarationKind, initial?: null | import('estree').Expression | import('estree').FunctionDeclaration | import('estree').ClassDeclaration | import('estree').ImportDeclaration | EachBlock): Binding;
10251031
child(porous?: boolean): Scope;
10261032

10271033
generate(preferred_name: string): string;

0 commit comments

Comments
 (0)