fix corner cases with arrow functions (#4688)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 25 Feb 2021 01:01:45 +0000 (01:01 +0000)
committerGitHub <noreply@github.com>
Thu, 25 Feb 2021 01:01:45 +0000 (09:01 +0800)
fixes #4687

lib/compress.js
test/compress/arrows.js
test/compress/classes.js

index ae96b76..2b28c75 100644 (file)
@@ -2106,12 +2106,17 @@ merge(Compressor.prototype, {
                     } : function(node) {
                         return node instanceof AST_Await && !tw.find_parent(AST_Scope);
                     };
-                    var tw = new TreeWalker(function(node) {
+                    var arg_scope = null;
+                    var tw = new TreeWalker(function(node, descend) {
                         if (!arg) return true;
                         if (has_await(node) || node instanceof AST_Yield) {
                             arg = null;
                             return true;
                         }
+                        if (node instanceof AST_ObjectIdentity && (fn_strict || !arg_scope)) {
+                            arg = null;
+                            return true;
+                        }
                         if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
                             var s = node.definition().scope;
                             if (s !== scope) while (s = s.parent_scope) {
@@ -2119,10 +2124,11 @@ merge(Compressor.prototype, {
                             }
                             arg = null;
                         }
-                        if (node instanceof AST_ObjectIdentity && (fn_strict
-                            || !tw.find_parent(AST_Scope)
-                            || is_arrow(arg) && iife instanceof AST_New)) {
-                            arg = null;
+                        if (node instanceof AST_Scope && !is_arrow(node)) {
+                            var save_scope = arg_scope;
+                            arg_scope = node;
+                            descend();
+                            arg_scope = save_scope;
                             return true;
                         }
                     });
@@ -4977,7 +4983,7 @@ merge(Compressor.prototype, {
 
     // determine if expression is constant
     (function(def) {
-        function all(list) {
+        function all_constant(list) {
             for (var i = list.length; --i >= 0;)
                 if (!list[i].is_constant_expression())
                     return false;
@@ -4985,7 +4991,7 @@ merge(Compressor.prototype, {
         }
         def(AST_Node, return_false);
         def(AST_Array, function() {
-            return all(this.elements);
+            return all_constant(this.elements);
         });
         def(AST_Binary, function() {
             return this.left.is_constant_expression()
@@ -4993,7 +4999,7 @@ merge(Compressor.prototype, {
                 && (this.operator != "in" || is_object(this.right));
         });
         def(AST_Class, function() {
-            return !this.extends && all(this.properties);
+            return !this.extends && all_constant(this.properties);
         });
         def(AST_ClassProperty, function() {
             return typeof this.key == "string" && (!this.value || this.value.is_constant_expression());
@@ -5031,14 +5037,16 @@ merge(Compressor.prototype, {
                     return true;
                 }
                 if (node instanceof AST_ObjectIdentity) {
-                    if (scopes.length == 0 && is_arrow(self)) result = false;
+                    if (is_arrow(self) && all(scopes, function(s) {
+                        return !(s instanceof AST_Scope) || is_arrow(s);
+                    })) result = false;
                     return true;
                 }
             }));
             return result;
         });
         def(AST_Object, function() {
-            return all(this.properties);
+            return all_constant(this.properties);
         });
         def(AST_ObjectProperty, function() {
             return typeof this.key == "string" && this.value.is_constant_expression();
index a3a4687..6cb5522 100644 (file)
@@ -704,7 +704,7 @@ issue_4666: {
     node_version: ">=4"
 }
 
-issue_4685: {
+issue_4685_1: {
     options = {
         collapse_vars: true,
         unused: true,
@@ -724,3 +724,82 @@ issue_4685: {
     expect_stdout: "PASS"
     node_version: ">=4"
 }
+
+issue_4685_2: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        new function(f) {
+            if (f() !== this)
+                console.log("PASS");
+        }(() => {
+            if (console)
+                return this;
+        });
+    }
+    expect: {
+        new function(f) {
+            if (f() !== this)
+                console.log("PASS");
+        }(() => {
+            if (console)
+                return this;
+        });
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
+issue_4687_1: {
+    options = {
+        collapse_vars: true,
+        unused: true,
+    }
+    input: {
+        new function() {
+            console.log(function(f) {
+                return f() === this;
+            }(() => this) || "PASS");
+        }
+    }
+    expect: {
+        new function() {
+            console.log(function(f) {
+                return f() === this;
+            }(() => this) || "PASS");
+        }
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
+issue_4687_2: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        new function() {
+            console.log(function(f) {
+                return f() === this;
+            }(() => {
+                if (console)
+                    return this;
+            }) || "PASS");
+        }
+    }
+    expect: {
+        new function() {
+            console.log(function(f) {
+                return f() === this;
+            }(() => {
+                if (console)
+                    return this;
+            }) || "PASS");
+        }
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
index 95b4037..ab2652c 100644 (file)
@@ -615,3 +615,135 @@ issue_4683: {
     expect_stdout: "PASS"
     node_version: ">=4"
 }
+
+issue_4685_1: {
+    options = {
+        collapse_vars: true,
+        unused: true,
+    }
+    input: {
+        "use strict";
+        new class {
+            f() {
+                (function(g) {
+                    if (g() !== this)
+                        console.log("PASS");
+                })(() => this);
+            }
+        }().f();
+    }
+    expect: {
+        "use strict";
+        new class {
+            f() {
+                (function(g) {
+                    if (g() !== this)
+                        console.log("PASS");
+                })(() => this);
+            }
+        }().f();
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
+issue_4685_2: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        "use strict";
+        new class {
+            f() {
+                (function(g) {
+                    if (g() !== this)
+                        console.log("PASS");
+                })(() => {
+                    if (console)
+                        return this;
+                });
+            }
+        }().f();
+    }
+    expect: {
+        "use strict";
+        new class {
+            f() {
+                (function(g) {
+                    if (g() !== this)
+                        console.log("PASS");
+                })(() => {
+                    if (console)
+                        return this;
+                });
+            }
+        }().f();
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
+issue_4687_1: {
+    options = {
+        collapse_vars: true,
+        unused: true,
+    }
+    input: {
+        "use strict";
+        new class {
+            f() {
+                console.log(function(g) {
+                    return g() === this;
+                }(() => this) || "PASS");
+            }
+        }().f();
+    }
+    expect: {
+        "use strict";
+        new class {
+            f() {
+                console.log(function(g) {
+                    return g() === this;
+                }(() => this) || "PASS");
+            }
+        }().f();
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
+issue_4687_2: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        "use strict";
+        new class {
+            f() {
+                console.log(function(g) {
+                    return g() === this;
+                }(() => {
+                    if (console)
+                        return this;
+                }) || "PASS");
+            }
+        }().f();
+    }
+    expect: {
+        "use strict";
+        new class {
+            f() {
+                console.log(function(g) {
+                    return g() === this;
+                }(() => {
+                    if (console)
+                        return this;
+                }) || "PASS");
+            }
+        }().f();
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}