unwind IIFE class patterns (#3373)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 21 Apr 2019 01:49:07 +0000 (09:49 +0800)
committerGitHub <noreply@github.com>
Sun, 21 Apr 2019 01:49:07 +0000 (09:49 +0800)
fixes #2332

lib/compress.js
test/compress/collapse_vars.js
test/compress/functions.js

index 2fd3609..8708280 100644 (file)
@@ -1287,7 +1287,9 @@ merge(Compressor.prototype, {
                 if (node instanceof AST_Try) return true;
                 if (node instanceof AST_With) return true;
                 if (replace_all) return false;
-                return node instanceof AST_SymbolRef && !node.is_declared(compressor);
+                return node instanceof AST_SymbolRef
+                    && !node.is_declared(compressor)
+                    && !(parent instanceof AST_Assign && parent.left === node);
             }
 
             function in_conditional(node, parent) {
@@ -5102,7 +5104,7 @@ merge(Compressor.prototype, {
                     })) {
                         return false;
                     }
-                } else if (line instanceof AST_EmptyStatement) {
+                } else if (line instanceof AST_Defun || line instanceof AST_EmptyStatement) {
                     continue;
                 } else if (stat) {
                     return false;
@@ -5113,16 +5115,15 @@ merge(Compressor.prototype, {
             return return_value(stat);
         }
 
+        function var_exists(catches, name) {
+            return catches[name] || identifier_atom[name] || scope.var_names()[name];
+        }
+
         function can_inject_args(catches, safe_to_inject) {
             for (var i = 0; i < fn.argnames.length; i++) {
                 var arg = fn.argnames[i];
                 if (arg.__unused) continue;
-                if (!safe_to_inject
-                    || catches[arg.name]
-                    || identifier_atom[arg.name]
-                    || scope.var_names()[arg.name]) {
-                    return false;
-                }
+                if (!safe_to_inject || var_exists(catches, arg.name)) return false;
                 if (in_loop) in_loop.push(arg.definition());
             }
             return true;
@@ -5131,15 +5132,15 @@ merge(Compressor.prototype, {
         function can_inject_vars(catches, safe_to_inject) {
             for (var i = 0; i < fn.body.length; i++) {
                 var stat = fn.body[i];
+                if (stat instanceof AST_Defun) {
+                    if (!safe_to_inject || var_exists(catches, stat.name.name)) return false;
+                    continue;
+                }
                 if (!(stat instanceof AST_Var)) continue;
                 if (!safe_to_inject) return false;
                 for (var j = stat.definitions.length; --j >= 0;) {
                     var name = stat.definitions[j].name;
-                    if (catches[name.name]
-                        || identifier_atom[name.name]
-                        || scope.var_names()[name.name]) {
-                        return false;
-                    }
+                    if (var_exists(catches, name.name)) return false;
                     if (in_loop) in_loop.push(name.definition());
                 }
             }
@@ -5243,12 +5244,21 @@ merge(Compressor.prototype, {
             flatten_args(decls, expressions);
             flatten_vars(decls, expressions);
             expressions.push(value);
-            if (decls.length) {
-                i = scope.body.indexOf(compressor.parent(level - 1)) + 1;
-                scope.body.splice(i, 0, make_node(AST_Var, fn, {
-                    definitions: decls
-                }));
-            }
+            var args = fn.body.filter(function(stat) {
+                if (stat instanceof AST_Defun) {
+                    var def = stat.name.definition();
+                    scope.functions.set(def.name, def);
+                    scope.variables.set(def.name, def);
+                    scope.enclosed.push(def);
+                    scope.var_names()[def.name] = true;
+                    return true;
+                }
+            });
+            args.unshift(scope.body.indexOf(compressor.parent(level - 1)) + 1, 0);
+            if (decls.length) args.push(make_node(AST_Var, fn, {
+                definitions: decls
+            }));
+            [].splice.apply(scope.body, args);
             return expressions;
         }
     });
index 22a8d7a..470f3b7 100644 (file)
@@ -6157,3 +6157,24 @@ sub_property: {
     }
     expect_stdout: "PASS"
 }
+
+assign_undeclared: {
+    options = {
+        collapse_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var A = (console.log(42), function() {});
+        B = new A();
+        console.log(typeof B);
+    }
+    expect: {
+        B = new (console.log(42), function() {})();
+        console.log(typeof B);
+    }
+    expect_stdout: [
+        "42",
+        "object",
+    ]
+}
index 983d706..e12ce3e 100644 (file)
@@ -3003,12 +3003,10 @@ issue_3366: {
         f();
     }
     expect: {
-        (function() {
-            function a() {}
-            (function() {
-                this && a && console.log("PASS");
-            })();
-        })();
+        void function() {
+            this && a && console.log("PASS");
+        }();
+        function a() {}
     }
     expect_stdout: "PASS"
 }
@@ -3041,3 +3039,29 @@ issue_3371: {
     }
     expect_stdout: "function"
 }
+
+class_iife: {
+    options = {
+        inline: true,
+        sequences: true,
+        toplevel: true,
+    }
+    input: {
+        var A = function() {
+            function B() {}
+            B.prototype.m = function() {
+                console.log("PASS");
+            };
+            return B;
+        }();
+        new A().m();
+    }
+    expect: {
+        var A = (B.prototype.m = function() {
+            console.log("PASS");
+        }, B);
+        function B() {}
+        new A().m();
+    }
+    expect_stdout: "PASS"
+}