enhance `unsafe` `comparisons` (#3419)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 16 May 2019 17:28:18 +0000 (01:28 +0800)
committerGitHub <noreply@github.com>
Thu, 16 May 2019 17:28:18 +0000 (01:28 +0800)
lib/compress.js
test/compress/comparisons.js

index 5d6567f..b7e5b3d 100644 (file)
@@ -5969,11 +5969,10 @@ merge(Compressor.prototype, {
                 }
             }
         }
-        if (compressor.option("unsafe")
-            && self.right instanceof AST_Call
-            && self.right.expression instanceof AST_Dot
-            && indexFns[self.right.expression.property]) {
+        if (compressor.option("unsafe")) {
+            var indexRight = is_indexFn(self.right);
             if (compressor.option("booleans")
+                && indexRight
                 && (self.operator == "==" || self.operator == "!=")
                 && self.left instanceof AST_Number
                 && self.left.getValue() == 0
@@ -5983,18 +5982,26 @@ merge(Compressor.prototype, {
                     expression: self.right
                 }) : self.right).optimize(compressor);
             }
+            var indexLeft = is_indexFn(self.left);
             if (compressor.option("comparisons") && is_indexOf_match_pattern()) {
                 var node = make_node(AST_UnaryPrefix, self, {
                     operator: "!",
                     expression: make_node(AST_UnaryPrefix, self, {
                         operator: "~",
-                        expression: self.right
+                        expression: indexLeft ? self.left : self.right
                     })
                 });
-                if (self.operator == "!=" || self.operator == "<=") node = make_node(AST_UnaryPrefix, self, {
-                    operator: "!",
-                    expression: node
-                });
+                switch (self.operator) {
+                  case "<":
+                    if (indexLeft) break;
+                  case "<=":
+                  case "!=":
+                    node = make_node(AST_UnaryPrefix, self, {
+                        operator: "!",
+                        expression: node
+                    });
+                    break;
+                }
                 return node.optimize(compressor);
             }
         }
@@ -6032,17 +6039,26 @@ merge(Compressor.prototype, {
             return node.evaluate(compressor);
         }
 
+        function is_indexFn(node) {
+            return node instanceof AST_Call
+                && node.expression instanceof AST_Dot
+                && indexFns[node.expression.property];
+        }
+
         function is_indexOf_match_pattern() {
             switch (self.operator) {
-              case ">":
               case "<=":
-                // 0 > array.indexOf(string) => !~array.indexOf(string)
                 // 0 <= array.indexOf(string) => !!~array.indexOf(string)
-                return self.left instanceof AST_Number && self.left.getValue() == 0;
+                return indexRight && self.left instanceof AST_Number && self.left.getValue() == 0;
+              case "<":
+                // array.indexOf(string) < 0 => !~array.indexOf(string)
+                if (indexLeft && self.right instanceof AST_Number && self.right.getValue() == 0) return true;
+                // -1 < array.indexOf(string) => !!~array.indexOf(string)
               case "==":
               case "!=":
                 // -1 == array.indexOf(string) => !~array.indexOf(string)
                 // -1 != array.indexOf(string) => !!~array.indexOf(string)
+                if (!indexRight) return false;
                 return self.left instanceof AST_Number && self.left.getValue() == -1
                     || self.left instanceof AST_UnaryPrefix && self.left.operator == "-"
                         && self.left.expression instanceof AST_Number && self.left.expression.getValue() == 1;
index 461f415..bb140fd 100644 (file)
@@ -373,12 +373,55 @@ unsafe_indexOf: {
         unsafe: true,
     }
     input: {
-        if (Object.keys({ foo: 42 }).indexOf("foo") >= 0) console.log("PASS");
+        var a = Object.keys({ foo: 42 });
+        if (a.indexOf("bar") < 0) console.log("PASS");
+        if (0 > a.indexOf("bar")) console.log("PASS");
+        if (a.indexOf("foo") >= 0) console.log("PASS");
+        if (0 <= a.indexOf("foo")) console.log("PASS");
+        if (a.indexOf("foo") > -1) console.log("PASS");
+        if (-1 < a.indexOf("foo")) console.log("PASS");
+        if (a.indexOf("bar") == -1) console.log("PASS");
+        if (-1 == a.indexOf("bar")) console.log("PASS");
+        if (a.indexOf("bar") === -1) console.log("PASS");
+        if (-1 === a.indexOf("bar")) console.log("PASS");
+        if (a.indexOf("foo") != -1) console.log("PASS");
+        if (-1 != a.indexOf("foo")) console.log("PASS");
+        if (a.indexOf("foo") !== -1) console.log("PASS");
+        if (-1 !== a.indexOf("foo")) console.log("PASS");
     }
     expect: {
-        if (~Object.keys({ foo: 42 }).indexOf("foo")) console.log("PASS");
-    }
-    expect_stdout: "PASS"
+        var a = Object.keys({ foo: 42 });
+        if (!~a.indexOf("bar")) console.log("PASS");
+        if (!~a.indexOf("bar")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (!~a.indexOf("bar")) console.log("PASS");
+        if (!~a.indexOf("bar")) console.log("PASS");
+        if (!~a.indexOf("bar")) console.log("PASS");
+        if (!~a.indexOf("bar")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+        if (~a.indexOf("foo")) console.log("PASS");
+    }
+    expect_stdout: [
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+        "PASS",
+    ]
 }
 
 issue_3413: {