diff --git a/crates/swc_ecma_ast/Cargo.toml b/crates/swc_ecma_ast/Cargo.toml index 088b41c80285..ebc63d48103d 100644 --- a/crates/swc_ecma_ast/Cargo.toml +++ b/crates/swc_ecma_ast/Cargo.toml @@ -33,7 +33,7 @@ rkyv-bytecheck-impl = [ arbitrary = { version = "1", optional = true, features = ["derive"] } bitflags = "1" bytecheck = { version = "0.6.9", optional = true } -is-macro = "0.2.0" +is-macro = "0.2.1" num-bigint = { version = "0.4", features = ["serde"] } rkyv = { package = "rkyv", version = "=0.7.37", optional = true } # This is to avoid cargo version selection conflict between rkyv=0.7.37 and other versions, as it is strictly pinned diff --git a/crates/swc_ecma_ast/src/expr.rs b/crates/swc_ecma_ast/src/expr.rs index f18d46da3ee1..5e3b5c19bcdc 100644 --- a/crates/swc_ecma_ast/src/expr.rs +++ b/crates/swc_ecma_ast/src/expr.rs @@ -8,7 +8,7 @@ use serde::{ Deserialize, Deserializer, Serialize, }; use string_enum::StringEnum; -use swc_atoms::Atom; +use swc_atoms::{js_word, Atom}; use swc_common::{ast_node, util::take::Take, BytePos, EqIgnoreSpan, Span, Spanned, DUMMY_SP}; use crate::{ @@ -215,6 +215,17 @@ impl Expr { })) } } + + /// Returns true for `eval` and member expressions. + pub fn directness_maters(&self) -> bool { + matches!( + self, + Expr::Ident(Ident { + sym: js_word!("eval"), + .. + }) | Expr::Member(..) + ) + } } // Implement Clone without inline to avoid multiple copies of the diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/6175/1/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/6175/1/input.js new file mode 100644 index 000000000000..a96bdc6e78f2 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/6175/1/input.js @@ -0,0 +1,11 @@ +let o = { + f() { + assert.ok(this !== o); + } +}; +(1, o.f)``; +(true ? o.f : false)``; +(true && o.f)``; + +let a; +(a = o.f)``; \ No newline at end of file diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/6175/1/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/6175/1/output.js new file mode 100644 index 000000000000..a892d4e02bb2 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/6175/1/output.js @@ -0,0 +1,6 @@ +let o = { + f () { + assert.ok(this !== o); + } +}; +(0, o.f)``, (0, o.f)``, (0, o.f)``, (0, o.f)``; diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs index eae73ffe8a3b..dff8c6efbc8b 100644 --- a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs +++ b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs @@ -483,7 +483,7 @@ impl SimplifyExpr { self.changed = true; // 0 && $right - *expr = *(left.take()); + *expr = *left.take(); return; } } else if val { @@ -500,7 +500,14 @@ impl SimplifyExpr { if !left.may_have_side_effects(&self.expr_ctx) { self.changed = true; - *expr = *node.take(); + if node.directness_maters() { + *expr = Expr::Seq(SeqExpr { + span: node.span(), + exprs: vec![0.into(), node.take()], + }); + } else { + *expr = *node.take(); + } } else { self.changed = true; @@ -1330,7 +1337,14 @@ impl VisitMut for SimplifyExpr { let expr_value = if val { cons } else { alt }; *expr = if p.is_pure() { - *(expr_value.take()) + if expr_value.directness_maters() { + Expr::Seq(SeqExpr { + span: *span, + exprs: vec![0.into(), expr_value.take()], + }) + } else { + *expr_value.take() + } } else { Expr::Seq(SeqExpr { span: *span,