Skip to content

Commit dbe1153

Browse files
authoredOct 12, 2021
Fix order of hoisted variable declarations (#7053)
1 parent bea9442 commit dbe1153

File tree

1 file changed

+66
-54
lines changed
  • packages/transformers/js/core/src

1 file changed

+66
-54
lines changed
 

‎packages/transformers/js/core/src/hoist.rs

+66-54
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct Hoist<'a> {
7575
collect: &'a Collect,
7676
module_items: Vec<ModuleItem>,
7777
export_decls: HashSet<JsWord>,
78+
hoisted_imports: Vec<ModuleItem>,
7879
imported_symbols: Vec<ImportedSymbol>,
7980
exported_symbols: Vec<ExportedSymbol>,
8081
re_exports: Vec<ImportedSymbol>,
@@ -105,6 +106,7 @@ impl<'a> Hoist<'a> {
105106
collect,
106107
module_items: vec![],
107108
export_decls: HashSet::new(),
109+
hoisted_imports: vec![],
108110
imported_symbols: vec![],
109111
exported_symbols: vec![],
110112
re_exports: vec![],
@@ -146,24 +148,25 @@ macro_rules! hoist_visit_fn {
146148
impl<'a> Fold for Hoist<'a> {
147149
fn fold_module(&mut self, node: Module) -> Module {
148150
let mut node = node;
149-
let mut hoisted_imports = vec![];
150151
for item in node.body {
151152
match item {
152153
ModuleItem::ModuleDecl(decl) => {
153154
match decl {
154155
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,
161161
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+
})));
167170

168171
// Ensure that all import specifiers are constant.
169172
for specifier in &import.specifiers {
@@ -201,18 +204,20 @@ impl<'a> Fold for Hoist<'a> {
201204
ModuleDecl::ExportNamed(export) => {
202205
if let Some(src) = export.src {
203206
// 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,
210212
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+
})));
216221

217222
for specifier in export.specifiers {
218223
match specifier {
@@ -286,18 +291,20 @@ impl<'a> Fold for Hoist<'a> {
286291
}
287292
}
288293
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,
295299
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+
})));
301308
self.re_exports.push(ImportedSymbol {
302309
source: export.src.value,
303310
local: "*".into(),
@@ -522,21 +529,9 @@ impl<'a> Fold for Hoist<'a> {
522529
}
523530
}
524531

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..));
540535
node.body = std::mem::take(&mut self.module_items);
541536
node
542537
}
@@ -922,7 +917,24 @@ impl<'a> Fold for Hoist<'a> {
922917

923918
let ident = BindingIdent::from(self.get_export_ident(member.span, &key));
924919
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+
}
926938
}
927939

928940
return AssignExpr {
@@ -1070,7 +1082,7 @@ impl<'a> Hoist<'a> {
10701082
// a local variable referencing them so that we can safely re-assign the local variable
10711083
// without affecting the original export. This is only possible in CommonJS since ESM
10721084
// 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![];
10741086
self
10751087
.collect
10761088
.get_non_const_binding_idents(&v.name, &mut non_const_bindings);
@@ -1850,11 +1862,11 @@ impl Collect {
18501862
}
18511863
}
18521864

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>) {
18541866
match node {
18551867
Pat::Ident(ident) => {
18561868
if self.non_const_bindings.contains_key(&id!(ident.id)) {
1857-
idents.insert(ident.id.clone());
1869+
idents.push(ident.id.clone());
18581870
}
18591871
}
18601872
Pat::Object(object) => {
@@ -1865,7 +1877,7 @@ impl Collect {
18651877
}
18661878
ObjectPatProp::Assign(assign) => {
18671879
if self.non_const_bindings.contains_key(&id!(assign.key)) {
1868-
idents.insert(assign.key.clone());
1880+
idents.push(assign.key.clone());
18691881
}
18701882
}
18711883
ObjectPatProp::Rest(rest) => {

0 commit comments

Comments
 (0)
Please sign in to comment.