diff --git a/crates/oxc_minifier/src/ast_passes/mod.rs b/crates/oxc_minifier/src/ast_passes/mod.rs index b0269f4ddd840..f9e4d9ddbbe67 100644 --- a/crates/oxc_minifier/src/ast_passes/mod.rs +++ b/crates/oxc_minifier/src/ast_passes/mod.rs @@ -42,12 +42,12 @@ pub struct PeepholeOptimizations { x1_minimize_exit_points: MinimizeExitPoints, x2_exploit_assigns: ExploitAssigns, x3_collapse_variable_declarations: CollapseVariableDeclarations, - x4_peephole_remove_dead_code: PeepholeRemoveDeadCode, - x5_peephole_minimize_conditions: PeepholeMinimizeConditions, - x6_peephole_substitute_alternate_syntax: PeepholeSubstituteAlternateSyntax, + x4_peephole_fold_constants: PeepholeFoldConstants, + x5_peephole_remove_dead_code: PeepholeRemoveDeadCode, + x6_peephole_minimize_conditions: PeepholeMinimizeConditions, x7_peephole_replace_known_methods: PeepholeReplaceKnownMethods, - x8_peephole_fold_constants: PeepholeFoldConstants, - x9_convert_to_dotted_properties: ConvertToDottedProperties, + x8_convert_to_dotted_properties: ConvertToDottedProperties, + x9_peephole_substitute_alternate_syntax: PeepholeSubstituteAlternateSyntax, } impl PeepholeOptimizations { @@ -59,15 +59,15 @@ impl PeepholeOptimizations { x1_minimize_exit_points: MinimizeExitPoints::new(), x2_exploit_assigns: ExploitAssigns::new(), x3_collapse_variable_declarations: CollapseVariableDeclarations::new(), - x4_peephole_remove_dead_code: PeepholeRemoveDeadCode::new(), - x5_peephole_minimize_conditions: PeepholeMinimizeConditions::new(), - x6_peephole_substitute_alternate_syntax: PeepholeSubstituteAlternateSyntax::new( + x4_peephole_fold_constants: PeepholeFoldConstants::new(), + x5_peephole_remove_dead_code: PeepholeRemoveDeadCode::new(), + x6_peephole_minimize_conditions: PeepholeMinimizeConditions::new(), + x7_peephole_replace_known_methods: PeepholeReplaceKnownMethods::new(), + x8_convert_to_dotted_properties: ConvertToDottedProperties::new(in_fixed_loop), + x9_peephole_substitute_alternate_syntax: PeepholeSubstituteAlternateSyntax::new( options.target, in_fixed_loop, ), - x7_peephole_replace_known_methods: PeepholeReplaceKnownMethods::new(), - x8_peephole_fold_constants: PeepholeFoldConstants::new(), - x9_convert_to_dotted_properties: ConvertToDottedProperties::new(in_fixed_loop), } } @@ -76,11 +76,11 @@ impl PeepholeOptimizations { self.x1_minimize_exit_points.changed = false; self.x2_exploit_assigns.changed = false; self.x3_collapse_variable_declarations.changed = false; - self.x4_peephole_remove_dead_code.changed = false; - self.x5_peephole_minimize_conditions.changed = false; - self.x6_peephole_substitute_alternate_syntax.changed = false; + self.x4_peephole_fold_constants.changed = false; + self.x5_peephole_remove_dead_code.changed = false; + self.x6_peephole_minimize_conditions.changed = false; self.x7_peephole_replace_known_methods.changed = false; - self.x8_peephole_fold_constants.changed = false; + self.x9_peephole_substitute_alternate_syntax.changed = false; } fn changed(&self) -> bool { @@ -88,11 +88,11 @@ impl PeepholeOptimizations { || self.x1_minimize_exit_points.changed || self.x2_exploit_assigns.changed || self.x3_collapse_variable_declarations.changed - || self.x4_peephole_remove_dead_code.changed - || self.x5_peephole_minimize_conditions.changed - || self.x6_peephole_substitute_alternate_syntax.changed + || self.x4_peephole_fold_constants.changed + || self.x5_peephole_remove_dead_code.changed + || self.x6_peephole_minimize_conditions.changed || self.x7_peephole_replace_known_methods.changed - || self.x8_peephole_fold_constants.changed + || self.x9_peephole_substitute_alternate_syntax.changed } pub fn run_in_loop<'a>( @@ -124,7 +124,7 @@ impl<'a> CompressorPass<'a> for PeepholeOptimizations { impl<'a> Traverse<'a> for PeepholeOptimizations { fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) { - self.x4_peephole_remove_dead_code.exit_program(program, ctx); + self.x5_peephole_remove_dead_code.exit_program(program, ctx); } fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { @@ -132,17 +132,17 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { self.x1_minimize_exit_points.exit_statements(stmts, ctx); self.x2_exploit_assigns.exit_statements(stmts, ctx); self.x3_collapse_variable_declarations.exit_statements(stmts, ctx); - self.x4_peephole_remove_dead_code.exit_statements(stmts, ctx); - self.x5_peephole_minimize_conditions.exit_statements(stmts, ctx); + self.x5_peephole_remove_dead_code.exit_statements(stmts, ctx); + self.x6_peephole_minimize_conditions.exit_statements(stmts, ctx); } fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { - self.x4_peephole_remove_dead_code.exit_statement(stmt, ctx); - self.x5_peephole_minimize_conditions.exit_statement(stmt, ctx); + self.x5_peephole_remove_dead_code.exit_statement(stmt, ctx); + self.x6_peephole_minimize_conditions.exit_statement(stmt, ctx); } fn exit_return_statement(&mut self, stmt: &mut ReturnStatement<'a>, ctx: &mut TraverseCtx<'a>) { - self.x6_peephole_substitute_alternate_syntax.exit_return_statement(stmt, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_return_statement(stmt, ctx); } fn exit_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) { @@ -154,23 +154,23 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { decl: &mut VariableDeclaration<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.x6_peephole_substitute_alternate_syntax.exit_variable_declaration(decl, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_variable_declaration(decl, ctx); } fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - self.x4_peephole_remove_dead_code.exit_expression(expr, ctx); - self.x5_peephole_minimize_conditions.exit_expression(expr, ctx); - self.x6_peephole_substitute_alternate_syntax.exit_expression(expr, ctx); + self.x4_peephole_fold_constants.exit_expression(expr, ctx); + self.x5_peephole_remove_dead_code.exit_expression(expr, ctx); + self.x6_peephole_minimize_conditions.exit_expression(expr, ctx); self.x7_peephole_replace_known_methods.exit_expression(expr, ctx); - self.x8_peephole_fold_constants.exit_expression(expr, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_expression(expr, ctx); } fn enter_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) { - self.x6_peephole_substitute_alternate_syntax.enter_call_expression(expr, ctx); + self.x9_peephole_substitute_alternate_syntax.enter_call_expression(expr, ctx); } fn exit_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) { - self.x6_peephole_substitute_alternate_syntax.exit_call_expression(expr, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_call_expression(expr, ctx); } fn exit_member_expression( @@ -178,11 +178,11 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { expr: &mut MemberExpression<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.x9_convert_to_dotted_properties.exit_member_expression(expr, ctx); + self.x8_convert_to_dotted_properties.exit_member_expression(expr, ctx); } fn exit_object_property(&mut self, prop: &mut ObjectProperty<'a>, ctx: &mut TraverseCtx<'a>) { - self.x6_peephole_substitute_alternate_syntax.exit_object_property(prop, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_object_property(prop, ctx); } fn exit_assignment_target_property_property( @@ -190,12 +190,12 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { prop: &mut AssignmentTargetPropertyProperty<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.x6_peephole_substitute_alternate_syntax + self.x9_peephole_substitute_alternate_syntax .exit_assignment_target_property_property(prop, ctx); } fn exit_binding_property(&mut self, prop: &mut BindingProperty<'a>, ctx: &mut TraverseCtx<'a>) { - self.x6_peephole_substitute_alternate_syntax.exit_binding_property(prop, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_binding_property(prop, ctx); } fn exit_method_definition( @@ -203,7 +203,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { prop: &mut MethodDefinition<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.x6_peephole_substitute_alternate_syntax.exit_method_definition(prop, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_method_definition(prop, ctx); } fn exit_property_definition( @@ -211,7 +211,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { prop: &mut PropertyDefinition<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.x6_peephole_substitute_alternate_syntax.exit_property_definition(prop, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_property_definition(prop, ctx); } fn exit_accessor_property( @@ -219,11 +219,11 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { prop: &mut AccessorProperty<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.x6_peephole_substitute_alternate_syntax.exit_accessor_property(prop, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_accessor_property(prop, ctx); } fn exit_catch_clause(&mut self, catch: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) { - self.x6_peephole_substitute_alternate_syntax.exit_catch_clause(catch, ctx); + self.x9_peephole_substitute_alternate_syntax.exit_catch_clause(catch, ctx); } } diff --git a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs index c04c201f40fbf..2ddeae9fb5ea8 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs @@ -140,8 +140,6 @@ impl<'a> Traverse<'a> for PeepholeSubstituteAlternateSyntax { // Fold if let Some(folded_expr) = match expr { - Expression::Identifier(ident) => self.try_compress_undefined(ident, ctx), - Expression::BooleanLiteral(_) => self.try_compress_boolean(expr, ctx), Expression::AssignmentExpression(e) => { Self::try_compress_assignment_to_update_expression(e, ctx) } @@ -168,6 +166,20 @@ impl<'a> Traverse<'a> for PeepholeSubstituteAlternateSyntax { *expr = folded_expr; self.changed = true; } + + // Out of fixed loop syntax changes happen last. + if self.in_fixed_loop { + return; + } + + if let Some(folded_expr) = match expr { + Expression::Identifier(ident) => self.try_compress_undefined(ident, ctx), + Expression::BooleanLiteral(_) => self.try_compress_boolean(expr, ctx), + _ => None, + } { + *expr = folded_expr; + self.changed = true; + } } } @@ -224,9 +236,7 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { ident: &IdentifierReference<'a>, ctx: Ctx<'a, 'b>, ) -> Option> { - if self.in_fixed_loop { - return None; - } + debug_assert!(!self.in_fixed_loop); if !ctx.is_identifier_undefined(ident) { return None; } @@ -240,9 +250,7 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { expr: &mut Expression<'a>, ctx: Ctx<'a, 'b>, ) -> Option> { - if self.in_fixed_loop { - return None; - } + debug_assert!(!self.in_fixed_loop); let Expression::BooleanLiteral(lit) = expr else { return None }; if self.in_define_export { return None; @@ -1016,9 +1024,6 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { computed: &mut bool, ctx: &mut TraverseCtx<'a>, ) { - if self.in_fixed_loop { - return; - } if let PropertyKey::NumericLiteral(_) = key { if *computed { *computed = false; @@ -1817,7 +1822,7 @@ mod test { // Don't fold the existence check to preserve behavior test_same("var a = Boolean?.({})"); - test("var a = Boolean()", "var a = false;"); + test("var a = Boolean()", "var a = !1;"); test_same("var a = Boolean(!0, !1);"); }