enhance "functions" (#4791)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 16 Mar 2021 21:38:33 +0000 (21:38 +0000)
committerGitHub <noreply@github.com>
Tue, 16 Mar 2021 21:38:33 +0000 (05:38 +0800)
lib/compress.js
test/compress/awaits.js
test/compress/functions.js
test/compress/yields.js

index 7264153..f8b9c8c 100644 (file)
@@ -6203,8 +6203,8 @@ merge(Compressor.prototype, {
                             && value instanceof AST_LambdaExpression
                             && !is_arrow(value)
                             && assigned_once(value, sym.references)
-                            && can_declare_defun()
-                            && can_rename(value, def.name.name)) {
+                            && can_declare_defun(value)
+                            && (old_def = rename_def(value, def.name.name)) !== false) {
                             AST_Node.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
                             var ctor;
                             switch (value.CTOR) {
@@ -6269,27 +6269,26 @@ merge(Compressor.prototype, {
                         });
                     }
 
-                    function can_declare_defun() {
-                        if (compressor.has_directive("use strict")) return parent instanceof AST_Scope;
+                    function can_declare_defun(fn) {
+                        if (compressor.has_directive("use strict") || !(fn instanceof AST_Function)) {
+                            return parent instanceof AST_Scope;
+                        }
                         return parent instanceof AST_Block
                             || parent instanceof AST_For && parent.init === node
                             || parent instanceof AST_If;
                     }
 
-                    function can_rename(fn, name) {
-                        if (!fn.name) return !fn.variables.get(name);
-                        old_def = fn.name.definition();
-                        if (old_def.orig.length > 1) {
-                            old_def = null;
-                        } else {
-                            if (old_def.assignments > 0) return false;
-                            if (old_def.name == name) return true;
-                        }
+                    function rename_def(fn, name) {
+                        if (!fn.name) return null;
+                        var def = fn.name.definition();
+                        if (def.orig.length > 1) return null;
+                        if (def.assignments > 0) return false;
+                        if (def.name == name) return def;
                         if (name == "await" && is_async(fn)) return false;
                         if (name == "yield" && is_generator(fn)) return false;
-                        return !old_def || all(old_def.references, function(ref) {
+                        return all(def.references, function(ref) {
                             return ref.scope.find_variable(name) === sym;
-                        });
+                        }) && def;
                     }
 
                     function is_catch(node) {
index be3cc5a..8882f1e 100644 (file)
@@ -614,14 +614,14 @@ functions: {
             async function b() {
                 return !!b;
             }
-            var c = async function(c) {
+            async function c(c) {
                 return c;
-            };
+            }
             if (await c(await b(await a()))) {
-                async function d() {}
-                async function e() {
-                    return typeof e;
-                }
+                var d = async function() {};
+                var e = async function y() {
+                    return typeof y;
+                };
                 var f = async function(f) {
                     return f;
                 };
@@ -672,9 +672,9 @@ functions_use_strict: {
             async function b() {
                 return !!b;
             }
-            var c = async function(c) {
+            async function c(c) {
                 return c;
-            };
+            }
             if (await c(await b(await a()))) {
                 var d = async function() {};
                 var e = async function y() {
@@ -691,6 +691,54 @@ functions_use_strict: {
     node_version: ">=8"
 }
 
+functions_anonymous: {
+    options = {
+        functions: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var await = async function() {
+            console.log("PASS");
+        };
+        await(await);
+    }
+    expect: {
+        async function await() {
+            console.log("PASS");
+        }
+        await();
+    }
+    expect_stdout: "PASS"
+    node_version: ">=8"
+}
+
+functions_inner_var: {
+    options = {
+        functions: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var await = function a() {
+            var a;
+            console.log(a, a);
+        };
+        await(await);
+    }
+    expect: {
+        function await() {
+            var a;
+            console.log(a, a);
+        }
+        await();
+    }
+    expect_stdout: "undefined undefined"
+    node_version: ">=8"
+}
+
 issue_4335_1: {
     options = {
         inline: true,
index e43efce..2c529f0 100644 (file)
@@ -2751,17 +2751,17 @@ functions: {
             function b() {
                 return !!b;
             }
-            var c = function(c) {
+            function c(c) {
                 return c;
-            };
+            }
             if (c(b(a()))) {
                 function d() {}
                 function e() {
                     return typeof e;
                 }
-                var f = function(f) {
+                function f(f) {
                     return f;
-                };
+                }
                 console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);
             }
         }();
@@ -2808,9 +2808,9 @@ functions_use_strict: {
             function b() {
                 return !!b;
             }
-            var c = function(c) {
+            function c(c) {
                 return c;
-            };
+            }
             if (c(b(a()))) {
                 var d = function() {};
                 var e = function y() {
@@ -2826,6 +2826,30 @@ functions_use_strict: {
     expect_stdout: "a true 42 function function function"
 }
 
+functions_inner_var: {
+    options = {
+        functions: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a = function() {
+            var a;
+            console.log(a, a);
+        };
+        a(a);
+    }
+    expect: {
+        function a() {
+            var a;
+            console.log(a, a);
+        }
+        a();
+    }
+    expect_stdout: "undefined undefined"
+}
+
 issue_2437: {
     options = {
         collapse_vars: true,
index 06f46c9..05972e5 100644 (file)
@@ -388,14 +388,14 @@ functions: {
             function* b() {
                 return !!b;
             }
-            var c = function*(c) {
+            function* c(c) {
                 return c;
-            };
+            }
             if (yield* c(yield* b(yield* a()))) {
-                function* d() {}
-                function* e() {
-                    return typeof e;
-                }
+                var d = function*() {};
+                var e = function* y() {
+                    return typeof y;
+                };
                 var f = function*(f) {
                     return f;
                 };
@@ -446,9 +446,9 @@ functions_use_strict: {
             function* b() {
                 return !!b;
             }
-            var c = function*(c) {
+            function* c(c) {
                 return c;
-            };
+            }
             if (yield* c(yield* b(yield* a()))) {
                 var d = function*() {};
                 var e = function* y() {
@@ -465,6 +465,54 @@ functions_use_strict: {
     node_version: ">=4"
 }
 
+functions_anonymous: {
+    options = {
+        functions: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var yield = function*() {
+            return "PASS";
+        };
+        console.log(yield().next(yield).value);
+    }
+    expect: {
+        function* yield() {
+            return "PASS";
+        }
+        console.log(yield().next(yield).value);
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
+functions_inner_var: {
+    options = {
+        functions: true,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var yield = function* a() {
+            var a;
+            console.log(a, a);
+        };
+        yield().next(yield);
+    }
+    expect: {
+        function* yield() {
+            var a;
+            console.log(a, a);
+        }
+        yield().next(yield);
+    }
+    expect_stdout: "undefined undefined"
+    node_version: ">=4"
+}
+
 negate_iife: {
     options = {
         negate_iife: true,