diff --git a/crates/oxc_minifier/src/peephole/collapse_variable_declarations.rs b/crates/oxc_minifier/src/peephole/collapse_variable_declarations.rs index 8866fe61d..a70a59f71 100644 --- a/crates/oxc_minifier/src/peephole/collapse_variable_declarations.rs +++ b/crates/oxc_minifier/src/peephole/collapse_variable_declarations.rs @@ -1,6 +1,7 @@ use oxc_allocator::Vec; use oxc_ast::ast::*; -use oxc_traverse::TraverseCtx; + +use crate::ctx::Ctx; use super::PeepholeOptimizations; @@ -17,7 +18,7 @@ impl<'a> PeepholeOptimizations { pub fn collapse_variable_declarations( &mut self, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.join_vars(stmts, ctx); self.maybe_collapse_into_for_statements(stmts, ctx); @@ -44,7 +45,7 @@ impl<'a> PeepholeOptimizations { None } - fn join_vars(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { + fn join_vars(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: Ctx<'a, '_>) { if stmts.len() < 2 { return; } @@ -102,7 +103,7 @@ impl<'a> PeepholeOptimizations { fn maybe_collapse_into_for_statements( &mut self, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { if stmts.len() <= 1 { return; @@ -142,7 +143,7 @@ impl<'a> PeepholeOptimizations { &mut self, i: usize, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { if let Statement::ExpressionStatement(expr_stmt) = ctx.ast.move_statement(&mut stmts[i]) { if let Statement::ForStatement(for_stmt) = &mut stmts[i + 1] { @@ -156,7 +157,7 @@ impl<'a> PeepholeOptimizations { &mut self, i: usize, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { if let Statement::VariableDeclaration(var) = ctx.ast.move_statement(&mut stmts[i]) { if let Statement::ForStatement(for_stmt) = &mut stmts[i + 1] { @@ -181,7 +182,7 @@ impl<'a> PeepholeOptimizations { &mut self, i: usize, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { if let Statement::VariableDeclaration(decl) = &stmts[i] { if decl.kind.is_var() diff --git a/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs b/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs index 2e617b645..c12e58b4e 100644 --- a/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs +++ b/crates/oxc_minifier/src/peephole/convert_to_dotted_properties.rs @@ -1,9 +1,9 @@ use oxc_ast::ast::*; use oxc_syntax::identifier::is_identifier_name; -use oxc_traverse::TraverseCtx; + +use crate::ctx::Ctx; use super::LatePeepholeOptimizations; -use crate::ctx::Ctx; impl<'a> LatePeepholeOptimizations { /// Converts property accesses from quoted string or bracket access syntax to dot or unquoted string @@ -13,10 +13,7 @@ impl<'a> LatePeepholeOptimizations { /// /// `foo['bar']` -> `foo.bar` /// `foo?.['bar']` -> `foo?.bar` - pub fn convert_to_dotted_properties( - expr: &mut MemberExpression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + pub fn convert_to_dotted_properties(expr: &mut MemberExpression<'a>, ctx: Ctx<'a, '_>) { let MemberExpression::ComputedMemberExpression(e) = expr else { return }; let Expression::StringLiteral(s) = &e.expression else { return }; if is_identifier_name(&s.value) { @@ -32,8 +29,7 @@ impl<'a> LatePeepholeOptimizations { return; } if let Some(n) = Ctx::string_to_equivalent_number_value(v) { - e.expression = - Ctx(ctx).ast.expression_numeric_literal(s.span, n, None, NumberBase::Decimal); + e.expression = ctx.ast.expression_numeric_literal(s.span, n, None, NumberBase::Decimal); } } } diff --git a/crates/oxc_minifier/src/peephole/fold_constants.rs b/crates/oxc_minifier/src/peephole/fold_constants.rs index e2685dae3..b1a3fa763 100644 --- a/crates/oxc_minifier/src/peephole/fold_constants.rs +++ b/crates/oxc_minifier/src/peephole/fold_constants.rs @@ -8,7 +8,7 @@ use oxc_syntax::{ number::NumberBase, operator::{BinaryOperator, LogicalOperator}, }; -use oxc_traverse::{Ancestor, TraverseCtx}; +use oxc_traverse::Ancestor; use crate::ctx::Ctx; @@ -18,12 +18,7 @@ impl<'a, 'b> PeepholeOptimizations { /// Constant Folding /// /// - pub fn fold_constants_exit_expression( - &mut self, - expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { - let ctx = Ctx(ctx); + pub fn fold_constants_exit_expression(&mut self, expr: &mut Expression<'a>, ctx: Ctx<'a, '_>) { if let Some(folded_expr) = match expr { Expression::BinaryExpression(e) => Self::try_fold_binary_expr(e, ctx) .or_else(|| Self::try_fold_binary_typeof_comparison(e, ctx)), diff --git a/crates/oxc_minifier/src/peephole/minimize_conditions.rs b/crates/oxc_minifier/src/peephole/minimize_conditions.rs index 4bb524852..c46372a91 100644 --- a/crates/oxc_minifier/src/peephole/minimize_conditions.rs +++ b/crates/oxc_minifier/src/peephole/minimize_conditions.rs @@ -7,7 +7,7 @@ use oxc_ecmascript::{ }; use oxc_span::{cmp::ContentEq, GetSpan}; use oxc_syntax::es_target::ESTarget; -use oxc_traverse::{Ancestor, TraverseCtx}; +use oxc_traverse::Ancestor; use crate::ctx::Ctx; @@ -24,7 +24,7 @@ impl<'a> PeepholeOptimizations { pub fn minimize_conditions_exit_statements( &mut self, stmts: &mut oxc_allocator::Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { let mut changed = false; loop { @@ -45,7 +45,7 @@ impl<'a> PeepholeOptimizations { pub fn minimize_conditions_exit_statement( &mut self, stmt: &mut Statement<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { let expr = match stmt { Statement::IfStatement(s) => Some(&mut s.test), @@ -80,7 +80,7 @@ impl<'a> PeepholeOptimizations { pub fn minimize_conditions_exit_expression( &mut self, expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { let mut changed = false; loop { @@ -123,7 +123,7 @@ impl<'a> PeepholeOptimizations { } } - fn minimize_not(span: Span, expr: Expression<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + fn minimize_not(span: Span, expr: Expression<'a>, ctx: Ctx<'a, '_>) -> Expression<'a> { let mut unary = ctx.ast.unary_expression(span, UnaryOperator::LogicalNot, expr); Self::try_minimize_not(&mut unary, ctx) .unwrap_or_else(|| Expression::UnaryExpression(ctx.ast.alloc(unary))) @@ -131,7 +131,7 @@ impl<'a> PeepholeOptimizations { fn try_minimize_not( expr: &mut UnaryExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { if !expr.operator.is_not() { return None; @@ -159,10 +159,7 @@ impl<'a> PeepholeOptimizations { } } - fn try_minimize_if( - stmt: &mut Statement<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> Option> { + fn try_minimize_if(stmt: &mut Statement<'a>, ctx: Ctx<'a, '_>) -> Option> { let Statement::IfStatement(if_stmt) = stmt else { unreachable!() }; // `if (x) foo()` -> `x && foo()` @@ -276,7 +273,7 @@ impl<'a> PeepholeOptimizations { &mut self, stmts: &mut Vec<'a, Statement<'a>>, changed: &mut bool, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { for i in 0..stmts.len() { let Statement::IfStatement(if_stmt) = &stmts[i] else { @@ -328,7 +325,7 @@ impl<'a> PeepholeOptimizations { matches!(stmt.get_one_child(), Some(Statement::ExpressionStatement(_))) } - fn get_block_expression(stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + fn get_block_expression(stmt: &mut Statement<'a>, ctx: Ctx<'a, '_>) -> Expression<'a> { let Some(Statement::ExpressionStatement(s)) = stmt.get_one_child_mut() else { unreachable!() }; @@ -353,15 +350,12 @@ impl<'a> PeepholeOptimizations { } } - fn get_block_return_expression( - stmt: &mut Statement<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> Expression<'a> { + fn get_block_return_expression(stmt: &mut Statement<'a>, ctx: Ctx<'a, '_>) -> Expression<'a> { let Some(stmt) = stmt.get_one_child_mut() else { unreachable!() }; Self::take_return_argument(stmt, ctx) } - fn take_return_argument(stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + fn take_return_argument(stmt: &mut Statement<'a>, ctx: Ctx<'a, '_>) -> Expression<'a> { let Statement::ReturnStatement(return_stmt) = ctx.ast.move_statement(stmt) else { unreachable!() }; @@ -377,7 +371,7 @@ impl<'a> PeepholeOptimizations { test: Expression<'a>, consequent: Expression<'a>, alternate: Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Expression<'a> { let mut cond_expr = ctx.ast.conditional_expression(span, test, consequent, alternate); Self::try_minimize_conditional(&mut cond_expr, ctx) @@ -387,7 +381,7 @@ impl<'a> PeepholeOptimizations { // fn try_minimize_conditional( expr: &mut ConditionalExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { match &mut expr.test { // "(a, b) ? c : d" => "a, b ? c : d" @@ -484,7 +478,7 @@ impl<'a> PeepholeOptimizations { // "a ? b ? c : d : d" => "a && b ? c : d" if let Expression::ConditionalExpression(consequent) = &mut expr.consequent { - if Ctx(ctx).expr_eq(&consequent.alternate, &expr.alternate) { + if ctx.expr_eq(&consequent.alternate, &expr.alternate) { return Some(ctx.ast.expression_conditional( expr.span, ctx.ast.expression_logical( @@ -501,7 +495,7 @@ impl<'a> PeepholeOptimizations { // "a ? b : c ? b : d" => "a || c ? b : d" if let Expression::ConditionalExpression(alternate) = &mut expr.alternate { - if Ctx(ctx).expr_eq(&alternate.consequent, &expr.consequent) { + if ctx.expr_eq(&alternate.consequent, &expr.consequent) { return Some(ctx.ast.expression_conditional( expr.span, ctx.ast.expression_logical( @@ -519,7 +513,7 @@ impl<'a> PeepholeOptimizations { // "a ? c : (b, c)" => "(a || b), c" if let Expression::SequenceExpression(alternate) = &mut expr.alternate { if alternate.expressions.len() == 2 - && Ctx(ctx).expr_eq(&alternate.expressions[1], &expr.consequent) + && ctx.expr_eq(&alternate.expressions[1], &expr.consequent) { return Some(ctx.ast.expression_sequence( expr.span, @@ -539,7 +533,7 @@ impl<'a> PeepholeOptimizations { // "a ? (b, c) : c" => "(a && b), c" if let Expression::SequenceExpression(consequent) = &mut expr.consequent { if consequent.expressions.len() == 2 - && Ctx(ctx).expr_eq(&consequent.expressions[1], &expr.alternate) + && ctx.expr_eq(&consequent.expressions[1], &expr.alternate) { return Some(ctx.ast.expression_sequence( expr.span, @@ -559,7 +553,7 @@ impl<'a> PeepholeOptimizations { // "a ? b || c : c" => "(a && b) || c" if let Expression::LogicalExpression(logical_expr) = &mut expr.consequent { if logical_expr.operator == LogicalOperator::Or - && Ctx(ctx).expr_eq(&logical_expr.right, &expr.alternate) + && ctx.expr_eq(&logical_expr.right, &expr.alternate) { return Some(ctx.ast.expression_logical( expr.span, @@ -578,7 +572,7 @@ impl<'a> PeepholeOptimizations { // "a ? c : b && c" => "(a || b) && c" if let Expression::LogicalExpression(logical_expr) = &mut expr.alternate { if logical_expr.operator == LogicalOperator::And - && Ctx(ctx).expr_eq(&logical_expr.right, &expr.consequent) + && ctx.expr_eq(&logical_expr.right, &expr.consequent) { return Some(ctx.ast.expression_logical( expr.span, @@ -602,8 +596,8 @@ impl<'a> PeepholeOptimizations { ) = (&expr.test, &mut expr.consequent, &mut expr.alternate) { if consequent.arguments.len() == alternate.arguments.len() - && !Ctx(ctx).is_global_reference(test) - && Ctx(ctx).expr_eq(&consequent.callee, &alternate.callee) + && !ctx.is_global_reference(test) + && ctx.expr_eq(&consequent.callee, &alternate.callee) && consequent .arguments .iter() @@ -671,7 +665,7 @@ impl<'a> PeepholeOptimizations { // TODO: Try using the "??" or "?." operators - if Ctx(ctx).expr_eq(&expr.alternate, &expr.consequent) { + if ctx.expr_eq(&expr.alternate, &expr.consequent) { // TODO: // "/* @__PURE__ */ a() ? b : b" => "b" // if ctx.ExprCanBeRemovedIfUnused(test) { @@ -694,7 +688,7 @@ impl<'a> PeepholeOptimizations { /// - `x ? a = 0 : a = 1` -> `a = x ? 0 : 1` fn try_merge_conditional_expression_inside( expr: &mut ConditionalExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let ( Expression::AssignmentExpression(consequent), @@ -733,10 +727,7 @@ impl<'a> PeepholeOptimizations { /// Simplify syntax when we know it's used inside a boolean context, e.g. `if (boolean_context) {}`. /// /// - fn try_fold_expr_in_boolean_context( - expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> bool { + fn try_fold_expr_in_boolean_context(expr: &mut Expression<'a>, ctx: Ctx<'a, '_>) -> bool { match expr { // "!!a" => "a" Expression::UnaryExpression(u1) if u1.operator.is_not() => { @@ -772,7 +763,7 @@ impl<'a> PeepholeOptimizations { Self::try_fold_expr_in_boolean_context(&mut e.left, ctx); Self::try_fold_expr_in_boolean_context(&mut e.right, ctx); // "if (anything && truthyNoSideEffects)" => "if (anything)" - if Ctx(ctx).get_side_free_boolean_value(&e.right) == Some(true) { + if ctx.get_side_free_boolean_value(&e.right) == Some(true) { *expr = ctx.ast.move_expression(&mut e.left); return true; } @@ -782,7 +773,7 @@ impl<'a> PeepholeOptimizations { Self::try_fold_expr_in_boolean_context(&mut e.left, ctx); Self::try_fold_expr_in_boolean_context(&mut e.right, ctx); // "if (anything || falsyNoSideEffects)" => "if (anything)" - if Ctx(ctx).get_side_free_boolean_value(&e.right) == Some(false) { + if ctx.get_side_free_boolean_value(&e.right) == Some(false) { *expr = ctx.ast.move_expression(&mut e.left); return true; } @@ -791,7 +782,7 @@ impl<'a> PeepholeOptimizations { // "if (a ? !!b : !!c)" => "if (a ? b : c)" Self::try_fold_expr_in_boolean_context(&mut e.consequent, ctx); Self::try_fold_expr_in_boolean_context(&mut e.alternate, ctx); - if let Some(boolean) = Ctx(ctx).get_side_free_boolean_value(&e.consequent) { + if let Some(boolean) = ctx.get_side_free_boolean_value(&e.consequent) { let right = ctx.ast.move_expression(&mut e.alternate); let left = ctx.ast.move_expression(&mut e.test); if boolean { @@ -806,7 +797,7 @@ impl<'a> PeepholeOptimizations { } return true; } - if let Some(boolean) = Ctx(ctx).get_side_free_boolean_value(&e.alternate) { + if let Some(boolean) = ctx.get_side_free_boolean_value(&e.alternate) { let left = ctx.ast.move_expression(&mut e.test); let right = ctx.ast.move_expression(&mut e.consequent); if boolean { @@ -836,7 +827,7 @@ impl<'a> PeepholeOptimizations { // ^^^^^^ ValueType::from(&e.left).is_number()` is `true`. fn try_minimize_binary( e: &mut BinaryExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { if !e.operator.is_equality() { return None; @@ -895,7 +886,7 @@ impl<'a> PeepholeOptimizations { /// - `document.all == null` is `true` fn try_compress_is_null_or_undefined( expr: &mut LogicalExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let op = expr.operator; let target_ops = match op { @@ -941,7 +932,7 @@ impl<'a> PeepholeOptimizations { right: &mut Expression<'a>, span: Span, (find_op, replace_op): (BinaryOperator, BinaryOperator), - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { enum LeftPairValueResult { Null(Span), @@ -1032,7 +1023,7 @@ impl<'a> PeepholeOptimizations { fn try_compress_normal_assignment_to_combined_logical_assignment( &mut self, expr: &mut AssignmentExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> bool { if self.target < ESTarget::ES2020 { return false; @@ -1053,7 +1044,7 @@ impl<'a> PeepholeOptimizations { }; // It should also early return when the reference might refer to a reference value created by a with statement // when the minifier supports with statements - if write_id_ref.name != read_id_ref.name || Ctx(ctx).is_global_reference(write_id_ref) { + if write_id_ref.name != read_id_ref.name || ctx.is_global_reference(write_id_ref) { return false; } @@ -1066,7 +1057,7 @@ impl<'a> PeepholeOptimizations { fn try_compress_logical_expression_to_assignment_expression( &self, expr: &mut LogicalExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { if self.target < ESTarget::ES2020 { return None; @@ -1093,7 +1084,7 @@ impl<'a> PeepholeOptimizations { /// Compress `a = a + b` to `a += b` fn try_compress_normal_assignment_to_combined_assignment( expr: &mut AssignmentExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> bool { if !matches!(expr.operator, AssignmentOperator::Assign) { return false; @@ -1125,7 +1116,7 @@ impl<'a> PeepholeOptimizations { fn has_no_side_effect_for_evaluation_same_target( assignment_target: &AssignmentTarget, expr: &Expression, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> bool { if let ( AssignmentTarget::AssignmentTargetIdentifier(write_id_ref), @@ -1146,7 +1137,7 @@ impl<'a> PeepholeOptimizations { 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 // when the minifier supports with statements - return !Ctx(ctx).is_global_reference(write_expr_object_id) + return !ctx.is_global_reference(write_expr_object_id) && write_expr.content_eq(read_expr); } } @@ -1156,7 +1147,7 @@ impl<'a> PeepholeOptimizations { /// Compress `a = a + b` to `a += b` fn try_compress_assignment_to_update_expression( expr: &mut AssignmentExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let target = expr.left.as_simple_assignment_target_mut()?; if !matches!(expr.operator, AssignmentOperator::Subtraction) { diff --git a/crates/oxc_minifier/src/peephole/minimize_exit_points.rs b/crates/oxc_minifier/src/peephole/minimize_exit_points.rs index 11a4da244..8d324d954 100644 --- a/crates/oxc_minifier/src/peephole/minimize_exit_points.rs +++ b/crates/oxc_minifier/src/peephole/minimize_exit_points.rs @@ -1,6 +1,7 @@ use oxc_allocator::Vec; use oxc_ast::ast::*; -use oxc_traverse::TraverseCtx; + +use crate::ctx::Ctx; use super::PeepholeOptimizations; @@ -9,11 +10,7 @@ impl<'a> PeepholeOptimizations { /// are minimized and instead flows to implicit exits conditions. /// /// - pub fn minimize_exit_points( - &mut self, - body: &mut FunctionBody<'_>, - _ctx: &mut TraverseCtx<'_>, - ) { + pub fn minimize_exit_points(&mut self, body: &mut FunctionBody<'_>, _ctx: Ctx<'a, '_>) { self.remove_last_return(&mut body.statements); } diff --git a/crates/oxc_minifier/src/peephole/mod.rs b/crates/oxc_minifier/src/peephole/mod.rs index 303d65b0e..a8558c03f 100644 --- a/crates/oxc_minifier/src/peephole/mod.rs +++ b/crates/oxc_minifier/src/peephole/mod.rs @@ -9,14 +9,17 @@ mod replace_known_methods; mod statement_fusion; mod substitute_alternate_syntax; +use rustc_hash::FxHashSet; + use oxc_allocator::Vec; use oxc_ast::ast::*; use oxc_data_structures::stack::NonEmptyStack; use oxc_syntax::{es_target::ESTarget, scope::ScopeId}; use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx}; -pub use normalize::{Normalize, NormalizeOptions}; -use rustc_hash::FxHashSet; +use crate::ctx::Ctx; + +pub use self::normalize::{Normalize, NormalizeOptions}; pub struct PeepholeOptimizations { target: ESTarget, @@ -138,6 +141,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.statement_fusion_exit_statements(stmts, ctx); self.collapse_variable_declarations(stmts, ctx); self.minimize_conditions_exit_statements(stmts, ctx); @@ -148,6 +152,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.minimize_conditions_exit_statement(stmt, ctx); self.remove_dead_code_exit_statement(stmt, ctx); } @@ -156,6 +161,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_return_statement(stmt, ctx); } @@ -163,6 +169,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.minimize_exit_points(body, ctx); } @@ -174,6 +181,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_variable_declaration(decl, ctx); } @@ -181,6 +189,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.fold_constants_exit_expression(expr, ctx); self.minimize_conditions_exit_expression(expr, ctx); self.remove_dead_code_exit_expression(expr, ctx); @@ -192,6 +201,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_call_expression(expr, ctx); } @@ -199,6 +209,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_object_property(prop, ctx); } @@ -210,6 +221,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_assignment_target_property_property(prop, ctx); } @@ -217,6 +229,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_binding_property(prop, ctx); } @@ -228,6 +241,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_method_definition(prop, ctx); } @@ -239,6 +253,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_property_definition(prop, ctx); } @@ -250,6 +265,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { if !self.is_prev_function_changed() { return; } + let ctx = Ctx(ctx); self.substitute_accessor_property(prop, ctx); } } @@ -276,19 +292,19 @@ impl<'a> Traverse<'a> for LatePeepholeOptimizations { expr: &mut MemberExpression<'a>, ctx: &mut TraverseCtx<'a>, ) { - Self::convert_to_dotted_properties(expr, ctx); + Self::convert_to_dotted_properties(expr, Ctx(ctx)); } fn exit_class_body(&mut self, body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) { - Self::remove_dead_code_exit_class_body(body, ctx); + Self::remove_dead_code_exit_class_body(body, Ctx(ctx)); } fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - Self::substitute_exit_expression(expr, ctx); + Self::substitute_exit_expression(expr, Ctx(ctx)); } fn exit_catch_clause(&mut self, catch: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) { - self.substitute_catch_clause(catch, ctx); + self.substitute_catch_clause(catch, Ctx(ctx)); } } @@ -308,15 +324,15 @@ impl<'a> DeadCodeElimination { impl<'a> Traverse<'a> for DeadCodeElimination { fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { - self.inner.remove_dead_code_exit_statement(stmt, ctx); + self.inner.remove_dead_code_exit_statement(stmt, Ctx(ctx)); } fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { - self.inner.remove_dead_code_exit_statements(stmts, ctx); + self.inner.remove_dead_code_exit_statements(stmts, Ctx(ctx)); } fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { - self.inner.fold_constants_exit_expression(expr, ctx); - self.inner.remove_dead_code_exit_expression(expr, ctx); + self.inner.fold_constants_exit_expression(expr, Ctx(ctx)); + self.inner.remove_dead_code_exit_expression(expr, Ctx(ctx)); } } diff --git a/crates/oxc_minifier/src/peephole/remove_dead_code.rs b/crates/oxc_minifier/src/peephole/remove_dead_code.rs index d6105558f..f7906cd76 100644 --- a/crates/oxc_minifier/src/peephole/remove_dead_code.rs +++ b/crates/oxc_minifier/src/peephole/remove_dead_code.rs @@ -5,7 +5,7 @@ use oxc_ecmascript::{ side_effects::MayHaveSideEffects, }; use oxc_span::GetSpan; -use oxc_traverse::{Ancestor, TraverseCtx}; +use oxc_traverse::Ancestor; use crate::{ctx::Ctx, keep_var::KeepVar}; @@ -21,20 +21,15 @@ impl<'a, 'b> PeepholeOptimizations { pub fn remove_dead_code_exit_statements( &mut self, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { if stmts.iter().any(|stmt| matches!(stmt, Statement::EmptyStatement(_))) { stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_))); } - self.dead_code_elimination(stmts, Ctx(ctx)); + self.dead_code_elimination(stmts, ctx); } - pub fn remove_dead_code_exit_statement( - &mut self, - stmt: &mut Statement<'a>, - ctx: &mut TraverseCtx<'a>, - ) { - let ctx = Ctx(ctx); + pub fn remove_dead_code_exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: Ctx<'a, '_>) { if let Some(new_stmt) = match stmt { Statement::BlockStatement(s) => Self::try_optimize_block(s, ctx), Statement::IfStatement(s) => self.try_fold_if(s, ctx), @@ -59,9 +54,8 @@ impl<'a, 'b> PeepholeOptimizations { pub fn remove_dead_code_exit_expression( &mut self, expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { - let ctx = Ctx(ctx); if let Some(folded_expr) = match expr { Expression::ConditionalExpression(e) => Self::try_fold_conditional_expression(e, ctx), Expression::SequenceExpression(sequence_expression) => { @@ -578,7 +572,7 @@ impl<'a, 'b> PeepholeOptimizations { } impl<'a> LatePeepholeOptimizations { - pub fn remove_dead_code_exit_class_body(body: &mut ClassBody<'a>, _ctx: &mut TraverseCtx<'a>) { + pub fn remove_dead_code_exit_class_body(body: &mut ClassBody<'a>, _ctx: Ctx<'a, '_>) { body.body.retain(|e| !matches!(e, ClassElement::StaticBlock(s) if s.body.is_empty())); } } diff --git a/crates/oxc_minifier/src/peephole/replace_known_methods.rs b/crates/oxc_minifier/src/peephole/replace_known_methods.rs index f5cf175a9..63c1cf3f7 100644 --- a/crates/oxc_minifier/src/peephole/replace_known_methods.rs +++ b/crates/oxc_minifier/src/peephole/replace_known_methods.rs @@ -9,7 +9,7 @@ use oxc_ecmascript::{ }; use oxc_span::SPAN; use oxc_syntax::es_target::ESTarget; -use oxc_traverse::{Ancestor, TraverseCtx}; +use oxc_traverse::Ancestor; use crate::ctx::Ctx; @@ -21,18 +21,14 @@ impl<'a> PeepholeOptimizations { pub fn replace_known_methods_exit_expression( &mut self, node: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.try_fold_concat_chain(node, ctx); self.try_fold_known_string_methods(node, ctx); self.try_fold_known_property_access(node, ctx); } - fn try_fold_known_string_methods( - &mut self, - node: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + fn try_fold_known_string_methods(&mut self, node: &mut Expression<'a>, ctx: Ctx<'a, '_>) { let Expression::CallExpression(ce) = node else { return }; let (name, object) = match &ce.callee { Expression::StaticMemberExpression(member) if !member.optional => { @@ -70,7 +66,7 @@ impl<'a> PeepholeOptimizations { ce: &CallExpression<'a>, name: &str, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { if ce.arguments.len() >= 1 { return None; @@ -89,7 +85,7 @@ impl<'a> PeepholeOptimizations { ce: &CallExpression<'a>, name: &str, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let args = &ce.arguments; if args.len() >= 3 { @@ -118,7 +114,7 @@ impl<'a> PeepholeOptimizations { fn try_fold_string_substring_or_slice( ce: &CallExpression<'a>, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let args = &ce.arguments; if args.len() > 2 { @@ -127,11 +123,11 @@ impl<'a> PeepholeOptimizations { let Expression::StringLiteral(s) = object else { return None }; let start_idx = args.first().and_then(|arg| match arg { Argument::SpreadElement(_) => None, - _ => Ctx(ctx).get_side_free_number_value(arg.to_expression()), + _ => ctx.get_side_free_number_value(arg.to_expression()), }); let end_idx = args.get(1).and_then(|arg| match arg { Argument::SpreadElement(_) => None, - _ => Ctx(ctx).get_side_free_number_value(arg.to_expression()), + _ => ctx.get_side_free_number_value(arg.to_expression()), }); #[expect(clippy::cast_precision_loss)] if start_idx.is_some_and(|start| start > s.value.len() as f64 || start < 0.0) @@ -154,7 +150,7 @@ impl<'a> PeepholeOptimizations { fn try_fold_string_char_at( ce: &CallExpression<'a>, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let args = &ce.arguments; if args.len() > 1 { @@ -183,13 +179,13 @@ impl<'a> PeepholeOptimizations { fn try_fold_string_char_code_at( ce: &CallExpression<'a>, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let Expression::StringLiteral(s) = object else { return None }; let char_at_index = match ce.arguments.first() { None => Some(0.0), Some(Argument::SpreadElement(_)) => None, - Some(e) => Ctx(ctx).get_side_free_number_value(e.to_expression()), + Some(e) => ctx.get_side_free_number_value(e.to_expression()), }?; let value = if (0.0..65536.0).contains(&char_at_index) { s.value.as_str().char_code_at(Some(char_at_index))? as f64 @@ -205,7 +201,7 @@ impl<'a> PeepholeOptimizations { ce: &CallExpression<'a>, name: &str, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { if ce.arguments.len() != 2 { return None; @@ -216,14 +212,14 @@ impl<'a> PeepholeOptimizations { let search_value = match search_value { Argument::SpreadElement(_) => return None, match_expression!(Argument) => { - Ctx(ctx).get_side_free_string_value(search_value.to_expression())? + ctx.get_side_free_string_value(search_value.to_expression())? } }; let replace_value = ce.arguments.get(1).unwrap(); let replace_value = match replace_value { Argument::SpreadElement(_) => return None, match_expression!(Argument) => { - Ctx(ctx).get_side_free_string_value(replace_value.to_expression())? + ctx.get_side_free_string_value(replace_value.to_expression())? } }; if replace_value.contains('$') { @@ -241,10 +237,9 @@ impl<'a> PeepholeOptimizations { fn try_fold_string_from_char_code( ce: &CallExpression<'a>, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let Expression::Identifier(ident) = object else { return None }; - let ctx = Ctx(ctx); if ident.name != "String" || !ctx.is_global_reference(ident) { return None; } @@ -269,7 +264,7 @@ impl<'a> PeepholeOptimizations { fn try_fold_to_string( ce: &CallExpression<'a>, object: &Expression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) -> Option> { let args = &ce.arguments; match object { @@ -335,7 +330,7 @@ impl<'a> PeepholeOptimizations { /// `[].concat(a).concat(b)` -> `[].concat(a, b)` /// `"".concat(a).concat(b)` -> `"".concat(a, b)` - fn try_fold_concat_chain(&mut self, node: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + fn try_fold_concat_chain(&mut self, node: &mut Expression<'a>, ctx: Ctx<'a, '_>) { let original_span = if let Expression::CallExpression(root_call_expr) = node { root_call_expr.span } else { @@ -415,10 +410,7 @@ impl<'a> PeepholeOptimizations { } /// `[].concat(1, 2)` -> `[1, 2]` - fn try_fold_concat( - ce: &mut CallExpression<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> Option> { + fn try_fold_concat(ce: &mut CallExpression<'a>, ctx: Ctx<'a, '_>) -> Option> { // let concat chaining reduction handle it first if let Ancestor::StaticMemberExpressionObject(parent_member) = ctx.parent() { if parent_member.property().name.as_str() == "concat" { @@ -476,11 +468,7 @@ impl<'a> PeepholeOptimizations { } } - fn try_fold_known_property_access( - &mut self, - node: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + fn try_fold_known_property_access(&mut self, node: &mut Expression<'a>, ctx: Ctx<'a, '_>) { let (name, object, span) = match &node { Expression::StaticMemberExpression(member) if !member.optional => { (member.property.name.as_str(), &member.object, member.span) @@ -495,7 +483,6 @@ impl<'a> PeepholeOptimizations { }; let Expression::Identifier(ident) = object else { return }; - let ctx = &mut Ctx(ctx); if !ctx.is_global_reference(ident) { return; } @@ -515,7 +502,7 @@ impl<'a> PeepholeOptimizations { &self, name: &str, span: Span, - ctx: &mut Ctx<'a, '_>, + ctx: Ctx<'a, '_>, ) -> Option> { let num = |span: Span, n: f64| { ctx.ast.expression_numeric_literal(span, n, None, NumberBase::Decimal) diff --git a/crates/oxc_minifier/src/peephole/statement_fusion.rs b/crates/oxc_minifier/src/peephole/statement_fusion.rs index 17c4b62cf..41b77b7cb 100644 --- a/crates/oxc_minifier/src/peephole/statement_fusion.rs +++ b/crates/oxc_minifier/src/peephole/statement_fusion.rs @@ -1,7 +1,8 @@ use oxc_allocator::Vec; use oxc_ast::ast::*; use oxc_span::GetSpan; -use oxc_traverse::TraverseCtx; + +use crate::ctx::Ctx; use super::PeepholeOptimizations; @@ -14,7 +15,7 @@ impl<'a> PeepholeOptimizations { pub fn statement_fusion_exit_statements( &mut self, stmts: &mut Vec<'a, Statement<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { let len = stmts.len(); @@ -81,7 +82,7 @@ impl<'a> PeepholeOptimizations { } } - fn fuse_into_one_statement(stmts: &mut [Statement<'a>], ctx: &mut TraverseCtx<'a>) { + fn fuse_into_one_statement(stmts: &mut [Statement<'a>], ctx: Ctx<'a, '_>) { let mut exprs = ctx.ast.vec(); let len = stmts.len(); @@ -108,7 +109,7 @@ impl<'a> PeepholeOptimizations { fn fuse_expression_into_control_flow_statement( stmt: &mut Statement<'a>, exprs: Vec<'a, Expression<'a>>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { let mut exprs = exprs; let expr = match stmt { diff --git a/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs b/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs index 9ebc4931c..363007ee4 100644 --- a/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs @@ -11,7 +11,7 @@ use oxc_syntax::{ number::NumberBase, operator::{BinaryOperator, UnaryOperator}, }; -use oxc_traverse::{Ancestor, TraverseCtx}; +use oxc_traverse::Ancestor; use crate::ctx::Ctx; @@ -22,18 +22,14 @@ use super::{LatePeepholeOptimizations, PeepholeOptimizations}; /// with literals, and simplifying returns. /// impl<'a> PeepholeOptimizations { - pub fn substitute_object_property( - &mut self, - prop: &mut ObjectProperty<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + pub fn substitute_object_property(&mut self, prop: &mut ObjectProperty<'a>, ctx: Ctx<'a, '_>) { self.try_compress_property_key(&mut prop.key, &mut prop.computed, ctx); } pub fn substitute_assignment_target_property_property( &mut self, prop: &mut AssignmentTargetPropertyProperty<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.try_compress_property_key(&mut prop.name, &mut prop.computed, ctx); } @@ -41,7 +37,7 @@ impl<'a> PeepholeOptimizations { pub fn substitute_binding_property( &mut self, prop: &mut BindingProperty<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.try_compress_property_key(&mut prop.key, &mut prop.computed, ctx); } @@ -49,7 +45,7 @@ impl<'a> PeepholeOptimizations { pub fn substitute_method_definition( &mut self, prop: &mut MethodDefinition<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.try_compress_property_key(&mut prop.key, &mut prop.computed, ctx); } @@ -57,7 +53,7 @@ impl<'a> PeepholeOptimizations { pub fn substitute_property_definition( &mut self, prop: &mut PropertyDefinition<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.try_compress_property_key(&mut prop.key, &mut prop.computed, ctx); } @@ -65,7 +61,7 @@ impl<'a> PeepholeOptimizations { pub fn substitute_accessor_property( &mut self, prop: &mut AccessorProperty<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.try_compress_property_key(&mut prop.key, &mut prop.computed, ctx); } @@ -73,7 +69,7 @@ impl<'a> PeepholeOptimizations { pub fn substitute_return_statement( &mut self, stmt: &mut ReturnStatement<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { self.compress_return_statement(stmt, ctx); } @@ -81,28 +77,18 @@ impl<'a> PeepholeOptimizations { pub fn substitute_variable_declaration( &mut self, decl: &mut VariableDeclaration<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { for declarator in &mut decl.declarations { - self.compress_variable_declarator(declarator, Ctx(ctx)); + self.compress_variable_declarator(declarator, ctx); } } - pub fn substitute_call_expression( - &mut self, - expr: &mut CallExpression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + pub fn substitute_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: Ctx<'a, '_>) { self.try_compress_call_expression_arguments(expr, ctx); } - pub fn substitute_exit_expression( - &mut self, - expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) { - let ctx = Ctx(ctx); - + pub fn substitute_exit_expression(&mut self, expr: &mut Expression<'a>, ctx: Ctx<'a, '_>) { // Change syntax match expr { Expression::ArrowFunctionExpression(e) => self.try_compress_arrow_expression(e, ctx), @@ -445,16 +431,12 @@ impl<'a> PeepholeOptimizations { /// /// `return undefined` -> `return` /// `return void 0` -> `return` - fn compress_return_statement( - &mut self, - stmt: &mut ReturnStatement<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + fn compress_return_statement(&mut self, stmt: &mut ReturnStatement<'a>, ctx: Ctx<'a, '_>) { let Some(argument) = &stmt.argument else { return }; if !match argument { - Expression::Identifier(ident) => Ctx(ctx).is_identifier_undefined(ident), + Expression::Identifier(ident) => ctx.is_identifier_undefined(ident), Expression::UnaryExpression(e) => { - e.operator.is_void() && !Ctx(ctx).expression_may_have_side_efffects(argument) + e.operator.is_void() && !ctx.expression_may_have_side_efffects(argument) } _ => false, } { @@ -762,7 +744,7 @@ impl<'a> PeepholeOptimizations { &mut self, key: &mut PropertyKey<'a>, computed: &mut bool, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { if let PropertyKey::NumericLiteral(_) = key { if *computed { @@ -805,7 +787,7 @@ impl<'a> PeepholeOptimizations { fn try_compress_call_expression_arguments( &mut self, node: &mut CallExpression<'a>, - ctx: &mut TraverseCtx<'a>, + ctx: Ctx<'a, '_>, ) { let (new_size, should_fold) = node.arguments.iter().fold((0, false), |(mut new_size, mut should_fold), arg| { @@ -865,7 +847,7 @@ impl<'a> PeepholeOptimizations { } impl<'a> LatePeepholeOptimizations { - pub fn substitute_exit_expression(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + pub fn substitute_exit_expression(expr: &mut Expression<'a>, ctx: Ctx<'a, '_>) { if let Expression::NewExpression(e) = expr { Self::try_compress_typed_array_constructor(e, ctx); } @@ -879,10 +861,10 @@ impl<'a> LatePeepholeOptimizations { } /// `new Int8Array(0)` -> `new Int8Array()` (also for other TypedArrays) - fn try_compress_typed_array_constructor(e: &mut NewExpression<'a>, ctx: &mut TraverseCtx<'a>) { + fn try_compress_typed_array_constructor(e: &mut NewExpression<'a>, ctx: Ctx<'a, '_>) { let Expression::Identifier(ident) = &e.callee else { return }; let name = ident.name.as_str(); - if !Self::is_typed_array_name(name) || !Ctx(ctx).is_global_reference(ident) { + if !Self::is_typed_array_name(name) || !ctx.is_global_reference(ident) { return; } if e.arguments.len() == 1 @@ -893,10 +875,7 @@ impl<'a> LatePeepholeOptimizations { } /// Transforms boolean expression `true` => `!0` `false` => `!1`. - fn try_compress_boolean( - expr: &mut Expression<'a>, - ctx: &mut TraverseCtx<'a>, - ) -> Option> { + fn try_compress_boolean(expr: &mut Expression<'a>, ctx: Ctx<'a, '_>) -> Option> { let Expression::BooleanLiteral(lit) = expr else { return None }; let num = ctx.ast.expression_numeric_literal( lit.span, @@ -907,11 +886,7 @@ impl<'a> LatePeepholeOptimizations { Some(ctx.ast.expression_unary(lit.span, UnaryOperator::LogicalNot, num)) } - pub fn substitute_catch_clause( - &mut self, - catch: &mut CatchClause<'a>, - ctx: &mut TraverseCtx<'a>, - ) { + pub fn substitute_catch_clause(&mut self, catch: &mut CatchClause<'a>, ctx: Ctx<'a, '_>) { if self.target >= ESTarget::ES2019 { if let Some(param) = &catch.param { if let BindingPatternKind::BindingIdentifier(ident) = ¶m.pattern.kind {