fix corner case in sign propagation (#3696)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 28 Jan 2020 14:44:18 +0000 (22:44 +0800)
committerGitHub <noreply@github.com>
Tue, 28 Jan 2020 14:44:18 +0000 (22:44 +0800)
- migrate de-facto functionality to `evaluate`

fixes #3695

lib/compress.js
test/compress/issue-1770.js
test/compress/numbers.js

index f2dfb64..9b054ca 100644 (file)
@@ -6062,6 +6062,8 @@ merge(Compressor.prototype, {
         return self;
     });
 
+    var SIGN_OPS = makePredicate("+ -");
+    var MULTIPLICATIVE_OPS = makePredicate("* / %");
     OPT(AST_UnaryPrefix, function(self, compressor) {
         var e = self.expression;
         if (compressor.option("evaluate")
@@ -6112,12 +6114,12 @@ merge(Compressor.prototype, {
                 ])).optimize(compressor);
             }
         }
-        if (self.operator == "-" && e instanceof AST_Infinity) {
-            e = e.transform(compressor);
-        }
-        if (e instanceof AST_Binary
-            && (self.operator == "+" || self.operator == "-")
-            && (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
+        if (self.operator == "-" && e instanceof AST_Infinity) e = e.transform(compressor);
+        if (compressor.option("evaluate")
+            && e instanceof AST_Binary
+            && SIGN_OPS[self.operator]
+            && MULTIPLICATIVE_OPS[e.operator]
+            && (e.left.is_constant() || !e.right.has_side_effects(compressor))) {
             return make_node(AST_Binary, self, {
                 operator: e.operator,
                 left: make_node(AST_UnaryPrefix, e.left, {
@@ -6387,7 +6389,8 @@ merge(Compressor.prototype, {
             if (self.right instanceof AST_Binary
                 && self.operator == self.right.operator
                 && (self.left.is_string(compressor) && self.right.is_string(compressor)
-                    || self.right.left.is_string(compressor) && !self.right.right.has_side_effects(compressor))) {
+                    || self.right.left.is_string(compressor)
+                        && (self.left.is_constant() || !self.right.right.has_side_effects(compressor)))) {
                 swap_chain();
             }
         }
@@ -7084,7 +7087,7 @@ merge(Compressor.prototype, {
         return reachable;
     }
 
-    var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
+    var ASSIGN_OPS = makePredicate("+ - * / % >> << >>> | ^ &");
     var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
     OPT(AST_Assign, function(self, compressor) {
         if (compressor.option("dead_code")) {
index 7a529b2..cd86d9d 100644 (file)
@@ -46,7 +46,7 @@ mangle_props: {
             obj[1/0],
             obj["Infinity"],
             obj[-1/0],
-            obj[-1/0],
+            obj[-(1/0)],
             obj["-Infinity"],
             obj[null],
             obj["null"]
index e6f6ce2..9fca46f 100644 (file)
@@ -669,6 +669,9 @@ issue_1710: {
 }
 
 unary_binary_parenthesis: {
+    options = {
+        evaluate: true,
+    }
     input: {
         var v = [ 0, 1, NaN, Infinity, null, undefined, true, false, "", "foo", /foo/ ];
         v.forEach(function(x) {
@@ -1233,3 +1236,18 @@ issue_3684: {
         "Infinity",
     ]
 }
+
+issue_3695: {
+    options = {
+        evaluate: true,
+    }
+    input: {
+        var a = [];
+        console.log(+(a * (a[0] = false)));
+    }
+    expect: {
+        var a = [];
+        console.log(+(a * (a[0] = false)));
+    }
+    expect_stdout: "NaN"
+}