[Pkg-javascript-commits] [uglifyjs] 208/228: fix incorrect context in variable substitution (#1791)

Jonas Smedegaard dr at jones.dk
Sat Apr 15 14:25:31 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 cc6aa3e5ac13c0da9f2481181f5b4f11275ca8c8
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Fri Apr 7 03:42:17 2017 +0800

    fix incorrect context in variable substitution (#1791)
    
    `AST_Node.optimize()` is context-aware, so don't cache its results to be used elsewhere.
    
    Also fixed a few cases of AST corruption and beef up safety of `pure_getters`.
---
 lib/compress.js              | 80 +++++++++++++++++++++++++++++++++-----------
 test/compress/reduce_vars.js | 72 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 19 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 22c79b8..de3b4db 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -283,10 +283,16 @@ merge(Compressor.prototype, {
                 if (node instanceof AST_VarDef) {
                     var d = node.name.definition();
                     if (d.fixed == null) {
-                        d.fixed = node.value && function() {
-                            return node.value;
-                        };
+                        if (node.value) {
+                            d.fixed = function() {
+                                return node.value;
+                            };
+                            descend();
+                        } else {
+                            d.fixed = null;
+                        }
                         mark_as_safe(d);
+                        return true;
                     } else if (node.value) {
                         d.fixed = false;
                     }
@@ -1160,13 +1166,42 @@ merge(Compressor.prototype, {
                 && !node.expression.has_side_effects(compressor);
     }
 
+    // may_eq_null()
+    // returns true if this node may evaluate to null or undefined
     (function(def) {
-        def(AST_Node, return_false);
+        def(AST_Node, return_true);
         def(AST_Null, return_true);
         def(AST_Undefined, return_true);
+        def(AST_Constant, return_false);
+        def(AST_Array, return_false);
+        def(AST_Object, return_false);
+        def(AST_Function, return_false);
+        def(AST_UnaryPostfix, return_false);
         def(AST_UnaryPrefix, function() {
             return this.operator == "void";
         });
+        def(AST_Binary, function(compressor) {
+            switch (this.operator) {
+              case "&&":
+                return this.left.may_eq_null(compressor);
+              case "||":
+                return this.left.may_eq_null(compressor)
+                    && this.right.may_eq_null(compressor);
+              default:
+                return false;
+            }
+        })
+        def(AST_Assign, function(compressor) {
+            return this.operator == "="
+                && this.right.may_eq_null(compressor);
+        })
+        def(AST_Conditional, function(compressor) {
+            return this.consequent.may_eq_null(compressor)
+                || this.alternative.may_eq_null(compressor);
+        })
+        def(AST_Seq, function(compressor) {
+            return this.cdr.may_eq_null(compressor);
+        });
         def(AST_PropAccess, function(compressor) {
             return !compressor.option("unsafe");
         });
@@ -3055,8 +3090,9 @@ merge(Compressor.prototype, {
             if (this.expression instanceof AST_Seq) {
                 var seq = this.expression;
                 var x = seq.to_array();
-                this.expression = x.pop();
-                x.push(this);
+                var e = this.clone();
+                e.expression = x.pop();
+                x.push(e);
                 seq = AST_Seq.from_array(x).transform(compressor);
                 return seq;
             }
@@ -3110,9 +3146,14 @@ merge(Compressor.prototype, {
         if (e instanceof AST_Binary
             && (self.operator == "+" || self.operator == "-")
             && (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
-            self.expression = e.left;
-            e.left = self;
-            return e;
+            return make_node(AST_Binary, self, {
+                operator: e.operator,
+                left: make_node(AST_UnaryPrefix, e.left, {
+                    operator: self.operator,
+                    expression: e.left
+                }),
+                right: e.right
+            });
         }
         // avoids infinite recursion of numerals
         if (self.operator != "-"
@@ -3131,23 +3172,25 @@ merge(Compressor.prototype, {
             if (this.left instanceof AST_Seq) {
                 var seq = this.left;
                 var x = seq.to_array();
-                this.left = x.pop();
-                x.push(this);
+                var e = this.clone();
+                e.left = x.pop();
+                x.push(e);
                 return AST_Seq.from_array(x).optimize(compressor);
             }
             if (this.right instanceof AST_Seq && !this.left.has_side_effects(compressor)) {
                 var assign = this.operator == "=" && this.left instanceof AST_SymbolRef;
-                var root = this.right;
+                var root = this.right.clone();
                 var cursor, seq = root;
                 while (assign || !seq.car.has_side_effects(compressor)) {
                     cursor = seq;
                     if (seq.cdr instanceof AST_Seq) {
-                        seq = seq.cdr;
+                        seq = seq.cdr = seq.cdr.clone();
                     } else break;
                 }
                 if (cursor) {
-                    this.right = cursor.cdr;
-                    cursor.cdr = this;
+                    var e = this.clone();
+                    e.right = cursor.cdr;
+                    cursor.cdr = e;
                     return root.optimize(compressor);
                 }
             }
@@ -3547,9 +3590,8 @@ merge(Compressor.prototype, {
                 if (d.should_replace === undefined) {
                     var init = fixed.evaluate(compressor);
                     if (init !== fixed) {
-                        init = make_node_from_constant(init, fixed).optimize(compressor);
-                        init = best_of_expression(init, fixed);
-                        var value = init.print_to_string().length;
+                        init = make_node_from_constant(init, fixed);
+                        var value = best_of_expression(init.optimize(compressor), fixed).print_to_string().length;
                         var name = d.name.length;
                         var freq = d.references.length;
                         var overhead = d.global || !freq ? 0 : (name + 2 + value) / freq;
@@ -3559,7 +3601,7 @@ merge(Compressor.prototype, {
                     }
                 }
                 if (d.should_replace) {
-                    return d.should_replace.clone(true);
+                    return best_of_expression(d.should_replace.optimize(compressor), fixed).clone(true);
                 }
             }
         }
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index cdc4ef2..fdfec99 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -1866,3 +1866,75 @@ delay_def: {
     }
     expect_stdout: true
 }
+
+booleans: {
+    options = {
+        booleans: true,
+        evaluate: true,
+        reduce_vars: true,
+    }
+    input: {
+        console.log(function(a) {
+            if (a != 0);
+            switch (a) {
+              case 0:
+                return "FAIL";
+              case false:
+                return "PASS";
+            }
+        }(false));
+    }
+    expect: {
+        console.log(function(a) {
+            if (!1);
+            switch (!1) {
+              case 0:
+                return "FAIL";
+              case !1:
+                return "PASS";
+            }
+        }(!1));
+    }
+    expect_stdout: "PASS"
+}
+
+side_effects_assign: {
+    options = {
+        evaluate: true,
+        reduce_vars: true,
+        sequences: true,
+        side_effects: true,
+        toplevel: true,
+    }
+    input: {
+        var a = typeof void (a && a.in == 1, 0);
+        console.log(a);
+    }
+    expect: {
+        var a = typeof void (a && a.in);
+        console.log(a);
+    }
+    expect_stdout: "undefined"
+}
+
+pure_getters: {
+    options = {
+        pure_getters: true,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+    }
+    input: {
+        try {
+            var a = (a.b, 2);
+        } catch (e) {}
+        console.log(a);
+    }
+    expect: {
+        try {
+            var a = (a.b, 2);
+        } catch (e) {}
+        console.log(a);
+    }
+    expect_stdout: "undefined"
+}

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