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
33 changes: 21 additions & 12 deletions crates/oxc_minifier/src/peephole/fold_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,24 @@ use oxc_syntax::operator::{BinaryOperator, LogicalOperator};

use crate::ctx::Ctx;

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

impl<'a> PeepholeOptimizations {
/// Constant Folding
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/PeepholeFoldConstants.java>
pub fn fold_constants_exit_expression(&mut self, expr: &mut Expression<'a>, ctx: Ctx<'a, '_>) {
if let Expression::TemplateLiteral(t) = expr {
self.try_inline_values_in_template_literal(t, ctx);
pub fn fold_constants_exit_expression(
&self,
expr: &mut Expression<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) {
match expr {
Expression::TemplateLiteral(t) => {
self.try_inline_values_in_template_literal(t, state, ctx);
}
Expression::ObjectExpression(e) => self.fold_object_spread(e, state, ctx),
_ => {}
}

if let Some(folded_expr) = match expr {
Expand All @@ -29,11 +38,10 @@ impl<'a> PeepholeOptimizations {
Expression::LogicalExpression(e) => Self::try_fold_logical_expr(e, ctx),
Expression::ChainExpression(e) => Self::try_fold_optional_chain(e, ctx),
Expression::CallExpression(e) => Self::try_fold_number_constructor(e, ctx),
Expression::ObjectExpression(e) => self.fold_object_spread(e, ctx),
_ => None,
} {
*expr = folded_expr;
self.mark_current_function_as_changed();
state.changed = true;
};
}

Expand Down Expand Up @@ -633,10 +641,11 @@ impl<'a> PeepholeOptimizations {
}

fn fold_object_spread(
&mut self,
&self,
e: &mut ObjectExpression<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) -> Option<Expression<'a>> {
) {
let len = e.properties.len();
e.properties.retain(|p| {
if let ObjectPropertyKind::SpreadProperty(spread_element) = p {
Expand All @@ -659,17 +668,17 @@ impl<'a> PeepholeOptimizations {
true
});
if e.properties.len() != len {
self.mark_current_function_as_changed();
state.changed = true;
}
None
}

/// Inline constant values in template literals
///
/// - `foo${1}bar${i}` => `foo1bar${i}`
fn try_inline_values_in_template_literal(
&mut self,
&self,
t: &mut TemplateLiteral<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) {
let has_expr_to_inline = t
Expand Down Expand Up @@ -719,7 +728,7 @@ impl<'a> PeepholeOptimizations {
}
}

self.mark_current_function_as_changed();
state.changed = true;
}
}

Expand Down
7 changes: 4 additions & 3 deletions crates/oxc_minifier/src/peephole/minimize_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ use oxc_syntax::es_target::ESTarget;

use crate::ctx::Ctx;

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

/// Minimize Conditions
///
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/PeepholeMinimizeConditions.java>
impl<'a> PeepholeOptimizations {
pub fn minimize_conditions_exit_expression(
&mut self,
&self,
expr: &mut Expression<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) {
let mut changed = false;
Expand Down Expand Up @@ -50,7 +51,7 @@ impl<'a> PeepholeOptimizations {
}
}
if changed {
self.mark_current_function_as_changed();
state.changed = true;
}
}

Expand Down
13 changes: 9 additions & 4 deletions crates/oxc_minifier/src/peephole/minimize_for_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ use oxc_span::GetSpan;

use crate::ctx::Ctx;

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

impl<'a> PeepholeOptimizations {
/// `mangleFor`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_parser.go#L9801>
pub fn minimize_for_statement(&mut self, for_stmt: &mut ForStatement<'a>, ctx: Ctx<'a, '_>) {
pub fn minimize_for_statement(
&self,
for_stmt: &mut ForStatement<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) {
// Get the first statement in the loop
let mut first = &for_stmt.body;
if let Statement::BlockStatement(block_stmt) = first {
Expand Down Expand Up @@ -60,7 +65,7 @@ impl<'a> PeepholeOptimizations {

let alternate = if_stmt.alternate.take();
for_stmt.body = Self::drop_first_statement(span, body, alternate, ctx);
self.mark_current_function_as_changed();
state.changed = true;
return;
}
// "for (;;) if (x) y(); else break;" => "for (; x;) y();"
Expand Down Expand Up @@ -97,7 +102,7 @@ impl<'a> PeepholeOptimizations {

let consequent = ctx.ast.move_statement(&mut if_stmt.consequent);
for_stmt.body = Self::drop_first_statement(span, body, Some(consequent), ctx);
self.mark_current_function_as_changed();
state.changed = true;
}
}

Expand Down
30 changes: 18 additions & 12 deletions crates/oxc_minifier/src/peephole/minimize_if_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ use oxc_span::GetSpan;

use crate::ctx::Ctx;

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

impl<'a> PeepholeOptimizations {
/// `MangleIf`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_parser/js_parser.go#L9860>
pub fn try_minimize_if(
&mut self,
&self,
if_stmt: &mut IfStatement<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) -> Option<Statement<'a>> {
self.wrap_to_avoid_ambiguous_else(if_stmt, ctx);
self.wrap_to_avoid_ambiguous_else(if_stmt, state, ctx);
if let Statement::ExpressionStatement(expr_stmt) = &mut if_stmt.consequent {
if if_stmt.alternate.is_none() {
let (op, e) = match &mut if_stmt.test {
Expand Down Expand Up @@ -46,7 +47,7 @@ impl<'a> PeepholeOptimizations {
{
// "if (a) {}" => "a;"
let mut expr = ctx.ast.move_expression(&mut if_stmt.test);
self.remove_unused_expression(&mut expr, ctx);
self.remove_unused_expression(&mut expr, state, ctx);
return Some(ctx.ast.statement_expression(if_stmt.span, expr));
} else if let Some(Statement::ExpressionStatement(expr_stmt)) = &mut if_stmt.alternate {
let (op, e) = match &mut if_stmt.test {
Expand All @@ -69,7 +70,7 @@ impl<'a> PeepholeOptimizations {
if_stmt.test = ctx.ast.move_expression(&mut unary_expr.argument);
if_stmt.consequent = ctx.ast.move_statement(stmt);
if_stmt.alternate = None;
self.mark_current_function_as_changed();
state.changed = true;
}
// "if (a) {} else return b;" => "if (!a) return b;"
_ => {
Expand All @@ -80,8 +81,8 @@ impl<'a> PeepholeOptimizations {
);
if_stmt.consequent = ctx.ast.move_statement(stmt);
if_stmt.alternate = None;
self.try_minimize_if(if_stmt, ctx);
self.mark_current_function_as_changed();
self.try_minimize_if(if_stmt, state, ctx);
state.changed = true;
}
}
}
Expand All @@ -94,8 +95,8 @@ impl<'a> PeepholeOptimizations {
// "if (!a) return b; else return c;" => "if (a) return c; else return b;"
if_stmt.test = ctx.ast.move_expression(&mut unary_expr.argument);
std::mem::swap(&mut if_stmt.consequent, alternate);
self.wrap_to_avoid_ambiguous_else(if_stmt, ctx);
self.mark_current_function_as_changed();
self.wrap_to_avoid_ambiguous_else(if_stmt, state, ctx);
state.changed = true;
}
}
// "if (a) return b; else {}" => "if (a) return b;" is handled by remove_dead_code
Expand All @@ -114,7 +115,7 @@ impl<'a> PeepholeOptimizations {
ctx,
);
if_stmt.consequent = ctx.ast.move_statement(&mut if2_stmt.consequent);
self.mark_current_function_as_changed();
state.changed = true;
}
}
}
Expand All @@ -125,7 +126,12 @@ impl<'a> PeepholeOptimizations {
/// Wrap to avoid ambiguous else.
/// `if (foo) if (bar) baz else quaz` -> `if (foo) { if (bar) baz else quaz }`
#[expect(clippy::cast_possible_truncation)]
fn wrap_to_avoid_ambiguous_else(&mut self, if_stmt: &mut IfStatement<'a>, ctx: Ctx<'a, '_>) {
fn wrap_to_avoid_ambiguous_else(
&self,
if_stmt: &mut IfStatement<'a>,
state: &mut State,
ctx: Ctx<'a, '_>,
) {
if let Statement::IfStatement(if2) = &mut if_stmt.consequent {
if if2.consequent.is_jump_statement() && if2.alternate.is_some() {
let scope_id = ScopeId::new(ctx.scoping.scoping().scopes_len() as u32);
Expand All @@ -136,7 +142,7 @@ impl<'a> PeepholeOptimizations {
scope_id,
),
));
self.mark_current_function_as_changed();
state.changed = true;
}
}
}
Expand Down
Loading