Skip to content

Commit

Permalink
fix(es/transforms/cjs): Allow using multiple export * (#2598)
Browse files Browse the repository at this point in the history
swc_ecma_transforms_module:
 - Preserve order of imports for reexports. (#2594)
  • Loading branch information
kwonoj authored Nov 2, 2021
1 parent f8c7d36 commit 5b141ee
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 201 deletions.
5 changes: 4 additions & 1 deletion ecmascript/transforms/module/src/amd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,10 @@ where
};

for export in export_alls {
stmts.push(scope.handle_export_all(
let export = scope
.import_to_export(&export.src, true)
.expect("Export should exists");
stmts.push(Scope::handle_export_all(
exports_ident.clone(),
exported_names.clone(),
export,
Expand Down
128 changes: 71 additions & 57 deletions ecmascript/transforms/module/src/common_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use std::{
cell::{Ref, RefCell, RefMut},
rc::Rc,
};
use swc_atoms::js_word;
use swc_common::{FileName, Mark, Span, DUMMY_SP};
use swc_atoms::{js_word, JsWord};
use swc_common::{collections::AHashMap, FileName, Mark, Span, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::helper;
use swc_ecma_utils::{
Expand Down Expand Up @@ -84,7 +84,10 @@ where

let mut exports = vec![];
let mut initialized = IndexSet::default();
let mut export_alls = vec![];

let mut export_alls: AHashMap<JsWord, Ident> = Default::default();
// Used only if export * exists
let mut exported_names: Option<Ident> = None;

for item in items {
self.in_top_level = true;
Expand Down Expand Up @@ -174,14 +177,69 @@ where
}
drop(scope);
drop(scope_ref_mut);

match item {
ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export)) => {
self.scope
.borrow_mut()
.lazy_blacklist
.insert(export.src.value.clone());

export_alls.push(export);
let mut scope_ref_mut = self.scope.borrow_mut();
let scope = &mut *scope_ref_mut;

if exported_names.is_none()
&& (export_alls.len() >= 1 || !exports.is_empty())
{
let exported_names_ident = private_ident!("_exportNames");
stmts.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(exported_names_ident.clone().into()),
init: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: exports
.clone()
.into_iter()
.filter_map(|export| {
if export == js_word!("default") {
return None;
}

Some(PropOrSpread::Prop(Box::new(
Prop::KeyValue(KeyValueProp {
key: PropName::Ident(Ident::new(
export, DUMMY_SP,
)),
value: Box::new(Expr::Lit(Lit::Bool(
Bool {
span: DUMMY_SP,
value: true,
},
))),
}),
)))
})
.collect(),
}))),
definite: false,
}],
declare: false,
}))));

exported_names = Some(exported_names_ident);
}

export_alls.entry(export.src.value.clone()).or_insert(
scope
.import_to_export(&export.src, true)
.expect("Export should exists"),
);

drop(scope);
drop(scope_ref_mut);
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: decl @ Decl::Class(..),
Expand Down Expand Up @@ -521,61 +579,8 @@ where
}
}

let has_export = !exports.is_empty();

let mut scope_ref_mut = self.scope.borrow_mut();
let scope = &mut *scope_ref_mut;
// Used only if export * exists
let exported_names = {
if (!export_alls.is_empty() && has_export) || export_alls.len() >= 2 {
let exported_names = private_ident!("_exportNames");
stmts.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(exported_names.clone().into()),
init: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: exports
.into_iter()
.filter_map(|export| {
if export == js_word!("default") {
return None;
}

Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(
KeyValueProp {
key: PropName::Ident(Ident::new(export, DUMMY_SP)),
value: Box::new(Expr::Lit(Lit::Bool(Bool {
span: DUMMY_SP,
value: true,
}))),
},
))))
})
.collect(),
}))),
definite: false,
}],
declare: false,
}))));

Some(exported_names)
} else {
None
}
};

for export in export_alls {
// We use extra_stmts because it should be placed *after* import
// statements.
extra_stmts.push(ModuleItem::Stmt(scope.handle_export_all(
quote_ident!("exports"),
exported_names.clone(),
export,
)));
}

if !initialized.is_empty() {
stmts.push(
Expand Down Expand Up @@ -699,6 +704,15 @@ where
stmts.push(require.into_stmt().into());
}
}

let exported = export_alls.remove(&src);
if let Some(export) = exported {
stmts.push(ModuleItem::Stmt(Scope::handle_export_all(
quote_ident!("exports"),
exported_names.clone(),
export,
)));
}
}

stmts.append(&mut extra_stmts);
Expand Down
5 changes: 4 additions & 1 deletion ecmascript/transforms/module/src/umd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,10 @@ where
};

for export in export_alls {
stmts.push(scope.handle_export_all(
let export = scope
.import_to_export(&export.src, true)
.expect("Export should exists");
stmts.push(Scope::handle_export_all(
exports_ident.clone(),
exported_names.clone(),
export,
Expand Down
5 changes: 1 addition & 4 deletions ecmascript/transforms/module/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,10 @@ impl Scope {
/// # Parameters
/// - `exported_names` Ident of the object literal.
pub fn handle_export_all(
&mut self,
exports: Ident,
exported_names: Option<Ident>,
export: ExportAll,
imported: Ident,
) -> Stmt {
let imported = self.import_to_export(&export.src, true).unwrap();

let key_ident = private_ident!("key");

let function = Function {
Expand Down
Loading

1 comment on commit 5b141ee

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 5b141ee Previous: f8c7d36 Ratio
base_tr_fixer 32055 ns/iter (± 3920) 31952 ns/iter (± 4430) 1.00
base_tr_resolver_and_hygiene 173059 ns/iter (± 38070) 178928 ns/iter (± 23917) 0.97
codegen_es2015 59104 ns/iter (± 13232) 63000 ns/iter (± 6623) 0.94
codegen_es2016 65662 ns/iter (± 7286) 63511 ns/iter (± 9102) 1.03
codegen_es2017 65726 ns/iter (± 15488) 63692 ns/iter (± 10809) 1.03
codegen_es2018 66512 ns/iter (± 6253) 63976 ns/iter (± 12885) 1.04
codegen_es2019 64548 ns/iter (± 6708) 62471 ns/iter (± 5873) 1.03
codegen_es2020 65674 ns/iter (± 8122) 64889 ns/iter (± 17793) 1.01
codegen_es3 65339 ns/iter (± 6577) 57927 ns/iter (± 10996) 1.13
codegen_es5 65619 ns/iter (± 7090) 58394 ns/iter (± 9320) 1.12
config_for_file 19889 ns/iter (± 7137) 17663 ns/iter (± 5165) 1.13
full_es2015 216137625 ns/iter (± 18934887) 208092249 ns/iter (± 23820745) 1.04
full_es2016 160468073 ns/iter (± 15959862) 159412268 ns/iter (± 23973850) 1.01
full_es2017 178972364 ns/iter (± 22465831) 162173212 ns/iter (± 16259176) 1.10
full_es2018 166104495 ns/iter (± 20972582) 169030629 ns/iter (± 22952669) 0.98
full_es2019 163223916 ns/iter (± 16152563) 160866622 ns/iter (± 25764736) 1.01
full_es2020 163109109 ns/iter (± 15471728) 164313524 ns/iter (± 19794526) 0.99
full_es3 238744786 ns/iter (± 36155757) 239130141 ns/iter (± 40485545) 1.00
full_es5 240135203 ns/iter (± 36458287) 227765201 ns/iter (± 32123697) 1.05
parser 830835 ns/iter (± 137641) 709285 ns/iter (± 121134) 1.17
transforms_es2015 1289060 ns/iter (± 105505) 1221587 ns/iter (± 222698) 1.06
transforms_es2016 811240 ns/iter (± 111351) 809297 ns/iter (± 200233) 1.00
transforms_es2017 864065 ns/iter (± 209342) 766126 ns/iter (± 127882) 1.13
transforms_es2018 802097 ns/iter (± 180696) 746318 ns/iter (± 101173) 1.07
transforms_es2019 766896 ns/iter (± 153283) 756119 ns/iter (± 147502) 1.01
transforms_es2020 758320 ns/iter (± 305269) 736180 ns/iter (± 128780) 1.03
transforms_es3 1466250 ns/iter (± 452238) 1459013 ns/iter (± 196805) 1.00
transforms_es5 1291760 ns/iter (± 180953) 1210476 ns/iter (± 248111) 1.07
ser_ast_node 191 ns/iter (± 22) 166 ns/iter (± 35) 1.15
ser_serde 187 ns/iter (± 21) 167 ns/iter (± 28) 1.12
emit_colors 16984204 ns/iter (± 22011803) 18115308 ns/iter (± 23607720) 0.94
emit_large 92749856 ns/iter (± 145239566) 88977071 ns/iter (± 144429865) 1.04
base_clone 2558411 ns/iter (± 368732) 2844187 ns/iter (± 555357) 0.90
fold_span 4653279 ns/iter (± 538329) 4802043 ns/iter (± 707131) 0.97
fold_span_panic 4923656 ns/iter (± 454101) 4817951 ns/iter (± 582510) 1.02
visit_mut_span 3316201 ns/iter (± 354745) 3321207 ns/iter (± 589551) 1.00
visit_mut_span_panic 3369164 ns/iter (± 395539) 3263651 ns/iter (± 553493) 1.03
boxing_boxed 188 ns/iter (± 20) 174 ns/iter (± 33) 1.08
boxing_boxed_clone 76 ns/iter (± 9) 83 ns/iter (± 20) 0.92
boxing_unboxed 148 ns/iter (± 20) 137 ns/iter (± 37) 1.08
boxing_unboxed_clone 105 ns/iter (± 17) 58 ns/iter (± 18) 1.81

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.