Skip to content

Commit 91de5c0

Browse files
authoredOct 6, 2021
Ensure symbol order is consistent (#7021)
1 parent 2ebed00 commit 91de5c0

File tree

2 files changed

+119
-93
lines changed

2 files changed

+119
-93
lines changed
 

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

+102-79
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,29 @@ pub fn hoist(
5555
Ok((module, hoist.get_result(), diagnostics))
5656
}
5757

58+
#[derive(Debug, Serialize, Deserialize)]
59+
struct ExportedSymbol {
60+
local: JsWord,
61+
exported: JsWord,
62+
loc: SourceLocation,
63+
}
64+
65+
#[derive(Debug, Serialize, Deserialize)]
66+
struct ImportedSymbol {
67+
source: JsWord,
68+
local: JsWord,
69+
imported: JsWord,
70+
loc: SourceLocation,
71+
}
72+
5873
struct Hoist<'a> {
5974
module_id: &'a str,
6075
collect: &'a Collect,
6176
module_items: Vec<ModuleItem>,
6277
export_decls: HashSet<JsWord>,
63-
imported_symbols: HashMap<JsWord, (JsWord, JsWord, SourceLocation)>,
64-
exported_symbols: HashMap<JsWord, (JsWord, SourceLocation)>,
65-
re_exports: Vec<(JsWord, JsWord, JsWord, SourceLocation)>,
78+
imported_symbols: Vec<ImportedSymbol>,
79+
exported_symbols: Vec<ExportedSymbol>,
80+
re_exports: Vec<ImportedSymbol>,
6681
self_references: HashSet<JsWord>,
6782
dynamic_imports: HashMap<JsWord, JsWord>,
6883
in_function_scope: bool,
@@ -71,9 +86,9 @@ struct Hoist<'a> {
7186

7287
#[derive(Debug, Default, Serialize, Deserialize)]
7388
pub struct HoistResult {
74-
imported_symbols: HashMap<JsWord, (JsWord, JsWord, SourceLocation)>,
75-
exported_symbols: HashMap<JsWord, (JsWord, SourceLocation)>,
76-
re_exports: Vec<(JsWord, JsWord, JsWord, SourceLocation)>,
89+
imported_symbols: Vec<ImportedSymbol>,
90+
exported_symbols: Vec<ExportedSymbol>,
91+
re_exports: Vec<ImportedSymbol>,
7792
self_references: HashSet<JsWord>,
7893
wrapped_requires: HashSet<JsWord>,
7994
dynamic_imports: HashMap<JsWord, JsWord>,
@@ -90,8 +105,8 @@ impl<'a> Hoist<'a> {
90105
collect,
91106
module_items: vec![],
92107
export_decls: HashSet::new(),
93-
imported_symbols: HashMap::new(),
94-
exported_symbols: HashMap::new(),
108+
imported_symbols: vec![],
109+
exported_symbols: vec![],
95110
re_exports: vec![],
96111
self_references: HashSet::new(),
97112
dynamic_imports: HashMap::new(),
@@ -206,28 +221,28 @@ impl<'a> Fold for Hoist<'a> {
206221
Some(exported) => exported.sym,
207222
None => named.orig.sym.clone(),
208223
};
209-
self.re_exports.push((
210-
exported,
211-
src.value.clone(),
212-
named.orig.sym,
213-
SourceLocation::from(&self.collect.source_map, named.span),
214-
));
224+
self.re_exports.push(ImportedSymbol {
225+
source: src.value.clone(),
226+
local: exported,
227+
imported: named.orig.sym,
228+
loc: SourceLocation::from(&self.collect.source_map, named.span),
229+
});
215230
}
216231
ExportSpecifier::Default(default) => {
217-
self.re_exports.push((
218-
default.exported.sym,
219-
src.value.clone(),
220-
js_word!("default"),
221-
SourceLocation::from(&self.collect.source_map, default.exported.span),
222-
));
232+
self.re_exports.push(ImportedSymbol {
233+
source: src.value.clone(),
234+
local: default.exported.sym,
235+
imported: js_word!("default"),
236+
loc: SourceLocation::from(&self.collect.source_map, default.exported.span),
237+
});
223238
}
224239
ExportSpecifier::Namespace(namespace) => {
225-
self.re_exports.push((
226-
namespace.name.sym,
227-
src.value.clone(),
228-
"*".into(),
229-
SourceLocation::from(&self.collect.source_map, namespace.span),
230-
));
240+
self.re_exports.push(ImportedSymbol {
241+
source: src.value.clone(),
242+
local: namespace.name.sym,
243+
imported: "*".into(),
244+
loc: SourceLocation::from(&self.collect.source_map, namespace.span),
245+
});
231246
}
232247
}
233248
}
@@ -243,12 +258,12 @@ impl<'a> Fold for Hoist<'a> {
243258
source, specifier, ..
244259
}) = self.collect.imports.get(&id)
245260
{
246-
self.re_exports.push((
247-
exported,
248-
source.clone(),
249-
specifier.clone(),
250-
SourceLocation::from(&self.collect.source_map, named.span),
251-
));
261+
self.re_exports.push(ImportedSymbol {
262+
source: source.clone(),
263+
local: exported,
264+
imported: specifier.clone(),
265+
loc: SourceLocation::from(&self.collect.source_map, named.span),
266+
});
252267
} else {
253268
// A variable will appear only once in the `exports` mapping but
254269
// could be exported multiple times with different names.
@@ -259,10 +274,11 @@ impl<'a> Fold for Hoist<'a> {
259274
} else {
260275
self.get_export_ident(DUMMY_SP, orig_exported)
261276
};
262-
self.exported_symbols.entry(exported).or_insert((
263-
id.sym,
264-
SourceLocation::from(&self.collect.source_map, named.span),
265-
));
277+
self.exported_symbols.push(ExportedSymbol {
278+
local: id.sym,
279+
exported,
280+
loc: SourceLocation::from(&self.collect.source_map, named.span),
281+
});
266282
}
267283
}
268284
}
@@ -281,12 +297,12 @@ impl<'a> Fold for Hoist<'a> {
281297
},
282298
type_only: false,
283299
})));
284-
self.re_exports.push((
285-
"*".into(),
286-
export.src.value,
287-
"*".into(),
288-
SourceLocation::from(&self.collect.source_map, export.span),
289-
));
300+
self.re_exports.push(ImportedSymbol {
301+
source: export.src.value,
302+
local: "*".into(),
303+
imported: "*".into(),
304+
loc: SourceLocation::from(&self.collect.source_map, export.span),
305+
});
290306
}
291307
ModuleDecl::ExportDefaultExpr(export) => {
292308
let ident = self.get_export_ident(export.span, &"default".into());
@@ -582,14 +598,12 @@ impl<'a> Fold for Hoist<'a> {
582598
hash!(key)
583599
)
584600
.into();
585-
self.imported_symbols.insert(
586-
name,
587-
(
588-
source.clone(),
589-
key.clone(),
590-
SourceLocation::from(&self.collect.source_map, member.span),
591-
),
592-
);
601+
self.imported_symbols.push(ImportedSymbol {
602+
source: source.clone(),
603+
local: name,
604+
imported: key.clone(),
605+
loc: SourceLocation::from(&self.collect.source_map, member.span),
606+
});
593607
} else {
594608
return Expr::Ident(self.get_import_ident(
595609
member.span,
@@ -676,14 +690,12 @@ impl<'a> Fold for Hoist<'a> {
676690
let name: JsWord = format!("${}$importAsync${:x}", self.module_id, hash!(source)).into();
677691
self.dynamic_imports.insert(name.clone(), source.clone());
678692
if self.collect.non_static_requires.contains(&source) || self.collect.should_wrap {
679-
self.imported_symbols.insert(
680-
name.clone(),
681-
(
682-
source,
683-
"*".into(),
684-
SourceLocation::from(&self.collect.source_map, call.span),
685-
),
686-
);
693+
self.imported_symbols.push(ImportedSymbol {
694+
source: source,
695+
local: name.clone(),
696+
imported: "*".into(),
697+
loc: SourceLocation::from(&self.collect.source_map, call.span),
698+
});
687699
}
688700
return Expr::Ident(Ident::new(name, call.span));
689701
}
@@ -784,15 +796,21 @@ impl<'a> Fold for Hoist<'a> {
784796
hash!(specifier)
785797
)
786798
.into();
787-
self
788-
.imported_symbols
789-
.insert(name, (source.clone(), specifier.clone(), loc.clone()));
799+
self.imported_symbols.push(ImportedSymbol {
800+
source: source.clone(),
801+
local: name,
802+
imported: specifier.clone(),
803+
loc: loc.clone(),
804+
});
790805
} else if self.collect.non_static_access.contains_key(&id!(node)) {
791806
let name: JsWord =
792807
format!("${}$importAsync${:x}", self.module_id, hash!(source)).into();
793-
self
794-
.imported_symbols
795-
.insert(name, (source.clone(), "*".into(), loc.clone()));
808+
self.imported_symbols.push(ImportedSymbol {
809+
source: source.clone(),
810+
local: name,
811+
imported: "*".into(),
812+
loc: loc.clone(),
813+
});
796814
}
797815
} else {
798816
// If this identifier is not constant, we cannot directly reference the imported
@@ -813,10 +831,11 @@ impl<'a> Fold for Hoist<'a> {
813831
// If wrapped, mark the original symbol as exported.
814832
// Otherwise replace with an export identifier.
815833
if self.collect.should_wrap {
816-
self.exported_symbols.entry(exported.clone()).or_insert((
817-
node.sym.clone(),
818-
SourceLocation::from(&self.collect.source_map, node.span),
819-
));
834+
self.exported_symbols.push(ExportedSymbol {
835+
local: node.sym.clone(),
836+
exported: exported.clone(),
837+
loc: SourceLocation::from(&self.collect.source_map, node.span),
838+
});
820839
return node;
821840
} else {
822841
return self.get_export_ident(node.span, exported);
@@ -1007,13 +1026,16 @@ impl<'a> Hoist<'a> {
10071026
&mut self,
10081027
span: Span,
10091028
source: &JsWord,
1010-
local: &JsWord,
1029+
imported: &JsWord,
10111030
loc: SourceLocation,
10121031
) -> Ident {
1013-
let new_name = self.get_import_name(source, local);
1014-
self
1015-
.imported_symbols
1016-
.insert(new_name.clone(), (source.clone(), local.clone(), loc));
1032+
let new_name = self.get_import_name(source, imported);
1033+
self.imported_symbols.push(ImportedSymbol {
1034+
source: source.clone(),
1035+
local: new_name.clone(),
1036+
imported: imported.clone(),
1037+
loc: loc.clone(),
1038+
});
10171039
Ident::new(new_name, span)
10181040
}
10191041

@@ -1031,10 +1053,11 @@ impl<'a> Hoist<'a> {
10311053
format!("${}$export${:x}", self.module_id, hash!(exported)).into()
10321054
};
10331055

1034-
self.exported_symbols.entry(exported.clone()).or_insert((
1035-
new_name.clone(),
1036-
SourceLocation::from(&self.collect.source_map, span),
1037-
));
1056+
self.exported_symbols.push(ExportedSymbol {
1057+
local: new_name.clone(),
1058+
exported: exported.clone(),
1059+
loc: SourceLocation::from(&self.collect.source_map, span),
1060+
});
10381061

10391062
let mut span = span;
10401063
span.ctxt = SyntaxContext::empty();
@@ -2054,8 +2077,8 @@ mod tests {
20542077
macro_rules! assert_eq_imported_symbols {
20552078
($m: expr, $match: expr) => {{
20562079
let mut map = HashMap::new();
2057-
for (key, val) in $m {
2058-
map.insert(key, (val.0, val.1));
2080+
for sym in $m {
2081+
map.insert(sym.local, (sym.source, sym.imported));
20592082
}
20602083
assert_eq!(map, $match);
20612084
}};

‎packages/transformers/js/src/JSTransformer.js

+17-14
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,8 @@ export default (new Transformer({
674674
asset.meta.id = asset.id;
675675
if (hoist_result) {
676676
asset.symbols.ensure();
677-
for (let symbol in hoist_result.exported_symbols) {
678-
let [local, loc] = hoist_result.exported_symbols[symbol];
679-
asset.symbols.set(symbol, local, convertLoc(loc));
677+
for (let {exported, local, loc} of hoist_result.exported_symbols) {
678+
asset.symbols.set(exported, local, convertLoc(loc));
680679
}
681680

682681
let deps = new Map(
@@ -688,25 +687,29 @@ export default (new Transformer({
688687
dep.symbols.ensure();
689688
}
690689

691-
for (let name in hoist_result.imported_symbols) {
692-
let [specifier, exported, loc] = hoist_result.imported_symbols[name];
693-
let dep = deps.get(specifier);
690+
for (let {
691+
source,
692+
local,
693+
imported,
694+
loc,
695+
} of hoist_result.imported_symbols) {
696+
let dep = deps.get(source);
694697
if (!dep) continue;
695-
dep.symbols.set(exported, name, convertLoc(loc));
698+
dep.symbols.set(imported, local, convertLoc(loc));
696699
}
697700

698-
for (let [name, specifier, exported, loc] of hoist_result.re_exports) {
699-
let dep = deps.get(specifier);
701+
for (let {source, local, imported, loc} of hoist_result.re_exports) {
702+
let dep = deps.get(source);
700703
if (!dep) continue;
701704

702-
if (name === '*' && exported === '*') {
705+
if (local === '*' && imported === '*') {
703706
dep.symbols.set('*', '*', convertLoc(loc), true);
704707
} else {
705708
let reExportName =
706-
dep.symbols.get(exported)?.local ??
707-
`$${asset.id}$re_export$${name}`;
708-
asset.symbols.set(name, reExportName);
709-
dep.symbols.set(exported, reExportName, convertLoc(loc), true);
709+
dep.symbols.get(imported)?.local ??
710+
`$${asset.id}$re_export$${local}`;
711+
asset.symbols.set(local, reExportName);
712+
dep.symbols.set(imported, reExportName, convertLoc(loc), true);
710713
}
711714
}
712715

0 commit comments

Comments
 (0)
Please sign in to comment.