100
lib/compress.js
100
lib/compress.js
@@ -784,8 +784,11 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (save) fixed = compressor.option("rests") && function() {
|
if (save) fixed = compressor.option("rests") && function() {
|
||||||
var value = save();
|
var value = save();
|
||||||
if (!(value instanceof AST_Array)) return node;
|
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);
|
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;
|
return fixed_node;
|
||||||
};
|
};
|
||||||
node.rest.walk(scanner);
|
node.rest.walk(scanner);
|
||||||
@@ -6662,8 +6665,28 @@ Compressor.prototype.compress = function(node) {
|
|||||||
unused_fn_names.push(node);
|
unused_fn_names.push(node);
|
||||||
}
|
}
|
||||||
if (!(node instanceof AST_Accessor)) {
|
if (!(node instanceof AST_Accessor)) {
|
||||||
if (node.rest) {
|
var args, spread;
|
||||||
var rest = node.rest.transform(trimmer);
|
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
|
if (rest instanceof AST_Destructured && !rest.rest
|
||||||
&& (!node.uses_arguments || tt.has_directive("use strict"))) {
|
&& (!node.uses_arguments || tt.has_directive("use strict"))) {
|
||||||
if (rest instanceof AST_DestructuredArray) {
|
if (rest instanceof AST_DestructuredArray) {
|
||||||
@@ -6674,37 +6697,43 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
node.rest = rest;
|
node.rest = rest;
|
||||||
}
|
}
|
||||||
var argnames = node.argnames;
|
|
||||||
var trim = compressor.drop_fargs(node, parent) && !node.rest;
|
var trim = compressor.drop_fargs(node, parent) && !node.rest;
|
||||||
var default_length = trim ? -1 : node.length();
|
var default_length = trim ? -1 : node.length();
|
||||||
for (var i = argnames.length; --i >= 0;) {
|
for (var i = argnames.length; --i >= 0;) {
|
||||||
var sym = argnames[i];
|
var sym = argnames[i];
|
||||||
if (!(sym instanceof AST_SymbolFunarg)) {
|
if (sym instanceof AST_SymbolFunarg) {
|
||||||
var arg = sym.transform(trimmer);
|
var def = sym.definition();
|
||||||
if (arg) {
|
if (def.id in in_use_ids) {
|
||||||
|
trim = false;
|
||||||
|
if (indexOf_assign(def, sym) < 0) sym.unused = null;
|
||||||
|
} else if (trim) {
|
||||||
|
log(sym, "Dropping unused function argument {name}");
|
||||||
|
argnames.pop();
|
||||||
|
} 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;
|
trim = false;
|
||||||
} else if (trim) {
|
} else if (trim) {
|
||||||
log(sym.name, "Dropping unused default argument {name}");
|
log_default(sym, "Dropping unused default argument {name}");
|
||||||
argnames.pop();
|
argnames.pop();
|
||||||
} else if (i > default_length) {
|
} else if (i > default_length) {
|
||||||
log(sym.name, "Dropping unused default argument assignment {name}");
|
log_default(sym, "Dropping unused default argument assignment {name}");
|
||||||
sym.name.unused = true;
|
if (sym.name instanceof AST_SymbolFunarg) sym.name.unused = true;
|
||||||
argnames[i] = sym.name;
|
argnames[i] = sym.name;
|
||||||
} else {
|
} else {
|
||||||
log(sym.name, "Dropping unused default argument value {name}");
|
log_default(sym, "Dropping unused default argument value {name}");
|
||||||
sym.value = make_node(AST_Number, sym, { value: 0 });
|
sym.value = make_node(AST_Number, sym, { value: 0 });
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var def = sym.definition();
|
|
||||||
if (def.id in in_use_ids) {
|
|
||||||
trim = false;
|
|
||||||
if (indexOf_assign(def, sym) < 0) sym.unused = null;
|
|
||||||
} else if (trim) {
|
|
||||||
log(sym, "Dropping unused function argument {name}");
|
|
||||||
argnames.pop();
|
|
||||||
} else {
|
|
||||||
sym.unused = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fns_with_marked_args.push(node);
|
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));
|
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) {
|
function template(sym) {
|
||||||
return {
|
return {
|
||||||
name: sym.name,
|
name: sym.name,
|
||||||
@@ -7245,18 +7287,20 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
function trim_destructured(node, value, process, drop) {
|
function trim_destructured(node, value, process, drop, root) {
|
||||||
var trimmer = new TreeTransformer(function(node) {
|
var trimmer = new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_DefaultValue) {
|
if (node instanceof AST_DefaultValue) {
|
||||||
if (compressor.option("default_values") && value && value.is_defined(compressor)) {
|
if (!(compressor.option("default_values") && value && value.is_defined(compressor))) {
|
||||||
node = node.name;
|
|
||||||
} else {
|
|
||||||
var save_drop = drop;
|
var save_drop = drop;
|
||||||
drop = false;
|
drop = false;
|
||||||
var trimmed = trim_default(trimmer, node);
|
var trimmed = trim_default(trimmer, node);
|
||||||
drop = save_drop;
|
drop = save_drop;
|
||||||
if (!trimmed && drop && value) value = value.drop_side_effect_free(compressor);
|
if (!trimmed && drop && value) value = value.drop_side_effect_free(compressor);
|
||||||
return trimmed;
|
return trimmed;
|
||||||
|
} else if (node === root) {
|
||||||
|
root = node = node.name;
|
||||||
|
} else {
|
||||||
|
node = node.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node instanceof AST_DestructuredArray) {
|
if (node instanceof AST_DestructuredArray) {
|
||||||
@@ -7319,10 +7363,12 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!node.rest && (value instanceof AST_Array
|
if (!node.rest && (value instanceof AST_Array
|
||||||
|| value && value.is_string(compressor))) switch (elements.length) {
|
|| value && value.is_string(compressor))) switch (elements.length) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (node === root) break;
|
||||||
if (drop) value = value.drop_side_effect_free(compressor);
|
if (drop) value = value.drop_side_effect_free(compressor);
|
||||||
return null;
|
return null;
|
||||||
case 1:
|
case 1:
|
||||||
if (!drop) break;
|
if (!drop) break;
|
||||||
|
if (node === root) break;
|
||||||
var sym = elements[0];
|
var sym = elements[0];
|
||||||
if (sym.has_side_effects(compressor)) break;
|
if (sym.has_side_effects(compressor)) break;
|
||||||
if (value.has_side_effects(compressor) && sym.match_symbol(function(node) {
|
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) {
|
if (value && !node.rest) switch (properties.length) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (node === root) break;
|
||||||
if (value.may_throw_on_access(compressor, true)) break;
|
if (value.may_throw_on_access(compressor, true)) break;
|
||||||
if (drop) value = value.drop_side_effect_free(compressor);
|
if (drop) value = value.drop_side_effect_free(compressor);
|
||||||
return null;
|
return null;
|
||||||
case 1:
|
case 1:
|
||||||
if (!drop) break;
|
if (!drop) break;
|
||||||
|
if (node === root) break;
|
||||||
var prop = properties[0];
|
var prop = properties[0];
|
||||||
if (prop.key instanceof AST_Node) break;
|
if (prop.key instanceof AST_Node) break;
|
||||||
if (prop.value.has_side_effects(compressor)) break;
|
if (prop.value.has_side_effects(compressor)) break;
|
||||||
|
|||||||
@@ -2038,3 +2038,59 @@ issue_5222: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ retain_funarg_destructured_object_2: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function({ p: a, ... b }) {
|
console.log(function({ p: a, ... b }) {
|
||||||
return b;
|
return b;
|
||||||
}({ p: "FAIL" }).p || "PASS");
|
}({}).p || "PASS");
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=8.3.0"
|
node_version: ">=8.3.0"
|
||||||
@@ -1104,7 +1104,7 @@ issue_5108: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function([]) {
|
console.log(function([]) {
|
||||||
return "PASS";
|
return "PASS";
|
||||||
}([ "PASS", "FAIL" ]));
|
}([]));
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
@@ -1205,3 +1205,62 @@ issue_5165_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1371,12 +1371,12 @@ issue_5034: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_5076: {
|
issue_5076_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
hoist_vars: true,
|
hoist_vars: true,
|
||||||
passes: 2,
|
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -1393,13 +1393,41 @@ issue_5076: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
var a;
|
||||||
console.log("PASS");
|
console.log("PASS"),
|
||||||
a = 42["a"];
|
a = 42["a"];
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
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: {
|
issue_5177: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user