From 5e307451ddf38b48bd1319e0c390d1eb8701793c Mon Sep 17 00:00:00 2001 From: baseballyama Date: Thu, 23 Nov 2023 16:09:36 +0900 Subject: [PATCH] support type for const tag --- .changeset/seven-ravens-check.md | 5 +++ .../src/compiler/phases/1-parse/state/tag.js | 44 ++++++++++++++++--- .../svelte/src/compiler/types/template.d.ts | 3 +- .../samples/typescript-const1/_config.js | 5 +++ .../samples/typescript-const1/main.svelte | 8 ++++ .../samples/typescript-const2/_config.js | 5 +++ .../samples/typescript-const2/main.svelte | 5 +++ 7 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 .changeset/seven-ravens-check.md create mode 100644 packages/svelte/tests/runtime-runes/samples/typescript-const1/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/typescript-const1/main.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/typescript-const2/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/typescript-const2/main.svelte diff --git a/.changeset/seven-ravens-check.md b/.changeset/seven-ravens-check.md new file mode 100644 index 0000000000..26063b2313 --- /dev/null +++ b/.changeset/seven-ravens-check.md @@ -0,0 +1,5 @@ +--- +'svelte': minor +--- + +feat: support type definition in {@const} diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index 2ad20d9cf1..f9df97a3c1 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -2,8 +2,8 @@ import read_context from '../read/context.js'; import read_expression from '../read/expression.js'; import { error } from '../../../errors.js'; import { create_fragment } from '../utils/create.js'; -import { parse_expression_at } from '../acorn.js'; import { walk } from 'zimmerframe'; +import { parse } from '../acorn.js'; const regex_whitespace_with_closing_curly_brace = /^\s*}/; @@ -532,13 +532,40 @@ function special(parser) { // {@const a = b} parser.require_whitespace(); - const expression = read_expression(parser); + const CONST_LENGTH = 'const '.length; + parser.index = parser.index - CONST_LENGTH; + + let end_index = parser.index; + /** @type {import('estree').VariableDeclaration | undefined} */ + let declaration = undefined; - if (!(expression.type === 'AssignmentExpression' && expression.operator === '=')) { + const dummy_spaces = parser.template.substring(0, parser.index).replace(/[^\n]/g, ' '); + while (true) { + end_index = parser.template.indexOf('}', end_index + 1); + if (end_index === -1) break; + try { + const node = parse( + dummy_spaces + parser.template.substring(parser.index, end_index), + parser.ts + ).body[0]; + if (node?.type === 'VariableDeclaration') { + declaration = node; + break; + } + } catch (e) { + continue; + } + } + + if ( + declaration === undefined || + declaration.declarations.length !== 1 || + declaration.declarations[0].init === undefined + ) { error(start, 'invalid-const'); } - parser.allow_whitespace(); + parser.index = end_index; parser.eat('}', true); parser.append( @@ -546,7 +573,14 @@ function special(parser) { type: 'ConstTag', start, end: parser.index, - expression + expression: { + type: 'AssignmentExpression', + start: (declaration.start ?? 0) + CONST_LENGTH, + end: declaration.end ?? 0, + operator: '=', + left: declaration.declarations[0].id, + right: declaration.declarations[0].init + } }) ); } diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index b69173e6b5..98c51b6ad0 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -11,7 +11,8 @@ import type { Node, ObjectExpression, Pattern, - Program + Program, + VariableDeclaration } from 'estree'; export interface BaseNode { diff --git a/packages/svelte/tests/runtime-runes/samples/typescript-const1/_config.js b/packages/svelte/tests/runtime-runes/samples/typescript-const1/_config.js new file mode 100644 index 0000000000..644f802ac6 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/typescript-const1/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +export default test({ + html: '

10 * 10 = 100

20 * 20 = 400

' +}); diff --git a/packages/svelte/tests/runtime-runes/samples/typescript-const1/main.svelte b/packages/svelte/tests/runtime-runes/samples/typescript-const1/main.svelte new file mode 100644 index 0000000000..1ec792c4ec --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/typescript-const1/main.svelte @@ -0,0 +1,8 @@ + + +{#each boxes as box} + {@const area: number = box.width * box.height} +

{box.width} * {box.height} = {area}

+{/each} diff --git a/packages/svelte/tests/runtime-runes/samples/typescript-const2/_config.js b/packages/svelte/tests/runtime-runes/samples/typescript-const2/_config.js new file mode 100644 index 0000000000..646f2812a2 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/typescript-const2/_config.js @@ -0,0 +1,5 @@ +import { test } from '../../test'; + +export default test({ + html: '

{}

' +}); diff --git a/packages/svelte/tests/runtime-runes/samples/typescript-const2/main.svelte b/packages/svelte/tests/runtime-runes/samples/typescript-const2/main.svelte new file mode 100644 index 0000000000..f1096908f8 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/typescript-const2/main.svelte @@ -0,0 +1,5 @@ + + +{@const name: string = "{}"} +

{name}