Skip to content

Commit 55656f5

Browse files
authored
feat: add support for {@const} inside snippet block (#9904)
* check for snippet block * change the error msg * edit tests * changeset * test
1 parent b0511a5 commit 55656f5

File tree

7 files changed

+35
-3
lines changed

7 files changed

+35
-3
lines changed

.changeset/chatty-cups-drop.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+
feat: add support for `{@const}` inside snippet block

packages/svelte/src/compiler/errors.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ const compiler_options = {
333333
/** @satisfies {Errors} */
334334
const const_tag = {
335335
'invalid-const-placement': () =>
336-
`{@const} must be the immediate child of {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>`
336+
`{@const} must be the immediate child of {#snippet}, {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>`
337337
};
338338

339339
/** @satisfies {Errors} */

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ export const validation = {
476476
grand_parent?.type !== 'SvelteComponent' &&
477477
grand_parent?.type !== 'EachBlock' &&
478478
grand_parent?.type !== 'AwaitBlock' &&
479+
grand_parent?.type !== 'SnippetBlock' &&
479480
((grand_parent?.type !== 'RegularElement' && grand_parent?.type !== 'SvelteElement') ||
480481
!grand_parent.attributes.some((a) => a.type === 'Attribute' && a.name === 'slot')))
481482
) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: `<button>0</button>`,
5+
async test({ assert, target }) {
6+
const btn = target.querySelector('button');
7+
8+
assert.htmlEqual(target.innerHTML, '<button>0</button>');
9+
10+
await btn?.click();
11+
assert.htmlEqual(target.innerHTML, '<button>2</button>');
12+
13+
await btn?.click();
14+
assert.htmlEqual(target.innerHTML, '<button>4</button>');
15+
}
16+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
let count = $state(0);
3+
</script>
4+
5+
{#snippet counter()}
6+
{@const doubled = count * 2}
7+
<button on:click={() => (count += 1)}>{doubled}</button>
8+
{/snippet}
9+
10+
{@render counter()}

packages/svelte/tests/validator/samples/const-tag-placement-1/errors.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
33
"code": "invalid-const-placement",
4-
"message": "{@const} must be the immediate child of {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>",
4+
"message": "{@const} must be the immediate child of {#snippet}, {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>",
55
"start": { "line": 5, "column": 0 },
66
"end": { "line": 5, "column": 18 }
77
}

packages/svelte/tests/validator/samples/const-tag-placement-2/errors.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
33
"code": "invalid-const-placement",
4-
"message": "{@const} must be the immediate child of {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>",
4+
"message": "{@const} must be the immediate child of {#snippet}, {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>",
55
"start": { "line": 7, "column": 4 },
66
"end": { "line": 7, "column": 18 }
77
}

0 commit comments

Comments
 (0)