improve unsafe comparisons (#3200)
This commit is contained in:
129
lib/compress.js
129
lib/compress.js
@@ -2264,29 +2264,35 @@ merge(Compressor.prototype, {
|
||||
|
||||
// methods to determine whether an expression has a boolean result type
|
||||
(function(def) {
|
||||
var unary_bool = makePredicate("! delete");
|
||||
var binary_bool = makePredicate("in instanceof == != === !== < <= >= >");
|
||||
def(AST_Node, return_false);
|
||||
def(AST_Assign, function(compressor) {
|
||||
return this.operator == "=" && this.right.is_boolean(compressor);
|
||||
});
|
||||
var binary = makePredicate("in instanceof == != === !== < <= >= >");
|
||||
def(AST_Binary, function(compressor) {
|
||||
return binary[this.operator] || lazy_op[this.operator]
|
||||
&& this.left.is_boolean(compressor)
|
||||
&& this.right.is_boolean(compressor);
|
||||
});
|
||||
def(AST_Boolean, return_true);
|
||||
var fn = makePredicate("every hasOwnProperty isPrototypeOf propertyIsEnumerable some");
|
||||
def(AST_Call, function(compressor) {
|
||||
if (!compressor.option("unsafe")) return false;
|
||||
var exp = this.expression;
|
||||
return exp instanceof AST_Dot && (fn[exp.property]
|
||||
|| exp.property == "test" && exp.expression instanceof AST_RegExp);
|
||||
});
|
||||
def(AST_Conditional, function(compressor) {
|
||||
return this.consequent.is_boolean(compressor) && this.alternative.is_boolean(compressor);
|
||||
});
|
||||
def(AST_New, return_false);
|
||||
def(AST_Sequence, function(compressor) {
|
||||
return this.tail_node().is_boolean(compressor);
|
||||
});
|
||||
var unary = makePredicate("! delete");
|
||||
def(AST_UnaryPrefix, function() {
|
||||
return unary_bool[this.operator];
|
||||
return unary[this.operator];
|
||||
});
|
||||
def(AST_Binary, function() {
|
||||
return binary_bool[this.operator]
|
||||
|| lazy_op[this.operator]
|
||||
&& this.left.is_boolean()
|
||||
&& this.right.is_boolean();
|
||||
});
|
||||
def(AST_Conditional, function() {
|
||||
return this.consequent.is_boolean() && this.alternative.is_boolean();
|
||||
});
|
||||
def(AST_Assign, function() {
|
||||
return this.operator == "=" && this.right.is_boolean();
|
||||
});
|
||||
def(AST_Sequence, function() {
|
||||
return this.tail_node().is_boolean();
|
||||
});
|
||||
def(AST_True, return_true);
|
||||
def(AST_False, return_true);
|
||||
})(function(node, func) {
|
||||
node.DEFMETHOD("is_boolean", func);
|
||||
});
|
||||
@@ -2294,27 +2300,80 @@ merge(Compressor.prototype, {
|
||||
// methods to determine if an expression has a numeric result type
|
||||
(function(def) {
|
||||
def(AST_Node, return_false);
|
||||
def(AST_Number, return_true);
|
||||
var unary = makePredicate("+ - ~ ++ --");
|
||||
def(AST_Unary, function() {
|
||||
return unary[this.operator];
|
||||
});
|
||||
var binary = makePredicate("- * / % & | ^ << >> >>>");
|
||||
def(AST_Assign, function(compressor) {
|
||||
return binary[this.operator.slice(0, -1)]
|
||||
|| this.operator == "=" && this.right.is_number(compressor);
|
||||
});
|
||||
def(AST_Binary, function(compressor) {
|
||||
return binary[this.operator] || this.operator == "+"
|
||||
&& this.left.is_number(compressor)
|
||||
&& this.right.is_number(compressor);
|
||||
});
|
||||
def(AST_Assign, function(compressor) {
|
||||
return binary[this.operator.slice(0, -1)]
|
||||
|| this.operator == "=" && this.right.is_number(compressor);
|
||||
});
|
||||
def(AST_Sequence, function(compressor) {
|
||||
return this.tail_node().is_number(compressor);
|
||||
var fn = makePredicate([
|
||||
"charCodeAt",
|
||||
"getDate",
|
||||
"getDay",
|
||||
"getFullYear",
|
||||
"getHours",
|
||||
"getMilliseconds",
|
||||
"getMinutes",
|
||||
"getMonth",
|
||||
"getSeconds",
|
||||
"getTime",
|
||||
"getTimezoneOffset",
|
||||
"getUTCDate",
|
||||
"getUTCDay",
|
||||
"getUTCFullYear",
|
||||
"getUTCHours",
|
||||
"getUTCMilliseconds",
|
||||
"getUTCMinutes",
|
||||
"getUTCMonth",
|
||||
"getUTCSeconds",
|
||||
"getYear",
|
||||
"indexOf",
|
||||
"lastIndexOf",
|
||||
"localeCompare",
|
||||
"push",
|
||||
"search",
|
||||
"setDate",
|
||||
"setFullYear",
|
||||
"setHours",
|
||||
"setMilliseconds",
|
||||
"setMinutes",
|
||||
"setMonth",
|
||||
"setSeconds",
|
||||
"setTime",
|
||||
"setUTCDate",
|
||||
"setUTCFullYear",
|
||||
"setUTCHours",
|
||||
"setUTCMilliseconds",
|
||||
"setUTCMinutes",
|
||||
"setUTCMonth",
|
||||
"setUTCSeconds",
|
||||
"setYear",
|
||||
"toExponential",
|
||||
"toFixed",
|
||||
"toPrecision",
|
||||
]);
|
||||
def(AST_Call, function(compressor) {
|
||||
if (!compressor.option("unsafe")) return false;
|
||||
var exp = this.expression;
|
||||
return exp instanceof AST_Dot && (fn[exp.property]
|
||||
|| is_undeclared_ref(exp.expression) && exp.expression.name == "Math");
|
||||
});
|
||||
def(AST_Conditional, function(compressor) {
|
||||
return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);
|
||||
});
|
||||
def(AST_New, return_false);
|
||||
def(AST_Number, return_true);
|
||||
def(AST_Sequence, function(compressor) {
|
||||
return this.tail_node().is_number(compressor);
|
||||
});
|
||||
var unary = makePredicate("+ - ~ ++ --");
|
||||
def(AST_Unary, function() {
|
||||
return unary[this.operator];
|
||||
});
|
||||
})(function(node, func) {
|
||||
node.DEFMETHOD("is_number", func);
|
||||
});
|
||||
@@ -2902,7 +2961,7 @@ merge(Compressor.prototype, {
|
||||
var map;
|
||||
if (expr instanceof AST_Array) {
|
||||
map = native_fns.Array;
|
||||
} else if (expr.is_boolean()) {
|
||||
} else if (expr.is_boolean(compressor)) {
|
||||
map = native_fns.Boolean;
|
||||
} else if (expr.is_number(compressor)) {
|
||||
map = native_fns.Number;
|
||||
@@ -5247,7 +5306,7 @@ merge(Compressor.prototype, {
|
||||
var is_strict_comparison = true;
|
||||
if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
|
||||
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
|
||||
(self.left.is_boolean() && self.right.is_boolean()) ||
|
||||
(self.left.is_boolean(compressor) && self.right.is_boolean(compressor)) ||
|
||||
self.left.equivalent_to(self.right)) {
|
||||
self.operator = self.operator.substr(0, 2);
|
||||
}
|
||||
@@ -5328,7 +5387,7 @@ merge(Compressor.prototype, {
|
||||
]).optimize(compressor);
|
||||
}
|
||||
}
|
||||
if (compressor.option("comparisons") && self.is_boolean()) {
|
||||
if (compressor.option("comparisons") && self.is_boolean(compressor)) {
|
||||
if (!(compressor.parent() instanceof AST_Binary)
|
||||
|| compressor.parent() instanceof AST_Assign) {
|
||||
var negated = make_node(AST_UnaryPrefix, self, {
|
||||
@@ -6102,7 +6161,7 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
|
||||
function booleanize(node) {
|
||||
if (node.is_boolean()) return node;
|
||||
if (node.is_boolean(compressor)) return node;
|
||||
// !!expression
|
||||
return make_node(AST_UnaryPrefix, node, {
|
||||
operator: "!",
|
||||
|
||||
Reference in New Issue
Block a user