Merge branch 'master' into harmony-v2.8.6
This commit is contained in:
355
lib/compress.js
355
lib/compress.js
@@ -54,6 +54,7 @@ function Compressor(options, false_by_default) {
|
||||
drop_debugger : !false_by_default,
|
||||
unsafe : false,
|
||||
unsafe_comps : false,
|
||||
unsafe_math : false,
|
||||
unsafe_proto : false,
|
||||
conditionals : !false_by_default,
|
||||
comparisons : !false_by_default,
|
||||
@@ -80,6 +81,7 @@ function Compressor(options, false_by_default) {
|
||||
ecma : 5,
|
||||
drop_console : false,
|
||||
angular : false,
|
||||
expression : false,
|
||||
warnings : true,
|
||||
global_defs : {},
|
||||
passes : 1,
|
||||
@@ -116,12 +118,18 @@ Compressor.prototype = new TreeTransformer;
|
||||
merge(Compressor.prototype, {
|
||||
option: function(key) { return this.options[key] },
|
||||
compress: function(node) {
|
||||
if (this.option("expression")) {
|
||||
node = node.process_expression(true);
|
||||
}
|
||||
var passes = +this.options.passes || 1;
|
||||
for (var pass = 0; pass < passes && pass < 3; ++pass) {
|
||||
if (pass > 0 || this.option("reduce_vars"))
|
||||
node.reset_opt_flags(this, true);
|
||||
node = node.transform(this);
|
||||
}
|
||||
if (this.option("expression")) {
|
||||
node = node.process_expression(false);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
warn: function(text, props) {
|
||||
@@ -178,8 +186,45 @@ merge(Compressor.prototype, {
|
||||
return this.print_to_string() == node.print_to_string();
|
||||
});
|
||||
|
||||
AST_Node.DEFMETHOD("process_expression", function(insert) {
|
||||
var self = this;
|
||||
var tt = new TreeTransformer(function(node) {
|
||||
if (insert && node instanceof AST_SimpleStatement) {
|
||||
return make_node(AST_Return, node, {
|
||||
value: node.body
|
||||
});
|
||||
}
|
||||
if (!insert && node instanceof AST_Return) {
|
||||
return make_node(AST_SimpleStatement, node, {
|
||||
body: node.value || make_node(AST_Undefined, node)
|
||||
});
|
||||
}
|
||||
if (node instanceof AST_Lambda && node !== self) {
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_Block) {
|
||||
var index = node.body.length - 1;
|
||||
if (index >= 0) {
|
||||
node.body[index] = node.body[index].transform(tt);
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_If) {
|
||||
node.body = node.body.transform(tt);
|
||||
if (node.alternative) {
|
||||
node.alternative = node.alternative.transform(tt);
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_With) {
|
||||
node.body = node.body.transform(tt);
|
||||
}
|
||||
return node;
|
||||
});
|
||||
return self.transform(tt);
|
||||
});
|
||||
|
||||
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
|
||||
var reduce_vars = rescan && compressor.option("reduce_vars");
|
||||
var ie8 = !compressor.option("screw_ie8");
|
||||
var safe_ids = [];
|
||||
push();
|
||||
var suppressor = new TreeWalker(function(node) {
|
||||
@@ -189,7 +234,7 @@ merge(Compressor.prototype, {
|
||||
d.fixed = false;
|
||||
}
|
||||
});
|
||||
var tw = new TreeWalker(function(node){
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||
node._squeezed = false;
|
||||
node._optimized = false;
|
||||
@@ -204,6 +249,9 @@ merge(Compressor.prototype, {
|
||||
d.fixed = false;
|
||||
}
|
||||
}
|
||||
if (ie8 && node instanceof AST_SymbolCatch) {
|
||||
node.definition().fixed = false;
|
||||
}
|
||||
if (node instanceof AST_VarDef) {
|
||||
if (node.name instanceof AST_Destructuring) {
|
||||
node.name.walk(suppressor);
|
||||
@@ -262,6 +310,12 @@ merge(Compressor.prototype, {
|
||||
pop();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Catch) {
|
||||
push();
|
||||
descend();
|
||||
pop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
@@ -494,11 +548,9 @@ merge(Compressor.prototype, {
|
||||
// Constant single use vars can be replaced in any scope.
|
||||
if (var_decl.value.is_constant()) {
|
||||
var ctt = new TreeTransformer(function(node) {
|
||||
if (node === ref) {
|
||||
var parent = ctt.parent();
|
||||
if (!(parent instanceof AST_ForIn && parent.init === node)) {
|
||||
return replace_var(node, parent, true);
|
||||
}
|
||||
if (node === ref
|
||||
&& !ctt.find_parent(AST_ForIn)) {
|
||||
return replace_var(node, ctt.parent(), true);
|
||||
}
|
||||
});
|
||||
stat.transform(ctt);
|
||||
@@ -568,10 +620,7 @@ merge(Compressor.prototype, {
|
||||
return statements;
|
||||
|
||||
function is_lvalue(node, parent) {
|
||||
return node instanceof AST_SymbolRef && (
|
||||
(parent instanceof AST_Assign && node === parent.left)
|
||||
|| (parent instanceof AST_Unary && parent.expression === node
|
||||
&& (parent.operator == "++" || parent.operator == "--")));
|
||||
return node instanceof AST_SymbolRef && isLHS(node, parent);
|
||||
}
|
||||
function replace_var(node, parent, is_constant) {
|
||||
if (is_lvalue(node, parent)) return node;
|
||||
@@ -744,7 +793,7 @@ merge(Compressor.prototype, {
|
||||
CHANGED = true;
|
||||
stat = stat.clone();
|
||||
stat.alternative = ret[0] || make_node(AST_Return, stat, {
|
||||
value: make_node(AST_Undefined, stat)
|
||||
value: null
|
||||
});
|
||||
ret[0] = stat.transform(compressor);
|
||||
continue loop;
|
||||
@@ -777,7 +826,7 @@ merge(Compressor.prototype, {
|
||||
&& !stat.alternative) {
|
||||
CHANGED = true;
|
||||
ret.push(make_node(AST_Return, ret[0], {
|
||||
value: make_node(AST_Undefined, ret[0])
|
||||
value: null
|
||||
}).transform(compressor));
|
||||
ret.unshift(stat);
|
||||
continue loop;
|
||||
@@ -1034,6 +1083,10 @@ merge(Compressor.prototype, {
|
||||
}));
|
||||
};
|
||||
|
||||
function is_undefined(node) {
|
||||
return node instanceof AST_Undefined || node.is_undefined;
|
||||
}
|
||||
|
||||
/* -----[ boolean/negation helpers ]----- */
|
||||
|
||||
// methods to determine whether an expression has a boolean result type
|
||||
@@ -1064,6 +1117,34 @@ merge(Compressor.prototype, {
|
||||
node.DEFMETHOD("is_boolean", func);
|
||||
});
|
||||
|
||||
// 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_Binary, function(compressor){
|
||||
return binary(this.operator) || this.operator == "+"
|
||||
&& this.left.is_number(compressor)
|
||||
&& this.right.is_number(compressor);
|
||||
});
|
||||
var assign = makePredicate("-= *= /= %= &= |= ^= <<= >>= >>>=");
|
||||
def(AST_Assign, function(compressor){
|
||||
return assign(this.operator) || this.right.is_number(compressor);
|
||||
});
|
||||
def(AST_Seq, function(compressor){
|
||||
return this.cdr.is_number(compressor);
|
||||
});
|
||||
def(AST_Conditional, function(compressor){
|
||||
return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);
|
||||
});
|
||||
})(function(node, func){
|
||||
node.DEFMETHOD("is_number", func);
|
||||
});
|
||||
|
||||
// methods to determine if an expression has a string result type
|
||||
(function (def){
|
||||
def(AST_Node, function(){ return false });
|
||||
@@ -1092,7 +1173,7 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
|
||||
function isLHS(node, parent) {
|
||||
return parent instanceof AST_Unary && (parent.operator === "++" || parent.operator === "--")
|
||||
return parent instanceof AST_Unary && (parent.operator == "++" || parent.operator == "--")
|
||||
|| parent instanceof AST_Assign && parent.left === node;
|
||||
}
|
||||
|
||||
@@ -2117,7 +2198,14 @@ merge(Compressor.prototype, {
|
||||
def(AST_Constant, return_null);
|
||||
def(AST_This, return_null);
|
||||
def(AST_Call, function(compressor, first_in_statement){
|
||||
if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return this;
|
||||
if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) {
|
||||
if (this.expression instanceof AST_Function) {
|
||||
var node = this.clone();
|
||||
node.expression = node.expression.process_expression(false);
|
||||
return node;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (this.pure) {
|
||||
compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
|
||||
this.pure.value = this.pure.value.replace(/[@#]__PURE__/g, ' ');
|
||||
@@ -2441,8 +2529,8 @@ merge(Compressor.prototype, {
|
||||
return make_node(self.body.CTOR, self, {
|
||||
value: make_node(AST_Conditional, self, {
|
||||
condition : self.condition,
|
||||
consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
|
||||
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
|
||||
consequent : self.body.value || make_node(AST_Undefined, self.body),
|
||||
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
|
||||
})
|
||||
}).transform(compressor);
|
||||
}
|
||||
@@ -2623,12 +2711,13 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
|
||||
OPT(AST_Call, function(self, compressor){
|
||||
var exp = self.expression;
|
||||
if (compressor.option("unused")
|
||||
&& self.expression instanceof AST_Function
|
||||
&& !self.expression.uses_arguments
|
||||
&& !self.expression.uses_eval
|
||||
&& self.args.length > self.expression.argnames.length) {
|
||||
var end = self.expression.argnames.length;
|
||||
&& exp instanceof AST_Function
|
||||
&& !exp.uses_arguments
|
||||
&& !exp.uses_eval
|
||||
&& self.args.length > exp.argnames.length) {
|
||||
var end = exp.argnames.length;
|
||||
for (var i = end, len = self.args.length; i < len; i++) {
|
||||
var node = self.args[i].drop_side_effect_free(compressor);
|
||||
if (node) {
|
||||
@@ -2638,7 +2727,6 @@ merge(Compressor.prototype, {
|
||||
self.args.length = end;
|
||||
}
|
||||
if (compressor.option("unsafe")) {
|
||||
var exp = self.expression;
|
||||
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
|
||||
switch (exp.name) {
|
||||
case "Array":
|
||||
@@ -2817,17 +2905,24 @@ merge(Compressor.prototype, {
|
||||
return best_of(self, node);
|
||||
}
|
||||
}
|
||||
if (compressor.option("side_effects")) {
|
||||
if (self.expression instanceof AST_Function
|
||||
&& !self.expression.is_generator
|
||||
&& self.args.length == 0
|
||||
&& !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) {
|
||||
return make_node(AST_Undefined, self).transform(compressor);
|
||||
if (exp instanceof AST_Function && !self.expression.is_generator) {
|
||||
if (exp.body[0] instanceof AST_Return) {
|
||||
var value = exp.body[0].value;
|
||||
if (!value || value.is_constant()) {
|
||||
var args = self.args.concat(value || make_node(AST_Undefined, self));
|
||||
return AST_Seq.from_array(args).transform(compressor);
|
||||
}
|
||||
}
|
||||
if (compressor.option("side_effects")) {
|
||||
if (!AST_Block.prototype.has_side_effects.call(exp, compressor)) {
|
||||
var args = self.args.concat(make_node(AST_Undefined, self));
|
||||
return AST_Seq.from_array(args).transform(compressor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compressor.option("drop_console")) {
|
||||
if (self.expression instanceof AST_PropAccess) {
|
||||
var name = self.expression.expression;
|
||||
if (exp instanceof AST_PropAccess) {
|
||||
var name = exp.expression;
|
||||
while (name.expression) {
|
||||
name = name.expression;
|
||||
}
|
||||
@@ -2838,12 +2933,6 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self.args.length == 0
|
||||
&& self.expression instanceof AST_Function
|
||||
&& self.expression.body[0] instanceof AST_Return
|
||||
&& self.expression.body[0].value.is_constant()) {
|
||||
return self.expression.body[0].value;
|
||||
}
|
||||
if (compressor.option("negate_iife")
|
||||
&& compressor.parent() instanceof AST_SimpleStatement
|
||||
&& is_iife_call(self)) {
|
||||
@@ -2875,23 +2964,37 @@ merge(Compressor.prototype, {
|
||||
self.car = self.car.drop_side_effect_free(compressor, first_in_statement(compressor));
|
||||
if (!self.car) return maintain_this_binding(compressor.parent(), self, self.cdr);
|
||||
if (compressor.option("cascade")) {
|
||||
var left;
|
||||
if (self.car instanceof AST_Assign
|
||||
&& !self.car.left.has_side_effects(compressor)) {
|
||||
if (self.car.left.equivalent_to(self.cdr)) {
|
||||
return self.car;
|
||||
}
|
||||
if (self.cdr instanceof AST_Call
|
||||
&& self.cdr.expression.equivalent_to(self.car.left)) {
|
||||
self.cdr.expression = self.car;
|
||||
return self.cdr;
|
||||
}
|
||||
left = self.car.left;
|
||||
} else if (self.car instanceof AST_UnaryPostfix
|
||||
&& (self.car.operator == "++" || self.car.operator == "--")) {
|
||||
left = self.car.expression;
|
||||
}
|
||||
if (!self.car.has_side_effects(compressor)
|
||||
&& self.car.equivalent_to(self.cdr)) {
|
||||
return self.car;
|
||||
if (left) {
|
||||
var parent, field;
|
||||
var cdr = self.cdr;
|
||||
while (true) {
|
||||
if (cdr.equivalent_to(left)) {
|
||||
if (parent) {
|
||||
parent[field] = self.car;
|
||||
return self.cdr;
|
||||
}
|
||||
return self.car;
|
||||
}
|
||||
if (cdr instanceof AST_Binary && !(cdr instanceof AST_Assign)) {
|
||||
field = cdr.left.is_constant() ? "right" : "left";
|
||||
} else if (cdr instanceof AST_Call
|
||||
|| cdr instanceof AST_Unary && cdr.operator != "++" && cdr.operator != "--") {
|
||||
field = "expression";
|
||||
} else break;
|
||||
parent = cdr;
|
||||
cdr = cdr[field];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self.cdr instanceof AST_Undefined) {
|
||||
if (is_undefined(self.cdr)) {
|
||||
return make_node(AST_UnaryPrefix, self, {
|
||||
operator : "void",
|
||||
expression : self.car
|
||||
@@ -2930,7 +3033,7 @@ merge(Compressor.prototype, {
|
||||
self.expression = e;
|
||||
return self;
|
||||
} else {
|
||||
return make_node(AST_Undefined, self);
|
||||
return make_node(AST_Undefined, self).transform(compressor);
|
||||
}
|
||||
}
|
||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||
@@ -3003,8 +3106,14 @@ merge(Compressor.prototype, {
|
||||
right: rhs[0]
|
||||
}).optimize(compressor);
|
||||
}
|
||||
function reverse(op, force) {
|
||||
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
|
||||
function reversible() {
|
||||
return self.left instanceof AST_Constant
|
||||
|| self.right instanceof AST_Constant
|
||||
|| !self.left.has_side_effects(compressor)
|
||||
&& !self.right.has_side_effects(compressor);
|
||||
}
|
||||
function reverse(op) {
|
||||
if (reversible()) {
|
||||
if (op) self.operator = op;
|
||||
var tmp = self.left;
|
||||
self.left = self.right;
|
||||
@@ -3020,7 +3129,7 @@ merge(Compressor.prototype, {
|
||||
|
||||
if (!(self.left instanceof AST_Binary
|
||||
&& PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
|
||||
reverse(null, true);
|
||||
reverse();
|
||||
}
|
||||
}
|
||||
if (/^[!=]==?$/.test(self.operator)) {
|
||||
@@ -3055,6 +3164,7 @@ merge(Compressor.prototype, {
|
||||
case "===":
|
||||
case "!==":
|
||||
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.operator = self.operator.substr(0, 2);
|
||||
}
|
||||
@@ -3192,7 +3302,10 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (self.operator == "+") {
|
||||
var associative = true;
|
||||
switch (self.operator) {
|
||||
case "+":
|
||||
// "foo" + ("bar" + x) => "foobar" + x
|
||||
if (self.left instanceof AST_Constant
|
||||
&& self.right instanceof AST_Binary
|
||||
&& self.right.operator == "+"
|
||||
@@ -3200,7 +3313,7 @@ merge(Compressor.prototype, {
|
||||
&& self.right.is_string(compressor)) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: "+",
|
||||
left: make_node(AST_String, null, {
|
||||
left: make_node(AST_String, self.left, {
|
||||
value: "" + self.left.getValue() + self.right.left.getValue(),
|
||||
start: self.left.start,
|
||||
end: self.right.left.end
|
||||
@@ -3208,6 +3321,7 @@ merge(Compressor.prototype, {
|
||||
right: self.right.right
|
||||
});
|
||||
}
|
||||
// (x + "foo") + "bar" => x + "foobar"
|
||||
if (self.right instanceof AST_Constant
|
||||
&& self.left instanceof AST_Binary
|
||||
&& self.left.operator == "+"
|
||||
@@ -3216,13 +3330,14 @@ merge(Compressor.prototype, {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: "+",
|
||||
left: self.left.left,
|
||||
right: make_node(AST_String, null, {
|
||||
right: make_node(AST_String, self.right, {
|
||||
value: "" + self.left.right.getValue() + self.right.getValue(),
|
||||
start: self.left.right.start,
|
||||
end: self.right.end
|
||||
})
|
||||
});
|
||||
}
|
||||
// (x + "foo") + ("bar" + y) => (x + "foobar") + y
|
||||
if (self.left instanceof AST_Binary
|
||||
&& self.left.operator == "+"
|
||||
&& self.left.is_string(compressor)
|
||||
@@ -3236,7 +3351,7 @@ merge(Compressor.prototype, {
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: "+",
|
||||
left: self.left.left,
|
||||
right: make_node(AST_String, null, {
|
||||
right: make_node(AST_String, self.left.right, {
|
||||
value: "" + self.left.right.getValue() + self.right.left.getValue(),
|
||||
start: self.left.right.start,
|
||||
end: self.right.left.end
|
||||
@@ -3245,6 +3360,122 @@ merge(Compressor.prototype, {
|
||||
right: self.right.right
|
||||
});
|
||||
}
|
||||
// a + -b => a - b
|
||||
if (self.right instanceof AST_UnaryPrefix
|
||||
&& self.right.operator == "-"
|
||||
&& self.left.is_number(compressor)) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: "-",
|
||||
left: self.left,
|
||||
right: self.right.expression
|
||||
});
|
||||
}
|
||||
// -a + b => b - a
|
||||
if (self.left instanceof AST_UnaryPrefix
|
||||
&& self.left.operator == "-"
|
||||
&& reversible()
|
||||
&& self.right.is_number(compressor)) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: "-",
|
||||
left: self.right,
|
||||
right: self.left.expression
|
||||
});
|
||||
}
|
||||
case "*":
|
||||
associative = compressor.option("unsafe_math");
|
||||
case "&":
|
||||
case "|":
|
||||
case "^":
|
||||
// a + +b => +b + a
|
||||
if (self.left.is_number(compressor)
|
||||
&& self.right.is_number(compressor)
|
||||
&& reversible()
|
||||
&& !(self.left instanceof AST_Binary
|
||||
&& self.left.operator != self.operator
|
||||
&& PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
|
||||
var reversed = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: self.right,
|
||||
right: self.left
|
||||
});
|
||||
if (self.right instanceof AST_Constant
|
||||
&& !(self.left instanceof AST_Constant)) {
|
||||
self = best_of(reversed, self);
|
||||
} else {
|
||||
self = best_of(self, reversed);
|
||||
}
|
||||
}
|
||||
if (associative && self.is_number(compressor)) {
|
||||
// a + (b + c) => (a + b) + c
|
||||
if (self.right instanceof AST_Binary
|
||||
&& self.right.operator == self.operator) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left,
|
||||
right: self.right.left,
|
||||
start: self.left.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
right: self.right.right
|
||||
});
|
||||
}
|
||||
// (n + 2) + 3 => 5 + n
|
||||
// (2 * n) * 3 => 6 + n
|
||||
if (self.right instanceof AST_Constant
|
||||
&& self.left instanceof AST_Binary
|
||||
&& self.left.operator == self.operator) {
|
||||
if (self.left.left instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.left,
|
||||
right: self.right,
|
||||
start: self.left.left.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.right
|
||||
});
|
||||
} else if (self.left.right instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.right,
|
||||
right: self.right,
|
||||
start: self.left.right.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.left
|
||||
});
|
||||
}
|
||||
}
|
||||
// (a | 1) | (2 | d) => (3 | a) | b
|
||||
if (self.left instanceof AST_Binary
|
||||
&& self.left.operator == self.operator
|
||||
&& self.left.right instanceof AST_Constant
|
||||
&& self.right instanceof AST_Binary
|
||||
&& self.right.operator == self.operator
|
||||
&& self.right.left instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.right,
|
||||
right: self.right.left,
|
||||
start: self.left.right.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
right: self.left.left
|
||||
}),
|
||||
right: self.right.right
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// x && (y && z) ==> x && y && z
|
||||
@@ -3277,11 +3508,13 @@ merge(Compressor.prototype, {
|
||||
return def;
|
||||
}
|
||||
// testing against !self.scope.uses_with first is an optimization
|
||||
if (self.undeclared() && !isLHS(self, compressor.parent())
|
||||
if (compressor.option("screw_ie8")
|
||||
&& self.undeclared()
|
||||
&& !isLHS(self, compressor.parent())
|
||||
&& (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
|
||||
switch (self.name) {
|
||||
case "undefined":
|
||||
return make_node(AST_Undefined, self);
|
||||
return make_node(AST_Undefined, self).transform(compressor);
|
||||
case "NaN":
|
||||
return make_node(AST_NaN, self).transform(compressor);
|
||||
case "Infinity":
|
||||
@@ -3324,11 +3557,13 @@ merge(Compressor.prototype, {
|
||||
var scope = compressor.find_parent(AST_Scope);
|
||||
var undef = scope.find_variable("undefined");
|
||||
if (undef) {
|
||||
return make_node(AST_SymbolRef, self, {
|
||||
var ref = make_node(AST_SymbolRef, self, {
|
||||
name : "undefined",
|
||||
scope : scope,
|
||||
thedef : undef
|
||||
});
|
||||
ref.is_undefined = true;
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
@@ -3631,7 +3866,7 @@ merge(Compressor.prototype, {
|
||||
OPT(AST_RegExp, literals_in_boolean_context);
|
||||
|
||||
OPT(AST_Return, function(self, compressor){
|
||||
if (self.value instanceof AST_Undefined) {
|
||||
if (self.value && is_undefined(self.value)) {
|
||||
self.value = null;
|
||||
}
|
||||
return self;
|
||||
|
||||
Reference in New Issue
Block a user