mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(minifier): rotate associative operators to make it more idempotent (#8424)
another **massive** pain to debug ~~https://github.com/oxc-project/monitor-oxc/actions/runs/12717213600~~ https://github.com/oxc-project/monitor-oxc/actions/runs/12717978983/job/35455601146
This commit is contained in:
parent
a80460c6fe
commit
52f88c0e9c
3 changed files with 46 additions and 2 deletions
|
|
@ -515,7 +515,7 @@ impl<'a> PeepholeMinimizeConditions {
|
|||
}
|
||||
}
|
||||
|
||||
// `a ? c : b && c` -> `(a || b) && c``
|
||||
// `a ? c : b && c` -> `(a || b) && c`
|
||||
if let Expression::LogicalExpression(logical_expr) = &mut expr.alternate {
|
||||
if logical_expr.operator == LogicalOperator::And
|
||||
&& logical_expr.right.content_eq(&expr.consequent)
|
||||
|
|
|
|||
|
|
@ -149,7 +149,8 @@ impl<'a> Traverse<'a> for PeepholeSubstituteAlternateSyntax {
|
|||
Self::try_compress_assignment_to_update_expression(e, ctx)
|
||||
}
|
||||
Expression::LogicalExpression(e) => Self::try_compress_is_null_or_undefined(e, ctx)
|
||||
.or_else(|| self.try_compress_logical_expression_to_assignment_expression(e, ctx)),
|
||||
.or_else(|| self.try_compress_logical_expression_to_assignment_expression(e, ctx))
|
||||
.or_else(|| Self::try_rotate_logical_expression(e, ctx)),
|
||||
Expression::TemplateLiteral(t) => Self::try_fold_template_literal(t, ctx),
|
||||
Expression::BinaryExpression(e) => Self::try_fold_loose_equals_undefined(e, ctx)
|
||||
.or_else(|| Self::try_compress_typeof_undefined(e, ctx)),
|
||||
|
|
@ -503,6 +504,38 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax {
|
|||
Some(ctx.ast.move_expression(&mut expr.right))
|
||||
}
|
||||
|
||||
/// `a || (b || c);` -> `(a || b) || c;`
|
||||
fn try_rotate_logical_expression(
|
||||
expr: &mut LogicalExpression<'a>,
|
||||
ctx: Ctx<'a, 'b>,
|
||||
) -> Option<Expression<'a>> {
|
||||
let Expression::LogicalExpression(right) = &mut expr.right else { return None };
|
||||
if right.operator != expr.operator {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut new_left = ctx.ast.expression_logical(
|
||||
expr.span,
|
||||
ctx.ast.move_expression(&mut expr.left),
|
||||
expr.operator,
|
||||
ctx.ast.move_expression(&mut right.left),
|
||||
);
|
||||
|
||||
{
|
||||
let Expression::LogicalExpression(new_left2) = &mut new_left else { unreachable!() };
|
||||
if let Some(expr) = Self::try_rotate_logical_expression(new_left2, ctx) {
|
||||
new_left = expr;
|
||||
}
|
||||
}
|
||||
|
||||
Some(ctx.ast.expression_logical(
|
||||
expr.span,
|
||||
new_left,
|
||||
expr.operator,
|
||||
ctx.ast.move_expression(&mut right.right),
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns `true` if the assignment target and expression have no side effect for *evaluation* and points to the same reference.
|
||||
///
|
||||
/// Evaluation here means `Evaluation` in the spec.
|
||||
|
|
|
|||
|
|
@ -50,6 +50,17 @@ fn integration() {
|
|||
return console.log(e || JSON.stringify(os));
|
||||
});"#,
|
||||
);
|
||||
|
||||
test_idempotent(
|
||||
"if (!(foo instanceof Var) || open) {
|
||||
arg0 = null;
|
||||
} else if (que || !(foo && bar)) {
|
||||
if (baz()) arg0 = null;
|
||||
}",
|
||||
"(!(foo instanceof Var) || open || (que || !(foo && bar)) && baz()) && (arg0 = null);",
|
||||
);
|
||||
|
||||
test_same("a && (b && (c && (d && (e && (f && (g && (h && i && j && k && l && m && n && o && p && q && r && s && t && u && v && w && x && y && z)))))))");
|
||||
}
|
||||
|
||||
#[test] // https://github.com/oxc-project/oxc/issues/4341
|
||||
|
|
|
|||
Loading…
Reference in a new issue