diff --git a/crates/swc/tests/tsc-references/logicalAssignment1(target=es2020).2.minified.js b/crates/swc/tests/tsc-references/logicalAssignment1(target=es2020).2.minified.js index ead7fa33b82f..78a37e96c9e1 100644 --- a/crates/swc/tests/tsc-references/logicalAssignment1(target=es2020).2.minified.js +++ b/crates/swc/tests/tsc-references/logicalAssignment1(target=es2020).2.minified.js @@ -1,2 +1,2 @@ //// [logicalAssignment1.ts] -a && (a = "foo"), b || (b = "foo"), c = "foo", d && (d = 42), e || (e = 42), f = 42, g && (g = 42), h || (h = 42), i = 42; +a && (a = "foo"), b || (b = "foo"), c ?? (c = "foo"), d && (d = 42), e || (e = 42), f ?? (f = 42), g && (g = 42), h || (h = 42), i ?? (i = 42); diff --git a/crates/swc/tests/tsc-references/logicalAssignment10(target=es2020).2.minified.js b/crates/swc/tests/tsc-references/logicalAssignment10(target=es2020).2.minified.js index 5caa48e7f7ee..b6e88407df32 100644 --- a/crates/swc/tests/tsc-references/logicalAssignment10(target=es2020).2.minified.js +++ b/crates/swc/tests/tsc-references/logicalAssignment10(target=es2020).2.minified.js @@ -1,5 +1,5 @@ //// [logicalAssignment10.ts] var _obj, _ref, _ref1, _ref2, count = 0, obj = {}; -(_obj = obj)[_ref = ++count], _obj[_ref] = ++count, (_ref1 = ({ +(_obj = obj)[_ref = ++count] ?? (_obj[_ref] = ++count), (_ref1 = ({ obj -}).obj)[_ref2 = ++count], _ref1[_ref2] = ++count; +}).obj)[_ref2 = ++count] ?? (_ref1[_ref2] = ++count); diff --git a/crates/swc/tests/tsc-references/logicalAssignment11(target=es2020).2.minified.js b/crates/swc/tests/tsc-references/logicalAssignment11(target=es2020).2.minified.js index 43791533fec7..94b153fbcd0c 100644 --- a/crates/swc/tests/tsc-references/logicalAssignment11(target=es2020).2.minified.js +++ b/crates/swc/tests/tsc-references/logicalAssignment11(target=es2020).2.minified.js @@ -1,3 +1,3 @@ //// [logicalAssignment11.ts] -let x; -(x ?? "x").length, (x ?? "x").length; +let x, d, e; +d ?? (d = x ?? "x"), d.length, e ?? (e = x ?? "x"), e.length; diff --git a/crates/swc/tests/tsc-references/logicalAssignment11(target=es2022).2.minified.js b/crates/swc/tests/tsc-references/logicalAssignment11(target=es2022).2.minified.js index e236490b2b0d..5f9626e7b173 100644 --- a/crates/swc/tests/tsc-references/logicalAssignment11(target=es2022).2.minified.js +++ b/crates/swc/tests/tsc-references/logicalAssignment11(target=es2022).2.minified.js @@ -1,3 +1,3 @@ //// [logicalAssignment11.ts] -let x, e; -(x ?? "x").length, (e ??= x ?? "x").length; +let x, d, e; +d ?? (d = x ?? "x"), d.length, (e ??= x ?? "x").length; diff --git a/crates/swc/tests/tsc-references/logicalAssignment2(target=es2020).2.minified.js b/crates/swc/tests/tsc-references/logicalAssignment2(target=es2020).2.minified.js index 430ca9f5db99..fd196d61420c 100644 --- a/crates/swc/tests/tsc-references/logicalAssignment2(target=es2020).2.minified.js +++ b/crates/swc/tests/tsc-references/logicalAssignment2(target=es2020).2.minified.js @@ -1,3 +1,3 @@ //// [logicalAssignment2.ts] var _a, _b, _c, _foo, _foo1, _foo2, _ref, _ref1, _ref2; -(_a = a).baz && (_a.baz = result.baz), (_b = b).baz || (_b.baz = result.baz), (_c = c).baz, _c.baz = result.baz, (_foo = a.foo).baz && (_foo.baz = result.foo.baz), (_foo1 = b.foo).baz || (_foo1.baz = result.foo.baz), (_foo2 = c.foo).baz, _foo2.baz = result.foo.baz, (_ref = a.foo.bar()).baz && (_ref.baz = result.foo.bar().baz), (_ref1 = b.foo.bar()).baz || (_ref1.baz = result.foo.bar().baz), (_ref2 = c.foo.bar()).baz, _ref2.baz = result.foo.bar().baz; +(_a = a).baz && (_a.baz = result.baz), (_b = b).baz || (_b.baz = result.baz), (_c = c).baz ?? (_c.baz = result.baz), (_foo = a.foo).baz && (_foo.baz = result.foo.baz), (_foo1 = b.foo).baz || (_foo1.baz = result.foo.baz), (_foo2 = c.foo).baz ?? (_foo2.baz = result.foo.baz), (_ref = a.foo.bar()).baz && (_ref.baz = result.foo.bar().baz), (_ref1 = b.foo.bar()).baz || (_ref1.baz = result.foo.bar().baz), (_ref2 = c.foo.bar()).baz ?? (_ref2.baz = result.foo.bar().baz); diff --git a/crates/swc/tests/tsc-references/logicalAssignment3(target=es2020).2.minified.js b/crates/swc/tests/tsc-references/logicalAssignment3(target=es2020).2.minified.js index 73c808202a92..7bc19cfd7859 100644 --- a/crates/swc/tests/tsc-references/logicalAssignment3(target=es2020).2.minified.js +++ b/crates/swc/tests/tsc-references/logicalAssignment3(target=es2020).2.minified.js @@ -1,3 +1,3 @@ //// [logicalAssignment3.ts] var _a, _b, _c; -(_a = a).baz && (_a.baz = result.baz), (_b = b).baz || (_b.baz = result.baz), (_c = c).baz, _c.baz = result.baz; +(_a = a).baz && (_a.baz = result.baz), (_b = b).baz || (_b.baz = result.baz), (_c = c).baz ?? (_c.baz = result.baz); diff --git a/crates/swc_ecma_minifier/src/compress/optimize/iife.rs b/crates/swc_ecma_minifier/src/compress/optimize/iife.rs index 4d10a87eb217..8e14005626ba 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/iife.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/iife.rs @@ -683,10 +683,7 @@ where match e { Expr::Lit(..) | Expr::Ident(..) => true, - Expr::Bin(BinExpr { - op: op!("&&") | op!("||") | op!("??"), - .. - }) => false, + Expr::Bin(BinExpr { op, .. }) if op.may_short_circuit() => false, Expr::Bin(e) => { self.is_return_arg_simple_enough_for_iife_eval(&e.left) diff --git a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs index 56edd29e3581..68589dd964dc 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs @@ -664,11 +664,8 @@ where Expr::Paren(e) => return self.ignore_return_value(&mut e.expr), Expr::Bin(BinExpr { - op: op!("&&") | op!("||"), - left, - right, - .. - }) => { + op, left, right, .. + }) if op.may_short_circuit() => { let ctx = Ctx { dont_use_negated_iife: self.ctx.dont_use_negated_iife || self.options.side_effects, @@ -1472,7 +1469,7 @@ where fn visit_mut_bin_expr(&mut self, n: &mut BinExpr) { { let ctx = Ctx { - in_cond: self.ctx.in_cond || matches!(n.op, op!("&&") | op!("||") | op!("??")), + in_cond: self.ctx.in_cond || n.op.may_short_circuit(), ..self.ctx }; diff --git a/crates/swc_ecma_minifier/src/compress/optimize/ops.rs b/crates/swc_ecma_minifier/src/compress/optimize/ops.rs index bef87f936eed..13920365c703 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/ops.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/ops.rs @@ -84,7 +84,7 @@ where pub(super) fn remove_bin_paren(&mut self, n: &mut BinExpr) { if let Expr::Bin(right) = &mut *n.right { if right.op == n.op { - if matches!(n.op, op!("&&") | op!("||") | op!("??")) + if n.op.may_short_circuit() || (right.left.is_str() && right.op == op!(bin, "+")) || (n.left.is_str() && right.right.is_str()) { diff --git a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs index 377a411cff80..50c46007a431 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs @@ -1570,9 +1570,8 @@ where return Ok(false); } - match *op { - op!("&&") | op!("||") | op!("??") => return Ok(false), - _ => {} + if op.may_short_circuit() { + return Ok(false); } trace_op!("seq: Try right of bin"); diff --git a/crates/swc_ecma_minifier/tests/fixture/pr/6272/input.js b/crates/swc_ecma_minifier/tests/fixture/pr/6272/input.js new file mode 100644 index 000000000000..5ed6896bb292 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/pr/6272/input.js @@ -0,0 +1 @@ +a ?? (a = b); diff --git a/crates/swc_ecma_minifier/tests/fixture/pr/6272/output.js b/crates/swc_ecma_minifier/tests/fixture/pr/6272/output.js new file mode 100644 index 000000000000..5ed6896bb292 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/pr/6272/output.js @@ -0,0 +1 @@ +a ?? (a = b);