[Pkg-javascript-commits] [uglifyjs] 05/50: fix `unsafe` on `evaluate` of `reduce_vars` (#1870)

Jonas Smedegaard dr at jones.dk
Thu Aug 17 23:06:43 UTC 2017


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

js pushed a commit to branch master
in repository uglifyjs.

commit 7305ba0296a1d3490d49498bf4742089a908cd4a
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Sat May 6 23:18:55 2017 +0800

    fix `unsafe` on `evaluate` of `reduce_vars` (#1870)
    
    Determine if variables with non-constant values can escape and be modified.
    
    fixes #1865
---
 lib/compress.js              | 28 ++++++++------
 test/compress/reduce_vars.js | 92 ++++++++++++++++++++++++++++++++------------
 2 files changed, 85 insertions(+), 35 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 411c284..14c419b 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -271,6 +271,14 @@ merge(Compressor.prototype, {
                     if (d.fixed === undefined || !is_safe(d)
                         || is_modified(node, 0, node.fixed_value() instanceof AST_Lambda)) {
                         d.fixed = false;
+                    } else {
+                        var parent = tw.parent();
+                        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
+                            || parent instanceof AST_VarDef && node === parent.value) {
+                            d.escaped = true;
+                        }
                     }
                 }
                 if (node instanceof AST_SymbolCatch) {
@@ -405,6 +413,7 @@ merge(Compressor.prototype, {
         }
 
         function reset_def(def) {
+            def.escaped = false;
             if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) {
                 def.fixed = undefined;
             } else {
@@ -1561,23 +1570,20 @@ merge(Compressor.prototype, {
                 : ev(this.alternative, compressor);
         });
         def(AST_SymbolRef, function(compressor){
-            if (this._evaluating) throw def;
+            if (!compressor.option("reduce_vars") || this._evaluating) throw def;
             this._evaluating = true;
             try {
                 var fixed = this.fixed_value();
-                if (compressor.option("reduce_vars") && fixed) {
-                    if (compressor.option("unsafe")) {
-                        if (!HOP(fixed, "_evaluated")) {
-                            fixed._evaluated = ev(fixed, compressor);
-                        }
-                        return fixed._evaluated;
-                    }
-                    return ev(fixed, compressor);
-                }
+                if (!fixed) throw def;
+                var value = ev(fixed, compressor);
+                if (!HOP(fixed, "_eval")) fixed._eval = function() {
+                    return value;
+                };
+                if (value && typeof value == "object" && this.definition().escaped) throw def;
+                return value;
             } finally {
                 this._evaluating = false;
             }
-            throw def;
         });
         def(AST_PropAccess, function(compressor){
             if (compressor.option("unsafe")) {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index ad7fcc6..92ec0ea 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -300,7 +300,7 @@ unsafe_evaluate_array: {
     }
 }
 
-unsafe_evaluate_equality: {
+unsafe_evaluate_equality_1: {
     options = {
         evaluate     : true,
         reduce_vars  : true,
@@ -308,47 +308,62 @@ unsafe_evaluate_equality: {
         unused       : true
     }
     input: {
-        function f0(){
+        function f0() {
             var a = {};
-            console.log(a === a);
+            return a === a;
         }
-
-        function f1(){
+        function f1() {
             var a = [];
-            console.log(a === a);
+            return a === a;
+        }
+        console.log(f0(), f1());
+    }
+    expect: {
+        function f0() {
+            return true;
+        }
+        function f1() {
+            return true;
         }
+        console.log(f0(), f1());
+    }
+    expect_stdout: true
+}
 
-        function f2(){
+unsafe_evaluate_equality_2: {
+    options = {
+        collapse_vars: true,
+        evaluate     : true,
+        passes       : 2,
+        reduce_vars  : true,
+        unsafe       : true,
+        unused       : true
+    }
+    input: {
+        function f2() {
             var a = {a:1, b:2};
             var b = a;
             var c = a;
-            console.log(b === c);
+            return b === c;
         }
-
-        function f3(){
+        function f3() {
             var a = [1, 2, 3];
             var b = a;
             var c = a;
-            console.log(b === c);
+            return b === c;
         }
+        console.log(f2(), f3());
     }
     expect: {
-        function f0(){
-            console.log(true);
-        }
-
-        function f1(){
-            console.log(true);
-        }
-
-        function f2(){
-            console.log(true);
+        function f2() {
+            return true;
         }
-
-        function f3(){
-            console.log(true);
+        function f3() {
+            return true;
         }
+        console.log(f2(), f3());
     }
+    expect_stdout: true
 }
 
 passes: {
@@ -2078,3 +2093,32 @@ try_abort: {
     }
     expect_stdout: "1 undefined"
 }
+
+issue_1865: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+        unsafe: true,
+    }
+    input: {
+        function f(a) {
+            a.b = false;
+        }
+        console.log(function() {
+            var some = { thing: true };
+            f(some);
+            return some.thing;
+        }());
+    }
+    expect: {
+        function f(a) {
+            a.b = false;
+        }
+        console.log(function() {
+            var some = { thing: true };
+            f(some);
+            return some.thing;
+        }());
+    }
+    expect_stdout: 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