enhance default_values (#4450)

This commit is contained in:
Alex Lam S.L
2020-12-24 23:31:34 +00:00
committed by GitHub
parent dfc3ec9cef
commit ced32f9bd8
2 changed files with 154 additions and 67 deletions

View File

@@ -3361,6 +3361,7 @@ merge(Compressor.prototype, {
return this.consequent.is_defined(compressor) && this.alternative.is_defined(compressor);
});
def(AST_Constant, return_true);
def(AST_Hole, return_false);
def(AST_Lambda, return_true);
def(AST_Object, return_true);
def(AST_Sequence, function(compressor) {
@@ -5566,71 +5567,7 @@ merge(Compressor.prototype, {
node.definitions.forEach(function(def) {
if (def.value) def.value = def.value.transform(tt);
if (def.name instanceof AST_Destructured) {
var value = def.value;
var trimmer = new TreeTransformer(function(node) {
if (node instanceof AST_DefaultValue) return trim_default(tt, trimmer, node);
if (node instanceof AST_DestructuredArray) {
var save = value;
if (value instanceof AST_SymbolRef) value = value.fixed_value();
var values = value instanceof AST_Array && value.elements;
var elements = [];
node.elements.forEach(function(element, index) {
if (element instanceof AST_Hole) return;
value = values && values[index];
element = element.transform(trimmer);
if (element) elements[index] = element;
});
value = save;
if (values && elements.length == 0) return null;
for (var i = elements.length; --i >= 0;) {
if (!elements[i]) elements[i] = make_node(AST_Hole, node.elements[i] || node);
}
node.elements = elements;
return node;
}
if (node instanceof AST_DestructuredObject) {
var save = value;
if (value instanceof AST_SymbolRef) value = value.fixed_value();
var values;
if (value instanceof AST_Object) {
values = Object.create(null);
for (var i = 0; i < value.properties.length; i++) {
var prop = value.properties[i];
if (typeof prop.key != "string") {
values = null;
break;
}
values[prop.key] = prop.value;
}
}
var properties = [];
node.properties.forEach(function(prop) {
var retain;
if (prop.key instanceof AST_Node) {
prop.key = prop.key.transform(tt);
value = null;
retain = prop.key.has_side_effects(compressor);
} else {
value = values && values[prop.key];
retain = false;
}
if (retain && is_decl(prop.value)) {
properties.push(prop);
} else {
var newValue = prop.value.transform(trimmer);
if (newValue) {
prop.value = newValue;
properties.push(prop);
}
}
});
value = save;
if (properties.length == 0 && value && !value.may_throw_on_access(compressor)) {
return null;
}
node.properties = properties;
return node;
}
var name = trim_destructured(def.name, def.value, function(node) {
if (node instanceof AST_SymbolDeclaration) {
if (!drop_vars) return node;
if (node.definition().id in in_use_ids) return node;
@@ -5639,11 +5576,10 @@ merge(Compressor.prototype, {
return null;
}
});
var name = def.name.transform(trimmer);
if (name) {
flush();
} else {
value = value.drop_side_effect_free(compressor);
var value = def.value.drop_side_effect_free(compressor);
if (value) side_effects.push(value);
}
return;
@@ -5807,6 +5743,17 @@ merge(Compressor.prototype, {
}
return insert_statements(body, node, in_list);
}
if (node instanceof AST_Assign) {
descend(node, tt);
if (node.left instanceof AST_Destructured) {
var lhs = trim_destructured(node.left, node.right, function(node) {
if (node instanceof AST_SymbolRef) return node;
});
if (!lhs) return node.right;
node.left = lhs;
}
return node;
}
if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
// Certain combination of unused name + side effect leads to invalid AST:
// https://github.com/mishoo/UglifyJS/issues/1830
@@ -6094,6 +6041,82 @@ merge(Compressor.prototype, {
}
return node;
}
function trim_destructured(node, value, process) {
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 {
return trim_default(tt, trimmer, node);
}
}
if (node instanceof AST_DestructuredArray) {
var save = value;
if (value instanceof AST_SymbolRef) value = value.fixed_value();
var values = value instanceof AST_Array && value.elements;
var elements = [];
node.elements.forEach(function(element, index) {
if (element instanceof AST_Hole) return;
value = values && values[index];
element = element.transform(trimmer);
if (element) elements[index] = element;
});
value = save;
if (values && elements.length == 0) return null;
for (var i = elements.length; --i >= 0;) {
if (!elements[i]) elements[i] = make_node(AST_Hole, node.elements[i] || node);
}
node.elements = elements;
return node;
}
if (node instanceof AST_DestructuredObject) {
var save = value;
if (value instanceof AST_SymbolRef) value = value.fixed_value();
var values;
if (value instanceof AST_Object) {
values = Object.create(null);
for (var i = 0; i < value.properties.length; i++) {
var prop = value.properties[i];
if (typeof prop.key != "string") {
values = null;
break;
}
values[prop.key] = prop.value;
}
}
var properties = [];
node.properties.forEach(function(prop) {
var retain;
if (prop.key instanceof AST_Node) {
prop.key = prop.key.transform(tt);
value = null;
retain = prop.key.has_side_effects(compressor);
} else {
value = values && values[prop.key];
retain = false;
}
if (retain && is_decl(prop.value)) {
properties.push(prop);
} else {
var newValue = prop.value.transform(trimmer);
if (newValue) {
prop.value = newValue;
properties.push(prop);
}
}
});
value = save;
if (properties.length == 0 && value && !value.may_throw_on_access(compressor)) {
return null;
}
node.properties = properties;
return node;
}
return process(node);
});
return node.transform(trimmer);
}
});
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {

View File

@@ -543,6 +543,70 @@ unused_var_2: {
node_version: ">=6"
}
unused_value_assign_1: {
options = {
default_values: true,
unused: true,
}
input: {
[] = [ console.log("PASS") ];
}
expect: {
[ console.log("PASS") ];
}
expect_stdout: "PASS"
node_version: ">=6"
}
unused_value_assign_2: {
options = {
default_values: true,
unused: true,
}
input: {
[ a = console.log("FAIL") ] = [ "PASS" ];
console.log(a);
}
expect: {
[ a ] = [ "PASS" ];
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
unused_value_var_1: {
options = {
default_values: true,
unused: true,
}
input: {
var [] = [ console.log("PASS") ];
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
unused_value_var_2: {
options = {
default_values: true,
unused: true,
}
input: {
var [ a = console.log("FAIL") ] = [ "PASS" ];
console.log(a);
}
expect: {
var [ a ] = [ "PASS" ];
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
mangle_var_1: {
mangle = {
toplevel: false,