1
1
import MagicString from 'magic-string' ;
2
2
import { Node } from 'estree-walker' ;
3
- import ts from 'typescript' ;
3
+ import ts , { VariableDeclaration } from 'typescript' ;
4
4
import { getBinaryAssignmentExpr , isNotPropertyNameOfImport , moveNode } from './utils/tsAst' ;
5
5
import { ExportedNames , is$$PropsDeclaration } from './nodes/ExportedNames' ;
6
6
import { ImplicitTopLevelNames } from './nodes/ImplicitTopLevelNames' ;
@@ -32,6 +32,7 @@ interface PendingStoreResolution {
32
32
node : ts . Identifier ;
33
33
parent : ts . Node ;
34
34
scope : Scope ;
35
+ isPropsId : boolean ;
35
36
}
36
37
37
38
export function processInstanceScriptContent (
@@ -82,13 +83,19 @@ export function processInstanceScriptContent(
82
83
//track if we are in a declaration scope
83
84
let isDeclaration = false ;
84
85
86
+ //track the variable declaration node
87
+ let variableDeclarationNode : VariableDeclaration | null = null ;
88
+
85
89
//track $store variables since we are only supposed to give top level scopes special treatment, and users can declare $blah variables at higher scopes
86
90
//which prevents us just changing all instances of Identity that start with $
87
- const pendingStoreResolutions : PendingStoreResolution [ ] = [ ] ;
91
+ let pendingStoreResolutions : PendingStoreResolution [ ] = [ ] ;
88
92
89
93
let scope = new Scope ( ) ;
90
94
const rootScope = scope ;
91
95
96
+ //track is the variable declared as `props` comes from `$props()`
97
+ let isPropsDeclarationRune = false ;
98
+
92
99
const pushScope = ( ) => ( scope = new Scope ( scope ) ) ;
93
100
const popScope = ( ) => ( scope = scope . parent ) ;
94
101
@@ -124,6 +131,17 @@ export function processInstanceScriptContent(
124
131
return ;
125
132
}
126
133
134
+ //if we are in a variable declaration and the identifier is `props` we check the initializer
135
+ if (
136
+ ident . text === 'props' &&
137
+ variableDeclarationNode &&
138
+ variableDeclarationNode . initializer &&
139
+ ts . isCallExpression ( variableDeclarationNode . initializer ) &&
140
+ variableDeclarationNode . initializer . getText ( ) === '$props()'
141
+ ) {
142
+ isPropsDeclarationRune = true ;
143
+ }
144
+
127
145
if ( isDeclaration || ts . isParameter ( parent ) ) {
128
146
if (
129
147
isNotPropertyNameOfImport ( ident ) &&
@@ -148,14 +166,25 @@ export function processInstanceScriptContent(
148
166
! ts . isTypeAliasDeclaration ( parent ) &&
149
167
! ts . isInterfaceDeclaration ( parent )
150
168
) {
169
+ let isPropsId = false ;
170
+ if (
171
+ text === '$props' &&
172
+ ts . isPropertyAccessExpression ( parent ) &&
173
+ parent . parent &&
174
+ ts . isCallExpression ( parent . parent ) &&
175
+ parent . parent . arguments . length === 0
176
+ ) {
177
+ const text = parent . getText ( ) ;
178
+ isPropsId = text === '$props.id' ;
179
+ }
151
180
// Handle the const { ...props } = $props() case
152
181
const is_rune =
153
182
( text === '$props' || text === '$derived' || text === '$state' ) &&
154
183
ts . isCallExpression ( parent ) &&
155
184
ts . isVariableDeclaration ( parent . parent ) &&
156
185
parent . parent . name . getText ( ) . includes ( text . slice ( 1 ) ) ;
157
186
if ( ! is_rune ) {
158
- pendingStoreResolutions . push ( { node : ident , parent, scope } ) ;
187
+ pendingStoreResolutions . push ( { node : ident , parent, scope, isPropsId } ) ;
159
188
}
160
189
}
161
190
}
@@ -234,7 +263,11 @@ export function processInstanceScriptContent(
234
263
235
264
if ( ts . isVariableDeclaration ( parent ) && parent . name == node ) {
236
265
isDeclaration = true ;
237
- onLeaveCallbacks . push ( ( ) => ( isDeclaration = false ) ) ;
266
+ variableDeclarationNode = parent ;
267
+ onLeaveCallbacks . push ( ( ) => {
268
+ isDeclaration = false ;
269
+ variableDeclarationNode = null ;
270
+ } ) ;
238
271
}
239
272
240
273
if ( ts . isBindingElement ( parent ) && parent . name == node ) {
@@ -295,6 +328,10 @@ export function processInstanceScriptContent(
295
328
tsAst . forEachChild ( ( n ) => walk ( n , tsAst ) ) ;
296
329
297
330
//resolve stores
331
+ if ( isPropsDeclarationRune ) {
332
+ //we filter out every pendingStore resolution that `isPropsId` if the variable names `props` comes from `$props()`
333
+ pendingStoreResolutions = pendingStoreResolutions . filter ( ( { isPropsId } ) => ! isPropsId ) ;
334
+ }
298
335
pendingStoreResolutions . map ( resolveStore ) ;
299
336
300
337
// declare implicit reactive variables we found in the script
0 commit comments