perf(minifier): reduce usage of minimize_conditional (#26028)

`minimize_conditional_expression` is complex and long this is first step
that simplifies generation this refactor, this can be simplified further
as we should not need almost any dummy nodes in here, but for now we are
going to just reuse exsiting nodes instead of rebuilding everything
This commit is contained in:
Armano authored and GitHub committed 2026-09-29 16:38:17 +01:00
1 parent 41ffec9a81
commit 0b9799dc26
2 files changed
+45 -58

No files matched your search

@@ -51,24 +51,13 @@ impl<'a> PeepholeOptimizations {
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
match &mut expr.test {
// "(a, b) ? c : d" => "a, b ? c : d"
// `(a, b) ? c : d` => `a, b ? c : d`
Expression::SequenceExpression(sequence_expr)
if sequence_expr.expressions.len() > 1 =>
{
let span = expr.span();
let mut sequence = expr.test.take_in(ctx);
let Expression::SequenceExpression(sequence_expr) = &mut sequence else {
unreachable!()
};
let expr = Self::minimize_conditional(
span,
sequence_expr.expressions.pop().unwrap(),
expr.consequent.take_in(ctx),
expr.alternate.take_in(ctx),
ctx,
);
sequence_expr.expressions.push(expr);
return Some(sequence);
let ConditionalExpression { test, consequent, alternate, span, .. } =
expr.take_in(ctx);
return Some(Self::minimize_conditional(span, test, consequent, alternate, ctx));
}
// "!a ? b : c" => "a ? c : b"
Expression::UnaryExpression(test_expr) if test_expr.operator.is_not() => {
@@ -116,42 +105,42 @@ impl<'a> PeepholeOptimizations {
_ => {}
}
// "a ? b ? c : d : d" => "a && b ? c : d"
// `a ? b ? c : d : d` => `a && b ? c : d`
if let Expression::ConditionalExpression(consequent) = &mut expr.consequent
&& ctx.expr_eq(&consequent.alternate, &expr.alternate)
{
return Some(Expression::new_conditional_expression(
expr.span,
let cons_expr = consequent.take_in(ctx);
ctx.replace_expression_with(&mut expr.test, |expr_0, ctx| {
Self::join_with_left_associative_op(
expr.test.span(),
expr_0.span(),
LogicalOperator::And,
expr.test.take_in(ctx),
consequent.test.take_in(ctx),
expr_0,
cons_expr.test,
ctx,
),
consequent.consequent.take_in(ctx),
consequent.alternate.take_in(ctx),
ctx,
));
)
});
ctx.replace_expression(&mut expr.consequent, cons_expr.consequent);
ctx.drop_expression(&cons_expr.alternate);
return Self::minimize_conditional_expression(expr, ctx);
}
// "a ? b : c ? b : d" => "a || c ? b : d"
// `a ? b : c ? b : d` => `a || c ? b : d`
if let Expression::ConditionalExpression(alternate) = &mut expr.alternate
&& ctx.expr_eq(&alternate.consequent, &expr.consequent)
{
return Some(Expression::new_conditional_expression(
expr.span,
let alt_expr = alternate.take_in(ctx);
ctx.replace_expression_with(&mut expr.test, |expr_0, ctx| {
Self::join_with_left_associative_op(
expr.test.span(),
expr_0.span(),
LogicalOperator::Or,
expr.test.take_in(ctx),
alternate.test.take_in(ctx),
expr_0,
alt_expr.test,
ctx,
),
expr.consequent.take_in(ctx),
alternate.alternate.take_in(ctx),
ctx,
));
)
});
ctx.replace_expression(&mut expr.alternate, alt_expr.alternate);
ctx.drop_expression(&alt_expr.consequent);
return Self::minimize_conditional_expression(expr, ctx);
}
// `a ? c : (b, c)` => `(a || b), c`
@@ -213,44 +202,42 @@ impl<'a> PeepholeOptimizations {
));
}
// "a ? b || c : c" => "(a && b) || c"
// `a ? b || c : c` => `(a && b) || c`
if let Expression::LogicalExpression(logical_expr) = &mut expr.consequent
&& logical_expr.operator.is_or()
&& ctx.expr_eq(&logical_expr.right, &expr.alternate)
{
return Some(Expression::new_logical_expression(
expr.span,
let mut new_logical = logical_expr.take_in_box(ctx);
new_logical.span = expr.span();
ctx.replace_expression_with(&mut new_logical.left, |left, ctx| {
Self::join_with_left_associative_op(
expr.test.span(),
LogicalOperator::And,
expr.test.take_in(ctx),
logical_expr.left.take_in(ctx),
left,
ctx,
),
LogicalOperator::Or,
expr.alternate.take_in(ctx),
ctx,
));
)
});
return Some(Expression::LogicalExpression(new_logical));
}
// "a ? c : b && c" => "(a || b) && c"
// `a ? c : b && c` => `(a || b) && c`
if let Expression::LogicalExpression(logical_expr) = &mut expr.alternate
&& logical_expr.operator == LogicalOperator::And
&& ctx.expr_eq(&logical_expr.right, &expr.consequent)
{
return Some(Expression::new_logical_expression(
expr.span,
let mut new_logical = logical_expr.take_in_box(ctx);
new_logical.span = expr.span();
ctx.replace_expression_with(&mut new_logical.left, |left, ctx| {
Self::join_with_left_associative_op(
expr.test.span(),
LogicalOperator::Or,
expr.test.take_in(ctx),
logical_expr.left.take_in(ctx),
left,
ctx,
),
LogicalOperator::And,
expr.consequent.take_in(ctx),
ctx,
));
)
});
return Some(Expression::LogicalExpression(new_logical));
}
// `a ? b(c, d) : b(e, d)` -> `b(a ? c : e, d)`
@@ -5,7 +5,7 @@ checker.ts:
sys deallocs: 122
sys alloc bytes: 14996287 # 15.00 MB
sys peak growth: 10169560 # 10.17 MB
arena allocs: 56225
arena allocs: 56217
arena reallocs: 5084
arena size: 16317568 # 16.32 MB
@@ -16,7 +16,7 @@ App.tsx:
sys deallocs: 61
sys alloc bytes: 2128539 # 2.13 MB
sys peak growth: 1612427 # 1.61 MB
arena allocs: 7474
arena allocs: 7470
arena reallocs: 920
arena size: 2683792 # 2.68 MB
@@ -49,7 +49,7 @@ antd.js:
sys deallocs: 860
sys alloc bytes: 29973448 # 29.97 MB
sys peak growth: 19934725 # 19.93 MB
arena allocs: 181540
arena allocs: 181536
arena reallocs: 34406
arena size: 43039192 # 43.04 MB