@@ -75,6 +75,7 @@ struct Hoist<'a> {
75
75
collect : & ' a Collect ,
76
76
module_items : Vec < ModuleItem > ,
77
77
export_decls : HashSet < JsWord > ,
78
+ hoisted_imports : Vec < ModuleItem > ,
78
79
imported_symbols : Vec < ImportedSymbol > ,
79
80
exported_symbols : Vec < ExportedSymbol > ,
80
81
re_exports : Vec < ImportedSymbol > ,
@@ -105,6 +106,7 @@ impl<'a> Hoist<'a> {
105
106
collect,
106
107
module_items : vec ! [ ] ,
107
108
export_decls : HashSet :: new ( ) ,
109
+ hoisted_imports : vec ! [ ] ,
108
110
imported_symbols : vec ! [ ] ,
109
111
exported_symbols : vec ! [ ] ,
110
112
re_exports : vec ! [ ] ,
@@ -146,24 +148,25 @@ macro_rules! hoist_visit_fn {
146
148
impl < ' a > Fold for Hoist < ' a > {
147
149
fn fold_module ( & mut self , node : Module ) -> Module {
148
150
let mut node = node;
149
- let mut hoisted_imports = vec ! [ ] ;
150
151
for item in node. body {
151
152
match item {
152
153
ModuleItem :: ModuleDecl ( decl) => {
153
154
match decl {
154
155
ModuleDecl :: Import ( import) => {
155
- hoisted_imports. push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
156
- specifiers : vec ! [ ] ,
157
- asserts : None ,
158
- span : DUMMY_SP ,
159
- src : Str {
160
- value : format ! ( "{}:{}" , self . module_id, import. src. value) . into ( ) ,
156
+ self
157
+ . hoisted_imports
158
+ . push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
159
+ specifiers : vec ! [ ] ,
160
+ asserts : None ,
161
161
span : DUMMY_SP ,
162
- kind : StrKind :: Synthesized ,
163
- has_escape : false ,
164
- } ,
165
- type_only : false ,
166
- } ) ) ) ;
162
+ src : Str {
163
+ value : format ! ( "{}:{}" , self . module_id, import. src. value) . into ( ) ,
164
+ span : DUMMY_SP ,
165
+ kind : StrKind :: Synthesized ,
166
+ has_escape : false ,
167
+ } ,
168
+ type_only : false ,
169
+ } ) ) ) ;
167
170
168
171
// Ensure that all import specifiers are constant.
169
172
for specifier in & import. specifiers {
@@ -201,18 +204,20 @@ impl<'a> Fold for Hoist<'a> {
201
204
ModuleDecl :: ExportNamed ( export) => {
202
205
if let Some ( src) = export. src {
203
206
// TODO: skip if already imported.
204
- hoisted_imports. push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
205
- specifiers : vec ! [ ] ,
206
- asserts : None ,
207
- span : DUMMY_SP ,
208
- src : Str {
209
- value : format ! ( "{}:{}" , self . module_id, src. value) . into ( ) ,
207
+ self
208
+ . hoisted_imports
209
+ . push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
210
+ specifiers : vec ! [ ] ,
211
+ asserts : None ,
210
212
span : DUMMY_SP ,
211
- kind : StrKind :: Synthesized ,
212
- has_escape : false ,
213
- } ,
214
- type_only : false ,
215
- } ) ) ) ;
213
+ src : Str {
214
+ value : format ! ( "{}:{}" , self . module_id, src. value) . into ( ) ,
215
+ span : DUMMY_SP ,
216
+ kind : StrKind :: Synthesized ,
217
+ has_escape : false ,
218
+ } ,
219
+ type_only : false ,
220
+ } ) ) ) ;
216
221
217
222
for specifier in export. specifiers {
218
223
match specifier {
@@ -286,18 +291,20 @@ impl<'a> Fold for Hoist<'a> {
286
291
}
287
292
}
288
293
ModuleDecl :: ExportAll ( export) => {
289
- hoisted_imports. push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
290
- specifiers : vec ! [ ] ,
291
- asserts : None ,
292
- span : DUMMY_SP ,
293
- src : Str {
294
- value : format ! ( "{}:{}" , self . module_id, export. src. value) . into ( ) ,
294
+ self
295
+ . hoisted_imports
296
+ . push ( ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
297
+ specifiers : vec ! [ ] ,
298
+ asserts : None ,
295
299
span : DUMMY_SP ,
296
- kind : StrKind :: Synthesized ,
297
- has_escape : false ,
298
- } ,
299
- type_only : false ,
300
- } ) ) ) ;
300
+ src : Str {
301
+ value : format ! ( "{}:{}" , self . module_id, export. src. value) . into ( ) ,
302
+ span : DUMMY_SP ,
303
+ kind : StrKind :: Synthesized ,
304
+ has_escape : false ,
305
+ } ,
306
+ type_only : false ,
307
+ } ) ) ) ;
301
308
self . re_exports . push ( ImportedSymbol {
302
309
source : export. src . value ,
303
310
local : "*" . into ( ) ,
@@ -522,21 +529,9 @@ impl<'a> Fold for Hoist<'a> {
522
529
}
523
530
}
524
531
525
- for name in self . export_decls . drain ( ) {
526
- hoisted_imports. push ( ModuleItem :: Stmt ( Stmt :: Decl ( Decl :: Var ( VarDecl {
527
- declare : false ,
528
- kind : VarDeclKind :: Var ,
529
- span : node. span ,
530
- decls : vec ! [ VarDeclarator {
531
- definite: false ,
532
- span: node. span,
533
- name: Pat :: Ident ( BindingIdent :: from( Ident :: new( name, DUMMY_SP ) ) ) ,
534
- init: None ,
535
- } ] ,
536
- } ) ) ) ) ;
537
- }
538
-
539
- self . module_items . splice ( 0 ..0 , hoisted_imports) ;
532
+ self
533
+ . module_items
534
+ . splice ( 0 ..0 , self . hoisted_imports . drain ( 0 ..) ) ;
540
535
node. body = std:: mem:: take ( & mut self . module_items ) ;
541
536
node
542
537
}
@@ -922,7 +917,24 @@ impl<'a> Fold for Hoist<'a> {
922
917
923
918
let ident = BindingIdent :: from ( self . get_export_ident ( member. span , & key) ) ;
924
919
if self . collect . static_cjs_exports {
925
- self . export_decls . insert ( ident. id . sym . clone ( ) ) ;
920
+ if self . export_decls . insert ( ident. id . sym . clone ( ) ) {
921
+ self
922
+ . hoisted_imports
923
+ . push ( ModuleItem :: Stmt ( Stmt :: Decl ( Decl :: Var ( VarDecl {
924
+ declare : false ,
925
+ kind : VarDeclKind :: Var ,
926
+ span : node. span ,
927
+ decls : vec ! [ VarDeclarator {
928
+ definite: false ,
929
+ span: node. span,
930
+ name: Pat :: Ident ( BindingIdent :: from( Ident :: new(
931
+ ident. id. sym. clone( ) ,
932
+ DUMMY_SP ,
933
+ ) ) ) ,
934
+ init: None ,
935
+ } ] ,
936
+ } ) ) ) ) ;
937
+ }
926
938
}
927
939
928
940
return AssignExpr {
@@ -1070,7 +1082,7 @@ impl<'a> Hoist<'a> {
1070
1082
// a local variable referencing them so that we can safely re-assign the local variable
1071
1083
// without affecting the original export. This is only possible in CommonJS since ESM
1072
1084
// imports are constant (this is ensured by the diagnostic in fold_module above).
1073
- let mut non_const_bindings = HashSet :: new ( ) ;
1085
+ let mut non_const_bindings = vec ! [ ] ;
1074
1086
self
1075
1087
. collect
1076
1088
. get_non_const_binding_idents ( & v. name , & mut non_const_bindings) ;
@@ -1850,11 +1862,11 @@ impl Collect {
1850
1862
}
1851
1863
}
1852
1864
1853
- fn get_non_const_binding_idents ( & self , node : & Pat , idents : & mut HashSet < Ident > ) {
1865
+ fn get_non_const_binding_idents ( & self , node : & Pat , idents : & mut Vec < Ident > ) {
1854
1866
match node {
1855
1867
Pat :: Ident ( ident) => {
1856
1868
if self . non_const_bindings . contains_key ( & id ! ( ident. id) ) {
1857
- idents. insert ( ident. id . clone ( ) ) ;
1869
+ idents. push ( ident. id . clone ( ) ) ;
1858
1870
}
1859
1871
}
1860
1872
Pat :: Object ( object) => {
@@ -1865,7 +1877,7 @@ impl Collect {
1865
1877
}
1866
1878
ObjectPatProp :: Assign ( assign) => {
1867
1879
if self . non_const_bindings . contains_key ( & id ! ( assign. key) ) {
1868
- idents. insert ( assign. key . clone ( ) ) ;
1880
+ idents. push ( assign. key . clone ( ) ) ;
1869
1881
}
1870
1882
}
1871
1883
ObjectPatProp :: Rest ( rest) => {
0 commit comments