enhance unsafe comparisons (#3419)

This commit is contained in:
Alex Lam S.L
2019-05-17 01:28:18 +08:00
committed by GitHub
parent 8939a36bc7
commit a246195412
2 changed files with 74 additions and 15 deletions

View File

@@ -5969,11 +5969,10 @@ merge(Compressor.prototype, {
} }
} }
} }
if (compressor.option("unsafe") if (compressor.option("unsafe")) {
&& self.right instanceof AST_Call var indexRight = is_indexFn(self.right);
&& self.right.expression instanceof AST_Dot
&& indexFns[self.right.expression.property]) {
if (compressor.option("booleans") if (compressor.option("booleans")
&& indexRight
&& (self.operator == "==" || self.operator == "!=") && (self.operator == "==" || self.operator == "!=")
&& self.left instanceof AST_Number && self.left instanceof AST_Number
&& self.left.getValue() == 0 && self.left.getValue() == 0
@@ -5983,18 +5982,26 @@ merge(Compressor.prototype, {
expression: self.right expression: self.right
}) : self.right).optimize(compressor); }) : self.right).optimize(compressor);
} }
var indexLeft = is_indexFn(self.left);
if (compressor.option("comparisons") && is_indexOf_match_pattern()) { if (compressor.option("comparisons") && is_indexOf_match_pattern()) {
var node = make_node(AST_UnaryPrefix, self, { var node = make_node(AST_UnaryPrefix, self, {
operator: "!", operator: "!",
expression: make_node(AST_UnaryPrefix, self, { expression: make_node(AST_UnaryPrefix, self, {
operator: "~", operator: "~",
expression: self.right expression: indexLeft ? self.left : self.right
}) })
}); });
if (self.operator == "!=" || self.operator == "<=") node = make_node(AST_UnaryPrefix, self, { switch (self.operator) {
case "<":
if (indexLeft) break;
case "<=":
case "!=":
node = make_node(AST_UnaryPrefix, self, {
operator: "!", operator: "!",
expression: node expression: node
}); });
break;
}
return node.optimize(compressor); return node.optimize(compressor);
} }
} }
@@ -6032,17 +6039,26 @@ merge(Compressor.prototype, {
return node.evaluate(compressor); 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() { function is_indexOf_match_pattern() {
switch (self.operator) { switch (self.operator) {
case ">":
case "<=": case "<=":
// 0 > array.indexOf(string) => !~array.indexOf(string)
// 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 "==":
case "!=": case "!=":
// -1 == array.indexOf(string) => !~array.indexOf(string) // -1 == array.indexOf(string) => !~array.indexOf(string)
// -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 return self.left instanceof AST_Number && self.left.getValue() == -1
|| self.left instanceof AST_UnaryPrefix && self.left.operator == "-" || self.left instanceof AST_UnaryPrefix && self.left.operator == "-"
&& self.left.expression instanceof AST_Number && self.left.expression.getValue() == 1; && self.left.expression instanceof AST_Number && self.left.expression.getValue() == 1;

View File

@@ -373,12 +373,55 @@ unsafe_indexOf: {
unsafe: true, unsafe: true,
} }
input: { 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: { expect: {
if (~Object.keys({ foo: 42 }).indexOf("foo")) console.log("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" expect_stdout: [
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
"PASS",
]
} }
issue_3413: { issue_3413: {