[Pkg-javascript-commits] [uglifyjs] 367/491: replace single-use recursive functions (#2659)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:51:53 UTC 2018


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag debian/3.3.10-1
in repository uglifyjs.

commit 4832bc5d88e37ca35f1dd5f5d8ddd95cd8bbdd7d
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Tue Dec 26 21:25:35 2017 +0800

    replace single-use recursive functions (#2659)
    
    fixes #2628
---
 lib/compress.js                | 39 +++++++++++++++++++++++++++++----------
 lib/scope.js                   |  4 +++-
 test/compress/collapse_vars.js |  7 +++----
 test/compress/functions.js     | 27 +++++++++++++++++++++++----
 test/compress/reduce_vars.js   | 12 +++++-------
 5 files changed, 63 insertions(+), 26 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index bb35542..d890caf 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -319,6 +319,7 @@ merge(Compressor.prototype, {
             } else {
                 def.fixed = false;
             }
+            def.recursive_refs = 0;
             def.references = [];
             def.should_replace = undefined;
             def.single_use = undefined;
@@ -369,7 +370,7 @@ merge(Compressor.prototype, {
             return compressor.option("unused")
                 && !def.scope.uses_eval
                 && !def.scope.uses_with
-                && def.references.length == 1
+                && def.references.length - def.recursive_refs == 1
                 && tw.loop_ids[def.id] === tw.in_loop;
         }
 
@@ -621,7 +622,9 @@ merge(Compressor.prototype, {
                 d.fixed = false;
             } else if (d.fixed) {
                 value = this.fixed_value();
-                if (value && ref_once(tw, compressor, d)) {
+                if (value instanceof AST_Lambda && recursive_ref(tw, d)) {
+                    d.recursive_refs++;
+                } else if (value && ref_once(tw, compressor, d)) {
                     d.single_use = value instanceof AST_Lambda
                         || d.scope === this.scope && value.is_constant_expression();
                 } else {
@@ -4670,17 +4673,18 @@ merge(Compressor.prototype, {
             if (fixed instanceof AST_Defun) {
                 d.fixed = fixed = make_node(AST_Function, fixed, fixed);
             }
-            if (d.single_use && fixed instanceof AST_Function) {
+            var single_use = d.single_use;
+            if (single_use && fixed instanceof AST_Function) {
                 if (d.scope !== self.scope
                     && (!compressor.option("reduce_funcs")
                         || d.escaped == 1
                         || fixed.inlined)) {
-                    d.single_use = false;
+                    single_use = false;
                 } else if (recursive_ref(compressor, d)) {
-                    d.single_use = false;
+                    single_use = false;
                 } else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) {
-                    d.single_use = fixed.is_constant_expression(self.scope);
-                    if (d.single_use == "f") {
+                    single_use = fixed.is_constant_expression(self.scope);
+                    if (single_use == "f") {
                         var scope = self.scope;
                         do {
                             if (scope instanceof AST_Defun || scope instanceof AST_Function) {
@@ -4690,9 +4694,24 @@ merge(Compressor.prototype, {
                     }
                 }
             }
-            if (d.single_use && fixed) {
-                var value = fixed.optimize(compressor);
-                return value === fixed ? fixed.clone(true) : value;
+            if (single_use && fixed) {
+                var value;
+                if (d.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
+                    value = fixed.clone(true);
+                    var defun_def = value.name.definition();
+                    value.name = make_node(AST_SymbolLambda, value.name, value.name);
+                    value.name.scope = value;
+                    var lambda_def = value.def_function(value.name);
+                    value.walk(new TreeWalker(function(node) {
+                        if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
+                            node.thedef = lambda_def;
+                        }
+                    }));
+                } else {
+                    value = fixed.optimize(compressor);
+                    if (value === fixed) value = fixed.clone(true);
+                }
+                return value;
             }
             if (fixed && d.should_replace === undefined) {
                 var init;
diff --git a/lib/scope.js b/lib/scope.js
index bbfa037..bceec28 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -307,7 +307,9 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
 });
 
 AST_Scope.DEFMETHOD("def_function", function(symbol){
-    this.functions.set(symbol.name, this.def_variable(symbol));
+    var def = this.def_variable(symbol);
+    this.functions.set(symbol.name, def);
+    return def;
 });
 
 AST_Scope.DEFMETHOD("def_variable", function(symbol){
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index 9a20c55..0bad06a 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -3878,10 +3878,9 @@ recursive_function_replacement: {
         console.log(f(c));
     }
     expect: {
-        function f(n) {
-            return x(y(f(n)));
-        }
-        console.log(f(c));
+        console.log(function n(o) {
+            return x(y(n(o)));
+        }(c));
     }
 }
 
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 7f35de7..83a27a0 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -1345,11 +1345,10 @@ issue_2630_3: {
     expect: {
         var x = 2, a = 1;
         (function() {
-            function f1(a) {
+            (function f1(a) {
                 f2();
                 --x >= 0 && f1({});
-            }
-            f1(a++);
+            })(a++);
             function f2() {
                 a++;
             }
@@ -1424,7 +1423,7 @@ issue_2630_5: {
     expect_stdout: "155"
 }
 
-recursive_inline: {
+recursive_inline_1: {
     options = {
         inline: true,
         reduce_funcs: true,
@@ -1448,6 +1447,26 @@ recursive_inline: {
     expect: {}
 }
 
+recursive_inline_2: {
+    options = {
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f(n) {
+            return n ? n * f(n - 1) : 1;
+        }
+        console.log(f(5));
+    }
+    expect: {
+        console.log(function f(n) {
+            return n ? n * f(n - 1) : 1;
+        }(5));
+    }
+    expect_stdout: "120"
+}
+
 issue_2657: {
     options = {
         inline: true,
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 2b2c77d..6f302ec 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -1355,10 +1355,9 @@ defun_inline_1: {
         function f() {
             return function(b) {
                 return b;
-            }(2) + h();
-            function h() {
+            }(2) + function h() {
                 return h();
-            }
+            }();
         }
     }
 }
@@ -1382,12 +1381,11 @@ defun_inline_2: {
     }
     expect: {
         function f() {
-            function h() {
-                return h();
-            }
             return function(b) {
                 return b;
-            }(2) + h();
+            }(2) + function h() {
+                return h();
+            }();
         }
     }
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git



More information about the Pkg-javascript-commits mailing list