diff --git a/crates/oxc_minifier/src/ast_passes/minimize_exit_points.rs b/crates/oxc_minifier/src/ast_passes/minimize_exit_points.rs index 38f375f717243..8b7c7255f6146 100644 --- a/crates/oxc_minifier/src/ast_passes/minimize_exit_points.rs +++ b/crates/oxc_minifier/src/ast_passes/minimize_exit_points.rs @@ -1,5 +1,6 @@ +use oxc_allocator::Vec; use oxc_ast::ast::*; -use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse}; +use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx}; use crate::CompressorPass; @@ -18,12 +19,26 @@ impl<'a> CompressorPass<'a> for MinimizeExitPoints { } } -impl Traverse<'_> for MinimizeExitPoints {} +impl Traverse<'_> for MinimizeExitPoints { + fn exit_function_body(&mut self, body: &mut FunctionBody<'_>, _ctx: &mut TraverseCtx<'_>) { + self.remove_last_return(&mut body.statements); + } +} -impl MinimizeExitPoints { +impl<'a> MinimizeExitPoints { pub fn new() -> Self { Self { changed: false } } + + // `function foo() { return }` -> `function foo() {}` + fn remove_last_return(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { + if let Some(last) = stmts.last() { + if matches!(last, Statement::ReturnStatement(ret) if ret.argument.is_none()) { + stmts.pop(); + self.changed = true; + } + } + } } #[cfg(test)] @@ -71,7 +86,6 @@ mod test { } #[test] - #[ignore] fn test_function_return_optimization1() { fold("function f(){return}", "function f(){}"); } @@ -140,7 +154,6 @@ mod test { } #[test] - #[ignore] fn test_function_return_scoped() { fold_same( "function f(a) { @@ -366,7 +379,6 @@ mod test { } #[test] - #[ignore] fn test_dont_remove_break_in_try_finally() { fold_same("function f() {b:try{throw 9} finally {break b} return 1;}"); } @@ -378,7 +390,6 @@ mod test { * @see https://github.com/google/closure-compiler/issues/554 */ #[test] - #[ignore] fn test_dont_fold_break_in_do_while_if_condition_has_side_effects() { fold_same("var b=true;do{break}while(b=false);"); } diff --git a/crates/oxc_minifier/src/ast_passes/mod.rs b/crates/oxc_minifier/src/ast_passes/mod.rs index 1215eca34b9dd..7c0a26ba050fb 100644 --- a/crates/oxc_minifier/src/ast_passes/mod.rs +++ b/crates/oxc_minifier/src/ast_passes/mod.rs @@ -130,7 +130,6 @@ impl<'a> Traverse<'a> for PeepholeOptimizations { fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { self.x0_statement_fusion.exit_statements(stmts, ctx); - 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.x5_peephole_minimize_conditions.exit_statements(stmts, ctx); diff --git a/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs b/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs index da750d8e0dd64..4e9c8c6112a05 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs @@ -27,6 +27,13 @@ impl<'a> CompressorPass<'a> for PeepholeRemoveDeadCode { } impl<'a> Traverse<'a> for PeepholeRemoveDeadCode { + fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { + if stmts.iter().any(|stmt| matches!(stmt, Statement::EmptyStatement(_))) { + stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_))); + } + self.dead_code_elimination(stmts, Ctx(ctx)); + } + fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { let ctx = Ctx(ctx); if let Some(new_stmt) = match stmt { @@ -50,13 +57,6 @@ impl<'a> Traverse<'a> for PeepholeRemoveDeadCode { } } - fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { - if stmts.iter().any(|stmt| matches!(stmt, Statement::EmptyStatement(_))) { - stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_))); - } - self.dead_code_elimination(stmts, Ctx(ctx)); - } - fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { let ctx = Ctx(ctx); if let Some(folded_expr) = match expr { diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index 565797d7fafe8..93506b0f41dc1 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -15,13 +15,13 @@ Original | minified | minified | gzip | gzip | Fixture 1.01 MB | 460.17 kB | 458.89 kB | 126.76 kB | 126.71 kB | bundle.min.js -1.25 MB | 652.84 kB | 646.76 kB | 163.54 kB | 163.73 kB | three.js +1.25 MB | 652.80 kB | 646.76 kB | 163.53 kB | 163.73 kB | three.js -2.14 MB | 725.68 kB | 724.14 kB | 180.07 kB | 181.07 kB | victory.js +2.14 MB | 725.52 kB | 724.14 kB | 180.05 kB | 181.07 kB | victory.js -3.20 MB | 1.01 MB | 1.01 MB | 331.79 kB | 331.56 kB | echarts.js +3.20 MB | 1.01 MB | 1.01 MB | 331.77 kB | 331.56 kB | echarts.js -6.69 MB | 2.32 MB | 2.31 MB | 492.64 kB | 488.28 kB | antd.js +6.69 MB | 2.32 MB | 2.31 MB | 492.62 kB | 488.28 kB | antd.js -10.95 MB | 3.49 MB | 3.49 MB | 907.42 kB | 915.50 kB | typescript.js +10.95 MB | 3.49 MB | 3.49 MB | 907.11 kB | 915.50 kB | typescript.js