diff --git a/.changeset/runes-auto.md b/.changeset/runes-auto.md
new file mode 100644
index 00000000..cc7aedf5
--- /dev/null
+++ b/.changeset/runes-auto.md
@@ -0,0 +1,5 @@
+---
+"svelte-eslint-parser": minor
+---
+
+feat: add explicit `auto` option for rune mode.
diff --git a/README.md b/README.md
index 628930aa..87fb7b52 100644
--- a/README.md
+++ b/README.md
@@ -286,11 +286,7 @@ export default [
svelteFeatures: {
/* -- Experimental Svelte Features -- */
/* It may be changed or removed in minor versions without notice. */
- // This option is for Svelte 5. The default value is `true`.
- // If `false`, ESLint will not recognize rune symbols.
- // If not configured this option, The parser will try to read the option from `compilerOptions.runes` from `svelte.config.js`.
- // If `parserOptions.svelteConfig` is not specified and the file cannot be parsed by static analysis, it will behave as `true`.
- runes: true,
+ runes: "auto", // or `true` or `false`
/* -- Experimental Svelte Features -- */
/* It may be changed or removed in minor versions without notice. */
// Whether to parse the `generics` attribute.
@@ -312,11 +308,7 @@ For example in `.eslintrc.*`:
"svelteFeatures": {
/* -- Experimental Svelte Features -- */
/* It may be changed or removed in minor versions without notice. */
- // This option is for Svelte 5. The default value is `true`.
- // If `false`, ESLint will not recognize rune symbols.
- // If not configured this option, The parser will try to read the option from `compilerOptions.runes` from `svelte.config.js`.
- // If `parserOptions.svelteConfig` is not specified and the file cannot be parsed by static analysis, it will behave as `true`.
- "runes": true,
+ "runes": "auto", // or `true` or `false`
/* -- Experimental Svelte Features -- */
/* It may be changed or removed in minor versions without notice. */
// Whether to parse the `generics` attribute.
@@ -327,6 +319,17 @@ For example in `.eslintrc.*`:
}
```
+#### parserOptions.svelteFeatures.runes
+
+Configures whether ESLint recognizes rune symbols.
+
+- `true` ... The parser recognizes rune symbols, and always passes `parserServices.svelteParseContext.runes` as `true`.
+- `"auto"` ... The parser recognizes rune symbols, and passes `true` to `parserServices.svelteParseContext.runes` if the file contains rune symbols, `false` if it does not.
+- `false` ... The parser does not recognize rune symbols, and always passes `parserServices.svelteParseContext.runes` as `false`.
+
+If not configured this option, The parser will try to read the option from `compilerOptions.runes` from `svelte.config.js`.
+If `parserOptions.svelteConfig` is not specified and the file cannot be analyzed by static analysis, or neither has `compilerOptions.runes`, it will behave as `"auto"`.
+
### Runes support
**_This is an experimental feature. It may be changed or removed in minor versions without notice._**
diff --git a/src/index.ts b/src/index.ts
index 3cb39f11..26f6c0d9 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -13,6 +13,7 @@ export {
export * as meta from "./meta";
export { name } from "./meta";
export type { SvelteConfig } from "./svelte-config";
+export type { PublicSvelteParseContext as SvelteParseContext } from "./parser/svelte-parse-context";
export { AST, ParseError };
diff --git a/src/parser/index.ts b/src/parser/index.ts
index 981f2f4f..118076b2 100644
--- a/src/parser/index.ts
+++ b/src/parser/index.ts
@@ -39,9 +39,10 @@ import type { NormalizedParserOptions } from "./parser-options";
import { isTypeScript, normalizeParserOptions } from "./parser-options";
import { getFragmentFromRoot } from "./compat";
import {
- isEnableRunes,
+ isMaybeEnableRunes,
resolveSvelteParseContextForSvelte,
resolveSvelteParseContextForSvelteScript,
+ type PublicSvelteParseContext,
type SvelteParseContext,
} from "./svelte-parse-context";
import type { SvelteConfig } from "../svelte-config";
@@ -81,12 +82,12 @@ type ParseResult = {
isSvelteScript: false;
getSvelteHtmlAst: () => SvAST.Fragment | Compiler.Fragment;
getStyleContext: () => StyleContext;
- svelteParseContext: SvelteParseContext;
+ svelteParseContext: PublicSvelteParseContext;
}
| {
isSvelte: false;
isSvelteScript: true;
- svelteParseContext: SvelteParseContext;
+ svelteParseContext: PublicSvelteParseContext;
}
);
visitorKeys: { [type: string]: string[] };
@@ -100,7 +101,7 @@ export function parseForESLint(code: string, options?: any): ParseResult {
const parserOptions = normalizeParserOptions(options);
if (
- isEnableRunes(svelteConfig, parserOptions) &&
+ isMaybeEnableRunes(svelteConfig, parserOptions) &&
parserOptions.filePath &&
!parserOptions.filePath.endsWith(".svelte") &&
// If no `filePath` is set in ESLint, "" will be specified.
@@ -152,6 +153,8 @@ function parseAsSvelte(
scripts.attrs,
parserOptions,
);
+ svelteParseContext.analyzeRunesMode(resultScript.scopeManager!);
+
ctx.scriptLet.restore(resultScript);
ctx.tokens.push(...resultScript.ast.tokens);
ctx.comments.push(...resultScript.ast.comments);
@@ -234,7 +237,7 @@ function parseAsSvelte(
},
styleNodeLoc,
styleNodeRange,
- svelteParseContext,
+ svelteParseContext: svelteParseContext.toPublic(),
});
resultScript.visitorKeys = Object.assign({}, KEYS, resultScript.visitorKeys);
@@ -263,7 +266,7 @@ function parseAsScript(
resultScript.services = Object.assign(resultScript.services || {}, {
isSvelte: false,
isSvelteScript: true,
- svelteParseContext,
+ svelteParseContext: svelteParseContext.toPublic(),
});
resultScript.visitorKeys = Object.assign({}, KEYS, resultScript.visitorKeys);
return resultScript as any;
diff --git a/src/parser/parser-options.ts b/src/parser/parser-options.ts
index b8f15d1a..1c3d0a38 100644
--- a/src/parser/parser-options.ts
+++ b/src/parser/parser-options.ts
@@ -21,11 +21,8 @@ export type NormalizedParserOptions = {
};
svelteFeatures?: {
/* -- Experimental Svelte Features -- */
- // This option is for Svelte 5. The default value is `true`.
- // If `false`, ESLint will not recognize rune symbols.
- // If not configured this option, The parser will try to read the option from `compilerOptions.runes` from `svelte.config.js`.
- // If `parserOptions.svelteConfig` is not specified and the file cannot be parsed by static analysis, it will behave as `true`.
- runes?: boolean;
+ // Configures whether ESLint recognizes rune symbols.
+ runes?: boolean | "auto";
// Whether to parse the `generics` attribute.
// See https://github.com/sveltejs/rfcs/pull/38
experimentalGenerics?: boolean;
diff --git a/src/parser/svelte-parse-context.ts b/src/parser/svelte-parse-context.ts
index 71c8c353..23cb547e 100644
--- a/src/parser/svelte-parse-context.ts
+++ b/src/parser/svelte-parse-context.ts
@@ -3,9 +3,11 @@ import type * as SvAST from "./svelte-ast-types";
import type { NormalizedParserOptions } from "./parser-options";
import { compilerVersion, svelteVersion } from "./svelte-version";
import type { SvelteConfig } from "../svelte-config";
+import type { ScopeManager } from "eslint-scope";
+import { globalsForRunes } from "./globals";
/** The context for parsing. */
-export type SvelteParseContext = {
+export type PublicSvelteParseContext = {
/**
* Whether to use Runes mode.
* May be `true` if the user is using Svelte v5.
@@ -18,18 +20,68 @@ export type SvelteParseContext = {
svelteConfig: SvelteConfig | null;
};
-export function isEnableRunes(
+export const enum RunesMode {
+ off,
+ on,
+ auto,
+}
+
+export class SvelteParseContext {
+ private runesMode: RunesMode;
+
+ private readonly svelteConfig: SvelteConfig | null;
+
+ public constructor(runesMode: RunesMode, svelteConfig: SvelteConfig | null) {
+ this.runesMode = runesMode;
+ this.svelteConfig = svelteConfig;
+ }
+
+ public get runes(): boolean {
+ if (this.runesMode === RunesMode.auto)
+ throw new Error("Runes mode is auto");
+ return this.runesMode === RunesMode.on;
+ }
+
+ public analyzeRunesMode(scopeManager: ScopeManager): void {
+ if (this.runesMode !== RunesMode.auto) return;
+ this.runesMode = scopeManager.globalScope.through.some((reference) =>
+ globalsForRunes.includes(reference.identifier.name as never),
+ )
+ ? RunesMode.on
+ : RunesMode.off;
+ }
+
+ /** Convert it into a format provided by the parser service. */
+ public toPublic(): PublicSvelteParseContext {
+ return {
+ runes: this.runes,
+ compilerVersion,
+ svelteConfig: this.svelteConfig,
+ };
+ }
+}
+
+function getRunesMode(
svelteConfig: SvelteConfig | null,
parserOptions: NormalizedParserOptions,
-): boolean {
- if (!svelteVersion.gte(5)) return false;
+): RunesMode {
+ if (!svelteVersion.gte(5)) return RunesMode.off;
if (parserOptions.svelteFeatures?.runes != null) {
- return Boolean(parserOptions.svelteFeatures.runes);
+ if (parserOptions.svelteFeatures.runes === "auto") return RunesMode.auto;
+ return parserOptions.svelteFeatures.runes ? RunesMode.on : RunesMode.off;
}
if (svelteConfig?.compilerOptions?.runes != null) {
- return Boolean(svelteConfig.compilerOptions.runes);
+ return svelteConfig.compilerOptions.runes ? RunesMode.on : RunesMode.off;
}
- return true;
+ return RunesMode.auto;
+}
+
+export function isMaybeEnableRunes(
+ svelteConfig: SvelteConfig | null,
+ parserOptions: NormalizedParserOptions,
+): boolean {
+ const mode = getRunesMode(svelteConfig, parserOptions);
+ return mode === RunesMode.on || mode === RunesMode.auto;
}
export function resolveSvelteParseContextForSvelte(
@@ -39,18 +91,12 @@ export function resolveSvelteParseContextForSvelte(
): SvelteParseContext {
const svelteOptions = (svelteAst as Compiler.Root).options;
if (svelteOptions?.runes != null) {
- return {
- runes: svelteOptions.runes,
- compilerVersion,
+ return new SvelteParseContext(
+ svelteOptions.runes ? RunesMode.on : RunesMode.off,
svelteConfig,
- };
+ );
}
-
- return {
- runes: isEnableRunes(svelteConfig, parserOptions),
- compilerVersion,
- svelteConfig,
- };
+ return resolveSvelteParseContext(svelteConfig, parserOptions);
}
export function resolveSvelteParseContextForSvelteScript(
@@ -64,9 +110,8 @@ function resolveSvelteParseContext(
svelteConfig: SvelteConfig | null,
parserOptions: NormalizedParserOptions,
): SvelteParseContext {
- return {
- runes: isEnableRunes(svelteConfig, parserOptions),
- compilerVersion,
+ return new SvelteParseContext(
+ getRunesMode(svelteConfig, parserOptions),
svelteConfig,
- };
+ );
}
diff --git a/src/parser/typescript/analyze/index.ts b/src/parser/typescript/analyze/index.ts
index 0e1d8bbe..b952c702 100644
--- a/src/parser/typescript/analyze/index.ts
+++ b/src/parser/typescript/analyze/index.ts
@@ -19,7 +19,7 @@ import type { SvelteAttribute, SvelteHTMLElement } from "../../../ast";
import type { NormalizedParserOptions } from "../../parser-options";
import { setParent } from "../set-parent";
import { getGlobalsForSvelte, globalsForRunes } from "../../globals";
-import type { SvelteParseContext } from "../../svelte-parse-context";
+import { type SvelteParseContext } from "../../svelte-parse-context";
export type AnalyzeTypeScriptContext = {
slots: Set;
@@ -56,6 +56,7 @@ export function analyzeTypeScriptInSvelte(
project: null,
},
) as unknown as TSESParseForESLintResult;
+ context.svelteParseContext.analyzeRunesMode(result.scopeManager as never);
ctx._beforeResult = result;
@@ -103,6 +104,7 @@ export function analyzeTypeScript(
// Without typings
project: null,
}) as unknown as TSESParseForESLintResult;
+ svelteParseContext.analyzeRunesMode(result.scopeManager as never);
ctx._beforeResult = result;
diff --git a/tests/fixtures/integrations/snippet-scope/ts-snippet-hoist-scope-setup.ts b/tests/fixtures/integrations/snippet-scope/ts-snippet-hoist-scope-setup.ts
index 6ea0958b..987969b6 100644
--- a/tests/fixtures/integrations/snippet-scope/ts-snippet-hoist-scope-setup.ts
+++ b/tests/fixtures/integrations/snippet-scope/ts-snippet-hoist-scope-setup.ts
@@ -14,7 +14,6 @@ export function getConfig() {
parser: "svelte-eslint-parser",
parserOptions: {
...generateParserOptions(),
- svelteFeatures: { runes: true },
},
rules: {
"@typescript-eslint/no-unused-vars": "error",
diff --git a/tests/fixtures/integrations/type-info-tests/$derived-setup.ts b/tests/fixtures/integrations/type-info-tests/$derived-setup.ts
index d53704e5..3fe79740 100644
--- a/tests/fixtures/integrations/type-info-tests/$derived-setup.ts
+++ b/tests/fixtures/integrations/type-info-tests/$derived-setup.ts
@@ -30,7 +30,6 @@ export function getConfig() {
parser: "svelte-eslint-parser",
parserOptions: {
...generateParserOptions(),
- svelteFeatures: { runes: true },
},
rules: {
"@typescript-eslint/no-unsafe-argument": "error",
diff --git a/tests/fixtures/integrations/type-info-tests/$derived-ts-setup.ts b/tests/fixtures/integrations/type-info-tests/$derived-ts-setup.ts
index d53704e5..3fe79740 100644
--- a/tests/fixtures/integrations/type-info-tests/$derived-ts-setup.ts
+++ b/tests/fixtures/integrations/type-info-tests/$derived-ts-setup.ts
@@ -30,7 +30,6 @@ export function getConfig() {
parser: "svelte-eslint-parser",
parserOptions: {
...generateParserOptions(),
- svelteFeatures: { runes: true },
},
rules: {
"@typescript-eslint/no-unsafe-argument": "error",
diff --git a/tests/fixtures/integrations/type-info-tests/$derived2-setup.ts b/tests/fixtures/integrations/type-info-tests/$derived2-setup.ts
index d53704e5..3fe79740 100644
--- a/tests/fixtures/integrations/type-info-tests/$derived2-setup.ts
+++ b/tests/fixtures/integrations/type-info-tests/$derived2-setup.ts
@@ -30,7 +30,6 @@ export function getConfig() {
parser: "svelte-eslint-parser",
parserOptions: {
...generateParserOptions(),
- svelteFeatures: { runes: true },
},
rules: {
"@typescript-eslint/no-unsafe-argument": "error",
diff --git a/tests/fixtures/integrations/type-info-tests/$derived2-ts-setup.ts b/tests/fixtures/integrations/type-info-tests/$derived2-ts-setup.ts
index b1b1f599..3a7d2c48 100644
--- a/tests/fixtures/integrations/type-info-tests/$derived2-ts-setup.ts
+++ b/tests/fixtures/integrations/type-info-tests/$derived2-ts-setup.ts
@@ -30,7 +30,6 @@ export function getConfig() {
parser: "svelte-eslint-parser",
parserOptions: {
...generateParserOptions(),
- svelteFeatures: { runes: true },
},
rules: {
"@typescript-eslint/no-unsafe-argument": "error",
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-config.json b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-config.json
new file mode 100644
index 00000000..68f794a1
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-config.json
@@ -0,0 +1,5 @@
+{
+ "svelteFeatures": {
+ "runes": "auto"
+ }
+}
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-input.svelte b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-input.svelte
new file mode 100644
index 00000000..60106664
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-input.svelte
@@ -0,0 +1,5 @@
+
+
+{p}
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-output.json b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-output.json
new file mode 100644
index 00000000..0ccd50d3
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-output.json
@@ -0,0 +1,860 @@
+{
+ "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": "VariableDeclaration",
+ "kind": "const",
+ "declarations": [
+ {
+ "type": "VariableDeclarator",
+ "id": {
+ "type": "ObjectPattern",
+ "properties": [
+ {
+ "type": "Property",
+ "kind": "init",
+ "computed": false,
+ "key": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "method": false,
+ "shorthand": true,
+ "value": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "range": [
+ 16,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ "init": {
+ "type": "CallExpression",
+ "arguments": [],
+ "callee": {
+ "type": "Identifier",
+ "name": "$props",
+ "range": [
+ 24,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ "optional": false,
+ "range": [
+ 24,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ },
+ "range": [
+ 16,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ }
+ ],
+ "range": [
+ 10,
+ 33
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 1
+ },
+ "end": {
+ "line": 2,
+ "column": 24
+ }
+ }
+ }
+ ],
+ "endTag": {
+ "type": "SvelteEndTag",
+ "range": [
+ 34,
+ 43
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ "range": [
+ 0,
+ 43
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "SvelteText",
+ "value": "\n\n",
+ "range": [
+ 43,
+ 45
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 0
+ }
+ }
+ },
+ {
+ "type": "SvelteElement",
+ "kind": "html",
+ "name": {
+ "type": "SvelteName",
+ "name": "span",
+ "range": [
+ 46,
+ 50
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 1
+ },
+ "end": {
+ "line": 5,
+ "column": 5
+ }
+ }
+ },
+ "startTag": {
+ "type": "SvelteStartTag",
+ "attributes": [],
+ "selfClosing": false,
+ "range": [
+ 45,
+ 51
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 6
+ }
+ }
+ },
+ "children": [
+ {
+ "type": "SvelteMustacheTag",
+ "kind": "text",
+ "expression": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 52,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ "range": [
+ 51,
+ 54
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 6
+ },
+ "end": {
+ "line": 5,
+ "column": 9
+ }
+ }
+ }
+ ],
+ "endTag": {
+ "type": "SvelteEndTag",
+ "range": [
+ 54,
+ 61
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ },
+ "range": [
+ 45,
+ 61
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ }
+ ],
+ "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": "const",
+ "range": [
+ 10,
+ 15
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 1
+ },
+ "end": {
+ "line": 2,
+ "column": 6
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "{",
+ "range": [
+ 16,
+ 17
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "}",
+ "range": [
+ 20,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 11
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "=",
+ "range": [
+ 22,
+ 23
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 13
+ },
+ "end": {
+ "line": 2,
+ "column": 14
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "$props",
+ "range": [
+ 24,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "(",
+ "range": [
+ 30,
+ 31
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 21
+ },
+ "end": {
+ "line": 2,
+ "column": 22
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ")",
+ "range": [
+ 31,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 22
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ";",
+ "range": [
+ 32,
+ 33
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 23
+ },
+ "end": {
+ "line": 2,
+ "column": 24
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "<",
+ "range": [
+ 34,
+ 35
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 1
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "/",
+ "range": [
+ 35,
+ 36
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 1
+ },
+ "end": {
+ "line": 3,
+ "column": 2
+ }
+ }
+ },
+ {
+ "type": "HTMLIdentifier",
+ "value": "script",
+ "range": [
+ 36,
+ 42
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 2
+ },
+ "end": {
+ "line": 3,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ">",
+ "range": [
+ 42,
+ 43
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 8
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "HTMLText",
+ "value": "\n\n",
+ "range": [
+ 43,
+ 45
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 0
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "<",
+ "range": [
+ 45,
+ 46
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 1
+ }
+ }
+ },
+ {
+ "type": "HTMLIdentifier",
+ "value": "span",
+ "range": [
+ 46,
+ 50
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 1
+ },
+ "end": {
+ "line": 5,
+ "column": 5
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ">",
+ "range": [
+ 50,
+ 51
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 5
+ },
+ "end": {
+ "line": 5,
+ "column": 6
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "{",
+ "range": [
+ 51,
+ 52
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 6
+ },
+ "end": {
+ "line": 5,
+ "column": 7
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "p",
+ "range": [
+ 52,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "}",
+ "range": [
+ 53,
+ 54
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 8
+ },
+ "end": {
+ "line": 5,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "<",
+ "range": [
+ 54,
+ 55
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "/",
+ "range": [
+ 55,
+ 56
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 10
+ },
+ "end": {
+ "line": 5,
+ "column": 11
+ }
+ }
+ },
+ {
+ "type": "HTMLIdentifier",
+ "value": "span",
+ "range": [
+ 56,
+ 60
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 11
+ },
+ "end": {
+ "line": 5,
+ "column": 15
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ">",
+ "range": [
+ 60,
+ 61
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 15
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ }
+ ],
+ "range": [
+ 0,
+ 62
+ ],
+ "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/runes-auto-with-$props-scope-output.json b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-scope-output.json
new file mode 100644
index 00000000..c8c1da71
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-with-$props-scope-output.json
@@ -0,0 +1,487 @@
+{
+ "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": []
+ },
+ {
+ "name": "$effect",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "$props",
+ "identifiers": [],
+ "defs": [],
+ "references": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "$props",
+ "range": [
+ 24,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": null
+ }
+ ]
+ },
+ {
+ "name": "$bindable",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "$inspect",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "$host",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ }
+ ],
+ "references": [],
+ "childScopes": [
+ {
+ "type": "module",
+ "variables": [
+ {
+ "name": "p",
+ "identifiers": [
+ {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "defs": [
+ {
+ "type": "Variable",
+ "name": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "node": {
+ "type": "VariableDeclarator",
+ "id": {
+ "type": "ObjectPattern",
+ "properties": [
+ {
+ "type": "Property",
+ "kind": "init",
+ "computed": false,
+ "key": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "method": false,
+ "shorthand": true,
+ "value": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "range": [
+ 16,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ "init": {
+ "type": "CallExpression",
+ "arguments": [],
+ "callee": {
+ "type": "Identifier",
+ "name": "$props",
+ "range": [
+ 24,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ "optional": false,
+ "range": [
+ 24,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ },
+ "range": [
+ 16,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ }
+ }
+ ],
+ "references": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "from": "module",
+ "init": true,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ },
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 52,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "references": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "from": "module",
+ "init": true,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ },
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "$props",
+ "range": [
+ 24,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": null
+ },
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 52,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ }
+ ],
+ "childScopes": [],
+ "through": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "$props",
+ "range": [
+ 24,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": null
+ }
+ ]
+ }
+ ],
+ "through": []
+}
\ No newline at end of file
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-config.json b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-config.json
new file mode 100644
index 00000000..68f794a1
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-config.json
@@ -0,0 +1,5 @@
+{
+ "svelteFeatures": {
+ "runes": "auto"
+ }
+}
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-input.svelte b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-input.svelte
new file mode 100644
index 00000000..b241ef28
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-input.svelte
@@ -0,0 +1,5 @@
+
+
+{p}
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-no-undef-result.json
new file mode 100644
index 00000000..86654fcb
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-no-undef-result.json
@@ -0,0 +1,8 @@
+[
+ {
+ "ruleId": "no-undef",
+ "code": "props",
+ "line": 2,
+ "column": 16
+ }
+]
\ No newline at end of file
diff --git a/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-output.json b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-output.json
new file mode 100644
index 00000000..9288b716
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-output.json
@@ -0,0 +1,860 @@
+{
+ "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": "VariableDeclaration",
+ "kind": "const",
+ "declarations": [
+ {
+ "type": "VariableDeclarator",
+ "id": {
+ "type": "ObjectPattern",
+ "properties": [
+ {
+ "type": "Property",
+ "kind": "init",
+ "computed": false,
+ "key": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "method": false,
+ "shorthand": true,
+ "value": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "range": [
+ 16,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ "init": {
+ "type": "CallExpression",
+ "arguments": [],
+ "callee": {
+ "type": "Identifier",
+ "name": "props",
+ "range": [
+ 24,
+ 29
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ }
+ },
+ "optional": false,
+ "range": [
+ 24,
+ 31
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 22
+ }
+ }
+ },
+ "range": [
+ 16,
+ 31
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 22
+ }
+ }
+ }
+ ],
+ "range": [
+ 10,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 1
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ }
+ ],
+ "endTag": {
+ "type": "SvelteEndTag",
+ "range": [
+ 33,
+ 42
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ "range": [
+ 0,
+ 42
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "SvelteText",
+ "value": "\n\n",
+ "range": [
+ 42,
+ 44
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 0
+ }
+ }
+ },
+ {
+ "type": "SvelteElement",
+ "kind": "html",
+ "name": {
+ "type": "SvelteName",
+ "name": "span",
+ "range": [
+ 45,
+ 49
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 1
+ },
+ "end": {
+ "line": 5,
+ "column": 5
+ }
+ }
+ },
+ "startTag": {
+ "type": "SvelteStartTag",
+ "attributes": [],
+ "selfClosing": false,
+ "range": [
+ 44,
+ 50
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 6
+ }
+ }
+ },
+ "children": [
+ {
+ "type": "SvelteMustacheTag",
+ "kind": "text",
+ "expression": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 51,
+ 52
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ "range": [
+ 50,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 6
+ },
+ "end": {
+ "line": 5,
+ "column": 9
+ }
+ }
+ }
+ ],
+ "endTag": {
+ "type": "SvelteEndTag",
+ "range": [
+ 53,
+ 60
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ },
+ "range": [
+ 44,
+ 60
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ }
+ ],
+ "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": "const",
+ "range": [
+ 10,
+ 15
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 1
+ },
+ "end": {
+ "line": 2,
+ "column": 6
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "{",
+ "range": [
+ 16,
+ 17
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "}",
+ "range": [
+ 20,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 11
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "=",
+ "range": [
+ 22,
+ 23
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 13
+ },
+ "end": {
+ "line": 2,
+ "column": 14
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "props",
+ "range": [
+ 24,
+ 29
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "(",
+ "range": [
+ 29,
+ 30
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 20
+ },
+ "end": {
+ "line": 2,
+ "column": 21
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ")",
+ "range": [
+ 30,
+ 31
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 21
+ },
+ "end": {
+ "line": 2,
+ "column": 22
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ";",
+ "range": [
+ 31,
+ 32
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 22
+ },
+ "end": {
+ "line": 2,
+ "column": 23
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "<",
+ "range": [
+ 33,
+ 34
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 0
+ },
+ "end": {
+ "line": 3,
+ "column": 1
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "/",
+ "range": [
+ 34,
+ 35
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 1
+ },
+ "end": {
+ "line": 3,
+ "column": 2
+ }
+ }
+ },
+ {
+ "type": "HTMLIdentifier",
+ "value": "script",
+ "range": [
+ 35,
+ 41
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 2
+ },
+ "end": {
+ "line": 3,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ">",
+ "range": [
+ 41,
+ 42
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 8
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "HTMLText",
+ "value": "\n\n",
+ "range": [
+ 42,
+ 44
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 0
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "<",
+ "range": [
+ 44,
+ 45
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 1
+ }
+ }
+ },
+ {
+ "type": "HTMLIdentifier",
+ "value": "span",
+ "range": [
+ 45,
+ 49
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 1
+ },
+ "end": {
+ "line": 5,
+ "column": 5
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ">",
+ "range": [
+ 49,
+ 50
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 5
+ },
+ "end": {
+ "line": 5,
+ "column": 6
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "{",
+ "range": [
+ 50,
+ 51
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 6
+ },
+ "end": {
+ "line": 5,
+ "column": 7
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "p",
+ "range": [
+ 51,
+ 52
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "}",
+ "range": [
+ 52,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 8
+ },
+ "end": {
+ "line": 5,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "<",
+ "range": [
+ 53,
+ 54
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "/",
+ "range": [
+ 54,
+ 55
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 10
+ },
+ "end": {
+ "line": 5,
+ "column": 11
+ }
+ }
+ },
+ {
+ "type": "HTMLIdentifier",
+ "value": "span",
+ "range": [
+ 55,
+ 59
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 11
+ },
+ "end": {
+ "line": 5,
+ "column": 15
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ">",
+ "range": [
+ 59,
+ 60
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 15
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ }
+ ],
+ "range": [
+ 0,
+ 61
+ ],
+ "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/runes-auto-without-runes-scope-output.json b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-scope-output.json
new file mode 100644
index 00000000..5414af01
--- /dev/null
+++ b/tests/fixtures/parser/ast/svelte5/runes-auto-without-runes-scope-output.json
@@ -0,0 +1,445 @@
+{
+ "type": "global",
+ "variables": [
+ {
+ "name": "$$slots",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "$$props",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ },
+ {
+ "name": "$$restProps",
+ "identifiers": [],
+ "defs": [],
+ "references": []
+ }
+ ],
+ "references": [],
+ "childScopes": [
+ {
+ "type": "module",
+ "variables": [
+ {
+ "name": "p",
+ "identifiers": [
+ {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "defs": [
+ {
+ "type": "Variable",
+ "name": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "node": {
+ "type": "VariableDeclarator",
+ "id": {
+ "type": "ObjectPattern",
+ "properties": [
+ {
+ "type": "Property",
+ "kind": "init",
+ "computed": false,
+ "key": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "method": false,
+ "shorthand": true,
+ "value": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "range": [
+ 16,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ "init": {
+ "type": "CallExpression",
+ "arguments": [],
+ "callee": {
+ "type": "Identifier",
+ "name": "props",
+ "range": [
+ 24,
+ 29
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ }
+ },
+ "optional": false,
+ "range": [
+ 24,
+ 31
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 22
+ }
+ }
+ },
+ "range": [
+ 16,
+ 31
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 7
+ },
+ "end": {
+ "line": 2,
+ "column": 22
+ }
+ }
+ }
+ }
+ ],
+ "references": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "from": "module",
+ "init": true,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ },
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 51,
+ 52
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "references": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "from": "module",
+ "init": true,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ },
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "props",
+ "range": [
+ 24,
+ 29
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": null
+ },
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 51,
+ 52
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 7
+ },
+ "end": {
+ "line": 5,
+ "column": 8
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": {
+ "type": "Identifier",
+ "name": "p",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ }
+ }
+ ],
+ "childScopes": [],
+ "through": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "props",
+ "range": [
+ 24,
+ 29
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": null
+ }
+ ]
+ }
+ ],
+ "through": [
+ {
+ "identifier": {
+ "type": "Identifier",
+ "name": "props",
+ "range": [
+ 24,
+ 29
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 20
+ }
+ }
+ },
+ "from": "module",
+ "init": null,
+ "resolved": null
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/src/parser/typescript/index.ts b/tests/src/parser/typescript/index.ts
index 49051278..48c3a851 100644
--- a/tests/src/parser/typescript/index.ts
+++ b/tests/src/parser/typescript/index.ts
@@ -1,7 +1,10 @@
import { Context } from "../../../../src/context";
import type { NormalizedParserOptions } from "../../../../src/parser/parser-options";
import { parseScriptInSvelte } from "../../../../src/parser/script";
-import { compilerVersion } from "../../../../src/parser/svelte-version";
+import {
+ SvelteParseContext,
+ RunesMode,
+} from "../../../../src/parser/svelte-parse-context";
import { parseTemplate } from "../../../../src/parser/template";
import { parseTypeScriptInSvelte } from "../../../../src/parser/typescript";
import { generateParserOptions, listupFixtures } from "../test-utils";
@@ -50,11 +53,7 @@ describe("Check for typescript analyze result.", () => {
parserOptions,
{
slots: new Set(),
- svelteParseContext: {
- runes: true,
- compilerVersion,
- svelteConfig: null,
- },
+ svelteParseContext: new SvelteParseContext(RunesMode.auto, null),
},
);
const result = parseScriptInSvelte(