From 4db81065ee8e6b3cd72e891a1c5f4d99ecb6562c Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 23 Aug 2022 17:19:47 +0100 Subject: [PATCH] fix corner case in `hoist_vars` (#5627) fixes #5626 --- lib/compress.js | 52 +-------------- test/compress/default-values.js | 8 ++- test/compress/destructured.js | 5 +- test/compress/hoist_vars.js | 112 ++++++++++++++++++++++++++++++-- test/compress/issue-913.js | 5 +- test/compress/pure_getters.js | 2 + 6 files changed, 119 insertions(+), 65 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index c421525ec24..515283f3e43 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -8221,59 +8221,9 @@ Compressor.prototype.compress = function(node) { vars.set(name, defn); defn.name.definition().orig.unshift(defn.name); }); - if (defns.length > 0) { - // try to merge in assignments - insert_vars(self.body); - hoisted.push(make_node(AST_Var, self, { definitions: defns })); - } + if (defns.length > 0) hoisted.push(make_node(AST_Var, self, { definitions: defns })); } self.body = dirs.concat(hoisted, self.body); - - function insert_vars(body) { - while (body.length) { - var stat = body[0]; - if (stat instanceof AST_SimpleStatement) { - var expr = stat.body, sym, assign; - if (expr instanceof AST_Assign - && expr.operator == "=" - && (sym = expr.left) instanceof AST_Symbol - && vars.has(sym.name)) { - var defn = vars.get(sym.name); - if (defn.value) break; - var value = expr.right; - if (value instanceof AST_Sequence) value = value.clone(); - defn.value = value; - remove(defns, defn); - defns.push(defn); - body.shift(); - continue; - } - if (expr instanceof AST_Sequence - && (assign = expr.expressions[0]) instanceof AST_Assign - && assign.operator == "=" - && (sym = assign.left) instanceof AST_Symbol - && vars.has(sym.name)) { - var defn = vars.get(sym.name); - if (defn.value) break; - defn.value = assign.right; - remove(defns, defn); - defns.push(defn); - stat.body = make_sequence(expr, expr.expressions.slice(1)); - continue; - } - } - if (stat instanceof AST_EmptyStatement) { - body.shift(); - continue; - } - if (stat instanceof AST_BlockStatement && !insert_vars(stat.body)) { - body.shift(); - continue; - } - break; - } - return body.length; - } }); function scan_local_returns(fn, transform) { diff --git a/test/compress/default-values.js b/test/compress/default-values.js index afc296fe189..49b9b7fa803 100644 --- a/test/compress/default-values.js +++ b/test/compress/default-values.js @@ -668,6 +668,8 @@ drop_fargs: { hoist_vars: { options = { hoist_vars: true, + join_vars: true, + unused: true, } input: { var a = "PASS"; @@ -675,8 +677,7 @@ hoist_vars: { console.log(a, b); } expect: { - var a = "PASS"; - var [ b = 42 ] = []; + var a = "PASS", [ b = 42 ] = []; console.log(a, b); } expect_stdout: "PASS 42" @@ -3035,7 +3036,8 @@ issue_5566_5: { (function(a, f = function() { return a; }) { - var b, a = "foo"; + var a, b; + a = "foo"; console.log(a, f()); })("bar"); } diff --git a/test/compress/destructured.js b/test/compress/destructured.js index 487685f18ed..284130d7a53 100644 --- a/test/compress/destructured.js +++ b/test/compress/destructured.js @@ -1652,6 +1652,8 @@ fn_name_unused: { hoist_vars: { options = { hoist_vars: true, + join_vars: true, + unused: true, } input: { var a = "PASS"; @@ -1659,8 +1661,7 @@ hoist_vars: { console.log(a, b); } expect: { - var a = "PASS"; - var [ b ] = [ 42 ]; + var a = "PASS", b = [ 42 ][0]; console.log(a, b); } expect_stdout: "PASS 42" diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js index 99a13fe6e21..cc24f5887a1 100644 --- a/test/compress/hoist_vars.js +++ b/test/compress/hoist_vars.js @@ -2,6 +2,8 @@ statements: { options = { hoist_funs: false, hoist_vars: true, + join_vars: true, + unused: true, } input: { function f() { @@ -25,6 +27,8 @@ statements_funs: { options = { hoist_funs: true, hoist_vars: true, + join_vars: true, + unused: true, } input: { function f() { @@ -48,6 +52,8 @@ sequences: { options = { hoist_funs: false, hoist_vars: true, + join_vars: true, + unused: true, } input: { function f() { @@ -71,6 +77,8 @@ sequences_funs: { options = { hoist_funs: true, hoist_vars: true, + join_vars: true, + unused: true, } input: { function f() { @@ -108,7 +116,8 @@ catch_var: { console.log(a); } expect: { - var a = "PASS"; + a = "PASS"; + var a; console.log(a); } expect_stdout: "PASS" @@ -118,6 +127,8 @@ issue_2295: { options = { collapse_vars: true, hoist_vars: true, + join_vars: true, + unused: true, } input: { function foo(o) { @@ -139,6 +150,7 @@ issue_4487_1: { options = { functions: true, hoist_vars: true, + join_vars: true, keep_fnames: true, reduce_vars: true, toplevel: true, @@ -163,6 +175,7 @@ issue_4487_2: { options = { functions: true, hoist_vars: true, + join_vars: true, keep_fnames: true, passes: 2, reduce_vars: true, @@ -188,6 +201,7 @@ issue_4487_3: { options = { functions: true, hoist_vars: true, + join_vars: true, keep_fnames: true, passes: 3, reduce_vars: true, @@ -248,8 +262,7 @@ issue_4517: { } expect: { console.log(function() { - var a = 2; - return (A = a) + typeof !1; + return (A = 2) + typeof !1; }()); } expect_stdout: "2boolean" @@ -260,6 +273,7 @@ issue_4736: { collapse_vars: true, evaluate: true, hoist_vars: true, + join_vars: true, merge_vars: true, reduce_vars: true, toplevel: true, @@ -279,7 +293,7 @@ issue_4736: { expect: { (function() { (function() { - 0, + 0; console.log(1 << 30); })(); })(); @@ -291,6 +305,7 @@ issue_4839: { options = { evaluate: true, hoist_vars: true, + join_vars: true, keep_fargs: false, reduce_vars: true, toplevel: true, @@ -317,6 +332,7 @@ issue_4859: { options = { evaluate: true, hoist_vars: true, + join_vars: true, keep_infinity: true, merge_vars: true, reduce_vars: true, @@ -441,7 +457,7 @@ issue_4898: { expect_stdout: "PASS" } -issue_5187: { +issue_5187_1: { options = { hoist_props: true, hoist_vars: true, @@ -459,6 +475,37 @@ issue_5187: { } f(); } + expect: { + (function() { + var a, b; + a = 42; + do { + b = { 0: a++ }; + } while (console.log(b[b ^= 0])); + })(); + } + expect_stdout: "42" +} + +issue_5187_2: { + options = { + hoist_props: true, + hoist_vars: true, + join_vars: true, + reduce_vars: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + function f() { + var a = 42; + do { + var b = { 0: a++ }; + } while (console.log(b[b ^= 0])); + } + f(); + } expect: { (function() { var b, a = 42; @@ -547,9 +594,9 @@ issue_5411_1: { console.log(b); } expect: { - var b, c, a = "PASS"; + var a, b, c; b++; - b = a; + b = a = "PASS"; c = c && c[b]; console.log(b); } @@ -596,6 +643,30 @@ issue_5411_3: { var a = A = a; console.log(A); } + expect: { + var a; + a = console; + a = A = ++a; + console.log(A); + } + expect_stdout: "NaN" +} + +issue_5411_4: { + options = { + collapse_vars: true, + hoist_vars: true, + join_vars: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + var a = console; + a++; + var a = A = a; + console.log(A); + } expect: { var a = console; a = A = ++a; @@ -603,3 +674,30 @@ issue_5411_3: { } expect_stdout: "NaN" } + +issue_5626: { + options = { + conditionals: true, + evaluate: true, + hoist_vars: true, + reduce_vars: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + var a = function() { + return console.log(arguments[0]), 42; + }("PASS") ? null : "foo"; + for (var b in a) + FAIL; + } + expect: { + (function() { + console.log(arguments[0]); + }("PASS")); + for (var b in null) + FAIL; + } + expect_stdout: "PASS" +} diff --git a/test/compress/issue-913.js b/test/compress/issue-913.js index 57fd563761e..db1127cf291 100644 --- a/test/compress/issue-913.js +++ b/test/compress/issue-913.js @@ -1,17 +1,18 @@ keep_var_for_in: { options = { hoist_vars: true, + join_vars: true, unused: true, } input: { - (function(obj){ + (function(obj) { var foo = 5; for (var i in obj) return foo; })(); } expect: { - (function(obj){ + (function(obj) { var i, foo = 5; for (i in obj) return foo; diff --git a/test/compress/pure_getters.js b/test/compress/pure_getters.js index d64de174b64..a06570c98e7 100644 --- a/test/compress/pure_getters.js +++ b/test/compress/pure_getters.js @@ -1540,10 +1540,12 @@ this_toString: { issue_4803: { options = { hoist_vars: true, + join_vars: true, pure_getters: "strict", reduce_vars: true, side_effects: true, toplevel: true, + unused: true, } input: { var o = {