Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions crates/oxc_minifier/src/compressor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use oxc_traverse::ReusableTraverseCtx;

use crate::{
CompressOptions,
peephole::{
DeadCodeElimination, LatePeepholeOptimizations, Normalize, NormalizeOptions,
PeepholeOptimizations,
},
peephole::{DeadCodeElimination, Normalize, NormalizeOptions, PeepholeOptimizations},
state::MinifierState,
};

Expand Down Expand Up @@ -38,7 +35,6 @@ impl<'a> Compressor<'a> {
NormalizeOptions { convert_while_to_fors: true, convert_const_to_let: true };
Normalize::new(normalize_options).build(program, &mut ctx);
PeepholeOptimizations::new().run_in_loop(program, &mut ctx);
LatePeepholeOptimizations::new().build(program, &mut ctx);
}

pub fn dead_code_elimination(self, program: &mut Program<'a>, options: CompressOptions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use oxc_ast::ast::*;

use crate::ctx::Ctx;

use super::LatePeepholeOptimizations;
use super::PeepholeOptimizations;

impl<'a> LatePeepholeOptimizations {
impl<'a> PeepholeOptimizations {
/// Converts property accesses from quoted string or bracket access syntax to dot or unquoted string
/// syntax, where possible. Dot syntax is more compact.
///
Expand Down
45 changes: 6 additions & 39 deletions crates/oxc_minifier/src/peephole/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,16 @@ impl<'a> Traverse<'a, MinifierState<'a>> for PeepholeOptimizations {
}
}

fn exit_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) {
fn exit_call_expression(&mut self, e: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) {
let mut ctx = Ctx::new(ctx);

self.substitute_call_expression(expr, &mut ctx);
self.substitute_call_expression(e, &mut ctx);
Self::remove_empty_spread_arguments(&mut e.arguments);
}

fn exit_new_expression(&mut self, expr: &mut NewExpression<'a>, ctx: &mut TraverseCtx<'a>) {
fn exit_new_expression(&mut self, e: &mut NewExpression<'a>, ctx: &mut TraverseCtx<'a>) {
let mut ctx = Ctx::new(ctx);

self.substitute_new_expression(expr, &mut ctx);
self.substitute_new_expression(e, &mut ctx);
Self::remove_empty_spread_arguments(&mut e.arguments);
}

fn exit_object_property(&mut self, prop: &mut ObjectProperty<'a>, ctx: &mut TraverseCtx<'a>) {
Expand Down Expand Up @@ -262,27 +262,7 @@ impl<'a> Traverse<'a, MinifierState<'a>> for PeepholeOptimizations {

self.substitute_accessor_property(prop, &mut ctx);
}
}

/// Changes that do not interfere with optimizations that are run inside the fixed-point loop,
/// which can be done as a last AST pass.
pub struct LatePeepholeOptimizations;

impl<'a> LatePeepholeOptimizations {
pub fn new() -> Self {
Self
}

pub fn build(
&mut self,
program: &mut Program<'a>,
ctx: &mut ReusableTraverseCtx<'a, MinifierState<'a>>,
) {
traverse_mut_with_ctx(self, program, ctx);
}
}

impl<'a> Traverse<'a, MinifierState<'a>> for LatePeepholeOptimizations {
fn exit_member_expression(
&mut self,
expr: &mut MemberExpression<'a>,
Expand All @@ -297,23 +277,10 @@ impl<'a> Traverse<'a, MinifierState<'a>> for LatePeepholeOptimizations {
Self::remove_dead_code_exit_class_body(body, &mut ctx);
}

fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
let mut ctx = Ctx::new(ctx);
Self::substitute_exit_expression(expr, &mut ctx);
}

fn exit_catch_clause(&mut self, catch: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {
let mut ctx = Ctx::new(ctx);
self.substitute_catch_clause(catch, &mut ctx);
}

fn exit_call_expression(&mut self, e: &mut CallExpression<'a>, _ctx: &mut TraverseCtx<'a>) {
Self::remove_empty_spread_arguments(&mut e.arguments);
}

fn exit_new_expression(&mut self, e: &mut NewExpression<'a>, _ctx: &mut TraverseCtx<'a>) {
Self::remove_empty_spread_arguments(&mut e.arguments);
}
}

pub struct DeadCodeElimination {
Expand Down
4 changes: 1 addition & 3 deletions crates/oxc_minifier/src/peephole/remove_dead_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use oxc_traverse::Ancestor;

use crate::{ctx::Ctx, keep_var::KeepVar};

use super::{LatePeepholeOptimizations, PeepholeOptimizations};
use super::PeepholeOptimizations;

/// Remove Dead Code from the AST.
///
Expand Down Expand Up @@ -565,9 +565,7 @@ impl<'a> PeepholeOptimizations {
_ => false,
}
}
}

impl<'a> LatePeepholeOptimizations {
pub fn remove_dead_code_exit_class_body(body: &mut ClassBody<'a>, _ctx: &mut Ctx<'a, '_>) {
Copy link

Copilot AI Aug 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method remove_dead_code_exit_class_body should be moved to the PeepholeOptimizations impl block to maintain consistency with the consolidation pattern used elsewhere in this PR.

Suggested change
pub fn remove_dead_code_exit_class_body(body: &mut ClassBody<'a>, _ctx: &mut Ctx<'a, '_>) {
pub fn remove_dead_code_exit_class_body(&self, body: &mut ClassBody<'a>, _ctx: &mut Ctx<'a, '_>) {

Copilot uses AI. Check for mistakes.
body.body.retain(|e| !matches!(e, ClassElement::StaticBlock(s) if s.body.is_empty()));
}
Expand Down
21 changes: 4 additions & 17 deletions crates/oxc_minifier/src/peephole/substitute_alternate_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use oxc_traverse::Ancestor;

use crate::ctx::Ctx;

use super::{LatePeepholeOptimizations, PeepholeOptimizations};
use super::PeepholeOptimizations;

/// A peephole optimization that minimizes code by simplifying conditional
/// expressions, replacing IFs with HOOKs, replacing object constructors
Expand Down Expand Up @@ -164,6 +164,7 @@ impl<'a> PeepholeOptimizations {
Expression::BinaryExpression(e) => Self::swap_binary_expressions(e),
Expression::FunctionExpression(e) => self.try_remove_name_from_functions(e, ctx),
Expression::ClassExpression(e) => self.try_remove_name_from_classes(e, ctx),
Expression::NewExpression(e) => Self::try_compress_typed_array_constructor(e, ctx),
_ => {}
}

Expand All @@ -185,6 +186,8 @@ impl<'a> PeepholeOptimizations {
Self::try_fold_object_or_array_constructor(e.span, name, &mut e.arguments, ctx)
})
.or_else(|| self.try_fold_simple_function_call(e, ctx)),
Expression::BooleanLiteral(_) => Self::try_compress_boolean(expr, ctx),
Expression::ArrayExpression(_) => Self::try_compress_array_expression(expr, ctx),
_ => None,
} {
*expr = folded_expr;
Expand Down Expand Up @@ -993,22 +996,6 @@ impl<'a> PeepholeOptimizations {
ctx.state.changed = true;
}
}
}

impl<'a> LatePeepholeOptimizations {
pub fn substitute_exit_expression(expr: &mut Expression<'a>, ctx: &mut Ctx<'a, '_>) {
if let Expression::NewExpression(e) = expr {
Self::try_compress_typed_array_constructor(e, ctx);
}

if let Some(folded_expr) = match expr {
Expression::BooleanLiteral(_) => Self::try_compress_boolean(expr, ctx),
Expression::ArrayExpression(_) => Self::try_compress_array_expression(expr, ctx),
_ => None,
} {
*expr = folded_expr;
}
}

/// `new Int8Array(0)` -> `new Int8Array()` (also for other TypedArrays)
fn try_compress_typed_array_constructor(e: &mut NewExpression<'a>, ctx: &mut Ctx<'a, '_>) {
Expand Down
Loading