Skip to content

Commit 5e30745

Browse files
committed
support type for const tag
1 parent d83bd7f commit 5e30745

File tree

7 files changed

+69
-6
lines changed

7 files changed

+69
-6
lines changed

.changeset/seven-ravens-check.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': minor
3+
---
4+
5+
feat: support type definition in {@const}

packages/svelte/src/compiler/phases/1-parse/state/tag.js

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import read_context from '../read/context.js';
22
import read_expression from '../read/expression.js';
33
import { error } from '../../../errors.js';
44
import { create_fragment } from '../utils/create.js';
5-
import { parse_expression_at } from '../acorn.js';
65
import { walk } from 'zimmerframe';
6+
import { parse } from '../acorn.js';
77

88
const regex_whitespace_with_closing_curly_brace = /^\s*}/;
99

@@ -532,21 +532,55 @@ function special(parser) {
532532
// {@const a = b}
533533
parser.require_whitespace();
534534

535-
const expression = read_expression(parser);
535+
const CONST_LENGTH = 'const '.length;
536+
parser.index = parser.index - CONST_LENGTH;
537+
538+
let end_index = parser.index;
539+
/** @type {import('estree').VariableDeclaration | undefined} */
540+
let declaration = undefined;
536541

537-
if (!(expression.type === 'AssignmentExpression' && expression.operator === '=')) {
542+
const dummy_spaces = parser.template.substring(0, parser.index).replace(/[^\n]/g, ' ');
543+
while (true) {
544+
end_index = parser.template.indexOf('}', end_index + 1);
545+
if (end_index === -1) break;
546+
try {
547+
const node = parse(
548+
dummy_spaces + parser.template.substring(parser.index, end_index),
549+
parser.ts
550+
).body[0];
551+
if (node?.type === 'VariableDeclaration') {
552+
declaration = node;
553+
break;
554+
}
555+
} catch (e) {
556+
continue;
557+
}
558+
}
559+
560+
if (
561+
declaration === undefined ||
562+
declaration.declarations.length !== 1 ||
563+
declaration.declarations[0].init === undefined
564+
) {
538565
error(start, 'invalid-const');
539566
}
540567

541-
parser.allow_whitespace();
568+
parser.index = end_index;
542569
parser.eat('}', true);
543570

544571
parser.append(
545572
/** @type {import('#compiler').ConstTag} */ ({
546573
type: 'ConstTag',
547574
start,
548575
end: parser.index,
549-
expression
576+
expression: {
577+
type: 'AssignmentExpression',
578+
start: (declaration.start ?? 0) + CONST_LENGTH,
579+
end: declaration.end ?? 0,
580+
operator: '=',
581+
left: declaration.declarations[0].id,
582+
right: declaration.declarations[0].init
583+
}
550584
})
551585
);
552586
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import type {
1111
Node,
1212
ObjectExpression,
1313
Pattern,
14-
Program
14+
Program,
15+
VariableDeclaration
1516
} from 'estree';
1617

1718
export interface BaseNode {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: '<p>10 * 10 = 100</p><p>20 * 20 = 400</p>'
5+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script lang="ts">
2+
const boxes = [ { width: 10, height: 10 }, { width: 20, height: 20 } ];
3+
</script>
4+
5+
{#each boxes as box}
6+
{@const area: number = box.width * box.height}
7+
<p>{box.width} * {box.height} = {area}</p>
8+
{/each}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: '<p>{}</p>'
5+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script lang="ts">
2+
</script>
3+
4+
{@const name: string = "{}"}
5+
<p>{name}</p>

0 commit comments

Comments
 (0)