From a26dbce9817c8f39c7d5857bb258298da274c6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 25 Jul 2023 12:30:33 +0900 Subject: [PATCH] fix(es/minifier): Abort seq inliner using visitor (#7699) **Related issue:** - Closes #7697. --- .../src/compress/optimize/sequences.rs | 41 ++++++++++++++-- .../tests/fixture/issues/7697/1/config.json | 47 +++++++++++++++++++ .../tests/fixture/issues/7697/1/input.js | 6 +++ .../tests/fixture/issues/7697/1/output.js | 4 ++ 4 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 crates/swc_ecma_minifier/tests/fixture/issues/7697/1/config.json create mode 100644 crates/swc_ecma_minifier/tests/fixture/issues/7697/1/input.js create mode 100644 crates/swc_ecma_minifier/tests/fixture/issues/7697/1/output.js diff --git a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs index e78964c3a717..b7873cfb1eb8 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs @@ -2031,9 +2031,11 @@ impl Optimizer<'_> { pat_usage: Default::default(), target: a_id, in_lhs: false, + abort: false, + in_abort: false, }; b.visit_with(&mut v); - if v.expr_usage != 1 || v.pat_usage != 0 { + if v.expr_usage != 1 || v.pat_usage != 0 || v.abort { log_abort!( "sequences: Aborting merging of an update expression because of \ usage counts ({}, ref = {}, pat = {})", @@ -2103,9 +2105,11 @@ impl Optimizer<'_> { pat_usage: Default::default(), target: a_id, in_lhs: false, + abort: false, + in_abort: false, }; b.visit_with(&mut v); - if v.expr_usage != 1 || v.pat_usage != 0 { + if v.expr_usage != 1 || v.pat_usage != 0 || v.abort { log_abort!( "sequences: Aborting merging of an update expression because of \ usage counts ({}, ref = {}, pat = {})", @@ -2426,9 +2430,11 @@ impl Optimizer<'_> { pat_usage: Default::default(), target: &left_id, in_lhs: false, + abort: false, + in_abort: false, }; b.visit_with(&mut v); - if v.expr_usage != 1 || v.pat_usage != 0 { + if v.expr_usage != 1 || v.pat_usage != 0 || v.abort { log_abort!( "sequences: Aborting because of usage counts ({}{:?}, ref = {}, pat = {})", left_id.sym, @@ -2493,8 +2499,11 @@ struct UsageCounter<'a> { expr_usage: usize, pat_usage: usize, + abort: bool, + target: &'a Ident, in_lhs: bool, + in_abort: bool, } impl Visit for UsageCounter<'_> { @@ -2502,6 +2511,11 @@ impl Visit for UsageCounter<'_> { fn visit_ident(&mut self, i: &Ident) { if self.target.sym == i.sym && self.target.span.ctxt == i.span.ctxt { + if self.in_abort { + self.abort = true; + return; + } + if self.in_lhs { self.pat_usage += 1; } else { @@ -2521,6 +2535,27 @@ impl Visit for UsageCounter<'_> { } } + fn visit_update_expr(&mut self, e: &UpdateExpr) { + let old_in_abort = self.in_abort; + self.in_abort = true; + e.visit_children_with(self); + self.in_abort = old_in_abort; + } + + fn visit_await_expr(&mut self, e: &AwaitExpr) { + let old_in_abort = self.in_abort; + self.in_abort = true; + e.visit_children_with(self); + self.in_abort = old_in_abort; + } + + fn visit_yield_expr(&mut self, e: &YieldExpr) { + let old_in_abort = self.in_abort; + self.in_abort = true; + e.visit_children_with(self); + self.in_abort = old_in_abort; + } + fn visit_pat(&mut self, p: &Pat) { let old = self.in_lhs; self.in_lhs = true; diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/config.json b/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/config.json new file mode 100644 index 000000000000..2c1ceea5a033 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/config.json @@ -0,0 +1,47 @@ +{ + "arguments": false, + "arrows": true, + "booleans": true, + "booleans_as_integers": false, + "collapse_vars": true, + "comparisons": true, + "computed_props": true, + "conditionals": true, + "dead_code": true, + "directives": true, + "drop_console": false, + "drop_debugger": true, + "evaluate": true, + "expression": true, + "hoist_funs": false, + "hoist_props": true, + "hoist_vars": false, + "if_return": true, + "join_vars": true, + "keep_classnames": false, + "keep_fargs": true, + "keep_fnames": false, + "keep_infinity": false, + "loops": true, + "negate_iife": true, + "properties": true, + "reduce_funcs": false, + "reduce_vars": false, + "side_effects": true, + "switches": true, + "typeofs": true, + "unsafe": false, + "unsafe_arrows": false, + "unsafe_comps": false, + "unsafe_Function": false, + "unsafe_math": false, + "unsafe_symbols": false, + "unsafe_methods": false, + "unsafe_proto": false, + "unsafe_regexp": false, + "unsafe_undefined": false, + "unused": true, + "const_to_let": true, + "pristine_globals": true, + "passes": 2 +} diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/input.js new file mode 100644 index 000000000000..9205884ee3e4 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/input.js @@ -0,0 +1,6 @@ +let id = 0; + +export function getId() { + id = id % 9999; + return `${id++}` +} \ No newline at end of file diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/output.js new file mode 100644 index 000000000000..bde1103104cc --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/7697/1/output.js @@ -0,0 +1,4 @@ +let id = 0; +export function getId() { + return id %= 9999, `${id++}`; +}