Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/thirty-rules-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: error if `each` block has `key` but no `as` clause
8 changes: 7 additions & 1 deletion documentation/docs/98-reference/.generated/compile-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Cyclical dependency detected: %cycle%
### const_tag_invalid_reference

```
The `{@const %name% = ...}` declaration is not available in this snippet
The `{@const %name% = ...}` declaration is not available in this snippet
```

The following is an error:
Expand Down Expand Up @@ -453,6 +453,12 @@ This turned out to be buggy and unpredictable, particularly when working with de
{/each}
```

### each_key_without_as

```
An `{#each ...}` block without an `as` clause cannot have a key
```

### effect_invalid_placement

```
Expand Down
6 changes: 5 additions & 1 deletion packages/svelte/messages/compile-errors/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
## const_tag_invalid_reference

> The `{@const %name% = ...}` declaration is not available in this snippet
> The `{@const %name% = ...}` declaration is not available in this snippet
The following is an error:

Expand Down Expand Up @@ -179,6 +179,10 @@ The same applies to components:

> `%type%` name cannot be empty
## each_key_without_as

> An `{#each ...}` block without an `as` clause cannot have a key
## element_invalid_closing_tag

> `</%name%>` attempted to close an element that was not open
Expand Down
13 changes: 11 additions & 2 deletions packages/svelte/src/compiler/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -986,13 +986,13 @@ export function const_tag_invalid_placement(node) {
}

/**
* The `{@const %name% = ...}` declaration is not available in this snippet
* The `{@const %name% = ...}` declaration is not available in this snippet
* @param {null | number | NodeLike} node
* @param {string} name
* @returns {never}
*/
export function const_tag_invalid_reference(node, name) {
e(node, 'const_tag_invalid_reference', `The \`{@const ${name} = ...}\` declaration is not available in this snippet \nhttps://svelte.dev/e/const_tag_invalid_reference`);
e(node, 'const_tag_invalid_reference', `The \`{@const ${name} = ...}\` declaration is not available in this snippet\nhttps://svelte.dev/e/const_tag_invalid_reference`);
}

/**
Expand Down Expand Up @@ -1023,6 +1023,15 @@ export function directive_missing_name(node, type) {
e(node, 'directive_missing_name', `\`${type}\` name cannot be empty\nhttps://svelte.dev/e/directive_missing_name`);
}

/**
* An `{#each ...}` block without an `as` clause cannot have a key
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function each_key_without_as(node) {
e(node, 'each_key_without_as', `An \`{#each ...}\` block without an \`as\` clause cannot have a key\nhttps://svelte.dev/e/each_key_without_as`);
}

/**
* `</%name%>` attempted to close an element that was not open
* @param {null | number | NodeLike} node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export function EachBlock(node, context) {
node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index;
}

if (node.metadata.keyed && !node.context) {
e.each_key_without_as(node);
}

// evaluate expression in parent scope
context.visit(node.expression, {
...context.state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default test({
async: true,
error: {
code: 'const_tag_invalid_reference',
message: 'The `{@const foo = ...}` declaration is not available in this snippet ',
message: 'The `{@const foo = ...}` declaration is not available in this snippet',
position: [376, 379]
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default test({
async: true,
error: {
code: 'const_tag_invalid_reference',
message: 'The `{@const foo = ...}` declaration is not available in this snippet ',
message: 'The `{@const foo = ...}` declaration is not available in this snippet',
position: [298, 301]
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test } from '../../test';

export default test({
error: {
code: 'each_key_without_as',
message: 'An `{#each ...}` block without an `as` clause cannot have a key'
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let items = [{ id: 3 }, { id: 2 }, { id: 1 }];
</script>

{#each items, i (items[i].id)}
<p>{items[i].id}</p>
{/each}
Loading