fix corner case in `unused` (#4362)
authorAlex Lam S.L <alexlamsl@gmail.com>
Fri, 11 Dec 2020 16:57:05 +0000 (16:57 +0000)
committerGitHub <noreply@github.com>
Fri, 11 Dec 2020 16:57:05 +0000 (00:57 +0800)
fixes #4361

lib/compress.js
test/compress/spread.js

index cb3351a..1862fd1 100644 (file)
@@ -4260,6 +4260,22 @@ merge(Compressor.prototype, {
         return map && map[prop];
     });
 
+    function spread_side_effects(exp) {
+        while ((exp = exp.tail_node()) instanceof AST_SymbolRef) {
+            exp = exp.fixed_value();
+            if (!exp) return true;
+        }
+        return !(exp instanceof AST_Array
+            || exp.TYPE == "Binary" && !lazy_op[exp.operator]
+            || exp instanceof AST_Constant
+            || exp instanceof AST_Lambda
+            || exp instanceof AST_Object && all(exp.properties, function(prop) {
+                return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);
+            })
+            || exp instanceof AST_This
+            || exp instanceof AST_Unary);
+    }
+
     // determine if expression has side effects
     (function(def) {
         function any(list, compressor, spread) {
@@ -4340,19 +4356,7 @@ merge(Compressor.prototype, {
         def(AST_Object, function(compressor) {
             return any(this.properties, compressor, function(node, compressor) {
                 var exp = node.expression;
-                if (exp instanceof AST_Object) return true;
-                if (exp instanceof AST_PropAccess) return true;
-                if (exp instanceof AST_SymbolRef) {
-                    exp = exp.fixed_value();
-                    if (!exp) return true;
-                    if (exp instanceof AST_SymbolRef) return true;
-                    if (exp instanceof AST_PropAccess) return true;
-                    if (!(exp instanceof AST_Object)) return false;
-                    return !all(exp.properties, function(prop) {
-                        return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);
-                    });
-                }
-                return exp.has_side_effects(compressor);
+                return spread_side_effects(exp) || exp.has_side_effects(compressor);
             });
         });
         def(AST_ObjectProperty, function(compressor) {
@@ -6459,24 +6463,8 @@ merge(Compressor.prototype, {
                 }
             });
             var values = trim(exprs, compressor, first_in_statement, function(node, compressor, first_in_statement) {
-                var exp = node.expression.tail_node();
-                if (exp instanceof AST_SymbolRef) {
-                    exp = exp.fixed_value();
-                    if (!exp) return node;
-                    exp = exp.tail_node();
-                }
-                if (exp instanceof AST_Array
-                    || exp.TYPE == "Binary" && !lazy_op[exp.operator]
-                    || exp instanceof AST_Constant
-                    || exp instanceof AST_Lambda
-                    || exp instanceof AST_Object && all(exp.properties, function(prop) {
-                        return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);
-                    })
-                    || exp instanceof AST_This
-                    || exp instanceof AST_Unary) {
-                    return node.expression.drop_side_effect_free(compressor, first_in_statement);
-                }
-                return node;
+                var exp = node.expression;
+                return spread_side_effects(exp) ? node : exp.drop_side_effect_free(compressor, first_in_statement);
             });
             if (!values) return null;
             if (values === exprs && !all(values, function(node) {
index 32ed0b8..8af7bff 100644 (file)
@@ -728,3 +728,33 @@ issue_4345: {
     expect_stdout: "PASS"
     node_version: ">=8"
 }
+
+issue_4361: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        console.log(function() {
+            var a = console.log("foo");
+            console;
+            var b = {
+                ...a,
+            };
+        }());
+    }
+    expect: {
+        console.log(function() {
+            var a = console.log("foo");
+            console;
+            ({
+                ...a,
+            });
+        }());
+    }
+    expect_stdout: [
+        "foo",
+        "undefined",
+    ]
+    node_version: ">=8"
+}