output optimal representations of NaN & Infinity (#1723)
- move these optimisations out from `Compressor` to `OutputStream` - fixes behaviour inconsistency when running uglified code from global or module levels due to redefinition
This commit is contained in:
@@ -413,18 +413,17 @@ merge(Compressor.prototype, {
|
||||
value: val
|
||||
});
|
||||
case "number":
|
||||
if (isNaN(val)) {
|
||||
return make_node(AST_NaN, orig);
|
||||
}
|
||||
|
||||
if ((1 / val) < 0) {
|
||||
return make_node(AST_UnaryPrefix, orig, {
|
||||
if (isNaN(val)) return make_node(AST_NaN, orig);
|
||||
if (isFinite(val)) {
|
||||
return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, {
|
||||
operator: "-",
|
||||
expression: make_node(AST_Number, orig, { value: -val })
|
||||
});
|
||||
}) : make_node(AST_Number, orig, { value: val });
|
||||
}
|
||||
|
||||
return make_node(AST_Number, orig, { value: val });
|
||||
return val < 0 ? make_node(AST_UnaryPrefix, orig, {
|
||||
operator: "-",
|
||||
expression: make_node(AST_Infinity, orig)
|
||||
}) : make_node(AST_Infinity, orig);
|
||||
case "boolean":
|
||||
return make_node(val ? AST_True : AST_False, orig);
|
||||
case "undefined":
|
||||
@@ -3023,7 +3022,9 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
// avoids infinite recursion of numerals
|
||||
if (self.operator != "-" || !(self.expression instanceof AST_Number)) {
|
||||
if (self.operator != "-"
|
||||
|| !(self.expression instanceof AST_Number
|
||||
|| self.expression instanceof AST_Infinity)) {
|
||||
var ev = self.evaluate(compressor);
|
||||
if (ev !== self) {
|
||||
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||
@@ -3455,9 +3456,9 @@ merge(Compressor.prototype, {
|
||||
case "undefined":
|
||||
return make_node(AST_Undefined, self).optimize(compressor);
|
||||
case "NaN":
|
||||
return make_node(AST_NaN, self).optimize(compressor);
|
||||
return make_node(AST_NaN, self);
|
||||
case "Infinity":
|
||||
return make_node(AST_Infinity, self).optimize(compressor);
|
||||
return make_node(AST_Infinity, self);
|
||||
}
|
||||
}
|
||||
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
||||
@@ -3485,14 +3486,6 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
});
|
||||
|
||||
OPT(AST_Infinity, function (self, compressor) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator : '/',
|
||||
left : make_node(AST_Number, self, {value: 1}),
|
||||
right : make_node(AST_Number, self, {value: 0})
|
||||
});
|
||||
});
|
||||
|
||||
OPT(AST_Undefined, function(self, compressor){
|
||||
if (compressor.option("unsafe")) {
|
||||
var scope = compressor.find_parent(AST_Scope);
|
||||
|
||||
@@ -592,6 +592,13 @@ function OutputStream(options) {
|
||||
|| p instanceof AST_Call && p.expression === this;
|
||||
});
|
||||
|
||||
PARENS([ AST_Infinity, AST_NaN ], function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this
|
||||
|| p instanceof AST_Unary && p.operator != "+" && p.operator != "-";
|
||||
});
|
||||
|
||||
PARENS(AST_Seq, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
||||
@@ -1254,10 +1261,18 @@ function OutputStream(options) {
|
||||
});
|
||||
DEFPRINT(AST_Hole, noop);
|
||||
DEFPRINT(AST_Infinity, function(self, output){
|
||||
output.print("Infinity");
|
||||
output.print("1");
|
||||
output.space();
|
||||
output.print("/");
|
||||
output.space();
|
||||
output.print("0");
|
||||
});
|
||||
DEFPRINT(AST_NaN, function(self, output){
|
||||
output.print("NaN");
|
||||
output.print("0");
|
||||
output.space();
|
||||
output.print("/");
|
||||
output.space();
|
||||
output.print("0");
|
||||
});
|
||||
DEFPRINT(AST_This, function(self, output){
|
||||
output.print("this");
|
||||
|
||||
Reference in New Issue
Block a user