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
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