fix(minifier): fold conditional expressions with long sequences (#27083)

extend conditional expression folding when sequence with more than 2
items is encountered:

`a ? (b, c, d) : d` -> `a && (b, c), d`
`a ? d : (b, c, d)` -> `a || (b, c), d`

---------

Co-authored-by: Cameron Clark <cameron.clark@hey.com>
This commit is contained in:
ArmanoandCameron Clark authored and GitHub committed 2026-09-29 14:07:29 +00:00
1 parent de7f60c79f
commit da1fed245b
4 files changed
+43 -24

No files matched your search

@@ -154,11 +154,19 @@ impl<'a> PeepholeOptimizations {
));
}
// "a ? c : (b, c)" => "(a || b), c"
// `a ? c : (b, c)` => `(a || b), c`
// `a ? d : (b, c, d)` => `(a || (b, c)), d`
if let Expression::SequenceExpression(alternate) = &mut expr.alternate
&& alternate.expressions.len() == 2
&& ctx.expr_eq(&alternate.expressions[1], &expr.consequent)
&& alternate.expressions.len() > 1
&& let Some(last) = alternate.expressions.last()
&& ctx.expr_eq(last, &expr.consequent)
{
let last_expr = alternate.expressions.pop().unwrap();
let seq_prefix = if alternate.expressions.len() == 1 {
alternate.expressions.pop().unwrap()
} else {
expr.alternate.take_in(ctx)
};
return Some(Expression::new_sequence_expression(
expr.span,
[
@@ -166,20 +174,29 @@ impl<'a> PeepholeOptimizations {
expr.test.span(),
LogicalOperator::Or,
expr.test.take_in(ctx),
alternate.expressions[0].take_in(ctx),
seq_prefix,
ctx,
),
expr.consequent.take_in(ctx),
last_expr,
],
ctx,
));
}
// "a ? (b, c) : c" => "(a && b), c"
// `a ? (b, c) : c` => `(a && b), c`
// `a ? (b, c, d) : d` => `(a && (b, c)), d`
if let Expression::SequenceExpression(consequent) = &mut expr.consequent
&& consequent.expressions.len() == 2
&& ctx.expr_eq(&consequent.expressions[1], &expr.alternate)
&& consequent.expressions.len() > 1
&& let Some(last) = consequent.expressions.last()
&& ctx.expr_eq(last, &expr.alternate)
{
let last_expr = consequent.expressions.pop().unwrap();
let seq_prefix = if consequent.expressions.len() == 1 {
consequent.expressions.pop().unwrap()
} else {
expr.consequent.take_in(ctx)
};
return Some(Expression::new_sequence_expression(
expr.span,
[
@@ -187,10 +204,10 @@ impl<'a> PeepholeOptimizations {
expr.test.span(),
LogicalOperator::And,
expr.test.take_in(ctx),
consequent.expressions[0].take_in(ctx),
seq_prefix,
ctx,
),
expr.alternate.take_in(ctx),
last_expr,
],
ctx,
));
@@ -45,7 +45,9 @@ fn minimize_conditional_exprs() {
test("a ? b ? c : d : d", "a && b ? c : d");
test("a ? b : c ? b : d", "a || c ? b : d");
test("a ? c : (b, c)", "(a || b), c");
test("a ? d : (b, c, d)", "a || (b, c), d;");
test("a ? (b, c) : c", "(a && b), c");
test("a ? (b, c, d) : d", "a && (b, c), d;");
test("a ? b || c : c", "(a && b) || c");
test("a ? c : b && c", "(a || b) && c");
test(
+5 -5
View File
@@ -5,9 +5,9 @@ Original | minified | minified | gzip | gzip | Iterations | Fi
173.90 kB | 55.50 kB | 59.82 kB | 18.77 kB | 19.33 kB | 2 | moment.js
287.63 kB | 89.01 kB | 90.07 kB | 30.85 kB | 31.95 kB | 2 | jquery.js
287.63 kB | 89.01 kB | 90.07 kB | 30.86 kB | 31.95 kB | 2 | jquery.js
342.15 kB | 114.80 kB | 118.14 kB | 42.71 kB | 44.37 kB | 2 | vue.js
342.15 kB | 114.80 kB | 118.14 kB | 42.70 kB | 44.37 kB | 2 | vue.js
544.10 kB | 69.88 kB | 72.48 kB | 25.58 kB | 26.20 kB | 2 | lodash.js
@@ -15,13 +15,13 @@ Original | minified | minified | gzip | gzip | Iterations | Fi
1.01 MB | 435.99 kB | 458.89 kB | 121.78 kB | 126.71 kB | 2 | bundle.min.js
1.25 MB | 634.39 kB | 646.76 kB | 158.43 kB | 163.73 kB | 2 | three.js
1.25 MB | 634.38 kB | 646.76 kB | 158.43 kB | 163.73 kB | 2 | three.js
2.14 MB | 707.63 kB | 724.14 kB | 160.08 kB | 181.07 kB | 2 | victory.js
3.20 MB | 958.89 kB | 1.01 MB | 317.07 kB | 331.56 kB | 2 | echarts.js
3.20 MB | 958.86 kB | 1.01 MB | 317.06 kB | 331.56 kB | 2 | echarts.js
6.69 MB | 2.12 MB | 2.31 MB | 453.42 kB | 488.28 kB | 4 | antd.js
10.95 MB | 3.31 MB | 3.49 MB | 849.96 kB | 915.50 kB | 4 | typescript.js
10.95 MB | 3.31 MB | 3.49 MB | 849.97 kB | 915.50 kB | 4 | typescript.js
@@ -5,9 +5,9 @@ checker.ts:
sys deallocs: 122
sys alloc bytes: 14996287 # 15.00 MB
sys peak growth: 10169560 # 10.17 MB
arena allocs: 56181
arena allocs: 56201
arena reallocs: 5084
arena size: 16316976 # 16.32 MB
arena size: 16317568 # 16.32 MB
App.tsx:
file size: 415342 # 415.34 kB
@@ -16,9 +16,9 @@ App.tsx:
sys deallocs: 61
sys alloc bytes: 2128539 # 2.13 MB
sys peak growth: 1612427 # 1.61 MB
arena allocs: 7451
arena allocs: 7449
arena reallocs: 920
arena size: 2683840 # 2.68 MB
arena size: 2683792 # 2.68 MB
RadixUIAdoptionSection.jsx:
file size: 2520 # 2.52 kB
@@ -38,9 +38,9 @@ pdf.mjs:
sys deallocs: 2427
sys alloc bytes: 5313795 # 5.31 MB
sys peak growth: 3693355 # 3.69 MB
arena allocs: 19497
arena allocs: 19495
arena reallocs: 2574
arena size: 5708368 # 5.71 MB
arena size: 5708304 # 5.71 MB
antd.js:
file size: 6686316 # 6.69 MB
@@ -49,9 +49,9 @@ antd.js:
sys deallocs: 860
sys alloc bytes: 29973448 # 29.97 MB
sys peak growth: 19934725 # 19.93 MB
arena allocs: 181469
arena allocs: 181463
arena reallocs: 34406
arena size: 43039576 # 43.04 MB
arena size: 43039480 # 43.04 MB
binder.ts:
file size: 193077 # 193.08 kB
@@ -73,4 +73,4 @@ kitchen-sink.tsx:
sys peak growth: 3707425 # 3.71 MB
arena allocs: 31107
arena reallocs: 3012
arena size: 8443808 # 8.44 MB
arena size: 8443456 # 8.44 MB