refactor(es): Use into for AST construction (#9197)

**Description:**

This PR changes the AST node construction code to use `.into()` or `::from()` to make changing the boxed-ness of the AST node easier. I used `ast-grep` to make large changes across codebase.
This commit is contained in:
Donny/강동윤 2024-07-10 22:57:22 +09:00
parent a7d236c162
commit e7358e0f81
138 changed files with 3685 additions and 2789 deletions

View File

@ -108,7 +108,7 @@ fn wrap_module(
}
// ... body of foo
let module_fn = Expr::Fn(FnExpr {
let module_fn: Expr = FnExpr {
ident: None,
function: Box::new(Function {
params: vec![
@ -145,7 +145,8 @@ fn wrap_module(
is_async: false,
..Default::default()
}),
});
}
.into();
// var load = __swcpack_require__.bind(void 0, moduleDecl)
@ -355,15 +356,12 @@ impl VisitMut for DefaultHandler {
if let Expr::Ident(i) = e {
if i.sym == "default" {
*e = Expr::Member(MemberExpr {
*e = MemberExpr {
span: i.span,
obj: Box::new(Expr::Ident(Ident::new(
"module".into(),
DUMMY_SP,
self.local_ctxt,
))),
obj: Ident::new("module".into(), DUMMY_SP, self.local_ctxt).into(),
prop: MemberProp::Ident(quote_ident!("exports")),
});
}
.into();
}
}
}

View File

@ -114,10 +114,13 @@ where
let return_stmt = Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: take(&mut export_visitor.return_props),
}))),
arg: Some(
ObjectLit {
span: DUMMY_SP,
props: take(&mut export_visitor.return_props),
}
.into(),
),
});
module.iter().for_each(|(_, v)| {
@ -131,7 +134,7 @@ where
}
});
let module_fn = Expr::Fn(FnExpr {
let module_fn: Expr = FnExpr {
function: Box::new(Function {
params: Default::default(),
body: Some(BlockStmt {
@ -144,20 +147,23 @@ where
..Default::default()
}),
ident: None,
});
}
.into();
let mut module_expr = Expr::Call(CallExpr {
let mut module_expr = CallExpr {
span: DUMMY_SP,
callee: module_fn.as_callee(),
args: Default::default(),
..Default::default()
});
}
.into();
if is_async {
module_expr = Expr::Await(AwaitExpr {
module_expr = AwaitExpr {
span: DUMMY_SP,
arg: Box::new(module_expr),
});
}
.into();
}
let var_decl = VarDecl {
@ -208,7 +214,7 @@ impl ExportToReturn {
self.return_props
.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(key.into()),
value: Box::new(Expr::Ident(value)),
value: value.into(),
}))));
}
}

View File

@ -693,7 +693,7 @@ where
))
}
None => {
let init = Expr::Class(c);
let init = c;
new.push(init.assign_to(local.clone()).into_module_item(
injected_ctxt,
"prepare -> export default decl -> class -> without \
@ -974,17 +974,20 @@ where
vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(mod_var.clone().into()),
init: Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: Ident::new(
"load".into(),
DUMMY_SP,
dep.export_ctxt(),
)
.as_callee(),
..Default::default()
}))),
name: mod_var.clone().into(),
init: Some(
CallExpr {
span: DUMMY_SP,
callee: Ident::new(
"load".into(),
DUMMY_SP,
dep.export_ctxt(),
)
.as_callee(),
..Default::default()
}
.into(),
),
definite: Default::default(),
});
for s in specifiers {
@ -994,10 +997,8 @@ where
ModuleExportName::Ident(name) => {
vars.push(VarDeclarator {
span: s.span,
name: Pat::Ident(name.clone().into()),
init: Some(Box::new(Expr::Ident(
mod_var.clone(),
))),
name: name.clone().into(),
init: Some(mod_var.clone().into()),
definite: Default::default(),
});
}
@ -1011,7 +1012,7 @@ where
ExportSpecifier::Default(s) => {
vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(s.exported.clone().into()),
name: s.exported.clone().into(),
init: Some(
mod_var
.clone()
@ -1042,9 +1043,7 @@ where
};
vars.push(VarDeclarator {
span: s.span,
name: Pat::Ident(
exported.clone().unwrap().into(),
),
name: exported.clone().unwrap().into(),
init: Some(
mod_var
.clone()
@ -1339,7 +1338,7 @@ impl VisitMut for ImportMetaHandler<'_, '_> {
..
}) = e
{
*e = Expr::Ident(self.inline_ident.clone());
*e = self.inline_ident.clone().into();
self.occurred = true;
}
}

View File

@ -210,7 +210,7 @@ where
"default".into(),
DUMMY_SP,
)),
value: Box::new(Expr::Ident(s.exported)),
value: s.exported.into(),
},
))));
}
@ -225,7 +225,7 @@ where
props.push(PropOrSpread::Prop(Box::new(
Prop::KeyValue(KeyValueProp {
key: PropName::Ident(exported.into()),
value: Box::new(Expr::Ident(orig)),
value: orig.into(),
}),
)));
}
@ -262,7 +262,7 @@ where
"default".into(),
export.span,
)),
value: Box::new(Expr::Ident(ident.clone())),
value: ident.clone().into(),
},
))));
@ -283,7 +283,7 @@ where
"default".into(),
export.span,
)),
value: Box::new(Expr::Ident(ident.clone())),
value: ident.clone().into(),
},
))));
@ -302,7 +302,7 @@ where
))));
let var = VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(default_var.into()),
name: default_var.into(),
init: Some(export.expr),
definite: false,
};
@ -323,10 +323,13 @@ where
};
body.stmts.push(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props,
}))),
arg: Some(
ObjectLit {
span: DUMMY_SP,
props,
}
.into(),
),
}));
let f = Function {
@ -342,12 +345,13 @@ where
function: Box::new(f),
};
let iife = Box::new(Expr::Call(CallExpr {
let iife = CallExpr {
span: DUMMY_SP,
callee: invoked_fn_expr.as_callee(),
args: Default::default(),
..Default::default()
}));
}
.into();
Module {
span: DUMMY_SP,

View File

@ -356,7 +356,7 @@ where
};
prop.ctxt = self.imported_idents.get(&obj.to_id()).copied().unwrap();
*e = Expr::Ident(prop);
*e = prop.into();
}
}

View File

@ -91,17 +91,18 @@ impl VisitMut for KeywordRenamer {
Some(default) => {
*n = ObjectPatProp::KeyValue(KeyValuePatProp {
key: PropName::Ident(pat.key.take().into()),
value: Box::new(Pat::Assign(AssignPat {
value: AssignPat {
span: pat.span,
left: Box::new(Pat::Ident(renamed.into())),
left: Box::new(renamed.into()),
right: default.take(),
})),
}
.into(),
});
}
None => {
*n = ObjectPatProp::KeyValue(KeyValuePatProp {
key: PropName::Ident(pat.key.take().into()),
value: Box::new(Pat::Ident(renamed.into())),
value: renamed.into(),
})
}
}
@ -134,7 +135,7 @@ impl VisitMut for KeywordRenamer {
if let Some(renamed) = self.renamed(i) {
*n = Prop::KeyValue(KeyValueProp {
key: PropName::Ident(i.clone().into()),
value: Box::new(Expr::Ident(renamed)),
value: renamed.into(),
});
}
}

View File

@ -127,6 +127,6 @@ impl From<Id> for Ident {
impl From<Id> for Expr {
#[inline]
fn from(id: Id) -> Self {
Expr::Ident(id.into_ident())
id.into_ident().into()
}
}

View File

@ -121,7 +121,7 @@ impl VisitMut for Inliner {
if i.sym != orig.sym {
*n = Prop::KeyValue(KeyValueProp {
key: PropName::Ident(orig.into()),
value: Box::new(Expr::Ident(i.clone())),
value: i.clone().into(),
});
}
}

View File

@ -58,7 +58,7 @@ pub(crate) trait ExprExt: Into<Expr> {
VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(Ident::new(lhs.0, DUMMY_SP, lhs.1).into()),
name: Ident::new(lhs.0, DUMMY_SP, lhs.1).into(),
init: Some(Box::new(init)),
definite: false,
}
@ -184,11 +184,12 @@ impl<T> IntoParallelIterator for T where T: IntoIterator {}
fn metadata(key: &str, value: &str) -> PropOrSpread {
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(IdentName::new(key.into(), DUMMY_SP)),
value: Box::new(Expr::Lit(Lit::Str(Str {
value: Lit::Str(Str {
span: DUMMY_SP,
value: value.into(),
raw: None,
}))),
})
.into(),
})))
}

View File

@ -302,10 +302,11 @@ impl Expr {
if exprs.len() == 1 {
exprs.remove(0)
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
}))
}
.into()
}
}
@ -418,7 +419,7 @@ impl Clone for Expr {
impl Take for Expr {
fn dummy() -> Self {
Expr::Invalid(Invalid { span: DUMMY_SP })
Invalid { span: DUMMY_SP }.into()
}
}
@ -469,12 +470,14 @@ boxed_expr!(JSXEmptyExpr);
boxed_expr!(Box<JSXElement>);
boxed_expr!(JSXFragment);
boxed_expr!(TsTypeAssertion);
boxed_expr!(TsSatisfiesExpr);
boxed_expr!(TsConstAssertion);
boxed_expr!(TsNonNullExpr);
boxed_expr!(TsAsExpr);
boxed_expr!(TsInstantiation);
boxed_expr!(PrivateName);
boxed_expr!(OptChainExpr);
boxed_expr!(Invalid);
#[ast_node("ThisExpression")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
@ -567,7 +570,7 @@ impl From<ImportWith> for ObjectLit {
.map(|item| {
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(item.key),
value: Box::new(Expr::Lit(Lit::Str(item.value))),
value: Lit::Str(item.value).into(),
})))
})
.collect(),
@ -1387,7 +1390,7 @@ impl TryFrom<Pat> for AssignTarget {
Pat::Expr(e) => match Self::try_from(e) {
Ok(v) => v,
Err(e) => return Err(Pat::Expr(e)),
Err(e) => return Err(e.into()),
},
_ => return Err(p),
@ -1437,9 +1440,9 @@ impl Default for AssignTargetPat {
impl From<AssignTargetPat> for Pat {
fn from(pat: AssignTargetPat) -> Self {
match pat {
AssignTargetPat::Array(a) => Pat::Array(a),
AssignTargetPat::Object(o) => Pat::Object(o),
AssignTargetPat::Invalid(i) => Pat::Invalid(i),
AssignTargetPat::Array(a) => a.into(),
AssignTargetPat::Object(o) => o.into(),
AssignTargetPat::Invalid(i) => i.into(),
}
}
}
@ -1551,17 +1554,17 @@ bridge_from!(AssignTarget, AssignTargetPat, ObjectPat);
impl From<SimpleAssignTarget> for Box<Expr> {
fn from(s: SimpleAssignTarget) -> Self {
match s {
SimpleAssignTarget::Ident(i) => Box::new(Expr::Ident(i.into())),
SimpleAssignTarget::Member(m) => Box::new(Expr::Member(m)),
SimpleAssignTarget::SuperProp(s) => Box::new(Expr::SuperProp(s)),
SimpleAssignTarget::Paren(s) => Box::new(Expr::Paren(s)),
SimpleAssignTarget::OptChain(s) => Box::new(Expr::OptChain(s)),
SimpleAssignTarget::TsAs(a) => Box::new(Expr::TsAs(a)),
SimpleAssignTarget::TsSatisfies(s) => Box::new(Expr::TsSatisfies(s)),
SimpleAssignTarget::TsNonNull(n) => Box::new(Expr::TsNonNull(n)),
SimpleAssignTarget::TsTypeAssertion(a) => Box::new(Expr::TsTypeAssertion(a)),
SimpleAssignTarget::TsInstantiation(a) => Box::new(Expr::TsInstantiation(a)),
SimpleAssignTarget::Invalid(i) => Box::new(Expr::Invalid(i)),
SimpleAssignTarget::Ident(i) => i.into(),
SimpleAssignTarget::Member(m) => m.into(),
SimpleAssignTarget::SuperProp(s) => s.into(),
SimpleAssignTarget::Paren(s) => s.into(),
SimpleAssignTarget::OptChain(s) => s.into(),
SimpleAssignTarget::TsAs(a) => a.into(),
SimpleAssignTarget::TsSatisfies(s) => s.into(),
SimpleAssignTarget::TsNonNull(n) => n.into(),
SimpleAssignTarget::TsTypeAssertion(a) => a.into(),
SimpleAssignTarget::TsInstantiation(a) => a.into(),
SimpleAssignTarget::Invalid(i) => i.into(),
}
}
}

View File

@ -55,7 +55,7 @@ impl Clone for Pat {
impl Default for Pat {
fn default() -> Self {
Pat::Invalid(Invalid { span: DUMMY_SP })
Invalid { span: DUMMY_SP }.into()
}
}
impl Take for Pat {
@ -80,6 +80,7 @@ pat_to_other!(ArrayPat);
pat_to_other!(ObjectPat);
pat_to_other!(AssignPat);
pat_to_other!(RestPat);
pat_to_other!(Box<Expr>);
#[ast_node("ArrayPattern")]
#[derive(Eq, Hash, EqIgnoreSpan)]

View File

@ -44,11 +44,12 @@ impl VisitMut for EdgeDefaultParam {
{
let prop = ObjectPatProp::KeyValue(KeyValuePatProp {
key: PropName::Ident(key.clone().into()),
value: Box::new(Pat::Assign(AssignPat {
value: AssignPat {
span: *span,
left: key.clone().into(),
right: value.clone(),
})),
}
.into(),
});
n.props[idx] = prop;

View File

@ -70,14 +70,17 @@ impl Fold for TemplateLiteralCaching {
self.helper_ident = Some(helper_ident.clone());
self.create_binding(
helper_ident,
Some(Expr::Arrow(ArrowExpr {
span: DUMMY_SP,
params: vec![t.clone().into()],
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Ident(t)))),
is_async: false,
is_generator: false,
..Default::default()
})),
Some(
ArrowExpr {
span: DUMMY_SP,
params: vec![t.clone().into()],
body: Box::new(BlockStmtOrExpr::Expr(t.into())),
is_async: false,
is_generator: false,
..Default::default()
}
.into(),
),
)
}
@ -88,7 +91,7 @@ impl Fold for TemplateLiteralCaching {
// the same shape. identity`a${0}`
let template = TaggedTpl {
span: DUMMY_SP,
tag: Box::new(Expr::Ident(helper_ident.clone())),
tag: helper_ident.clone().into(),
tpl: Box::new(Tpl {
span: DUMMY_SP,
quasis: n.tpl.quasis,
@ -101,23 +104,25 @@ impl Fold for TemplateLiteralCaching {
// _t || (_t = identity`a${0}`)
let t = private_ident!("t");
self.create_binding(t.clone(), None);
let inline_cache = Expr::Bin(BinExpr {
let inline_cache: Expr = BinExpr {
span: DUMMY_SP,
op: op!("||"),
left: Box::new(Expr::Ident(t.clone())),
right: Box::new(Expr::Assign(AssignExpr {
left: t.clone().into(),
right: AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: t.into(),
right: Box::new(Expr::TaggedTpl(template)),
})),
});
}
.into(),
}
.into();
// The original tag function becomes a plain function call.
// The expressions omitted from the cached Strings tag are
// directly applied as arguments.
// tag(_t || (_t = Object`a${0}`), 'hello')
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: n.tag.as_callee(),
args: vec![inline_cache.as_arg()]
@ -125,7 +130,8 @@ impl Fold for TemplateLiteralCaching {
.chain(n.tpl.exprs.into_iter().map(|expr| expr.as_arg()))
.collect(),
..Default::default()
})
}
.into()
}
_ => n,
}

View File

@ -267,10 +267,11 @@ impl BlockScoping {
}
if !inits.is_empty() {
call = Expr::Seq(SeqExpr {
call = SeqExpr {
span: DUMMY_SP,
exprs: inits.into_iter().chain(once(Box::new(call))).collect(),
})
}
.into()
}
if flow_helper.has_return || flow_helper.has_break || !flow_helper.label.is_empty() {
@ -297,7 +298,7 @@ impl BlockScoping {
stmts.push(
IfStmt {
span: DUMMY_SP,
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
op: op!("==="),
left: {
@ -314,7 +315,8 @@ impl BlockScoping {
},
//"object"
right: "object".into(),
})),
}
.into(),
cons: Box::new(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(ret.clone().make_member(quote_ident!("v")).into()),
@ -792,11 +794,14 @@ impl VisitMut for FlowHelper<'_> {
};
*node = Stmt::Return(ReturnStmt {
span,
arg: Some(Box::new(Expr::Lit(Lit::Str(Str {
span,
value,
raw: None,
})))),
arg: Some(
Lit::Str(Str {
span,
value,
raw: None,
})
.into(),
),
});
}
Stmt::Return(s) => {
@ -805,19 +810,24 @@ impl VisitMut for FlowHelper<'_> {
*node = Stmt::Return(ReturnStmt {
span,
arg: Some(Box::new(Expr::Object(ObjectLit {
span,
props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(IdentName::new("v".into(), DUMMY_SP)),
value: s.arg.take().unwrap_or_else(|| {
Box::new(Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: Expr::undefined(DUMMY_SP),
}))
}),
})))],
}))),
arg: Some(
ObjectLit {
span,
props: vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(
KeyValueProp {
key: PropName::Ident(IdentName::new("v".into(), DUMMY_SP)),
value: s.arg.take().unwrap_or_else(|| {
Box::new(Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: Expr::undefined(DUMMY_SP),
}))
}),
},
)))],
}
.into(),
),
});
}
_ => node.visit_mut_children_with(self),
@ -869,19 +879,23 @@ impl MutationHandler<'_> {
let mut exprs = Vec::with_capacity(self.map.len() + 1);
for (id, ctxt) in &*self.map {
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: Ident::new(id.0.clone(), DUMMY_SP, id.1).into(),
op: op!("="),
right: Box::new(Expr::Ident(Ident::new(id.0.clone(), DUMMY_SP, *ctxt))),
})));
exprs.push(
AssignExpr {
span: DUMMY_SP,
left: Ident::new(id.0.clone(), DUMMY_SP, id.1).into(),
op: op!("="),
right: Box::new(Ident::new(id.0.clone(), DUMMY_SP, *ctxt).into()),
}
.into(),
);
}
exprs.push(orig.unwrap_or_else(|| Expr::undefined(DUMMY_SP)));
Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
})
}
.into()
}
}

View File

@ -209,7 +209,7 @@ impl VisitMut for ConstructorFolder<'_> {
{
let right = match self.super_var.clone() {
Some(super_var) => {
let call = Box::new(Expr::Call(CallExpr {
let call = CallExpr {
span: DUMMY_SP,
callee: if self.is_constructor_default {
super_var.make_member(quote_ident!("apply")).as_callee()
@ -228,15 +228,17 @@ impl VisitMut for ConstructorFolder<'_> {
call_args
},
..Default::default()
}));
}
.into();
if self.super_is_callable_constructor {
Box::new(Expr::Bin(BinExpr {
BinExpr {
span: DUMMY_SP,
left: call,
op: op!("||"),
right: Box::new(Expr::This(ThisExpr { span: DUMMY_SP })),
}))
right: Box::new(ThisExpr { span: DUMMY_SP }.into()),
}
.into()
} else {
call
}
@ -249,12 +251,13 @@ impl VisitMut for ConstructorFolder<'_> {
})),
};
*expr = Expr::Assign(AssignExpr {
*expr = AssignExpr {
span: DUMMY_SP,
left: quote_ident!(SyntaxContext::empty().apply_mark(self.mark), "_this").into(),
op: op!("="),
right,
});
}
.into();
};
}
@ -284,7 +287,7 @@ impl VisitMut for ConstructorFolder<'_> {
}) = &mut **expr
{
let expr = match self.super_var.clone() {
Some(super_var) => Box::new(Expr::Call(CallExpr {
Some(super_var) => CallExpr {
span: DUMMY_SP,
callee: if self.is_constructor_default {
super_var.make_member(quote_ident!("apply")).as_callee()
@ -303,7 +306,8 @@ impl VisitMut for ConstructorFolder<'_> {
call_args
},
..Default::default()
})),
}
.into(),
None => Box::new(make_possible_return_value(ReturningMode::Prototype {
is_constructor_default: self.is_constructor_default,
class_name: self.class_name.clone(),
@ -378,7 +382,7 @@ pub(super) enum ReturningMode {
pub(super) fn make_possible_return_value(mode: ReturningMode) -> Expr {
let callee = helper!(possible_constructor_return);
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee,
args: match mode {
@ -455,7 +459,8 @@ pub(super) fn make_possible_return_value(mode: ReturningMode) -> Expr {
}
},
..Default::default()
})
}
.into()
}
/// `mark`: Mark for `_this`
@ -481,14 +486,15 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: &mut Constructor) -> bo
let this = quote_ident!(SyntaxContext::empty().apply_mark(self.mark), "_this");
if self.wrap_with_assertion {
*expr = Expr::Call(CallExpr {
*expr = CallExpr {
span: DUMMY_SP,
callee: helper!(assert_this_initialized),
args: vec![this.as_arg()],
..Default::default()
})
}
.into()
} else {
*expr = Expr::Ident(this);
*expr = this.into();
}
}

View File

@ -489,10 +489,11 @@ where
prepend_stmt(&mut function.body.as_mut().unwrap().stmts, use_strict);
}
function.span = span;
return Expr::Fn(FnExpr {
return FnExpr {
ident: Some(ident),
function,
});
}
.into();
}
_ => unreachable!(),
}
@ -519,7 +520,7 @@ where
..Default::default()
};
Expr::Call(call)
call.into()
}
/// Returned `stmts` contains `return Foo`
@ -714,7 +715,7 @@ where
if is_always_initialized {
body.push(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Ident(this))),
arg: Some(this.into()),
}));
} else {
let possible_return_value =
@ -805,7 +806,7 @@ where
// `return Foo`
stmts.push(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Ident(class_name_sym))),
arg: Some(class_name_sym.into()),
}));
stmts
@ -890,17 +891,15 @@ where
Box::new(Prop::KeyValue(KeyValueProp {
key: PropName::Ident(quote_ident!(Default::default(), key.span(), "key").into()),
value: match key {
PropName::Ident(i) => Box::new(Expr::Lit(Lit::Str(quote_str!(i.span, i.sym)))),
PropName::Str(s) => Box::new(Expr::from(s)),
PropName::Num(n) => Box::new(Expr::from(n)),
PropName::BigInt(b) => Box::new(Expr::Lit(
Str {
span: b.span,
raw: None,
value: b.value.to_string().into(),
}
.into(),
)),
PropName::Ident(i) => Lit::Str(quote_str!(i.span, i.sym)).into(),
PropName::Str(s) => s.into(),
PropName::Num(n) => n.into(),
PropName::BigInt(b) => Str {
span: b.span,
raw: None,
value: b.value.to_string().into(),
}
.into(),
PropName::Computed(c) => c.expr,
},
}))
@ -911,22 +910,20 @@ where
PropName::Ident(i) => MemberProp::Ident(i),
PropName::Str(s) => MemberProp::Computed(ComputedPropName {
span: s.span,
expr: Box::new(Expr::Lit(Lit::Str(s))),
expr: Lit::Str(s).into(),
}),
PropName::Num(n) => MemberProp::Computed(ComputedPropName {
span: n.span,
expr: Box::new(Expr::Lit(Lit::Num(n))),
expr: Lit::Num(n).into(),
}),
PropName::BigInt(b) => MemberProp::Computed(ComputedPropName {
span: b.span,
expr: Box::new(Expr::Lit(
Str {
span: b.span,
raw: None,
value: b.value.to_string().into(),
}
.into(),
)),
expr: Str {
span: b.span,
raw: None,
value: b.value.to_string().into(),
}
.into(),
}),
PropName::Computed(c) => MemberProp::Computed(c),
}
@ -936,7 +933,7 @@ where
if props.is_empty() {
return quote_expr!(DUMMY_SP, null).as_arg();
}
Expr::Array(ArrayLit {
ArrayLit {
span: DUMMY_SP,
elems: props
.into_iter()
@ -969,7 +966,7 @@ where
})
.map(Some)
.collect(),
})
}
.as_arg()
}
@ -1078,7 +1075,7 @@ where
);
}
let value = Box::new(Expr::Fn(FnExpr {
let value = FnExpr {
ident: if m.kind == MethodKind::Method && !computed {
match prop_name {
Expr::Ident(ident) => Some(private_ident!(ident.span, ident.sym)),
@ -1095,7 +1092,8 @@ where
None
},
function: m.function,
}));
}
.into();
let data = append_to.entry(key).or_insert_with(|| Data {
key_prop,
@ -1153,7 +1151,7 @@ where
let prop = *v.key_prop.clone();
res.push(Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span,
op: op!("="),
left: MemberExpr {
@ -1163,7 +1161,8 @@ where
}
.into(),
right: escape_keywords(method),
})),
}
.into(),
}));
!(v.get.is_none() && v.set.is_none())
} else {
@ -1177,7 +1176,7 @@ where
let prop = *v.key_prop.clone();
res.push(Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span,
op: op!("="),
left: MemberExpr {
@ -1187,7 +1186,8 @@ where
}
.into(),
right: escape_keywords(method),
})),
}
.into(),
}));
!(v.get.is_none() && v.set.is_none())
} else {

View File

@ -76,7 +76,7 @@ impl VisitMut for ComputedProps {
let mark = Mark::fresh(Mark::root());
let obj_ident = quote_ident!(SyntaxContext::empty().apply_mark(mark), *span, "_obj");
let mut exprs = Vec::with_capacity(props.len() + 2);
let mut exprs: Vec<Box<Expr>> = Vec::with_capacity(props.len() + 2);
let mutator_map = quote_ident!(
SyntaxContext::empty().apply_mark(mark),
*span,
@ -98,20 +98,25 @@ impl VisitMut for ComputedProps {
exprs.push(
if !self.c.loose && props_cnt == 1 && !self.used_define_enum_props {
Box::new(Expr::Object(ObjectLit {
ObjectLit {
span: DUMMY_SP,
props: obj_props,
}))
}
.into()
} else {
Box::new(Expr::Assign(AssignExpr {
AssignExpr {
span: DUMMY_SP,
left: obj_ident.clone().into(),
op: op!("="),
right: Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: obj_props,
})),
}))
right: Box::new(
ObjectLit {
span: DUMMY_SP,
props: obj_props,
}
.into(),
),
}
.into()
},
);
@ -125,17 +130,18 @@ impl VisitMut for ComputedProps {
Prop::Shorthand(ident) => (
(
if self.c.loose {
Expr::Ident(ident.clone())
ident.clone().into()
} else {
Expr::Lit(Lit::Str(Str {
Lit::Str(Str {
span: ident.span,
raw: None,
value: ident.sym.clone(),
}))
})
.into()
},
false,
),
Expr::Ident(ident),
ident.into(),
),
Prop::KeyValue(KeyValueProp { key, value }) => {
(prop_name_to_expr(key, self.c.loose), *value)
@ -193,55 +199,71 @@ impl VisitMut for ComputedProps {
.computed_member(prop_name_to_expr(key, false).0);
// mutator[f] = mutator[f] || {}
exprs.push(Box::new(Expr::Assign(AssignExpr {
span,
left: mutator_elem.clone().into(),
op: op!("="),
right: Box::new(Expr::Bin(BinExpr {
exprs.push(
AssignExpr {
span,
left: mutator_elem.clone().into(),
op: op!("||"),
right: Box::new(Expr::Object(ObjectLit {
span,
props: vec![],
})),
})),
})));
op: op!("="),
right: Box::new(
BinExpr {
span,
left: mutator_elem.clone().into(),
op: op!("||"),
right: Box::new(Expr::Object(ObjectLit {
span,
props: vec![],
})),
}
.into(),
),
}
.into(),
);
// mutator[f].get = function(){}
exprs.push(Box::new(Expr::Assign(AssignExpr {
span,
left: mutator_elem
.make_member(quote_ident!(gs_prop_name.unwrap()))
.into(),
op: op!("="),
right: Box::new(Expr::Fn(FnExpr {
ident: None,
function,
})),
})));
exprs.push(
AssignExpr {
span,
left: mutator_elem
.make_member(quote_ident!(gs_prop_name.unwrap()))
.into(),
op: op!("="),
right: Box::new(
FnExpr {
ident: None,
function,
}
.into(),
),
}
.into(),
);
continue;
// unimplemented!("getter /setter property")
}
Prop::Method(MethodProp { key, function }) => (
prop_name_to_expr(key, self.c.loose),
Expr::Fn(FnExpr {
FnExpr {
ident: None,
function,
}),
}
.into(),
),
},
PropOrSpread::Spread(..) => unimplemented!("computed spread property"),
};
if !self.c.loose && props_cnt == 1 {
single_cnt_prop = Some(Expr::Call(CallExpr {
span,
callee: helper!(define_property),
args: vec![exprs.pop().unwrap().as_arg(), key.as_arg(), value.as_arg()],
..Default::default()
}));
single_cnt_prop = Some(
CallExpr {
span,
callee: helper!(define_property),
args: vec![exprs.pop().unwrap().as_arg(), key.as_arg(), value.as_arg()],
..Default::default()
}
.into(),
);
break;
}
exprs.push(if self.c.loose {
@ -250,19 +272,21 @@ impl VisitMut for ComputedProps {
} else {
obj_ident.clone().make_member(key.ident().unwrap().into())
};
Box::new(Expr::Assign(AssignExpr {
AssignExpr {
span,
op: op!("="),
left: left.into(),
right: value.into(),
}))
}
.into()
} else {
Box::new(Expr::Call(CallExpr {
CallExpr {
span,
callee: helper!(define_property),
args: vec![obj_ident.clone().as_arg(), key.as_arg(), value.as_arg()],
..Default::default()
}))
}
.into()
});
}
@ -281,26 +305,33 @@ impl VisitMut for ComputedProps {
self.vars.push(VarDeclarator {
span: DUMMY_SP,
name: mutator_map.clone().into(),
init: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: vec![],
}))),
init: Some(
ObjectLit {
span: DUMMY_SP,
props: vec![],
}
.into(),
),
definite: false,
});
exprs.push(Box::new(Expr::Call(CallExpr {
span: *span,
callee: helper!(define_enumerable_properties),
args: vec![obj_ident.clone().as_arg(), mutator_map.as_arg()],
..Default::default()
})));
exprs.push(
CallExpr {
span: *span,
callee: helper!(define_enumerable_properties),
args: vec![obj_ident.clone().as_arg(), mutator_map.as_arg()],
..Default::default()
}
.into(),
);
}
// Last value
exprs.push(Box::new(Expr::Ident(obj_ident)));
*expr = Expr::Seq(SeqExpr {
exprs.push(obj_ident.into());
*expr = SeqExpr {
span: DUMMY_SP,
exprs,
});
}
.into();
};
}
@ -380,19 +411,20 @@ fn prop_name_to_expr(p: PropName, loose: bool) -> (Expr, bool) {
match p {
PropName::Ident(i) => (
if loose {
Expr::Ident(i.into())
i.into()
} else {
Expr::Lit(Lit::Str(Str {
Lit::Str(Str {
raw: None,
value: i.sym,
span: i.span,
}))
})
.into()
},
false,
),
PropName::Str(s) => (Expr::Lit(Lit::Str(s)), true),
PropName::Num(n) => (Expr::Lit(Lit::Num(n)), true),
PropName::BigInt(b) => (Expr::Lit(Lit::BigInt(b)), true),
PropName::Str(s) => (Lit::Str(s).into(), true),
PropName::Num(n) => (Lit::Num(n).into(), true),
PropName::BigInt(b) => (Lit::BigInt(b).into(), true),
PropName::Computed(c) => (*c.expr, true),
}
}

View File

@ -178,13 +178,16 @@ impl AssignFolder {
VarDeclarator {
span: p.span(),
name: *p.arg,
init: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: arr_elems
.take()
.expect("two rest element?")
.collect(),
}))),
init: Some(
ArrayLit {
span: DUMMY_SP,
elems: arr_elems
.take()
.expect("two rest element?")
.collect(),
}
.into(),
),
definite: false,
},
);
@ -249,20 +252,23 @@ impl AssignFolder {
}) => VarDeclarator {
span: dot3_token,
name: *arg,
init: Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: ref_ident
.clone()
.make_member(quote_ident!("slice"))
.as_callee(),
args: vec![Number {
value: i as f64,
span: dot3_token,
raw: None,
init: Some(
CallExpr {
span: DUMMY_SP,
callee: ref_ident
.clone()
.make_member(quote_ident!("slice"))
.as_callee(),
args: vec![Number {
value: i as f64,
span: dot3_token,
raw: None,
}
.as_arg()],
..Default::default()
}
.as_arg()],
..Default::default()
}))),
.into(),
),
definite: false,
},
_ => VarDeclarator {
@ -339,7 +345,7 @@ impl AssignFolder {
let ref_ident = make_ref_ident(self.c, ref_decls, decl.init);
let ref_ident = if can_be_null {
let init = Box::new(Expr::Ident(ref_ident));
let init = ref_ident.into();
make_ref_ident(self.c, ref_decls, Some(init))
} else {
ref_ident
@ -507,7 +513,7 @@ impl Destructuring {
decls.push(VarDeclarator {
span,
name: param.pat,
init: Some(Box::new(Expr::Ident(ref_ident))),
init: Some(ref_ident.into()),
definite: false,
})
}
@ -570,20 +576,22 @@ impl AssignFolder {
.into(),
)];
let mut assign_cond_expr = Expr::Assign(AssignExpr {
let mut assign_cond_expr: Expr = AssignExpr {
span,
left: pat.left.take().try_into().unwrap(),
op: op!("="),
right: Box::new(make_cond_expr(ref_ident, pat.right.take())),
});
}
.into();
assign_cond_expr.visit_mut_with(self);
exprs.push(Box::new(assign_cond_expr));
Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
})
}
.into()
}
}
@ -662,18 +670,24 @@ impl VisitMut for AssignFolder {
let mut arr_elems = Some(arr.elems.take().into_iter());
elems.iter_mut().for_each(|p| match p {
Some(Pat::Rest(p)) => {
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: p.span(),
left: p.arg.take().try_into().unwrap(),
op: op!("="),
right: Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: arr_elems
.take()
.expect("two rest element?")
.collect(),
})),
})));
exprs.push(
AssignExpr {
span: p.span(),
left: p.arg.take().try_into().unwrap(),
op: op!("="),
right: Box::new(
ArrayLit {
span: DUMMY_SP,
elems: arr_elems
.take()
.expect("two rest element?")
.collect(),
}
.into(),
),
}
.into(),
);
}
Some(p) => {
let e = arr_elems
@ -692,12 +706,13 @@ impl VisitMut for AssignFolder {
let mut expr = if let Pat::Assign(pat) = p {
self.handle_assign_pat(*span, pat, &mut right)
} else {
Expr::Assign(AssignExpr {
AssignExpr {
span: p.span(),
left: p.try_into().unwrap(),
op: op!("="),
right,
})
}
.into()
};
self.visit_mut_expr(&mut expr);
@ -730,57 +745,68 @@ impl VisitMut for AssignFolder {
elems.len()
}),
);
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: ref_ident.clone().into(),
right: if self.c.loose {
right.take()
} else {
match &mut **right {
Expr::Ident(Ident { sym, .. }) if &**sym == "arguments" => {
Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: member_expr!(
Default::default(),
Default::default(),
Array.prototype.slice.call
)
.as_callee(),
args: vec![right.take().as_arg()],
..Default::default()
}))
}
Expr::Array(..) => right.take(),
_ => {
// if left has rest then need `_to_array`
// else `_sliced_to_array`
if elems.iter().any(|elem| matches!(elem, Some(Pat::Rest(..))))
{
Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: helper!(to_array),
args: vec![right.take().as_arg()],
..Default::default()
}))
} else {
exprs.push(
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: ref_ident.clone().into(),
right: if self.c.loose {
right.take()
} else {
match &mut **right {
Expr::Ident(Ident { sym, .. }) if &**sym == "arguments" => {
Box::new(
CallExpr {
span: DUMMY_SP,
callee: helper!(sliced_to_array),
args: vec![
right.take().as_arg(),
elems.len().as_arg(),
],
callee: member_expr!(
Default::default(),
Default::default(),
Array.prototype.slice.call
)
.as_callee(),
args: vec![right.take().as_arg()],
..Default::default()
}
.into(),
)
}
Expr::Array(..) => right.take(),
_ => {
// if left has rest then need `_to_array`
// else `_sliced_to_array`
if elems
.iter()
.any(|elem| matches!(elem, Some(Pat::Rest(..))))
{
Box::new(
CallExpr {
span: DUMMY_SP,
callee: helper!(to_array),
args: vec![right.take().as_arg()],
..Default::default()
}
.into(),
)
} else {
Box::new(
CallExpr {
span: DUMMY_SP,
callee: helper!(sliced_to_array),
args: vec![
right.take().as_arg(),
elems.len().as_arg(),
],
..Default::default()
}
.into(),
)
}
}
}
}
},
})));
},
}
.into(),
);
for (i, elem) in elems.iter_mut().enumerate() {
let elem = match elem {
@ -795,29 +821,33 @@ impl VisitMut for AssignFolder {
}) => {
// initialized by sequence expression.
let assign_ref_ident = make_ref_ident(self.c, &mut self.vars, None);
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: assign_ref_ident.clone().into(),
op: op!("="),
right: ref_ident.clone().computed_member(i as f64).into(),
})));
exprs.push(
AssignExpr {
span: DUMMY_SP,
left: assign_ref_ident.clone().into(),
op: op!("="),
right: ref_ident.clone().computed_member(i as f64).into(),
}
.into(),
);
let mut assign_expr = Expr::Assign(AssignExpr {
let mut assign_expr: Expr = AssignExpr {
span: *span,
left: left.take().try_into().unwrap(),
op: op!("="),
right: Box::new(make_cond_expr(assign_ref_ident, right.take())),
});
}
.into();
assign_expr.visit_mut_with(self);
exprs.push(Box::new(assign_expr));
}
Pat::Rest(RestPat { arg, .. }) => {
let mut assign_expr = Expr::Assign(AssignExpr {
let mut assign_expr: Expr = AssignExpr {
span: elem_span,
op: op!("="),
left: arg.take().try_into().unwrap(),
right: Box::new(Expr::Call(CallExpr {
right: CallExpr {
span: DUMMY_SP,
callee: ref_ident
.clone()
@ -825,19 +855,22 @@ impl VisitMut for AssignFolder {
.as_callee(),
args: vec![(i as f64).as_arg()],
..Default::default()
})),
});
}
.into(),
}
.into();
assign_expr.visit_mut_with(self);
exprs.push(Box::new(assign_expr));
}
_ => {
let mut assign_expr = Expr::Assign(AssignExpr {
let mut assign_expr: Expr = AssignExpr {
span: elem_span,
op: op!("="),
left: elem.take().try_into().unwrap(),
right: make_ref_idx_expr(&ref_ident, i).into(),
});
}
.into();
assign_expr.visit_mut_with(self);
exprs.push(Box::new(assign_expr))
@ -846,12 +879,13 @@ impl VisitMut for AssignFolder {
}
// last one should be `ref`
exprs.push(Box::new(Expr::Ident(ref_ident)));
exprs.push(ref_ident.into());
*expr = Expr::Seq(SeqExpr {
*expr = SeqExpr {
span: DUMMY_SP,
exprs,
})
}
.into()
}
AssignTargetPat::Object(ObjectPat { props, .. }) if props.is_empty() => {
let mut right = right.take();
@ -865,12 +899,13 @@ impl VisitMut for AssignFolder {
if let ObjectPatProp::Assign(p @ AssignPatProp { value: None, .. }) =
&props[0]
{
*expr = Expr::Assign(AssignExpr {
*expr = AssignExpr {
span: *span,
op: op!("="),
left: p.key.clone().into(),
right: right.take().make_member(p.key.clone().into()).into(),
});
}
.into();
return;
}
}
@ -900,12 +935,13 @@ impl VisitMut for AssignFolder {
let mut expr = if let Pat::Assign(pat) = *value {
self.handle_assign_pat(span, pat, &mut right)
} else {
Expr::Assign(AssignExpr {
AssignExpr {
span,
left: value.try_into().unwrap(),
op: op!("="),
right,
})
}
.into()
};
expr.visit_mut_with(self);
@ -919,38 +955,47 @@ impl VisitMut for AssignFolder {
let prop_ident =
make_ref_ident(self.c, &mut self.vars, None);
exprs.push(Box::new(Expr::Assign(AssignExpr {
span,
left: prop_ident.clone().into(),
op: op!("="),
right: Box::new(make_ref_prop_expr(
&ref_ident,
key.clone().into(),
computed,
)),
})));
exprs.push(
AssignExpr {
span,
left: prop_ident.clone().into(),
op: op!("="),
right: Box::new(make_ref_prop_expr(
&ref_ident,
key.clone().into(),
computed,
)),
}
.into(),
);
exprs.push(Box::new(Expr::Assign(AssignExpr {
span,
left: key.clone().into(),
op: op!("="),
right: Box::new(make_cond_expr(
prop_ident,
value.take(),
)),
})));
exprs.push(
AssignExpr {
span,
left: key.clone().into(),
op: op!("="),
right: Box::new(make_cond_expr(
prop_ident,
value.take(),
)),
}
.into(),
);
}
None => {
exprs.push(Box::new(Expr::Assign(AssignExpr {
span,
left: key.clone().into(),
op: op!("="),
right: Box::new(make_ref_prop_expr(
&ref_ident,
key.clone().into(),
computed,
)),
})));
exprs.push(
AssignExpr {
span,
left: key.clone().into(),
op: op!("="),
right: Box::new(make_ref_prop_expr(
&ref_ident,
key.clone().into(),
computed,
)),
}
.into(),
);
}
}
}
@ -962,12 +1007,13 @@ impl VisitMut for AssignFolder {
}
// Last one should be object itself.
exprs.push(Box::new(Expr::Ident(ref_ident)));
exprs.push(ref_ident.into());
*expr = Expr::Seq(SeqExpr {
*expr = SeqExpr {
span: DUMMY_SP,
exprs,
});
}
.into();
}
AssignTargetPat::Invalid(..) => unreachable!(),
@ -1161,7 +1207,7 @@ fn make_ref_ident_for_array(
fn make_ref_prop_expr(ref_ident: &Ident, prop: Box<Expr>, mut computed: bool) -> Expr {
computed |= matches!(*prop, Expr::Lit(Lit::Num(..)) | Expr::Lit(Lit::Str(..)));
Expr::Member(MemberExpr {
MemberExpr {
span: DUMMY_SP,
obj: Box::new(ref_ident.clone().into()),
prop: if computed {
@ -1172,14 +1218,15 @@ fn make_ref_prop_expr(ref_ident: &Ident, prop: Box<Expr>, mut computed: bool) ->
} else {
MemberProp::Ident(prop.ident().unwrap().into())
},
})
}
.into()
}
/// Creates `tmp === void 0 ? def_value : tmp`
fn make_cond_expr(tmp: Ident, def_value: Box<Expr>) -> Expr {
Expr::Cond(CondExpr {
CondExpr {
span: DUMMY_SP,
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
left: Box::new(Expr::Ident(tmp.clone())),
op: op!("==="),
@ -1188,10 +1235,12 @@ fn make_cond_expr(tmp: Ident, def_value: Box<Expr>) -> Expr {
op: op!("void"),
arg: 0.0.into(),
})),
})),
}
.into(),
cons: def_value,
alt: Box::new(Expr::Ident(tmp)),
})
alt: tmp.into(),
}
.into()
}
fn can_be_null(e: &Expr) -> bool {

View File

@ -59,7 +59,7 @@ impl VisitMut for PropFolder {
span: ident.span,
expr: quote_str!(ident.sym.clone()).into(),
}),
value: Box::new(Expr::Ident(ident.clone())),
value: ident.clone().into(),
})
}
}
@ -102,11 +102,12 @@ impl<'a> VisitMut for PropNameFolder<'a> {
if !self.props.insert(ident.sym.clone()) {
*name = PropName::Computed(ComputedPropName {
span,
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span,
raw: None,
value: ident.sym.clone(),
}))),
})
.into(),
})
}
}

View File

@ -100,18 +100,24 @@ impl ForOf {
let i = private_ident!("_i");
let test = Some(Box::new(Expr::Bin(BinExpr {
span: DUMMY_SP,
left: Box::new(Expr::Ident(i.clone())),
op: op!("<"),
right: arr.clone().make_member(quote_ident!("length")).into(),
})));
let update = Some(Box::new(Expr::Update(UpdateExpr {
span: DUMMY_SP,
prefix: false,
op: op!("++"),
arg: Box::new(Expr::Ident(i.clone())),
})));
let test = Some(
BinExpr {
span: DUMMY_SP,
left: Box::new(i.clone().into()),
op: op!("<"),
right: arr.clone().make_member(quote_ident!("length")).into(),
}
.into(),
);
let update = Some(
UpdateExpr {
span: DUMMY_SP,
prefix: false,
op: op!("++"),
arg: Box::new(i.clone().into()),
}
.into(),
);
let mut decls = Vec::with_capacity(2);
decls.push(VarDeclarator {
@ -281,7 +287,7 @@ impl ForOf {
}
// !(_step = _iterator()).done;
let test = Box::new(Expr::Unary(UnaryExpr {
let test = UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: AssignExpr {
@ -298,7 +304,8 @@ impl ForOf {
}
.make_member(quote_ident!("done"))
.into(),
}));
}
.into();
let stmt = Stmt::For(ForStmt {
span,
@ -393,10 +400,7 @@ impl ForOf {
self.top_level_vars.push(VarDeclarator {
span: DUMMY_SP,
name: error_ident.clone().into(),
init: Some(Box::new(Expr::Ident(Ident::new_no_ctxt(
"undefined".into(),
DUMMY_SP,
)))),
init: Some(Ident::new_no_ctxt("undefined".into(), DUMMY_SP).into()),
definite: false,
});
@ -437,40 +441,50 @@ impl ForOf {
.into(),
),
// !(_iteratorNormalCompletion = (_step = _iterator.next()).done)
test: Some(Box::new(Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: {
let step_expr = Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: step.into(),
op: op!("="),
// `_iterator.next()`
right: Box::new(Expr::Call(CallExpr {
test: Some(
UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: {
let step_expr: Expr = AssignExpr {
span: DUMMY_SP,
// `_iterator.next`
callee: iterator.make_member(quote_ident!("next")).as_callee(),
args: vec![],
..Default::default()
})),
}));
left: step.into(),
op: op!("="),
// `_iterator.next()`
right: Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
// `_iterator.next`
callee: iterator.make_member(quote_ident!("next")).as_callee(),
args: vec![],
..Default::default()
})),
}
.into();
Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: normal_completion_ident.clone().into(),
op: op!("="),
right: step_expr.make_member(quote_ident!("done")).into(),
}))
},
}))),
Box::new(
AssignExpr {
span: DUMMY_SP,
left: normal_completion_ident.clone().into(),
op: op!("="),
right: step_expr.make_member(quote_ident!("done")).into(),
}
.into(),
)
},
}
.into(),
),
// `_iteratorNormalCompletion = true`
update: Some(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: normal_completion_ident.clone().into(),
op: op!("="),
right: true.into(),
}))),
update: Some(
AssignExpr {
span: DUMMY_SP,
left: normal_completion_ident.clone().into(),
op: op!("="),
right: true.into(),
}
.into(),
),
body: Box::new(Stmt::Block(body)),
}
.into();

View File

@ -76,12 +76,13 @@ impl VisitMut for FnName {
if let Expr::Fn(expr @ FnExpr { ident: None, .. }) = &mut *p.value {
//
p.value = if let PropName::Ident(ref i) = p.key {
Box::new(Expr::Fn(FnExpr {
FnExpr {
ident: Some(prepare(i.clone().into())),
..expr.take()
}))
}
.into()
} else {
Box::new(Expr::Fn(expr.take()))
expr.take().into()
};
};
}

View File

@ -85,7 +85,7 @@ impl VisitMut for Wrapper {
is_async: false,
..Default::default()
});
let generator_object = Box::new(Expr::Call(CallExpr {
let generator_object = CallExpr {
span: DUMMY_SP,
callee: helper!(ts, ts_generator),
args: vec![
@ -97,7 +97,8 @@ impl VisitMut for Wrapper {
.as_arg(),
],
..Default::default()
}));
}
.into();
let mut stmts = vec![];
if !v.hoisted_vars.is_empty() {
stmts.push(
@ -494,7 +495,7 @@ impl VisitMut for Generator {
self.mark_label(result_label);
*e = Expr::Ident(result_local);
*e = result_local.into();
} else {
node.visit_mut_with(self);
}
@ -528,10 +529,11 @@ impl VisitMut for Generator {
expr: if pending_expressions.len() == 1 {
pending_expressions.remove(0)
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs: pending_expressions.take(),
}))
}
.into()
},
})))),
None,
@ -565,7 +567,7 @@ impl VisitMut for Generator {
// .mark resumeLabel
// a = _a[%sent%]
*obj = Box::new(Expr::Ident(self.cache_expression(obj.take())));
*obj = self.cache_expression(obj.take()).into();
prop.visit_mut_with(self);
return;
}
@ -590,7 +592,7 @@ impl VisitMut for Generator {
left.obj.visit_mut_with(self);
let obj = self.cache_expression(left.obj.take());
left.obj = Box::new(Expr::Ident(obj));
left.obj = obj.into();
}
MemberProp::Computed(prop) => {
// [source]
@ -611,10 +613,10 @@ impl VisitMut for Generator {
prop.visit_mut_with(self);
let prop = self.cache_expression(prop.expr.take());
left.obj = Box::new(Expr::Ident(obj));
left.obj = obj.into();
left.prop = MemberProp::Computed(ComputedPropName {
span: prop_span,
expr: Box::new(Expr::Ident(prop)),
expr: prop.into(),
});
}
}
@ -630,12 +632,13 @@ impl VisitMut for Generator {
node.right.visit_mut_with(self);
*e = Expr::Assign(AssignExpr {
*e = AssignExpr {
span: node.right.span(),
op: node.op,
left: left_of_right.into(),
right: node.right.take(),
});
}
.into();
} else {
node.right.visit_mut_with(self);
}
@ -672,7 +675,7 @@ impl VisitMut for Generator {
self.emit_assignment(
temp.clone().into(),
Box::new(Expr::Object(ObjectLit {
ObjectLit {
span: DUMMY_SP,
props: node
.props
@ -680,7 +683,8 @@ impl VisitMut for Generator {
.take(num_initial_properties)
.map(|v| v.take())
.collect(),
})),
}
.into(),
None,
);
@ -736,7 +740,7 @@ impl VisitMut for Generator {
self.reduce_property(exprs, property, &mut temp)
});
expressions.push(Box::new(Expr::Ident(temp)));
expressions.push(temp.into());
*e = *Expr::from_exprs(expressions);
}
@ -821,7 +825,7 @@ impl VisitMut for Generator {
None
};
let apply = Expr::Ident(callee).apply(
let apply = callee.apply(
node.span,
this_arg,
arg.take().map(|v| v.as_arg()).into_iter().collect(),
@ -863,10 +867,11 @@ impl VisitMut for Generator {
Some(VarDeclOrExpr::Expr(if exprs.len() == 1 {
exprs.remove(0)
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
}))
}
.into()
}))
};
node.test.visit_mut_with(self);
@ -1030,10 +1035,11 @@ impl VisitMut for Generator {
expr: if exprs.len() == 1 {
exprs.remove(0)
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
}))
}
.into()
},
});
}
@ -1082,7 +1088,7 @@ impl Generator {
self.emit_assignment(
temp.clone().unwrap().into(),
Box::new(Expr::Array(ArrayLit {
ArrayLit {
span: DUMMY_SP,
elems: leading_element
.take()
@ -1095,7 +1101,8 @@ impl Generator {
.map(|e| e.take()),
)
.collect(),
})),
}
.into(),
None,
);
}
@ -1109,7 +1116,7 @@ impl Generator {
});
if let Some(temp) = temp {
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: temp.make_member(quote_ident!("concat")).as_callee(),
args: vec![ExprOrSpread {
@ -1120,9 +1127,10 @@ impl Generator {
})),
}],
..Default::default()
})
}
.into()
} else {
Expr::Array(ArrayLit {
ArrayLit {
span: DUMMY_SP,
elems: leading_element
.take()
@ -1130,7 +1138,8 @@ impl Generator {
.map(Some)
.chain(expressions)
.collect(),
})
}
.into()
}
}
@ -1150,7 +1159,7 @@ impl Generator {
self.emit_assignment(
temp.clone().unwrap().into(),
if has_assigned_temp {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: temp
.clone()
@ -1163,7 +1172,8 @@ impl Generator {
}))
.as_arg()],
..Default::default()
}))
}
.into()
} else {
Box::new(
ArrayLit {
@ -1209,47 +1219,50 @@ impl Generator {
}));
}
let mut expression = match property {
let mut expression: Expr = match property {
CompiledProp::Prop(p) => match p {
Prop::Shorthand(p) => Expr::Assign(AssignExpr {
Prop::Shorthand(p) => AssignExpr {
span: p.span,
op: op!("="),
left: MemberExpr {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(temp.clone())),
obj: temp.clone().into(),
prop: MemberProp::Ident(p.clone().into()),
}
.into(),
right: Box::new(Expr::Ident(p)),
}),
Prop::KeyValue(p) => Expr::Assign(AssignExpr {
right: p.into(),
}
.into(),
Prop::KeyValue(p) => AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: MemberExpr {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(temp.clone())),
obj: temp.clone().into(),
prop: p.key.into(),
}
.into(),
right: p.value,
}),
}
.into(),
Prop::Assign(_) => {
unreachable!("assignment property be removed before generator pass")
}
Prop::Getter(_) | Prop::Setter(_) => {
unreachable!("getter/setter property be compiled as CompiledProp::Accessor")
}
Prop::Method(p) => Expr::Assign(AssignExpr {
Prop::Method(p) => AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: MemberExpr {
span: DUMMY_SP,
obj: Box::new(Expr::Ident(temp.clone())),
obj: temp.clone().into(),
prop: p.key.into(),
}
.into(),
right: p.function.into(),
}),
}
.into(),
},
CompiledProp::Accessor(getter, setter) => {
let key = getter
@ -1293,7 +1306,7 @@ impl Generator {
.collect(),
};
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: helper!(define_property),
args: vec![
@ -1302,7 +1315,8 @@ impl Generator {
desc.as_arg(),
],
..Default::default()
})
}
.into()
}
};
@ -1329,7 +1343,7 @@ impl Generator {
// _a + %sent% + c()
node.left.visit_mut_with(self);
node.left = Box::new(Expr::Ident(self.cache_expression(node.left.take())));
node.left = self.cache_expression(node.left.take()).into();
node.right.visit_mut_with(self);
return None;
}
@ -1404,7 +1418,7 @@ impl Generator {
);
self.mark_label(result_label);
Expr::Ident(result_local)
result_local.into()
}
fn transform_and_emit_stmts(&mut self, stmts: Vec<Stmt>, start: usize) {
@ -1509,10 +1523,11 @@ impl Generator {
expr: if pending_expressions.len() == 1 {
pending_expressions.pop().unwrap()
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs: take(&mut pending_expressions),
}))
}
.into()
},
}))
}
@ -1748,7 +1763,7 @@ impl Generator {
right: node.right.take(),
body: Box::new(Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Call(CallExpr {
expr: CallExpr {
span: DUMMY_SP,
callee: keys_array
.clone()
@ -1756,7 +1771,8 @@ impl Generator {
.as_callee(),
args: vec![key.as_arg()],
..Default::default()
})),
}
.into(),
})),
}));
@ -1797,14 +1813,15 @@ impl Generator {
};
self.emit_assignment(
variable.try_into().unwrap(),
Box::new(Expr::Member(MemberExpr {
MemberExpr {
span: DUMMY_SP,
obj: Box::new(keys_array.into()),
prop: MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: Box::new(keys_index.clone().into()),
}),
})),
}
.into(),
None,
);
self.transform_and_emit_embedded_stmt(*node.body);
@ -1812,12 +1829,13 @@ impl Generator {
self.mark_label(increment_label);
self.emit_stmt(Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Update(UpdateExpr {
expr: UpdateExpr {
span: DUMMY_SP,
prefix: false,
op: op!("++"),
arg: Box::new(keys_index.clone().into()),
})),
}
.into(),
}));
self.emit_break(condition_label, None);
@ -1966,7 +1984,7 @@ impl Generator {
clauses_written += pending_clauses.len();
self.emit_stmt(Stmt::Switch(SwitchStmt {
span: DUMMY_SP,
discriminant: Box::new(Expr::Ident(expression.clone())),
discriminant: expression.clone().into(),
cases: take(&mut pending_clauses),
}));
}
@ -2302,7 +2320,7 @@ impl Generator {
self.emit_assignment(
name.clone().into(),
Box::new(Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: self
.state
@ -2311,7 +2329,8 @@ impl Generator {
.as_callee(),
args: vec![],
..Default::default()
})),
}
.into(),
None,
);
@ -2594,9 +2613,10 @@ impl Generator {
.unwrap()
.push(expr);
}
return Box::new(Expr::Invalid(Invalid {
return Invalid {
span: Span::new(BytePos(label.0 as _), BytePos(label.0 as _)),
}));
}
.into();
}
}
@ -2631,10 +2651,13 @@ impl Generator {
];
ReturnStmt {
span: span.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: args,
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: args,
}
.into(),
),
}
}
@ -2645,22 +2668,25 @@ impl Generator {
fn create_inline_return(&mut self, expr: Option<Box<Expr>>, loc: Option<Span>) -> ReturnStmt {
ReturnStmt {
span: loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: match expr {
Some(expr) => vec![
Some(self.create_instruction(Instruction::Return).as_arg()),
Some(expr.as_arg()),
],
None => vec![Some(self.create_instruction(Instruction::Return).as_arg())],
},
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: match expr {
Some(expr) => vec![
Some(self.create_instruction(Instruction::Return).as_arg()),
Some(expr.as_arg()),
],
None => vec![Some(self.create_instruction(Instruction::Return).as_arg())],
},
}
.into(),
),
}
}
/// Creates an expression that can be used to resume from a Yield operation.
fn create_generator_resume(&mut self, loc: Option<Span>) -> Box<Expr> {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: loc.unwrap_or(DUMMY_SP),
callee: self
.state
@ -2669,7 +2695,8 @@ impl Generator {
.as_callee(),
args: vec![],
..Default::default()
}))
}
.into()
}
/// Emits an empty instruction.
@ -2976,7 +3003,7 @@ impl Generator {
0,
Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Call(CallExpr {
expr: CallExpr {
span: DUMMY_SP,
callee: self
.state
@ -2995,7 +3022,8 @@ impl Generator {
}
.as_arg()],
..Default::default()
})),
}
.into(),
}),
);
}
@ -3007,12 +3035,13 @@ impl Generator {
stmts.push(Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: self.state.clone().make_member(quote_ident!("label")).into(),
right: (self.label_number + 1).into(),
})),
}
.into(),
}));
}
@ -3241,12 +3270,13 @@ impl Generator {
fn write_assign(&mut self, left: AssignTarget, right: Box<Expr>, op_loc: Option<Span>) {
self.write_stmt(Stmt::Expr(ExprStmt {
span: op_loc.unwrap_or(DUMMY_SP),
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span: DUMMY_SP,
op: op!("="),
left,
right,
})),
}
.into(),
}))
}
@ -3276,17 +3306,20 @@ impl Generator {
let inst = self.create_instruction(Instruction::Return);
self.write_stmt(Stmt::Return(ReturnStmt {
span: op_loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: match expr {
Some(expr) => {
vec![Some(inst.as_arg()), Some(expr.as_arg())]
}
_ => {
vec![Some(inst.as_arg())]
}
},
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: match expr {
Some(expr) => {
vec![Some(inst.as_arg()), Some(expr.as_arg())]
}
_ => {
vec![Some(inst.as_arg())]
}
},
}
.into(),
),
}))
}
@ -3301,10 +3334,13 @@ impl Generator {
let label = self.create_label(Some(label));
self.write_stmt(Stmt::Return(ReturnStmt {
span: op_loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: vec![Some(inst.as_arg()), Some(label.as_arg())],
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: vec![Some(inst.as_arg()), Some(label.as_arg())],
}
.into(),
),
}))
}
@ -3321,10 +3357,13 @@ impl Generator {
test: cond,
cons: Box::new(Stmt::Return(ReturnStmt {
span: op_loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: vec![Some(inst.as_arg()), Some(label.as_arg())],
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: vec![Some(inst.as_arg()), Some(label.as_arg())],
}
.into(),
),
})),
alt: None,
}))
@ -3340,17 +3379,21 @@ impl Generator {
let label = self.create_label(Some(label));
self.write_stmt(Stmt::If(IfStmt {
span: DUMMY_SP,
test: Box::new(Expr::Unary(UnaryExpr {
test: UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: cond,
})),
}
.into(),
cons: Box::new(Stmt::Return(ReturnStmt {
span: op_loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: vec![Some(inst.as_arg()), Some(label.as_arg())],
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: vec![Some(inst.as_arg()), Some(label.as_arg())],
}
.into(),
),
})),
alt: None,
}))
@ -3374,10 +3417,13 @@ impl Generator {
};
self.write_stmt(Stmt::Return(ReturnStmt {
span: op_loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems,
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems,
}
.into(),
),
}));
}
@ -3391,10 +3437,13 @@ impl Generator {
let arg1 = self.create_instruction(Instruction::YieldStar);
self.write_stmt(Stmt::Return(ReturnStmt {
span: op_loc.unwrap_or(DUMMY_SP),
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: vec![Some(arg1.as_arg()), Some(expr.as_arg())],
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: vec![Some(arg1.as_arg()), Some(expr.as_arg())],
}
.into(),
),
}))
}
@ -3405,10 +3454,13 @@ impl Generator {
let arg = self.create_instruction(Instruction::Endfinally);
self.write_stmt(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Array(ArrayLit {
span: DUMMY_SP,
elems: vec![Some(arg.as_arg())],
}))),
arg: Some(
ArrayLit {
span: DUMMY_SP,
elems: vec![Some(arg.as_arg())],
}
.into(),
),
}))
}
@ -3472,7 +3524,7 @@ impl Generator {
let this_arg = self.create_temp_variable();
*obj = Box::new(obj.take().make_assign_to(op!("="), this_arg.clone().into()));
(callee, Box::new(Expr::Ident(this_arg)))
(callee, this_arg.into())
}
_ => {
@ -3481,7 +3533,7 @@ impl Generator {
} else {
let this_arg = self.create_temp_variable();
let target = callee.make_assign_to(op!("="), this_arg.clone().into());
(Box::new(target), Box::new(Expr::Ident(this_arg)))
(Box::new(target), this_arg.into())
}
}
}

View File

@ -62,12 +62,13 @@ impl VisitMut for InstanceOf {
hi: right.span_lo(),
};
*expr = Expr::Call(CallExpr {
*expr = CallExpr {
span: *span,
callee: helper!(instanceof_span, instanceof),
args: vec![left.take().as_arg(), right.take().as_arg()],
..Default::default()
});
}
.into();
}
}
}

View File

@ -70,19 +70,21 @@ impl VisitMut for NewTarget {
Ctx::Constructor => *e = this_ctor(*span),
Ctx::Method => *e = *Expr::undefined(DUMMY_SP),
Ctx::Function(i) => {
*e = Expr::Cond(CondExpr {
*e = CondExpr {
span: *span,
// this instanceof Foo
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
op: op!("instanceof"),
left: Box::new(Expr::This(ThisExpr { span: DUMMY_SP })),
right: Box::new(Expr::Ident(i.clone())),
})),
}
.into(),
cons: Box::new(this_ctor(DUMMY_SP)),
// void 0
alt: Expr::undefined(DUMMY_SP),
})
}
.into()
}
}
}

View File

@ -114,12 +114,13 @@ impl VisitMut for ObjectSuper {
}
}
if let Some(obj) = replacer.obj {
*expr = Expr::Assign(AssignExpr {
*expr = AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: obj.clone().into(),
right: Box::new(expr.take()),
});
}
.into();
self.extra_vars.push(obj);
}
}
@ -176,13 +177,13 @@ impl SuperReplacer {
}
fn get_proto(&mut self) -> ExprOrSpread {
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: helper!(get_prototype_of),
args: vec![self.get_obj_ref().as_arg()],
..Default::default()
})
}
.as_arg()
}
@ -191,11 +192,12 @@ impl SuperReplacer {
match prop.take() {
SuperProp::Ident(IdentName {
sym: value, span, ..
}) => Box::new(Expr::Lit(Lit::Str(Str {
}) => Lit::Str(Str {
raw: None,
value,
span,
}))),
})
.into(),
SuperProp::Computed(ComputedPropName { expr, .. }) => expr,
}
@ -227,7 +229,7 @@ impl SuperReplacer {
SuperReplacer::super_to_get_call(self.get_proto(), *super_token, prop.as_arg());
let this = ThisExpr { span: DUMMY_SP }.as_arg();
if args.len() == 1 && is_rest_arguments(&args[0]) {
*n = Expr::Call(CallExpr {
*n = CallExpr {
span: DUMMY_SP,
callee: MemberExpr {
span: DUMMY_SP,
@ -243,11 +245,12 @@ impl SuperReplacer {
}))
.collect(),
..Default::default()
});
}
.into();
return;
}
*n = Expr::Call(CallExpr {
*n = CallExpr {
span: DUMMY_SP,
callee: MemberExpr {
span: DUMMY_SP,
@ -257,7 +260,8 @@ impl SuperReplacer {
.as_callee(),
args: iter::once(this).chain(args.take()).collect(),
..Default::default()
});
}
.into();
}
}
}
@ -305,12 +309,13 @@ impl SuperReplacer {
return;
}
left.visit_mut_children_with(self);
*n = Expr::Assign(AssignExpr {
*n = AssignExpr {
span: *span,
left: left.take(),
op: *op,
right: right.take(),
});
}
.into();
}
_ => {}
}
@ -339,12 +344,13 @@ impl SuperReplacer {
}
fn super_to_get_call(proto: ExprOrSpread, super_token: Span, prop: ExprOrSpread) -> Expr {
Expr::Call(CallExpr {
CallExpr {
span: super_token,
callee: helper!(get),
args: vec![proto, prop, ThisExpr { span: super_token }.as_arg()],
..Default::default()
})
}
.into()
}
fn to_bin_expr(left: Box<Expr>, op: AssignOp, rhs: Box<Expr>) -> BinExpr {
@ -362,7 +368,7 @@ impl SuperReplacer {
prop: ExprOrSpread,
rhs: ExprOrSpread,
) -> Expr {
Expr::Call(CallExpr {
CallExpr {
span: super_token,
callee: helper!(set),
args: vec![
@ -374,7 +380,8 @@ impl SuperReplacer {
true.as_arg(),
],
..Default::default()
})
}
.into()
}
fn super_to_set_call(
@ -400,12 +407,13 @@ impl SuperReplacer {
if computed {
let ref_ident = alias_ident_for(&rhs, "_ref").into_private();
self.vars.push(ref_ident.clone());
*prop = Expr::Assign(AssignExpr {
*prop = AssignExpr {
span: DUMMY_SP,
left: ref_ident.clone().into(),
op: op!("="),
right: prop.take(),
});
}
.into();
ref_ident.as_arg()
} else {
prop.clone().as_arg()
@ -417,11 +425,12 @@ impl SuperReplacer {
super_token,
prop.as_arg(),
SuperReplacer::to_bin_expr(
Box::new(Expr::Unary(UnaryExpr {
UnaryExpr {
span: DUMMY_SP,
op: op!(unary, "+"),
arg: left,
})),
}
.into(),
op,
rhs,
)
@ -430,7 +439,7 @@ impl SuperReplacer {
} else {
let update_ident = alias_ident_for(&rhs, "_super").into_private();
self.vars.push(update_ident.clone());
Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs: vec![
Box::new(
@ -459,7 +468,8 @@ impl SuperReplacer {
),
Box::new(Expr::Ident(update_ident)),
],
})
}
.into()
}
} else {
self.call_set_helper(

View File

@ -114,7 +114,7 @@ impl Params {
let decl = VarDeclarator {
span,
name: param.pat,
init: Some(Box::new(Expr::Ident(binding))),
init: Some(binding.into()),
definite: false,
};
if self.c.ignore_function_length {
@ -141,22 +141,28 @@ impl Params {
decls.push(VarDeclarator {
span,
name: *left,
init: Some(Box::new(Expr::Cond(CondExpr {
span,
test: Box::new(Expr::Bin(BinExpr {
left: Box::new(check_arg_len(i)),
op: op!("&&"),
right: Box::new(Expr::Bin(BinExpr {
left: make_arg_nth(i).into(),
op: op!("!=="),
right: Expr::undefined(DUMMY_SP),
span: DUMMY_SP,
})),
init: Some(
CondExpr {
span,
})),
cons: make_arg_nth(i).into(),
alt: right,
}))),
test: Box::new(
BinExpr {
left: Box::new(check_arg_len(i)),
op: op!("&&"),
right: Box::new(Expr::Bin(BinExpr {
left: make_arg_nth(i).into(),
op: op!("!=="),
right: Expr::undefined(DUMMY_SP),
span: DUMMY_SP,
})),
span,
}
.into(),
),
cons: make_arg_nth(i).into(),
alt: right,
}
.into(),
),
definite: false,
})
} else if let Pat::Ident(ident) = left.as_ref() {
@ -167,20 +173,22 @@ impl Params {
});
loose_stmt.push(Stmt::If(IfStmt {
span,
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
left: Box::new(Expr::Ident(Ident::from(ident))),
left: Box::new(Ident::from(ident).into()),
op: op!("==="),
right: Expr::undefined(DUMMY_SP),
})),
}
.into(),
cons: Box::new(Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span,
left: left.try_into().unwrap(),
op: op!("="),
right,
})),
}
.into(),
})),
alt: None,
}))
@ -258,37 +266,40 @@ impl Params {
// `len - $i`
let bin: Expr = BinExpr {
span,
left: Box::new(Expr::Ident(ident.clone())),
left: ident.clone().into(),
op: op!(bin, "-"),
right: Box::new(Expr::Lit(Lit::Num(Number {
right: Lit::Num(Number {
span,
value: i as f64,
raw: None,
}))),
})
.into(),
}
.into();
if !min_zero {
return bin;
}
Expr::Cond(CondExpr {
CondExpr {
span,
test: Box::new(
BinExpr {
span,
left: Box::new(len_ident.clone().into()),
op: op!(">"),
right: Box::new(Expr::Lit(Lit::Num(Number {
right: Lit::Num(Number {
span,
value: i as _,
raw: None,
}))),
})
.into(),
}
.into(),
),
cons: Box::new(bin),
alt: 0.into(),
})
}
.into()
}
};
@ -348,19 +359,25 @@ impl Params {
.into(),
),
// `_key < _len`
test: Some(Box::new(Expr::Bin(BinExpr {
span,
left: Box::new(idx_ident.clone().into()),
op: op!("<"),
right: Box::new(len_ident.clone().into()),
}))),
test: Some(
BinExpr {
span,
left: Box::new(idx_ident.clone().into()),
op: op!("<"),
right: Box::new(len_ident.clone().into()),
}
.into(),
),
// _key++
update: Some(Box::new(Expr::Update(UpdateExpr {
span,
op: op!("++"),
prefix: false,
arg: Box::new(idx_ident.clone().into()),
}))),
update: Some(
UpdateExpr {
span,
op: op!("++"),
prefix: false,
arg: Box::new(idx_ident.clone().into()),
}
.into(),
),
body: Box::new(Stmt::Block(BlockStmt {
span: DUMMY_SP,
stmts: vec![{
@ -634,7 +651,7 @@ impl VisitMut for Params {
}
.into();
*e = match (self.in_prop, local_vars) {
(true, Some(var_decl)) => Expr::Arrow(ArrowExpr {
(true, Some(var_decl)) => ArrowExpr {
span: f.span,
params: Vec::new(),
is_async: false,
@ -651,7 +668,7 @@ impl VisitMut for Params {
..Default::default()
})),
..Default::default()
})
}
.as_iife()
.into(),
_ => func,
@ -675,7 +692,7 @@ impl VisitMut for Params {
Box::new(BlockStmtOrExpr::BlockStmt(body))
};
*e = Expr::Arrow(ArrowExpr {
*e = ArrowExpr {
params: params.into_iter().map(|param| param.pat).collect(),
body,
span: f.span,
@ -684,7 +701,8 @@ impl VisitMut for Params {
type_params: f.type_params.take(),
return_type: f.return_type.take(),
..Default::default()
});
}
.into();
}
_ => e.visit_mut_children_with(self),
}
@ -784,25 +802,27 @@ impl VisitMut for Params {
}
fn make_arg_nth(n: usize) -> MemberExpr {
Expr::Ident(Ident::new_no_ctxt("arguments".into(), DUMMY_SP)).computed_member(n)
Ident::new_no_ctxt("arguments".into(), DUMMY_SP).computed_member(n)
}
fn check_arg_len(n: usize) -> Expr {
Expr::Bin(BinExpr {
BinExpr {
left: Expr::Ident(Ident::new_no_ctxt("arguments".into(), DUMMY_SP))
.make_member(IdentName::new("length".into(), DUMMY_SP))
.into(),
op: op!(">"),
right: n.into(),
span: DUMMY_SP,
})
}
.into()
}
fn check_arg_len_or_undef(n: usize) -> Expr {
Expr::Cond(CondExpr {
CondExpr {
test: Box::new(check_arg_len(n)),
cons: make_arg_nth(n).into(),
alt: Expr::undefined(DUMMY_SP),
span: DUMMY_SP,
})
}
.into()
}

View File

@ -96,10 +96,11 @@ impl VisitMut for Shorthand {
};
*prop = Prop::KeyValue(KeyValueProp {
key,
value: Box::new(Expr::Fn(FnExpr {
value: FnExpr {
ident: None,
function: function.take(),
})),
}
.into(),
})
}
_ => {}

View File

@ -85,7 +85,7 @@ impl VisitMut for Spread {
Expr::SuperProp(SuperPropExpr {
obj: Super { span, .. },
..
}) => (Box::new(Expr::This(ThisExpr { span: *span })), None),
}) => (ThisExpr { span: *span }.into(), None),
Expr::Member(MemberExpr { obj, .. }) if obj.is_this() => (obj.clone(), None),
@ -93,7 +93,7 @@ impl VisitMut for Spread {
Expr::Member(MemberExpr { obj, .. })
if obj.as_ident().is_some() && obj.as_ident().unwrap().span.is_dummy() =>
{
(Box::new(Expr::Ident(obj.as_ident().unwrap().clone())), None)
(obj.as_ident().unwrap().clone().into(), None)
}
Expr::Ident(Ident { span, .. }) => (Expr::undefined(*span), None),
@ -109,29 +109,34 @@ impl VisitMut for Spread {
init: None,
});
let this = Box::new(Expr::Ident(ident.clone()));
let callee = Expr::Assign(AssignExpr {
let this = ident.clone().into();
let callee: Expr = AssignExpr {
span: DUMMY_SP,
left: ident.into(),
op: op!("="),
right: obj.clone(),
});
}
.into();
(
this,
Some(Box::new(Expr::Member(MemberExpr {
span: *span,
obj: callee.into(),
prop: prop.clone(),
}))),
Some(
MemberExpr {
span: *span,
obj: callee.into(),
prop: prop.clone(),
}
.into(),
),
)
}
// https://github.com/swc-project/swc/issues/400
// _ => (undefined(callee.span()), callee),
_ => (
Box::new(Expr::This(ThisExpr {
ThisExpr {
span: callee.span(),
})),
}
.into(),
None,
),
};
@ -140,10 +145,11 @@ impl VisitMut for Spread {
matches!(e, ExprOrSpread { spread: None, .. })
|| matches!(e, ExprOrSpread { expr, .. } if expr.is_array())
}) {
Expr::Array(ArrayLit {
ArrayLit {
span: *span,
elems: expand_literal_args(args.take().into_iter().map(Some)),
})
}
.into()
} else {
self.concat_args(*span, args.take().into_iter().map(Some), false)
};
@ -154,12 +160,13 @@ impl VisitMut for Spread {
prop: MemberProp::Ident(IdentName::new("apply".into(), *span)),
};
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
callee: apply.as_callee(),
args: vec![this.as_arg(), args_array.as_arg()],
..Default::default()
})
}
.into()
}
Expr::New(NewExpr {
callee,
@ -176,12 +183,13 @@ impl VisitMut for Spread {
let args = self.concat_args(*span, args.take().into_iter().map(Some), true);
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
callee: helper!(construct),
args: vec![callee.take().as_arg(), args.as_arg()],
..Default::default()
});
}
.into();
}
_ => {}
};
@ -291,7 +299,7 @@ impl Spread {
);
}
return Expr::Call(CallExpr {
return CallExpr {
span: DUMMY_SP,
callee: ArrayLit {
span: DUMMY_SP,
@ -301,7 +309,8 @@ impl Spread {
.as_callee(),
args: arg_list,
..Default::default()
});
}
.into();
}
for arg in args {
@ -338,7 +347,7 @@ impl Spread {
Expr::Ident(Ident { ref sym, .. }) if &**sym == "arguments" => {
if args_len == 1 {
if need_array {
return Expr::Call(CallExpr {
return CallExpr {
span,
callee: member_expr!(
Default::default(),
@ -348,7 +357,8 @@ impl Spread {
.as_callee(),
args: vec![expr.as_arg()],
..Default::default()
});
}
.into();
} else {
return *expr;
}
@ -372,13 +382,13 @@ impl Spread {
return if self.c.loose {
*expr
} else {
Expr::Call(to_consumable_array(expr, span))
to_consumable_array(expr, span).into()
};
}
// [].concat(arr) is shorter than _to_consumable_array(arr)
if args_len == 1 {
return if self.c.loose {
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: ArrayLit {
span: DUMMY_SP,
@ -388,9 +398,10 @@ impl Spread {
.as_callee(),
args: vec![expr.as_arg()],
..Default::default()
})
}
.into()
} else {
Expr::Call(to_consumable_array(expr, span))
to_consumable_array(expr, span).into()
};
}
to_consumable_array(expr, span).as_arg()
@ -418,15 +429,16 @@ impl Spread {
.make_member(IdentName::new("concat".into(), DUMMY_SP))
.as_callee();
return Expr::Call(CallExpr {
return CallExpr {
span,
callee,
args: buf,
..Default::default()
});
}
.into();
}
Expr::Call(CallExpr {
CallExpr {
// TODO
span,
@ -446,7 +458,8 @@ impl Spread {
args: buf,
..Default::default()
})
}
.into()
}
}

View File

@ -41,12 +41,13 @@ impl VisitMut for StickyRegex {
if let Expr::Lit(Lit::Regex(Regex { exp, flags, span })) = e {
if flags.contains('y') {
*e = Expr::New(NewExpr {
*e = NewExpr {
span: *span,
callee: Box::new(quote_ident!(Default::default(), *span, "RegExp").into()),
args: Some(vec![exp.clone().as_arg(), flags.clone().as_arg()]),
..Default::default()
})
}
.into()
}
}
}

View File

@ -132,16 +132,16 @@ impl VisitMut for TemplateLiteral {
value: r_value,
..
})) => {
obj = Box::new(Expr::Lit(Lit::Str(Str {
obj = Lit::Str(Str {
span: span.with_hi(r_span.hi()),
raw: None,
value: format!("{}{}", value, r_value).into(),
})));
})
.into();
continue;
}
_ => {
obj =
Box::new(Expr::Lit(Lit::Str(Str { span, raw, value })));
obj = Lit::Str(Str { span, raw, value }).into();
}
}
}
@ -155,16 +155,17 @@ impl VisitMut for TemplateLiteral {
obj = if self.c.ignore_to_primitive {
let args = mem::take(&mut args);
for arg in args {
obj = Box::new(Expr::Bin(BinExpr {
obj = BinExpr {
span: span.with_hi(expr_span.hi() + BytePos(1)),
op: op!(bin, "+"),
left: obj,
right: arg,
}))
}
.into()
}
obj
} else {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: span.with_hi(expr_span.hi() + BytePos(1)),
callee: MemberExpr {
span: DUMMY_SP,
@ -180,7 +181,8 @@ impl VisitMut for TemplateLiteral {
.map(|expr| expr.as_arg())
.collect(),
..Default::default()
}))
}
.into()
}
}
} else {
@ -196,16 +198,17 @@ impl VisitMut for TemplateLiteral {
continue;
}
}
obj = Box::new(Expr::Bin(BinExpr {
obj = BinExpr {
span: span.with_hi(expr_span.hi() + BytePos(1)),
op: op!(bin, "+"),
left: obj,
right: arg,
}))
}
.into()
}
obj
} else {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: span.with_hi(expr_span.hi() + BytePos(1)),
callee: MemberExpr {
span: DUMMY_SP,
@ -221,7 +224,8 @@ impl VisitMut for TemplateLiteral {
.map(|expr| expr.as_arg())
.collect(),
..Default::default()
}))
}
.into()
};
}
debug_assert!(args.is_empty());
@ -310,8 +314,8 @@ impl VisitMut for TemplateLiteral {
// _templateObject2 = function () {
// return data;
// };
let assign_expr = {
Expr::Assign(AssignExpr {
let assign_expr: Expr = {
AssignExpr {
span: DUMMY_SP,
left: fn_ident.clone().into(),
op: op!("="),
@ -331,7 +335,8 @@ impl VisitMut for TemplateLiteral {
..Default::default()
}
.into(),
})
}
.into()
};
Some(BlockStmt {
@ -357,7 +362,7 @@ impl VisitMut for TemplateLiteral {
function: f.into(),
})));
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: DUMMY_SP,
callee: tag.take().as_callee(),
args: iter::once(
@ -372,7 +377,8 @@ impl VisitMut for TemplateLiteral {
.chain(tpl.exprs.take().into_iter().map(|e| e.as_arg()))
.collect(),
..Default::default()
})
}
.into()
}
_ => {}

View File

@ -67,39 +67,46 @@ impl VisitMut for TypeOfSymbol {
Expr::Ident(..) => {
let undefined_str: Box<Expr> = quote_str!("undefined").into();
let test = Box::new(Expr::Bin(BinExpr {
let test = BinExpr {
span: DUMMY_SP,
op: op!("==="),
left: Box::new(Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!("typeof"),
arg: arg.clone(),
})),
left: Box::new(
UnaryExpr {
span: DUMMY_SP,
op: op!("typeof"),
arg: arg.clone(),
}
.into(),
),
right: undefined_str.clone(),
}));
}
.into();
let call = Expr::Call(CallExpr {
let call = CallExpr {
span: *span,
callee: helper!(*span, type_of),
args: vec![arg.take().as_arg()],
..Default::default()
});
}
.into();
*expr = Expr::Cond(CondExpr {
*expr = CondExpr {
span: *span,
test,
cons: undefined_str,
alt: Box::new(call),
});
}
.into();
}
_ => {
let call = Expr::Call(CallExpr {
let call = CallExpr {
span: *span,
callee: helper!(*span, type_of),
args: vec![arg.take().as_arg()],
..Default::default()
});
}
.into();
*expr = call;
}

View File

@ -109,12 +109,13 @@ impl VisitMut for Exponentiation {
}
left => {
*e = Expr::Assign(AssignExpr {
*e = AssignExpr {
span: *span,
left: left.take(),
op: op!("="),
right: right.take(),
});
}
.into();
return;
}
};
@ -138,13 +139,14 @@ impl VisitMut for Exponentiation {
#[tracing::instrument(level = "info", skip_all)]
fn mk_call(span: Span, left: Box<Expr>, right: Box<Expr>) -> Expr {
// Math.pow()
Expr::Call(CallExpr {
CallExpr {
span,
callee: member_expr!(Default::default(), span, Math.pow).as_callee(),
args: vec![left.as_arg(), right.as_arg()],
..Default::default()
})
}
.into()
}
#[cfg(test)]

View File

@ -156,12 +156,15 @@ impl<C: Comments> VisitMut for Actual<C> {
.into_iter()
.chain(iter::once(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: expr.as_callee(),
args: vec![],
..Default::default()
}))),
arg: Some(
CallExpr {
span: DUMMY_SP,
callee: expr.as_callee(),
args: vec![],
..Default::default()
}
.into(),
),
})))
.collect(),
..Default::default()
@ -267,18 +270,15 @@ impl<C: Comments> VisitMut for Actual<C> {
);
let fn_ref = if is_this_used {
fn_ref.apply(
DUMMY_SP,
Box::new(Expr::This(ThisExpr { span: DUMMY_SP })),
vec![],
)
fn_ref.apply(DUMMY_SP, ThisExpr { span: DUMMY_SP }.into(), vec![])
} else {
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: fn_ref.as_callee(),
args: vec![],
..Default::default()
})
}
.into()
};
prop.function = Function {
@ -427,14 +427,13 @@ fn make_fn_ref(mut expr: FnExpr) -> Expr {
let span = expr.span();
let expr = Expr::Fn(expr);
Expr::Call(CallExpr {
CallExpr {
span,
callee: helper,
args: vec![expr.as_arg()],
..Default::default()
})
}
.into()
}
struct AsyncFnBodyHandler {
@ -470,7 +469,7 @@ impl VisitMut for AsyncFnBodyHandler {
delegate: true,
}) => {
let callee = helper!(async_generator_delegate);
let arg = Box::new(Expr::Call(CallExpr {
let arg = CallExpr {
span: *span,
callee,
args: vec![
@ -484,34 +483,39 @@ impl VisitMut for AsyncFnBodyHandler {
helper_expr!(await_async_generator).as_arg(),
],
..Default::default()
}));
*expr = Expr::Yield(YieldExpr {
}
.into();
*expr = YieldExpr {
span: *span,
delegate: true,
arg: Some(arg),
})
}
.into()
}
Expr::Await(AwaitExpr { span, arg }) => {
if self.is_async_generator {
let callee = helper!(await_async_generator);
let arg = Box::new(Expr::Call(CallExpr {
let arg = CallExpr {
span: *span,
callee,
args: vec![arg.take().as_arg()],
..Default::default()
}));
*expr = Expr::Yield(YieldExpr {
}
.into();
*expr = YieldExpr {
span: *span,
delegate: false,
arg: Some(arg),
})
}
.into()
} else {
*expr = Expr::Yield(YieldExpr {
*expr = YieldExpr {
span: *span,
delegate: false,
arg: Some(arg.take()),
})
}
.into()
}
}
_ => {}
@ -606,7 +610,7 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
let var_decl = VarDeclarator {
span: DUMMY_SP,
name: var.name,
init: Some(Box::new(Expr::Ident(value))),
init: Some(value.into()),
definite: false,
};
for_loop_body.push(
@ -623,12 +627,13 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
ForHead::Pat(p) => {
for_loop_body.push(Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: p.try_into().unwrap(),
right: Box::new(Expr::Ident(value)),
})),
right: Box::new(value.into()),
}
.into(),
}));
}
@ -653,12 +658,15 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
init: {
let callee = helper!(async_iterator);
Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee,
args: vec![s.right.as_arg()],
..Default::default()
})))
Some(
CallExpr {
span: DUMMY_SP,
callee,
args: vec![s.right.as_arg()],
..Default::default()
}
.into(),
)
},
definite: false,
});
@ -693,49 +701,59 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
};
let yield_arg = if is_async_generator {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: helper!(await_async_generator),
args: vec![iter_next.as_arg()],
..Default::default()
}))
}
.into()
} else {
Box::new(Expr::Call(iter_next))
iter_next.into()
};
let assign_to_step = Expr::Assign(AssignExpr {
let assign_to_step: Expr = AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: step.into(),
right: Box::new(Expr::Yield(YieldExpr {
right: YieldExpr {
span: DUMMY_SP,
arg: Some(yield_arg),
delegate: false,
})),
});
}
.into(),
}
.into();
let right = Box::new(Expr::Unary(UnaryExpr {
let right = UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: assign_to_step.make_member(quote_ident!("done")).into(),
}));
}
.into();
let left = iterator_abrupt_completion.clone().into();
Some(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left,
right,
})))
Some(
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left,
right,
}
.into(),
)
},
// _iteratorNormalCompletion = true
update: Some(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: iterator_abrupt_completion.clone().into(),
right: false.into(),
}))),
update: Some(
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: iterator_abrupt_completion.clone().into(),
right: false.into(),
}
.into(),
),
body: Box::new(Stmt::Block(for_loop_body)),
});
@ -750,22 +768,24 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
// _didIteratorError = true;
let mark_as_errorred = Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: did_iteration_error.clone().into(),
right: true.into(),
})),
}
.into(),
});
// _iteratorError = err;
let store_error = Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Assign(AssignExpr {
expr: AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: iterator_error.clone().into(),
right: Box::new(Expr::Ident(err_param.clone())),
})),
right: Box::new(err_param.clone().into()),
}
.into(),
});
CatchClause {
@ -781,11 +801,11 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
let finally_block = {
let throw_iterator_error = Stmt::Throw(ThrowStmt {
span: DUMMY_SP,
arg: Box::new(Expr::Ident(iterator_error.clone())),
arg: iterator_error.clone().into(),
});
let throw_iterator_error = Stmt::If(IfStmt {
span: DUMMY_SP,
test: Box::new(Expr::Ident(did_iteration_error.clone())),
test: did_iteration_error.clone().into(),
cons: Box::new(Stmt::Block(BlockStmt {
span: DUMMY_SP,
stmts: vec![throw_iterator_error],
@ -794,7 +814,7 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
alt: None,
});
let iterator_return = Box::new(Expr::Call(CallExpr {
let iterator_return: Expr = CallExpr {
span: DUMMY_SP,
callee: iterator
.clone()
@ -802,45 +822,52 @@ fn handle_await_for(stmt: &mut Stmt, is_async_generator: bool) {
.as_callee(),
args: vec![],
..Default::default()
}));
}
.into();
// yield _iterator.return();
// or
// yield _awaitAsyncGenerator(_iterator.return());
let yield_stmt = Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(Expr::Yield(YieldExpr {
expr: YieldExpr {
span: DUMMY_SP,
delegate: false,
arg: Some(if is_async_generator {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: helper!(await_async_generator),
args: vec![iterator_return.as_arg()],
..Default::default()
}))
}
.into()
} else {
iterator_return
iterator_return.into()
}),
})),
}
.into(),
});
let conditional_yield = Stmt::If(IfStmt {
span: DUMMY_SP,
// _iteratorAbruptCompletion && _iterator.return != null
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
op: op!("&&"),
// _iteratorAbruptCompletion
left: Box::new(Expr::Ident(iterator_abrupt_completion.clone())),
left: Box::new(iterator_abrupt_completion.clone().into()),
// _iterator.return != null
right: Box::new(Expr::Bin(BinExpr {
span: DUMMY_SP,
op: op!("!="),
left: iterator.make_member(quote_ident!("return")).into(),
right: Null { span: DUMMY_SP }.into(),
})),
})),
right: Box::new(
BinExpr {
span: DUMMY_SP,
op: op!("!="),
left: iterator.make_member(quote_ident!("return")).into(),
right: Null { span: DUMMY_SP }.into(),
}
.into(),
),
}
.into(),
cons: Box::new(Stmt::Block(BlockStmt {
stmts: vec![yield_stmt],
..Default::default()

View File

@ -229,34 +229,41 @@ impl VisitMut for ObjectRest {
definite: false,
});
// println!("Expr: var_ident = right");
self.exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: var_ident.clone().into(),
op: op!("="),
right: right.take(),
})));
self.exprs.push(
AssignExpr {
span: DUMMY_SP,
left: var_ident.clone().into(),
op: op!("="),
right: right.take(),
}
.into(),
);
let pat = self.fold_rest(
&mut 0,
pat.take().into(),
Box::new(Expr::Ident(var_ident.clone())),
var_ident.clone().into(),
true,
true,
);
match pat {
Pat::Object(ObjectPat { ref props, .. }) if props.is_empty() => {}
_ => self.exprs.push(Box::new(Expr::Assign(AssignExpr {
span: *span,
left: pat.try_into().unwrap(),
op: op!("="),
right: Box::new(var_ident.clone().into()),
}))),
_ => self.exprs.push(
AssignExpr {
span: *span,
left: pat.try_into().unwrap(),
op: op!("="),
right: Box::new(var_ident.clone().into()),
}
.into(),
),
}
self.exprs.push(Box::new(var_ident.into()));
*expr = Expr::Seq(SeqExpr {
*expr = SeqExpr {
span: DUMMY_SP,
exprs: mem::take(&mut self.exprs),
});
}
.into();
};
}
@ -362,21 +369,24 @@ impl VisitMut for ObjectRest {
self.vars.push(VarDeclarator {
span: prop.span(),
name: *prop.arg,
init: Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: helper!(extends),
args: vec![
ObjectLit {
span: DUMMY_SP,
props: vec![],
}
.as_arg(),
helper_expr!(object_destructuring_empty)
.as_call(DUMMY_SP, vec![init.as_arg()])
init: Some(
CallExpr {
span: DUMMY_SP,
callee: helper!(extends),
args: vec![
ObjectLit {
span: DUMMY_SP,
props: vec![],
}
.as_arg(),
],
..Default::default()
}))),
helper_expr!(object_destructuring_empty)
.as_call(DUMMY_SP, vec![init.as_arg()])
.as_arg(),
],
..Default::default()
}
.into(),
),
definite: false,
});
continue;
@ -400,13 +410,8 @@ impl VisitMut for ObjectRest {
}
let mut index = self.vars.len();
let mut pat = self.fold_rest(
&mut index,
decl.name,
Box::new(Expr::Ident(var_ident.clone())),
false,
true,
);
let mut pat =
self.fold_rest(&mut index, decl.name, var_ident.clone().into(), false, true);
match pat {
// skip `{} = z`
Pat::Object(ObjectPat { ref props, .. }) if props.is_empty() => {}
@ -426,7 +431,7 @@ impl VisitMut for ObjectRest {
name: pat,
// preserve
init: if has_init {
Some(Box::new(Expr::Ident(var_ident.clone())))
Some(var_ident.clone().into())
} else {
None
},
@ -567,13 +572,8 @@ impl ObjectRest {
.map(|mut param| {
let var_ident = private_ident!(param.span(), "_param");
let mut index = self.vars.len();
param.pat = self.fold_rest(
&mut index,
param.pat,
Box::new(Expr::Ident(var_ident.clone())),
false,
true,
);
param.pat =
self.fold_rest(&mut index, param.pat, var_ident.clone().into(), false, true);
match param.pat {
Pat::Rest(..) | Pat::Ident(..) => param,
@ -591,18 +591,19 @@ impl ObjectRest {
VarDeclarator {
span,
name: *left,
init: Some(Box::new(Expr::Ident(var_ident.clone()))),
init: Some(var_ident.clone().into()),
definite: false,
},
);
Param {
span: DUMMY_SP,
decorators: Default::default(),
pat: Pat::Assign(AssignPat {
pat: AssignPat {
span,
left: var_ident.into(),
right,
}),
}
.into(),
}
}
_ => {
@ -612,7 +613,7 @@ impl ObjectRest {
VarDeclarator {
span: DUMMY_SP,
name: param.pat,
init: Some(Box::new(Expr::Ident(var_ident.clone()))),
init: Some(var_ident.clone().into()),
definite: false,
},
);
@ -693,7 +694,7 @@ impl ObjectRest {
use_expr_for_assign,
use_member_for_array,
));
return Pat::Assign(AssignPat { span, left, right });
return AssignPat { span, left, right }.into();
}
Pat::Array(n) => {
let ArrayPat { span, elems, .. } = n;
@ -717,7 +718,7 @@ impl ObjectRest {
})
.collect();
return Pat::Array(ArrayPat { span, elems, ..n });
return ArrayPat { span, elems, ..n }.into();
}
_ => return pat,
};
@ -760,11 +761,12 @@ impl ObjectRest {
key,
MemberProp::Computed(ComputedPropName {
span,
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span,
raw: None,
value: format!("{}", value).into(),
}))),
})
.into(),
}),
),
PropName::BigInt(BigInt {
@ -775,11 +777,12 @@ impl ObjectRest {
key,
MemberProp::Computed(ComputedPropName {
span,
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span,
raw: None,
value: format!("{}", value).into(),
}))),
})
.into(),
}),
)
}
@ -802,7 +805,7 @@ impl ObjectRest {
(
PropName::Computed(ComputedPropName {
span: c.span,
expr: Box::new(Expr::Ident(ident.clone())),
expr: ident.clone().into(),
}),
MemberProp::Computed(ComputedPropName {
span: c.span,
@ -837,12 +840,13 @@ impl ObjectRest {
match props.last() {
Some(ObjectPatProp::Rest(..)) => {}
_ => {
return Pat::Object(ObjectPat {
return ObjectPat {
span,
props,
optional: false,
type_ann,
});
}
.into();
}
}
let last = match props.pop() {
@ -854,16 +858,19 @@ impl ObjectRest {
if use_expr_for_assign {
// println!("Expr: last.arg = objectWithoutProperties()",);
self.exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
left: last.arg.try_into().unwrap(),
op: op!("="),
right: Box::new(object_without_properties(
obj,
excluded_props,
self.config.no_symbol,
)),
})));
self.exprs.push(
AssignExpr {
span: DUMMY_SP,
left: last.arg.try_into().unwrap(),
op: op!("="),
right: Box::new(object_without_properties(
obj,
excluded_props,
self.config.no_symbol,
)),
}
.into(),
);
} else {
// println!("Var: rest = objectWithoutProperties()",);
self.push_var_if_not_empty(VarDeclarator {
@ -878,12 +885,13 @@ impl ObjectRest {
});
}
Pat::Object(ObjectPat {
ObjectPat {
props,
span,
type_ann,
optional: false,
})
}
.into()
}
}
@ -894,7 +902,7 @@ fn object_without_properties(
no_symbol: bool,
) -> Expr {
if excluded_props.is_empty() {
return Expr::Call(CallExpr {
return CallExpr {
span: DUMMY_SP,
callee: helper!(extends),
args: vec![
@ -908,7 +916,8 @@ fn object_without_properties(
.as_arg(),
],
..Default::default()
});
}
.into();
}
let excluded_props = excluded_props
@ -916,11 +925,12 @@ fn object_without_properties(
.map(|v| {
v.map(|v| match *v.expr {
Expr::Lit(Lit::Num(Number { span, value, .. })) => ExprOrSpread {
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span,
raw: None,
value: value.to_string().into(),
}))),
})
.into(),
..v
},
_ => v,
@ -928,7 +938,7 @@ fn object_without_properties(
})
.collect();
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: if no_symbol {
helper!(object_without_properties_loose)
@ -959,7 +969,8 @@ fn object_without_properties(
},
],
..Default::default()
})
}
.into()
}
#[tracing::instrument(level = "info", skip_all)]

View File

@ -95,12 +95,13 @@ impl VisitMut for ObjectSpread {
buf
};
*expr = Expr::Call(CallExpr {
*expr = CallExpr {
span: *span,
callee,
args,
..Default::default()
});
}
.into();
}
}
}

View File

@ -109,14 +109,15 @@ impl VisitMut for NullishCoalescing {
}
let var_expr = if aliased {
Expr::Assign(AssignExpr {
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: l.clone().into(),
right: left.take(),
})
}
.into()
} else {
Expr::Ident(l.clone())
l.clone().into()
};
*e = make_cond(self.c, *span, &l, var_expr, right.take());
@ -125,7 +126,7 @@ impl VisitMut for NullishCoalescing {
Expr::Assign(ref mut assign @ AssignExpr { op: op!("??="), .. }) => {
match &mut assign.left {
AssignTarget::Simple(SimpleAssignTarget::Ident(i)) => {
*e = Expr::Assign(AssignExpr {
*e = AssignExpr {
span: assign.span,
op: op!("="),
left: i.clone().into(),
@ -136,7 +137,8 @@ impl VisitMut for NullishCoalescing {
Expr::Ident(Ident::from(&*i)),
assign.right.take(),
)),
});
}
.into();
}
AssignTarget::Simple(left) => {
@ -149,21 +151,23 @@ impl VisitMut for NullishCoalescing {
});
// TODO: Check for computed.
let right_expr = Box::new(Expr::Assign(AssignExpr {
let right_expr = AssignExpr {
span: assign.span,
left: left.clone().into(),
op: op!("="),
right: assign.right.take(),
}));
}
.into();
let var_expr = Expr::Assign(AssignExpr {
let var_expr = AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: alias.clone().into(),
right: left.take().into(),
});
}
.into();
*e = Expr::Assign(AssignExpr {
*e = AssignExpr {
span: assign.span,
op: op!("="),
left: alias.clone().into(),
@ -174,7 +178,8 @@ impl VisitMut for NullishCoalescing {
var_expr,
right_expr,
)),
});
}
.into();
}
_ => {}
@ -221,22 +226,23 @@ impl VisitMut for NullishCoalescing {
#[tracing::instrument(level = "info", skip_all)]
fn make_cond(c: Config, span: Span, alias: &Ident, var_expr: Expr, init: Box<Expr>) -> Expr {
Expr::Cond(if c.no_document_all {
if c.no_document_all {
CondExpr {
span,
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
left: Box::new(var_expr),
op: op!("!="),
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
})),
cons: Box::new(Expr::Ident(alias.clone())),
}
.into(),
cons: alias.clone().into(),
alt: init,
}
} else {
CondExpr {
span,
test: Box::new(Expr::Bin(BinExpr {
test: BinExpr {
span: DUMMY_SP,
left: Box::new(Expr::Bin(BinExpr {
span: DUMMY_SP,
@ -251,9 +257,11 @@ fn make_cond(c: Config, span: Span, alias: &Ident, var_expr: Expr, init: Box<Exp
op: op!("!=="),
right: Expr::undefined(DUMMY_SP),
})),
})),
cons: Box::new(Expr::Ident(alias.clone())),
}
.into(),
cons: alias.clone().into(),
alt: init,
}
})
}
.into()
}

View File

@ -111,13 +111,14 @@ impl VisitMut for Operators {
});
(
Box::new(Expr::Assign(AssignExpr {
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: alias.clone().into(),
right: obj.into(),
})),
Box::new(Expr::Ident(alias)),
}
.into(),
alias.into(),
)
}
};
@ -131,16 +132,18 @@ impl VisitMut for Operators {
};
(
Box::new(Expr::Member(MemberExpr {
MemberExpr {
span: DUMMY_SP,
obj: left_obj,
prop: left_prop,
})),
Box::new(Expr::Member(MemberExpr {
}
.into(),
MemberExpr {
span: DUMMY_SP,
obj: right_obj,
prop: right_prop,
})),
}
.into(),
)
}
_ => {
@ -149,12 +152,13 @@ impl VisitMut for Operators {
}
};
let right = Box::new(Expr::Assign(AssignExpr {
let right = AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: r_assign_target.try_into().unwrap(),
right: right.take(),
}));
}
.into();
let op = match *op {
op!("??=") => op!("??"),
@ -163,12 +167,13 @@ impl VisitMut for Operators {
_ => unreachable!(),
};
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op,
left: left_expr,
right,
});
}
.into();
}
}

View File

@ -19,7 +19,7 @@ impl<'a> VisitMut for ClassNameTdzFolder<'a> {
//
if i.sym == self.class_name.sym {
*expr = Expr::Seq(SeqExpr {
*expr = SeqExpr {
span: DUMMY_SP,
exprs: vec![
Box::new(Expr::Call(CallExpr {
@ -36,7 +36,8 @@ impl<'a> VisitMut for ClassNameTdzFolder<'a> {
})),
Box::new(Expr::Ident(i.clone())),
],
});
}
.into();
}
}

View File

@ -150,7 +150,7 @@ impl MemberInitRecord {
MemberInit::PubProp(PubProp { span, name, value }) => value_init.push(
if self.c.set_public_fields {
let this = ThisExpr { span: DUMMY_SP };
Expr::Assign(AssignExpr {
Expr::from(AssignExpr {
span,
left: match name {
PropName::Ident(id) => this.make_member(id).into(),
@ -160,7 +160,7 @@ impl MemberInitRecord {
right: value,
})
} else {
Expr::Call(CallExpr {
CallExpr {
span,
callee: helper!(define_property),
args: vec![
@ -169,7 +169,8 @@ impl MemberInitRecord {
value.as_arg(),
],
..Default::default()
})
}
.into()
}
.into(),
),
@ -193,7 +194,7 @@ impl MemberInitRecord {
span,
expr: (if self.c.set_public_fields {
let class = class_ident.clone();
Expr::Assign(AssignExpr {
Expr::from(AssignExpr {
span,
left: match name {
PropName::Ident(id) => class.make_member(id).into(),
@ -203,7 +204,7 @@ impl MemberInitRecord {
right: value,
})
} else {
Expr::Call(CallExpr {
CallExpr {
span,
callee: helper!(define_property),
args: vec![
@ -212,7 +213,8 @@ impl MemberInitRecord {
value.as_arg(),
],
..Default::default()
})
}
.into()
})
.into(),
}))
@ -221,7 +223,7 @@ impl MemberInitRecord {
value_init.push(if self.c.private_as_properties {
Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Call(CallExpr {
expr: CallExpr {
span,
callee: obj_def_prop(),
args: vec![
@ -230,7 +232,8 @@ impl MemberInitRecord {
get_value_desc(value).as_arg(),
],
..Default::default()
})),
}
.into(),
})
} else {
VarDecl {
@ -255,7 +258,7 @@ impl MemberInitRecord {
}) => normal_init.push(if self.c.private_as_properties {
Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Call(CallExpr {
expr: CallExpr {
span,
callee: obj_def_prop(),
args: vec![
@ -264,7 +267,8 @@ impl MemberInitRecord {
get_accessor_desc(getter, setter).as_arg(),
],
..Default::default()
})),
}
.into(),
})
} else {
VarDecl {

View File

@ -195,7 +195,7 @@ impl<C: Comments> VisitMut for ClassProperties<C> {
stmts.push(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Ident(ident))),
arg: Some(ident.into()),
}));
*body = BlockStmtOrExpr::BlockStmt(BlockStmt {
@ -221,10 +221,11 @@ impl<C: Comments> VisitMut for ClassProperties<C> {
let (decl, ClassExtra { lets, vars, stmts }) =
self.visit_mut_class_as_decl(ident.clone(), class.take());
let class = Expr::Class(ClassExpr {
let class = ClassExpr {
ident: orig_ident.clone(),
class: decl.class,
});
}
.into();
if vars.is_empty() && lets.is_empty() && stmts.is_empty() {
*expr = class;
return;
@ -319,10 +320,11 @@ impl<C: Comments> VisitMut for ClassProperties<C> {
exprs.push(Box::new(ident.into()))
}
*expr = Expr::Seq(SeqExpr {
*expr = SeqExpr {
span: DUMMY_SP,
exprs,
})
}
.into()
} else {
expr.visit_mut_children_with(self);
};
@ -579,7 +581,7 @@ impl<C: Comments> ClassProperties<C> {
// string.
PropName::Computed(ComputedPropName {
span: c_span,
expr: Box::new(Expr::Ident(ident)),
expr: ident.into(),
})
}
_ => method.key,
@ -629,7 +631,7 @@ impl<C: Comments> ClassProperties<C> {
definite: false,
});
}
*key.expr = Expr::from(ident);
*key.expr = ident.into();
}
_ => (),
};
@ -658,12 +660,13 @@ impl<C: Comments> ClassProperties<C> {
definite: false,
});
let span = super_class.span();
**super_class = Expr::Assign(AssignExpr {
**super_class = AssignExpr {
span,
op: op!("="),
left: ident.into(),
right: super_class.take(),
})
}
.into()
}
}
@ -766,24 +769,30 @@ impl<C: Comments> ClassProperties<C> {
span: DUMMY_SP,
definite: false,
name: ident.clone().into(),
init: Some(Box::new(Expr::from(CallExpr {
span,
callee: helper!(class_private_field_loose_key),
args: vec![ident.sym.as_arg()],
..Default::default()
}))),
init: Some(
CallExpr {
span,
callee: helper!(class_private_field_loose_key),
args: vec![ident.sym.as_arg()],
..Default::default()
}
.into(),
),
});
} else if !prop.is_static {
vars.push(VarDeclarator {
span: DUMMY_SP,
definite: false,
name: ident.into(),
init: Some(Box::new(Expr::from(NewExpr {
span,
callee: Box::new(Expr::Ident(quote_ident!("WeakMap").into())),
args: Some(Default::default()),
..Default::default()
}))),
init: Some(
NewExpr {
span,
callee: Box::new(quote_ident!("WeakMap").into()),
args: Some(Default::default()),
..Default::default()
}
.into(),
),
});
};
if prop.is_static {
@ -915,19 +924,21 @@ impl<C: Comments> ClassProperties<C> {
definite: false,
name: weak_coll_var.clone().into(),
init: Some(Box::new(if self.c.private_as_properties {
Expr::from(CallExpr {
CallExpr {
span,
callee: helper!(class_private_field_loose_key),
args: vec![weak_coll_var.sym.as_arg()],
..Default::default()
})
}
.into()
} else {
Expr::New(NewExpr {
NewExpr {
span,
callee: Box::new(Expr::Ident(extra.into())),
callee: extra.into(),
args: Some(Default::default()),
..Default::default()
})
}
.into()
})),
})
};

View File

@ -102,12 +102,13 @@ impl VisitMut for BrandCheckHandler<'_> {
if let Expr::Ident(right) = &**right {
let curr_class = self.private.curr_class();
if curr_class.sym == right.sym && curr_class.ctxt == right.ctxt {
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op: op!("==="),
left: Box::new(Expr::Ident(curr_class.clone())),
right: Box::new(Expr::Ident(right.clone())),
});
left: curr_class.clone().into(),
right: right.clone().into(),
}
.into();
return;
}
}
@ -119,12 +120,13 @@ impl VisitMut for BrandCheckHandler<'_> {
}
if kind.is_static {
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op: op!("==="),
left: right.take(),
right: Box::new(Expr::Ident(class_name.clone())),
});
right: class_name.clone().into(),
}
.into();
return;
}
@ -134,13 +136,14 @@ impl VisitMut for BrandCheckHandler<'_> {
SyntaxContext::empty().apply_mark(mark),
);
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
callee: weak_coll_ident.make_member(quote_ident!("has")).as_callee(),
args: vec![right.take().as_arg()],
..Default::default()
});
}
.into();
}
_ => {}
@ -254,12 +257,12 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
SyntaxContext::empty().apply_mark(mark),
);
*e = Expr::Call(CallExpr {
*e = CallExpr {
callee: helper!(class_private_field_loose_base),
span: *span,
args: vec![obj.take().as_arg(), ident.clone().as_arg()],
..Default::default()
})
}
.computed_member(ident)
.into();
} else {
@ -290,12 +293,13 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
let n = match &left.prop {
MemberProp::PrivateName(n) => n.clone(),
_ => {
*e = Expr::Assign(AssignExpr {
*e = AssignExpr {
span: *span,
left: left.into(),
op: *op,
right: right.take(),
});
}
.into();
return;
}
@ -355,7 +359,7 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
};
if kind.is_static {
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: DUMMY_SP,
callee: helper!(class_static_private_field_spec_set),
args: vec![
@ -366,7 +370,8 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
],
..Default::default()
});
}
.into();
} else if kind.is_readonly() {
let err = CallExpr {
span: DUMMY_SP,
@ -375,20 +380,22 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
..Default::default()
}
.into();
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: *span,
exprs: vec![this, value, err],
});
}
.into();
} else {
let set = helper!(class_private_field_set);
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: DUMMY_SP,
callee: set,
args: vec![this.as_arg(), ident.as_arg(), value.as_arg()],
..Default::default()
});
}
.into();
}
}
@ -415,24 +422,27 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
let (expr, this) = self.visit_mut_private_get(&mut tag, None);
if let Some(this) = this {
*e = Expr::TaggedTpl(TaggedTpl {
*e = TaggedTpl {
span: *span,
tag: Box::new(Expr::Call(CallExpr {
tag: CallExpr {
span: DUMMY_SP,
callee: expr.make_member(quote_ident!("bind")).as_callee(),
args: vec![this.as_arg()],
..Default::default()
})),
}
.into(),
tpl: tpl.take(),
..Default::default()
});
}
.into();
} else {
*e = Expr::TaggedTpl(TaggedTpl {
*e = TaggedTpl {
span: *span,
tag: Box::new(expr),
tpl: tpl.take(),
..Default::default()
});
}
.into();
}
}
@ -448,19 +458,21 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
let (expr, this) = self.visit_mut_private_get(&mut callee, None);
if let Some(this) = this {
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
callee: expr.make_member(quote_ident!("call")).as_callee(),
args: iter::once(this.as_arg()).chain(args.take()).collect(),
..Default::default()
});
}
.into();
} else {
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
callee: expr.as_callee(),
args: args.take(),
..Default::default()
});
}
.into();
}
}
@ -519,12 +531,12 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
SyntaxContext::empty().apply_mark(mark),
);
*e = Expr::Call(CallExpr {
*e = CallExpr {
callee: helper!(class_private_field_loose_base),
span: *span,
args: vec![obj.take().as_arg(), ident.clone().as_arg()],
..Default::default()
})
}
.computed_member(ident)
.into();
} else {
@ -662,7 +674,7 @@ impl<'a> PrivateAccessVisitor<'a> {
let h = helper!(class_static_private_method_get);
return (
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: h,
args: vec![
@ -671,21 +683,23 @@ impl<'a> PrivateAccessVisitor<'a> {
method_name.as_arg(),
],
..Default::default()
}),
Some(Expr::Ident(class_name.clone())),
}
.into(),
Some(class_name.clone().into()),
);
}
let get = helper!(class_static_private_field_spec_get);
(
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: get,
args: vec![obj.as_arg(), class_name.clone().as_arg(), ident.as_arg()],
..Default::default()
}),
Some(Expr::Ident(class_name.clone())),
}
.into(),
Some(class_name.clone().into()),
)
} else {
match self.private_access_type {
@ -821,7 +835,7 @@ impl<'a> PrivateAccessVisitor<'a> {
..Default::default()
}
.into(),
Some(Expr::Ident(var)),
Some(var.into()),
)
}
}

View File

@ -17,7 +17,7 @@ impl VisitMut for ThisInStaticFolder {
e.visit_mut_children_with(self);
if let Expr::This(..) = e {
*e = Expr::Ident(self.ident.clone())
*e = self.ident.clone().into()
}
}

View File

@ -116,9 +116,9 @@ impl VisitMut for OptionalChaining {
arg: Some(a.right.take()),
}),
];
a.right = Box::new(Expr::Call(CallExpr {
a.right = CallExpr {
span: DUMMY_SP,
callee: Expr::Arrow(ArrowExpr {
callee: ArrowExpr {
span: DUMMY_SP,
params: vec![],
body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt {
@ -129,11 +129,12 @@ impl VisitMut for OptionalChaining {
is_async: false,
is_generator: false,
..Default::default()
})
}
.as_callee(),
args: vec![],
..Default::default()
}));
}
.into();
}
self.vars = uninit;
@ -158,7 +159,7 @@ enum Memo {
impl Memo {
fn into_expr(self) -> Expr {
match self {
Memo::Cache(i) => Expr::Ident(i),
Memo::Cache(i) => i.into(),
Memo::Raw(e) => *e,
}
}
@ -259,12 +260,12 @@ impl OptionalChaining {
Gathering::Call(mut c) => {
c.callee = current.as_callee();
ctx = None;
Expr::Call(c)
c.into()
}
Gathering::Member(mut m) => {
m.obj = Box::new(current);
ctx = None;
Expr::Member(m)
m.into()
}
Gathering::OptCall(mut c, memo) => {
let mut call = false;
@ -278,12 +279,13 @@ impl OptionalChaining {
match &this {
Memo::Cache(i) => {
m.obj = Box::new(Expr::Assign(AssignExpr {
m.obj = AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: i.clone().into(),
right: m.obj.take(),
}));
}
.into();
this
}
Memo::Raw(_) => this,
@ -316,7 +318,7 @@ impl OptionalChaining {
memo.into_expr().as_callee()
};
ctx = None;
Expr::Call(c)
c.into()
}
Gathering::OptMember(mut m, memo) => {
committed_cond.push(CondExpr {
@ -331,24 +333,25 @@ impl OptionalChaining {
});
ctx = Some(memo.clone());
m.obj = memo.into_expr().into();
Expr::Member(m)
m.into()
}
};
}
// At this point, `current` is the right-most expression `_a_b.c` in `a?.b?.c`
if is_delete {
current = Expr::Unary(UnaryExpr {
current = UnaryExpr {
span: DUMMY_SP,
op: op!("delete"),
arg: Box::new(current),
});
}
.into();
}
// We now need to reverse iterate the conditionals to construct out tree.
for mut cond in committed_cond.into_iter().rev() {
cond.alt = Box::new(current);
current = Expr::Cond(cond)
current = cond.into()
}
current
}
@ -423,47 +426,52 @@ impl OptionalChaining {
fn init_and_eq_null_or_undefined(i: &Memo, init: Expr, no_document_all: bool) -> Box<Expr> {
let lhs = match i {
Memo::Cache(i) => Box::new(Expr::Assign(AssignExpr {
Memo::Cache(i) => AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: i.clone().into(),
right: Box::new(init),
})),
}
.into(),
Memo::Raw(e) => e.to_owned(),
};
if no_document_all {
return Box::new(Expr::Bin(BinExpr {
return BinExpr {
span: DUMMY_SP,
left: lhs,
op: op!("=="),
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
}));
right: Box::new(Lit::Null(Null { span: DUMMY_SP }).into()),
}
.into();
}
let null_cmp = Box::new(Expr::Bin(BinExpr {
let null_cmp = BinExpr {
span: DUMMY_SP,
left: lhs,
op: op!("==="),
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
}));
right: Box::new(Lit::Null(Null { span: DUMMY_SP }).into()),
}
.into();
let left_expr = match i {
Memo::Cache(i) => Box::new(i.clone().into()),
Memo::Raw(e) => e.to_owned(),
};
let void_cmp = Box::new(Expr::Bin(BinExpr {
let void_cmp = BinExpr {
span: DUMMY_SP,
left: left_expr,
op: op!("==="),
right: Expr::undefined(DUMMY_SP),
}));
}
.into();
Box::new(Expr::Bin(BinExpr {
BinExpr {
span: DUMMY_SP,
left: null_cmp,
op: op!("||"),
right: void_cmp,
}))
}
.into()
}

View File

@ -51,12 +51,15 @@ impl Mode {
definite: Default::default(),
});
if let Some(init) = init {
init_exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: n.into(),
right: init,
})));
init_exprs.push(
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: n.into(),
right: init,
}
.into(),
);
}
}
Mode::ClassDecl { vars } => {
@ -265,7 +268,7 @@ impl VisitMut for PrivateInObject {
}));
bs.visit_mut_with(self);
p.right = Box::new(Expr::Call(CallExpr {
p.right = CallExpr {
span: DUMMY_SP,
callee: ArrowExpr {
span: DUMMY_SP,
@ -278,7 +281,8 @@ impl VisitMut for PrivateInObject {
.as_callee(),
args: Default::default(),
..Default::default()
}));
}
.into();
}
}
}
@ -297,10 +301,11 @@ impl VisitMut for PrivateInObject {
}
_ => {
prepend_exprs.push(Box::new(e.take()));
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: DUMMY_SP,
exprs: prepend_exprs,
});
}
.into();
}
}
return;
@ -320,12 +325,13 @@ impl VisitMut for PrivateInObject {
if let Some(cls_ident) = self.cls.ident.clone() {
if is_static && is_method {
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op: op!("==="),
left: Box::new(Expr::Ident(cls_ident)),
left: cls_ident.into(),
right: right.take(),
});
}
.into();
return;
}
}
@ -337,18 +343,20 @@ impl VisitMut for PrivateInObject {
{
self.cls.vars.push_var(
var_name.clone(),
Some(Box::new(Expr::New(NewExpr {
span: DUMMY_SP,
callee: Box::new(Expr::Ident(quote_ident!("WeakSet").into())),
args: Some(Default::default()),
..Default::default()
}))),
Some(
NewExpr {
span: DUMMY_SP,
callee: Box::new(quote_ident!("WeakSet").into()),
args: Some(Default::default()),
..Default::default()
}
.into(),
),
);
if is_method {
self.cls
.constructor_exprs
.push(Box::new(Expr::Call(CallExpr {
self.cls.constructor_exprs.push(
CallExpr {
span: DUMMY_SP,
callee: var_name
.clone()
@ -356,16 +364,19 @@ impl VisitMut for PrivateInObject {
.as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
})));
}
.into(),
);
}
}
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
callee: var_name.make_member(quote_ident!("has")).as_callee(),
args: vec![right.take().as_arg()],
..Default::default()
});
}
.into();
}
_ => {}
@ -404,36 +415,45 @@ impl VisitMut for PrivateInObject {
self.cls.vars.push_var(tmp.clone(), None);
let assign = Box::new(Expr::Assign(AssignExpr {
let assign = AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: tmp.clone().into(),
right: init.take(),
}));
}
.into();
let add_to_checker = Box::new(Expr::Call(CallExpr {
let add_to_checker = CallExpr {
span: DUMMY_SP,
callee: var_name.make_member(quote_ident!("add")).as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
}));
}
.into();
*init = Box::new(Expr::Seq(SeqExpr {
*init = SeqExpr {
span: init_span,
exprs: vec![assign, add_to_checker, Box::new(tmp.into())],
}));
}
.into();
}
None => {
n.value = Some(Box::new(Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: Box::new(Expr::Call(CallExpr {
n.value = Some(
UnaryExpr {
span: DUMMY_SP,
callee: var_name.make_member(quote_ident!("add")).as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
})),
})))
op: op!("void"),
arg: Box::new(
CallExpr {
span: DUMMY_SP,
callee: var_name.make_member(quote_ident!("add")).as_callee(),
args: vec![ThisExpr { span: DUMMY_SP }.as_arg()],
..Default::default()
}
.into(),
),
}
.into(),
)
}
}
}

View File

@ -30,7 +30,7 @@ impl ClassStaticBlock {
} else {
static_block.body.stmts = stmts;
let expr = Expr::Call(CallExpr {
let expr = CallExpr {
span: DUMMY_SP,
callee: ArrowExpr {
span: DUMMY_SP,
@ -43,7 +43,8 @@ impl ClassStaticBlock {
.as_callee(),
args: Vec::new(),
..Default::default()
});
}
.into();
Some(Box::new(expr))
};

View File

@ -42,11 +42,12 @@ impl Fold for MemberExprLit {
return MemberExpr {
prop: MemberProp::Computed(ComputedPropName {
span: i.span,
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span: i.span,
raw: None,
value: i.sym,
}))),
})
.into(),
}),
..e
};

View File

@ -148,7 +148,7 @@ impl Hoister<'_> {
var_decls.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(id.into()),
name: id.into(),
init: None,
definite: false,
})
@ -157,12 +157,15 @@ impl Hoister<'_> {
if let Some(init) = decl.init {
//
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: decl.span,
left: decl.name.try_into().unwrap(),
op: op!("="),
right: init,
})));
exprs.push(
AssignExpr {
span: decl.span,
left: decl.name.try_into().unwrap(),
op: op!("="),
right: init,
}
.into(),
);
}
}
@ -174,10 +177,11 @@ impl Hoister<'_> {
expr: if exprs.len() == 1 {
exprs.into_iter().next().unwrap()
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
}))
}
.into()
},
})))
}

View File

@ -135,7 +135,7 @@ impl ArgReplacer<'_> {
let p = Param {
span: DUMMY_SP,
decorators: Default::default(),
pat: Pat::Ident(private_ident!(format!("argument_{}", start)).into()),
pat: private_ident!(format!("argument_{}", start)).into(),
};
start += 1;
p
@ -191,7 +191,7 @@ impl VisitMut for ArgReplacer<'_> {
"arguments: Replacing access to arguments to normal \
reference"
);
*n = Expr::Ident(i.id.clone());
*n = i.id.clone().into();
}
}
}
@ -213,7 +213,7 @@ impl VisitMut for ArgReplacer<'_> {
reference"
);
self.changed = true;
*n = Expr::Ident(i.id.clone());
*n = i.id.clone().into();
}
}
}

View File

@ -99,12 +99,13 @@ impl Optimizer<'_> {
report_change!("conditionals: `if (foo) bar;` => `foo && bar`");
*s = Stmt::Expr(ExprStmt {
span: stmt.span,
expr: Box::new(Expr::Bin(BinExpr {
expr: BinExpr {
span: stmt.test.span(),
op: op!("&&"),
left: stmt.test.take(),
right: cons.expr.take(),
})),
}
.into(),
});
}
}
@ -194,7 +195,7 @@ impl Optimizer<'_> {
span: e.span,
op: e.op,
left: left.left.take(),
right: Box::new(Expr::Bin(res)),
right: res.into(),
};
}
}
@ -283,7 +284,7 @@ impl Optimizer<'_> {
span,
op: op!("=="),
left: cmp.take(),
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
right: Lit::Null(Null { span: DUMMY_SP }).into(),
});
} else {
report_change!(
@ -293,7 +294,7 @@ impl Optimizer<'_> {
span,
op: op!("!="),
left: cmp.take(),
right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
right: Lit::Null(Null { span: DUMMY_SP }).into(),
});
}
}

View File

@ -66,24 +66,26 @@ impl Optimizer<'_> {
if !cond.cons.may_have_side_effects(&self.expr_ctx) {
self.changed = true;
report_change!("conditionals: `cond ? useless : alt` => `cond || alt`");
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("||"),
left: cond.test.take(),
right: cond.alt.take(),
});
}
.into();
return;
}
if !cond.alt.may_have_side_effects(&self.expr_ctx) {
self.changed = true;
report_change!("conditionals: `cond ? cons : useless` => `cond && cons`");
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("&&"),
left: cond.test.take(),
right: cond.cons.take(),
});
}
.into();
}
}
@ -144,12 +146,13 @@ impl Optimizer<'_> {
if SyntaxContext::within_ignored_ctxt(|| {
cur_if.cons.eq_ignore_span(&stmt.cons)
}) {
cur_if.test = Box::new(Expr::Bin(BinExpr {
cur_if.test = BinExpr {
span: DUMMY_SP,
left: cur_if.test.take(),
op: op!("||"),
right: stmt.test.take(),
}));
}
.into();
} else {
new.extend(cur.take().map(Stmt::If).map(T::from_stmt));
@ -244,31 +247,33 @@ impl Optimizer<'_> {
}) => {
report_change!("Optimizing `if (!foo); else bar();` as `foo && bar();`");
let mut expr = Box::new(Expr::Bin(BinExpr {
let mut expr = BinExpr {
span: DUMMY_SP,
left: arg.take(),
op: op!("&&"),
right: Box::new(alt.take()),
}));
}
.into();
self.compress_logical_exprs_as_bang_bang(&mut expr, true);
*s = Stmt::Expr(ExprStmt {
span: stmt.span,
expr,
expr: expr.into(),
});
}
_ => {
report_change!("Optimizing `if (foo); else bar();` as `foo || bar();`");
let mut expr = Box::new(Expr::Bin(BinExpr {
let mut expr = BinExpr {
span: DUMMY_SP,
left: stmt.test.take(),
op: op!("||"),
right: Box::new(alt.take()),
}));
}
.into();
self.compress_logical_exprs_as_bang_bang(&mut expr, false);
*s = Stmt::Expr(ExprStmt {
span: stmt.span,
expr,
expr: expr.into(),
});
}
}
@ -303,12 +308,13 @@ impl Optimizer<'_> {
self.changed = true;
*s = Stmt::Expr(ExprStmt {
span: stmt.span,
expr: Box::new(Expr::Cond(CondExpr {
expr: CondExpr {
span: DUMMY_SP,
test: stmt.test.take(),
cons: Box::new(cons.take()),
alt: Box::new(alt.take()),
})),
}
.into(),
})
}
}
@ -337,12 +343,13 @@ impl Optimizer<'_> {
if cond.test.is_ident() && cond.test.eq_ignore_span(&cond.cons) {
report_change!("Compressing `x ? x : y` as `x || y`");
self.changed = true;
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("||"),
left: cond.test.take(),
right: cond.alt.take(),
});
}
.into();
}
}
@ -358,10 +365,13 @@ impl Optimizer<'_> {
if cons.eq_ignore_span(alt) && !matches!(&*cons, Expr::Yield(..) | Expr::Fn(..)) {
report_change!("conditionals: cons is same as alt");
return Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs: vec![test.take(), Box::new(cons.take())],
}));
return Some(
SeqExpr {
span: DUMMY_SP,
exprs: vec![test.take(), Box::new(cons.take())],
}
.into(),
);
}
match (cons, alt) {
@ -418,12 +428,13 @@ impl Optimizer<'_> {
// Inject conditional.
new_args.push(ExprOrSpread {
spread: None,
expr: Box::new(Expr::Cond(CondExpr {
expr: CondExpr {
span: arg.expr.span(),
test: test.take(),
cons: arg.expr,
alt: alt.args[idx].expr.take(),
})),
}
.into(),
})
} else {
//
@ -431,12 +442,15 @@ impl Optimizer<'_> {
}
}
return Some(Expr::Call(CallExpr {
span: test.span(),
callee: cons_callee.clone().as_callee(),
args: new_args,
..Default::default()
}));
return Some(
CallExpr {
span: test.span(),
callee: cons_callee.clone().as_callee(),
args: new_args,
..Default::default()
}
.into(),
);
}
}
@ -466,22 +480,28 @@ impl Optimizer<'_> {
"Compressing if into cond as there's no side effect and the number of \
arguments is 1"
);
return Some(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: cons.callee.take(),
args,
..Default::default()
}));
return Some(
CallExpr {
span: DUMMY_SP,
callee: cons.callee.take(),
args,
..Default::default()
}
.into(),
);
}
if !side_effect_free && is_for_if_stmt {
report_change!("Compressing if into cond while preserving side effects");
return Some(Expr::Cond(CondExpr {
span: DUMMY_SP,
test: test.take(),
cons: Box::new(Expr::Call(cons.take())),
alt: Box::new(Expr::Call(alt.take())),
}));
return Some(
CondExpr {
span: DUMMY_SP,
test: test.take(),
cons: cons.take().into(),
alt: alt.take().into(),
}
.into(),
);
}
None
@ -532,12 +552,15 @@ impl Optimizer<'_> {
"Compressing if statement into a conditional expression of `new` as \
there's no side effect and the number of arguments is 1"
);
return Some(Expr::New(NewExpr {
span: DUMMY_SP,
callee: cons.callee.take(),
args: Some(args),
..Default::default()
}));
return Some(
NewExpr {
span: DUMMY_SP,
callee: cons.callee.take(),
args: Some(args),
..Default::default()
}
.into(),
);
}
None
@ -552,33 +575,41 @@ impl Optimizer<'_> {
}
report_change!("Merging assignments in cons and alt of if statement");
Some(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: cons.op,
left: cons.left.take(),
right: Box::new(Expr::Cond(CondExpr {
Some(
AssignExpr {
span: DUMMY_SP,
test: test.take(),
cons: cons.right.take(),
alt: alt.right.take(),
})),
}))
op: cons.op,
left: cons.left.take(),
right: CondExpr {
span: DUMMY_SP,
test: test.take(),
cons: cons.right.take(),
alt: alt.right.take(),
}
.into(),
}
.into(),
)
}
// a ? b ? c() : d() : d() => a && b ? c() : d()
(Expr::Cond(cons), alt) if (*cons.alt).eq_ignore_span(&*alt) => {
report_change!("conditionals: a ? b ? c() : d() : d() => a && b ? c() : d()");
Some(Expr::Cond(CondExpr {
span: DUMMY_SP,
test: Box::new(Expr::Bin(BinExpr {
Some(
CondExpr {
span: DUMMY_SP,
left: test.take(),
op: op!("&&"),
right: cons.test.take(),
})),
cons: cons.cons.take(),
alt: cons.alt.take(),
}))
test: BinExpr {
span: DUMMY_SP,
left: test.take(),
op: op!("&&"),
right: cons.test.take(),
}
.into(),
cons: cons.cons.take(),
alt: cons.alt.take(),
}
.into(),
)
}
// z ? "fuji" : (condition(), "fuji");
@ -589,16 +620,20 @@ impl Optimizer<'_> {
report_change!("conditionals: Reducing seq expr in alt");
//
alt.exprs.pop();
let first = Box::new(Expr::Bin(BinExpr {
let first = BinExpr {
span: DUMMY_SP,
left: test.take(),
op: op!("||"),
right: Expr::from_exprs(alt.exprs.take()),
}));
Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs: vec![first, Box::new(cons.take())],
}))
}
.into();
Some(
SeqExpr {
span: DUMMY_SP,
exprs: vec![first, Box::new(cons.take())],
}
.into(),
)
}
// z ? (condition(), "fuji") : "fuji"
@ -609,16 +644,20 @@ impl Optimizer<'_> {
report_change!("conditionals: Reducing seq expr in cons");
//
cons.exprs.pop();
let first = Box::new(Expr::Bin(BinExpr {
let first = BinExpr {
span: DUMMY_SP,
left: test.take(),
op: op!("&&"),
right: Expr::from_exprs(cons.exprs.take()),
}));
Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs: vec![first, Box::new(alt.take())],
}))
}
.into();
Some(
SeqExpr {
span: DUMMY_SP,
exprs: vec![first, Box::new(alt.take())],
}
.into(),
)
}
(Expr::Seq(left), Expr::Seq(right)) => {
@ -657,10 +696,13 @@ impl Optimizer<'_> {
}))];
seq.append(&mut left.exprs);
Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs: seq,
}))
Some(
SeqExpr {
span: DUMMY_SP,
exprs: seq,
}
.into(),
)
} else if idx == right_len {
self.changed = true;
report_change!("conditionals: Reducing similar seq expr in alt");
@ -677,10 +719,13 @@ impl Optimizer<'_> {
}))];
seq.append(&mut right.exprs);
Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs: seq,
}))
Some(
SeqExpr {
span: DUMMY_SP,
exprs: seq,
}
.into(),
)
} else {
self.changed = true;
report_change!("conditionals: Reducing similar seq expr");
@ -695,10 +740,13 @@ impl Optimizer<'_> {
}))];
seq.append(&mut common);
Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs: seq,
}))
Some(
SeqExpr {
span: DUMMY_SP,
exprs: seq,
}
.into(),
)
}
}

View File

@ -87,12 +87,13 @@ impl Optimizer<'_> {
);
self.changed = true;
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: assign.span,
op,
left: Box::new(Expr::Ident(lhs.clone().into())),
left: lhs.clone().into(),
right: assign.right.take(),
});
}
.into();
return true;
}
}

View File

@ -49,22 +49,24 @@ impl Optimizer<'_> {
"length" => {
report_change!("evaluate: function.length");
*e = Expr::Lit(Lit::Num(Number {
*e = Lit::Num(Number {
span: *span,
value: metadata.len as _,
raw: None,
}));
})
.into();
self.changed = true;
}
"name" => {
report_change!("evaluate: function.name");
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: *span,
value: obj.sym.clone(),
raw: None,
}));
})
.into();
self.changed = true;
}
@ -113,20 +115,23 @@ impl Optimizer<'_> {
Expr::Ident(Ident { span, sym, .. }) if &**sym == "Infinity" => {
report_change!("evaluate: `Infinity` -> `1 / 0`");
self.changed = true;
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op: op!("/"),
left: Box::new(Expr::Lit(Lit::Num(Number {
left: Lit::Num(Number {
span: DUMMY_SP,
value: 1.0,
raw: None,
}))),
right: Box::new(Expr::Lit(Lit::Num(Number {
})
.into(),
right: Lit::Num(Number {
span: DUMMY_SP,
value: 0.0,
raw: None,
}))),
});
})
.into(),
}
.into();
}
_ => {}
@ -187,11 +192,12 @@ impl Optimizer<'_> {
exp.value
);
*e = Expr::Lit(Lit::Regex(Regex {
*e = Lit::Regex(Regex {
span,
exp: exp.value.as_ref().into(),
flags: atom!(""),
}));
})
.into();
}
}
_ => {
@ -205,11 +211,12 @@ impl Optimizer<'_> {
flags.value
);
*e = Expr::Lit(Lit::Regex(Regex {
*e = Lit::Regex(Regex {
span,
exp: exp.value.as_ref().into(),
flags: flags.value.as_ref().into(),
}));
})
.into();
}
}
}
@ -242,11 +249,12 @@ impl Optimizer<'_> {
let value = v.to_string();
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value: value.into(),
}));
})
.into();
}
}
}
@ -272,28 +280,30 @@ impl Optimizer<'_> {
Prop::Shorthand(p) => {
keys.push(Some(ExprOrSpread {
spread: None,
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span: p.span,
raw: None,
value: p.sym.clone(),
}))),
})
.into(),
}));
}
Prop::KeyValue(p) => match &p.key {
PropName::Ident(key) => {
keys.push(Some(ExprOrSpread {
spread: None,
expr: Box::new(Expr::Lit(Lit::Str(Str {
expr: Lit::Str(Str {
span: key.span,
raw: None,
value: key.sym.clone(),
}))),
})
.into(),
}));
}
PropName::Str(key) => {
keys.push(Some(ExprOrSpread {
spread: None,
expr: Box::new(Expr::Lit(Lit::Str(key.clone()))),
expr: Lit::Str(key.clone()).into(),
}));
}
_ => return,
@ -303,7 +313,7 @@ impl Optimizer<'_> {
}
}
*e = Expr::Array(ArrayLit { span, elems: keys })
*e = ArrayLit { span, elems: keys }.into()
}
}
@ -335,11 +345,12 @@ impl Optimizer<'_> {
self.changed = true;
report_change!("evaluate: Evaluated an expression as `{}`", value);
*e = Expr::Lit(Lit::Num(Number {
*e = Lit::Num(Number {
span: e.span(),
value,
raw: None,
}));
})
.into();
return;
}
}
@ -355,17 +366,19 @@ impl Optimizer<'_> {
report_change!("evaluate: Evaluated `{:?} ** {:?}`", l, r);
if l.is_nan() || r.is_nan() {
*e = Expr::Ident(Ident::new(
*e = Ident::new(
"NaN".into(),
bin.span,
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
));
)
.into();
} else {
*e = Expr::Lit(Lit::Num(Number {
*e = Lit::Num(Number {
span: bin.span,
value: l.powf(r),
raw: None,
}));
})
.into();
};
}
}
@ -401,11 +414,12 @@ impl Optimizer<'_> {
report_change!("evaluate: `0 / 0` => `NaN`");
// Sign does not matter for NaN
*e = Expr::Ident(Ident::new(
*e = Ident::new(
"NaN".into(),
bin.span,
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
));
)
.into();
}
(FpCategory::Normal, FpCategory::Zero) => {
self.changed = true;
@ -413,16 +427,14 @@ impl Optimizer<'_> {
// Sign does not matter for NaN
*e = if ln.is_sign_positive() == rn.is_sign_positive() {
Expr::Ident(Ident::new_no_ctxt("Infinity".into(), bin.span))
Ident::new_no_ctxt("Infinity".into(), bin.span).into()
} else {
Expr::Unary(UnaryExpr {
UnaryExpr {
span: bin.span,
op: op!(unary, "-"),
arg: Box::new(Expr::Ident(Ident::new_no_ctxt(
"Infinity".into(),
bin.span,
))),
})
arg: Ident::new_no_ctxt("Infinity".into(), bin.span).into(),
}
.into()
};
}
_ => {}

View File

@ -31,12 +31,13 @@ impl Optimizer<'_> {
self.changed = true;
report_change!("if_return: Merging nested if statements");
s.test = Box::new(Expr::Bin(BinExpr {
s.test = BinExpr {
span: s.test.span(),
op: op!("&&"),
left: s.test.take(),
right: test.take(),
}));
}
.into();
s.cons = cons.take();
}
}
@ -313,7 +314,7 @@ impl Optimizer<'_> {
)
}
},
None => cur = Some(Box::new(Expr::Seq(v))),
None => cur = Some(v.into()),
},
Expr::Cond(v) => match &mut cur {
Some(cur) => match &mut **cur {
@ -328,26 +329,31 @@ impl Optimizer<'_> {
(prev_seq.span, exprs)
};
*alt = Expr::Cond(CondExpr {
*alt = CondExpr {
span: DUMMY_SP,
test: Box::new(Expr::Seq(SeqExpr { span, exprs })),
test: SeqExpr { span, exprs }.into(),
cons: v.cons,
alt: v.alt,
});
}
.into();
}
Expr::Seq(prev_seq) => {
prev_seq.exprs.push(v.test);
let exprs = prev_seq.exprs.take();
*cur = Box::new(Expr::Cond(CondExpr {
*cur = CondExpr {
span: DUMMY_SP,
test: Box::new(Expr::Seq(SeqExpr {
span: prev_seq.span,
exprs,
})),
test: Box::new(
SeqExpr {
span: prev_seq.span,
exprs,
}
.into(),
),
cons: v.cons,
alt: v.alt,
}));
}
.into();
}
_ => {
unreachable!(
@ -356,7 +362,7 @@ impl Optimizer<'_> {
)
}
},
None => cur = Some(Box::new(Expr::Cond(v))),
None => cur = Some(v.into()),
},
_ => {
unreachable!(
@ -432,34 +438,41 @@ impl Optimizer<'_> {
exprs.push(test);
Expr::Cond(CondExpr {
CondExpr {
span,
test: Box::new(Expr::Seq(SeqExpr {
test: SeqExpr {
span: DUMMY_SP,
exprs,
})),
}
.into(),
cons,
alt,
})
}
.into()
}
Stmt::Expr(stmt) => {
exprs.push(Box::new(Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: stmt.expr,
})));
Expr::Seq(SeqExpr {
exprs.push(
UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: stmt.expr,
}
.into(),
);
SeqExpr {
span: DUMMY_SP,
exprs,
})
}
.into()
}
Stmt::Return(stmt) => {
let span = stmt.span;
exprs.push(stmt.arg.unwrap_or_else(|| Expr::undefined(span)));
Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs,
})
}
.into()
}
_ => unreachable!(),
}

View File

@ -35,11 +35,12 @@ impl Optimizer<'_> {
if let Expr::Fn(..) = callee {
report_change!("negate_iife: Negating iife");
*e = Expr::Unary(UnaryExpr {
*e = UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: Box::new(e.take()),
});
}
.into();
}
}
@ -66,11 +67,12 @@ impl Optimizer<'_> {
match callee {
Expr::Fn(..) => {
report_change!("negate_iife: Swapping cons and alt");
cond.test = Box::new(Expr::Unary(UnaryExpr {
cond.test = UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg: cond.test.take(),
}));
}
.into();
swap(&mut cond.cons, &mut cond.alt);
true
}
@ -95,12 +97,13 @@ impl Optimizer<'_> {
}) = &mut **arg
{
if let Expr::Fn(..) = &**callee {
cond.test = Box::new(Expr::Call(CallExpr {
cond.test = CallExpr {
span: *call_span,
callee: callee.take().as_callee(),
args: args.take(),
..Default::default()
}));
}
.into();
swap(&mut cond.cons, &mut cond.alt);
}
}
@ -263,7 +266,7 @@ impl Optimizer<'_> {
vars.insert(
param_id.to_id(),
Box::new(Expr::Array(ArrayLit {
ArrayLit {
span: param_id.span,
elems: e
.args
@ -271,7 +274,8 @@ impl Optimizer<'_> {
.skip(idx)
.map(|arg| Some(arg.clone()))
.collect(),
})),
}
.into(),
);
param.take();
}
@ -899,7 +903,7 @@ impl Optimizer<'_> {
vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(param.clone().into()),
name: param.clone().into(),
init: if self.ctx.executed_multiple_time && no_arg {
Some(Expr::undefined(DUMMY_SP))
} else {
@ -970,12 +974,15 @@ impl Optimizer<'_> {
}
}
exprs.push(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: decl.name.clone().try_into().unwrap(),
right: decl.init.take().unwrap(),
})))
exprs.push(
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: decl.name.clone().try_into().unwrap(),
right: decl.init.take().unwrap(),
}
.into(),
)
}
}
@ -997,7 +1004,7 @@ impl Optimizer<'_> {
};
self.merge_sequences_in_seq_expr(&mut e);
let mut e = Expr::Seq(e);
let mut e = e.into();
self.normalize_expr(&mut e);
return Some(e);
}
@ -1006,11 +1013,12 @@ impl Optimizer<'_> {
}
if let Some(last) = exprs.last_mut() {
*last = Box::new(Expr::Unary(UnaryExpr {
*last = UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: last.take(),
}));
}
.into();
} else {
return Some(*Expr::undefined(body.span));
}
@ -1021,7 +1029,7 @@ impl Optimizer<'_> {
};
self.merge_sequences_in_seq_expr(&mut e);
let mut e = Expr::Seq(e);
let mut e = e.into();
self.normalize_expr(&mut e);
Some(e)
}

View File

@ -688,10 +688,11 @@ impl Optimizer<'_> {
self.vars.simple_functions.insert(
i.to_id(),
Box::new(Expr::Fn(FnExpr {
FnExpr {
ident: None,
function: f.function.clone(),
})),
}
.into(),
);
return;
@ -764,18 +765,20 @@ impl Optimizer<'_> {
}
let e = match decl.take() {
Decl::Class(c) => Box::new(Expr::Class(ClassExpr {
Decl::Class(c) => ClassExpr {
ident: Some(c.ident),
class: c.class,
})),
Decl::Fn(f) => Box::new(Expr::Fn(FnExpr {
}
.into(),
Decl::Fn(f) => FnExpr {
ident: if usage.used_recursively {
Some(f.ident)
} else {
None
},
function: f.function,
})),
}
.into(),
_ => {
unreachable!()
}

View File

@ -641,15 +641,17 @@ impl Optimizer<'_> {
if let Lit::Bool(v) = lit {
self.changed = true;
report_change!("Compressing boolean literal");
*e = Expr::Unary(UnaryExpr {
*e = UnaryExpr {
span: v.span,
op: op!("!"),
arg: Box::new(Expr::Lit(Lit::Num(Number {
arg: Lit::Num(Number {
span: v.span,
value: if v.value { 0.0 } else { 1.0 },
raw: None,
}))),
});
})
.into(),
}
.into();
}
}
}
@ -716,7 +718,7 @@ impl Optimizer<'_> {
.any(|m| m.as_static_block().iter().any(|s| !s.body.is_empty()))
{
// there's nothing we can do about it
return Some(Expr::Class(cls.take()));
return Some(cls.take().into());
}
let exprs: Vec<Box<Expr>> =
@ -730,10 +732,13 @@ impl Optimizer<'_> {
return None;
}
return Some(Expr::Seq(SeqExpr {
span: cls.class.span,
exprs,
}));
return Some(
SeqExpr {
span: cls.class.span,
exprs,
}
.into(),
);
}
Expr::Paren(e) => return self.ignore_return_value(&mut e.expr),
@ -807,10 +812,13 @@ impl Optimizer<'_> {
self.changed = true;
report_change!("ignore_return_value: Compressing binary as seq");
return Some(Expr::Seq(SeqExpr {
span,
exprs: vec![Box::new(left.unwrap()), Box::new(right.unwrap())],
}));
return Some(
SeqExpr {
span,
exprs: vec![Box::new(left.unwrap()), Box::new(right.unwrap())],
}
.into(),
);
}
// Pure calls can be removed
@ -890,10 +898,13 @@ impl Optimizer<'_> {
return None;
}
return Some(Expr::Array(ArrayLit {
span: callee.span,
elems,
}));
return Some(
ArrayLit {
span: callee.span,
elems,
}
.into(),
);
}
let args = args
@ -907,10 +918,13 @@ impl Optimizer<'_> {
return None;
}
return Some(Expr::Seq(SeqExpr {
span: callee.span,
exprs: args,
}));
return Some(
SeqExpr {
span: callee.span,
exprs: args,
}
.into(),
);
}
}
}
@ -1022,25 +1036,28 @@ impl Optimizer<'_> {
}) => true,
_ => false,
}) {
return Some(Expr::Array(ArrayLit {
elems: arr
.elems
.take()
.into_iter()
.flatten()
.filter_map(|mut e| {
if e.spread.is_some() {
return Some(e);
}
return Some(
ArrayLit {
elems: arr
.elems
.take()
.into_iter()
.flatten()
.filter_map(|mut e| {
if e.spread.is_some() {
return Some(e);
}
self.ignore_return_value(&mut e.expr)
.map(Box::new)
.map(|expr| ExprOrSpread { expr, spread: None })
})
.map(Some)
.collect(),
..*arr
}));
self.ignore_return_value(&mut e.expr)
.map(Box::new)
.map(|expr| ExprOrSpread { expr, spread: None })
})
.map(Some)
.collect(),
..*arr
}
.into(),
);
}
let mut exprs = vec![];
@ -1060,10 +1077,13 @@ impl Optimizer<'_> {
return None;
}
return Some(Expr::Seq(SeqExpr {
span: arr.span,
exprs,
}));
return Some(
SeqExpr {
span: arr.span,
exprs,
}
.into(),
);
}
Expr::Object(obj) => {
@ -1120,10 +1140,13 @@ impl Optimizer<'_> {
return None;
}
return Some(Expr::Seq(SeqExpr {
span: obj.span,
exprs,
}));
return Some(
SeqExpr {
span: obj.span,
exprs,
}
.into(),
);
}
// Preserves negated iife
@ -1174,10 +1197,11 @@ impl Optimizer<'_> {
let left = self.ignore_return_value(left).map(Box::new);
let right = self.ignore_return_value(right).map(Box::new);
let mut seq = Expr::Seq(SeqExpr {
let mut seq = SeqExpr {
span: *span,
exprs: left.into_iter().chain(right).collect(),
});
}
.into();
return self.ignore_return_value(&mut seq);
}
@ -1205,20 +1229,23 @@ impl Optimizer<'_> {
// TODO: Remove if test is side effect free.
return Some(Expr::Cond(CondExpr {
span: cond.span,
test: cond.test.take(),
cons: cons.unwrap_or_else(|| {
report_change!("ignore_return_value: Dropped `cons`");
self.changed = true;
Expr::undefined(cons_span)
}),
alt: alt.unwrap_or_else(|| {
report_change!("ignore_return_value: Dropped `alt`");
self.changed = true;
Expr::undefined(alt_span)
}),
}));
return Some(
CondExpr {
span: cond.span,
test: cond.test.take(),
cons: cons.unwrap_or_else(|| {
report_change!("ignore_return_value: Dropped `cons`");
self.changed = true;
Expr::undefined(cons_span)
}),
alt: alt.unwrap_or_else(|| {
report_change!("ignore_return_value: Dropped `alt`");
self.changed = true;
Expr::undefined(alt_span)
}),
}
.into(),
);
}
Expr::Seq(seq) => {
@ -1263,11 +1290,12 @@ impl Optimizer<'_> {
if let Some(last) = exprs.last_mut() {
report_change!("ignore_return_value: Shifting void");
self.changed = true;
*last = Box::new(Expr::Unary(UnaryExpr {
*last = UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: last.take(),
}));
}
.into();
}
}
@ -1276,10 +1304,13 @@ impl Optimizer<'_> {
return None;
}
return Some(Expr::Seq(SeqExpr {
span: seq.span,
exprs,
}));
return Some(
SeqExpr {
span: seq.span,
exprs,
}
.into(),
);
}
}
@ -1626,18 +1657,20 @@ impl VisitMut for Optimizer<'_> {
if is_this_undefined {
if let Callee::Expr(callee) = &mut e.callee {
if let Expr::Member(..) = &mut **callee {
let zero = Box::new(Expr::Lit(Lit::Num(Number {
let zero = Lit::Num(Number {
span: DUMMY_SP,
value: 0.0,
raw: None,
})));
})
.into();
self.changed = true;
report_change!("injecting zero to preserve `this` in call");
*callee = Box::new(Expr::Seq(SeqExpr {
*callee = SeqExpr {
span: callee.span(),
exprs: vec![zero, callee.take()],
}));
}
.into();
}
}
}
@ -2393,12 +2426,12 @@ impl VisitMut for Optimizer<'_> {
if let Prop::Shorthand(i) = n {
if self.vars.has_pending_inline_for(&i.to_id()) {
let mut e = Box::new(Expr::Ident(i.clone()));
let mut e: Expr = i.clone().into();
e.visit_mut_with(self);
*n = Prop::KeyValue(KeyValueProp {
key: PropName::Ident(i.clone().into()),
value: e,
value: Box::new(e),
});
}
}
@ -3036,10 +3069,11 @@ impl VisitMut for Optimizer<'_> {
expr: if side_effects.len() == 1 {
side_effects.remove(0)
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs: side_effects.take(),
}))
}
.into()
},
}));
} else {
@ -3061,10 +3095,11 @@ impl VisitMut for Optimizer<'_> {
expr: if side_effects.len() == 1 {
side_effects.remove(0)
} else {
Box::new(Expr::Seq(SeqExpr {
SeqExpr {
span: DUMMY_SP,
exprs: side_effects,
}))
}
.into()
},
}));
}

View File

@ -119,10 +119,13 @@ impl Optimizer<'_> {
let flag = n.op == op!("!=");
let mut make_lit_bool = |value: bool| {
self.changed = true;
Some(Expr::Lit(Lit::Bool(Bool {
span: n.span,
value: flag ^ value,
})))
Some(
Lit::Bool(Bool {
span: n.span,
value: flag ^ value,
})
.into(),
)
};
match (n.left.get_type().opt()?, n.right.get_type().opt()?) {
// Abort if types differ, or one of them is unknown.
@ -358,32 +361,35 @@ impl Optimizer<'_> {
"Converting typeof of variable to literal as we know the value"
);
self.changed = true;
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: *span,
raw: None,
value,
}));
})
.into();
}
}
Expr::Arrow(..) | Expr::Fn(..) => {
report_change!("Converting typeof to 'function' as we know the value");
self.changed = true;
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: *span,
raw: None,
value: "function".into(),
}));
})
.into();
}
Expr::Array(..) | Expr::Object(..) => {
report_change!("Converting typeof to 'object' as we know the value");
self.changed = true;
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: *span,
raw: None,
value: "object".into(),
}));
})
.into();
}
_ => {}
}

View File

@ -458,12 +458,13 @@ impl Optimizer<'_> {
report_change!("sequences: Lifting Assign");
self.changed = true;
if let Some(last) = seq.exprs.last_mut() {
**last = Expr::Assign(AssignExpr {
**last = AssignExpr {
span: *span,
op: op!("="),
left: left.take(),
right: last.take(),
})
}
.into()
}
*e = *right.take()
@ -541,11 +542,12 @@ impl Optimizer<'_> {
e.exprs.pop();
let last = e.exprs.last_mut().unwrap();
*last = Box::new(Expr::Unary(UnaryExpr {
*last = UnaryExpr {
span: DUMMY_SP,
op: op!("void"),
arg: last.take(),
}))
}
.into()
}
}
}
@ -1279,7 +1281,7 @@ impl Optimizer<'_> {
}
}
if !self.is_skippable_for_seq(a, &Expr::Ident(left_id.id.clone())) {
if !self.is_skippable_for_seq(a, &left_id.id.clone().into()) {
return false;
}
@ -1315,7 +1317,7 @@ impl Optimizer<'_> {
PropOrSpread::Spread(_) => return false,
PropOrSpread::Prop(p) => match &**p {
Prop::Shorthand(i) => {
if !self.is_skippable_for_seq(a, &Expr::Ident(i.clone())) {
if !self.is_skippable_for_seq(a, &i.clone().into()) {
return false;
}
}
@ -1785,7 +1787,7 @@ impl Optimizer<'_> {
return Ok(false);
};
if !self.is_skippable_for_seq(Some(a), &Expr::Ident(b_left.id.clone())) {
if !self.is_skippable_for_seq(Some(a), &b_left.id.clone().into()) {
// Let's be safe
if IdentUsageFinder::find(&b_left.to_id(), &b_assign.right) {
return Ok(false);
@ -1871,17 +1873,19 @@ impl Optimizer<'_> {
if self.merge_sequential_expr(a, b_callee)? {
if is_this_undefined {
if let Expr::Member(..) = &**b_callee {
let zero = Box::new(Expr::Lit(Lit::Num(Number {
let zero = Lit::Num(Number {
span: DUMMY_SP,
value: 0.0,
raw: None,
})));
})
.into();
report_change!("injecting zero to preserve `this` in call");
*b_callee = Box::new(Expr::Seq(SeqExpr {
*b_callee = SeqExpr {
span: b_callee.span(),
exprs: vec![zero, b_callee.take()],
}));
}
.into();
}
}
@ -1988,7 +1992,7 @@ impl Optimizer<'_> {
// We can't ignore shorthand properties
//
// https://github.com/swc-project/swc/issues/6914
let mut new_b = Box::new(Expr::Ident(shorthand.clone()));
let mut new_b = shorthand.clone().into();
if self.merge_sequential_expr(a, &mut new_b)? {
*prop = Box::new(Prop::KeyValue(KeyValueProp {
key: Ident::new_no_ctxt(
@ -1996,7 +2000,7 @@ impl Optimizer<'_> {
shorthand.span,
)
.into(),
value: new_b.clone(),
value: new_b.clone().into(),
}));
}
@ -2123,12 +2127,13 @@ impl Optimizer<'_> {
if let Expr::Ident(orig_expr) = &*e {
if orig_expr.to_id() == a_id.to_id() {
replaced = true;
*e = Expr::Update(UpdateExpr {
*e = UpdateExpr {
span: DUMMY_SP,
op: *op,
prefix: true,
arg: Box::new(Expr::Ident(orig_expr.clone())),
});
arg: orig_expr.clone().into(),
}
.into();
return;
}
}
@ -2197,12 +2202,13 @@ impl Optimizer<'_> {
if let Expr::Ident(orig_expr) = &*e {
if orig_expr.to_id() == a_id.to_id() {
replaced = true;
*e = Expr::Update(UpdateExpr {
*e = UpdateExpr {
span: DUMMY_SP,
op: *op,
prefix: true,
arg: Box::new(Expr::Ident(orig_expr.clone())),
});
arg: orig_expr.clone().into(),
}
.into();
return;
}
}
@ -2421,10 +2427,11 @@ impl Optimizer<'_> {
Mergable::FnDecl(a) => {
// We can inline a function declaration as a function expression.
Box::new(Expr::Fn(FnExpr {
FnExpr {
ident: Some(a.ident.take()),
function: a.function.take(),
}))
}
.into()
}
Mergable::Drop => {
@ -2445,10 +2452,11 @@ impl Optimizer<'_> {
let a_expr = self.ignore_return_value(&mut a_expr);
if let Some(a) = a_expr {
b.right = Box::new(Expr::Seq(SeqExpr {
b.right = SeqExpr {
span: DUMMY_SP,
exprs: vec![Box::new(a), b.right.take()],
}));
}
.into();
}
return Ok(true);
}
@ -2476,12 +2484,13 @@ impl Optimizer<'_> {
let to = take_a(a, true, true);
b.right = Box::new(Expr::Bin(BinExpr {
b.right = BinExpr {
span: DUMMY_SP,
op: bin_op,
left: to,
right: b.right.take(),
}));
}
.into();
return Ok(true);
}
}

View File

@ -65,11 +65,12 @@ impl Optimizer<'_> {
report_change!(
"strings: Converted an expression into a string literal (in string context)"
);
*n = Expr::Lit(Lit::Str(Str {
*n = Lit::Str(Str {
span,
raw: None,
value: value.into(),
}));
})
.into();
return;
}
@ -84,11 +85,12 @@ impl Optimizer<'_> {
let value = format!("{:?}", v.value);
*n = Expr::Lit(Lit::Str(Str {
*n = Lit::Str(Str {
span: v.span,
raw: None,
value: value.into(),
}));
})
.into();
}
Expr::Lit(Lit::Regex(v)) => {
@ -104,11 +106,12 @@ impl Optimizer<'_> {
let value = format!("/{}/{}", v.exp, v.flags);
*n = Expr::Lit(Lit::Str(Str {
*n = Lit::Str(Str {
span: v.span,
raw: None,
value: value.into(),
}));
})
.into();
}
Expr::Bin(BinExpr {
@ -119,11 +122,12 @@ impl Optimizer<'_> {
}) => {
if let (Expr::Lit(Lit::Num(l)), Expr::Lit(Lit::Num(r))) = (&**left, &**right) {
if l.value == 0.0 && r.value == 0.0 {
*n = Expr::Ident(Ident::new(
*n = Ident::new(
"NaN".into(),
*span,
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
));
)
.into();
self.changed = true;
report_change!("strings: Evaluated 0 / 0 => NaN in string context");
}

View File

@ -112,7 +112,7 @@ impl Optimizer<'_> {
.into_iter()
.map(|name| VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(name.into()),
name: name.into(),
init: None,
definite: Default::default(),
})
@ -369,12 +369,13 @@ impl Optimizer<'_> {
let discriminant = sw.discriminant.take();
if let Some(test) = case.test {
let test = Box::new(Expr::Bin(BinExpr {
let test = BinExpr {
left: discriminant,
right: test,
op: op!("==="),
span: DUMMY_SP,
}));
}
.into();
*s = Stmt::If(IfStmt {
span: sw.span,

View File

@ -206,7 +206,7 @@ impl Optimizer<'_> {
if let Some(VarDeclKind::Const | VarDeclKind::Let) = self.ctx.var_kind {
*e = Null { span: DUMMY_SP }.into();
} else {
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
}
}
}
@ -677,10 +677,11 @@ impl Optimizer<'_> {
);
self.changed = true;
if self.ctx.is_this_aware_callee {
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: DUMMY_SP,
exprs: vec![0.into(), assign.right.take()],
})
}
.into()
} else {
*e = *assign.right.take();
}

View File

@ -276,12 +276,13 @@ impl<'a> Finalizer<'a> {
e.visit_mut_children_with(self);
match &*e {
Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => {
Some(Box::new(Expr::Seq(SeqExpr {
Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => Some(
SeqExpr {
span: DUMMY_SP,
exprs: vec![0.into(), e],
})))
}
}
.into(),
),
_ => Some(e),
}
}
@ -469,12 +470,13 @@ impl<'a> NormalMultiReplacer<'a> {
e.visit_mut_children_with(self);
match &*e {
Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => {
Some(Box::new(Expr::Seq(SeqExpr {
Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => Some(
SeqExpr {
span: DUMMY_SP,
exprs: vec![0.into(), e],
})))
}
}
.into(),
),
_ => Some(e),
}
}
@ -553,12 +555,13 @@ impl ExprReplacer {
let e = self.to.take()?;
match &*e {
Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => {
Some(Box::new(Expr::Seq(SeqExpr {
Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => Some(
SeqExpr {
span: DUMMY_SP,
exprs: vec![0.into(), e],
})))
}
}
.into(),
),
_ => Some(e),
}
}

View File

@ -28,14 +28,15 @@ impl Pure<'_> {
self.changed = true;
report_change!("unsafe_arrows: Fn expr => arrow");
*e = Expr::Arrow(ArrowExpr {
*e = ArrowExpr {
span: function.span,
params: function.params.take().into_iter().map(|p| p.pat).collect(),
body: Box::new(BlockStmtOrExpr::BlockStmt(function.body.take().unwrap())),
is_async: function.is_async,
is_generator: function.is_generator,
..Default::default()
});
}
.into();
}
}
@ -94,7 +95,7 @@ impl Pure<'_> {
*p = Prop::KeyValue(KeyValueProp {
key: m.key.take(),
value: Box::new(Expr::Arrow(ArrowExpr {
value: ArrowExpr {
span: m_span,
params: m
.function
@ -107,7 +108,8 @@ impl Pure<'_> {
is_async: m.function.is_async,
is_generator: m.function.is_generator,
..Default::default()
})),
}
.into(),
});
return;
}

View File

@ -233,10 +233,11 @@ impl Pure<'_> {
self.changed = true;
let span = delete.arg.span();
report_change!("booleans: Compressing `delete` as sequence expression");
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span,
exprs: vec![delete.arg.take(), Box::new(make_bool(span, true))],
});
}
.into();
return;
}
}
@ -321,11 +322,12 @@ impl Pure<'_> {
report_change!("Optimizing: number => number (in bool context)");
self.changed = true;
*n = Expr::Lit(Lit::Num(Number {
*n = Lit::Num(Number {
span: *span,
value: if *value == 0.0 { 1.0 } else { 0.0 },
raw: None,
}))
})
.into()
}
Expr::Unary(UnaryExpr {
@ -348,23 +350,26 @@ impl Pure<'_> {
match &**arg {
Expr::Ident(..) => {
*n = Expr::Lit(Lit::Num(Number {
*n = Lit::Num(Number {
span: *span,
value: 1.0,
raw: None,
}))
})
.into()
}
_ => {
// Return value of typeof is always truthy
let true_expr = Box::new(Expr::Lit(Lit::Num(Number {
let true_expr = Lit::Num(Number {
span: *span,
value: 1.0,
raw: None,
})));
*n = Expr::Seq(SeqExpr {
})
.into();
*n = SeqExpr {
span: *span,
exprs: vec![arg.take(), true_expr],
})
}
.into()
}
}
}
@ -373,11 +378,12 @@ impl Pure<'_> {
if !is_ignore {
report_change!("Converting string as boolean expressions");
self.changed = true;
*n = Expr::Lit(Lit::Num(Number {
*n = Lit::Num(Number {
span: s.span,
value: if s.value.is_empty() { 0.0 } else { 1.0 },
raw: None,
}));
})
.into();
}
}
@ -388,11 +394,12 @@ impl Pure<'_> {
if self.options.bools {
report_change!("booleans: Converting number as boolean expressions");
self.changed = true;
*n = Expr::Lit(Lit::Num(Number {
*n = Lit::Num(Number {
span: num.span,
value: if num.value == 0.0 { 0.0 } else { 1.0 },
raw: None,
}));
})
.into();
}
}

View File

@ -30,12 +30,13 @@ impl Pure<'_> {
self.negate_twice(&mut cond.test, false);
self.changed = true;
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("||"),
left: cond.test.take(),
right: cond.alt.take(),
});
}
.into();
return;
}
@ -46,12 +47,13 @@ impl Pure<'_> {
self.changed = true;
self.negate(&mut cond.test, false, false);
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("&&"),
left: cond.test.take(),
right: cond.alt.take(),
});
}
.into();
return;
}
}
@ -66,12 +68,13 @@ impl Pure<'_> {
// Negate twice to convert `test` to boolean.
self.negate_twice(&mut cond.test, false);
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("&&"),
left: cond.test.take(),
right: cond.cons.take(),
});
}
.into();
return;
}
@ -81,12 +84,13 @@ impl Pure<'_> {
self.negate(&mut cond.test, false, false);
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("||"),
left: cond.test.take(),
right: cond.cons.take(),
});
}
.into();
}
}
}
@ -110,17 +114,19 @@ impl Pure<'_> {
report_change!("conditionals: `x ? y || z : z` => `x || y && z`");
self.changed = true;
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: cond.span,
op: op!("||"),
left: Box::new(Expr::Bin(BinExpr {
left: BinExpr {
span: cons_span,
op: op!("&&"),
left: cond.test.take(),
right: cons.left.take(),
})),
}
.into(),
right: cons.right.take(),
});
}
.into();
}
_ => {}
}

View File

@ -525,7 +525,7 @@ impl Pure<'_> {
.into_iter()
.map(|name| VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(name.into()),
name: name.into(),
init: None,
definite: Default::default(),
})
@ -551,7 +551,7 @@ impl Pure<'_> {
.into_iter()
.map(|name| VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(name.into()),
name: name.into(),
init: None,
definite: Default::default(),
})

View File

@ -88,16 +88,17 @@ impl Pure<'_> {
report_change!("evaluate: Reducing array.slice({}) call", start);
if start >= arr.elems.len() {
*e = Expr::Array(ArrayLit {
*e = ArrayLit {
span: *span,
elems: Default::default(),
});
}
.into();
return;
}
let elems = arr.elems.drain(start..).collect();
*e = Expr::Array(ArrayLit { span: *span, elems });
*e = ArrayLit { span: *span, elems }.into();
}
}
_ => {
@ -129,16 +130,17 @@ impl Pure<'_> {
end
);
if start >= arr.elems.len() {
*e = Expr::Array(ArrayLit {
*e = ArrayLit {
span: *span,
elems: Default::default(),
});
}
.into();
return;
}
let elems = arr.elems.drain(start..end).collect();
*e = Expr::Array(ArrayLit { span: *span, elems });
*e = ArrayLit { span: *span, elems }.into();
}
}
}
@ -282,11 +284,12 @@ impl Pure<'_> {
"evaluate: Reducing a call to `Number` into an unary operation"
);
*e = Expr::Unary(UnaryExpr {
*e = UnaryExpr {
span: *span,
op: op!(unary, "+"),
arg: args.take().into_iter().next().unwrap().expr,
});
}
.into();
}
}
}
@ -369,11 +372,12 @@ impl Pure<'_> {
value
);
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value: value.into(),
}));
})
.into();
}
return;
@ -393,11 +397,12 @@ impl Pure<'_> {
value
);
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value,
}));
})
.into();
return;
}
@ -418,11 +423,12 @@ impl Pure<'_> {
num,
value
);
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value: value.into(),
}));
})
.into();
return;
}
}
@ -439,11 +445,12 @@ impl Pure<'_> {
value
);
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value,
}));
})
.into();
return;
} else if let Some(precision) = args
.first()
@ -465,11 +472,12 @@ impl Pure<'_> {
value
);
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value,
}));
})
.into();
return;
}
}
@ -481,11 +489,12 @@ impl Pure<'_> {
{
if base.trunc() == 10. {
let value = num.value.to_js_string().into();
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value,
}));
})
.into();
return;
}
@ -505,11 +514,12 @@ impl Pure<'_> {
}
.into();
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: e.span(),
raw: None,
value,
}))
})
.into()
}
}
}
@ -570,10 +580,11 @@ impl Pure<'_> {
self.changed = true;
report_change!("evaluate: `foo || true` => `foo, 1`");
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: bin_expr.span,
exprs: vec![bin_expr.left.clone(), bin_expr.right.clone()],
});
}
.into();
} else {
self.changed = true;
report_change!("evaluate: `foo || false` => `foo` (bool ctx)");
@ -603,10 +614,11 @@ impl Pure<'_> {
self.changed = true;
report_change!("evaluate: `foo && false` => `foo, false`");
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: bin_expr.span,
exprs: vec![bin_expr.left.clone(), bin_expr.right.clone()],
});
}
.into();
}
return;
}
@ -749,22 +761,19 @@ impl Pure<'_> {
"evaluate: Evaluated `charCodeAt` of a string literal as `{}`",
v
);
*e = Expr::Lit(Lit::Num(Number {
*e = Lit::Num(Number {
span: call.span,
value: v as usize as f64,
raw: None,
}))
})
.into()
}
None => {
self.changed = true;
report_change!(
"evaluate: Evaluated `charCodeAt` of a string literal as `NaN`",
);
*e = Expr::Ident(Ident::new(
"NaN".into(),
e.span(),
SyntaxContext::empty(),
))
*e = Ident::new("NaN".into(), e.span(), SyntaxContext::empty()).into()
}
}
}
@ -788,22 +797,24 @@ impl Pure<'_> {
"evaluate: Evaluated `codePointAt` of a string literal as `{}`",
v
);
*e = Expr::Lit(Lit::Num(Number {
*e = Lit::Num(Number {
span: call.span,
value: v as usize as f64,
raw: None,
}))
})
.into()
}
None => {
self.changed = true;
report_change!(
"evaluate: Evaluated `codePointAt` of a string literal as `NaN`",
);
*e = Expr::Ident(Ident::new(
*e = Ident::new(
"NaN".into(),
e.span(),
SyntaxContext::empty().apply_mark(self.marks.unresolved_mark),
))
)
.into()
}
}
}
@ -814,11 +825,12 @@ impl Pure<'_> {
self.changed = true;
report_change!("evaluate: Evaluated `{method}` of a string literal");
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
value: new_val.into(),
raw: None,
..s
}));
})
.into();
}
}

View File

@ -79,12 +79,13 @@ impl Pure<'_> {
match s.test.as_deref_mut() {
Some(e) => {
let orig_test = e.take();
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op: op!("&&"),
left: Box::new(orig_test),
right: test.take(),
});
}
.into();
}
None => {
s.test = Some(test.take());
@ -110,12 +111,13 @@ impl Pure<'_> {
match s.test.as_deref_mut() {
Some(e) => {
let orig_test = e.take();
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: *span,
op: op!("&&"),
left: Box::new(orig_test),
right: test.take(),
});
}
.into();
}
None => {
s.test = Some(test.take());
@ -173,12 +175,15 @@ impl Pure<'_> {
match s.test.take() {
Some(left) => {
s.test = Some(Box::new(Expr::Bin(BinExpr {
span: s.test.span(),
op: op!("&&"),
left,
right: test.take(),
})));
s.test = Some(
BinExpr {
span: s.test.span(),
op: op!("&&"),
left,
right: test.take(),
}
.into(),
);
}
None => {
s.test = Some(test.take());

View File

@ -322,7 +322,7 @@ impl Pure<'_> {
let mut exprs: Vec<Box<Expr>> = exprs.drain(..(exprs.len() - 1)).collect();
exprs.push(Box::new(replacement));
Some(Expr::Seq(SeqExpr { span: *span, exprs }))
Some(SeqExpr { span: *span, exprs }.into())
}
Expr::Lit(Lit::Str(Str { value, span, .. })) => {
@ -381,20 +381,20 @@ impl Pure<'_> {
Some(if exprs.is_empty() {
// No side effects, replacement is:
// (0, void 0)
Expr::Seq(SeqExpr {
SeqExpr {
span: *span,
exprs: vec![0.into(), Expr::undefined(*span)]
})
}.into()
} else {
// Side effects exist, replacement is:
// (x(), y(), void 0)
// Where `x()` and `y()` are side effects.
exprs.push(Expr::undefined(*span));
Expr::Seq(SeqExpr {
SeqExpr {
span: *span,
exprs
})
}.into()
})
}
@ -429,9 +429,9 @@ impl Pure<'_> {
Some(if is_known_symbol {
// [x(), y()].push
Expr::Member(MemberExpr {
MemberExpr {
span: *span,
obj: Box::new(Expr::Array(ArrayLit {
obj: ArrayLit {
span: *span,
elems: exprs
.into_iter()
@ -440,29 +440,30 @@ impl Pure<'_> {
expr: elem,
}))
.collect()
})),
}.into(),
prop: prop.clone(),
})
}.into()
} else {
let val = Expr::undefined(*span);
let val = Expr::undefined(
*span);
if exprs.is_empty() {
// No side effects, replacement is:
// (0, void 0)
Expr::Seq(SeqExpr {
SeqExpr {
span: val.span(),
exprs: vec![0.into(), val]
})
}.into()
} else {
// Side effects exist, replacement is:
// (x(), y(), void 0)
// Where `x()` and `y()` are side effects.
exprs.push(val);
Expr::Seq(SeqExpr {
SeqExpr {
span: *span,
exprs
})
}.into()
}
})
}
@ -522,22 +523,24 @@ impl Pure<'_> {
}
// Can be optimized fully or partially
Some(self.expr_ctx.preserve_effects(
Some(*self.expr_ctx.preserve_effects(
*span,
if is_known_symbol {
// Valid key, e.g. "hasOwnProperty". Replacement:
// (foo(), bar(), {}.hasOwnProperty)
Expr::Member(MemberExpr {
MemberExpr {
span: *span,
obj: Box::new(Expr::Object(ObjectLit {
obj: ObjectLit {
span: *span,
props: vec![],
})),
}
.into(),
prop: MemberProp::Ident(IdentName::new(key, *span)),
})
}
.into()
} else {
// Invalid key. Replace with side effects plus `undefined`.
*Expr::undefined(*span)
Expr::undefined(*span)
},
props.drain(..).map(|x| match x {
PropOrSpread::Prop(prop) => match *prop {

View File

@ -232,25 +232,28 @@ impl Pure<'_> {
return;
}
let sep = Box::new(Expr::Lit(Lit::Str(Str {
let sep: Box<Expr> = Lit::Str(Str {
span: DUMMY_SP,
raw: None,
value: separator,
})));
let mut res = Expr::Lit(Lit::Str(Str {
})
.into();
let mut res = Lit::Str(Str {
span: DUMMY_SP,
raw: None,
value: js_word!(""),
}));
})
.into();
fn add(to: &mut Expr, right: Box<Expr>) {
let lhs = to.take();
*to = Expr::Bin(BinExpr {
*to = BinExpr {
span: DUMMY_SP,
left: Box::new(lhs),
op: op!(bin, "+"),
right,
});
}
.into();
}
for (last, elem) in arr.elems.take().into_iter().identify_last() {
@ -305,11 +308,12 @@ impl Pure<'_> {
report_change!("Compressing array.join()");
self.changed = true;
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: call.span,
raw: None,
value: res.into(),
}))
})
.into()
}
pub(super) fn drop_undefined_from_return_arg(&mut self, s: &mut ReturnStmt) {
@ -398,17 +402,20 @@ impl Pure<'_> {
report_change!("Optimized regex");
Some(Expr::Lit(Lit::Regex(Regex {
span: *span,
exp: pattern,
flags: {
let flag = flag.to_string();
let mut bytes = flag.into_bytes();
bytes.sort_unstable();
Some(
Lit::Regex(Regex {
span: *span,
exp: pattern,
flags: {
let flag = flag.to_string();
let mut bytes = flag.into_bytes();
bytes.sort_unstable();
String::from_utf8(bytes).unwrap().into()
},
})))
String::from_utf8(bytes).unwrap().into()
},
})
.into(),
)
}
/// Array() -> []
@ -418,38 +425,50 @@ impl Pure<'_> {
match &**expr {
Expr::Lit(Lit::Num(num)) => {
if num.value <= 5_f64 && num.value >= 0_f64 {
Some(Expr::Array(ArrayLit {
span: *span,
elems: vec![None; num.value as usize],
}))
Some(
ArrayLit {
span: *span,
elems: vec![None; num.value as usize],
}
.into(),
)
} else {
None
}
}
Expr::Lit(_) => Some(Expr::Array(ArrayLit {
span: *span,
elems: vec![args.take().into_iter().next()],
})),
Expr::Lit(_) => Some(
ArrayLit {
span: *span,
elems: vec![args.take().into_iter().next()],
}
.into(),
),
_ => None,
}
} else {
None
}
} else {
Some(Expr::Array(ArrayLit {
span: *span,
elems: args.take().into_iter().map(Some).collect(),
}))
Some(
ArrayLit {
span: *span,
elems: args.take().into_iter().map(Some).collect(),
}
.into(),
)
}
}
/// Object -> {}
fn optimize_object(&mut self, args: &mut Vec<ExprOrSpread>, span: &mut Span) -> Option<Expr> {
if args.is_empty() {
Some(Expr::Object(ObjectLit {
span: *span,
props: Vec::new(),
}))
Some(
ObjectLit {
span: *span,
props: Vec::new(),
}
.into(),
)
} else {
None
}
@ -470,11 +489,12 @@ impl Pure<'_> {
self.changed = true;
report_change!("Optimized optional chaining expression where object is not null");
*e = Expr::Member(MemberExpr {
*e = MemberExpr {
span: opt.span,
obj: base.obj.take(),
prop: base.prop.take(),
});
}
.into();
}
}
}
@ -534,57 +554,73 @@ impl Pure<'_> {
{
let new_expr = match &**callee {
Expr::Ident(Ident { sym, .. }) if &**sym == "Boolean" => match &mut args[..] {
[] => Some(Expr::Lit(Lit::Bool(Bool {
span: *span,
value: false,
}))),
[ExprOrSpread { spread: None, expr }] => Some(Expr::Unary(UnaryExpr {
span: *span,
op: op!("!"),
arg: UnaryExpr {
[] => Some(
Lit::Bool(Bool {
span: *span,
value: false,
})
.into(),
),
[ExprOrSpread { spread: None, expr }] => Some(
UnaryExpr {
span: *span,
op: op!("!"),
arg: expr.take(),
arg: UnaryExpr {
span: *span,
op: op!("!"),
arg: expr.take(),
}
.into(),
}
.into(),
})),
),
_ => None,
},
Expr::Ident(Ident { sym, .. }) if &**sym == "Number" => match &mut args[..] {
[] => Some(Expr::Lit(Lit::Num(Number {
span: *span,
value: 0.0,
raw: None,
}))),
[] => Some(
Lit::Num(Number {
span: *span,
value: 0.0,
raw: None,
})
.into(),
),
// this is indeed very unsafe in case of BigInt
[ExprOrSpread { spread: None, expr }] if self.options.unsafe_math => {
Some(Expr::Unary(UnaryExpr {
[ExprOrSpread { spread: None, expr }] if self.options.unsafe_math => Some(
UnaryExpr {
span: *span,
op: op!(unary, "+"),
arg: expr.take(),
}))
}
}
.into(),
),
_ => None,
},
Expr::Ident(Ident { sym, .. }) if &**sym == "String" => match &mut args[..] {
[] => Some(Expr::Lit(Lit::Str(Str {
span: *span,
value: "".into(),
raw: None,
}))),
[] => Some(
Lit::Str(Str {
span: *span,
value: "".into(),
raw: None,
})
.into(),
),
// this is also very unsafe in case of Symbol
[ExprOrSpread { spread: None, expr }] if self.options.unsafe_passes => {
Some(Expr::Bin(BinExpr {
span: *span,
left: expr.take(),
op: op!(bin, "+"),
right: Lit::Str(Str {
Some(
BinExpr {
span: *span,
value: "".into(),
raw: None,
})
left: expr.take(),
op: op!(bin, "+"),
right: Lit::Str(Str {
span: *span,
value: "".into(),
raw: None,
})
.into(),
}
.into(),
}))
)
}
_ => None,
},
@ -648,13 +684,14 @@ impl Pure<'_> {
report_change!(
"new operator: Compressing `new Array/RegExp/..` => `Array()/RegExp()/..`"
);
*e = Expr::Call(CallExpr {
*e = CallExpr {
span: *span,
ctxt: *ctxt,
callee: callee.take().as_callee(),
args: args.take().unwrap_or_default(),
..Default::default()
})
}
.into()
}
_ => {}
}
@ -777,7 +814,7 @@ impl Pure<'_> {
raw: cur_raw.into(),
});
Some(Expr::Tpl(new_tpl))
Some(new_tpl.into())
}
/// Returns true if something is modified.
@ -860,10 +897,13 @@ impl Pure<'_> {
return Some(*exprs.remove(0));
}
Some(Expr::Seq(SeqExpr {
span: DUMMY_SP,
exprs,
}))
Some(
SeqExpr {
span: DUMMY_SP,
exprs,
}
.into(),
)
}
/// Calls [`Self::ignore_return_value`] on the arguments of return
@ -936,7 +976,7 @@ impl Pure<'_> {
let new = self.make_ignored_expr(args.take().into_iter().map(|arg| arg.expr));
*e = new.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
*e = new.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
@ -946,7 +986,7 @@ impl Pure<'_> {
let new = self.make_ignored_expr(tpl.exprs.take().into_iter());
*e = new.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
*e = new.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
@ -957,7 +997,7 @@ impl Pure<'_> {
let new =
self.make_ignored_expr(args.take().into_iter().flatten().map(|arg| arg.expr));
*e = new.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
*e = new.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
@ -975,7 +1015,7 @@ impl Pure<'_> {
report_change!("Dropping pure call as callee is pure");
*e = self
.make_ignored_expr(args.take().into_iter().map(|arg| arg.expr))
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
}
@ -988,7 +1028,7 @@ impl Pure<'_> {
report_change!("Dropping pure tag tpl as callee is pure");
*e = self
.make_ignored_expr(tpl.exprs.take().into_iter())
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
}
@ -1000,7 +1040,7 @@ impl Pure<'_> {
// Skip 0
if n.value != 0.0 && n.value.classify() == FpCategory::Normal {
self.changed = true;
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
}
@ -1014,13 +1054,13 @@ impl Pure<'_> {
{
if is_global_var_with_pure_property_access(&i.sym) {
report_change!("Dropping a reference to a global variable");
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
}
} else {
report_change!("Dropping an identifier as it's declared");
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
}
@ -1044,7 +1084,7 @@ impl Pure<'_> {
if arg.is_invalid() {
report_change!("Dropping an unary expression");
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
}
@ -1078,10 +1118,11 @@ impl Pure<'_> {
if tpl.exprs.len() == 1 {
*e = *tpl.exprs.remove(0);
} else {
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: tpl.span,
exprs: tpl.exprs.take(),
});
}
.into();
}
}
@ -1111,7 +1152,7 @@ impl Pure<'_> {
Expr::Lit(Lit::Num(n)) => {
if n.value == 0.0 && opts.drop_zero {
self.changed = true;
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
}
@ -1121,7 +1162,7 @@ impl Pure<'_> {
report_change!("Dropping an identifier as it's declared");
self.changed = true;
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
}
@ -1130,7 +1171,7 @@ impl Pure<'_> {
report_change!("Dropping literals");
self.changed = true;
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
@ -1180,7 +1221,7 @@ impl Pure<'_> {
let span = bin.span;
if bin.left.is_invalid() && bin.right.is_invalid() {
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
} else if bin.right.is_invalid() {
*e = *bin.left.take();
@ -1193,10 +1234,11 @@ impl Pure<'_> {
if matches!(*bin.left, Expr::Await(..) | Expr::Update(..)) {
self.changed = true;
report_change!("ignore_return_value: Compressing binary as seq");
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span,
exprs: vec![bin.left.take(), bin.right.take()],
});
}
.into();
return;
}
}
@ -1225,7 +1267,7 @@ impl Pure<'_> {
|| s.value.starts_with("@babel/helpers"))
{
self.changed = true;
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
@ -1328,7 +1370,7 @@ impl Pure<'_> {
self.changed = true;
*e = self
.make_ignored_expr(args.iter_mut().flatten().map(|arg| arg.expr.take()))
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
@ -1346,7 +1388,7 @@ impl Pure<'_> {
self.changed = true;
*e = self
.make_ignored_expr(args.iter_mut().map(|arg| arg.expr.take()))
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
@ -1364,7 +1406,7 @@ impl Pure<'_> {
if let PropOrSpread::Prop(p) = prop {
match *p {
Prop::Shorthand(p) => {
exprs.push(Box::new(Expr::Ident(p)));
exprs.push(p.into());
}
Prop::KeyValue(p) => {
if let PropName::Computed(e) = p.key {
@ -1386,7 +1428,7 @@ impl Pure<'_> {
*e = self
.make_ignored_expr(exprs.into_iter())
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
report_change!("Ignored an object literal");
self.changed = true;
return;
@ -1400,7 +1442,7 @@ impl Pure<'_> {
}) => true,
_ => false,
}) {
*e = Expr::Array(ArrayLit {
*e = ArrayLit {
elems: arr
.elems
.take()
@ -1432,7 +1474,8 @@ impl Pure<'_> {
.map(Some)
.collect(),
..*arr
});
}
.into();
return;
}
@ -1457,7 +1500,7 @@ impl Pure<'_> {
*e = self
.make_ignored_expr(exprs.into_iter())
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
report_change!("Ignored an array literal");
self.changed = true;
return;
@ -1485,7 +1528,7 @@ impl Pure<'_> {
.make_ignored_expr(
vec![obj.take(), prop.expr.take()].into_iter(),
)
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
.unwrap_or(Invalid { span: DUMMY_SP }.into());
return;
}
};
@ -1504,7 +1547,7 @@ impl Pure<'_> {
if is_pure_member_access(obj, prop) {
self.changed = true;
report_change!("Remving pure member access to global var");
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
}
}
}
@ -1534,7 +1577,7 @@ impl Pure<'_> {
right,
..
}) => {
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: unary.span,
op: if *op == op!("==") {
op!("!=")
@ -1543,7 +1586,8 @@ impl Pure<'_> {
},
left: left.take(),
right: right.take(),
})
}
.into()
}
_ => {}
}

View File

@ -419,7 +419,7 @@ impl VisitMut for Pure<'_> {
if let Expr::Seq(seq) = e {
if seq.exprs.is_empty() {
*e = Expr::Invalid(Invalid { span: DUMMY_SP });
*e = Invalid { span: DUMMY_SP }.into();
return;
}
if seq.exprs.len() == 1 {

View File

@ -18,11 +18,12 @@ impl Pure<'_> {
self.changed = true;
report_change!("numbers: Converting a string literal to {:?}", value);
*e = Expr::Lit(Lit::Num(Number {
*e = Lit::Num(Number {
span: *span,
value,
raw: None,
}));
})
.into();
}
}
@ -47,16 +48,18 @@ impl Pure<'_> {
self.changed = true;
report_change!("numbers: Lifting `-`");
*e = Expr::Unary(UnaryExpr {
*e = UnaryExpr {
span: arg.span,
op: op!(unary, "-"),
arg: Box::new(Expr::Bin(BinExpr {
arg: BinExpr {
span: arg.span,
op: arg.op,
left: arg.left.take(),
right: right_arg.take(),
})),
});
}
.into(),
}
.into();
}
Expr::Lit(Lit::Num(Number { span, value, .. })) => {
@ -64,10 +67,10 @@ impl Pure<'_> {
self.changed = true;
report_change!("numbers: Lifting `-` in a literal");
*e = Expr::Unary(UnaryExpr {
*e = UnaryExpr {
span: arg.span,
op: op!(unary, "-"),
arg: Box::new(Expr::Bin(BinExpr {
arg: BinExpr {
span: arg.span,
op: arg.op,
left: arg.left.take(),
@ -76,8 +79,10 @@ impl Pure<'_> {
value: -*value,
raw: None,
}))),
})),
});
}
.into(),
}
.into();
}
}

View File

@ -52,17 +52,21 @@ impl Pure<'_> {
let mut exprs = left.exprs.take();
exprs.push(Box::new(Expr::Bin(BinExpr {
span: left.span,
op: bin.op,
left: left_last,
right: bin.right.take(),
})));
exprs.push(
BinExpr {
span: left.span,
op: bin.op,
left: left_last,
right: bin.right.take(),
}
.into(),
);
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: bin.span,
exprs,
})
}
.into()
}
}
@ -99,17 +103,21 @@ impl Pure<'_> {
alt: cond.alt.take(),
};
new_seq.push(Box::new(Expr::Assign(AssignExpr {
span: assign.span,
op: assign.op,
left: assign.left.take(),
right: Box::new(Expr::Cond(new_cond)),
})));
new_seq.push(
AssignExpr {
span: assign.span,
op: assign.op,
left: assign.left.take(),
right: Box::new(new_cond.into()),
}
.into(),
);
*e = Expr::Seq(SeqExpr {
*e = SeqExpr {
span: assign.span,
exprs: new_seq,
});
}
.into();
}
}
}
@ -169,7 +177,7 @@ impl Pure<'_> {
let obj = Box::new(a.take());
let new = Expr::Call(CallExpr {
let new = CallExpr {
span,
callee: MemberExpr {
span: DUMMY_SP,
@ -179,7 +187,8 @@ impl Pure<'_> {
.as_callee(),
args: args.take(),
..Default::default()
});
}
.into();
b.take();
self.changed = true;
report_change!(

View File

@ -45,12 +45,13 @@ impl Pure<'_> {
report_change!("evaluate: 'foo' + ('bar' + baz) => 'foobar' + baz");
let s = lls.into_owned() + &*rls;
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span,
op: op!(bin, "+"),
left: s.into(),
right: r_r.take(),
});
}
.into();
}
}
@ -82,7 +83,7 @@ impl Pure<'_> {
self.changed = true;
report_change!("evaluating a template to a string");
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: tpl.span,
op: op!(bin, "+"),
left: tpl.quasis[0]
@ -91,7 +92,8 @@ impl Pure<'_> {
.unwrap_or_else(|| tpl.quasis[0].raw.clone())
.into(),
right: tpl.exprs[0].take(),
});
}
.into();
}
}
@ -182,7 +184,7 @@ impl Pure<'_> {
raw: s,
});
*e = Expr::Tpl(new_tpl);
*e = new_tpl.into();
}
/// Converts template literals to string if `exprs` of [Tpl] is empty.
@ -198,11 +200,12 @@ impl Pure<'_> {
}) {
report_change!("converting a template literal to a string literal");
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: t.span,
raw: None,
value: value.clone(),
}));
})
.into();
return;
}
}
@ -224,11 +227,12 @@ impl Pure<'_> {
report_change!("converting a template literal to a string literal");
*e = Expr::Lit(Lit::Str(Str {
*e = Lit::Str(Str {
span: t.span,
raw: None,
value,
}));
})
.into();
}
}
_ => {}
@ -496,16 +500,18 @@ impl Pure<'_> {
new_str
);
*e = Expr::Bin(BinExpr {
*e = BinExpr {
span: bin.span,
op: op!(bin, "+"),
left: left.left.take(),
right: Box::new(Expr::Lit(Lit::Str(Str {
right: Lit::Str(Str {
span: left_span,
raw: None,
value: new_str.into(),
}))),
});
})
.into(),
}
.into();
}
}
}

View File

@ -165,11 +165,12 @@ fn negate_inner(
} else {
report_change!("negate: e => !e");
*e = Expr::Unary(UnaryExpr {
*e = UnaryExpr {
span: DUMMY_SP,
op: op!("!"),
arg,
});
}
.into();
dump_change_detail!("Negated `{}` as `{}`", start_str, dump(&*e, false));

View File

@ -200,11 +200,12 @@ impl Evaluator {
}) if !prop.is_computed() => {
let obj = self.eval_as_expr(obj)?;
let mut e = Expr::Member(MemberExpr {
let mut e: Expr = MemberExpr {
span: *span,
obj,
prop: prop.clone(),
});
}
.into();
e.visit_mut_with(&mut expr_simplifier(
self.marks.unresolved_mark,
@ -226,16 +227,17 @@ impl Evaluator {
for expr in &q.exprs {
let res = self.eval(expr)?;
exprs.push(match res {
EvalResult::Lit(v) => Box::new(Expr::Lit(v)),
EvalResult::Lit(v) => v.into(),
EvalResult::Undefined => Expr::undefined(DUMMY_SP),
});
}
let mut e = Expr::Tpl(Tpl {
let mut e: Box<Expr> = Tpl {
span: q.span,
exprs,
quasis: q.quasis.clone(),
});
}
.into();
{
e.visit_mut_with(&mut pure_optimizer(

View File

@ -456,28 +456,31 @@ impl From<TerserTopRetainOption> for Vec<JsWord> {
fn value_to_expr(v: Value) -> Box<Expr> {
match v {
Value::Null => Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))),
Value::Bool(value) => Box::new(Expr::Lit(Lit::Bool(Bool {
Value::Null => Lit::Null(Null { span: DUMMY_SP }).into(),
Value::Bool(value) => Lit::Bool(Bool {
span: DUMMY_SP,
value,
}))),
})
.into(),
Value::Number(v) => {
trace_op!("Creating a numeric literal from value");
Box::new(Expr::Lit(Lit::Num(Number {
Lit::Num(Number {
span: DUMMY_SP,
value: v.as_f64().unwrap(),
raw: None,
})))
})
.into()
}
Value::String(v) => {
let value: JsWord = v.into();
Box::new(Expr::Lit(Lit::Str(Str {
Lit::Str(Str {
span: DUMMY_SP,
raw: None,
value,
})))
})
.into()
}
Value::Array(arr) => {
@ -486,10 +489,11 @@ fn value_to_expr(v: Value) -> Box<Expr> {
.map(value_to_expr)
.map(|expr| Some(ExprOrSpread { spread: None, expr }))
.collect();
Box::new(Expr::Array(ArrayLit {
ArrayLit {
span: DUMMY_SP,
elems,
}))
}
.into()
}
Value::Object(obj) => {
@ -509,10 +513,11 @@ fn value_to_expr(v: Value) -> Box<Expr> {
.map(PropOrSpread::Prop)
.collect();
Box::new(Expr::Object(ObjectLit {
ObjectLit {
span: DUMMY_SP,
props,
}))
}
.into()
}
}
}

View File

@ -266,7 +266,7 @@ impl VisitMut for Mangler<'_> {
*prop = Prop::KeyValue(KeyValueProp {
key: PropName::Ident(new_ident),
value: Box::new(Expr::Ident(ident.clone())),
value: ident.clone().into(),
});
}
}

View File

@ -16,11 +16,12 @@ pub(crate) mod unit;
pub(crate) fn make_number(span: Span, value: f64) -> Expr {
trace_op!("Creating a numeric literal");
Expr::Lit(Lit::Num(Number {
Lit::Num(Number {
span,
value,
raw: None,
}))
})
.into()
}
pub trait ModuleItemExt:
@ -80,15 +81,17 @@ impl ModuleItemExt for ModuleItem {
pub(crate) fn make_bool(span: Span, value: bool) -> Expr {
trace_op!("Creating a boolean literal");
Expr::Unary(UnaryExpr {
UnaryExpr {
span,
op: op!("!"),
arg: Box::new(Expr::Lit(Lit::Num(Number {
arg: Lit::Num(Number {
span: DUMMY_SP,
value: if value { 0.0 } else { 1.0 },
raw: None,
}))),
})
})
.into(),
}
.into()
}
/// Additional methods for optimizing expressions.
@ -128,10 +131,11 @@ pub(crate) trait ExprOptExt: Sized {
Expr::Seq(seq) => seq,
_ => {
let inner = expr.take();
*expr = Expr::Seq(SeqExpr {
*expr = SeqExpr {
span: DUMMY_SP,
exprs: vec![Box::new(inner)],
});
}
.into();
expr.force_seq()
}
}
@ -151,10 +155,11 @@ pub(crate) trait ExprOptExt: Sized {
_ => {
let v = to.take();
exprs.push(Box::new(v));
*to = Expr::Seq(SeqExpr {
*to = SeqExpr {
span: DUMMY_SP,
exprs,
});
}
.into();
}
}
}

View File

@ -323,12 +323,13 @@ impl<I: Tokens> Parser<I> {
}
let args = self.parse_args(false)?;
Ok(Box::new(Expr::Call(CallExpr {
Ok(CallExpr {
span: span!(self, expr.span_lo()),
callee: Callee::Expr(expr),
args,
..Default::default()
})))
}
.into())
}
fn parse_class_body(&mut self) -> PResult<Vec<ClassMember>> {
@ -1571,7 +1572,7 @@ impl OutputType for Box<Expr> {
ident: Option<Ident>,
function: Box<Function>,
) -> Result<Self, SyntaxError> {
Ok(Box::new(Expr::Fn(FnExpr { ident, function })))
Ok(FnExpr { ident, function }.into())
}
fn finish_class(
@ -1579,7 +1580,7 @@ impl OutputType for Box<Expr> {
ident: Option<Ident>,
class: Box<Class>,
) -> Result<Self, SyntaxError> {
Ok(Box::new(Expr::Class(ClassExpr { ident, class })))
Ok(ClassExpr { ident, class }.into())
}
}

View File

@ -24,10 +24,11 @@ impl<I: Tokens> Parser<I> {
exprs.push(self.parse_assignment_expr()?);
}
return Ok(Box::new(Expr::Seq(SeqExpr {
return Ok(SeqExpr {
span: span!(self, start),
exprs,
})));
}
.into());
}
Ok(expr)
@ -195,13 +196,14 @@ impl<I: Tokens> Parser<I> {
bump!(self);
let right = self.parse_assignment_expr()?;
Ok(Box::new(Expr::Assign(AssignExpr {
Ok(AssignExpr {
span: span!(self, start),
op,
// TODO:
left,
right,
})))
}
.into())
}
_ => Ok(cond),
}
@ -233,12 +235,13 @@ impl<I: Tokens> Parser<I> {
};
let alt = self.with_ctx(ctx).parse_assignment_expr()?;
let span = Span::new(start, alt.span_hi());
Ok(Box::new(Expr::Cond(CondExpr {
Ok(CondExpr {
span,
test,
cons,
alt,
})))
}
.into())
} else {
Ok(test)
}
@ -262,9 +265,10 @@ impl<I: Tokens> Parser<I> {
match tok {
tok!("this") => {
self.input.bump();
return Ok(Box::new(Expr::This(ThisExpr {
return Ok(ThisExpr {
span: span!(self, start),
})));
}
.into());
}
tok!("async") => {
@ -282,7 +286,7 @@ impl<I: Tokens> Parser<I> {
assert_and_bump!(p, "async");
p.try_parse_ts_generic_async_arrow_fn(start)
}) {
return Ok(Box::new(Expr::Arrow(res)));
return Ok(res.into());
}
}
@ -320,7 +324,7 @@ impl<I: Tokens> Parser<I> {
| Token::Num { .. }
| Token::BigInt { .. }
| Token::Str { .. } => {
return Ok(Box::new(Expr::Lit(self.parse_lit()?)));
return Ok(self.parse_lit()?.into());
}
// Regexp
@ -359,11 +363,7 @@ impl<I: Tokens> Parser<I> {
self.emit_err(span, SyntaxError::DuplicatedRegExpFlags(*flag));
}
return Ok(Box::new(Expr::Lit(Lit::Regex(Regex {
span,
exp,
flags,
}))));
return Ok(Lit::Regex(Regex { span, exp, flags }).into());
}
_ => unreachable!(),
}
@ -377,7 +377,7 @@ impl<I: Tokens> Parser<I> {
};
// parse template literal
return Ok(Box::new(Expr::Tpl(self.with_ctx(ctx).parse_tpl(false)?)));
return Ok(self.with_ctx(ctx).parse_tpl(false)?.into());
}
tok!('(') => {
@ -428,35 +428,37 @@ impl<I: Tokens> Parser<I> {
self.emit_err(self.input.prev_span(), SyntaxError::TS1106);
}
return Ok(Box::new(Expr::Ident(id)));
return Ok(id.into());
}
let ident = self.parse_binding_ident()?;
if self.input.syntax().typescript() && ident.sym == "as" && !is!(self, "=>") {
// async as type
let type_ann = self.in_type().parse_with(|p| p.parse_ts_type())?;
return Ok(Box::new(Expr::TsAs(TsAsExpr {
return Ok(TsAsExpr {
span: span!(self, start),
expr: Box::new(Expr::Ident(id)),
expr: Box::new(id.into()),
type_ann,
})));
}
.into());
}
// async a => body
let arg = Pat::from(ident);
let arg = ident.into();
let params = vec![arg];
expect!(self, "=>");
let body =
self.parse_fn_body(true, false, true, params.is_simple_parameter_list())?;
return Ok(Box::new(Expr::Arrow(ArrowExpr {
return Ok(ArrowExpr {
span: span!(self, start),
body,
params,
is_async: true,
is_generator: false,
..Default::default()
})));
}
.into());
} else if can_be_arrow && !self.input.had_line_break_before_cur() && eat!(self, "=>") {
if self.ctx().strict && id.is_reserved_in_strict_bind() {
self.emit_strict_mode_err(id.span, SyntaxError::EvalAndArgumentsInStrict)
@ -465,25 +467,27 @@ impl<I: Tokens> Parser<I> {
let body =
self.parse_fn_body(false, false, true, params.is_simple_parameter_list())?;
return Ok(Box::new(Expr::Arrow(ArrowExpr {
return Ok(ArrowExpr {
span: span!(self, start),
body,
params,
is_async: false,
is_generator: false,
..Default::default()
})));
}
.into());
} else {
return Ok(Box::new(Expr::Ident(id)));
return Ok(id.into());
}
}
if eat!(self, '#') {
let id = self.parse_ident_name()?;
return Ok(Box::new(Expr::PrivateName(PrivateName {
return Ok(PrivateName {
span: span!(self, start),
name: id.sym,
})));
}
.into());
}
syntax_error!(self, self.input.cur_span(), SyntaxError::TS1109)
@ -522,7 +526,7 @@ impl<I: Tokens> Parser<I> {
expect!(self, ']');
let span = span!(self, start);
Ok(Box::new(Expr::Array(ArrayLit { span, elems })))
Ok(ArrayLit { span, elems }.into())
}
#[allow(dead_code)]
@ -549,10 +553,11 @@ impl<I: Tokens> Parser<I> {
if eat!(self, '.') {
if eat!(self, "target") {
let span = span!(self, start);
let expr = Box::new(Expr::MetaProp(MetaPropExpr {
let expr = MetaPropExpr {
span,
kind: MetaPropKind::NewTarget,
}));
}
.into();
let ctx = self.ctx();
if (!ctx.inside_non_arrow_function_scope) && !ctx.in_parameters && !ctx.in_class
@ -619,13 +624,16 @@ impl<I: Tokens> Parser<I> {
// Parsed with 'MemberExpression' production.
let args = self.parse_args(false).map(Some)?;
let new_expr = Callee::Expr(Box::new(Expr::New(NewExpr {
span: span!(self, start),
callee,
args,
type_args,
..Default::default()
})));
let new_expr = Callee::Expr(
NewExpr {
span: span!(self, start),
callee,
args,
type_args,
..Default::default()
}
.into(),
);
// We should parse subscripts for MemberExpression.
// Because it's left recursive.
@ -634,13 +642,14 @@ impl<I: Tokens> Parser<I> {
// Parsed with 'NewExpression' production.
return Ok(Box::new(Expr::New(NewExpr {
return Ok(NewExpr {
span: span!(self, start),
callee,
args: None,
type_args,
..Default::default()
})));
}
.into());
}
if eat!(self, "super") {
@ -662,11 +671,12 @@ impl<I: Tokens> Parser<I> {
};
let obj = if let Some(type_args) = type_args {
trace_cur!(self, parse_member_expr_or_new_expr__with_type_args);
Box::new(Expr::TsInstantiation(TsInstantiation {
TsInstantiation {
expr: obj,
type_args,
span: span!(self, start),
}))
}
.into()
} else {
obj
};
@ -813,15 +823,18 @@ impl<I: Tokens> Parser<I> {
unexpected!(p, "fail")
}
Ok(Some(Box::new(Expr::Arrow(ArrowExpr {
span: span!(p, expr_start),
is_async: async_span.is_some(),
is_generator: false,
params,
body,
return_type: Some(return_type),
..Default::default()
}))))
Ok(Some(
ArrowExpr {
span: span!(p, expr_start),
is_async: async_span.is_some(),
is_generator: false,
params,
body,
return_type: Some(return_type),
..Default::default()
}
.into(),
))
}) {
return Ok(expr);
}
@ -894,7 +907,7 @@ impl<I: Tokens> Parser<I> {
return Ok(errorred_expr);
}
}
return Ok(Box::new(Expr::Arrow(arrow_expr)));
return Ok(arrow_expr.into());
} else {
// If there's no arrow function, we have to check there's no
// AssignProp in lhs to check against assignment in object literals
@ -925,15 +938,15 @@ impl<I: Tokens> Parser<I> {
.collect::<Result<Vec<_>, _>>()?;
if let Some(async_span) = async_span {
// It's a call expression
return Ok(Box::new(Expr::Call(CallExpr {
return Ok(CallExpr {
span: span!(self, async_span.lo()),
callee: Callee::Expr(Box::new(Expr::Ident(Ident::new_no_ctxt(
"async".into(),
async_span,
)))),
callee: Callee::Expr(Box::new(
Ident::new_no_ctxt("async".into(), async_span).into(),
)),
args: expr_or_spreads,
..Default::default()
})));
}
.into());
}
// It was not head of arrow function.
@ -957,10 +970,11 @@ impl<I: Tokens> Parser<I> {
} => syntax_error!(self, expr.span(), SyntaxError::SpreadInParenExpr),
ExprOrSpread { expr, .. } => expr,
};
Ok(Box::new(Expr::Paren(ParenExpr {
Ok(ParenExpr {
span: span!(self, expr_start),
expr,
})))
}
.into())
} else {
debug_assert!(expr_or_spreads.len() >= 2);
@ -977,17 +991,19 @@ impl<I: Tokens> Parser<I> {
debug_assert!(exprs.len() >= 2);
// span of sequence expression should not include '(', ')'
let seq_expr = Box::new(Expr::Seq(SeqExpr {
let seq_expr = SeqExpr {
span: Span::new(
exprs.first().unwrap().span_lo(),
exprs.last().unwrap().span_hi(),
),
exprs,
}));
Ok(Box::new(Expr::Paren(ParenExpr {
}
.into();
Ok(ParenExpr {
span: span!(self, expr_start),
expr: seq_expr,
})))
}
.into())
}
}
@ -1140,10 +1156,11 @@ impl<I: Tokens> Parser<I> {
Callee::Expr(expr) => expr,
};
return Ok((
Box::new(Expr::TsNonNull(TsNonNullExpr {
TsNonNullExpr {
span: span!(self, start),
expr,
})),
}
.into(),
true,
));
}
@ -1174,7 +1191,7 @@ impl<I: Tokens> Parser<I> {
// But it might be a call with a type argument `async<T>();`
let async_arrow_fn = p.try_parse_ts_generic_async_arrow_fn(start)?;
if let Some(async_arrow_fn) = async_arrow_fn {
return Ok(Some((Box::new(Expr::Arrow(async_arrow_fn)), true)));
return Ok(Some((async_arrow_fn.into(), true)));
}
}
@ -1190,7 +1207,7 @@ impl<I: Tokens> Parser<I> {
if let Callee::Expr(callee) = &obj {
if let Expr::OptChain(..) = &**callee {
return Ok(Some((
Box::new(Expr::OptChain(OptChainExpr {
OptChainExpr {
span: span!(p, start),
base: Box::new(OptChainBase::Call(OptCall {
span: span!(p, start),
@ -1200,20 +1217,22 @@ impl<I: Tokens> Parser<I> {
..Default::default()
})),
optional: false,
})),
}
.into(),
true,
)));
}
}
Ok(Some((
Box::new(Expr::Call(CallExpr {
CallExpr {
span: span!(p, start),
callee: obj,
type_args: Some(type_args),
args,
..Default::default()
})),
}
.into(),
true,
)))
} else if is!(p, '`') {
@ -1224,18 +1243,19 @@ impl<I: Tokens> Parser<I> {
},
Some(type_args),
)
.map(|expr| (Box::new(Expr::TaggedTpl(expr)), true))
.map(|expr| (expr.into(), true))
.map(Some)
} else if is_one_of!(p, '=', "as") {
Ok(Some((
Box::new(Expr::TsInstantiation(TsInstantiation {
TsInstantiation {
span: span!(p, start),
expr: match mut_obj_opt {
Some(Callee::Expr(obj)) => obj.take(),
_ => unreachable!(),
},
type_args,
})),
}
.into(),
false,
)))
} else if no_call {
@ -1313,11 +1333,12 @@ impl<I: Tokens> Parser<I> {
}
syntax_error!(self, self.input.cur_span(), SyntaxError::InvalidSuper);
} else {
Expr::SuperProp(SuperPropExpr {
SuperPropExpr {
span,
obj,
prop: SuperProp::Computed(prop),
})
}
.into()
}
}
Callee::Expr(obj) => {
@ -1328,21 +1349,23 @@ impl<I: Tokens> Parser<I> {
prop: MemberProp::Computed(prop),
};
let expr = if is_opt_chain || question_dot_token.is_some() {
Expr::OptChain(OptChainExpr {
OptChainExpr {
span,
optional: question_dot_token.is_some(),
base: Box::new(OptChainBase::Member(expr)),
})
}
.into()
} else {
Expr::Member(expr)
expr.into()
};
if let Some(type_args) = type_args {
Expr::TsInstantiation(TsInstantiation {
TsInstantiation {
expr: Box::new(expr),
type_args,
span: span!(self, start),
})
}
.into()
} else {
expr
}
@ -1375,7 +1398,7 @@ impl<I: Tokens> Parser<I> {
syntax_error!(self, self.input.cur_span(), SyntaxError::SuperCallOptional)
}
Callee::Expr(callee) => Ok((
Box::new(Expr::OptChain(OptChainExpr {
OptChainExpr {
span,
optional: question_dot_token.is_some(),
base: Box::new(OptChainBase::Call(OptCall {
@ -1385,7 +1408,8 @@ impl<I: Tokens> Parser<I> {
type_args,
..Default::default()
})),
})),
}
.into(),
true,
)),
}
@ -1429,20 +1453,22 @@ impl<I: Tokens> Parser<I> {
self.emit_err(span, SyntaxError::ImportMetaInScript);
}
match &*sym {
"meta" => Expr::MetaProp(MetaPropExpr {
"meta" => MetaPropExpr {
span,
kind: MetaPropKind::ImportMeta,
}),
}
.into(),
_ => {
let args = self.parse_args(true)?;
Expr::Call(CallExpr {
CallExpr {
span,
callee,
args,
type_args: None,
..Default::default()
})
}
.into()
}
}
}
@ -1466,11 +1492,12 @@ impl<I: Tokens> Parser<I> {
syntax_error!(self, self.input.cur_span(), SyntaxError::InvalidSuper);
} else {
match prop {
MemberProp::Ident(ident) => Expr::SuperProp(SuperPropExpr {
MemberProp::Ident(ident) => SuperPropExpr {
span,
obj,
prop: SuperProp::Ident(ident),
}),
}
.into(),
MemberProp::PrivateName(..) => syntax_error!(
self,
self.input.cur_span(),
@ -1485,20 +1512,22 @@ impl<I: Tokens> Parser<I> {
let expr = if unwrap_ts_non_null(&expr.obj).is_opt_chain()
|| question_dot_token.is_some()
{
Expr::OptChain(OptChainExpr {
OptChainExpr {
span: span!(self, start),
optional: question_dot_token.is_some(),
base: Box::new(OptChainBase::Member(expr)),
})
}
.into()
} else {
Expr::Member(expr)
expr.into()
};
if let Some(type_args) = type_args {
Expr::TsInstantiation(TsInstantiation {
TsInstantiation {
expr: Box::new(expr),
type_args,
span: span!(self, start),
})
}
.into()
} else {
expr
}
@ -1511,11 +1540,12 @@ impl<I: Tokens> Parser<I> {
match obj {
Callee::Expr(expr) => {
let expr = if let Some(type_args) = type_args {
Box::new(Expr::TsInstantiation(TsInstantiation {
TsInstantiation {
expr,
type_args,
span: span!(self, start),
}))
}
.into()
} else {
expr
};
@ -1528,7 +1558,7 @@ impl<I: Tokens> Parser<I> {
};
let tpl = self.with_ctx(ctx).parse_tagged_tpl(expr, None)?;
return Ok((Box::new(Expr::TaggedTpl(tpl)), true));
return Ok((tpl.into(), true));
}
Ok((expr, false))
@ -1624,7 +1654,7 @@ impl<I: Tokens> Parser<I> {
Some(&tok!('(')),
"parse_new_expr() should eat paren if it exists"
);
return Ok(Box::new(Expr::New(NewExpr { type_args, ..ne })));
return Ok(NewExpr { type_args, ..ne }.into());
}
// 'CallExpr' rule contains 'MemberExpr (...)',
// and 'MemberExpr' rule contains 'new MemberExpr (...)'
@ -1645,27 +1675,27 @@ impl<I: Tokens> Parser<I> {
let args = self.parse_args(is_import)?;
let call_expr = match callee {
Callee::Expr(e) if unwrap_ts_non_null(&e).is_opt_chain() => {
Box::new(Expr::OptChain(OptChainExpr {
Callee::Expr(e) if unwrap_ts_non_null(&e).is_opt_chain() => OptChainExpr {
span: span!(self, start),
base: Box::new(OptChainBase::Call(OptCall {
span: span!(self, start),
base: Box::new(OptChainBase::Call(OptCall {
span: span!(self, start),
callee: e,
args,
type_args,
..Default::default()
})),
optional: false,
}))
callee: e,
args,
type_args,
..Default::default()
})),
optional: false,
}
_ => Box::new(Expr::Call(CallExpr {
.into(),
_ => CallExpr {
span: span!(self, start),
callee,
args,
type_args,
..Default::default()
})),
}
.into(),
};
return self.parse_subscripts(Callee::Expr(call_expr), false, false);
@ -1794,13 +1824,14 @@ impl<I: Tokens> Parser<I> {
arg = ExprOrSpread {
spread: None,
expr: Box::new(Expr::Cond(CondExpr {
expr: CondExpr {
span: Span::new(start, alt.span_hi()),
test,
cons,
alt,
})),
}
.into(),
};
false
@ -1829,12 +1860,13 @@ impl<I: Tokens> Parser<I> {
}
}
if let Some(span) = arg.spread {
pat = Pat::Rest(RestPat {
pat = RestPat {
span: span!(self, pat_start),
dot3_token: span,
arg: Box::new(pat),
type_ann: None,
});
}
.into();
}
match pat {
Pat::Ident(BindingIdent {
@ -1876,11 +1908,12 @@ impl<I: Tokens> Parser<I> {
if eat!(self, '=') {
let right = self.parse_assignment_expr()?;
pat = Pat::Assign(AssignPat {
pat = AssignPat {
span: span!(self, pat_start),
left: Box::new(pat),
right,
});
}
.into();
}
if has_modifier {
@ -1979,11 +2012,12 @@ impl<I: Tokens> Parser<I> {
.map(|t| t.kind().starts_expr())
.unwrap_or(true))
{
Ok(Box::new(Expr::Yield(YieldExpr {
Ok(YieldExpr {
span: span!(self, start),
arg: None,
delegate: false,
})))
}
.into())
} else {
let has_star = eat!(self, '*');
let err_span = span!(self, start);
@ -1999,11 +2033,12 @@ impl<I: Tokens> Parser<I> {
)
})?;
Ok(Box::new(Expr::Yield(YieldExpr {
Ok(YieldExpr {
span: span!(self, start),
arg: Some(arg),
delegate: has_star,
})))
}
.into())
}
}

View File

@ -19,12 +19,12 @@ impl<I: Tokens> Parser<I> {
&tok!("in") if ctx.include_in_expr => {
self.emit_err(self.input.cur_span(), SyntaxError::TS1109);
Box::new(Expr::Invalid(Invalid { span: err.span() }))
Invalid { span: err.span() }.into()
}
&tok!("instanceof") | &Token::BinOp(..) => {
self.emit_err(self.input.cur_span(), SyntaxError::TS1109);
Box::new(Expr::Invalid(Invalid { span: err.span() }))
Invalid { span: err.span() }.into()
}
_ => return Err(err),
}
@ -98,17 +98,19 @@ impl<I: Tokens> Parser<I> {
bump!(self); // as
let _ = cur!(self, false);
bump!(self); // const
Box::new(Expr::TsConstAssertion(TsConstAssertion {
TsConstAssertion {
span: span!(self, start),
expr,
}))
}
.into()
} else {
let type_ann = self.next_then_parse_ts_type()?;
Box::new(Expr::TsAs(TsAsExpr {
TsAsExpr {
span: span!(self, start),
expr,
type_ann,
}))
}
.into()
};
return self.parse_bin_op_recursively_inner(node, min_prec);
@ -121,11 +123,12 @@ impl<I: Tokens> Parser<I> {
let expr = left;
let node = {
let type_ann = self.next_then_parse_ts_type()?;
Box::new(Expr::TsSatisfies(TsSatisfiesExpr {
TsSatisfiesExpr {
span: span!(self, start),
expr,
type_ann,
}))
}
.into()
};
return self.parse_bin_op_recursively_inner(node, min_prec);
@ -227,12 +230,13 @@ impl<I: Tokens> Parser<I> {
}
}
let node = Box::new(Expr::Bin(BinExpr {
let node = BinExpr {
span: Span::new(left.span_lo(), right.span_hi()),
op,
left,
right,
}));
}
.into();
Ok((node, Some(min_prec)))
}
@ -248,10 +252,11 @@ impl<I: Tokens> Parser<I> {
if eat!(self, "const") {
expect!(self, '>');
let expr = self.parse_unary_expr()?;
return Ok(Box::new(Expr::TsConstAssertion(TsConstAssertion {
return Ok(TsConstAssertion {
span: span!(self, start),
expr,
})));
}
.into());
}
return self
@ -272,12 +277,13 @@ impl<I: Tokens> Parser<I> {
let span = Span::new(start, arg.span_hi());
self.check_assign_target(&arg, false);
return Ok(Box::new(Expr::Update(UpdateExpr {
return Ok(UpdateExpr {
span,
prefix: true,
op,
arg,
})));
}
.into());
}
// Parse unary expression
@ -297,9 +303,10 @@ impl<I: Tokens> Parser<I> {
Ok(expr) => expr,
Err(err) => {
self.emit_error(err);
Box::new(Expr::Invalid(Invalid {
Invalid {
span: Span::new(arg_start, arg_start),
}))
}
.into()
}
};
@ -321,11 +328,12 @@ impl<I: Tokens> Parser<I> {
}
}
return Ok(Box::new(Expr::Unary(UnaryExpr {
return Ok(UnaryExpr {
span: Span::new(start, arg.span_hi()),
op,
arg,
})));
}
.into());
}
if is!(self, "await") {
@ -350,12 +358,13 @@ impl<I: Tokens> Parser<I> {
op!("--")
};
return Ok(Box::new(Expr::Update(UpdateExpr {
return Ok(UpdateExpr {
span: span!(self, expr.span_lo()),
prefix: false,
op,
arg: expr,
})));
}
.into());
}
Ok(expr)
}
@ -383,10 +392,7 @@ impl<I: Tokens> Parser<I> {
self.emit_err(span, SyntaxError::InvalidIdentInAsync);
}
return Ok(Box::new(Expr::Ident(Ident::new_no_ctxt(
"await".into(),
span,
))));
return Ok(Ident::new_no_ctxt("await".into(), span).into());
}
if ctx.in_function && !ctx.in_async {
@ -398,10 +404,11 @@ impl<I: Tokens> Parser<I> {
}
let arg = self.parse_unary_expr()?;
Ok(Box::new(Expr::Await(AwaitExpr {
Ok(AwaitExpr {
span: span!(self, start),
arg,
})))
}
.into())
}
}

View File

@ -34,16 +34,20 @@ fn expr(s: &'static str) -> Box<Expr> {
})
}
fn regex_expr() -> Box<Expr> {
Box::new(Expr::Assign(AssignExpr {
AssignExpr {
span,
left: Ident::new_no_ctxt("re".into(), span).into(),
op: AssignOp::Assign,
right: Box::new(Expr::Lit(Lit::Regex(Regex {
span,
exp: "w+".into(),
flags: "".into(),
}))),
}))
right: Box::new(
Lit::Regex(Regex {
span,
exp: "w+".into(),
flags: "".into(),
})
.into(),
),
}
.into()
}
#[test]
fn regex_single_line_comment() {

View File

@ -134,7 +134,7 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
if let Some(trailing_comma) = trailing_comma {
self.state.trailing_commas.insert(span.lo, trailing_comma);
}
Ok(Box::new(Expr::Object(ObjectLit { span, props })))
Ok(ObjectLit { span, props }.into())
}
/// spec: 'PropertyDefinition'
@ -192,9 +192,10 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
self.emit_err(self.input.cur_span(), SyntaxError::TS1005);
return Ok(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key,
value: Box::new(Expr::Invalid(Invalid {
value: Invalid {
span: span!(self, start),
})),
}
.into(),
}))));
}
//
@ -373,7 +374,7 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
SyntaxError::SetterParam,
);
Pat::Invalid(Invalid { span: DUMMY_SP })
Invalid { span: DUMMY_SP }.into()
}),
);
@ -454,12 +455,13 @@ impl<I: Tokens> ParseObject<Pat> for Parser<I> {
let optional = (self.input.syntax().dts() || self.ctx().in_declare) && eat!(self, '?');
Ok(Pat::Object(ObjectPat {
Ok(ObjectPat {
span,
props,
optional,
type_ann: None,
}))
}
.into())
}
/// Production 'BindingProperty'

View File

@ -76,11 +76,12 @@ impl<I: Tokens> Parser<I> {
self.emit_err(span!(self, start), SyntaxError::TS2371);
}
return Ok(Pat::Assign(AssignPat {
return Ok(AssignPat {
span: span!(self, start),
left: Box::new(left),
right,
}));
}
.into());
}
Ok(left)
@ -117,12 +118,13 @@ impl<I: Tokens> Parser<I> {
let pat = self.parse_binding_pat_or_ident()?;
rest_span = span!(self, start);
let pat = Pat::Rest(RestPat {
let pat = RestPat {
span: rest_span,
dot3_token,
arg: Box::new(pat),
type_ann: None,
});
}
.into();
elems.push(Some(pat));
} else {
elems.push(self.parse_binding_element().map(Some)?);
@ -139,12 +141,13 @@ impl<I: Tokens> Parser<I> {
expect!(self, ']');
let optional = (self.input.syntax().dts() || self.ctx().in_declare) && eat!(self, '?');
Ok(Pat::Array(ArrayPat {
Ok(ArrayPat {
span: span!(self, start),
elems,
optional,
type_ann: None,
}))
}
.into())
}
pub(super) fn eat_any_ts_modifier(&mut self) -> PResult<bool> {
@ -260,11 +263,12 @@ impl<I: Tokens> Parser<I> {
self.emit_err(span!(self, start), SyntaxError::TS2371);
}
Pat::Assign(AssignPat {
AssignPat {
span: span!(self, start),
left: Box::new(pat),
right,
})
}
.into()
} else {
pat
};
@ -304,12 +308,13 @@ impl<I: Tokens> Parser<I> {
};
rest_span = span!(self, pat_start);
let pat = Pat::Rest(RestPat {
let pat = RestPat {
span: rest_span,
dot3_token,
arg: Box::new(pat),
type_ann,
});
}
.into();
params.push(ParamOrTsParamProp::Param(Param {
span: span!(self, param_start),
decorators,
@ -429,12 +434,13 @@ impl<I: Tokens> Parser<I> {
};
rest_span = span!(self, pat_start);
let pat = Pat::Rest(RestPat {
let pat = RestPat {
span: rest_span,
dot3_token,
arg: Box::new(pat),
type_ann,
});
}
.into();
if self.syntax().typescript() && eat!(self, '?') {
self.emit_err(self.input.prev_span(), SyntaxError::TS1047);
@ -493,7 +499,7 @@ impl<I: Tokens> Parser<I> {
/// rest.
pub(super) fn reparse_expr_as_pat(&mut self, pat_ty: PatType, expr: Box<Expr>) -> PResult<Pat> {
if let Expr::Invalid(i) = *expr {
return Ok(Pat::Invalid(i));
return Ok(i.into());
}
if pat_ty == PatType::AssignPat {
@ -536,11 +542,11 @@ impl<I: Tokens> Parser<I> {
// to these rules if that phrase were substituted for
// LeftHandSideExpression. This rule is recursively applied.
Expr::Paren(..) => {
return Ok(Pat::Expr(expr));
return Ok(expr.into());
}
Expr::Ident(i) => return Ok(i.into()),
_ => {
return Ok(Pat::Expr(expr));
return Ok(expr.into());
}
},
}
@ -572,7 +578,7 @@ impl<I: Tokens> Parser<I> {
match *expr {
Expr::Ident(i) => return Ok(i.into()),
_ => {
return Ok(Pat::Expr(expr));
return Ok(expr.into());
}
}
}
@ -587,7 +593,7 @@ impl<I: Tokens> Parser<I> {
match *expr {
Expr::Paren(..) => {
self.emit_err(span, SyntaxError::InvalidPat);
Ok(Pat::Invalid(Invalid { span }))
Ok(Invalid { span }.into())
}
Expr::Assign(
assign_expr @ AssignExpr {
@ -598,7 +604,7 @@ impl<I: Tokens> Parser<I> {
let AssignExpr {
span, left, right, ..
} = assign_expr;
Ok(Pat::Assign(AssignPat {
Ok(AssignPat {
span,
left: match left {
AssignTarget::Simple(left) => {
@ -607,7 +613,8 @@ impl<I: Tokens> Parser<I> {
AssignTarget::Pat(pat) => pat.into(),
},
right,
}))
}
.into())
}
Expr::Object(ObjectLit {
span: object_span,
@ -615,7 +622,7 @@ impl<I: Tokens> Parser<I> {
}) => {
// {}
let len = props.len();
Ok(Pat::Object(ObjectPat {
Ok(ObjectPat {
span: object_span,
props: props
.into_iter()
@ -690,19 +697,21 @@ impl<I: Tokens> Parser<I> {
.collect::<PResult<_>>()?,
optional: false,
type_ann: None,
}))
}
.into())
}
Expr::Ident(ident) => Ok(ident.into()),
Expr::Array(ArrayLit {
elems: mut exprs, ..
}) => {
if exprs.is_empty() {
return Ok(Pat::Array(ArrayPat {
return Ok(ArrayPat {
span,
elems: vec![],
optional: false,
type_ann: None,
}));
}
.into());
}
// Trailing comma may exist. We should remove those commas.
@ -753,12 +762,13 @@ impl<I: Tokens> Parser<I> {
let expr_span = expr.span();
self.reparse_expr_as_pat(pat_ty.element(), expr)
.map(|pat| {
Pat::Rest(RestPat {
RestPat {
span: expr_span,
dot3_token,
arg: Box::new(pat),
type_ann: None,
})
}
.into()
})
.map(Some)?
}
@ -771,30 +781,31 @@ impl<I: Tokens> Parser<I> {
};
params.push(last);
}
Ok(Pat::Array(ArrayPat {
Ok(ArrayPat {
span,
elems: params,
optional: false,
type_ann: None,
}))
}
.into())
}
// Invalid patterns.
// Note that assignment expression with '=' is valid, and handled above.
Expr::Lit(..) | Expr::Assign(..) => {
self.emit_err(span, SyntaxError::InvalidPat);
Ok(Pat::Invalid(Invalid { span }))
Ok(Invalid { span }.into())
}
Expr::Yield(..) if self.ctx().in_generator => {
self.emit_err(span, SyntaxError::InvalidPat);
Ok(Pat::Invalid(Invalid { span }))
Ok(Invalid { span }.into())
}
_ => {
self.emit_err(span, SyntaxError::InvalidPat);
Ok(Pat::Invalid(Invalid { span }))
Ok(Invalid { span }.into())
}
}
}
@ -845,12 +856,13 @@ impl<I: Tokens> Parser<I> {
}
let expr_span = expr.span();
self.reparse_expr_as_pat(pat_ty, expr).map(|pat| {
Pat::Rest(RestPat {
RestPat {
span: expr_span,
dot3_token,
arg: Box::new(pat),
type_ann: None,
})
}
.into()
})?
}
AssignTargetOrSpread::ExprOrSpread(ExprOrSpread { expr, .. }) => {
@ -940,12 +952,15 @@ mod tests {
}
fn rest() -> Option<Pat> {
Some(Pat::Rest(RestPat {
span,
dot3_token: span,
type_ann: None,
arg: Box::new(Pat::Ident(ident("tail").into())),
}))
Some(
RestPat {
span,
dot3_token: span,
type_ann: None,
arg: ident("tail").into(),
}
.into(),
)
}
#[test]
@ -1153,12 +1168,13 @@ mod tests {
fn prop(key: PropName, assign_name: &str, expr: Expr) -> PropOrSpread {
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
key,
value: Box::new(Expr::Assign(AssignExpr {
value: AssignExpr {
span,
op: AssignOp::Assign,
left: ident(assign_name).into(),
right: Box::new(expr),
})),
}
.into(),
})))
}

View File

@ -263,7 +263,7 @@ impl<'a, I: Tokens> Parser<I> {
return Ok(Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Invalid(Invalid { span })),
expr: Invalid { span }.into(),
}));
}
@ -276,7 +276,7 @@ impl<'a, I: Tokens> Parser<I> {
return Ok(Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Invalid(Invalid { span })),
expr: Invalid { span }.into(),
}));
}
@ -399,7 +399,7 @@ impl<'a, I: Tokens> Parser<I> {
if eat!(self, ':') {
return self.parse_labelled_stmt(ident);
}
Box::new(Expr::Ident(ident))
ident.into()
}
_ => self.verify_expr(expr)?,
};
@ -1327,7 +1327,7 @@ impl<'a, I: Tokens> Parser<I> {
if is_using_decl {
let name = self.parse_binding_ident()?;
let decl = VarDeclarator {
name: Pat::Ident(name),
name: name.into(),
span: span!(self, start),
init: None,
definite: false,

View File

@ -1027,7 +1027,7 @@ impl<I: Tokens> Parser<I> {
// Note: TS uses parseLeftHandSideExpressionOrHigher,
// then has grammar errors later if it's not an EntityName.
let ident = Box::new(Expr::Ident(self.parse_ident_name()?.into()));
let ident = self.parse_ident_name()?.into();
let expr = self.parse_subscripts(Callee::Expr(ident), true, true)?;
if !matches!(
&*expr,
@ -1390,9 +1390,9 @@ impl<I: Tokens> Parser<I> {
Either::Left(e) => {
p.emit_err(e.span(), SyntaxError::PrivateNameInInterface);
Box::new(Expr::PrivateName(e))
e.into()
}
Either::Right(e) => Box::new(Expr::Ident(e.into())),
Either::Right(e) => e.into(),
}),
};
@ -1736,14 +1736,15 @@ impl<I: Tokens> Parser<I> {
expect!(p, ':');
Ok(Some(if let Some(dot3_token) = rest {
Pat::Rest(RestPat {
RestPat {
span: span!(p, start),
dot3_token,
arg: Box::new(Pat::Ident(ident.into())),
arg: ident.into(),
type_ann: None,
})
}
.into()
} else {
Pat::Ident(ident.into())
ident.into()
}))
})
}

View File

@ -25,10 +25,11 @@ impl Fold for Normalizer {
match e {
Expr::Paren(ParenExpr { expr, .. }) if self.is_test262 => *expr,
Expr::New(n @ NewExpr { args: None, .. }) if self.is_test262 => Expr::New(NewExpr {
Expr::New(n @ NewExpr { args: None, .. }) if self.is_test262 => NewExpr {
args: Some(vec![]),
..n
}),
}
.into(),
// Flatten comma expressions.
Expr::Seq(SeqExpr { mut exprs, span }) => {
let need_work = exprs.iter().any(|n| matches!(**n, Expr::Seq(..)));
@ -42,7 +43,7 @@ impl Fold for Normalizer {
v
});
}
Expr::Seq(SeqExpr { exprs, span })
SeqExpr { exprs, span }.into()
}
_ => e,
}
@ -84,9 +85,9 @@ impl Fold for Normalizer {
if let Pat::Expr(expr) = node {
match *expr {
Expr::Ident(i) => return Pat::Ident(i.into()),
Expr::Ident(i) => return i.into(),
_ => {
node = Pat::Expr(expr);
node = expr.into();
}
}
}

View File

@ -123,9 +123,9 @@ impl Fold for Normalizer {
if let Pat::Expr(expr) = node {
match *expr {
Expr::Ident(i) => return Pat::Ident(i.into()),
Expr::Ident(i) => return i.into(),
_ => {
node = Pat::Expr(expr);
node = expr.into();
}
}
}

View File

@ -144,7 +144,7 @@ impl Visit for UsageVisitor {
self.visit_object_pat_props(init, &o.props)
}
} else if let Pat::Object(ref o) = d.name {
self.visit_object_pat_props(&Expr::Ident(Ident::default()), &o.props)
self.visit_object_pat_props(&Ident::default().into(), &o.props)
}
}

View File

@ -254,7 +254,7 @@ impl Visit for UsageVisitor {
self.visit_object_pat_props(init, &o.props)
}
} else if let Pat::Object(ref o) = d.name {
self.visit_object_pat_props(&Expr::Ident(Ident::default()), &o.props)
self.visit_object_pat_props(&Ident::default().into(), &o.props)
}
}

View File

@ -511,11 +511,11 @@ impl VisitMut for Polyfills {
span: DUMMY_SP,
expr: CallExpr {
span,
callee: Expr::Ident(Ident {
callee: Ident {
ctxt: SyntaxContext::empty().apply_mark(self.unresolved_mark),
sym: "require".into(),
..Default::default()
})
}
.as_callee(),
args: vec![Str {
span: DUMMY_SP,
@ -538,11 +538,11 @@ impl VisitMut for Polyfills {
span: DUMMY_SP,
expr: CallExpr {
span,
callee: Expr::Ident(Ident {
callee: Ident {
ctxt: SyntaxContext::empty().apply_mark(self.unresolved_mark),
sym: "require".into(),
..Default::default()
})
}
.as_callee(),
args: vec![Str {
span: DUMMY_SP,

View File

@ -120,12 +120,13 @@ fn fold_noop_impl_vec(b: &mut Bencher) {
}
fn mk_expr() -> Expr {
Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: Ident::new_no_ctxt("foo".into(), DUMMY_SP).as_callee(),
args: vec![],
..Default::default()
})
}
.into()
}
fn boxing_boxed_clone(b: &mut Bencher) {

View File

@ -486,8 +486,8 @@ impl VisitMut for Fixer<'_> {
_ => false,
} =>
{
let expr = Expr::Ident(p.clone().expect_ident().into());
s.left = ForHead::Pat(Box::new(Pat::Expr(Box::new(expr))));
let expr: Pat = p.clone().expect_ident().into();
s.left = ForHead::Pat(expr.into());
}
_ => (),
}
@ -878,7 +878,7 @@ impl Fixer<'_> {
}
}
let mut expr = Expr::Seq(SeqExpr { span: *span, exprs });
let mut expr = SeqExpr { span: *span, exprs }.into();
if let Context::ForcedExpr = self.ctx {
self.wrap(&mut expr);
@ -985,7 +985,7 @@ impl Fixer<'_> {
};
let expr = Box::new(e.take());
*e = Expr::Paren(ParenExpr { expr, span });
*e = ParenExpr { expr, span }.into();
}
/// Removes paren
@ -1071,7 +1071,7 @@ fn ignore_return_value(expr: Box<Expr>, has_padding_value: &mut bool) -> Option<
match exprs.len() {
0 | 1 => exprs.pop(),
_ => Some(Box::new(Expr::Seq(SeqExpr { span, exprs }))),
_ => Some(SeqExpr { span, exprs }.into()),
}
}
Expr::Unary(UnaryExpr {

View File

@ -434,7 +434,7 @@ impl InjectHelpers {
fn build_reqire(&self, name: &str, mark: Mark) -> Stmt {
let c = CallExpr {
span: DUMMY_SP,
callee: Expr::Ident(Ident {
callee: Expr::from(Ident {
span: DUMMY_SP,
ctxt: SyntaxContext::empty().apply_mark(self.global_mark),
sym: "require".into(),

View File

@ -132,7 +132,7 @@ where
let var = VarDeclarator {
span,
name: cls.ident.clone().into(),
init: Some(Box::new(Expr::Class(expr))),
init: Some(expr.into()),
definite: false,
};
*decl = VarDecl {
@ -466,11 +466,12 @@ where
*n = KeyValuePatProp {
key: PropName::Ident(p.key.take().into()),
value: match p.value.take() {
Some(default_expr) => Box::new(Pat::Assign(AssignPat {
Some(default_expr) => AssignPat {
span: p.span,
left: renamed.into(),
right: default_expr,
})),
}
.into(),
None => renamed.into(),
},
}
@ -500,7 +501,7 @@ where
span: i.span,
sym: i.sym.clone(),
}),
value: Box::new(Expr::Ident(renamed)),
value: renamed.into(),
})
}
}

View File

@ -15,10 +15,11 @@ pub mod super_field;
/// Child.__proto__ || Object.getPrototypeOf(Child)
/// ```
pub fn get_prototype_of(obj: Box<Expr>) -> Box<Expr> {
Box::new(Expr::Call(CallExpr {
CallExpr {
span: DUMMY_SP,
callee: helper!(get_prototype_of),
args: vec![obj.as_arg()],
..Default::default()
}))
}
.into()
}

View File

@ -75,7 +75,7 @@ impl<'a> VisitMut for SuperFieldAccessFolder<'a> {
fn visit_mut_expr(&mut self, n: &mut Expr) {
match n {
Expr::This(ThisExpr { span }) if self.in_nested_scope => {
*n = Expr::Ident(quote_ident!(
*n = quote_ident!(
SyntaxContext::empty().apply_mark(
*self
.this_alias_mark
@ -83,7 +83,8 @@ impl<'a> VisitMut for SuperFieldAccessFolder<'a> {
),
*span,
"_this"
));
)
.into();
}
// We pretend method folding mode for while folding injected `_define_property`
// calls.
@ -210,7 +211,7 @@ impl<'a> SuperFieldAccessFolder<'a> {
let mut args = args.clone();
if args.len() == 1 && is_rest_arguments(&args[0]) {
*n = Expr::Call(CallExpr {
*n = CallExpr {
span: DUMMY_SP,
callee: callee.make_member(quote_ident!("apply")).as_callee(),
args: iter::once(this)
@ -221,16 +222,18 @@ impl<'a> SuperFieldAccessFolder<'a> {
}))
.collect(),
..Default::default()
});
}
.into();
return;
}
*n = Expr::Call(CallExpr {
*n = CallExpr {
span: DUMMY_SP,
callee: callee.make_member(quote_ident!("call")).as_callee(),
args: iter::once(this).chain(args).collect(),
..Default::default()
});
}
.into();
}
}
}
@ -313,7 +316,7 @@ impl<'a> SuperFieldAccessFolder<'a> {
});
// in static default super class is Function.prototype
if self.is_static && self.super_class.is_some() {
Expr::Ident(name)
name.into()
} else {
name.make_member(quote_ident!("prototype")).into()
}
@ -370,18 +373,19 @@ impl<'a> SuperFieldAccessFolder<'a> {
},
};
Expr::Assign(AssignExpr {
AssignExpr {
span: super_token,
left: left.into(),
op,
right: rhs,
})
}
.into()
} else {
let proto_arg = self.proto_arg();
let prop_arg = prop_arg(prop).as_arg();
Expr::Call(CallExpr {
CallExpr {
span: super_token,
callee: helper!(set),
args: vec![
@ -393,7 +397,8 @@ impl<'a> SuperFieldAccessFolder<'a> {
true.as_arg(),
],
..Default::default()
})
}
.into()
}
}
@ -404,7 +409,7 @@ impl<'a> SuperFieldAccessFolder<'a> {
let this_arg = self.this_arg(super_token).as_arg();
let expr = Expr::Call(CallExpr {
let expr: Expr = CallExpr {
span: super_token,
callee: helper!(update),
args: vec![
@ -415,7 +420,8 @@ impl<'a> SuperFieldAccessFolder<'a> {
true.as_arg(),
],
..Default::default()
});
}
.into();
expr.make_member(quote_ident!("_"))
}
@ -423,7 +429,7 @@ impl<'a> SuperFieldAccessFolder<'a> {
fn proto_arg(&mut self) -> Box<Expr> {
let expr = if self.is_static {
// Foo
Box::new(Expr::Ident(self.class_name.clone()))
self.class_name.clone().into()
} else {
// Foo.prototype
self.class_name
@ -484,11 +490,12 @@ fn prop_arg(prop: SuperProp) -> Expr {
match prop {
SuperProp::Ident(IdentName {
sym: value, span, ..
}) => Expr::Lit(Lit::Str(Str {
}) => Lit::Str(Str {
span,
raw: None,
value,
})),
})
.into(),
SuperProp::Computed(c) => *c.expr,
}
}

View File

@ -276,7 +276,7 @@ impl VisitMut for ComputedFieldsHandler {
if !is_literal(expr) && !is_simple_pure_expr(expr, self.pure_getters) =>
{
let ref_key = private_ident!("prop");
let mut computed_expr = Box::new(Expr::Ident(ref_key.clone()));
let mut computed_expr = ref_key.clone().into();
mem::swap(expr, &mut computed_expr);

View File

@ -25,8 +25,8 @@ impl Fold for ParenRemover {
match expr {
Expr::Paren(ParenExpr { expr, .. }) => match *expr {
Expr::Member(e) => Expr::Member(MemberExpr { span, ..e }),
Expr::New(e) => Expr::New(NewExpr { span, ..e }),
Expr::Member(e) => MemberExpr { span, ..e }.into(),
Expr::New(e) => NewExpr { span, ..e }.into(),
_ => *expr,
},
_ => expr,

Some files were not shown because too many files have changed in this diff Show More