From ced32f9bd87e3fdc693412d1bdc924a99ecc9712 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 24 Dec 2020 23:31:34 +0000 Subject: [PATCH] enhance `default_values` (#4450) --- lib/compress.js | 157 ++++++++++++++++++-------------- test/compress/default-values.js | 64 +++++++++++++ 2 files changed, 154 insertions(+), 67 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 2c1f87d1..a6615773 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -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) { diff --git a/test/compress/default-values.js b/test/compress/default-values.js index 8b9b3a95..bda32c1b 100644 --- a/test/compress/default-values.js +++ b/test/compress/default-values.js @@ -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, -- 2.34.1