diff options
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/lib/compress.js b/lib/compress.js index a2332a9c..1d9cd401 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -66,6 +66,7 @@ function Compressor(options, false_by_default) { join_vars : !false_by_default, keep_fargs : true, keep_fnames : false, + keep_infinity : false, loops : !false_by_default, negate_iife : !false_by_default, passes : 1, @@ -215,7 +216,12 @@ merge(Compressor.prototype, { }) : make_node(AST_EmptyStatement, node); } return make_node(AST_SimpleStatement, node, { - body: node.value || make_node(AST_Undefined, node) + body: node.value || make_node(AST_UnaryPrefix, node, { + operator: "void", + expression: make_node(AST_Number, node, { + value: 0 + }) + }) }); } if (node instanceof AST_Lambda && node !== self) { @@ -1123,8 +1129,12 @@ merge(Compressor.prototype, { })); }; - function is_undefined(node) { - return node instanceof AST_Undefined || node.is_undefined; + function is_undefined(node, compressor) { + return node.is_undefined + || node instanceof AST_Undefined + || node instanceof AST_UnaryPrefix + && node.operator == "void" + && !node.expression.has_side_effects(compressor); } /* -----[ boolean/negation helpers ]----- */ @@ -1313,7 +1323,7 @@ merge(Compressor.prototype, { return this; } }); - var unaryPrefix = makePredicate("! ~ - +"); + var unaryPrefix = makePredicate("! ~ - + void"); AST_Node.DEFMETHOD("is_constant", function(){ // Accomodate when compress option evaluate=false // as well as the common constant expressions !0 and -1 @@ -2971,7 +2981,7 @@ merge(Compressor.prototype, { } } } - if (is_undefined(self.cdr)) { + if (is_undefined(self.cdr, compressor)) { return make_node(AST_UnaryPrefix, self, { operator : "void", expression : self.car @@ -3010,7 +3020,7 @@ merge(Compressor.prototype, { self.expression = e; return self; } else { - return make_node(AST_Undefined, self).transform(compressor); + return make_node(AST_Undefined, self).optimize(compressor); } } if (compressor.option("booleans") && compressor.in_boolean_context()) { @@ -3034,6 +3044,9 @@ merge(Compressor.prototype, { })).optimize(compressor); } } + if (self.operator == "-" && e instanceof AST_Infinity) { + e = e.transform(compressor); + } if (e instanceof AST_Binary && (self.operator == "+" || self.operator == "-") && (e.operator == "*" || e.operator == "/" || e.operator == "%")) { @@ -3043,8 +3056,7 @@ merge(Compressor.prototype, { } // avoids infinite recursion of numerals if (self.operator != "-" - || !(self.expression instanceof AST_Number - || self.expression instanceof AST_Infinity)) { + || !(e instanceof AST_Number || e instanceof AST_Infinity)) { var ev = self.evaluate(compressor); if (ev !== self) { ev = make_node_from_constant(ev, self).optimize(compressor); @@ -3087,8 +3099,8 @@ merge(Compressor.prototype, { OPT(AST_Binary, function(self, compressor){ function reversible() { - return self.left instanceof AST_Constant - || self.right instanceof AST_Constant + return self.left.is_constant() + || self.right.is_constant() || !self.left.has_side_effects(compressor) && !self.right.has_side_effects(compressor); } @@ -3101,8 +3113,8 @@ merge(Compressor.prototype, { } } if (commutativeOperators(self.operator)) { - if (self.right instanceof AST_Constant - && !(self.left instanceof AST_Constant)) { + if (self.right.is_constant() + && !self.left.is_constant()) { // if right is a constant, whatever side effects the // left side might have could not influence the // result. hence, force switch. @@ -3464,9 +3476,9 @@ merge(Compressor.prototype, { case "undefined": return make_node(AST_Undefined, self).optimize(compressor); case "NaN": - return make_node(AST_NaN, self); + return make_node(AST_NaN, self).optimize(compressor); case "Infinity": - return make_node(AST_Infinity, self); + return make_node(AST_Infinity, self).optimize(compressor); } } if (compressor.option("evaluate") && compressor.option("reduce_vars")) { @@ -3508,7 +3520,38 @@ merge(Compressor.prototype, { return ref; } } - return self; + return make_node(AST_UnaryPrefix, self, { + operator: "void", + expression: make_node(AST_Number, self, { + value: 0 + }) + }); + }); + + OPT(AST_Infinity, function(self, compressor){ + var retain = compressor.option("keep_infinity") + && !compressor.find_parent(AST_Scope).find_variable("Infinity"); + return retain ? self : make_node(AST_Binary, self, { + operator: "/", + left: make_node(AST_Number, self, { + value: 1 + }), + right: make_node(AST_Number, self, { + value: 0 + }) + }); + }); + + OPT(AST_NaN, function(self, compressor){ + return compressor.find_parent(AST_Scope).find_variable("NaN") ? make_node(AST_Binary, self, { + operator: "/", + left: make_node(AST_Number, self, { + value: 0 + }), + right: make_node(AST_Number, self, { + value: 0 + }) + }) : self; }); var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; @@ -3809,7 +3852,7 @@ merge(Compressor.prototype, { OPT(AST_RegExp, literals_in_boolean_context); OPT(AST_Return, function(self, compressor){ - if (self.value && is_undefined(self.value)) { + if (self.value && is_undefined(self.value, compressor)) { self.value = null; } return self; |