Skip to main content

swc_ecma_transforms_base/
fixer.rs

1use std::{hash::BuildHasherDefault, mem, ops::RangeFull};
2
3use indexmap::IndexMap;
4use rustc_hash::FxHasher;
5use swc_common::{comments::Comments, util::take::Take, Span, Spanned, DUMMY_SP};
6use swc_ecma_ast::*;
7use swc_ecma_utils::stack_size::maybe_grow_default;
8use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith};
9
10/// Fixes ast nodes before printing so semantics are preserved.
11///
12/// You don't have to bother to create appropriate parenthesis.
13/// The pass will insert parenthesis as needed. In other words, it's
14/// okay to store `a * (b + c)` as `Bin { a * Bin { b + c } }`.
15pub fn fixer(comments: Option<&dyn Comments>) -> impl '_ + Pass + VisitMut {
16    visit_mut_pass(Fixer {
17        comments,
18        ctx: Default::default(),
19        span_map: Default::default(),
20        in_for_stmt_head: Default::default(),
21        in_opt_chain: Default::default(),
22        remove_only: false,
23    })
24}
25
26pub fn paren_remover(comments: Option<&dyn Comments>) -> impl '_ + Pass + VisitMut {
27    visit_mut_pass(Fixer {
28        comments,
29        ctx: Default::default(),
30        span_map: Default::default(),
31        in_for_stmt_head: Default::default(),
32        in_opt_chain: Default::default(),
33        remove_only: true,
34    })
35}
36
37struct Fixer<'a> {
38    comments: Option<&'a dyn Comments>,
39    ctx: Context,
40    /// A hash map to preserve original span.
41    ///
42    /// Key is span of inner expression, and value is span of the paren
43    /// expression.
44    span_map: IndexMap<Span, Span, BuildHasherDefault<FxHasher>>,
45
46    in_for_stmt_head: bool,
47    in_opt_chain: bool,
48
49    remove_only: bool,
50}
51
52#[repr(u8)]
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
54enum Context {
55    #[default]
56    Default,
57
58    Callee {
59        is_new: bool,
60    },
61    /// Always treated as expr. (But number of comma-separated expression
62    /// matters)
63    ///
64    ///  - `foo((bar, x))` != `foo(bar, x)`
65    ///  - `var foo = (bar, x)` != `var foo = bar, x`
66    ///  - `[(foo, bar)]` != `[foo, bar]`
67    ForcedExpr,
68
69    /// Always treated as expr and comma does not matter.
70    FreeExpr,
71}
72
73impl Fixer<'_> {
74    fn wrap_callee(&mut self, e: &mut Expr) {
75        match e {
76            Expr::Lit(Lit::Num(..) | Lit::Str(..)) => (),
77            Expr::Cond(..)
78            | Expr::Class(..)
79            | Expr::Bin(..)
80            | Expr::Lit(..)
81            | Expr::Unary(..)
82            | Expr::Object(..)
83            | Expr::Await(..)
84            | Expr::Yield(..) => self.wrap(e),
85            _ => (),
86        }
87    }
88}
89
90impl VisitMut for Fixer<'_> {
91    noop_visit_mut_type!();
92
93    fn visit_mut_array_lit(&mut self, e: &mut ArrayLit) {
94        let ctx = mem::replace(&mut self.ctx, Context::ForcedExpr);
95        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
96        e.elems.visit_mut_with(self);
97        self.in_for_stmt_head = in_for_stmt_head;
98        self.ctx = ctx;
99    }
100
101    fn visit_mut_arrow_expr(&mut self, node: &mut ArrowExpr) {
102        let old = self.ctx;
103        self.ctx = Context::Default;
104        node.visit_mut_children_with(self);
105        match &mut *node.body {
106            BlockStmtOrExpr::Expr(e) if e.is_seq() => {
107                self.wrap(e);
108            }
109
110            BlockStmtOrExpr::Expr(e) if e.is_assign() => {
111                if let Expr::Assign(assign) = &**e {
112                    if let AssignTarget::Pat(..) = &assign.left {
113                        self.wrap(e);
114                    }
115                }
116            }
117
118            _ => {}
119        };
120        self.ctx = old;
121    }
122
123    fn visit_mut_assign_expr(&mut self, expr: &mut AssignExpr) {
124        expr.left.visit_mut_with(self);
125
126        let ctx = self.ctx;
127        self.ctx = Context::FreeExpr;
128        expr.right.visit_mut_with(self);
129        self.ctx = ctx;
130
131        fn rhs_need_paren(e: &Expr) -> bool {
132            match e {
133                Expr::Assign(e) => rhs_need_paren(&e.right),
134                Expr::Seq(..) => true,
135                _ => false,
136            }
137        }
138
139        if rhs_need_paren(&expr.right) {
140            self.wrap(&mut expr.right);
141        }
142
143        fn find_nearest_opt_chain_as_obj(e: &mut Expr) -> Option<&mut Expr> {
144            match e {
145                Expr::Member(MemberExpr { obj, .. }) => {
146                    if obj.is_opt_chain() {
147                        Some(obj)
148                    } else {
149                        find_nearest_opt_chain_as_obj(obj)
150                    }
151                }
152                _ => None,
153            }
154        }
155
156        let lhs_expr = match &mut expr.left {
157            AssignTarget::Simple(e) => Some(e),
158            AssignTarget::Pat(..) => None,
159            #[cfg(swc_ast_unknown)]
160            _ => None,
161        };
162
163        if let Some(e) = lhs_expr
164            .and_then(|e| e.as_mut_member())
165            .and_then(|me| find_nearest_opt_chain_as_obj(&mut me.obj))
166        {
167            self.wrap(e)
168        };
169    }
170
171    fn visit_mut_assign_pat(&mut self, node: &mut AssignPat) {
172        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
173        node.visit_mut_children_with(self);
174        self.in_for_stmt_head = in_for_stmt_head;
175
176        if let Expr::Seq(..) = &*node.right {
177            self.wrap(&mut node.right);
178        }
179    }
180
181    fn visit_mut_assign_pat_prop(&mut self, node: &mut AssignPatProp) {
182        node.key.visit_mut_children_with(self);
183
184        let old = self.ctx;
185        self.ctx = Context::ForcedExpr;
186        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
187        node.value.visit_mut_with(self);
188        self.in_for_stmt_head = in_for_stmt_head;
189        self.ctx = old;
190    }
191
192    fn visit_mut_assign_target(&mut self, n: &mut AssignTarget) {
193        n.visit_mut_children_with(self);
194
195        match n {
196            AssignTarget::Simple(a) => {
197                if let SimpleAssignTarget::Paren(s) = a {
198                    *n = AssignTarget::try_from(s.expr.take()).unwrap();
199                }
200            }
201            AssignTarget::Pat(b) => {
202                if let AssignTargetPat::Invalid(_) = b {
203                    *n = AssignTarget::Simple(SimpleAssignTarget::Invalid(Invalid {
204                        span: DUMMY_SP,
205                    }));
206                }
207            }
208            #[cfg(swc_ast_unknown)]
209            _ => (),
210        }
211    }
212
213    fn visit_mut_await_expr(&mut self, expr: &mut AwaitExpr) {
214        let old = self.ctx;
215        self.ctx = Context::ForcedExpr;
216        expr.arg.visit_mut_with(self);
217        self.ctx = old;
218
219        match &*expr.arg {
220            Expr::Cond(..)
221            | Expr::Assign(..)
222            | Expr::Bin(..)
223            | Expr::Yield(..)
224            | Expr::Arrow(..) => self.wrap(&mut expr.arg),
225            _ => {}
226        }
227    }
228
229    fn visit_mut_bin_expr(&mut self, expr: &mut BinExpr) {
230        expr.left.visit_mut_with(self);
231        let ctx = self.ctx;
232        self.ctx = Context::FreeExpr;
233        expr.right.visit_mut_with(self);
234        self.ctx = ctx;
235
236        match expr.op {
237            op!("||") | op!("&&") => match (&*expr.left, &*expr.right) {
238                (Expr::Update(..), Expr::Call(..)) => {
239                    return;
240                }
241
242                (Expr::Update(..), Expr::Assign(..)) => {
243                    self.wrap(&mut expr.right);
244                    return;
245                }
246
247                _ => {}
248            },
249
250            op!(">") | op!(">=") | op!("<") | op!("<=") => {
251                if let (Expr::Update(..) | Expr::Lit(..), Expr::Update(..) | Expr::Lit(..)) =
252                    (&*expr.left, &*expr.right)
253                {
254                    return;
255                }
256            }
257
258            op!("**") => match &*expr.left {
259                Expr::Unary(..) => {
260                    self.wrap(&mut expr.left);
261                }
262                Expr::Lit(Lit::Num(v)) if v.value.is_sign_negative() => {
263                    self.wrap(&mut expr.left);
264                }
265                _ => {}
266            },
267
268            _ => {}
269        }
270
271        match &mut *expr.right {
272            Expr::Assign(..)
273            | Expr::Seq(..)
274            | Expr::Yield(..)
275            | Expr::Cond(..)
276            | Expr::Arrow(..) => {
277                self.wrap(&mut expr.right);
278            }
279            Expr::Bin(BinExpr { op: op_of_rhs, .. }) => {
280                if *op_of_rhs == expr.op {
281                    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#precedence_and_associativity
282                    // `**` is the only right associative operator in js
283                    if !(expr.op.may_short_circuit() || expr.op == op!("**")) {
284                        self.wrap(&mut expr.right);
285                    }
286                } else if op_of_rhs.precedence() <= expr.op.precedence()
287                    || (*op_of_rhs == op!("&&") && expr.op == op!("??"))
288                {
289                    self.wrap(&mut expr.right);
290                }
291            }
292            _ => {}
293        };
294
295        match &mut *expr.left {
296            Expr::Bin(BinExpr { op: op!("??"), .. }) if expr.op != op!("??") => {
297                self.wrap(&mut expr.left);
298            }
299
300            // While simplifying, (1 + x) * Nan becomes `1 + x * Nan`.
301            // But it should be `(1 + x) * Nan`
302            Expr::Bin(BinExpr { op: op_of_lhs, .. }) => {
303                if op_of_lhs.precedence() < expr.op.precedence()
304                    || (op_of_lhs.precedence() == expr.op.precedence() && expr.op == op!("**"))
305                {
306                    self.wrap(&mut expr.left);
307                }
308            }
309
310            Expr::Unary(UnaryExpr {
311                op: op!("void"), ..
312            }) if expr.op == op!("==")
313                || expr.op == op!("===")
314                || expr.op == op!("!=")
315                || expr.op == op!("!==") => {}
316
317            Expr::Seq(..)
318            | Expr::Unary(UnaryExpr {
319                op: op!("delete"), ..
320            })
321            | Expr::Unary(UnaryExpr {
322                op: op!("void"), ..
323            })
324            | Expr::Yield(..)
325            | Expr::Cond(..)
326            | Expr::Assign(..)
327            | Expr::Arrow(..) => {
328                self.wrap(&mut expr.left);
329            }
330            Expr::Object(..)
331                if expr.op == op!("instanceof")
332                    || expr.op == op!("==")
333                    || expr.op == op!("===")
334                    || expr.op == op!("!=")
335                    || expr.op == op!("!==") =>
336            {
337                self.wrap(&mut expr.left)
338            }
339            _ => {}
340        }
341
342        if let op!("??") = expr.op {
343            match &*expr.left {
344                Expr::Bin(BinExpr { op, .. }) if *op != op!("??") => {
345                    self.wrap(&mut expr.left);
346                }
347                _ => (),
348            }
349        }
350    }
351
352    fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) {
353        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
354        n.visit_mut_children_with(self);
355        self.in_for_stmt_head = in_for_stmt_head;
356    }
357
358    fn visit_mut_block_stmt_or_expr(&mut self, body: &mut BlockStmtOrExpr) {
359        body.visit_mut_children_with(self);
360
361        match body {
362            BlockStmtOrExpr::Expr(expr) if expr.is_object() => {
363                self.wrap(expr);
364            }
365
366            _ => {}
367        }
368    }
369
370    fn visit_mut_call_expr(&mut self, node: &mut CallExpr) {
371        let ctx = mem::replace(&mut self.ctx, Context::Callee { is_new: false });
372
373        node.callee.visit_mut_with(self);
374        if let Callee::Expr(e) = &mut node.callee {
375            match &**e {
376                Expr::OptChain(_) if !self.in_opt_chain => self.wrap(e),
377                _ => self.wrap_callee(e),
378            }
379        }
380
381        self.ctx = Context::ForcedExpr;
382
383        node.args.visit_mut_with(self);
384
385        self.ctx = ctx;
386    }
387
388    fn visit_mut_class(&mut self, node: &mut Class) {
389        let ctx = mem::replace(&mut self.ctx, Context::Default);
390
391        node.super_class.visit_mut_with(self);
392
393        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
394        node.body.visit_mut_with(self);
395        self.in_for_stmt_head = in_for_stmt_head;
396
397        match &mut node.super_class {
398            Some(e)
399                if e.is_seq()
400                    || e.is_await_expr()
401                    || e.is_yield_expr()
402                    || e.is_bin()
403                    || e.is_assign()
404                    || e.is_cond()
405                    || e.is_unary() =>
406            {
407                self.wrap(e)
408            }
409            _ => {}
410        };
411        self.ctx = ctx;
412
413        node.body.retain(|m| !matches!(m, ClassMember::Empty(..)));
414    }
415
416    fn visit_mut_computed_prop_name(&mut self, name: &mut ComputedPropName) {
417        let ctx = self.ctx;
418        self.ctx = Context::FreeExpr;
419        name.visit_mut_children_with(self);
420        self.ctx = ctx;
421    }
422
423    fn visit_mut_cond_expr(&mut self, expr: &mut CondExpr) {
424        expr.test.visit_mut_with(self);
425
426        let ctx = self.ctx;
427        self.ctx = Context::FreeExpr;
428        expr.cons.visit_mut_with(self);
429        expr.alt.visit_mut_with(self);
430        self.ctx = ctx;
431    }
432
433    fn visit_mut_export_default_expr(&mut self, node: &mut ExportDefaultExpr) {
434        let old = self.ctx;
435        self.ctx = Context::Default;
436        node.visit_mut_children_with(self);
437        match &mut *node.expr {
438            Expr::Arrow(..) | Expr::Seq(..) => self.wrap(&mut node.expr),
439            Expr::Fn(FnExpr { ident: Some(_), .. })
440            | Expr::Class(ClassExpr { ident: Some(_), .. }) => self.wrap(&mut node.expr),
441            _ => {}
442        };
443        self.ctx = old;
444    }
445
446    fn visit_mut_expr(&mut self, e: &mut Expr) {
447        let ctx = self.ctx;
448
449        if ctx == Context::Default {
450            match e {
451                // might have a child expr in start of stmt
452                Expr::OptChain(_)
453                | Expr::Member(_)
454                | Expr::Bin(_)
455                | Expr::Assign(_)
456                | Expr::Seq(_)
457                | Expr::Cond(_)
458                | Expr::TaggedTpl(_)
459                | Expr::Update(UpdateExpr { prefix: false, .. }) => {}
460                _ => self.ctx = Context::FreeExpr,
461            }
462        }
463        self.unwrap_expr(e);
464
465        maybe_grow_default(|| e.visit_mut_children_with(self));
466
467        self.ctx = ctx;
468        self.wrap_with_paren_if_required(e)
469    }
470
471    fn visit_mut_expr_or_spread(&mut self, e: &mut ExprOrSpread) {
472        e.visit_mut_children_with(self);
473
474        if e.spread.is_none() {
475            if let Expr::Yield(..) = *e.expr {
476                self.wrap(&mut e.expr);
477            }
478        }
479    }
480
481    fn visit_mut_expr_stmt(&mut self, s: &mut ExprStmt) {
482        let old = self.ctx;
483        self.ctx = Context::Default;
484        s.expr.visit_mut_with(self);
485        self.ctx = old;
486
487        self.handle_expr_stmt(&mut s.expr);
488    }
489
490    fn visit_mut_for_head(&mut self, n: &mut ForHead) {
491        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, true);
492        n.visit_mut_children_with(self);
493        self.in_for_stmt_head = in_for_stmt_head;
494    }
495
496    fn visit_mut_for_of_stmt(&mut self, s: &mut ForOfStmt) {
497        s.visit_mut_children_with(self);
498
499        if !s.is_await {
500            match &s.left {
501                ForHead::Pat(p)
502                    if match &**p {
503                        Pat::Ident(BindingIdent {
504                            id: Ident { sym, .. },
505                            ..
506                        }) => &**sym == "async",
507                        _ => false,
508                    } =>
509                {
510                    let expr: Pat = p.clone().expect_ident().into();
511                    s.left = ForHead::Pat(expr.into());
512                }
513                _ => (),
514            }
515
516            if let ForHead::Pat(e) = &mut s.left {
517                if let Pat::Expr(expr) = &mut **e {
518                    if expr.is_ident_ref_to("async") {
519                        self.wrap(&mut *expr);
520                    }
521                }
522            }
523        }
524
525        if let Expr::Seq(..) | Expr::Await(..) = &*s.right {
526            self.wrap(&mut s.right)
527        }
528    }
529
530    fn visit_mut_for_stmt(&mut self, n: &mut ForStmt) {
531        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, true);
532        n.init.visit_mut_with(self);
533        self.in_for_stmt_head = in_for_stmt_head;
534
535        n.test.visit_mut_with(self);
536        n.update.visit_mut_with(self);
537        n.body.visit_mut_with(self);
538    }
539
540    fn visit_mut_if_stmt(&mut self, node: &mut IfStmt) {
541        node.visit_mut_children_with(self);
542
543        if will_eat_else_token(&node.cons) {
544            node.cons = Box::new(
545                BlockStmt {
546                    span: node.cons.span(),
547                    stmts: vec![*node.cons.take()],
548                    ..Default::default()
549                }
550                .into(),
551            );
552        }
553    }
554
555    fn visit_mut_key_value_pat_prop(&mut self, node: &mut KeyValuePatProp) {
556        let old = self.ctx;
557        self.ctx = Context::ForcedExpr;
558        node.key.visit_mut_with(self);
559        self.ctx = old;
560
561        node.value.visit_mut_with(self);
562    }
563
564    fn visit_mut_key_value_prop(&mut self, prop: &mut KeyValueProp) {
565        prop.visit_mut_children_with(self);
566
567        if let Expr::Seq(..) = *prop.value {
568            self.wrap(&mut prop.value)
569        }
570    }
571
572    fn visit_mut_member_expr(&mut self, n: &mut MemberExpr) {
573        n.visit_mut_children_with(self);
574
575        match *n.obj {
576            Expr::Object(..) if self.ctx == Context::ForcedExpr => {}
577            Expr::Fn(..)
578            | Expr::Cond(..)
579            | Expr::Unary(..)
580            | Expr::Seq(..)
581            | Expr::Update(..)
582            | Expr::Bin(..)
583            | Expr::Object(..)
584            | Expr::Assign(..)
585            | Expr::Arrow(..)
586            | Expr::Class(..)
587            | Expr::Yield(..)
588            | Expr::Await(..)
589            | Expr::New(NewExpr { args: None, .. }) => {
590                self.wrap(&mut n.obj);
591            }
592            Expr::Call(..) if self.ctx == Context::Callee { is_new: true } => {
593                self.wrap(&mut n.obj);
594            }
595            Expr::OptChain(..) if !self.in_opt_chain => {
596                self.wrap(&mut n.obj);
597            }
598            _ => {}
599        }
600    }
601
602    fn visit_mut_module(&mut self, n: &mut Module) {
603        debug_assert!(self.span_map.is_empty());
604        self.span_map.clear();
605
606        n.visit_mut_children_with(self);
607        if let Some(c) = self.comments {
608            for (to, from) in self.span_map.drain(RangeFull).rev() {
609                c.move_leading(from.lo, to.lo);
610                c.move_trailing(from.hi, to.hi);
611            }
612        }
613    }
614
615    fn visit_mut_new_expr(&mut self, node: &mut NewExpr) {
616        let ctx = mem::replace(&mut self.ctx, Context::ForcedExpr);
617
618        node.args.visit_mut_with(self);
619
620        self.ctx = Context::Callee { is_new: true };
621        node.callee.visit_mut_with(self);
622        match *node.callee {
623            Expr::Call(..)
624            | Expr::Await(..)
625            | Expr::Yield(..)
626            | Expr::Bin(..)
627            | Expr::Assign(..)
628            | Expr::Seq(..)
629            | Expr::Unary(..)
630            | Expr::Lit(..) => self.wrap(&mut node.callee),
631            _ => {}
632        }
633        self.ctx = ctx;
634    }
635
636    fn visit_mut_opt_call(&mut self, node: &mut OptCall) {
637        let ctx = mem::replace(&mut self.ctx, Context::Callee { is_new: false });
638        let in_opt_chain = mem::replace(&mut self.in_opt_chain, true);
639
640        node.callee.visit_mut_with(self);
641        self.wrap_callee(&mut node.callee);
642
643        self.in_opt_chain = in_opt_chain;
644
645        self.ctx = Context::ForcedExpr;
646        node.args.visit_mut_with(self);
647
648        self.ctx = ctx;
649    }
650
651    fn visit_mut_opt_chain_base(&mut self, n: &mut OptChainBase) {
652        if !n.is_member() {
653            n.visit_mut_children_with(self);
654            return;
655        }
656
657        let in_opt_chain = mem::replace(&mut self.in_opt_chain, true);
658        n.visit_mut_children_with(self);
659        self.in_opt_chain = in_opt_chain;
660    }
661
662    fn visit_mut_param(&mut self, node: &mut Param) {
663        let old = self.ctx;
664        self.ctx = Context::ForcedExpr;
665        node.visit_mut_children_with(self);
666        self.ctx = old;
667    }
668
669    fn visit_mut_prop_name(&mut self, name: &mut PropName) {
670        name.visit_mut_children_with(self);
671
672        match name {
673            PropName::Computed(c) if c.expr.is_seq() => {
674                self.wrap(&mut c.expr);
675            }
676            _ => {}
677        }
678    }
679
680    fn visit_mut_script(&mut self, n: &mut Script) {
681        debug_assert!(self.span_map.is_empty());
682        self.span_map.clear();
683
684        n.visit_mut_children_with(self);
685        if let Some(c) = self.comments {
686            for (to, from) in self.span_map.drain(RangeFull).rev() {
687                c.move_leading(from.lo, to.lo);
688                c.move_trailing(from.hi, to.hi);
689            }
690        }
691    }
692
693    fn visit_mut_seq_expr(&mut self, seq: &mut SeqExpr) {
694        if seq.exprs.len() > 1 {
695            seq.exprs[0].visit_mut_with(self);
696
697            let ctx = self.ctx;
698            self.ctx = Context::FreeExpr;
699            for expr in seq.exprs.iter_mut().skip(1) {
700                expr.visit_mut_with(self)
701            }
702            self.ctx = ctx;
703        } else {
704            seq.exprs.visit_mut_children_with(self)
705        }
706    }
707
708    fn visit_mut_spread_element(&mut self, e: &mut SpreadElement) {
709        let old = self.ctx;
710        self.ctx = Context::ForcedExpr;
711        e.visit_mut_children_with(self);
712        self.ctx = old;
713    }
714
715    fn visit_mut_stmt(&mut self, s: &mut Stmt) {
716        let old = self.ctx;
717        // only ExprStmt would have unparented expr,
718        // which would be handled in its own visit function
719        self.ctx = Context::FreeExpr;
720        s.visit_mut_children_with(self);
721        self.ctx = old;
722    }
723
724    fn visit_mut_tagged_tpl(&mut self, e: &mut TaggedTpl) {
725        e.visit_mut_children_with(self);
726
727        match &*e.tag {
728            Expr::Object(..) if self.ctx == Context::Default => {
729                self.wrap(&mut e.tag);
730            }
731            Expr::OptChain(..)
732            | Expr::Arrow(..)
733            | Expr::Cond(..)
734            | Expr::Bin(..)
735            | Expr::Seq(..)
736            | Expr::Fn(..)
737            | Expr::Assign(..)
738            | Expr::Unary(..) => {
739                self.wrap(&mut e.tag);
740            }
741            _ => {}
742        }
743    }
744
745    fn visit_mut_unary_expr(&mut self, n: &mut UnaryExpr) {
746        let old = self.ctx;
747        self.ctx = Context::FreeExpr;
748        n.visit_mut_children_with(self);
749        self.ctx = old;
750
751        match &*n.arg {
752            Expr::Bin(BinExpr {
753                op: op!("/") | op!("*"),
754                left,
755                right,
756                ..
757            }) if n.op == op!(unary, "-")
758                && match (&**left, &**right) {
759                    (Expr::Lit(Lit::Num(l)), Expr::Lit(Lit::Num(..))) => {
760                        !l.value.is_sign_negative()
761                    }
762                    _ => false,
763                } => {}
764
765            Expr::Assign(..)
766            | Expr::Bin(..)
767            | Expr::Seq(..)
768            | Expr::Cond(..)
769            | Expr::Arrow(..)
770            | Expr::Yield(..) => self.wrap(&mut n.arg),
771
772            _ => {}
773        }
774    }
775
776    fn visit_mut_var_declarator(&mut self, node: &mut VarDeclarator) {
777        node.name.visit_mut_children_with(self);
778
779        let old = self.ctx;
780        self.ctx = Context::ForcedExpr;
781        node.init.visit_mut_with(self);
782        self.ctx = old;
783    }
784
785    fn visit_mut_yield_expr(&mut self, expr: &mut YieldExpr) {
786        let old = self.ctx;
787        self.ctx = Context::ForcedExpr;
788        expr.arg.visit_mut_with(self);
789        self.ctx = old;
790    }
791
792    fn visit_mut_object_lit(&mut self, n: &mut ObjectLit) {
793        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
794        n.visit_mut_children_with(self);
795        self.in_for_stmt_head = in_for_stmt_head;
796    }
797
798    fn visit_mut_params(&mut self, n: &mut Vec<Param>) {
799        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
800        n.visit_mut_children_with(self);
801        self.in_for_stmt_head = in_for_stmt_head;
802    }
803
804    // only used in ArrowExpr
805    fn visit_mut_pats(&mut self, n: &mut Vec<Pat>) {
806        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
807        n.visit_mut_children_with(self);
808        self.in_for_stmt_head = in_for_stmt_head;
809    }
810
811    fn visit_mut_expr_or_spreads(&mut self, n: &mut Vec<ExprOrSpread>) {
812        let in_for_stmt_head = mem::replace(&mut self.in_for_stmt_head, false);
813        n.visit_mut_children_with(self);
814        self.in_for_stmt_head = in_for_stmt_head;
815    }
816}
817
818impl Fixer<'_> {
819    fn wrap_with_paren_if_required(&mut self, e: &mut Expr) {
820        let mut has_padding_value = false;
821        match e {
822            Expr::Bin(BinExpr { op: op!("in"), .. }) if self.in_for_stmt_head => {
823                // TODO:
824                // if the in expression is in a parentheses, we should not wrap it with a
825                // parentheses again. But the parentheses is added later,
826                // so we don't have enough information to detect it at this moment.
827                // Example:
828                // for(var a = 1 + (2 || b in c) in {});
829                //                 |~~~~~~~~~~~|
830                // this parentheses is removed by unwrap_expr and added again later
831                self.wrap(e);
832            }
833
834            Expr::Bin(BinExpr { left, .. })
835                if self.ctx == Context::Default
836                    && matches!(&**left, Expr::Object(..) | Expr::Fn(..) | Expr::Class(..)) =>
837            {
838                self.wrap(left);
839            }
840
841            // Flatten seq expr
842            Expr::Seq(SeqExpr { span, exprs }) => {
843                let len = exprs
844                    .iter()
845                    .map(|expr| match **expr {
846                        Expr::Paren(ParenExpr { ref expr, .. }) => {
847                            if let Expr::Seq(SeqExpr { exprs, .. }) = expr.as_ref() {
848                                exprs.len()
849                            } else {
850                                1
851                            }
852                        }
853                        Expr::Seq(SeqExpr { ref exprs, .. }) => exprs.len(),
854                        _ => 1,
855                    })
856                    .sum();
857
858                let exprs_len = exprs.len();
859                // don't has child seq
860                let mut exprs = if len == exprs_len {
861                    let mut exprs = exprs
862                        .iter_mut()
863                        .enumerate()
864                        .filter_map(|(i, e)| {
865                            let is_last = i + 1 == exprs_len;
866                            if is_last {
867                                Some(e.take())
868                            } else {
869                                ignore_return_value(e.take(), &mut has_padding_value)
870                            }
871                        })
872                        .collect::<Vec<_>>();
873                    if exprs.len() == 1 {
874                        *e = *exprs.pop().unwrap();
875                        return;
876                    }
877                    ignore_padding_value(exprs)
878                } else {
879                    let mut buf = Vec::with_capacity(len);
880                    for (i, expr) in exprs.iter_mut().enumerate() {
881                        let is_last = i + 1 == exprs_len;
882
883                        match &mut **expr {
884                            Expr::Seq(SeqExpr { exprs, .. }) => {
885                                let exprs = exprs.take();
886                                if !is_last {
887                                    buf.extend(exprs.into_iter().filter_map(|expr| {
888                                        ignore_return_value(expr, &mut has_padding_value)
889                                    }));
890                                } else {
891                                    let exprs_len = exprs.len();
892                                    for (i, expr) in exprs.into_iter().enumerate() {
893                                        let is_last = i + 1 == exprs_len;
894                                        if is_last {
895                                            buf.push(expr);
896                                        } else {
897                                            buf.extend(ignore_return_value(
898                                                expr,
899                                                &mut has_padding_value,
900                                            ));
901                                        }
902                                    }
903                                }
904                            }
905                            _ => {
906                                if is_last {
907                                    buf.push(expr.take());
908                                } else {
909                                    buf.extend(ignore_return_value(
910                                        expr.take(),
911                                        &mut has_padding_value,
912                                    ));
913                                }
914                            }
915                        }
916                    }
917
918                    if buf.len() == 1 {
919                        *e = *buf.pop().unwrap();
920                        return;
921                    }
922
923                    ignore_padding_value(buf)
924                };
925
926                if self.ctx == Context::Default {
927                    if let Some(expr) = exprs.first_mut() {
928                        match &mut **expr {
929                            Expr::Call(CallExpr {
930                                callee: Callee::Expr(callee_expr),
931                                ..
932                            }) if callee_expr.is_fn_expr() => self.wrap(callee_expr),
933                            // Also handle when the call is inside a binary expression
934                            Expr::Bin(BinExpr { left, .. }) => {
935                                if let Expr::Call(CallExpr {
936                                    callee: Callee::Expr(callee_expr),
937                                    ..
938                                }) = &mut **left
939                                {
940                                    if callee_expr.is_fn_expr() {
941                                        self.wrap(callee_expr)
942                                    }
943                                }
944                            }
945                            _ => (),
946                        }
947                    }
948                }
949
950                let mut expr = SeqExpr { span: *span, exprs }.into();
951
952                if let Context::ForcedExpr = self.ctx {
953                    self.wrap(&mut expr);
954                };
955
956                *e = expr;
957            }
958
959            Expr::Cond(expr) => {
960                match &mut *expr.test {
961                    Expr::Seq(..)
962                    | Expr::Assign(..)
963                    | Expr::Cond(..)
964                    | Expr::Arrow(..)
965                    | Expr::Yield(..) => self.wrap(&mut expr.test),
966
967                    Expr::Object(..) | Expr::Fn(..) | Expr::Class(..) => {
968                        if self.ctx == Context::Default {
969                            self.wrap(&mut expr.test)
970                        }
971                    }
972                    _ => {}
973                };
974
975                if let Expr::Seq(..) = *expr.cons {
976                    self.wrap(&mut expr.cons)
977                };
978
979                if let Expr::Seq(..) = *expr.alt {
980                    self.wrap(&mut expr.alt)
981                };
982
983                if let Context::Callee { is_new: true } = self.ctx {
984                    self.wrap(e)
985                }
986            }
987
988            Expr::Call(CallExpr {
989                callee: Callee::Expr(callee),
990                ..
991            }) if callee.is_seq()
992                || callee.is_arrow()
993                || callee.is_await_expr()
994                || callee.is_assign() =>
995            {
996                self.wrap(callee);
997            }
998            Expr::OptChain(OptChainExpr { base, .. }) => match &mut **base {
999                OptChainBase::Call(OptCall { callee, .. })
1000                    if callee.is_seq()
1001                        || callee.is_arrow()
1002                        || callee.is_await_expr()
1003                        || callee.is_assign() =>
1004                {
1005                    self.wrap(callee);
1006                }
1007
1008                OptChainBase::Call(OptCall { callee, .. }) if callee.is_fn_expr() => match self.ctx
1009                {
1010                    Context::ForcedExpr | Context::FreeExpr => {}
1011
1012                    Context::Callee { is_new: true } => self.wrap(e),
1013
1014                    _ => self.wrap(callee),
1015                },
1016
1017                _ => {}
1018            },
1019
1020            // Function expression cannot start with `function`
1021            Expr::Call(CallExpr {
1022                callee: Callee::Expr(callee),
1023                ..
1024            }) if callee.is_fn_expr() => match self.ctx {
1025                Context::ForcedExpr | Context::FreeExpr => {}
1026
1027                Context::Callee { is_new: true } => self.wrap(e),
1028
1029                _ => self.wrap(callee),
1030            },
1031
1032            Expr::Member(MemberExpr { obj, .. }) => match &**obj {
1033                Expr::Lit(Lit::Num(num)) if num.value.signum() == -1. => {
1034                    self.wrap(obj);
1035                }
1036                _ => {}
1037            },
1038            _ => {}
1039        }
1040    }
1041
1042    /// Wrap with a paren.
1043    fn wrap(&mut self, e: &mut Expr) {
1044        if self.remove_only {
1045            return;
1046        }
1047
1048        let mut span = e.span();
1049
1050        if let Some(new_span) = self.span_map.shift_remove(&span) {
1051            span = new_span;
1052        }
1053
1054        if span.is_pure() {
1055            span = DUMMY_SP;
1056        }
1057
1058        let expr = Box::new(e.take());
1059        *e = ParenExpr { expr, span }.into();
1060    }
1061
1062    /// Removes paren
1063    fn unwrap_expr(&mut self, e: &mut Expr) {
1064        loop {
1065            match e {
1066                Expr::Seq(SeqExpr { exprs, .. }) if exprs.len() == 1 => {
1067                    *e = *exprs[0].take();
1068                }
1069
1070                Expr::Paren(ParenExpr {
1071                    span: paren_span,
1072                    expr,
1073                    ..
1074                }) => {
1075                    let expr_span = expr.span();
1076                    let paren_span = *paren_span;
1077                    *e = *expr.take();
1078
1079                    self.span_map.insert(expr_span, paren_span);
1080                }
1081
1082                _ => return,
1083            }
1084        }
1085    }
1086
1087    fn handle_expr_stmt(&mut self, expr: &mut Expr) {
1088        match expr {
1089            // It's important for arrow pass to work properly.
1090            Expr::Object(..) | Expr::Class(..) | Expr::Fn(..) => self.wrap(expr),
1091
1092            // ({ a } = foo)
1093            Expr::Assign(AssignExpr {
1094                left: AssignTarget::Pat(left),
1095                ..
1096            }) if left.is_object() => self.wrap(expr),
1097
1098            Expr::Seq(SeqExpr { exprs, .. }) => {
1099                debug_assert!(
1100                    exprs.len() != 1,
1101                    "SeqExpr should be unwrapped if exprs.len() == 1, but length is 1"
1102                );
1103
1104                let len = exprs.len();
1105                exprs.iter_mut().enumerate().for_each(|(i, expr)| {
1106                    let is_last = len == i + 1;
1107
1108                    if !is_last {
1109                        self.handle_expr_stmt(expr);
1110                    }
1111                });
1112            }
1113
1114            _ => {}
1115        }
1116    }
1117}
1118
1119fn ignore_return_value(expr: Box<Expr>, has_padding_value: &mut bool) -> Option<Box<Expr>> {
1120    match *expr {
1121        Expr::Fn(..) | Expr::Arrow(..) | Expr::Lit(..) => {
1122            if *has_padding_value {
1123                None
1124            } else {
1125                *has_padding_value = true;
1126                Some(expr)
1127            }
1128        }
1129        Expr::Seq(SeqExpr { span, exprs }) => {
1130            let len = exprs.len();
1131            let mut exprs: Vec<_> = exprs
1132                .into_iter()
1133                .enumerate()
1134                .filter_map(|(i, expr)| {
1135                    if i + 1 == len {
1136                        Some(expr)
1137                    } else {
1138                        ignore_return_value(expr, has_padding_value)
1139                    }
1140                })
1141                .collect();
1142
1143            match exprs.len() {
1144                0 | 1 => exprs.pop(),
1145                _ => Some(SeqExpr { span, exprs }.into()),
1146            }
1147        }
1148        Expr::Unary(UnaryExpr {
1149            op: op!("void"),
1150            arg,
1151            ..
1152        }) => ignore_return_value(arg, has_padding_value),
1153        _ => Some(expr),
1154    }
1155}
1156
1157// at least 3 element in seq, which means we can safely
1158// remove that padding, if not at last position
1159#[allow(clippy::vec_box)]
1160fn ignore_padding_value(exprs: Vec<Box<Expr>>) -> Vec<Box<Expr>> {
1161    let len = exprs.len();
1162
1163    if len > 2 {
1164        exprs
1165            .into_iter()
1166            .enumerate()
1167            .filter_map(|(i, e)| match e.as_ref() {
1168                Expr::Fn(..) | Expr::Arrow(..) | Expr::Lit(..) if i + 1 != len => None,
1169                _ => Some(e),
1170            })
1171            .collect()
1172    } else {
1173        exprs
1174    }
1175}
1176
1177fn will_eat_else_token(s: &Stmt) -> bool {
1178    match s {
1179        Stmt::If(s) => match &s.alt {
1180            Some(alt) => will_eat_else_token(alt),
1181            None => true,
1182        },
1183        // Ends with `}`.
1184        Stmt::Block(..) => false,
1185
1186        Stmt::Labeled(s) => will_eat_else_token(&s.body),
1187
1188        Stmt::While(s) => will_eat_else_token(&s.body),
1189
1190        Stmt::For(s) => will_eat_else_token(&s.body),
1191
1192        Stmt::ForIn(s) => will_eat_else_token(&s.body),
1193
1194        Stmt::ForOf(s) => will_eat_else_token(&s.body),
1195
1196        _ => false,
1197    }
1198}
1199
1200#[cfg(test)]
1201mod tests {
1202    use swc_ecma_ast::noop_pass;
1203
1204    fn run_test(from: &str, to: &str) {
1205        crate::tests::test_transform(
1206            Default::default(),
1207            // test_transform has alreay included fixer
1208            |_| noop_pass(),
1209            from,
1210            to,
1211            true,
1212            Default::default,
1213        );
1214    }
1215
1216    macro_rules! test_fixer {
1217        ($name:ident, $from:literal, $to:literal) => {
1218            #[test]
1219            fn $name() {
1220                run_test($from, $to);
1221            }
1222        };
1223    }
1224
1225    macro_rules! identical {
1226        ($name:ident, $src:literal) => {
1227            test_fixer!($name, $src, $src);
1228        };
1229    }
1230
1231    identical!(fn_expr_position, r#"foo(function(){}())"#);
1232
1233    identical!(fn_decl, r#"function foo(){}"#);
1234
1235    identical!(iife, r#"(function(){})()"#);
1236
1237    identical!(paren_seq_arg, "foo(( _temp = _this = init(), _temp));");
1238
1239    identical!(
1240        regression_01,
1241        "_set(_get_prototype_of(Obj.prototype), _ref = proper.prop, (_superRef = \
1242         +_get(_get_prototype_of(Obj.prototype), _ref, this)) + 1, this, true), _superRef;"
1243    );
1244
1245    identical!(
1246        regression_02,
1247        "var obj = (_obj = {}, _define_property(_obj, 'first', 'first'), _define_property(_obj, \
1248         'second', 'second'), _obj);"
1249    );
1250
1251    identical!(
1252        regression_03,
1253        "_iteratorNormalCompletion = (_step = _iterator.next()).done"
1254    );
1255
1256    identical!(
1257        regression_04,
1258        "var _tmp;
1259const _ref = {}, { c =( _tmp = {}, d = _extends({}, _tmp), _tmp)  } = _ref;"
1260    );
1261
1262    identical!(
1263        regression_05,
1264        "for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step \
1265         = _iterator.next()).done); _iteratorNormalCompletion = true) {
1266    i = _step.value;
1267}"
1268    );
1269
1270    identical!(
1271        regression_06,
1272        "
1273        var _tmp;
1274        const { [( _tmp = {}, d = _extends({}, _tmp), _tmp)]: c  } = _ref;
1275        "
1276    );
1277
1278    identical!(
1279        regression_07,
1280        "( _temp = super(), _initialize(this), _temp).method();"
1281    );
1282
1283    identical!(regression_08, "exports.bar = exports.default = void 0;");
1284
1285    identical!(regression_09, "({x} = { x: 1 });");
1286
1287    identical!(regression_10, "({x} = { x: 1 }), exports.x = x;");
1288
1289    identical!(regression_11, "(void 0).foo();");
1290
1291    identical!(regression_12, "(function(){})()");
1292
1293    identical!(regression_13, "a || (a = 1);");
1294
1295    identical!(issue_192, "a === true && (a = true)");
1296
1297    identical!(issue_199, "(i - 1).toString()");
1298
1299    identical!(
1300        issue_201_01,
1301        "outer = {
1302    inner: (_obj = {}, _define_property(_obj, ns.EXPORT1, true), _define_property(_obj, \
1303         ns.EXPORT2, true), _obj)
1304};"
1305    );
1306
1307    identical!(issue_207, "a => ({x: 'xxx', y: {a}});");
1308
1309    test_fixer!(
1310        fixer_01,
1311        "var a, b, c, d, e, f;
1312((a, b), (c())) + ((d, e), (f()));
1313",
1314        "var a, b, c, d, e, f;
1315(a, b, c()) + (d, e, f())"
1316    );
1317
1318    test_fixer!(fixer_02, "(b, c), d;", "b, c, d;");
1319
1320    test_fixer!(fixer_03, "((a, b), (c && d)) && e;", "(a, b, c && d) && e;");
1321
1322    test_fixer!(fixer_04, "for ((a, b), c;;) ;", "for(a, b, c;;);");
1323
1324    test_fixer!(
1325        fixer_05,
1326        "var a, b, c = (1), d, e, f = (2);
1327((a, b), c) + ((d, e), f);",
1328        "var a, b, c = 1, d, e, f = 2;
1329(a, b, c) + (d, e, f);"
1330    );
1331
1332    test_fixer!(
1333        fixer_06,
1334        "var a, b, c, d;
1335a = ((b, c), d);",
1336        "var a, b, c, d;
1337a = (b, c, d);"
1338    );
1339
1340    test_fixer!(
1341        fixer_07,
1342        "a => ((b, c) => ((a, b), c));",
1343        "(a)=>(b, c)=>(a, b, c);"
1344    );
1345
1346    test_fixer!(fixer_08, "typeof (((1), a), (2));", "typeof (a, 2)");
1347
1348    test_fixer!(
1349        fixer_09,
1350        "(((a, b), c), d) ? e : f;",
1351        "(a, b, c, d) ? e : f;"
1352    );
1353
1354    test_fixer!(
1355        fixer_10,
1356        "
1357function a() {
1358  return (((void (1)), (void (2))), a), (void (3));
1359}
1360",
1361        "
1362function a() {
1363  return a, void 3;
1364}
1365"
1366    );
1367
1368    test_fixer!(fixer_11, "c && ((((2), (3)), d), b);", "c && (d, b)");
1369
1370    test_fixer!(fixer_12, "(((a, b), c), d) + e;", "(a, b, c, d) + e;");
1371
1372    test_fixer!(fixer_13, "delete (((1), a), (2));", "delete (a, 2)");
1373
1374    test_fixer!(fixer_14, "(1, 2, a)", "1, a");
1375
1376    identical!(issue_231, "'' + (truthy && '?') + truthy;");
1377
1378    identical!(issue_252, "!!(a && b);");
1379
1380    identical!(issue_255, "b < 0 ? (t = b, b = 1) : (t = -b, b = 0);");
1381
1382    identical!(
1383        issue_266_1,
1384        "'Q' + +x1 + ',' + +y1 + ',' + (this._x1 = +x) + ',' + (this._y1 = +y);"
1385    );
1386
1387    test_fixer!(
1388        issue_266_2,
1389        "'Q' + (+x1) + ',' + (+y1) + ',' + (this._x1 = +x) + ',' + (this._y1 = +y);",
1390        "'Q' + +x1 + ',' + +y1 + ',' + (this._x1 = +x) + ',' + (this._y1 = +y);"
1391    );
1392
1393    identical!(
1394        issue_280,
1395        "e.hasOwnProperty(a) && (t = e[a] ? this[a] = t(n) : 'target' === a ? this.target = r : \
1396         this[a] = n[a]);"
1397    );
1398
1399    identical!(
1400        issue_282,
1401        "!(A = [], B = (function () { return classNames; }).apply(exports, A), B !== undefined && \
1402         (module.exports = B));"
1403    );
1404
1405    identical!(
1406        issue_286,
1407        "var SHARED = '__core-js_shared__';
1408var store = global[SHARED] || (global[SHARED] = {});
1409(module.exports = function (key, value) {
1410  return store[key] || (store[key] = value !== undefined ? value : {});
1411})('versions', []).push({
1412  version: core.version,
1413  mode: __webpack_require__(39) ? 'pure' : 'global',
1414  copyright: '© 2018 Denis Pushkarev (zloirock.ru)'
1415});"
1416    );
1417
1418    identical!(
1419        issue_293_1,
1420        "for (var e in a) a.hasOwnProperty(e) && ((b = a[e]) ? this[e] = b(c) : 'target' === e ? \
1421         this.target = d : this[e] = c[e]);"
1422    );
1423
1424    identical!(
1425        issue_293_2,
1426        "(a = rb ? zb(a, c) : Ab(a, c)) ? (b = nb.getPooled(ub.beforeInput, b, c, d), b.data = a, \
1427         Ra(b)) : b = null;"
1428    );
1429
1430    identical!(member_object_lit, "({}).foo");
1431
1432    identical!(member_cond_expr, "(foo ? 1 : 2).foo");
1433
1434    identical!(member_new_exp_1, "(new Foo).foo");
1435
1436    identical!(member_new_exp_2, "new ctor().property");
1437
1438    identical!(member_tagged_tpl, "tag``.foo");
1439
1440    identical!(member_arrow_expr_1, "(a => a).foo");
1441
1442    identical!(member_arrow_expr_2, "((a) => a).foo");
1443
1444    identical!(member_class, "(class Foo{}).foo");
1445
1446    identical!(member_yield, "function* foo(){ (yield bar).baz }");
1447
1448    identical!(member_await, "async function foo(){ (await bar).baz }");
1449
1450    identical!(bin_yield_expr_1, "function* foo(){ (yield foo) && bar }");
1451
1452    identical!(bin_yield_expr_2, "function* foo(){ bar && (yield foo) }");
1453
1454    identical!(bin_seq_expr_1, "(foo(), op) || (seq(), foo)");
1455
1456    identical!(bin_seq_expr_2, "(foo, op) || (seq, foo)");
1457
1458    identical!(cond_object_1, "let foo = {} ? 1 : 2;");
1459
1460    identical!(cond_object_2, "({}) ? 1 : 2;");
1461
1462    identical!(cond_in_cond, "(foo ? 1 : 2) ? 3 : 4");
1463
1464    identical!(arrow_in_cond, "(() => {}) ? 3 : 4");
1465
1466    identical!(unary_cond_arg, "void (foo ? 1 : 2)");
1467
1468    identical!(unary_arrow_arg, "void ((foo) => foo)");
1469
1470    identical!(unary_yield_arg, "(function* foo() { void (yield foo); })()");
1471
1472    identical!(
1473        issue_365,
1474        "const foo = (() => {
1475  return 1
1476})();"
1477    );
1478
1479    identical!(
1480        issue_382_1,
1481        "const myFilter = (arr, filter) => arr.filter(((x) => x) || filter);"
1482    );
1483
1484    identical!(
1485        issue_382_2,
1486        "const myFilter = (arr, filter) => arr.filter(filter || ((x) => x));"
1487    );
1488
1489    identical!(issue_418, "const a = 1 - (1 - 1)");
1490
1491    test_fixer!(
1492        issue_439,
1493        "() => {
1494  return (
1495    Promise.resolve('foo')
1496      // Interfering comment
1497      .then(() => {})
1498  );
1499};",
1500        "() => {
1501  return Promise.resolve('foo')
1502      // Interfering comment
1503      .then(() => {})
1504  ;
1505};"
1506    );
1507
1508    test_fixer!(
1509        issue_451,
1510        "const instance = new (
1511  function() {
1512    function klass(opts) {
1513      this.options = opts;
1514    }
1515    return (Object.assign(klass.prototype, {
1516      method() {}
1517    }), klass);
1518  }()
1519)({ foo: 1 });",
1520        "const instance = new (function() {
1521    function klass(opts) {
1522        this.options = opts;
1523    }
1524    return Object.assign(klass.prototype, {
1525        method () {
1526        }
1527    }), klass;
1528}())({
1529    foo: 1
1530});"
1531    );
1532
1533    test_fixer!(void_and_bin, "(void 0) * 2", "(void 0) * 2");
1534
1535    test_fixer!(new_cond, "new (a ? B : C)()", "new (a ? B : C)()");
1536
1537    identical!(issue_931, "new (eval('Date'))();");
1538
1539    identical!(issue_1002, "new (P || (P = Promise))");
1540
1541    identical!(
1542        issue_1050,
1543        "
1544        (a) => (set) => (elemE(a, set) ? removeE : insertE)(a)(set)
1545        "
1546    );
1547
1548    identical!(
1549        deno_001,
1550        "
1551    var Status;
1552    (function init(Status1) {
1553    })(Status || (Status = {
1554    }));
1555"
1556    );
1557
1558    identical!(issue_1093, "const x = (fnA || fnB)();");
1559
1560    identical!(
1561        issue_1133,
1562        "async function foo() {
1563            const item = await (data === null || data === void 0 ? void 0 : data.foo());
1564        }"
1565    );
1566
1567    identical!(deno_8722, "console.log((true || false) ?? true);");
1568
1569    identical!(
1570        deno_8597,
1571        "
1572        biasInitializer = new (_a = class CustomInit extends Initializer {})();
1573        "
1574    );
1575
1576    test_fixer!(
1577        minifier_001,
1578        "var bitsLength = 3, bitsOffset = 3, what = (len = 0)",
1579        "var bitsLength = 3, bitsOffset = 3, what = len = 0"
1580    );
1581
1582    test_fixer!(minifier_002, "!(function(){})()", "!function(){}()");
1583
1584    identical!(
1585        issue_1397,
1586        "const main = async () => await (await server)()"
1587    );
1588
1589    identical!(deno_9810, "await (bar = Promise.resolve(2));");
1590
1591    identical!(issue_1493, "('a' ?? 'b') || ''");
1592    identical!(call_seq, "let x = ({}, () => 2)();");
1593
1594    test_fixer!(
1595        call_seq_with_padding,
1596        "let x = ({}, (1, 2), () => 2)();",
1597        "let x = ({}, () => 2)();"
1598    );
1599
1600    identical!(
1601        param_seq,
1602        "function t(x = ({}, 2)) {
1603            return x;
1604        }"
1605    );
1606
1607    identical!(
1608        yield_expr_cond,
1609        "function *test1(foo) {
1610            return (yield foo) ? 'bar' : 'baz';
1611        }"
1612    );
1613
1614    identical!(
1615        deno_10487_1,
1616        "var generator = class MultiVector extends (options.baseType||Float32Array) {}"
1617    );
1618
1619    identical!(
1620        deno_10487_2,
1621        "class MultiVector extends (options.baseType||Float32Array) {}"
1622    );
1623
1624    identical!(
1625        extends_nullish_coalescing,
1626        "class Foo extends (Bar ?? class{}) {}"
1627    );
1628
1629    identical!(extends_assign, "class Foo extends (Bar = class{}) {}");
1630
1631    identical!(
1632        extends_logical_or_assin,
1633        "class Foo extends (Bar ||= class{}) {}"
1634    );
1635
1636    identical!(
1637        extends_logical_and_assin,
1638        "class Foo extends (Bar &&= class{}) {}"
1639    );
1640
1641    identical!(
1642        extends_logical_nullish_assin,
1643        "class Foo extends (Bar ??= class{}) {}"
1644    );
1645
1646    identical!(extends_cond, "class Foo extends (true ? Bar : Baz) {}");
1647
1648    identical!(
1649        extends_await_yield,
1650        "
1651        async function* func() {
1652            class A extends (await p) {}
1653            class B extends (yield p) {}
1654        }
1655        "
1656    );
1657
1658    identical!(deno_10668_1, "console.log(null ?? (undefined && true))");
1659
1660    identical!(deno_10668_2, "console.log(null && (undefined ?? true))");
1661
1662    identical!(minifier_003, "(four ** one) ** two");
1663
1664    identical!(minifier_004, "(void 0)(0)");
1665
1666    identical!(issue_1781, "const n = ~~(Math.PI * 10)");
1667
1668    identical!(issue_1789, "+(+1 / 4)");
1669
1670    identical!(new_member_call_1, "new (getObj()).ctor()");
1671    test_fixer!(
1672        new_member_call_2,
1673        "new (getObj().ctor)()",
1674        "new (getObj()).ctor()"
1675    );
1676    test_fixer!(
1677        new_member_call_3,
1678        "new (x.getObj().ctor)()",
1679        "new (x.getObj()).ctor()"
1680    );
1681    identical!(new_call, "new (getCtor())");
1682    test_fixer!(new_member_1, "new obj.ctor()", "new obj.ctor()");
1683    test_fixer!(new_member_2, "new (obj.ctor)", "new obj.ctor");
1684
1685    identical!(
1686        new_await_1,
1687        "async function foo() { new (await getServerImpl())(options) }"
1688    );
1689    test_fixer!(minifier_005, "-(1/0)", "-1/0");
1690
1691    test_fixer!(minifier_006, "-('s'/'b')", "-('s'/'b')");
1692
1693    test_fixer!(minifier_007, "(void 0) === value", "void 0 === value");
1694    test_fixer!(minifier_008, "(size--) && (b = (c))", "size-- && (b = c)");
1695
1696    test_fixer!(
1697        minifier_009,
1698        "(--remaining) || deferred.resolveWith()",
1699        "--remaining || deferred.resolveWith()"
1700    );
1701
1702    test_fixer!(minifier_010, "(--remaining) + ''", "--remaining + ''");
1703
1704    identical!(
1705        if_stmt_001,
1706        "
1707        export const obj = {
1708            each: function (obj, callback, args) {
1709                var i = 0, length = obj.length, isArray = isArraylike(obj);
1710                if (args) {
1711                    if (isArray)
1712                        for (; i < length && !1 !== callback.apply(obj[i], args); i++);
1713                    else
1714                        for (i in obj)
1715                            if (!1 === callback.apply(obj[i], args))
1716                                break
1717                } else if (isArray)
1718                    for (; i < length && !1 !== callback.call(obj[i], i, obj[i]); i++);
1719                else
1720                    for (i in obj)
1721                        if (!1 === callback.call(obj[i], i, obj[i]))
1722                            break;
1723                return obj
1724            }
1725        };
1726        "
1727    );
1728
1729    identical!(
1730        issue_2155,
1731        "
1732        async function main() {
1733            let promise;
1734            await (promise || (promise = Promise.resolve('this is a string')));
1735        }
1736        "
1737    );
1738
1739    identical!(issue_2163_1, "() => ({foo} = bar());");
1740
1741    identical!(issue_2163_2, "() => ([foo] = bar());");
1742
1743    identical!(issue_2191, "(-1) ** h");
1744
1745    identical!(
1746        minifier_011,
1747        "
1748        function ItemsList() {
1749            var _ref;
1750
1751            var _temp, _this, _ret;
1752
1753            _class_call_check(this, ItemsList);
1754
1755            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
1756              args[_key] = arguments[_key];
1757            }
1758
1759            return _ret = (_temp = (_this = _possible_constructor_return(this, (_ref = \
1760         ItemsList.__proto__ || Object.getPrototypeOf(ItemsList)).call.apply(_ref, \
1761         [this].concat(args))), _this), _this.storeHighlightedItemReference = function \
1762         (highlightedItem) {
1763              _this.props.onHighlightedItemChange(highlightedItem === null ? null : \
1764         highlightedItem.item);
1765            }, _temp), _possible_constructor_return(_this, _ret);
1766          }
1767        "
1768    );
1769
1770    identical!(
1771        minifier_012,
1772        "
1773        function ItemsList() {
1774            for(var _ref, _temp, _this, _len = arguments.length, args = Array(_len), _key = 0; \
1775         _key < _len; _key++)args[_key] = arguments[_key];
1776            return _possible_constructor_return(_this, (_temp = (_this = \
1777         _possible_constructor_return(this, (_ref = ItemsList.__proto__ || \
1778         Object.getPrototypeOf(ItemsList)).call.apply(_ref, [
1779                this
1780            ].concat(args))), _this), _this.storeHighlightedItemReference = \
1781         function(highlightedItem) {
1782                _this.props.onHighlightedItemChange(null === highlightedItem ? null : \
1783         highlightedItem.item);
1784            }, _temp));
1785        }
1786        "
1787    );
1788
1789    test_fixer!(issue_2550_1, "(1 && { a: 1 })", "1 && { a:1 }");
1790
1791    identical!(issue_2550_2, "({ isNewPrefsActive }) && { a: 1 }");
1792
1793    test_fixer!(paren_of_bin_left_1, "({} && 1)", "({}) && 1");
1794    identical!(paren_of_bin_left_2, "({}) && 1");
1795    test_fixer!(
1796        paren_of_bin_left_3,
1797        "(function () {} || 2)",
1798        "(function () {}) || 2"
1799    );
1800    identical!(paren_of_bin_left_4, "(function () {}) || 2");
1801
1802    test_fixer!(paren_of_bin_left_5, "(class{} ?? 3)", "(class{}) ?? 3");
1803    identical!(paren_of_bin_left_6, "(class{}) ?? 3");
1804
1805    identical!(issue_4761, "x = { ...(0, foo) }");
1806
1807    identical!(issue_4914, "(a ?? b)?.()");
1808
1809    identical!(issue_5109_1, "(0, b)?.()");
1810    identical!(issue_5109_2, "1 + (0, b)?.()");
1811    identical!(issue_5109_3, "(0, a)() ? undefined : (0, b)?.()");
1812
1813    identical!(
1814        issue_5313,
1815        "
1816        async function* foo() {
1817            (await a)();
1818            (yield b)();
1819        }
1820        "
1821    );
1822
1823    identical!(issue_5417, "console.log(a ?? b ?? c)");
1824
1825    identical!(bin_and_unary, "console.log(a++ && b--)");
1826
1827    test_fixer!(
1828        issue_11322,
1829        "((function () { })() && a, b)",
1830        "(function () { })() && a, b"
1831    );
1832
1833    test_fixer!(
1834        issue_11322_simple,
1835        "(function () { })() && a",
1836        "(function () { })() && a"
1837    );
1838
1839    test_fixer!(
1840        issue_11322_stmt,
1841        "(function () { })() && a;",
1842        "(function () { })() && a;"
1843    );
1844}