mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(minifier): clean up has_no_side_effect_for_evaluation_same_target (#8675)
This commit is contained in:
parent
3fa87ff6a6
commit
75a579b619
2 changed files with 23 additions and 25 deletions
|
|
@ -673,6 +673,7 @@ impl<'a, 'b> PeepholeOptimizations {
|
||||||
| "undefined"
|
| "undefined"
|
||||||
| "object"
|
| "object"
|
||||||
| "function"
|
| "function"
|
||||||
|
| "unknown" // IE
|
||||||
) {
|
) {
|
||||||
return Some(ctx.ast.expression_boolean_literal(
|
return Some(ctx.ast.expression_boolean_literal(
|
||||||
bin_expr.span,
|
bin_expr.span,
|
||||||
|
|
@ -1032,6 +1033,7 @@ mod test {
|
||||||
test("'a' == 'a'", "!0");
|
test("'a' == 'a'", "!0");
|
||||||
test("'b' != 'a'", "!0");
|
test("'b' != 'a'", "!0");
|
||||||
test_same("typeof a != 'number'");
|
test_same("typeof a != 'number'");
|
||||||
|
test_same("typeof a != 'unknown'"); // IE
|
||||||
test("'a' === 'a'", "!0");
|
test("'a' === 'a'", "!0");
|
||||||
test("'b' !== 'a'", "!0");
|
test("'b' !== 'a'", "!0");
|
||||||
test_same("'' + x <= '' + y");
|
test_same("'' + x <= '' + y");
|
||||||
|
|
|
||||||
|
|
@ -1075,16 +1075,13 @@ impl<'a> PeepholeOptimizations {
|
||||||
if self.target < ESTarget::ES2020 {
|
if self.target < ESTarget::ES2020 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Expression::AssignmentExpression(assignment_expr) = &mut expr.right else {
|
let Expression::AssignmentExpression(assignment_expr) = &mut expr.right else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
if assignment_expr.operator != AssignmentOperator::Assign {
|
if assignment_expr.operator != AssignmentOperator::Assign {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_op = expr.operator.to_assignment_operator();
|
let new_op = expr.operator.to_assignment_operator();
|
||||||
|
|
||||||
if !Self::has_no_side_effect_for_evaluation_same_target(
|
if !Self::has_no_side_effect_for_evaluation_same_target(
|
||||||
&assignment_expr.left,
|
&assignment_expr.left,
|
||||||
&expr.left,
|
&expr.left,
|
||||||
|
|
@ -1092,7 +1089,6 @@ impl<'a> PeepholeOptimizations {
|
||||||
) {
|
) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
assignment_expr.span = expr.span;
|
assignment_expr.span = expr.span;
|
||||||
assignment_expr.operator = new_op;
|
assignment_expr.operator = new_op;
|
||||||
Some(ctx.ast.move_expression(&mut expr.right))
|
Some(ctx.ast.move_expression(&mut expr.right))
|
||||||
|
|
@ -1129,37 +1125,36 @@ impl<'a> PeepholeOptimizations {
|
||||||
///
|
///
|
||||||
/// - `a`, `a`
|
/// - `a`, `a`
|
||||||
/// - `a.b`, `a.b`
|
/// - `a.b`, `a.b`
|
||||||
/// - `a.#b`, `a.#b`
|
/// - `a["b"]`, `a["b"]`
|
||||||
fn has_no_side_effect_for_evaluation_same_target(
|
fn has_no_side_effect_for_evaluation_same_target(
|
||||||
assignment_target: &AssignmentTarget,
|
assignment_target: &AssignmentTarget,
|
||||||
expr: &Expression,
|
expr: &Expression,
|
||||||
ctx: &mut TraverseCtx<'a>,
|
ctx: &mut TraverseCtx<'a>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match (&assignment_target, &expr) {
|
if let (
|
||||||
(
|
AssignmentTarget::AssignmentTargetIdentifier(write_id_ref),
|
||||||
AssignmentTarget::AssignmentTargetIdentifier(write_id_ref),
|
Expression::Identifier(read_id_ref),
|
||||||
Expression::Identifier(read_id_ref),
|
) = (assignment_target, expr)
|
||||||
) => write_id_ref.name == read_id_ref.name,
|
{
|
||||||
(
|
return write_id_ref.name == read_id_ref.name;
|
||||||
AssignmentTarget::StaticMemberExpression(_),
|
}
|
||||||
Expression::StaticMemberExpression(_),
|
if let Some(write_expr) = assignment_target.as_member_expression() {
|
||||||
)
|
if let MemberExpression::ComputedMemberExpression(e) = write_expr {
|
||||||
| (
|
if !matches!(e.expression, Expression::StringLiteral(_)) {
|
||||||
AssignmentTarget::PrivateFieldExpression(_),
|
|
||||||
Expression::PrivateFieldExpression(_),
|
|
||||||
) => {
|
|
||||||
let write_expr = assignment_target.to_member_expression();
|
|
||||||
let read_expr = expr.to_member_expression();
|
|
||||||
let Expression::Identifier(write_expr_object_id) = &write_expr.object() else {
|
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
let Expression::Identifier(write_expr_object_id) = &write_expr.object() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if let Some(read_expr) = expr.as_member_expression() {
|
||||||
// It should also return false when the reference might refer to a reference value created by a with statement
|
// It should also return false when the reference might refer to a reference value created by a with statement
|
||||||
// when the minifier supports with statements
|
// when the minifier supports with statements
|
||||||
!Ctx(ctx).is_global_reference(write_expr_object_id)
|
return !Ctx(ctx).is_global_reference(write_expr_object_id)
|
||||||
&& write_expr.content_eq(read_expr)
|
&& write_expr.content_eq(read_expr);
|
||||||
}
|
}
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compress `a = a + b` to `a += b`
|
/// Compress `a = a + b` to `a += b`
|
||||||
|
|
@ -2475,6 +2470,7 @@ mod test {
|
||||||
|
|
||||||
// GetValue(x) has no sideeffect when x is a resolved identifier
|
// GetValue(x) has no sideeffect when x is a resolved identifier
|
||||||
test("var x; x.y || (x.y = 3)", "var x; x.y ||= 3");
|
test("var x; x.y || (x.y = 3)", "var x; x.y ||= 3");
|
||||||
|
test("var x; x['y'] || (x['y'] = 3)", "var x; x.y ||= 3");
|
||||||
test("var x; x.#y || (x.#y = 3)", "var x; x.#y ||= 3");
|
test("var x; x.#y || (x.#y = 3)", "var x; x.#y ||= 3");
|
||||||
test_same("x.y || (x.y = 3)");
|
test_same("x.y || (x.y = 3)");
|
||||||
// this can be compressed if `y` does not have side effect
|
// this can be compressed if `y` does not have side effect
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue