Skip to content

Commit 29417dd

Browse files
committed
feat(minifier): minimize !(a, b) -> a, !b (#8746)
1 parent 3ece991 commit 29417dd

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

crates/oxc_minifier/src/peephole/minimize_conditions.rs

+20
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ impl<'a> PeepholeOptimizations {
128128
.unwrap_or_else(|| Expression::UnaryExpression(ctx.ast.alloc(unary)))
129129
}
130130

131+
/// `MaybeSimplifyNot`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_ast_helpers.go#L73>
131132
fn try_minimize_not(
132133
expr: &mut UnaryExpression<'a>,
133134
ctx: Ctx<'a, '_>,
@@ -136,15 +137,22 @@ impl<'a> PeepholeOptimizations {
136137
return None;
137138
}
138139
match &mut expr.argument {
140+
// `!!true` -> `true`
141+
// `!!false` -> `false`
139142
Expression::UnaryExpression(e)
140143
if e.operator.is_not() && ValueType::from(&e.argument).is_boolean() =>
141144
{
142145
Some(ctx.ast.move_expression(&mut e.argument))
143146
}
147+
// `!(a == b)` => `a != b`
148+
// `!(a != b)` => `a == b`
149+
// `!(a === b)` => `a !== b`
150+
// `!(a !== b)` => `a === b`
144151
Expression::BinaryExpression(e) if e.operator.is_equality() => {
145152
e.operator = e.operator.equality_inverse_operator().unwrap();
146153
Some(ctx.ast.move_expression(&mut expr.argument))
147154
}
155+
// `!(a == b ? foo: bar)` => `a != b ? foo : bar`
148156
Expression::ConditionalExpression(conditional_expr) => {
149157
if let Expression::BinaryExpression(e) = &mut conditional_expr.test {
150158
if e.operator.is_equality() {
@@ -154,6 +162,17 @@ impl<'a> PeepholeOptimizations {
154162
}
155163
None
156164
}
165+
// "!(a, b)" => "a, !b"
166+
Expression::SequenceExpression(sequence_expr) => {
167+
if let Some(e) = sequence_expr.expressions.pop() {
168+
let e = ctx.ast.expression_unary(e.span(), UnaryOperator::LogicalNot, e);
169+
let expressions = ctx.ast.vec_from_iter(
170+
sequence_expr.expressions.drain(..).chain(std::iter::once(e)),
171+
);
172+
return Some(ctx.ast.expression_sequence(sequence_expr.span, expressions));
173+
}
174+
None
175+
}
157176
_ => None,
158177
}
159178
}
@@ -2310,6 +2329,7 @@ mod test {
23102329
test("!!!delete x.y", "!delete x.y");
23112330
test("!!!!delete x.y", "delete x.y");
23122331
test("var k = !!(foo instanceof bar)", "var k = foo instanceof bar");
2332+
test("!(a, b)", "a, !b");
23132333
}
23142334

23152335
#[test]

crates/oxc_minifier/src/peephole/statement_fusion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ mod test {
201201
#[test]
202202
fn fold_block_into_if() {
203203
test("a;b;c;if(x){}", "a,b,c,x");
204-
test("a;b;c;if(x,y){}else{}", "a, b, c, !(x, y);");
204+
test("a;b;c;if(x,y){}else{}", "a, b, c, x, !y;");
205205
test("a;b;c;if(x,y){}", "a, b, c, x, y");
206206
test("a;b;c;if(x,y,z){}", "a, b, c, x, y, z");
207207
test("a();if(a()){}a()", "a(), a(), a()");

crates/oxc_minifier/tests/peephole/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn integration() {
8282
}
8383
console.log(c, d);
8484
",
85-
"if (!((() => console.log('effect'))(), !0)) for (var c = 1, c; unknownGlobal; unknownGlobal && !0) var d;
85+
"if ((() => console.log('effect'))(), !1) for (var c = 1, c; unknownGlobal; unknownGlobal && !0) var d;
8686
console.log(c, d);
8787
",
8888
);

tasks/minsize/minsize.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ Original | minified | minified | gzip | gzip | Fixture
2323

2424
6.69 MB | 2.30 MB | 2.31 MB | 470.00 kB | 488.28 kB | antd.js
2525

26-
10.95 MB | 3.37 MB | 3.49 MB | 866.66 kB | 915.50 kB | typescript.js
26+
10.95 MB | 3.37 MB | 3.49 MB | 866.64 kB | 915.50 kB | typescript.js
2727

0 commit comments

Comments
 (0)