enhance `default_values` (#4450)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 24 Dec 2020 23:31:34 +0000 (23:31 +0000)
committerGitHub <noreply@github.com>
Thu, 24 Dec 2020 23:31:34 +0000 (07:31 +0800)
lib/compress.js
test/compress/default-values.js

index 2c1f87d..a661577 100644 (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) {
index 8b9b3a9..bda32c1 100644 (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,