fix corner case in hoist_vars (#5627)

fixes #5626
This commit is contained in:
Alex Lam S.L
2022-08-23 17:19:47 +01:00
committed by GitHub
parent 4653e8aec0
commit 4db81065ee
6 changed files with 119 additions and 65 deletions

View File

@@ -8221,59 +8221,9 @@ Compressor.prototype.compress = function(node) {
vars.set(name, defn); vars.set(name, defn);
defn.name.definition().orig.unshift(defn.name); defn.name.definition().orig.unshift(defn.name);
}); });
if (defns.length > 0) { if (defns.length > 0) hoisted.push(make_node(AST_Var, self, { definitions: defns }));
// try to merge in assignments
insert_vars(self.body);
hoisted.push(make_node(AST_Var, self, { definitions: defns }));
}
} }
self.body = dirs.concat(hoisted, self.body); 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) { function scan_local_returns(fn, transform) {

View File

@@ -668,6 +668,8 @@ drop_fargs: {
hoist_vars: { hoist_vars: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
var a = "PASS"; var a = "PASS";
@@ -675,8 +677,7 @@ hoist_vars: {
console.log(a, b); console.log(a, b);
} }
expect: { expect: {
var a = "PASS"; var a = "PASS", [ b = 42 ] = [];
var [ b = 42 ] = [];
console.log(a, b); console.log(a, b);
} }
expect_stdout: "PASS 42" expect_stdout: "PASS 42"
@@ -3035,7 +3036,8 @@ issue_5566_5: {
(function(a, f = function() { (function(a, f = function() {
return a; return a;
}) { }) {
var b, a = "foo"; var a, b;
a = "foo";
console.log(a, f()); console.log(a, f());
})("bar"); })("bar");
} }

View File

@@ -1652,6 +1652,8 @@ fn_name_unused: {
hoist_vars: { hoist_vars: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
var a = "PASS"; var a = "PASS";
@@ -1659,8 +1661,7 @@ hoist_vars: {
console.log(a, b); console.log(a, b);
} }
expect: { expect: {
var a = "PASS"; var a = "PASS", b = [ 42 ][0];
var [ b ] = [ 42 ];
console.log(a, b); console.log(a, b);
} }
expect_stdout: "PASS 42" expect_stdout: "PASS 42"

View File

@@ -2,6 +2,8 @@ statements: {
options = { options = {
hoist_funs: false, hoist_funs: false,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -25,6 +27,8 @@ statements_funs: {
options = { options = {
hoist_funs: true, hoist_funs: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -48,6 +52,8 @@ sequences: {
options = { options = {
hoist_funs: false, hoist_funs: false,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -71,6 +77,8 @@ sequences_funs: {
options = { options = {
hoist_funs: true, hoist_funs: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function f() { function f() {
@@ -108,7 +116,8 @@ catch_var: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a = "PASS"; a = "PASS";
var a;
console.log(a); console.log(a);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -118,6 +127,8 @@ issue_2295: {
options = { options = {
collapse_vars: true, collapse_vars: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true,
} }
input: { input: {
function foo(o) { function foo(o) {
@@ -139,6 +150,7 @@ issue_4487_1: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fnames: true, keep_fnames: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -163,6 +175,7 @@ issue_4487_2: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fnames: true, keep_fnames: true,
passes: 2, passes: 2,
reduce_vars: true, reduce_vars: true,
@@ -188,6 +201,7 @@ issue_4487_3: {
options = { options = {
functions: true, functions: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fnames: true, keep_fnames: true,
passes: 3, passes: 3,
reduce_vars: true, reduce_vars: true,
@@ -248,8 +262,7 @@ issue_4517: {
} }
expect: { expect: {
console.log(function() { console.log(function() {
var a = 2; return (A = 2) + typeof !1;
return (A = a) + typeof !1;
}()); }());
} }
expect_stdout: "2boolean" expect_stdout: "2boolean"
@@ -260,6 +273,7 @@ issue_4736: {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
merge_vars: true, merge_vars: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -279,7 +293,7 @@ issue_4736: {
expect: { expect: {
(function() { (function() {
(function() { (function() {
0, 0;
console.log(1 << 30); console.log(1 << 30);
})(); })();
})(); })();
@@ -291,6 +305,7 @@ issue_4839: {
options = { options = {
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_fargs: false, keep_fargs: false,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
@@ -317,6 +332,7 @@ issue_4859: {
options = { options = {
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
join_vars: true,
keep_infinity: true, keep_infinity: true,
merge_vars: true, merge_vars: true,
reduce_vars: true, reduce_vars: true,
@@ -441,7 +457,7 @@ issue_4898: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_5187: { issue_5187_1: {
options = { options = {
hoist_props: true, hoist_props: true,
hoist_vars: true, hoist_vars: true,
@@ -459,6 +475,37 @@ issue_5187: {
} }
f(); 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: { expect: {
(function() { (function() {
var b, a = 42; var b, a = 42;
@@ -547,9 +594,9 @@ issue_5411_1: {
console.log(b); console.log(b);
} }
expect: { expect: {
var b, c, a = "PASS"; var a, b, c;
b++; b++;
b = a; b = a = "PASS";
c = c && c[b]; c = c && c[b];
console.log(b); console.log(b);
} }
@@ -596,6 +643,30 @@ issue_5411_3: {
var a = A = a; var a = A = a;
console.log(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: { expect: {
var a = console; var a = console;
a = A = ++a; a = A = ++a;
@@ -603,3 +674,30 @@ issue_5411_3: {
} }
expect_stdout: "NaN" 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"
}

View File

@@ -1,17 +1,18 @@
keep_var_for_in: { keep_var_for_in: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
unused: true, unused: true,
} }
input: { input: {
(function(obj){ (function(obj) {
var foo = 5; var foo = 5;
for (var i in obj) for (var i in obj)
return foo; return foo;
})(); })();
} }
expect: { expect: {
(function(obj){ (function(obj) {
var i, foo = 5; var i, foo = 5;
for (i in obj) for (i in obj)
return foo; return foo;

View File

@@ -1540,10 +1540,12 @@ this_toString: {
issue_4803: { issue_4803: {
options = { options = {
hoist_vars: true, hoist_vars: true,
join_vars: true,
pure_getters: "strict", pure_getters: "strict",
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
toplevel: true, toplevel: true,
unused: true,
} }
input: { input: {
var o = { var o = {