1
+ use std:: sync:: Arc ;
2
+
1
3
use cow_utils:: CowUtils ;
4
+
2
5
use oxc_allocator:: Allocator ;
3
- use oxc_ast:: { ast:: * , visit :: walk_mut , AstBuilder , VisitMut } ;
6
+ use oxc_ast:: { ast:: * , AstBuilder } ;
4
7
use oxc_semantic:: { ScopeTree , SymbolTable } ;
5
8
use oxc_span:: { CompactStr , SPAN } ;
6
- use std :: sync :: Arc ;
9
+ use oxc_traverse :: { traverse_mut , Traverse , TraverseCtx } ;
7
10
8
11
use super :: replace_global_defines:: { DotDefine , ReplaceGlobalDefines } ;
9
12
@@ -100,12 +103,18 @@ impl<'a> From<&InjectImport> for DotDefineState<'a> {
100
103
}
101
104
}
102
105
106
+ #[ must_use]
107
+ pub struct InjectGlobalVariablesReturn {
108
+ pub symbols : SymbolTable ,
109
+ pub scopes : ScopeTree ,
110
+ }
111
+
103
112
/// Injects import statements for global variables.
104
113
///
105
114
/// References:
106
115
///
107
116
/// * <https://www.npmjs.com/package/@rollup/plugin-inject>
108
- pub struct InjectGlobalVariables < ' a , ' b > {
117
+ pub struct InjectGlobalVariables < ' a > {
109
118
ast : AstBuilder < ' a > ,
110
119
config : InjectGlobalVariablesConfig ,
111
120
@@ -116,36 +125,32 @@ pub struct InjectGlobalVariables<'a, 'b> {
116
125
/// Identifiers for which dot define replaced a member expression.
117
126
replaced_dot_defines :
118
127
Vec < ( /* identifier of member expression */ CompactStr , /* local */ CompactStr ) > ,
119
-
120
- symbols : & ' b mut SymbolTable , // will be used to keep symbols in sync
121
- scopes : & ' b mut ScopeTree ,
122
128
}
123
129
124
- impl < ' a , ' b > VisitMut < ' a > for InjectGlobalVariables < ' a , ' b > {
125
- fn visit_expression ( & mut self , expr : & mut Expression < ' a > ) {
126
- self . replace_dot_defines ( expr) ;
127
- walk_mut:: walk_expression ( self , expr) ;
130
+ impl < ' a > Traverse < ' a > for InjectGlobalVariables < ' a > {
131
+ fn enter_expression ( & mut self , expr : & mut Expression < ' a > , ctx : & mut TraverseCtx < ' a > ) {
132
+ self . replace_dot_defines ( expr, ctx) ;
128
133
}
129
134
}
130
135
131
- impl < ' a , ' b > InjectGlobalVariables < ' a , ' b > {
132
- pub fn new (
133
- allocator : & ' a Allocator ,
134
- symbols : & ' b mut SymbolTable ,
135
- scopes : & ' b mut ScopeTree ,
136
- config : InjectGlobalVariablesConfig ,
137
- ) -> Self {
136
+ impl < ' a > InjectGlobalVariables < ' a > {
137
+ pub fn new ( allocator : & ' a Allocator , config : InjectGlobalVariablesConfig ) -> Self {
138
138
Self {
139
139
ast : AstBuilder :: new ( allocator) ,
140
140
config,
141
141
dot_defines : vec ! [ ] ,
142
142
replaced_dot_defines : vec ! [ ] ,
143
- symbols,
144
- scopes,
145
143
}
146
144
}
147
145
148
- pub fn build ( & mut self , program : & mut Program < ' a > ) {
146
+ pub fn build (
147
+ & mut self ,
148
+ symbols : SymbolTable ,
149
+ scopes : ScopeTree ,
150
+ program : & mut Program < ' a > ,
151
+ ) -> InjectGlobalVariablesReturn {
152
+ let mut symbols = symbols;
153
+ let mut scopes = scopes;
149
154
// Step 1: slow path where visiting the AST is required to replace dot defines.
150
155
let dot_defines = self
151
156
. config
@@ -157,7 +162,7 @@ impl<'a, 'b> InjectGlobalVariables<'a, 'b> {
157
162
158
163
if !dot_defines. is_empty ( ) {
159
164
self . dot_defines = dot_defines;
160
- self . visit_program ( program) ;
165
+ ( symbols , scopes ) = traverse_mut ( self , self . ast . allocator , program, symbols , scopes ) ;
161
166
}
162
167
163
168
// Step 2: find all the injects that are referenced.
@@ -172,17 +177,19 @@ impl<'a, 'b> InjectGlobalVariables<'a, 'b> {
172
177
} else if self . replaced_dot_defines . iter ( ) . any ( |d| d. 0 == i. specifier . local ( ) ) {
173
178
false
174
179
} else {
175
- self . scopes . root_unresolved_references ( ) . contains_key ( i. specifier . local ( ) )
180
+ scopes. root_unresolved_references ( ) . contains_key ( i. specifier . local ( ) )
176
181
}
177
182
} )
178
183
. cloned ( )
179
184
. collect :: < Vec < _ > > ( ) ;
180
185
181
186
if injects. is_empty ( ) {
182
- return ;
187
+ return InjectGlobalVariablesReturn { symbols , scopes } ;
183
188
}
184
189
185
190
self . inject_imports ( & injects, program) ;
191
+
192
+ InjectGlobalVariablesReturn { symbols, scopes }
186
193
}
187
194
188
195
fn inject_imports ( & self , injects : & [ InjectImport ] , program : & mut Program < ' a > ) {
@@ -227,10 +234,10 @@ impl<'a, 'b> InjectGlobalVariables<'a, 'b> {
227
234
}
228
235
}
229
236
230
- fn replace_dot_defines ( & mut self , expr : & mut Expression < ' a > ) {
237
+ fn replace_dot_defines ( & mut self , expr : & mut Expression < ' a > , ctx : & mut TraverseCtx < ' a > ) {
231
238
if let Expression :: StaticMemberExpression ( member) = expr {
232
239
for DotDefineState { dot_define, value_atom } in & mut self . dot_defines {
233
- if ReplaceGlobalDefines :: is_dot_define ( self . symbols , dot_define, member) {
240
+ if ReplaceGlobalDefines :: is_dot_define ( ctx . symbols ( ) , dot_define, member) {
234
241
// If this is first replacement made for this dot define,
235
242
// create `Atom` for replacement, and record in `replaced_dot_defines`
236
243
if value_atom. is_none ( ) {
0 commit comments