Skip to content

Commit 6838948

Browse files
committed
refactor(minifier): remove change detection based on function changes (#12429)
Previously minification methods were run when functions are changed during the previous iteration, this is not longer the case after addition of removing unused vars and inline constant values.
1 parent 124d376 commit 6838948

14 files changed

+303
-609
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_minifier/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ oxc_allocator = { workspace = true }
2525
oxc_ast = { workspace = true }
2626
oxc_ast_visit = { workspace = true }
2727
oxc_codegen = { workspace = true }
28-
oxc_data_structures = { workspace = true, features = ["stack"] }
2928
oxc_ecmascript = { workspace = true }
3029
oxc_mangler = { workspace = true }
3130
oxc_parser = { workspace = true }

crates/oxc_minifier/src/peephole/fold_constants.rs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,18 @@ use oxc_traverse::Ancestor;
1111

1212
use crate::ctx::Ctx;
1313

14-
use super::{PeepholeOptimizations, State};
14+
use super::PeepholeOptimizations;
1515

1616
impl<'a> PeepholeOptimizations {
1717
/// Constant Folding
1818
///
1919
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/PeepholeFoldConstants.java>
20-
pub fn fold_constants_exit_expression(
21-
&self,
22-
expr: &mut Expression<'a>,
23-
state: &mut State,
24-
ctx: &mut Ctx<'a, '_>,
25-
) {
20+
pub fn fold_constants_exit_expression(&self, expr: &mut Expression<'a>, ctx: &mut Ctx<'a, '_>) {
2621
match expr {
2722
Expression::TemplateLiteral(t) => {
28-
self.try_inline_values_in_template_literal(t, state, ctx);
23+
self.try_inline_values_in_template_literal(t, ctx);
2924
}
30-
Expression::ObjectExpression(e) => self.fold_object_spread(e, state, ctx),
25+
Expression::ObjectExpression(e) => self.fold_object_spread(e, ctx),
3126
_ => {}
3227
}
3328

@@ -43,7 +38,7 @@ impl<'a> PeepholeOptimizations {
4338
_ => None,
4439
} {
4540
*expr = folded_expr;
46-
state.changed = true;
41+
ctx.state.changed = true;
4742
}
4843

4944
// Save `const value = false` into constant values.
@@ -664,12 +659,7 @@ impl<'a> PeepholeOptimizations {
664659
None
665660
}
666661

667-
fn fold_object_spread(
668-
&self,
669-
e: &mut ObjectExpression<'a>,
670-
state: &mut State,
671-
ctx: &mut Ctx<'a, '_>,
672-
) {
662+
fn fold_object_spread(&self, e: &mut ObjectExpression<'a>, ctx: &mut Ctx<'a, '_>) {
673663
let (new_size, should_fold) =
674664
e.properties.iter().fold((0, false), |(new_size, should_fold), p| {
675665
let ObjectPropertyKind::SpreadProperty(spread_element) = p else {
@@ -745,7 +735,7 @@ impl<'a> PeepholeOptimizations {
745735
}
746736

747737
e.properties = new_properties;
748-
state.changed = true;
738+
ctx.state.changed = true;
749739
}
750740

751741
fn is_spread_inlineable_object_literal(
@@ -774,7 +764,7 @@ impl<'a> PeepholeOptimizations {
774764
fn try_inline_values_in_template_literal(
775765
&self,
776766
t: &mut TemplateLiteral<'a>,
777-
state: &mut State,
767+
778768
ctx: &mut Ctx<'a, '_>,
779769
) {
780770
let has_expr_to_inline = t
@@ -824,7 +814,7 @@ impl<'a> PeepholeOptimizations {
824814
}
825815
}
826816

827-
state.changed = true;
817+
ctx.state.changed = true;
828818
}
829819
}
830820

crates/oxc_minifier/src/peephole/minimize_conditions.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use oxc_syntax::es_target::ESTarget;
66

77
use crate::ctx::Ctx;
88

9-
use super::{PeepholeOptimizations, State};
9+
use super::PeepholeOptimizations;
1010

1111
/// Minimize Conditions
1212
///
@@ -15,7 +15,6 @@ impl<'a> PeepholeOptimizations {
1515
pub fn minimize_conditions_exit_expression(
1616
&self,
1717
expr: &mut Expression<'a>,
18-
state: &mut State,
1918
ctx: &mut Ctx<'a, '_>,
2019
) {
2120
let mut changed = false;
@@ -57,7 +56,7 @@ impl<'a> PeepholeOptimizations {
5756
}
5857
}
5958
if changed {
60-
state.changed = true;
59+
ctx.state.changed = true;
6160
}
6261
}
6362

crates/oxc_minifier/src/peephole/minimize_for_statement.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@ use oxc_span::GetSpan;
44

55
use crate::ctx::Ctx;
66

7-
use super::{PeepholeOptimizations, State};
7+
use super::PeepholeOptimizations;
88

99
impl<'a> PeepholeOptimizations {
1010
/// `mangleFor`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_parser.go#L9801>
11-
pub fn minimize_for_statement(
12-
&self,
13-
for_stmt: &mut ForStatement<'a>,
14-
state: &mut State,
15-
ctx: &mut Ctx<'a, '_>,
16-
) {
11+
pub fn minimize_for_statement(&self, for_stmt: &mut ForStatement<'a>, ctx: &mut Ctx<'a, '_>) {
1712
// Get the first statement in the loop
1813
let mut first = &for_stmt.body;
1914
if let Statement::BlockStatement(block_stmt) = first {
@@ -66,7 +61,7 @@ impl<'a> PeepholeOptimizations {
6661

6762
let alternate = if_stmt.alternate.take();
6863
for_stmt.body = Self::drop_first_statement(span, body, alternate, ctx);
69-
state.changed = true;
64+
ctx.state.changed = true;
7065
return;
7166
}
7267
// "for (;;) if (x) y(); else break;" => "for (; x;) y();"
@@ -103,7 +98,7 @@ impl<'a> PeepholeOptimizations {
10398

10499
let consequent = if_stmt.consequent.take_in(ctx.ast);
105100
for_stmt.body = Self::drop_first_statement(span, body, Some(consequent), ctx);
106-
state.changed = true;
101+
ctx.state.changed = true;
107102
}
108103
}
109104

crates/oxc_minifier/src/peephole/minimize_if_statement.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ use oxc_span::GetSpan;
66

77
use crate::ctx::Ctx;
88

9-
use super::{PeepholeOptimizations, State};
9+
use super::PeepholeOptimizations;
1010

1111
impl<'a> PeepholeOptimizations {
1212
/// `MangleIf`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_parser/js_parser.go#L9860>
1313
pub fn try_minimize_if(
1414
&self,
1515
if_stmt: &mut IfStatement<'a>,
16-
state: &mut State,
1716
ctx: &mut Ctx<'a, '_>,
1817
) -> Option<Statement<'a>> {
19-
self.wrap_to_avoid_ambiguous_else(if_stmt, state, ctx);
18+
self.wrap_to_avoid_ambiguous_else(if_stmt, ctx);
2019
if let Statement::ExpressionStatement(expr_stmt) = &mut if_stmt.consequent {
2120
if if_stmt.alternate.is_none() {
2221
let (op, e) = match &mut if_stmt.test {
@@ -48,7 +47,7 @@ impl<'a> PeepholeOptimizations {
4847
{
4948
// "if (a) {}" => "a;"
5049
let mut expr = if_stmt.test.take_in(ctx.ast);
51-
self.remove_unused_expression(&mut expr, state, ctx);
50+
self.remove_unused_expression(&mut expr, ctx);
5251
return Some(ctx.ast.statement_expression(if_stmt.span, expr));
5352
} else if let Some(Statement::ExpressionStatement(expr_stmt)) = &mut if_stmt.alternate {
5453
let (op, e) = match &mut if_stmt.test {
@@ -71,7 +70,7 @@ impl<'a> PeepholeOptimizations {
7170
if_stmt.test = unary_expr.argument.take_in(ctx.ast);
7271
if_stmt.consequent = stmt.take_in(ctx.ast);
7372
if_stmt.alternate = None;
74-
state.changed = true;
73+
ctx.state.changed = true;
7574
}
7675
// "if (a) {} else return b;" => "if (!a) return b;"
7776
_ => {
@@ -82,8 +81,8 @@ impl<'a> PeepholeOptimizations {
8281
);
8382
if_stmt.consequent = stmt.take_in(ctx.ast);
8483
if_stmt.alternate = None;
85-
self.try_minimize_if(if_stmt, state, ctx);
86-
state.changed = true;
84+
self.try_minimize_if(if_stmt, ctx);
85+
ctx.state.changed = true;
8786
}
8887
}
8988
}
@@ -96,8 +95,8 @@ impl<'a> PeepholeOptimizations {
9695
// "if (!a) return b; else return c;" => "if (a) return c; else return b;"
9796
if_stmt.test = unary_expr.argument.take_in(ctx.ast);
9897
std::mem::swap(&mut if_stmt.consequent, alternate);
99-
self.wrap_to_avoid_ambiguous_else(if_stmt, state, ctx);
100-
state.changed = true;
98+
self.wrap_to_avoid_ambiguous_else(if_stmt, ctx);
99+
ctx.state.changed = true;
101100
}
102101
}
103102
// "if (a) return b; else {}" => "if (a) return b;" is handled by remove_dead_code
@@ -116,7 +115,7 @@ impl<'a> PeepholeOptimizations {
116115
ctx,
117116
);
118117
if_stmt.consequent = if2_stmt.consequent.take_in(ctx.ast);
119-
state.changed = true;
118+
ctx.state.changed = true;
120119
}
121120
}
122121
}
@@ -127,12 +126,7 @@ impl<'a> PeepholeOptimizations {
127126
/// Wrap to avoid ambiguous else.
128127
/// `if (foo) if (bar) baz else quaz` -> `if (foo) { if (bar) baz else quaz }`
129128
#[expect(clippy::cast_possible_truncation)]
130-
fn wrap_to_avoid_ambiguous_else(
131-
&self,
132-
if_stmt: &mut IfStatement<'a>,
133-
state: &mut State,
134-
ctx: &mut Ctx<'a, '_>,
135-
) {
129+
fn wrap_to_avoid_ambiguous_else(&self, if_stmt: &mut IfStatement<'a>, ctx: &mut Ctx<'a, '_>) {
136130
if let Statement::IfStatement(if2) = &mut if_stmt.consequent {
137131
if if2.consequent.is_jump_statement() && if2.alternate.is_some() {
138132
let scope_id = ScopeId::new(ctx.scoping.scoping().scopes_len() as u32);
@@ -143,7 +137,7 @@ impl<'a> PeepholeOptimizations {
143137
scope_id,
144138
),
145139
));
146-
state.changed = true;
140+
ctx.state.changed = true;
147141
}
148142
}
149143
}

0 commit comments

Comments
 (0)