fix corner cases in collapse_vars (#5553)

fixes #5552
This commit is contained in:
Alex Lam S.L
2022-07-09 13:50:54 +01:00
committed by GitHub
parent 0b808f6428
commit 38bd4f65d0
2 changed files with 132 additions and 29 deletions

View File

@@ -2477,24 +2477,24 @@ Compressor.prototype.compress = function(node) {
can_replace = false;
var after = stop_after;
var if_hit = stop_if_hit;
if (!all(fn.argnames, function(argname) {
if (argname instanceof AST_DefaultValue) {
argname.value.transform(scanner);
if (abort) return false;
argname = argname.name;
for (var i = 0; !abort && i < fn.argnames.length; i++) {
if (may_throw_arg(reject, fn.argnames[i], node.args[i])) abort = true;
}
if (!abort) {
if (fn.rest && may_throw_arg(reject, fn.rest, make_node(AST_Array, node, {
elements: node.args.slice(i),
}))) {
abort = true;
} else if (is_arrow(fn) && fn.value) {
fn.value.transform(scanner);
} else for (var i = 0; !abort && i < fn.body.length; i++) {
var stat = fn.body[i];
if (stat instanceof AST_Return) {
if (stat.value) stat.value.transform(scanner);
break;
}
stat.transform(scanner);
}
return !(argname instanceof AST_Destructured);
})) {
abort = true;
} else if (is_arrow(fn) && fn.value) {
fn.value.transform(scanner);
} else for (var i = 0; !abort && i < fn.body.length; i++) {
var stat = fn.body[i];
if (stat instanceof AST_Return) {
if (stat.value) stat.value.transform(scanner);
break;
}
stat.transform(scanner);
}
stop_if_hit = if_hit;
stop_after = after;
@@ -2560,28 +2560,35 @@ Compressor.prototype.compress = function(node) {
return node instanceof AST_SymbolRef
&& (lvalues.has(node.name) || read_toplevel && compressor.exposed(node.definition()));
}, true);
function reject(node) {
node.transform(scanner);
return abort;
}
}
function may_throw_destructured(node, value) {
if (!value) return !(node instanceof AST_Symbol);
function may_throw_arg(reject, node, value) {
if (node instanceof AST_DefaultValue) {
return value.has_side_effects(compressor)
|| node.value.has_side_effects(compressor)
|| may_throw_destructured(node.name, is_undefined(value) && node.value);
return reject(node.value)
|| may_throw_arg(reject, node.name, node.value)
|| !is_undefined(value) && may_throw_arg(reject, node.name, value);
}
if (!value) return !(node instanceof AST_Symbol);
if (node instanceof AST_Destructured) {
if (node.rest && may_throw_destructured(node.rest)) return true;
if (node.rest && may_throw_arg(reject, node.rest)) return true;
if (node instanceof AST_DestructuredArray) {
if (!(value instanceof AST_Array || value.is_string(compressor))) return true;
return !all(node.elements, function(element) {
return !may_throw_destructured(element);
if (value instanceof AST_Array) return !all(node.elements, function(element, index) {
return !may_throw_arg(reject, element, value[index]);
});
return value.is_string(compressor) && !all(node.elements, function(element) {
return !may_throw_arg(reject, element);
});
}
if (node instanceof AST_DestructuredObject) {
if (!value.is_defined(compressor)) return true;
return !all(node.properties, function(prop) {
if (prop instanceof AST_Node && prop.has_side_effects(compressor)) return false;
return !may_throw_destructured(prop.value);
if (prop.key instanceof AST_Node && reject(prop.key)) return false;
return !may_throw_arg(reject, prop.value);
});
}
}
@@ -2645,7 +2652,9 @@ Compressor.prototype.compress = function(node) {
args[len + i] = value;
}
if (sym instanceof AST_Destructured) {
if (!may_throw_destructured(sym, arg)) continue;
if (!may_throw_arg(function(node) {
return node.has_side_effects(compressor);
}, sym, arg)) continue;
candidates.length = 0;
break;
}
@@ -2668,6 +2677,7 @@ Compressor.prototype.compress = function(node) {
candidate.arg_index = value ? len + i : i;
candidates.unshift([ candidate ]);
}
if (fn.rest) args.push(fn.rest);
}
}

View File

@@ -1531,3 +1531,96 @@ issue_5533_2_drop_fargs: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5552_1: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = f, b = log();
function f(...[ c = a = "PASS" ]) {}
f((a = "FAIL", b));
log(a);
}
expect: {
var log = console.log;
var a = f, b = log();
function f(...[ c = a = "PASS" ]) {}
f((a = "FAIL", b));
log(a);
}
expect_stdout: [
"",
"PASS",
]
node_version: ">=6"
}
issue_5552_2: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var log = console.log;
var a = f;
function f(...{ [a = "PASS"]: b }) {}
f((a = "FAIL", 42));
log(a);
}
expect: {
var log = console.log;
var a = f;
function f(...{ [a = "PASS"]: b }) {}
f((a = "FAIL", 42));
log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5552_3: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...[ c = a.pop() ]) {
return b;
}(a.pop()));
}
expect: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...[ c = a.pop() ]) {
return b;
}(a.pop()));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5552_4: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...{ [a.pop()]: c }) {
return b;
}(a.pop()));
}
expect: {
var a = [ "FAIL", "PASS" ];
console.log(function(b, ...{ [a.pop()]: c }) {
return b;
}(a.pop()));
}
expect_stdout: "PASS"
node_version: ">=6"
}