diff --git a/lib/compress.js b/lib/compress.js index 758e4595e3..710813504a 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5495,6 +5495,7 @@ merge(Compressor.prototype, { return this; }); + var indexFns = makePredicate("indexOf lastIndexOf"); var commutativeOperators = makePredicate("== === != !== * & | ^"); function is_object(node) { return node instanceof AST_Array @@ -5913,6 +5914,25 @@ 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("comparisons") && is_indexOf_match_pattern()) { + var node = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_UnaryPrefix, self, { + operator: "~", + expression: self.right + }) + }); + if (self.operator == "!=" || self.operator == "<=") node = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: node + }); + return node.optimize(compressor); + } + } // x && (y && z) ==> x && y && z // x || (y || z) ==> x || y || z // x + ("y" + z) ==> x + "y" + z @@ -5946,6 +5966,23 @@ merge(Compressor.prototype, { if (node.is_truthy()) return true; return node.evaluate(compressor); } + + 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; + case "==": + case "!=": + // -1 == array.indexOf(string) => !~array.indexOf(string) + // -1 != array.indexOf(string) => !!~array.indexOf(string) + 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; + } + } }); function recursive_ref(compressor, def) { diff --git a/test/compress/comparisons.js b/test/compress/comparisons.js index 4680562535..ef0db00cd7 100644 --- a/test/compress/comparisons.js +++ b/test/compress/comparisons.js @@ -365,3 +365,18 @@ is_defined: { "WARN: Expression always defined [test/compress/comparisons.js:2,19]", ] } + +unsafe_indexOf: { + options = { + booleans: true, + comparisons: true, + unsafe: true, + } + input: { + if (Object.keys({ foo: 42 }).indexOf("foo") >= 0) console.log("PASS"); + } + expect: { + if (~Object.keys({ foo: 42 }).indexOf("foo")) console.log("PASS"); + } + expect_stdout: "PASS" +}