[Pkg-javascript-commits] [uglifyjs] 268/491: preserve function identity in `reduce_vars` (#2451)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:51:43 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 4c0b0177b6fa556c31f0099c6d52a4ad4f670ba3
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Wed Nov 8 03:28:46 2017 +0800

    preserve function identity in `reduce_vars` (#2451)
    
    fixes #2450
---
 lib/compress.js              |  45 ++++++++-----
 test/compress/reduce_vars.js | 154 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 176 insertions(+), 23 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 274ab60..6354197 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -324,9 +324,8 @@ merge(Compressor.prototype, {
                                     || value.is_constant_expression(node.scope);
                             } else {
                                 d.single_use = d.scope === node.scope
-                                    && loop_ids[d.id] === in_loop
                                     && value.is_constant_expression();
-                                }
+                            }
                         } else {
                             d.single_use = false;
                         }
@@ -384,6 +383,7 @@ merge(Compressor.prototype, {
                         d.fixed = false;
                     } else {
                         d.fixed = node;
+                        loop_ids[d.id] = in_loop;
                         mark(d, true);
                         if (ref_once(d)) {
                             d.single_use = d.scope === d.references[0].scope
@@ -577,7 +577,11 @@ merge(Compressor.prototype, {
         }
 
         function ref_once(def) {
-            return unused && !def.scope.uses_eval && !def.scope.uses_with && def.references.length == 1;
+            return unused
+                && !def.scope.uses_eval
+                && !def.scope.uses_with
+                && def.references.length == 1
+                && loop_ids[def.id] === in_loop;
         }
 
         function is_immutable(value) {
@@ -623,7 +627,8 @@ merge(Compressor.prototype, {
 
         function mark_escaped(d, node, value, level) {
             var parent = tw.parent(level);
-            if (value instanceof AST_Constant || value instanceof AST_Function) return;
+            if (value instanceof AST_Constant) return;
+            if (level > 0 && value instanceof AST_Function) return;
             if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
                 || parent instanceof AST_Call && node !== parent.expression
                 || parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
@@ -4216,6 +4221,17 @@ merge(Compressor.prototype, {
         return self;
     });
 
+    function recursive_ref(compressor, def) {
+        var node;
+        for (var i = 0; node = compressor.parent(i); i++) {
+            if (node instanceof AST_Lambda) {
+                var name = node.name;
+                if (name && name.definition() === def) break;
+            }
+        }
+        return node;
+    }
+
     OPT(AST_SymbolRef, function(self, compressor){
         var def = self.resolve_defines(compressor);
         if (def) {
@@ -4241,20 +4257,13 @@ merge(Compressor.prototype, {
             if (fixed instanceof AST_Defun) {
                 d.fixed = fixed = make_node(AST_Function, fixed, fixed);
             }
-            if (fixed && d.single_use) {
-                var recurse;
-                if (fixed instanceof AST_Function) {
-                    for (var i = 0; recurse = compressor.parent(i); i++) {
-                        if (recurse instanceof AST_Lambda) {
-                            var name = recurse.name;
-                            if (name && name.definition() === d) break;
-                        }
-                    }
-                }
-                if (!recurse) {
-                    var value = fixed.optimize(compressor);
-                    return value === fixed ? fixed.clone(true) : value;
-                }
+            if (fixed
+                && d.single_use
+                && !(fixed instanceof AST_Function
+                    && (d.escaped && d.scope !== self.scope
+                        || recursive_ref(compressor, d)))) {
+                var value = fixed.optimize(compressor);
+                return value === fixed ? fixed.clone(true) : value;
             }
             if (fixed && d.should_replace === undefined) {
                 var init;
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index f1a27ff..8afea85 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -1123,11 +1123,12 @@ toplevel_on_loops_1: {
         while (x);
     }
     expect: {
+        function bar() {
+            console.log("bar:", --x);
+        }
         var x = 3;
         do
-            (function() {
-                console.log("bar:", --x);
-            })();
+            bar();
         while (x);
     }
     expect_stdout: true
@@ -1180,9 +1181,10 @@ toplevel_on_loops_2: {
         while (x);
     }
     expect: {
-        for (;;) (function() {
+        function bar() {
             console.log("bar:");
-        })();
+        }
+        for (;;) bar();
     }
 }
 
@@ -3845,3 +3847,145 @@ recursive_inlining_5: {
         "foo 0",
     ]
 }
+
+issue_2450_1: {
+    options = {
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function f() {}
+        function g() {
+            return f;
+        }
+        console.log(g() === g());
+    }
+    expect: {
+        function f() {}
+        function g() {
+            return f;
+        }
+        console.log(g() === g());
+    }
+    expect_stdout: "true"
+}
+
+issue_2450_2: {
+    options = {
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        function g() {
+            function f() {}
+            return f;
+        }
+        console.log(g() === g());
+    }
+    expect: {
+        function g() {
+            return function() {};
+        }
+        console.log(g() === g());
+    }
+    expect_stdout: "false"
+}
+
+issue_2450_3: {
+    options = {
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        var x = (function() {
+            function test() {
+                return "foo";
+            }
+            return function b() {
+                return [1, test];
+            }
+        })();
+        console.log(x()[1] === x()[1]);
+    }
+    expect: {
+        var x = (function() {
+            function test() {
+                return "foo";
+            }
+            return function() {
+                return [1, test];
+            }
+        })();
+        console.log(x()[1] === x()[1]);
+    }
+    expect_stdout: "true"
+}
+
+issue_2450_4: {
+    options = {
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a;
+        function f(b) {
+            console.log(a === b);
+            a = b;
+        }
+        function g() {}
+        for (var i = 3; --i >= 0;)
+            f(g);
+    }
+    expect: {
+        var a;
+        function f(b) {
+            console.log(a === b);
+            a = b;
+        }
+        function g() {}
+        for (var i = 3; --i >= 0;)
+            f(g);
+    }
+    expect_stdout: [
+        "false",
+        "true",
+        "true",
+    ]
+}
+
+issue_2450_5: {
+    options = {
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a;
+        function f(b) {
+            console.log(a === b);
+            a = b;
+        }
+        function g() {}
+        [1, 2, 3].forEach(function() {
+            f(g);
+        });
+    }
+    expect: {
+        var a;
+        function g() {}
+        [1, 2, 3].forEach(function() {
+            (function(b) {
+                console.log(a === b);
+                a = b;
+            })(g);
+        });
+    }
+    expect_stdout: [
+        "false",
+        "true",
+        "true",
+    ]
+}

-- 
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