@@ -90,30 +90,65 @@ export function analyzeReactiveScope(scopeManager: ScopeManager): void {
9090 * Analyze store scope. e.g. $count
9191 */
9292export function analyzeStoreScope ( scopeManager : ScopeManager ) : void {
93+ const moduleScope = scopeManager . scopes . find (
94+ ( scope ) => scope . type === "module" ,
95+ )
96+ if ( ! moduleScope ) {
97+ return
98+ }
99+ const toBeMarkAsUsedReferences : Reference [ ] = [ ]
100+
93101 for ( const reference of [ ...scopeManager . globalScope . through ] ) {
94102 if ( reference . identifier . name . startsWith ( "$" ) ) {
95103 const realName = reference . identifier . name . slice ( 1 )
96- const moduleScope = scopeManager . scopes . find (
97- ( scope ) => scope . type === "module" ,
98- )
99- if ( moduleScope ) {
100- const variable = moduleScope ?. set . get ( realName )
101- if ( variable ) {
102- // It does not write directly to the original variable.
103- // Therefore, this variable is always a reference.
104- reference . isWrite = ( ) => false
105- reference . isWriteOnly = ( ) => false
106- reference . isReadWrite = ( ) => false
107- reference . isReadOnly = ( ) => true
108- reference . isRead = ( ) => true
109-
110- variable . references . push ( reference )
111- reference . resolved = variable
112- removeReferenceFromThrough ( reference , moduleScope )
104+ const variable = moduleScope . set . get ( realName )
105+ if ( variable ) {
106+ if ( reference . isWriteOnly ( ) ) {
107+ // Need mark as used
108+ toBeMarkAsUsedReferences . push ( reference )
113109 }
110+
111+ // It does not write directly to the original variable.
112+ // Therefore, this variable is always a reference.
113+ reference . isWrite = ( ) => false
114+ reference . isWriteOnly = ( ) => false
115+ reference . isReadWrite = ( ) => false
116+ reference . isReadOnly = ( ) => true
117+ reference . isRead = ( ) => true
118+
119+ variable . references . push ( reference )
120+ reference . resolved = variable
121+ removeReferenceFromThrough ( reference , moduleScope )
114122 }
115123 }
116124 }
125+
126+ for ( const variable of new Set (
127+ toBeMarkAsUsedReferences . map ( ( ref ) => ref . resolved ! ) ,
128+ ) ) {
129+ if (
130+ variable . references . some (
131+ ( ref ) =>
132+ ! toBeMarkAsUsedReferences . includes ( ref ) &&
133+ ref . identifier !== variable . identifiers [ 0 ] ,
134+ )
135+ ) {
136+ // It is already used.
137+ continue
138+ }
139+
140+ // Add the virtual reference for reading.
141+ ; (
142+ addVirtualReference (
143+ variable . identifiers [ 0 ] ,
144+ variable ,
145+ moduleScope ,
146+ {
147+ read : true ,
148+ } ,
149+ ) as any
150+ ) . svelteMarkAsUsed = true
151+ }
117152}
118153
119154/** Transform props exports */
@@ -163,27 +198,25 @@ export function analyzePropsScope(
163198 }
164199
165200 // Add the virtual reference for writing.
166- const reference = new Reference ( )
167- ; ( reference as any ) . sveltePropReference = true
168- reference . from = scope
169- reference . identifier = {
170- ... node ,
171- // @ts -expect-error -- ignore
172- parent : body ,
173- loc : {
174- start : { ... node . loc ! . start } ,
175- end : { ...node . loc ! . end } ,
201+ const reference = addVirtualReference (
202+ {
203+ ... node ,
204+ // @ts -expect-error -- ignore
205+ parent : body ,
206+ loc : {
207+ start : { ... node . loc ! . start } ,
208+ end : { ... node . loc ! . end } ,
209+ } ,
210+ range : [ ...node . range ! ] ,
176211 } ,
177- range : [ ...node . range ! ] ,
178- }
179- reference . isWrite = ( ) => true
180- reference . isWriteOnly = ( ) => false
181- reference . isRead = ( ) => true
182- reference . isReadOnly = ( ) => false
183- reference . isReadWrite = ( ) => true
184-
185- variable . references . push ( reference )
186- reference . resolved = variable
212+ variable ,
213+ scope ,
214+ {
215+ write : true ,
216+ read : true ,
217+ } ,
218+ )
219+ ; ( reference as any ) . sveltePropReference = true
187220 }
188221 }
189222}
@@ -210,6 +243,31 @@ function removeReferenceFromThrough(reference: Reference, baseScope: Scope) {
210243 }
211244}
212245
246+ /**
247+ * Add the virtual reference.
248+ */
249+ function addVirtualReference (
250+ node : ESTree . Identifier ,
251+ variable : Variable ,
252+ scope : Scope ,
253+ readWrite : { read ?: boolean ; write ?: boolean } ,
254+ ) {
255+ const reference = new Reference ( )
256+ ; ( reference as any ) . svelteVirtualReference = true
257+ reference . from = scope
258+ reference . identifier = node
259+ reference . isWrite = ( ) => Boolean ( readWrite . write )
260+ reference . isWriteOnly = ( ) => Boolean ( readWrite . write ) && ! readWrite . read
261+ reference . isRead = ( ) => Boolean ( readWrite . read )
262+ reference . isReadOnly = ( ) => Boolean ( readWrite . read ) && ! readWrite . write
263+ reference . isReadWrite = ( ) => Boolean ( readWrite . read && readWrite . write )
264+
265+ variable . references . push ( reference )
266+ reference . resolved = variable
267+
268+ return reference
269+ }
270+
213271/** Get parent node */
214272function getParent ( node : ESTree . Node ) : ESTree . Node | null {
215273 return ( node as any ) . parent
0 commit comments