mirror of
https://github.com/swc-project/swc.git
synced 2024-10-05 04:39:06 +03:00
Improve transforms (#1035)
swc_ecma_transforms: - Fix `this` in optional chaining expression. (https://github.com/Brooooooklyn/swc-node/issues/62) - Optimize typescript stripper - Optimize fixer
This commit is contained in:
parent
eb2162cbd2
commit
57112fc42b
7
.github/workflows/cargo.yml
vendored
7
.github/workflows/cargo.yml
vendored
@ -76,12 +76,15 @@ jobs:
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/swc-project/ts-parser-test-ref.git ecmascript/parser/tests/typescript/tsc
|
||||
|
||||
- name: Run cargo test
|
||||
- name: Run fast cargo test
|
||||
run: |
|
||||
export PATH="$PATH:$HOME/npm/bin"
|
||||
EXEC=0 cargo test --color always --all --exclude node --exclude wasm
|
||||
cargo test --color always --all --exclude node --exclude wasm
|
||||
|
||||
- name: Run slow cargo test
|
||||
run: |
|
||||
export PATH="$PATH:$HOME/npm/bin"
|
||||
cargo test --color always --all --exclude node --exclude wasm
|
||||
#
|
||||
deploy-docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -107,39 +107,6 @@ fn config_for_file(b: &mut Bencher) {
|
||||
}
|
||||
|
||||
/// This benchmark exists to know exact execution time of each pass.
|
||||
#[bench]
|
||||
fn config_transforms(b: &mut Bencher) {
|
||||
let c = mk();
|
||||
let module = parse(&c);
|
||||
|
||||
b.iter(|| {
|
||||
let program = module.clone();
|
||||
|
||||
let mut config = c
|
||||
.config_for_file(
|
||||
&Options {
|
||||
config: Some(Config {
|
||||
jsc: JscConfig {
|
||||
target: JscTarget::Es2016,
|
||||
syntax: Some(Syntax::Typescript(TsConfig {
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
},
|
||||
module: None,
|
||||
..Default::default()
|
||||
}),
|
||||
swcrc: false,
|
||||
is_module: true,
|
||||
..Default::default()
|
||||
},
|
||||
&FileName::Real("rxjs/src/internal/observable/dom/AjaxObservable.ts".into()),
|
||||
)
|
||||
.unwrap();
|
||||
let program = c.run_transform(true, || program.fold_with(&mut config.pass));
|
||||
black_box(program)
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_codegen(b: &mut Bencher, _target: JscTarget) {
|
||||
let c = mk();
|
||||
@ -220,3 +187,63 @@ compat!(full_es2017, JscTarget::Es2017);
|
||||
compat!(full_es2018, JscTarget::Es2018);
|
||||
compat!(full_es2019, JscTarget::Es2019);
|
||||
compat!(full_es2020, JscTarget::Es2020);
|
||||
|
||||
macro_rules! tr_only {
|
||||
($name:ident, $target:expr) => {
|
||||
#[bench]
|
||||
fn $name(b: &mut Bencher) {
|
||||
let c = mk();
|
||||
let module = parse(&c);
|
||||
|
||||
b.iter(|| {
|
||||
let program = module.clone();
|
||||
|
||||
let mut config = c
|
||||
.config_for_file(
|
||||
&Options {
|
||||
config: Some(Config {
|
||||
jsc: JscConfig {
|
||||
target: $target,
|
||||
syntax: Some(Syntax::Typescript(TsConfig {
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
},
|
||||
module: None,
|
||||
..Default::default()
|
||||
}),
|
||||
swcrc: false,
|
||||
is_module: true,
|
||||
..Default::default()
|
||||
},
|
||||
&FileName::Real(
|
||||
"rxjs/src/internal/observable/dom/AjaxObservable.ts".into(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
let program = c.run_transform(true, || program.fold_with(&mut config.pass));
|
||||
black_box(program)
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
tr_only!(transforms_es3, JscTarget::Es3);
|
||||
tr_only!(transforms_es5, JscTarget::Es5);
|
||||
tr_only!(transforms_es2015, JscTarget::Es2015);
|
||||
tr_only!(transforms_es2016, JscTarget::Es2016);
|
||||
tr_only!(transforms_es2017, JscTarget::Es2017);
|
||||
tr_only!(transforms_es2018, JscTarget::Es2018);
|
||||
tr_only!(transforms_es2019, JscTarget::Es2019);
|
||||
tr_only!(transforms_es2020, JscTarget::Es2020);
|
||||
|
||||
#[bench]
|
||||
fn parser(b: &mut Bencher) {
|
||||
let c = mk();
|
||||
|
||||
//TODO: Use target
|
||||
|
||||
b.iter(|| {
|
||||
black_box(parse(&c));
|
||||
})
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_ecma_transforms"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.23.2"
|
||||
version = "0.23.3"
|
||||
|
||||
[features]
|
||||
const-modules = ["dashmap"]
|
||||
|
@ -6,6 +6,7 @@ use std::{fmt::Debug, iter::once, mem};
|
||||
use swc_common::{Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::alias_if_required;
|
||||
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit};
|
||||
|
||||
pub fn optional_chaining() -> impl Fold {
|
||||
@ -330,9 +331,8 @@ impl OptChaining {
|
||||
type_args,
|
||||
..
|
||||
}) => {
|
||||
let obj = *obj;
|
||||
let obj_span = obj.span();
|
||||
let is_super_access = match obj {
|
||||
let is_super_access = match *obj {
|
||||
Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Super(..),
|
||||
..
|
||||
@ -340,9 +340,35 @@ impl OptChaining {
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let (left, right, alt) = match obj {
|
||||
Expr::Ident(..) => (Box::new(obj.clone()), Box::new(obj), e.expr),
|
||||
let (left, right, alt) = match *obj {
|
||||
Expr::Ident(..) => (obj.clone(), obj, e.expr),
|
||||
_ => {
|
||||
let this_as_super;
|
||||
let (this_obj, aliased) = alias_if_required(
|
||||
match &*obj {
|
||||
Expr::Member(m) => match &m.obj {
|
||||
ExprOrSuper::Super(s) => {
|
||||
this_as_super = Expr::This(ThisExpr { span: s.span });
|
||||
&this_as_super
|
||||
}
|
||||
ExprOrSuper::Expr(obj) => &**obj,
|
||||
},
|
||||
_ => &*obj,
|
||||
},
|
||||
"_obj",
|
||||
);
|
||||
let obj = if !is_super_access && aliased {
|
||||
self.vars.push(VarDeclarator {
|
||||
span: obj_span,
|
||||
definite: false,
|
||||
name: Pat::Ident(this_obj.clone()),
|
||||
init: Some(obj),
|
||||
});
|
||||
|
||||
Box::new(Expr::Ident(this_obj.clone()))
|
||||
} else {
|
||||
obj
|
||||
};
|
||||
let i = private_ident!(obj_span, "ref");
|
||||
self.vars.push(VarDeclarator {
|
||||
span: obj_span,
|
||||
@ -356,7 +382,7 @@ impl OptChaining {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(Box::new(Pat::Ident(i.clone()))),
|
||||
op: op!("="),
|
||||
right: Box::new(obj),
|
||||
right: obj,
|
||||
})),
|
||||
Box::new(Expr::Ident(i.clone())),
|
||||
Box::new(Expr::Call(CallExpr {
|
||||
@ -367,11 +393,10 @@ impl OptChaining {
|
||||
prop: Box::new(Expr::Ident(Ident::new("call".into(), span))),
|
||||
computed: false,
|
||||
}))),
|
||||
// TODO;
|
||||
args: once(if is_super_access {
|
||||
ThisExpr { span }.as_arg()
|
||||
} else {
|
||||
i.as_arg()
|
||||
this_obj.as_arg()
|
||||
})
|
||||
.chain(args)
|
||||
.collect(),
|
||||
|
@ -92,6 +92,18 @@ impl VisitMut for Fixer<'_> {
|
||||
self.ctx = old;
|
||||
}
|
||||
|
||||
fn visit_mut_assign_expr(&mut self, expr: &mut AssignExpr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
match &mut *expr.right {
|
||||
// `foo = (bar = baz)` => foo = bar = baz
|
||||
Expr::Assign(AssignExpr { ref left, .. }) if left.as_ident().is_some() => {}
|
||||
|
||||
Expr::Seq(..) => self.wrap(&mut expr.right),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_arrow_expr(&mut self, node: &mut ArrowExpr) {
|
||||
let old = self.ctx;
|
||||
self.ctx = Context::Default;
|
||||
@ -105,6 +117,116 @@ impl VisitMut for Fixer<'_> {
|
||||
self.ctx = old;
|
||||
}
|
||||
|
||||
fn visit_mut_bin_expr(&mut self, expr: &mut BinExpr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
match &mut *expr.right {
|
||||
Expr::Assign(..)
|
||||
| Expr::Seq(..)
|
||||
| Expr::Yield(..)
|
||||
| Expr::Cond(..)
|
||||
| Expr::Arrow(..) => {
|
||||
self.wrap(&mut expr.right);
|
||||
}
|
||||
Expr::Bin(BinExpr { op: op_of_rhs, .. }) => {
|
||||
if op_of_rhs.precedence() <= expr.op.precedence() {
|
||||
self.wrap(&mut expr.right);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match &mut *expr.left {
|
||||
// While simplifying, (1 + x) * Nan becomes `1 + x * Nan`.
|
||||
// But it should be `(1 + x) * Nan`
|
||||
Expr::Bin(BinExpr { op: op_of_lhs, .. }) => {
|
||||
if op_of_lhs.precedence() < expr.op.precedence() {
|
||||
self.wrap(&mut expr.left);
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Seq(..)
|
||||
| Expr::Update(..)
|
||||
| Expr::Unary(UnaryExpr {
|
||||
op: op!("delete"), ..
|
||||
})
|
||||
| Expr::Unary(UnaryExpr {
|
||||
op: op!("void"), ..
|
||||
})
|
||||
| Expr::Yield(..)
|
||||
| Expr::Cond(..)
|
||||
| Expr::Assign(..)
|
||||
| Expr::Arrow(..) => {
|
||||
self.wrap(&mut expr.left);
|
||||
}
|
||||
Expr::Object(..)
|
||||
if expr.op == op!("instanceof")
|
||||
|| expr.op == op!("==")
|
||||
|| expr.op == op!("===")
|
||||
|| expr.op == op!("!=")
|
||||
|| expr.op == op!("!==") =>
|
||||
{
|
||||
self.wrap(&mut expr.left)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_member_expr(&mut self, n: &mut MemberExpr) {
|
||||
n.obj.visit_mut_with(self);
|
||||
n.prop.visit_mut_with(self);
|
||||
|
||||
match n {
|
||||
MemberExpr { obj, .. }
|
||||
if obj.as_expr().map(|e| e.is_object()).unwrap_or(false)
|
||||
&& match self.ctx {
|
||||
Context::ForcedExpr { is_var_decl: true } => true,
|
||||
_ => false,
|
||||
} => {}
|
||||
|
||||
MemberExpr {
|
||||
obj: ExprOrSuper::Expr(ref mut obj),
|
||||
..
|
||||
} if obj.is_fn_expr()
|
||||
|| obj.is_cond()
|
||||
|| obj.is_unary()
|
||||
|| obj.is_seq()
|
||||
|| obj.is_update()
|
||||
|| obj.is_bin()
|
||||
|| obj.is_object()
|
||||
|| obj.is_assign()
|
||||
|| obj.is_arrow()
|
||||
|| obj.is_class()
|
||||
|| obj.is_yield_expr()
|
||||
|| obj.is_await_expr()
|
||||
|| match **obj {
|
||||
Expr::New(NewExpr { args: None, .. }) => true,
|
||||
_ => false,
|
||||
} =>
|
||||
{
|
||||
self.wrap(&mut **obj);
|
||||
return;
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_unary_expr(&mut self, n: &mut UnaryExpr) {
|
||||
n.visit_mut_children_with(self);
|
||||
|
||||
match *n.arg {
|
||||
Expr::Assign(..)
|
||||
| Expr::Bin(..)
|
||||
| Expr::Seq(..)
|
||||
| Expr::Cond(..)
|
||||
| Expr::Arrow(..)
|
||||
| Expr::Yield(..) => self.wrap(&mut n.arg),
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_assign_pat_prop(&mut self, node: &mut AssignPatProp) {
|
||||
node.key.visit_mut_children_with(self);
|
||||
|
||||
@ -154,12 +276,11 @@ impl VisitMut for Fixer<'_> {
|
||||
}
|
||||
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
e.visit_mut_children_with(self);
|
||||
self.unwrap_expr(e);
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
self.wrap_with_paren_if_required(e)
|
||||
}
|
||||
|
||||
fn visit_mut_expr_or_spread(&mut self, e: &mut ExprOrSpread) {
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
@ -217,24 +338,13 @@ impl VisitMut for Fixer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_stmt(&mut self, stmt: &mut Stmt) {
|
||||
match stmt {
|
||||
Stmt::Expr(expr) => {
|
||||
let old = self.ctx;
|
||||
self.ctx = Context::Default;
|
||||
expr.visit_mut_with(self);
|
||||
self.ctx = old;
|
||||
}
|
||||
_ => stmt.visit_mut_children_with(self),
|
||||
};
|
||||
fn visit_mut_expr_stmt(&mut self, s: &mut ExprStmt) {
|
||||
let old = self.ctx;
|
||||
self.ctx = Context::Default;
|
||||
s.expr.visit_mut_with(self);
|
||||
self.ctx = old;
|
||||
|
||||
match stmt {
|
||||
Stmt::Expr(ExprStmt { ref mut expr, .. }) => {
|
||||
self.handle_expr_stmt(&mut **expr);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
self.handle_expr_stmt(&mut *s.expr);
|
||||
}
|
||||
|
||||
fn visit_mut_var_declarator(&mut self, node: &mut VarDeclarator) {
|
||||
@ -280,39 +390,6 @@ impl VisitMut for Fixer<'_> {
|
||||
impl Fixer<'_> {
|
||||
fn wrap_with_paren_if_required(&mut self, e: &mut Expr) {
|
||||
match e {
|
||||
Expr::Member(MemberExpr { obj, .. })
|
||||
if obj.as_expr().map(|e| e.is_object()).unwrap_or(false)
|
||||
&& match self.ctx {
|
||||
Context::ForcedExpr { is_var_decl: true } => true,
|
||||
_ => false,
|
||||
} =>
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(ref mut obj),
|
||||
..
|
||||
}) if obj.is_fn_expr()
|
||||
|| obj.is_cond()
|
||||
|| obj.is_unary()
|
||||
|| obj.is_seq()
|
||||
|| obj.is_update()
|
||||
|| obj.is_bin()
|
||||
|| obj.is_object()
|
||||
|| obj.is_assign()
|
||||
|| obj.is_arrow()
|
||||
|| obj.is_class()
|
||||
|| obj.is_yield_expr()
|
||||
|| obj.is_await_expr()
|
||||
|| match **obj {
|
||||
Expr::New(NewExpr { args: None, .. }) => true,
|
||||
_ => false,
|
||||
} =>
|
||||
{
|
||||
self.wrap(&mut **obj);
|
||||
}
|
||||
|
||||
// Flatten seq expr
|
||||
Expr::Seq(SeqExpr { span, exprs }) => {
|
||||
let len = exprs
|
||||
@ -364,7 +441,13 @@ impl Fixer<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => buf.push(expr.take()),
|
||||
_ => {
|
||||
if is_last {
|
||||
buf.push(expr.take());
|
||||
} else {
|
||||
buf.extend(ignore_return_value(expr.take()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,59 +474,6 @@ impl Fixer<'_> {
|
||||
};
|
||||
}
|
||||
|
||||
Expr::Bin(ref mut expr) => {
|
||||
match &mut *expr.right {
|
||||
Expr::Assign(..)
|
||||
| Expr::Seq(..)
|
||||
| Expr::Yield(..)
|
||||
| Expr::Cond(..)
|
||||
| Expr::Arrow(..) => {
|
||||
self.wrap(&mut expr.right);
|
||||
}
|
||||
Expr::Bin(BinExpr { op: op_of_rhs, .. }) => {
|
||||
if op_of_rhs.precedence() <= expr.op.precedence() {
|
||||
self.wrap(&mut expr.right);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match &mut *expr.left {
|
||||
// While simplifying, (1 + x) * Nan becomes `1 + x * Nan`.
|
||||
// But it should be `(1 + x) * Nan`
|
||||
Expr::Bin(BinExpr { op: op_of_lhs, .. }) => {
|
||||
if op_of_lhs.precedence() < expr.op.precedence() {
|
||||
self.wrap(&mut expr.left);
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Seq(..)
|
||||
| Expr::Update(..)
|
||||
| Expr::Unary(UnaryExpr {
|
||||
op: op!("delete"), ..
|
||||
})
|
||||
| Expr::Unary(UnaryExpr {
|
||||
op: op!("void"), ..
|
||||
})
|
||||
| Expr::Yield(..)
|
||||
| Expr::Cond(..)
|
||||
| Expr::Assign(..)
|
||||
| Expr::Arrow(..) => {
|
||||
self.wrap(&mut expr.left);
|
||||
}
|
||||
Expr::Object(..)
|
||||
if expr.op == op!("instanceof")
|
||||
|| expr.op == op!("==")
|
||||
|| expr.op == op!("===")
|
||||
|| expr.op == op!("!=")
|
||||
|| expr.op == op!("!==") =>
|
||||
{
|
||||
self.wrap(&mut expr.left)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Cond(expr) => {
|
||||
match &mut *expr.test {
|
||||
Expr::Seq(..) | Expr::Assign(..) | Expr::Cond(..) | Expr::Arrow(..) => {
|
||||
@ -474,27 +504,6 @@ impl Fixer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Unary(expr) => match *expr.arg {
|
||||
Expr::Assign(..)
|
||||
| Expr::Bin(..)
|
||||
| Expr::Seq(..)
|
||||
| Expr::Cond(..)
|
||||
| Expr::Arrow(..)
|
||||
| Expr::Yield(..) => self.wrap(&mut expr.arg),
|
||||
_ => {}
|
||||
},
|
||||
|
||||
Expr::Assign(expr) => {
|
||||
match &mut *expr.right {
|
||||
// `foo = (bar = baz)` => foo = bar = baz
|
||||
Expr::Assign(AssignExpr { ref left, .. }) if left.as_ident().is_some() => {}
|
||||
|
||||
// Handle `foo = bar = init()
|
||||
Expr::Seq(..) => self.wrap(&mut expr.right),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(ref mut callee),
|
||||
..
|
||||
@ -593,6 +602,25 @@ impl Fixer<'_> {
|
||||
fn ignore_return_value(expr: Box<Expr>) -> Option<Box<Expr>> {
|
||||
match *expr {
|
||||
Expr::Ident(..) | Expr::Fn(..) | Expr::Lit(..) => None,
|
||||
Expr::Seq(SeqExpr { span, exprs }) => {
|
||||
let len = exprs.len();
|
||||
let mut exprs: Vec<_> = exprs
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, expr)| {
|
||||
if i + 1 == len {
|
||||
Some(expr)
|
||||
} else {
|
||||
ignore_return_value(expr)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
match exprs.len() {
|
||||
0 | 1 => exprs.pop(),
|
||||
_ => Some(Box::new(Expr::Seq(SeqExpr { span, exprs }))),
|
||||
}
|
||||
}
|
||||
Expr::Unary(UnaryExpr {
|
||||
op: op!("void"),
|
||||
arg,
|
||||
|
@ -671,14 +671,6 @@ impl SimplifyExpr {
|
||||
|
||||
op!("~") => {
|
||||
if let Known(value) = arg.as_number() {
|
||||
println!(
|
||||
"Value: {} -> {} -> {} -> {}",
|
||||
value,
|
||||
value as u32,
|
||||
!(value as u32),
|
||||
!(value as u32) as i32
|
||||
);
|
||||
println!("{}", value as i32 as u32);
|
||||
if value.fract() == 0.0 {
|
||||
return Expr::Lit(Lit::Num(Number {
|
||||
span,
|
||||
|
@ -105,62 +105,43 @@ impl Strip {
|
||||
fn handle_expr<'a>(&mut self, n: &'a mut Expr) -> Vec<&'a mut Expr> {
|
||||
match n {
|
||||
Expr::Bin(BinExpr { left, right, .. }) => return vec![&mut **left, &mut **right],
|
||||
_ => {}
|
||||
}
|
||||
|
||||
n.map_with_mut(|expr| {
|
||||
let mut expr = match expr {
|
||||
Expr::TsAs(TsAsExpr { expr, .. })
|
||||
| Expr::TsNonNull(TsNonNullExpr { expr, .. })
|
||||
| Expr::TsTypeAssertion(TsTypeAssertion { expr, .. })
|
||||
| Expr::TsConstAssertion(TsConstAssertion { expr, .. })
|
||||
| Expr::TsTypeCast(TsTypeCastExpr { expr, .. }) => {
|
||||
let mut expr = *expr;
|
||||
expr.visit_mut_with(self);
|
||||
expr
|
||||
}
|
||||
_ => expr,
|
||||
};
|
||||
// Remove types
|
||||
Expr::TsAs(TsAsExpr { expr, .. })
|
||||
| Expr::TsNonNull(TsNonNullExpr { expr, .. })
|
||||
| Expr::TsTypeAssertion(TsTypeAssertion { expr, .. })
|
||||
| Expr::TsConstAssertion(TsConstAssertion { expr, .. })
|
||||
| Expr::TsTypeCast(TsTypeCastExpr { expr, .. }) => {
|
||||
expr.visit_mut_with(self);
|
||||
let expr = *expr.take();
|
||||
*n = expr;
|
||||
}
|
||||
|
||||
let expr = match expr {
|
||||
Expr::Bin(..) => expr,
|
||||
Expr::Member(MemberExpr {
|
||||
span,
|
||||
mut obj,
|
||||
mut prop,
|
||||
computed,
|
||||
}) => {
|
||||
obj.visit_mut_with(self);
|
||||
Expr::Member(MemberExpr {
|
||||
obj,
|
||||
prop,
|
||||
computed,
|
||||
..
|
||||
}) => {
|
||||
obj.visit_mut_with(self);
|
||||
|
||||
let prop = if computed {
|
||||
prop.visit_mut_with(self);
|
||||
prop
|
||||
} else {
|
||||
match *prop {
|
||||
Expr::Ident(i) => Box::new(Expr::Ident(Ident {
|
||||
optional: false,
|
||||
type_ann: None,
|
||||
..i
|
||||
})),
|
||||
_ => prop,
|
||||
if *computed {
|
||||
prop.visit_mut_with(self);
|
||||
} else {
|
||||
match &mut **prop {
|
||||
Expr::Ident(i) => {
|
||||
i.type_ann = None;
|
||||
i.optional = false;
|
||||
}
|
||||
};
|
||||
|
||||
Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj,
|
||||
prop,
|
||||
computed,
|
||||
})
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
expr.visit_mut_children_with(self);
|
||||
expr
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
expr
|
||||
});
|
||||
_ => {
|
||||
n.visit_mut_children_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
vec![]
|
||||
}
|
||||
|
@ -115,12 +115,12 @@ function test(foo) {
|
||||
foo === null || foo === void 0 ? void 0 : (ref = foo.bar) === null || ref === void 0 ? void 0 : ref.baz;
|
||||
foo === null || foo === void 0 ? void 0 : foo(foo);
|
||||
foo === null || foo === void 0 ? void 0 : foo.bar();
|
||||
(ref1 = foo.bar) === null || ref1 === void 0 ? void 0 : ref1.call(ref1, foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref2 = foo.bar) === null || ref2 === void 0 ? void 0 : ref2.call(ref2, foo.bar, true);
|
||||
(ref1 = foo.bar) === null || ref1 === void 0 ? void 0 : ref1.call(foo, foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref2 = foo.bar) === null || ref2 === void 0 ? void 0 : ref2.call(foo, foo.bar, true);
|
||||
(ref3 = foo.bar) === null || ref3 === void 0 ? void 0 : ref3.baz(foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref4 = foo.bar) === null || ref4 === void 0 ? void 0 : ref4.baz(foo.bar, true);
|
||||
(ref5 = foo.bar) === null || ref5 === void 0 ? void 0 : (ref6 = ref5.baz) === null || ref6 === void 0 ? void 0 : ref6.call(ref6, foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref7 = foo.bar) === null || ref7 === void 0 ? void 0 : (ref8 = ref7.baz) === null || ref8 === void 0 ? void 0 : ref8.call(ref8, foo.bar, true);
|
||||
(ref5 = foo.bar) === null || ref5 === void 0 ? void 0 : (ref6 = ref5.baz) === null || ref6 === void 0 ? void 0 : ref6.call(ref5, foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref7 = foo.bar) === null || ref7 === void 0 ? void 0 : (ref8 = ref7.baz) === null || ref8 === void 0 ? void 0 : ref8.call(ref7, foo.bar, true);
|
||||
}
|
||||
"#
|
||||
);
|
||||
@ -302,15 +302,14 @@ foo?.bar?.()?.baz
|
||||
var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8;
|
||||
foo === null || foo === void 0 ? void 0 : foo(foo);
|
||||
foo === null || foo === void 0 ? void 0 : foo.bar();
|
||||
(ref = foo.bar) === null || ref === void 0 ? void 0 : ref.call(ref, foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref1 = foo.bar) === null || ref1 === void 0 ? void 0 : ref1.call(ref1, foo.bar, true);
|
||||
(ref = foo.bar) === null || ref === void 0 ? void 0 : ref.call(foo, foo.bar, false);
|
||||
foo === null || foo === void 0 ? void 0 : (ref1 = foo.bar) === null || ref1 === void 0 ? void 0 : ref1.call(foo, foo.bar, true);
|
||||
foo === null || foo === void 0 ? void 0 : foo().bar;
|
||||
foo === null || foo === void 0 ? void 0 : (ref2 = foo()) === null || ref2 === void 0 ? void 0 : ref2.bar;
|
||||
(ref3 = foo.bar) === null || ref3 === void 0 ? void 0 : ref3.call(ref3).baz;
|
||||
(ref4 = foo.bar) === null || ref4 === void 0 ? void 0 : (ref5 = ref4.call(ref4)) === null || ref5 === void 0 ? void 0 : ref5.baz;
|
||||
foo === null || foo === void 0 ? void 0 : (ref6 = foo.bar) === null || ref6 === void 0 ? void 0 : ref6.call(ref6).baz;
|
||||
foo === null || foo === void 0 ? void 0 : (ref7 = foo.bar) === null || ref7 === void 0 ? void 0 : (ref8 = ref7.call(ref7)) === null || ref8 === void 0 ? void 0 : ref8.baz;
|
||||
"#
|
||||
(ref3 = foo.bar) === null || ref3 === void 0 ? void 0 : ref3.call(foo).baz;
|
||||
(ref4 = foo.bar) === null || ref4 === void 0 ? void 0 : (ref5 = ref4.call(foo)) === null || ref5 === void 0 ? void 0 : ref5.baz;
|
||||
foo === null || foo === void 0 ? void 0 : (ref6 = foo.bar) === null || ref6 === void 0 ? void 0 : ref6.call(foo).baz;
|
||||
foo === null || foo === void 0 ? void 0 : (ref7 = foo.bar) === null || ref7 === void 0 ? void 0 : (ref8 = ref7.call(foo)) === null || ref8 === void 0 ? void 0 : ref8.baz;"#
|
||||
);
|
||||
|
||||
// general_unary_exec
|
||||
@ -539,7 +538,7 @@ a === null || a === void 0
|
||||
? void 0
|
||||
: (ref1 = ref.c) === null || ref1 === void 0
|
||||
? void 0
|
||||
: ref1.call(ref1);"
|
||||
: ref1.call(ref);"
|
||||
);
|
||||
|
||||
test!(
|
||||
@ -568,3 +567,13 @@ test!(
|
||||
"var ref;
|
||||
(ref = test.a) === null || ref === void 0 ? void 0 : ref.b.c.d.e.f.g.h.i"
|
||||
);
|
||||
|
||||
// https://github.com/Brooooooklyn/swc-node/issues/62
|
||||
test!(
|
||||
syntax(),
|
||||
|_| tr(()),
|
||||
swc_node_issue_62,
|
||||
"a.focus?.()",
|
||||
"var ref;
|
||||
(ref = a.focus) === null || ref === void 0 ? void 0 : ref.call(a);"
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user