fix corner cases in reduce_vars & unused (#5247)

fixes #5246
This commit is contained in:
Alex Lam S.L
2021-12-30 20:47:13 +00:00
committed by GitHub
parent 80d5f23fee
commit e7ce1051fe
4 changed files with 222 additions and 31 deletions

View File

@@ -784,8 +784,11 @@ Compressor.prototype.compress = function(node) {
if (save) fixed = compressor.option("rests") && function() {
var value = save();
if (!(value instanceof AST_Array)) return node;
for (var i = 0, len = node.elements.length; i < len; i++) {
if (value.elements[i] instanceof AST_Spread) return node;
}
if (!fixed_node) fixed_node = make_node(AST_Array, node);
fixed_node.elements = value.elements.slice(node.elements.length);
fixed_node.elements = value.elements.slice(len);
return fixed_node;
};
node.rest.walk(scanner);
@@ -6662,8 +6665,28 @@ Compressor.prototype.compress = function(node) {
unused_fn_names.push(node);
}
if (!(node instanceof AST_Accessor)) {
if (node.rest) {
var rest = node.rest.transform(trimmer);
var args, spread;
if (parent instanceof AST_Call && parent.expression === node) {
args = parent.args;
for (spread = 0; spread < args.length; spread++) {
if (args[spread] instanceof AST_Spread) break;
}
}
var argnames = node.argnames;
var rest = node.rest;
if (rest) {
if (!args || spread < argnames.length || rest instanceof AST_SymbolFunarg) {
rest = rest.transform(trimmer);
} else {
var trimmed = trim_destructured(rest, make_node(AST_Array, parent, {
elements: args.slice(argnames.length),
}), function(node) {
return node.definition().id in in_use_ids ? node : null;
}, !node.uses_arguments, rest);
rest = trimmed.name;
args.length = argnames.length;
if (trimmed.value.elements.length) [].push.apply(args, trimmed.value.elements);
}
if (rest instanceof AST_Destructured && !rest.rest
&& (!node.uses_arguments || tt.has_directive("use strict"))) {
if (rest instanceof AST_DestructuredArray) {
@@ -6674,28 +6697,11 @@ Compressor.prototype.compress = function(node) {
}
node.rest = rest;
}
var argnames = node.argnames;
var trim = compressor.drop_fargs(node, parent) && !node.rest;
var default_length = trim ? -1 : node.length();
for (var i = argnames.length; --i >= 0;) {
var sym = argnames[i];
if (!(sym instanceof AST_SymbolFunarg)) {
var arg = sym.transform(trimmer);
if (arg) {
trim = false;
} else if (trim) {
log(sym.name, "Dropping unused default argument {name}");
argnames.pop();
} else if (i > default_length) {
log(sym.name, "Dropping unused default argument assignment {name}");
sym.name.unused = true;
argnames[i] = sym.name;
} else {
log(sym.name, "Dropping unused default argument value {name}");
sym.value = make_node(AST_Number, sym, { value: 0 });
}
continue;
}
if (sym instanceof AST_SymbolFunarg) {
var def = sym.definition();
if (def.id in in_use_ids) {
trim = false;
@@ -6706,6 +6712,29 @@ Compressor.prototype.compress = function(node) {
} else {
sym.unused = true;
}
} else {
var funarg;
if (!args || spread < i) {
funarg = sym.transform(trimmer);
} else {
funarg = trim_destructured(sym, args[i], function(node) {
return node.definition().id in in_use_ids ? node : null;
}, !node.uses_arguments, sym).name;
}
if (funarg) {
trim = false;
} else if (trim) {
log_default(sym, "Dropping unused default argument {name}");
argnames.pop();
} else if (i > default_length) {
log_default(sym, "Dropping unused default argument assignment {name}");
if (sym.name instanceof AST_SymbolFunarg) sym.name.unused = true;
argnames[i] = sym.name;
} else {
log_default(sym, "Dropping unused default argument value {name}");
sym.value = make_node(AST_Number, sym, { value: 0 });
}
}
}
fns_with_marked_args.push(node);
}
@@ -7049,6 +7078,19 @@ Compressor.prototype.compress = function(node) {
AST_Node[sym.definition().references.length > 0 ? "info" : "warn"](text + " [{file}:{line},{col}]", template(sym));
}
function log_default(node, text) {
if (node.name instanceof AST_SymbolFunarg) {
log(node.name, text);
} else {
AST_Node.info(text + " [{file}:{line},{col}]", {
name: node.print_to_string(),
file: node.start.file,
line: node.start.line,
col : node.start.col,
});
}
}
function template(sym) {
return {
name: sym.name,
@@ -7245,18 +7287,20 @@ Compressor.prototype.compress = function(node) {
return node;
}
function trim_destructured(node, value, process, drop) {
function trim_destructured(node, value, process, drop, root) {
var trimmer = new TreeTransformer(function(node) {
if (node instanceof AST_DefaultValue) {
if (compressor.option("default_values") && value && value.is_defined(compressor)) {
node = node.name;
} else {
if (!(compressor.option("default_values") && value && value.is_defined(compressor))) {
var save_drop = drop;
drop = false;
var trimmed = trim_default(trimmer, node);
drop = save_drop;
if (!trimmed && drop && value) value = value.drop_side_effect_free(compressor);
return trimmed;
} else if (node === root) {
root = node = node.name;
} else {
node = node.name;
}
}
if (node instanceof AST_DestructuredArray) {
@@ -7319,10 +7363,12 @@ Compressor.prototype.compress = function(node) {
if (!node.rest && (value instanceof AST_Array
|| value && value.is_string(compressor))) switch (elements.length) {
case 0:
if (node === root) break;
if (drop) value = value.drop_side_effect_free(compressor);
return null;
case 1:
if (!drop) break;
if (node === root) break;
var sym = elements[0];
if (sym.has_side_effects(compressor)) break;
if (value.has_side_effects(compressor) && sym.match_symbol(function(node) {
@@ -7446,11 +7492,13 @@ Compressor.prototype.compress = function(node) {
});
if (value && !node.rest) switch (properties.length) {
case 0:
if (node === root) break;
if (value.may_throw_on_access(compressor, true)) break;
if (drop) value = value.drop_side_effect_free(compressor);
return null;
case 1:
if (!drop) break;
if (node === root) break;
var prop = properties[0];
if (prop.key instanceof AST_Node) break;
if (prop.value.has_side_effects(compressor)) break;

View File

@@ -2038,3 +2038,59 @@ issue_5222: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5246_1: {
options = {
pure_getters: true,
unused: true,
}
input: {
console.log(function({} = 42) {
return "PASS";
}("foo"));
}
expect: {
console.log(function({} = 0) {
return "PASS";
}("foo"));
}
expect_stdout: "PASS"
expect_warnings: [
"INFO: Dropping unused default argument value {}=42 [test/compress/default-values.js:1,29]",
"INFO: Dropping unused default argument value {}=0 [test/compress/default-values.js:1,29]",
]
node_version: ">=6"
}
issue_5246_2: {
options = {
unused: true,
}
input: {
(function f(a = "FAIL", [] = 42) {
console.log(a);
})("PASS", []);
}
expect: {
(function(a = "FAIL", []) {
console.log(a);
})("PASS", []);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5246_3: {
options = {
default_values: true,
unused: true,
}
input: {
console.log(function f([ , {} ] = null){}([ , {} ]));
}
expect: {
console.log(function([ {} ]){}([ {} ]));
}
expect_stdout: "undefined"
node_version: ">=6"
}

View File

@@ -359,7 +359,7 @@ retain_funarg_destructured_object_2: {
expect: {
console.log(function({ p: a, ... b }) {
return b;
}({ p: "FAIL" }).p || "PASS");
}({}).p || "PASS");
}
expect_stdout: "PASS"
node_version: ">=8.3.0"
@@ -1104,7 +1104,7 @@ issue_5108: {
expect: {
console.log(function([]) {
return "PASS";
}([ "PASS", "FAIL" ]));
}([]));
}
expect_stdout: "PASS"
node_version: ">=6"
@@ -1205,3 +1205,62 @@ issue_5165_2: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5246_1: {
options = {
reduce_vars: true,
rests: true,
unused: true,
}
input: {
console.log(typeof function([ , ...a ]) {
return this && a;
}([ , function(){} ])[0]);
}
expect: {
console.log(typeof function([]) {
return this && [ function(){} ];
}([])[0]);
}
expect_stdout: "function"
node_version: ">=6"
}
issue_5246_2: {
options = {
reduce_vars: true,
rests: true,
toplevel: true,
unused: true,
}
input: {
A = [ , "PASS", "FAIL" ];
var [ , ...a ] = [ ... A ];
console.log(a[0]);
}
expect: {
A = [ , "PASS", "FAIL" ];
var [ , ...a ] = [ ... A ];
console.log(a[0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5246_3: {
options = {
unused: true,
}
input: {
(function f(...[ [ a ] ]) {
console.log(a);
})([ "PASS" ]);
}
expect: {
(function(...[ a ]) {
console.log(a);
})([ "PASS" ][0]);
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -1371,12 +1371,12 @@ issue_5034: {
node_version: ">=4"
}
issue_5076: {
issue_5076_1: {
options = {
evaluate: true,
hoist_vars: true,
passes: 2,
pure_getters: "strict",
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
@@ -1393,13 +1393,41 @@ issue_5076: {
}
expect: {
var a;
console.log("PASS");
console.log("PASS"),
a = 42["a"];
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5076_2: {
options = {
evaluate: true,
hoist_vars: true,
passes: 2,
pure_getters: "strict",
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
console.log("PASS");
var b = function*({
p: {},
}) {}({
p: { a } = 42,
});
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5177: {
options = {
properties: true,