fix(minifier): add missing negation for boolean literal (#26847)

we sometimes do construct `BooleanLiteral`, mostly in dce mode, with
this we can negate its value instead of first wrapping it with not and
afterwards flipping it

instead of:
`true` -> `!true`
`true` -> `false`

And in non dce
`true` -> `!true` -> `!!0` -> `!1`
`true` -> `false` -> `!1`
This commit is contained in:
Armano authored and GitHub committed 2026-09-21 14:02:18 +08:00
1 parent c55ae7d460
commit cd7228fdf2
4 files changed
+25 -19

No files matched your search

@@ -840,8 +840,7 @@ impl<'a> PeepholeOptimizations {
let new_expr = Expression::new_boolean_literal(
e.span,
e.operator == BinaryOperator::Inequality
|| e.operator == BinaryOperator::StrictInequality,
matches!(e.operator, BinaryOperator::StrictInequality | BinaryOperator::Inequality),
ctx,
);
ctx.replace_expression(expr, new_expr);
@@ -117,7 +117,8 @@ impl<'a> PeepholeOptimizations {
if let Some(symbol_id) = ctx.scoping().get_reference(reference_id).symbol_id()
&& ctx.state.symbols.value(symbol_id).is_some_and(|sv| sv.boolean_falsy)
{
let new_expr = Expression::new_boolean_literal(span, false, ctx);
let new_expr =
Expression::new_numeric_literal(span, 0.0, None, NumberBase::Decimal, ctx);
ctx.replace_expression(expr, new_expr);
}
}
@@ -60,6 +60,12 @@ impl<'a> PeepholeOptimizations {
num.value = if num.value.is_nan() || num.value == 0.0 { 1.0 } else { 0.0 };
true
}
// `true` => `false`
// `false` => `true`
Expression::BooleanLiteral(bool_expr) => {
bool_expr.value = !bool_expr.value;
true
}
// `!(a == b || c == d)` => `a != b && c != d`
// `!(a == b && c == d)` => `a != b || c != d`
// De Morgan's law, only when every comparison in the `&&`/`||` chain
@@ -3,22 +3,22 @@ checker.ts:
sys allocs: 122
sys reallocs: 5
sys deallocs: 122
sys alloc bytes: 14996632 # 15.00 MB
sys alloc bytes: 14996287 # 15.00 MB
sys peak growth: 10169560 # 10.17 MB
arena allocs: 56226
arena reallocs: 5084
arena size: 16317704 # 16.32 MB
arena size: 16317648 # 16.32 MB
App.tsx:
file size: 415342 # 415.34 kB
sys allocs: 61
sys reallocs: 8
sys deallocs: 61
sys alloc bytes: 2128563 # 2.13 MB
sys alloc bytes: 2128539 # 2.13 MB
sys peak growth: 1612427 # 1.61 MB
arena allocs: 7489
arena allocs: 7488
arena reallocs: 920
arena size: 2684576 # 2.68 MB
arena size: 2684416 # 2.68 MB
RadixUIAdoptionSection.jsx:
file size: 2520 # 2.52 kB
@@ -29,26 +29,26 @@ RadixUIAdoptionSection.jsx:
sys peak growth: 11628 # 11.63 kB
arena allocs: 16
arena reallocs: 0
arena size: 35224 # 35.22 kB
arena size: 35120 # 35.12 kB
pdf.mjs:
file size: 567296 # 567.30 kB
sys allocs: 2427
sys reallocs: 205
sys deallocs: 2427
sys alloc bytes: 5316219 # 5.32 MB
sys peak growth: 3693363 # 3.69 MB
sys alloc bytes: 5313795 # 5.31 MB
sys peak growth: 3693355 # 3.69 MB
arena allocs: 19526
arena reallocs: 2574
arena size: 5708896 # 5.71 MB
arena size: 5708848 # 5.71 MB
antd.js:
file size: 6686316 # 6.69 MB
sys allocs: 860
sys reallocs: 56
sys deallocs: 860
sys alloc bytes: 29976375 # 29.98 MB
sys peak growth: 19934749 # 19.93 MB
sys alloc bytes: 29973448 # 29.97 MB
sys peak growth: 19934725 # 19.93 MB
arena allocs: 181721
arena reallocs: 34406
arena size: 43045192 # 43.05 MB
@@ -58,19 +58,19 @@ binder.ts:
sys allocs: 33
sys reallocs: 1
sys deallocs: 33
sys alloc bytes: 963032 # 963.03 kB
sys alloc bytes: 963008 # 963.01 kB
sys peak growth: 657404 # 657.40 kB
arena allocs: 2923
arena reallocs: 244
arena size: 1075024 # 1.08 MB
arena size: 1074976 # 1.07 MB
kitchen-sink.tsx:
file size: 732898 # 732.90 kB
sys allocs: 1854
sys reallocs: 174
sys deallocs: 1854
sys alloc bytes: 5304692 # 5.30 MB
sys peak growth: 3707457 # 3.71 MB
sys alloc bytes: 5304252 # 5.30 MB
sys peak growth: 3707425 # 3.71 MB
arena allocs: 31159
arena reallocs: 3012
arena size: 8444408 # 8.44 MB
arena size: 8444304 # 8.44 MB