mirror of
https://github.com/swc-project/swc.git
synced 2024-11-24 10:12:42 +03:00
Amd & Fix for exports (#164)
swc_ecma_transforms: - correctly tracks exported names. - Implement amd Fix #162
This commit is contained in:
parent
42f94a3f24
commit
8c5c7b55b7
705
ecmascript/transforms/src/modules/amd/mod.rs
Normal file
705
ecmascript/transforms/src/modules/amd/mod.rs
Normal file
@ -0,0 +1,705 @@
|
||||
use super::util::{
|
||||
define_es_module, define_property, initialize_to_undefined, local_name_for_src,
|
||||
make_descriptor, use_strict, Exports, Scope, VarCollector,
|
||||
};
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
util::{prepend_stmts, DestructuringFinder, ExprFactory, State},
|
||||
};
|
||||
use ast::*;
|
||||
use fxhash::FxHashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::hash_map::Entry, iter};
|
||||
use swc_common::{Fold, FoldWith, Mark, VisitWith, DUMMY_SP};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn amd(config: Config) -> impl Pass + Clone {
|
||||
Amd {
|
||||
config,
|
||||
scope: Default::default(),
|
||||
exports: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Amd {
|
||||
config: Config,
|
||||
scope: State<Scope>,
|
||||
exports: State<Exports>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
pub module_id: Option<String>,
|
||||
}
|
||||
|
||||
impl Fold<Module> for Amd {
|
||||
fn fold(&mut self, module: Module) -> Module {
|
||||
let items = module.body;
|
||||
|
||||
// Inserted after initializing exported names to undefined.
|
||||
let mut extra_stmts = vec![];
|
||||
let mut stmts = Vec::with_capacity(items.len() + 2);
|
||||
stmts.push(use_strict());
|
||||
|
||||
let mut exports = vec![];
|
||||
let mut initialized = FxHashSet::default();
|
||||
let mut export_alls = vec![];
|
||||
let mut emitted_esmodule = false;
|
||||
let exports_ident = self.exports.value.0.clone();
|
||||
|
||||
// Process items
|
||||
for item in items {
|
||||
let decl = match item {
|
||||
ModuleItem::Stmt(stmt) => {
|
||||
extra_stmts.push(stmt.fold_with(self));
|
||||
continue;
|
||||
}
|
||||
ModuleItem::ModuleDecl(decl) => decl,
|
||||
};
|
||||
|
||||
match decl {
|
||||
ModuleDecl::Import(import) => self.scope.insert_import(import),
|
||||
|
||||
ModuleDecl::ExportAll(..)
|
||||
| ModuleDecl::ExportDecl(..)
|
||||
| ModuleDecl::ExportDefaultDecl(..)
|
||||
| ModuleDecl::ExportDefaultExpr(..)
|
||||
| ModuleDecl::ExportNamed(..) => {
|
||||
if !emitted_esmodule {
|
||||
emitted_esmodule = true;
|
||||
stmts.push(define_es_module(exports_ident.clone()));
|
||||
}
|
||||
|
||||
macro_rules! init_export {
|
||||
("default") => {{
|
||||
init_export!(js_word!("default"))
|
||||
}};
|
||||
($name:expr) => {{
|
||||
exports.push($name.clone());
|
||||
initialized.insert($name.clone());
|
||||
}};
|
||||
}
|
||||
match decl {
|
||||
// Function declaration cannot throw an error.
|
||||
ModuleDecl::ExportDefaultDecl(ExportDefaultDecl::Fn(..)) => {
|
||||
// initialized.insert(js_word!("default"));
|
||||
}
|
||||
|
||||
ModuleDecl::ExportDefaultDecl(ExportDefaultDecl::TsInterfaceDecl(..)) => {}
|
||||
|
||||
ModuleDecl::ExportAll(ref export) => {
|
||||
self.scope
|
||||
.value
|
||||
.import_types
|
||||
.entry(export.src.value.clone())
|
||||
.and_modify(|v| *v = true);
|
||||
}
|
||||
|
||||
ModuleDecl::ExportDefaultDecl(..) | ModuleDecl::ExportDefaultExpr(..) => {
|
||||
// TODO: Optimization (when expr cannot throw, `exports.default =
|
||||
// void 0` is not required)
|
||||
init_export!("default")
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match decl {
|
||||
ModuleDecl::ExportAll(export) => export_alls.push(export),
|
||||
ModuleDecl::ExportDecl(decl @ Decl::Class(..))
|
||||
| ModuleDecl::ExportDecl(decl @ Decl::Fn(..)) => {
|
||||
let (ident, is_class) = match decl {
|
||||
Decl::Class(ref c) => (c.ident.clone(), true),
|
||||
Decl::Fn(ref f) => (f.ident.clone(), false),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
//
|
||||
extra_stmts.push(Stmt::Decl(decl.fold_with(self)));
|
||||
|
||||
let append_to: &mut Vec<_> = if is_class {
|
||||
&mut extra_stmts
|
||||
} else {
|
||||
// Function declaration cannot throw
|
||||
&mut stmts
|
||||
};
|
||||
|
||||
append_to.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident.clone().member(ident.clone()),
|
||||
),
|
||||
op: op!("="),
|
||||
right: box ident.into(),
|
||||
})));
|
||||
}
|
||||
ModuleDecl::ExportDecl(Decl::Var(var)) => {
|
||||
extra_stmts.push(Stmt::Decl(Decl::Var(var.clone().fold_with(self))));
|
||||
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
});
|
||||
|
||||
let mut found = vec![];
|
||||
for decl in var.decls {
|
||||
let mut v = DestructuringFinder { found: &mut found };
|
||||
decl.visit_with(&mut v);
|
||||
|
||||
for ident in found.drain(..).map(|v| Ident::new(v.0, v.1)) {
|
||||
self.scope
|
||||
.exported_vars
|
||||
.entry((ident.sym.clone(), ident.span.ctxt()))
|
||||
.or_default()
|
||||
.push((ident.sym.clone(), ident.span.ctxt()));
|
||||
init_export!(ident.sym);
|
||||
|
||||
extra_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident.clone().member(ident.clone()),
|
||||
),
|
||||
op: op!("="),
|
||||
right: box ident.into(),
|
||||
})));
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleDecl::ExportDefaultDecl(decl) => match decl {
|
||||
ExportDefaultDecl::Class(ClassExpr { ident, class }) => {
|
||||
let ident = ident.unwrap_or_else(|| private_ident!("_default"));
|
||||
|
||||
extra_stmts.push(Stmt::Decl(Decl::Class(ClassDecl {
|
||||
ident: ident.clone(),
|
||||
class,
|
||||
declare: false,
|
||||
})));
|
||||
|
||||
extra_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident.clone().member(quote_ident!("default")),
|
||||
),
|
||||
op: op!("="),
|
||||
right: box ident.into(),
|
||||
})));
|
||||
}
|
||||
ExportDefaultDecl::Fn(FnExpr { ident, function }) => {
|
||||
let ident = ident.unwrap_or_else(|| private_ident!("_default"));
|
||||
|
||||
extra_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident.clone().member(quote_ident!("default")),
|
||||
),
|
||||
op: op!("="),
|
||||
right: box ident.clone().into(),
|
||||
})));
|
||||
|
||||
extra_stmts.push(Stmt::Decl(Decl::Fn(
|
||||
FnDecl {
|
||||
ident,
|
||||
function,
|
||||
declare: false,
|
||||
}
|
||||
.fold_with(self),
|
||||
)));
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
|
||||
ModuleDecl::ExportDefaultExpr(expr) => {
|
||||
let ident = private_ident!("_default");
|
||||
|
||||
// We use extra statements because of the initialzation
|
||||
extra_stmts.push(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(ident.clone()),
|
||||
init: Some(expr.fold_with(self)),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
})));
|
||||
extra_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident.clone().member(quote_ident!("default")),
|
||||
),
|
||||
op: op!("="),
|
||||
right: box ident.into(),
|
||||
})));
|
||||
}
|
||||
|
||||
// export { foo } from 'foo';
|
||||
ModuleDecl::ExportNamed(export) => {
|
||||
let imported = export.src.clone().map(|src| {
|
||||
self.scope
|
||||
.import_to_export(&src, !export.specifiers.is_empty())
|
||||
});
|
||||
|
||||
stmts.reserve(export.specifiers.len());
|
||||
|
||||
for ExportSpecifier { orig, exported, .. } in export.specifiers {
|
||||
let is_import_default = orig.sym == js_word!("default");
|
||||
|
||||
let key = (orig.sym.clone(), orig.span.ctxt());
|
||||
if self.scope.value.declared_vars.contains(&key) {
|
||||
self.scope
|
||||
.exported_vars
|
||||
.entry(key.clone())
|
||||
.or_default()
|
||||
.push(
|
||||
exported
|
||||
.clone()
|
||||
.map(|i| (i.sym.clone(), i.span.ctxt()))
|
||||
.unwrap_or_else(|| {
|
||||
(orig.sym.clone(), orig.span.ctxt())
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(ref src) = export.src {
|
||||
if is_import_default {
|
||||
self.scope
|
||||
.import_types
|
||||
.entry(src.value.clone())
|
||||
.or_insert(false);
|
||||
}
|
||||
}
|
||||
|
||||
let value = match imported {
|
||||
Some(ref imported) => {
|
||||
box imported.clone().unwrap().member(orig.clone())
|
||||
}
|
||||
None => box Expr::Ident(orig.clone()).fold_with(self),
|
||||
};
|
||||
|
||||
// True if we are exporting our own stuff.
|
||||
let is_value_ident = match *value {
|
||||
Expr::Ident(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if is_value_ident {
|
||||
let exported_symbol = exported
|
||||
.as_ref()
|
||||
.map(|e| e.sym.clone())
|
||||
.unwrap_or_else(|| orig.sym.clone());
|
||||
init_export!(exported_symbol);
|
||||
|
||||
extra_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident
|
||||
.clone()
|
||||
.member(exported.unwrap_or(orig)),
|
||||
),
|
||||
op: op!("="),
|
||||
right: value,
|
||||
})));
|
||||
} else {
|
||||
stmts.push(Stmt::Expr(box define_property(vec![
|
||||
exports_ident.clone().as_arg(),
|
||||
{
|
||||
// export { foo }
|
||||
// -> 'foo'
|
||||
|
||||
// export { foo as bar }
|
||||
// -> 'bar'
|
||||
let i = exported.unwrap_or_else(|| orig);
|
||||
Lit::Str(quote_str!(i.span, i.sym)).as_arg()
|
||||
},
|
||||
make_descriptor(value).as_arg(),
|
||||
])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleDecl::TsImportEqualsDecl(..)
|
||||
| ModuleDecl::TsExportAssignment(..)
|
||||
| ModuleDecl::TsNamespaceExportDecl(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Handle imports
|
||||
// ====================
|
||||
|
||||
// Prepended to statements.
|
||||
let mut import_stmts = vec![];
|
||||
let mut define_deps_arg = ArrayLit {
|
||||
span: DUMMY_SP,
|
||||
elems: vec![],
|
||||
};
|
||||
|
||||
let mut factory_params = Vec::with_capacity(self.scope.imports.len() + 1);
|
||||
if emitted_esmodule {
|
||||
define_deps_arg
|
||||
.elems
|
||||
.push(Some(Lit::Str(quote_str!("exports")).as_arg()));
|
||||
factory_params.push(Pat::Ident(exports_ident.clone()));
|
||||
}
|
||||
|
||||
// Used only if export * exists
|
||||
let exported_names = {
|
||||
if !export_alls.is_empty() && !exports.is_empty() {
|
||||
let exported_names = private_ident!("_exportNames");
|
||||
stmts.push(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(exported_names.clone()),
|
||||
init: Some(box Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: exports
|
||||
.into_iter()
|
||||
.filter_map(|export| {
|
||||
if export == js_word!("default") {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(PropOrSpread::Prop(box Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(export, DUMMY_SP)),
|
||||
value: box 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 {
|
||||
stmts.push(self.scope.handle_export_all(
|
||||
exports_ident.clone(),
|
||||
exported_names.clone(),
|
||||
export,
|
||||
));
|
||||
}
|
||||
|
||||
if !initialized.is_empty() {
|
||||
stmts.push(Stmt::Expr(initialize_to_undefined(
|
||||
exports_ident.clone(),
|
||||
initialized,
|
||||
)));
|
||||
}
|
||||
|
||||
for (src, import) in self.scope.value.imports.drain(..) {
|
||||
let import = import.unwrap_or_else(|| {
|
||||
(
|
||||
local_name_for_src(&src),
|
||||
DUMMY_SP.apply_mark(Mark::fresh(Mark::root())),
|
||||
)
|
||||
});
|
||||
let ident = Ident::new(import.0.clone(), import.1);
|
||||
|
||||
define_deps_arg
|
||||
.elems
|
||||
.push(Some(Lit::Str(quote_str!(src.clone())).as_arg()));
|
||||
factory_params.push(Pat::Ident(ident.clone()));
|
||||
|
||||
{
|
||||
// handle interop
|
||||
let ty = self.scope.value.import_types.get(&src);
|
||||
|
||||
match ty {
|
||||
Some(&wildcard) => {
|
||||
let right = box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: if wildcard {
|
||||
helper!(interop_require_wildcard);
|
||||
quote_ident!("_interopRequireWildcard").as_callee()
|
||||
} else {
|
||||
helper!(interop_require_default);
|
||||
quote_ident!("_interopRequireDefault").as_callee()
|
||||
},
|
||||
args: vec![ident.clone().as_arg()],
|
||||
type_args: Default::default(),
|
||||
});
|
||||
|
||||
import_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(ident.clone())),
|
||||
op: op!("="),
|
||||
right,
|
||||
})));
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
prepend_stmts(&mut stmts, import_stmts.into_iter());
|
||||
stmts.append(&mut extra_stmts);
|
||||
|
||||
// ====================
|
||||
// Emit
|
||||
// ====================
|
||||
|
||||
Module {
|
||||
span: module.span,
|
||||
body: vec![ModuleItem::Stmt(Stmt::Expr(box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: quote_ident!("define").as_callee(),
|
||||
args: self
|
||||
.config
|
||||
.module_id
|
||||
.clone()
|
||||
.map(|s| quote_str!(s).as_arg())
|
||||
.into_iter()
|
||||
.chain(iter::once(define_deps_arg.as_arg()))
|
||||
.chain(iter::once(
|
||||
FnExpr {
|
||||
ident: None,
|
||||
function: Function {
|
||||
span: DUMMY_SP,
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
decorators: Default::default(),
|
||||
params: factory_params,
|
||||
body: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts,
|
||||
}),
|
||||
type_params: Default::default(),
|
||||
return_type: Default::default(),
|
||||
},
|
||||
}
|
||||
.as_arg(),
|
||||
))
|
||||
.collect(),
|
||||
type_args: Default::default(),
|
||||
})))],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Expr> for Amd {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
let exports_ident = self.exports.value.0.clone();
|
||||
|
||||
macro_rules! entry {
|
||||
($i:expr) => {
|
||||
self.scope
|
||||
.value
|
||||
.exported_vars
|
||||
.entry(($i.sym.clone(), $i.span.ctxt()))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! chain_assign {
|
||||
($entry:expr, $e:expr) => {{
|
||||
let mut e = $e;
|
||||
for i in $entry.get() {
|
||||
e = box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Expr(
|
||||
box exports_ident
|
||||
.clone()
|
||||
.member(Ident::new(i.0.clone(), DUMMY_SP.with_ctxt(i.1))),
|
||||
),
|
||||
op: op!("="),
|
||||
right: e,
|
||||
});
|
||||
}
|
||||
e
|
||||
}};
|
||||
}
|
||||
|
||||
match expr {
|
||||
Expr::Ident(i) => {
|
||||
let v = self.scope.value.idents.get(&(i.sym.clone(), i.span.ctxt()));
|
||||
match v {
|
||||
None => return Expr::Ident(i),
|
||||
Some((src, prop)) => {
|
||||
let (ident, span) = self
|
||||
.scope
|
||||
.value
|
||||
.imports
|
||||
.get(src)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
let obj = {
|
||||
let ident = Ident::new(ident.clone(), *span);
|
||||
|
||||
Expr::Ident(ident)
|
||||
};
|
||||
|
||||
if *prop == js_word!("") {
|
||||
// import * as foo from 'foo';
|
||||
obj
|
||||
} else {
|
||||
obj.member(Ident::new(prop.clone(), DUMMY_SP))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Member(e) => {
|
||||
if e.computed {
|
||||
Expr::Member(MemberExpr {
|
||||
obj: e.obj.fold_with(self),
|
||||
prop: e.prop.fold_with(self),
|
||||
..e
|
||||
})
|
||||
} else {
|
||||
Expr::Member(MemberExpr {
|
||||
obj: e.obj.fold_with(self),
|
||||
..e
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Update(UpdateExpr {
|
||||
span,
|
||||
arg: box Expr::Ident(arg),
|
||||
op,
|
||||
prefix,
|
||||
}) => {
|
||||
let entry = entry!(arg);
|
||||
|
||||
match entry {
|
||||
Entry::Occupied(entry) => {
|
||||
let e = chain_assign!(
|
||||
entry,
|
||||
box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(arg.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: box Expr::Unary(UnaryExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!(unary, "+"),
|
||||
arg: box Expr::Ident(arg)
|
||||
}),
|
||||
op: match op {
|
||||
op!("++") => op!(bin, "+"),
|
||||
op!("--") => op!(bin, "-"),
|
||||
},
|
||||
right: box Expr::Lit(Lit::Num(Number {
|
||||
span: DUMMY_SP,
|
||||
value: 1.0,
|
||||
})),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
*e
|
||||
}
|
||||
_ => {
|
||||
return Expr::Update(UpdateExpr {
|
||||
span,
|
||||
arg: box Expr::Ident(arg),
|
||||
op,
|
||||
prefix,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Assign(expr) => {
|
||||
//
|
||||
|
||||
match expr.left {
|
||||
PatOrExpr::Pat(box Pat::Ident(ref i)) => {
|
||||
let entry = entry!(i);
|
||||
|
||||
match entry {
|
||||
Entry::Occupied(entry) => {
|
||||
let e = chain_assign!(entry, box Expr::Assign(expr));
|
||||
|
||||
*e
|
||||
}
|
||||
_ => {
|
||||
return Expr::Assign(AssignExpr {
|
||||
left: expr.left,
|
||||
..expr
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mut found = vec![];
|
||||
let mut v = DestructuringFinder { found: &mut found };
|
||||
expr.left.visit_with(&mut v);
|
||||
if v.found.is_empty() {
|
||||
return Expr::Assign(AssignExpr {
|
||||
left: expr.left,
|
||||
..expr
|
||||
});
|
||||
}
|
||||
|
||||
let mut exprs = iter::once(box Expr::Assign(expr))
|
||||
.chain(
|
||||
found
|
||||
.into_iter()
|
||||
.map(|var| Ident::new(var.0, var.1))
|
||||
.filter_map(|i| {
|
||||
let entry = match entry!(i) {
|
||||
Entry::Occupied(entry) => entry,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let e = chain_assign!(entry, box Expr::Ident(i));
|
||||
|
||||
// exports.name = x
|
||||
Some(e)
|
||||
}),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
if exprs.len() == 1 {
|
||||
return *exprs.pop().unwrap();
|
||||
}
|
||||
|
||||
Expr::Seq(SeqExpr {
|
||||
span: DUMMY_SP,
|
||||
exprs,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => expr.fold_children(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<VarDecl> for Amd {
|
||||
///
|
||||
/// - collects all declared variables for let and var.
|
||||
fn fold(&mut self, var: VarDecl) -> VarDecl {
|
||||
if var.kind != VarDeclKind::Const {
|
||||
var.decls.visit_with(&mut VarCollector {
|
||||
to: &mut self.scope.value.declared_vars,
|
||||
});
|
||||
}
|
||||
|
||||
VarDecl {
|
||||
decls: var.decls.fold_with(self),
|
||||
..var
|
||||
}
|
||||
}
|
||||
}
|
988
ecmascript/transforms/src/modules/amd/tests.rs
Normal file
988
ecmascript/transforms/src/modules/amd/tests.rs
Normal file
@ -0,0 +1,988 @@
|
||||
use super::{amd, Config};
|
||||
use ast::Module;
|
||||
use swc_common::Fold;
|
||||
use swc_ecma_parser::Syntax;
|
||||
|
||||
fn syntax() -> Syntax {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn tr(config: Config) -> impl Fold<Module> {
|
||||
amd(config)
|
||||
}
|
||||
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Config {
|
||||
module_id: Some("moduleId".into()),
|
||||
..Default::default()
|
||||
}),
|
||||
custom_named_define,
|
||||
r#"
|
||||
import {foo} from 'src';
|
||||
export {foo};
|
||||
"#,
|
||||
r#"define('moduleId', ['exports', 'src'], function(_exports, _src) {
|
||||
'use strict';
|
||||
Object.defineProperty(_exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, 'foo', {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return _src.foo;
|
||||
}
|
||||
});
|
||||
});
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_4
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_4,
|
||||
r#"
|
||||
export default foo;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var _default = foo;
|
||||
_exports.default = _default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_from_2
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_from_2,
|
||||
r#"
|
||||
export {foo} from "foo";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "foo", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.foo;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_named_2
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_named_2,
|
||||
r#"
|
||||
var foo, bar;
|
||||
export {foo, bar};
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.bar = _exports.foo = void 0;
|
||||
var foo, bar;
|
||||
_exports.foo = foo;
|
||||
_exports.bar = bar;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// imports_default
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
imports_default,
|
||||
r#"
|
||||
import foo from "foo";
|
||||
import {default as foo2} from "foo";
|
||||
|
||||
foo;
|
||||
foo2;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo = babelHelpers.interopRequireDefault(_foo);
|
||||
_foo.default;
|
||||
_foo.default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// imports_mixing
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
imports_mixing,
|
||||
r#"
|
||||
import foo, {baz as xyz} from "foo";
|
||||
|
||||
foo;
|
||||
xyz;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo = babelHelpers.interopRequireWildcard(_foo);
|
||||
_foo.default;
|
||||
_foo.baz;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_9
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_9,
|
||||
r#"
|
||||
var foo;
|
||||
export { foo as default };
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var foo;
|
||||
_exports.default = foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// noInterop_export_from
|
||||
|
||||
// amd
|
||||
|
||||
// export_default
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default,
|
||||
r#"
|
||||
export default 42;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var _default = 42;
|
||||
_exports.default = _default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_2
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_2,
|
||||
r#"
|
||||
export default {};
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var _default = {};
|
||||
_exports.default = _default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_from_4
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_from_4,
|
||||
r#"
|
||||
export {foo as bar} from "foo";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "bar", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.foo;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_named
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_named,
|
||||
r#"
|
||||
var foo;
|
||||
export {foo};
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.foo = void 0;
|
||||
var foo;
|
||||
_exports.foo = foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// noInterop_import_default_only
|
||||
|
||||
// export_from
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_from,
|
||||
r#"
|
||||
export * from "foo";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.keys(_foo).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
Object.defineProperty(_exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_7
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_7,
|
||||
r#"
|
||||
export default function foo () {}
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = foo;
|
||||
|
||||
function foo() {}
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_named_4
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_named_4,
|
||||
r#"
|
||||
var foo;
|
||||
export {foo as default};
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var foo;
|
||||
_exports.default = foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// imports_glob
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
imports_glob,
|
||||
r#"
|
||||
import * as foo from "foo";
|
||||
|
||||
foo;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["foo"], function (foo) {
|
||||
"use strict";
|
||||
|
||||
foo = babelHelpers.interopRequireWildcard(foo);
|
||||
foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// remap
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
remap,
|
||||
r#"
|
||||
export var test = 2;
|
||||
test = 5;
|
||||
test++;
|
||||
|
||||
(function () {
|
||||
var test = 2;
|
||||
test = 3;
|
||||
test++;
|
||||
})();
|
||||
|
||||
var a = 2;
|
||||
export { a };
|
||||
a = 3;
|
||||
|
||||
var b = 2;
|
||||
export { b as c };
|
||||
b = 3;
|
||||
|
||||
var d = 3;
|
||||
export { d as e, d as f };
|
||||
d = 4;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.f = _exports.e = _exports.c = _exports.a = _exports.test = void 0;
|
||||
var test = 2;
|
||||
_exports.test = test;
|
||||
_exports.test = test = 5;
|
||||
_exports.test = test = test + 1;
|
||||
|
||||
(function () {
|
||||
var test = 2;
|
||||
test = 3;
|
||||
test++;
|
||||
})();
|
||||
|
||||
var a = 2;
|
||||
_exports.a = a;
|
||||
_exports.a = a = 3;
|
||||
var b = 2;
|
||||
_exports.c = b;
|
||||
_exports.c = b = 3;
|
||||
var d = 3;
|
||||
_exports.f = _exports.e = d;
|
||||
_exports.f = _exports.e = d = 4;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// regression_4192
|
||||
|
||||
// imports
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
imports,
|
||||
r#"
|
||||
import "foo";
|
||||
import "foo-bar";
|
||||
import "./directory/foo-bar";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["foo", "foo-bar", "./directory/foo-bar"], function (_foo, _fooBar, _fooBar2) {
|
||||
"use strict";
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_from_3
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_from_3,
|
||||
r#"
|
||||
export {foo, bar} from "foo";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "foo", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.foo;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(_exports, "bar", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.bar;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_5
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_5,
|
||||
r#"
|
||||
export default function () {}
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = _default;
|
||||
|
||||
function _default() {}
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_10
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_10,
|
||||
r#"
|
||||
export default (function(){return "foo"})();
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
|
||||
var _default = function () {
|
||||
return "foo";
|
||||
}();
|
||||
|
||||
_exports.default = _default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_named_3
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_named_3,
|
||||
r#"
|
||||
var foo;
|
||||
export {foo as bar};
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.bar = void 0;
|
||||
var foo;
|
||||
_exports.bar = foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// overview
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
overview,
|
||||
r#"
|
||||
import "foo";
|
||||
import "foo-bar";
|
||||
import "./directory/foo-bar";
|
||||
import foo from "foo";
|
||||
import * as foo2 from "foo";
|
||||
import {bar} from "foo";
|
||||
import {foo as bar2} from "foo";
|
||||
|
||||
var test;
|
||||
export {test};
|
||||
export var test2 = 5;
|
||||
|
||||
export default test;
|
||||
|
||||
foo;
|
||||
foo2;
|
||||
bar;
|
||||
bar2;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo", "foo-bar", "./directory/foo-bar"],
|
||||
function (_exports, foo2, _fooBar, _fooBar2) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = _exports.test2 = _exports.test = void 0;
|
||||
foo2 = babelHelpers.interopRequireWildcard(foo2);
|
||||
var test;
|
||||
_exports.test = test;
|
||||
var test2 = 5;
|
||||
_exports.test2 = test2;
|
||||
var _default = test;
|
||||
_exports.default = _default;
|
||||
foo2.default;
|
||||
foo2;
|
||||
foo2.bar;
|
||||
foo2.foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_from_6
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_from_6,
|
||||
r#"
|
||||
export {foo as default, bar} from "foo";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.foo;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(_exports, "bar", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.bar;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// hoist_function_exports
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
hoist_function_exports,
|
||||
r#"
|
||||
import { isEven } from "./evens";
|
||||
|
||||
export function nextOdd(n) {
|
||||
return isEven(n) ? n + 1 : n + 2;
|
||||
}
|
||||
|
||||
export var isOdd = (function (isEven) {
|
||||
return function (n) {
|
||||
return !isEven(n);
|
||||
};
|
||||
})(isEven);
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "./evens"], function (_exports, _evens) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.nextOdd = nextOdd;
|
||||
_exports.isOdd = void 0;
|
||||
|
||||
function nextOdd(n) {
|
||||
return _evens.isEven(n) ? n + 1 : n + 2;
|
||||
}
|
||||
|
||||
var isOdd = function (isEven) {
|
||||
return function (n) {
|
||||
return !isEven(n);
|
||||
};
|
||||
}(_evens.isEven);
|
||||
|
||||
_exports.isOdd = isOdd;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_8
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_8,
|
||||
r#"
|
||||
export default class Foo {}
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
|
||||
class Foo {}
|
||||
|
||||
_exports.default = Foo;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_from_5
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_from_5,
|
||||
r#"
|
||||
export {foo as default} from "foo";
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.foo;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_3
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_3,
|
||||
r#"
|
||||
export default [];
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var _default = [];
|
||||
_exports.default = _default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// import_order
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
import_order,
|
||||
r#"
|
||||
import './foo';
|
||||
import bar from './bar';
|
||||
import './derp';
|
||||
import { qux } from './qux';
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["./foo", "./bar", "./derp", "./qux"], function (_foo, _bar, _derp, _qux) {
|
||||
"use strict";
|
||||
|
||||
_bar = babelHelpers.interopRequireDefault(_bar);
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_specifier_default
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_specifier_default,
|
||||
r#"
|
||||
var a = 1;
|
||||
export { a as default };
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
var a = 1;
|
||||
_exports.default = a;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// exports_variable
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
exports_variable,
|
||||
r#"
|
||||
export var foo = 1;
|
||||
export var foo2 = 1, bar = 2;
|
||||
export var foo3 = function () {};
|
||||
export var foo4;
|
||||
export let foo5 = 2;
|
||||
export let foo6;
|
||||
export const foo7 = 3;
|
||||
export function foo8 () {}
|
||||
export class foo9 {}
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.foo8 = foo8;
|
||||
_exports.foo3 = _exports.foo4 = _exports.foo2 = _exports.foo7 = _exports.bar =
|
||||
_exports.foo = _exports.foo5 = _exports.foo6 = void 0;
|
||||
var foo = 1;
|
||||
_exports.foo = foo;
|
||||
var foo2 = 1,
|
||||
bar = 2;
|
||||
_exports.foo2 = foo2;
|
||||
_exports.bar = bar;
|
||||
|
||||
var foo3 = function () {};
|
||||
|
||||
_exports.foo3 = foo3;
|
||||
var foo4;
|
||||
_exports.foo4 = foo4;
|
||||
let foo5 = 2;
|
||||
_exports.foo5 = foo5;
|
||||
let foo6;
|
||||
_exports.foo6 = foo6;
|
||||
const foo7 = 3;
|
||||
_exports.foo7 = foo7;
|
||||
|
||||
function foo8() {}
|
||||
|
||||
class foo9 {}
|
||||
|
||||
_exports.foo9 = foo9;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// imports_named
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
imports_named,
|
||||
r#"
|
||||
import {bar} from "foo";
|
||||
import {bar2, baz} from "foo";
|
||||
import {bar as baz2} from "foo";
|
||||
import {bar as baz3, xyz} from "foo";
|
||||
|
||||
bar;
|
||||
bar2;
|
||||
baz;
|
||||
baz2;
|
||||
baz3;
|
||||
xyz;
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo.bar;
|
||||
_foo.bar2;
|
||||
_foo.baz;
|
||||
_foo.bar;
|
||||
_foo.bar;
|
||||
_foo.xyz;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// export_default_6
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_default_6,
|
||||
r#"
|
||||
export default class {}
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = void 0;
|
||||
|
||||
class _default {}
|
||||
|
||||
_exports.default = _default;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
// get_module_name_option
|
||||
|
||||
// module_name
|
||||
|
||||
// export_named_5
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Default::default()),
|
||||
export_named_5,
|
||||
r#"
|
||||
var foo, bar;
|
||||
export {foo as default, bar};
|
||||
|
||||
"#,
|
||||
r#"
|
||||
define(["exports"], function (_exports) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = _exports.bar = void 0;
|
||||
var foo, bar;
|
||||
_exports.default = foo;
|
||||
_exports.bar = bar;
|
||||
});
|
||||
|
||||
"#
|
||||
);
|
@ -16,7 +16,7 @@ use swc_common::{Fold, FoldWith, VisitWith, DUMMY_SP};
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
#[serde(default)]
|
||||
@ -44,7 +44,7 @@ const fn default_strict_mode() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged, deny_unknown_fields, rename_all = "camelCase")]
|
||||
pub enum Lazy {
|
||||
Bool(bool),
|
||||
|
@ -34,6 +34,33 @@ var foo = 2;
|
||||
exports.foo = foo;
|
||||
exports.foo = foo = 3;
|
||||
|
||||
"#
|
||||
);
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(Config {
|
||||
..Default::default()
|
||||
}),
|
||||
custom_02,
|
||||
r#"
|
||||
export const good = {
|
||||
a(bad1) {
|
||||
(...bad2) => { };
|
||||
}
|
||||
};"#,
|
||||
r#"
|
||||
'use strict';
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
exports.good = void 0;
|
||||
const good = {
|
||||
a (bad1) {
|
||||
(...bad2)=>{};
|
||||
}
|
||||
};
|
||||
exports.good = good;
|
||||
|
||||
"#
|
||||
);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod amd;
|
||||
pub mod common_js;
|
||||
pub mod umd;
|
||||
mod util;
|
||||
|
@ -10,7 +10,7 @@ use swc_common::{
|
||||
};
|
||||
use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
|
||||
|
||||
#[derive(Default, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
#[serde(default)]
|
||||
|
@ -2,7 +2,7 @@ use self::config::BuiltConfig;
|
||||
pub use self::config::Config;
|
||||
use super::util::{
|
||||
define_es_module, define_property, initialize_to_undefined, local_name_for_src,
|
||||
make_descriptor, make_require_call, use_strict, Scope, VarCollector,
|
||||
make_descriptor, make_require_call, use_strict, Exports, Scope, VarCollector,
|
||||
};
|
||||
use crate::{
|
||||
pass::Pass,
|
||||
@ -35,14 +35,6 @@ struct Umd {
|
||||
exports: State<Exports>,
|
||||
}
|
||||
|
||||
struct Exports(Ident);
|
||||
|
||||
impl Default for Exports {
|
||||
fn default() -> Self {
|
||||
Exports(private_ident!("_exports"))
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Module> for Umd {
|
||||
fn fold(&mut self, module: Module) -> Module {
|
||||
let filename = self.cm.span_to_filename(module.span);
|
||||
|
@ -423,6 +423,25 @@ impl<'a> Visit<Ident> for VarCollector<'a> {
|
||||
self.to.push((i.sym.clone(), i.span.ctxt()))
|
||||
}
|
||||
}
|
||||
impl<'a> Visit<Expr> for VarCollector<'a> {
|
||||
fn visit(&mut self, _: &Expr) {}
|
||||
|
||||
macro_rules! var_noop {
|
||||
($T:path) => {
|
||||
impl<'a> Visit<$T> for VarCollector<'a> {
|
||||
fn visit(&mut self, _: &$T) {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var_noop!(Expr);
|
||||
var_noop!(ArrowExpr);
|
||||
var_noop!(Function);
|
||||
var_noop!(Constructor);
|
||||
|
||||
/// Private `_exports` ident.
|
||||
pub(super) struct Exports(pub Ident);
|
||||
|
||||
impl Default for Exports {
|
||||
fn default() -> Self {
|
||||
Exports(private_ident!("_exports"))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user