1
1
import type * as Compiler from "./svelte-ast-types-for-v5.js" ;
2
2
import type * as SvAST from "./svelte-ast-types.js" ;
3
+ import type * as ESTree from "estree" ;
3
4
import type { NormalizedParserOptions } from "./parser-options.js" ;
4
5
import { compilerVersion , svelteVersion } from "./svelte-version.js" ;
5
6
import type { SvelteConfig } from "../svelte-config/index.js" ;
7
+ import { traverseNodes } from "../traverse.js" ;
8
+
9
+ const runeSymbols : string [ ] = [
10
+ "$state" ,
11
+ "$derived" ,
12
+ "$effect" ,
13
+ "$props" ,
14
+ "$bindable" ,
15
+ "$inspect" ,
16
+ "$host" ,
17
+ ] as const ;
6
18
7
19
/** The context for parsing. */
8
20
export type SvelteParseContext = {
@@ -18,55 +30,76 @@ export type SvelteParseContext = {
18
30
svelteConfig : SvelteConfig | null ;
19
31
} ;
20
32
21
- export function isEnableRunes (
22
- svelteConfig : SvelteConfig | null ,
23
- parserOptions : NormalizedParserOptions ,
24
- ) : boolean {
25
- if ( ! svelteVersion . gte ( 5 ) ) return false ;
26
- if ( parserOptions . svelteFeatures ?. runes != null ) {
27
- return Boolean ( parserOptions . svelteFeatures . runes ) ;
28
- }
29
- if ( svelteConfig ?. compilerOptions ?. runes != null ) {
30
- return Boolean ( svelteConfig . compilerOptions . runes ) ;
31
- }
32
- return true ;
33
- }
34
-
35
33
export function resolveSvelteParseContextForSvelte (
36
34
svelteConfig : SvelteConfig | null ,
37
35
parserOptions : NormalizedParserOptions ,
38
36
svelteAst : Compiler . Root | SvAST . AstLegacy ,
39
37
) : SvelteParseContext {
40
- const svelteOptions = ( svelteAst as Compiler . Root ) . options ;
41
- if ( svelteOptions ?. runes != null ) {
42
- return {
43
- runes : svelteOptions . runes ,
44
- compilerVersion,
45
- svelteConfig,
46
- } ;
47
- }
48
-
49
38
return {
50
- runes : isEnableRunes ( svelteConfig , parserOptions ) ,
39
+ runes : isRunes ( svelteConfig , parserOptions , svelteAst ) ,
51
40
compilerVersion,
52
41
svelteConfig,
53
42
} ;
54
43
}
55
44
56
45
export function resolveSvelteParseContextForSvelteScript (
57
46
svelteConfig : SvelteConfig | null ,
58
- parserOptions : NormalizedParserOptions ,
59
- ) : SvelteParseContext {
60
- return resolveSvelteParseContext ( svelteConfig , parserOptions ) ;
61
- }
62
-
63
- function resolveSvelteParseContext (
64
- svelteConfig : SvelteConfig | null ,
65
- parserOptions : NormalizedParserOptions ,
66
47
) : SvelteParseContext {
67
48
return {
68
- runes : isEnableRunes ( svelteConfig , parserOptions ) ,
49
+ // .svelte.js files are always in Runes mode for Svelte 5.
50
+ runes : svelteVersion . gte ( 5 ) ,
69
51
compilerVersion,
70
52
svelteConfig,
71
53
} ;
72
54
}
55
+
56
+ function isRunes (
57
+ svelteConfig : SvelteConfig | null ,
58
+ parserOptions : NormalizedParserOptions ,
59
+ svelteAst : Compiler . Root | SvAST . AstLegacy ,
60
+ ) : boolean {
61
+ // Svelte 3/4 does not support Runes mode.
62
+ if ( ! svelteVersion . gte ( 5 ) ) {
63
+ return false ;
64
+ }
65
+
66
+ // Compiler option.
67
+ if ( parserOptions . svelteFeatures ?. runes != null ) {
68
+ return parserOptions . svelteFeatures ?. runes ;
69
+ }
70
+ if ( svelteConfig ?. compilerOptions ?. runes != null ) {
71
+ return svelteConfig ?. compilerOptions ?. runes ;
72
+ }
73
+
74
+ // `<svelte:options>`.
75
+ const svelteOptions = ( svelteAst as Compiler . Root ) . options ;
76
+ if ( svelteOptions ?. runes != null ) {
77
+ return svelteOptions ?. runes ;
78
+ }
79
+
80
+ // Static analysis.
81
+ const { module, instance } = svelteAst ;
82
+ return (
83
+ ( module != null && hasRuneSymbol ( module ) ) ||
84
+ ( instance != null && hasRuneSymbol ( instance ) )
85
+ ) ;
86
+ }
87
+
88
+ function hasRuneSymbol ( ast : Compiler . Script | SvAST . Script ) : boolean {
89
+ let hasRuneSymbol = false ;
90
+ traverseNodes ( ast as unknown as ESTree . Node , {
91
+ enterNode ( node ) {
92
+ if ( hasRuneSymbol ) {
93
+ return ;
94
+ }
95
+ if ( node . type === "Identifier" && runeSymbols . includes ( node . name ) ) {
96
+ hasRuneSymbol = true ;
97
+ }
98
+ } ,
99
+ leaveNode ( ) {
100
+ // do nothing
101
+ } ,
102
+ } ) ;
103
+
104
+ return hasRuneSymbol ;
105
+ }
0 commit comments