fix corner case in `reduce_vars` (#3141)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 21 May 2018 07:53:51 +0000 (15:53 +0800)
committerGitHub <noreply@github.com>
Mon, 21 May 2018 07:53:51 +0000 (15:53 +0800)
fixes #3140

lib/compress.js
test/compress/reduce_vars.js

index efc7c47..498729d 100644 (file)
@@ -380,6 +380,16 @@ merge(Compressor.prototype, {
                     mark(tw, def, true);
                 }
             });
+            scope.may_call_this = function() {
+                scope.may_call_this = noop;
+                if (!scope.contains_this()) return;
+                scope.functions.each(function(def) {
+                    if (def.init instanceof AST_Defun && !(def.id in tw.defun_ids)) {
+                        tw.defun_ids[def.id] = false;
+                    }
+                });
+                return true;
+            };
         }
 
         function mark_defun(tw, def) {
@@ -556,6 +566,7 @@ merge(Compressor.prototype, {
             return true;
         });
         def(AST_Call, function(tw, descend) {
+            if (tw.find_parent(AST_Scope).may_call_this()) return;
             var exp = this.expression;
             if (!(exp instanceof AST_SymbolRef)) return;
             var def = exp.definition();
@@ -6278,7 +6289,7 @@ merge(Compressor.prototype, {
         return self;
     });
 
-    AST_Lambda.DEFMETHOD("contains_this", function() {
+    AST_Scope.DEFMETHOD("contains_this", function() {
         var result;
         var self = this;
         self.walk(new TreeWalker(function(node) {
index ac55f81..626893f 100644 (file)
@@ -6178,3 +6178,192 @@ issue_3125: {
     }
     expect_stdout: "7"
 }
+
+issue_3140_1: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                this();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                this();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3140_2: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                var self = this;
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                self();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                this();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3140_3: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                var self = this;
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                (function() {
+                    return self;
+                })()();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                var self = this;
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                (function() {
+                    return self;
+                })()();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3140_4: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                var o = {
+                    p: this
+                };
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                o.p();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect: {
+        (function() {
+            var a;
+            function f() {
+            }
+            f.g = function g() {
+                var o = {
+                    p: this
+                };
+                function h() {
+                    console.log(a ? "PASS" : "FAIL");
+                }
+                a = true;
+                o.p();
+                a = false;
+                h.g = g;
+                return h;
+            };
+            return f;
+        })().g().g();
+    }
+    expect_stdout: "PASS"
+}