From a85d3eeb1f36afdfedb4d5d400283196982f94a8 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Thu, 3 Apr 2025 16:44:42 +0900 Subject: [PATCH 1/2] fix: crash with `$derived()` in template using ts --- src/parser/typescript/analyze/index.ts | 29 +- ...derived-in-template-with-ts01-input.svelte | 5 + ...$derived-in-template-with-ts01-output.json | 1032 +++++++++++++++++ ...ed-in-template-with-ts01-scope-output.json | 345 ++++++ ...ived-in-template-without-ts01-input.svelte | 5 + ...rived-in-template-without-ts01-output.json | 884 ++++++++++++++ ...in-template-without-ts01-scope-output.json | 345 ++++++ 7 files changed, 2637 insertions(+), 8 deletions(-) create mode 100644 tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-input.svelte create mode 100644 tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-output.json create mode 100644 tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-scope-output.json create mode 100644 tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-input.svelte create mode 100644 tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-output.json create mode 100644 tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-scope-output.json diff --git a/src/parser/typescript/analyze/index.ts b/src/parser/typescript/analyze/index.ts index b6de0a9b..9d784e7a 100644 --- a/src/parser/typescript/analyze/index.ts +++ b/src/parser/typescript/analyze/index.ts @@ -73,15 +73,26 @@ export function analyzeTypeScriptInSvelte( analyzeRuneVariables(result, ctx, context.svelteParseContext); - applyTransforms( - [ - ...analyzeReactiveScopes(result), - ...analyzeDollarDerivedScopes(result, context.svelteParseContext), - ], - ctx, - ); + const scriptTransformers: TransformInfo[] = [ + ...analyzeReactiveScopes(result), + ]; + const templateTransformers: TransformInfo[] = []; + for (const transform of analyzeDollarDerivedScopes( + result, + context.svelteParseContext, + )) { + if (transform.node.range[0] < code.script.length) { + scriptTransformers.push(transform); + } else { + templateTransformers.push(transform); + } + } - analyzeRenderScopes(code, ctx); + applyTransforms(scriptTransformers, ctx); + + analyzeRenderScopes(code, ctx, () => + applyTransforms(templateTransformers, ctx), + ); // When performing type checking on TypeScript code that is not a module, the error `Cannot redeclare block-scoped variable 'xxx'`. occurs. To fix this, add an `export`. // see: https://github.com/sveltejs/svelte-eslint-parser/issues/557 @@ -625,10 +636,12 @@ function* analyzeDollarDerivedScopes( function analyzeRenderScopes( code: { script: string; render: string; rootScope: string }, ctx: VirtualTypeScriptContext, + analyzeInTemplate: () => void, ) { ctx.appendOriginal(code.script.length); const renderFunctionName = ctx.generateUniqueId("render"); ctx.appendVirtualScript(`export function ${renderFunctionName}(){`); + analyzeInTemplate(); ctx.appendOriginal(code.script.length + code.render.length); ctx.appendVirtualScript(`}`); ctx.restoreContext.addRestoreStatementProcess((node, result) => { diff --git a/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-input.svelte b/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-input.svelte new file mode 100644 index 00000000..f2935614 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-input.svelte @@ -0,0 +1,5 @@ + + + $derived(0)} /> diff --git a/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-output.json b/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-output.json new file mode 100644 index 00000000..af4df0a9 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-output.json @@ -0,0 +1,1032 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteScriptElement", + "name": { + "type": "SvelteName", + "name": "script", + "range": [ + 1, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 7 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "lang", + "range": [ + 8, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "ts", + "range": [ + 14, + 16 + ], + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 16 + } + } + } + ], + "range": [ + 8, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 17 + } + } + } + ], + "selfClosing": false, + "range": [ + 0, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + "body": [ + { + "type": "ImportDeclaration", + "importKind": "value", + "source": { + "type": "Literal", + "raw": "'./MyComponent.svelte'", + "value": "./MyComponent.svelte", + "range": [ + 47, + 69 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 50 + } + } + }, + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "local": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + ], + "range": [ + 23, + 70 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 51 + } + } + } + ], + "endTag": { + "type": "SvelteEndTag", + "range": [ + 71, + 80 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + "range": [ + 0, + 80 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "SvelteText", + "value": "\n\n", + "range": [ + 80, + 82 + ], + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 5, + "column": 0 + } + } + }, + { + "type": "SvelteElement", + "kind": "component", + "name": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 83, + 94 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": ":foo", + "range": [ + 95, + 99 + ], + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 17 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteMustacheTag", + "kind": "text", + "expression": { + "type": "ArrowFunctionExpression", + "async": false, + "body": { + "type": "CallExpression", + "arguments": [ + { + "type": "Literal", + "raw": "0", + "value": 0, + "range": [ + 116, + 117 + ], + "loc": { + "start": { + "line": 5, + "column": 34 + }, + "end": { + "line": 5, + "column": 35 + } + } + } + ], + "callee": { + "type": "Identifier", + "name": "$derived", + "range": [ + 107, + 115 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "optional": false, + "range": [ + 107, + 118 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 36 + } + } + }, + "expression": true, + "generator": false, + "id": null, + "params": [], + "range": [ + 101, + 118 + ], + "loc": { + "start": { + "line": 5, + "column": 19 + }, + "end": { + "line": 5, + "column": 36 + } + } + }, + "range": [ + 100, + 119 + ], + "loc": { + "start": { + "line": 5, + "column": 18 + }, + "end": { + "line": 5, + "column": 37 + } + } + } + ], + "range": [ + 95, + 119 + ], + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 37 + } + } + } + ], + "selfClosing": true, + "range": [ + 82, + 122 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 40 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 82, + 122 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 40 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "script", + "range": [ + 1, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 7 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "lang", + "range": [ + 8, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 12, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 13, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 14 + } + } + }, + { + "type": "HTMLText", + "value": "ts", + "range": [ + 14, + 16 + ], + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 16 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 16, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Keyword", + "value": "import", + "range": [ + 23, + 29 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 10 + } + } + }, + { + "type": "Identifier", + "value": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + { + "type": "Identifier", + "value": "from", + "range": [ + 42, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 27 + } + } + }, + { + "type": "String", + "value": "'./MyComponent.svelte'", + "range": [ + 47, + 69 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 50 + } + } + }, + { + "type": "Punctuator", + "value": ";", + "range": [ + 69, + 70 + ], + "loc": { + "start": { + "line": 2, + "column": 50 + }, + "end": { + "line": 2, + "column": 51 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 71, + 72 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 72, + 73 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 2 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "script", + "range": [ + 73, + 79 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 8 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 79, + 80 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "HTMLText", + "value": "\n\n", + "range": [ + 80, + 82 + ], + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 5, + "column": 0 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 82, + 83 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + } + }, + { + "type": "Identifier", + "value": "MyComponent", + "range": [ + 83, + 94 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": ":foo", + "range": [ + 95, + 99 + ], + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 99, + 100 + ], + "loc": { + "start": { + "line": 5, + "column": 17 + }, + "end": { + "line": 5, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 100, + 101 + ], + "loc": { + "start": { + "line": 5, + "column": 18 + }, + "end": { + "line": 5, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 101, + 102 + ], + "loc": { + "start": { + "line": 5, + "column": 19 + }, + "end": { + "line": 5, + "column": 20 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 102, + 103 + ], + "loc": { + "start": { + "line": 5, + "column": 20 + }, + "end": { + "line": 5, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": "=>", + "range": [ + 104, + 106 + ], + "loc": { + "start": { + "line": 5, + "column": 22 + }, + "end": { + "line": 5, + "column": 24 + } + } + }, + { + "type": "Identifier", + "value": "$derived", + "range": [ + 107, + 115 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 115, + 116 + ], + "loc": { + "start": { + "line": 5, + "column": 33 + }, + "end": { + "line": 5, + "column": 34 + } + } + }, + { + "type": "Numeric", + "value": "0", + "range": [ + 116, + 117 + ], + "loc": { + "start": { + "line": 5, + "column": 34 + }, + "end": { + "line": 5, + "column": 35 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 117, + 118 + ], + "loc": { + "start": { + "line": 5, + "column": 35 + }, + "end": { + "line": 5, + "column": 36 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 118, + 119 + ], + "loc": { + "start": { + "line": 5, + "column": 36 + }, + "end": { + "line": 5, + "column": 37 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 120, + 121 + ], + "loc": { + "start": { + "line": 5, + "column": 38 + }, + "end": { + "line": 5, + "column": 39 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 121, + 122 + ], + "loc": { + "start": { + "line": 5, + "column": 39 + }, + "end": { + "line": 5, + "column": 40 + } + } + } + ], + "range": [ + 0, + 123 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-scope-output.json b/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-scope-output.json new file mode 100644 index 00000000..45ae4174 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/$derived-in-template-with-ts01-scope-output.json @@ -0,0 +1,345 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 107, + 115 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [ + { + "name": "MyComponent", + "identifiers": [ + { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + ], + "defs": [ + { + "type": "ImportBinding", + "name": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + "node": { + "type": "ImportDefaultSpecifier", + "local": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + } + ], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 83, + 94 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + "from": "module", + "init": null, + "resolved": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + } + ] + } + ], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 83, + 94 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + "from": "module", + "init": null, + "resolved": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 30, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + } + ], + "childScopes": [ + { + "type": "function", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 107, + 115 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 107, + 115 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 107, + 115 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + } + ], + "through": [] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-input.svelte b/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-input.svelte new file mode 100644 index 00000000..7e006dff --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-input.svelte @@ -0,0 +1,5 @@ + + + $derived(0)} /> diff --git a/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-output.json b/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-output.json new file mode 100644 index 00000000..ddf94b02 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-output.json @@ -0,0 +1,884 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteScriptElement", + "name": { + "type": "SvelteName", + "name": "script", + "range": [ + 1, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 7 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [], + "selfClosing": false, + "range": [ + 0, + 8 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + } + }, + "body": [ + { + "type": "ImportDeclaration", + "source": { + "type": "Literal", + "raw": "'./MyComponent.svelte'", + "value": "./MyComponent.svelte", + "range": [ + 37, + 59 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 50 + } + } + }, + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "local": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + ], + "range": [ + 13, + 60 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 51 + } + } + } + ], + "endTag": { + "type": "SvelteEndTag", + "range": [ + 61, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + "range": [ + 0, + 70 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "SvelteText", + "value": "\n\n", + "range": [ + 70, + 72 + ], + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 5, + "column": 0 + } + } + }, + { + "type": "SvelteElement", + "kind": "component", + "name": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 73, + 84 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": ":foo", + "range": [ + 85, + 89 + ], + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 17 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteMustacheTag", + "kind": "text", + "expression": { + "type": "ArrowFunctionExpression", + "async": false, + "body": { + "type": "CallExpression", + "arguments": [ + { + "type": "Literal", + "raw": "0", + "value": 0, + "range": [ + 106, + 107 + ], + "loc": { + "start": { + "line": 5, + "column": 34 + }, + "end": { + "line": 5, + "column": 35 + } + } + } + ], + "callee": { + "type": "Identifier", + "name": "$derived", + "range": [ + 97, + 105 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "optional": false, + "range": [ + 97, + 108 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 36 + } + } + }, + "expression": true, + "generator": false, + "id": null, + "params": [], + "range": [ + 91, + 108 + ], + "loc": { + "start": { + "line": 5, + "column": 19 + }, + "end": { + "line": 5, + "column": 36 + } + } + }, + "range": [ + 90, + 109 + ], + "loc": { + "start": { + "line": 5, + "column": 18 + }, + "end": { + "line": 5, + "column": 37 + } + } + } + ], + "range": [ + 85, + 109 + ], + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 37 + } + } + } + ], + "selfClosing": true, + "range": [ + 72, + 112 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 40 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 72, + 112 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 40 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "script", + "range": [ + 1, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 7, + 8 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 8 + } + } + }, + { + "type": "Keyword", + "value": "import", + "range": [ + 13, + 19 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 10 + } + } + }, + { + "type": "Identifier", + "value": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + { + "type": "Identifier", + "value": "from", + "range": [ + 32, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 27 + } + } + }, + { + "type": "String", + "value": "'./MyComponent.svelte'", + "range": [ + 37, + 59 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 50 + } + } + }, + { + "type": "Punctuator", + "value": ";", + "range": [ + 59, + 60 + ], + "loc": { + "start": { + "line": 2, + "column": 50 + }, + "end": { + "line": 2, + "column": 51 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 61, + 62 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 62, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 2 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "script", + "range": [ + 63, + 69 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 8 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 69, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "HTMLText", + "value": "\n\n", + "range": [ + 70, + 72 + ], + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 5, + "column": 0 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 72, + 73 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + } + }, + { + "type": "Identifier", + "value": "MyComponent", + "range": [ + 73, + 84 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": ":foo", + "range": [ + 85, + 89 + ], + "loc": { + "start": { + "line": 5, + "column": 13 + }, + "end": { + "line": 5, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 89, + 90 + ], + "loc": { + "start": { + "line": 5, + "column": 17 + }, + "end": { + "line": 5, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 90, + 91 + ], + "loc": { + "start": { + "line": 5, + "column": 18 + }, + "end": { + "line": 5, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 91, + 92 + ], + "loc": { + "start": { + "line": 5, + "column": 19 + }, + "end": { + "line": 5, + "column": 20 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 92, + 93 + ], + "loc": { + "start": { + "line": 5, + "column": 20 + }, + "end": { + "line": 5, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": "=>", + "range": [ + 94, + 96 + ], + "loc": { + "start": { + "line": 5, + "column": 22 + }, + "end": { + "line": 5, + "column": 24 + } + } + }, + { + "type": "Identifier", + "value": "$derived", + "range": [ + 97, + 105 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 105, + 106 + ], + "loc": { + "start": { + "line": 5, + "column": 33 + }, + "end": { + "line": 5, + "column": 34 + } + } + }, + { + "type": "Numeric", + "value": "0", + "range": [ + 106, + 107 + ], + "loc": { + "start": { + "line": 5, + "column": 34 + }, + "end": { + "line": 5, + "column": 35 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 107, + 108 + ], + "loc": { + "start": { + "line": 5, + "column": 35 + }, + "end": { + "line": 5, + "column": 36 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 108, + 109 + ], + "loc": { + "start": { + "line": 5, + "column": 36 + }, + "end": { + "line": 5, + "column": 37 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 110, + 111 + ], + "loc": { + "start": { + "line": 5, + "column": 38 + }, + "end": { + "line": 5, + "column": 39 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 111, + 112 + ], + "loc": { + "start": { + "line": 5, + "column": 39 + }, + "end": { + "line": 5, + "column": 40 + } + } + } + ], + "range": [ + 0, + 113 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-scope-output.json b/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-scope-output.json new file mode 100644 index 00000000..0e14a8ee --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/$derived-in-template-without-ts01-scope-output.json @@ -0,0 +1,345 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 97, + 105 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [ + { + "name": "MyComponent", + "identifiers": [ + { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + ], + "defs": [ + { + "type": "ImportBinding", + "name": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + "node": { + "type": "ImportDefaultSpecifier", + "local": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + } + ], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 73, + 84 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + "from": "module", + "init": null, + "resolved": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + } + ] + } + ], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 73, + 84 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 12 + } + } + }, + "from": "module", + "init": null, + "resolved": { + "type": "Identifier", + "name": "MyComponent", + "range": [ + 20, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + } + ], + "childScopes": [ + { + "type": "function", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 97, + 105 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 97, + 105 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "$derived", + "range": [ + 97, + 105 + ], + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 33 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + } + ], + "through": [] +} \ No newline at end of file From 8d3706b8972a99b46f82cd30a650a149c622f89a Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Thu, 3 Apr 2025 16:45:13 +0900 Subject: [PATCH 2/2] Create gold-planes-retire.md --- .changeset/gold-planes-retire.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/gold-planes-retire.md diff --git a/.changeset/gold-planes-retire.md b/.changeset/gold-planes-retire.md new file mode 100644 index 00000000..1e1207d8 --- /dev/null +++ b/.changeset/gold-planes-retire.md @@ -0,0 +1,5 @@ +--- +"svelte-eslint-parser": patch +--- + +fix: crash with `$derived()` in template using ts