From 6d3ea17aa6b708c7819a6769dccd920bd3fe2efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 29 Mar 2022 13:25:15 +0900 Subject: [PATCH] feat(es/minifier): Optimize switches more correctly (#4180) --- .../src/compress/optimize/switches.rs | 31 ++++++++++++++++--- crates/swc_ecma_minifier/tests/TODO.txt | 2 -- crates/swc_ecma_minifier/tests/golden.txt | 2 ++ .../compress/switch/issue_1663/output.js | 9 +++--- .../src/simplify/branch/mod.rs | 10 ++++-- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/crates/swc_ecma_minifier/src/compress/optimize/switches.rs b/crates/swc_ecma_minifier/src/compress/optimize/switches.rs index 55f15817efe..24a22eeb6bb 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/switches.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/switches.rs @@ -34,6 +34,14 @@ where return; } + if stmt + .cases + .iter() + .any(|case| matches!(case.test.as_deref(), Some(Expr::Update(..)))) + { + return; + } + let matching_case = stmt.cases.iter_mut().position(|case| { case.test .as_ref() @@ -117,7 +125,16 @@ where _ => !found_break, }); - stmts.append(&mut case.cons); + for case_stmt in case.cons.take() { + match case_stmt { + Stmt::Decl(Decl::Var(v)) if v.decls.iter().all(|v| v.init.is_none()) => { + var_ids.extend(v.decls) + } + _ => { + stmts.push(case_stmt); + } + } + } if found_break { break; } @@ -235,7 +252,7 @@ where /// If a case ends with break but content is same with the consequtive case /// except the break statement, we merge them. fn merge_cases_with_same_cons(&mut self, cases: &mut Vec) { - let stop_pos = cases + let mut stop_pos_opt = cases .iter() .position(|case| matches!(case.test.as_deref(), Some(Expr::Update(..)))); @@ -245,8 +262,14 @@ where continue; } - if let Some(stop_pos) = stop_pos { - if li > stop_pos { + if let Some(stop_pos) = stop_pos_opt { + if li == stop_pos { + // Look for next stop position + stop_pos_opt = cases + .iter() + .skip(li) + .position(|case| matches!(case.test.as_deref(), Some(Expr::Update(..)))) + .map(|v| v + li); continue; } } diff --git a/crates/swc_ecma_minifier/tests/TODO.txt b/crates/swc_ecma_minifier/tests/TODO.txt index 2e2c6b6fbd4..bc329119d34 100644 --- a/crates/swc_ecma_minifier/tests/TODO.txt +++ b/crates/swc_ecma_minifier/tests/TODO.txt @@ -749,8 +749,6 @@ sequences/issue_1758/input.js sequences/lift_sequences_2/input.js sequences/lift_sequences_5/input.js sequences/side_effects_cascade_3/input.js -switch/issue_1663/input.js -switch/issue_1680_2/input.js template_string/array_join/input.js template_string/coerce_to_string/input.js template_string/evaluate_nested_templates/input.js diff --git a/crates/swc_ecma_minifier/tests/golden.txt b/crates/swc_ecma_minifier/tests/golden.txt index 1d354dbbdc5..ee78126f060 100644 --- a/crates/swc_ecma_minifier/tests/golden.txt +++ b/crates/swc_ecma_minifier/tests/golden.txt @@ -1257,9 +1257,11 @@ switch/drop_case/input.js switch/drop_default_1/input.js switch/drop_default_2/input.js switch/if_switch_typeof/input.js +switch/issue_1663/input.js switch/issue_1674/input.js switch/issue_1679/input.js switch/issue_1680_1/input.js +switch/issue_1680_2/input.js switch/issue_1690_1/input.js switch/issue_1690_2/input.js switch/issue_1698/input.js diff --git a/crates/swc_ecma_minifier/tests/terser/compress/switch/issue_1663/output.js b/crates/swc_ecma_minifier/tests/terser/compress/switch/issue_1663/output.js index 916ad09ac3e..ff362bba25a 100644 --- a/crates/swc_ecma_minifier/tests/terser/compress/switch/issue_1663/output.js +++ b/crates/swc_ecma_minifier/tests/terser/compress/switch/issue_1663/output.js @@ -1,9 +1,8 @@ -var a = 100, - b = 10; +var a = 100, b = 10; function f() { - var b; - b = a++; - return ++b; + var b1; + b1 = a++; + return ++b1; } f(); console.log(a, b); diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs index bb902d43a5b..aaa6c948430 100644 --- a/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs +++ b/crates/swc_ecma_transforms_optimization/src/simplify/branch/mod.rs @@ -1079,6 +1079,8 @@ impl Remover { where T: StmtLike + VisitWith + VisitMutWith, { + let orig_len = stmts.len(); + let is_block_stmt = self.normal_block; self.normal_block = false; @@ -1142,10 +1144,14 @@ impl Remover { new_stmts.extend(hoisted_fns); *stmts = new_stmts; + if stmts.len() != orig_len { + self.changed = true; - if cfg!(feature = "debug") { - debug!("Dropping statements after a control keyword"); + if cfg!(feature = "debug") { + debug!("Dropping statements after a control keyword"); + } } + return; }