1
- /** @import { Expression, ExpressionStatement, MethodDefinition, Pattern, Program, Property, PropertyDefinition , Statement, VariableDeclarator } from 'estree' */
2
- /** @import { Binding, Namespace, SvelteNode, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
1
+ /** @import { Expression, ExpressionStatement, Program, Property, Statement, VariableDeclarator } from 'estree' */
2
+ /** @import { Namespace, SvelteNode, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
3
3
/** @import { ComponentServerTransformState, ComponentVisitors, ServerTransformState, Visitors } from './types.js' */
4
4
/** @import { Analysis, ComponentAnalysis } from '../../types.js' */
5
5
/** @import { Scope } from '../../scope.js' */
6
6
/** @import { StateField } from '../../3-transform/client/types.js' */ // TODO move this type
7
7
import { walk } from 'zimmerframe' ;
8
- import { set_scope , get_rune } from '../../scope.js' ;
9
- import { extract_identifiers , extract_paths , is_expression_async } from '../../../utils/ast.js' ;
8
+ import { set_scope } from '../../scope.js' ;
9
+ import { extract_identifiers } from '../../../utils/ast.js' ;
10
10
import * as b from '../../../utils/builders.js' ;
11
11
import { filename } from '../../../state.js' ;
12
12
import { render_stylesheet } from '../css/index.js' ;
13
13
import { AssignmentExpression } from './visitors/javascript/AssignmentExpression.js' ;
14
14
import { CallExpression } from './visitors/javascript/CallExpression.js' ;
15
15
import { ClassBodyRunes } from './visitors/javascript/ClassBody.js' ;
16
+ import { ExpressionStatementRunes } from './visitors/javascript/ExpressionStatement.js' ;
16
17
import { Identifier } from './visitors/javascript/Identifier.js' ;
18
+ import { MemberExpressionRunes } from './visitors/javascript/MemberExpression.js' ;
17
19
import { UpdateExpression } from './visitors/javascript/UpdateExpression.js' ;
18
20
import { PropertyDefinitionRunes } from './visitors/javascript/PropertyDefinition.js' ;
21
+ import {
22
+ VariableDeclarationLegacy ,
23
+ VariableDeclarationRunes
24
+ } from './visitors/javascript/VariableDeclaration.js' ;
19
25
import { AwaitBlock } from './visitors/template/AwaitBlock.js' ;
20
26
import { Component } from './visitors/template/Component.js' ;
21
27
import { ConstTag } from './visitors/template/ConstTag.js' ;
@@ -38,28 +44,6 @@ import { SvelteHead } from './visitors/template/SvelteHead.js';
38
44
import { SvelteSelf } from './visitors/template/SvelteSelf.js' ;
39
45
import { TitleElement } from './visitors/template/TitleElement.js' ;
40
46
41
- /**
42
- * @param {VariableDeclarator } declarator
43
- * @param {Scope } scope
44
- * @param {Expression } value
45
- * @returns {VariableDeclarator[] }
46
- */
47
- function create_state_declarators ( declarator , scope , value ) {
48
- if ( declarator . id . type === 'Identifier' ) {
49
- return [ b . declarator ( declarator . id , value ) ] ;
50
- }
51
-
52
- const tmp = scope . generate ( 'tmp' ) ;
53
- const paths = extract_paths ( declarator . id ) ;
54
- return [
55
- b . declarator ( b . id ( tmp ) , value ) , // TODO inject declarator for opts, so we can use it below
56
- ...paths . map ( ( path ) => {
57
- const value = path . expression ?. ( b . id ( tmp ) ) ;
58
- return b . declarator ( path . node , value ) ;
59
- } )
60
- ] ;
61
- }
62
-
63
47
/** @type {Visitors } */
64
48
const global_visitors = {
65
49
AssignmentExpression,
@@ -72,171 +56,14 @@ const global_visitors = {
72
56
const javascript_visitors_runes = {
73
57
ClassBody : ClassBodyRunes ,
74
58
PropertyDefinition : PropertyDefinitionRunes ,
75
- VariableDeclaration ( node , { state, visit } ) {
76
- const declarations = [ ] ;
77
-
78
- for ( const declarator of node . declarations ) {
79
- const init = declarator . init ;
80
- const rune = get_rune ( init , state . scope ) ;
81
- if ( ! rune || rune === '$effect.tracking' || rune === '$inspect' || rune === '$effect.root' ) {
82
- declarations . push ( /** @type {VariableDeclarator } */ ( visit ( declarator ) ) ) ;
83
- continue ;
84
- }
85
-
86
- if ( rune === '$props' ) {
87
- // remove $bindable() from props declaration
88
- const id = walk ( declarator . id , null , {
89
- AssignmentPattern ( node ) {
90
- if (
91
- node . right . type === 'CallExpression' &&
92
- get_rune ( node . right , state . scope ) === '$bindable'
93
- ) {
94
- const right = node . right . arguments . length
95
- ? /** @type {Expression } */ ( visit ( node . right . arguments [ 0 ] ) )
96
- : b . id ( 'undefined' ) ;
97
- return b . assignment_pattern ( node . left , right ) ;
98
- }
99
- }
100
- } ) ;
101
- declarations . push ( b . declarator ( id , b . id ( '$$props' ) ) ) ;
102
- continue ;
103
- }
104
-
105
- const args = /** @type {CallExpression } */ ( init ) . arguments ;
106
- const value =
107
- args . length === 0 ? b . id ( 'undefined' ) : /** @type {Expression } */ ( visit ( args [ 0 ] ) ) ;
108
-
109
- if ( rune === '$derived.by' ) {
110
- declarations . push (
111
- b . declarator ( /** @type {Pattern } */ ( visit ( declarator . id ) ) , b . call ( value ) )
112
- ) ;
113
- continue ;
114
- }
115
-
116
- if ( declarator . id . type === 'Identifier' ) {
117
- declarations . push ( b . declarator ( declarator . id , value ) ) ;
118
- continue ;
119
- }
120
-
121
- if ( rune === '$derived' ) {
122
- declarations . push ( b . declarator ( /** @type {Pattern } */ ( visit ( declarator . id ) ) , value ) ) ;
123
- continue ;
124
- }
125
-
126
- declarations . push ( ...create_state_declarators ( declarator , state . scope , value ) ) ;
127
- }
128
-
129
- return {
130
- ...node ,
131
- declarations
132
- } ;
133
- } ,
134
- ExpressionStatement ( node , context ) {
135
- const expression = node . expression ;
136
- if ( expression . type === 'CallExpression' ) {
137
- const callee = expression . callee ;
138
-
139
- if ( callee . type === 'Identifier' && callee . name === '$effect' ) {
140
- return b . empty ;
141
- }
142
-
143
- if (
144
- callee . type === 'MemberExpression' &&
145
- callee . object . type === 'Identifier' &&
146
- callee . object . name === '$effect'
147
- ) {
148
- return b . empty ;
149
- }
150
- }
151
- context . next ( ) ;
152
- } ,
153
- MemberExpression ( node , context ) {
154
- if ( node . object . type === 'ThisExpression' && node . property . type === 'PrivateIdentifier' ) {
155
- const field = context . state . private_derived . get ( node . property . name ) ;
156
- if ( field ) {
157
- return b . call ( node ) ;
158
- }
159
- }
160
-
161
- context . next ( ) ;
162
- }
59
+ VariableDeclaration : VariableDeclarationRunes ,
60
+ ExpressionStatement : ExpressionStatementRunes ,
61
+ MemberExpression : MemberExpressionRunes
163
62
} ;
164
63
165
64
/** @type {Visitors } */
166
65
const javascript_visitors_legacy = {
167
- VariableDeclaration ( node , { state, visit } ) {
168
- /** @type {VariableDeclarator[] } */
169
- const declarations = [ ] ;
170
-
171
- for ( const declarator of node . declarations ) {
172
- const bindings = /** @type {Binding[] } */ ( state . scope . get_bindings ( declarator ) ) ;
173
- const has_state = bindings . some ( ( binding ) => binding . kind === 'state' ) ;
174
- const has_props = bindings . some ( ( binding ) => binding . kind === 'bindable_prop' ) ;
175
-
176
- if ( ! has_state && ! has_props ) {
177
- declarations . push ( /** @type {VariableDeclarator } */ ( visit ( declarator ) ) ) ;
178
- continue ;
179
- }
180
-
181
- if ( has_props ) {
182
- if ( declarator . id . type !== 'Identifier' ) {
183
- // Turn export let into props. It's really really weird because export let { x: foo, z: [bar]} = ..
184
- // means that foo and bar are the props (i.e. the leafs are the prop names), not x and z.
185
- const tmp = state . scope . generate ( 'tmp' ) ;
186
- const paths = extract_paths ( declarator . id ) ;
187
- declarations . push (
188
- b . declarator (
189
- b . id ( tmp ) ,
190
- /** @type {Expression } */ ( visit ( /** @type {Expression } */ ( declarator . init ) ) )
191
- )
192
- ) ;
193
- for ( const path of paths ) {
194
- const value = path . expression ?. ( b . id ( tmp ) ) ;
195
- const name = /** @type {Identifier } */ ( path . node ) . name ;
196
- const binding = /** @type {Binding } */ ( state . scope . get ( name ) ) ;
197
- const prop = b . member ( b . id ( '$$props' ) , b . literal ( binding . prop_alias ?? name ) , true ) ;
198
- declarations . push (
199
- b . declarator ( path . node , b . call ( '$.value_or_fallback' , prop , b . thunk ( value ) ) )
200
- ) ;
201
- }
202
- continue ;
203
- }
204
-
205
- const binding = /** @type {Binding } */ ( state . scope . get ( declarator . id . name ) ) ;
206
- const prop = b . member (
207
- b . id ( '$$props' ) ,
208
- b . literal ( binding . prop_alias ?? declarator . id . name ) ,
209
- true
210
- ) ;
211
-
212
- /** @type {Expression } */
213
- let init = prop ;
214
- if ( declarator . init ) {
215
- const default_value = /** @type {Expression } */ ( visit ( declarator . init ) ) ;
216
- init = is_expression_async ( default_value )
217
- ? b . await ( b . call ( '$.value_or_fallback_async' , prop , b . thunk ( default_value , true ) ) )
218
- : b . call ( '$.value_or_fallback' , prop , b . thunk ( default_value ) ) ;
219
- }
220
-
221
- declarations . push ( b . declarator ( declarator . id , init ) ) ;
222
-
223
- continue ;
224
- }
225
-
226
- declarations . push (
227
- ...create_state_declarators (
228
- declarator ,
229
- state . scope ,
230
- /** @type {Expression } */ ( declarator . init && visit ( declarator . init ) )
231
- )
232
- ) ;
233
- }
234
-
235
- return {
236
- ...node ,
237
- declarations
238
- } ;
239
- } ,
66
+ VariableDeclaration : VariableDeclarationLegacy ,
240
67
LabeledStatement ( node , context ) {
241
68
if ( context . path . length > 1 ) return ;
242
69
if ( node . label . name !== '$' ) return ;
0 commit comments