enhance `collapse_vars` (#3697)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 29 Jan 2020 00:52:20 +0000 (08:52 +0800)
committerGitHub <noreply@github.com>
Wed, 29 Jan 2020 00:52:20 +0000 (08:52 +0800)
lib/compress.js
test/compress/collapse_vars.js

index 9b054ca..85ad449 100644 (file)
@@ -1382,7 +1382,34 @@ merge(Compressor.prototype, {
             }
 
             function is_last_node(node, parent) {
-                if (node instanceof AST_Call) return true;
+                if (node instanceof AST_Call) {
+                    var fn = node.expression;
+                    if (fn instanceof AST_SymbolRef) fn = fn.fixed_value();
+                    if (!(fn instanceof AST_Lambda)) return true;
+                    if (fn.collapse_scanning) return false;
+                    fn.collapse_scanning = true;
+                    var replace = can_replace;
+                    can_replace = false;
+                    var after = stop_after;
+                    var if_hit = stop_if_hit;
+                    var rhs_fn = scan_rhs;
+                    for (var i = 0; !abort && i < fn.body.length; i++) {
+                        var stat = fn.body[i];
+                        if (stat instanceof AST_Exit) {
+                            if (stat.value) stat.value.transform(scanner);
+                            break;
+                        }
+                        stat.transform(scanner);
+                    }
+                    scan_rhs = rhs_fn;
+                    stop_if_hit = if_hit;
+                    stop_after = after;
+                    can_replace = replace;
+                    delete fn.collapse_scanning;
+                    if (!abort) return false;
+                    abort = false;
+                    return true;
+                }
                 if (node instanceof AST_Exit) {
                     if (in_try) {
                         if (in_try.bfinally) return true;
index c3832d4..4cd59a4 100644 (file)
@@ -7491,3 +7491,170 @@ issue_3671: {
     }
     expect_stdout: "1"
 }
+
+call_1: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        (function(a) {
+            a = console;
+            (function() {})();
+            a.log("PASS");
+        })();
+    }
+    expect: {
+        (function(a) {
+            (function() {})();
+            (a = console).log("PASS");
+        })();
+    }
+    expect_stdout: "PASS"
+}
+
+call_1_symbol: {
+    options = {
+        collapse_vars: true,
+        reduce_vars: true,
+    }
+    input: {
+        (function(a) {
+            function f() {}
+            a = console;
+            f();
+            a.log(typeof f);
+        })();
+    }
+    expect: {
+        (function(a) {
+            function f() {}
+            f();
+            (a = console).log(typeof f);
+        })();
+    }
+    expect_stdout: "function"
+}
+
+call_2: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        (function(a) {
+            a = console;
+            (function() {
+                return 42;
+                console.log("FAIL");
+            })();
+            a.log("PASS");
+        })();
+    }
+    expect: {
+        (function(a) {
+            (function() {
+                return 42;
+                console.log("FAIL");
+            })();
+            (a = console).log("PASS");
+        })();
+    }
+    expect_stdout: "PASS"
+}
+
+call_2_symbol: {
+    options = {
+        collapse_vars: true,
+        reduce_vars: true,
+    }
+    input: {
+        (function(a) {
+            function f() {
+                return 42;
+                console.log("FAIL");
+            }
+            a = console;
+            f();
+            a.log(typeof f);
+        })();
+    }
+    expect: {
+        (function(a) {
+            function f() {
+                return 42;
+                console.log("FAIL");
+            }
+            f();
+            (a = console).log(typeof f);
+        })();
+    }
+    expect_stdout: "function"
+}
+
+call_3: {
+    options = {
+        collapse_vars: true,
+    }
+    input: {
+        (function(a) {
+            a = console;
+            (function() {
+                a = {
+                    log: function() {
+                        console.log("PASS");
+                    }
+                }
+            })();
+            a.log("FAIL");
+        })();
+    }
+    expect: {
+        (function(a) {
+            a = console;
+            (function() {
+                a = {
+                    log: function() {
+                        console.log("PASS");
+                    }
+                }
+            })();
+            a.log("FAIL");
+        })();
+    }
+    expect_stdout: "PASS"
+}
+
+call_3_symbol: {
+    options = {
+        collapse_vars: true,
+        reduce_vars: true,
+    }
+    input: {
+        (function(a) {
+            function f() {
+                a = {
+                    log: function() {
+                        console.log(typeof f);
+                    }
+                }
+            }
+            a = console;
+            f();
+            a.log("FAIL");
+        })();
+    }
+    expect: {
+        (function(a) {
+            function f() {
+                a = {
+                    log: function() {
+                        console.log(typeof f);
+                    }
+                }
+            }
+            a = console;
+            f();
+            a.log("FAIL");
+        })();
+    }
+    expect_stdout: "function"
+}