diff options
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/lib/compress.js b/lib/compress.js index 1b22d861..99e67b91 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4797,9 +4797,15 @@ merge(Compressor.prototype, { || this.right.has_side_effects(compressor); }); def(AST_Binary, function(compressor) { - return this.left.has_side_effects(compressor) - || this.right.has_side_effects(compressor) - || this.operator == "in" && !is_object(this.right); + var lhs = this.left; + if (lhs.has_side_effects(compressor)) return true; + var rhs = this.right; + var op = this.operator; + if (!rhs.has_side_effects(compressor)) return op == "in" && !is_object(rhs); + if (op == "&&" && rhs instanceof AST_PropAccess && lhs.equivalent_to(rhs.expression)) { + return rhs instanceof AST_Sub && rhs.property.has_side_effects(compressor); + } + return true; }); def(AST_Block, function(compressor) { return any(this.body, compressor); @@ -7208,33 +7214,42 @@ merge(Compressor.prototype, { return node; }); def(AST_Binary, function(compressor, first_in_statement) { - if (this.operator == "in" && !is_object(this.right)) { - var left = this.left.drop_side_effect_free(compressor, first_in_statement); - if (left === this.left) return this; + var left = this.left; + var right = this.right; + var op = this.operator; + if (op == "in" && !is_object(right)) { + var lhs = left.drop_side_effect_free(compressor, first_in_statement); + if (lhs === left) return this; var node = this.clone(); - node.left = left || make_node(AST_Number, this.left, { - value: 0 - }); + node.left = lhs || make_node(AST_Number, left, { value: 0 }); return node; } - var right = this.right.drop_side_effect_free(compressor, first_in_statement); - if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); - if (lazy_op[this.operator] && !(right instanceof AST_Function)) { + var rhs = right.drop_side_effect_free(compressor, first_in_statement); + if (!rhs) return left.drop_side_effect_free(compressor, first_in_statement); + if (lazy_op[op] && !(rhs instanceof AST_Function)) { var node = this; - if (right !== node.right) { - node = this.clone(); - node.right = right.drop_side_effect_free(compressor); - } - if (this.operator == "??") return node; + if (op == "&&" + && rhs instanceof AST_PropAccess + && left.equivalent_to(rhs.expression) + && !left.has_side_effects(compressor)) { + var prop = rhs instanceof AST_Sub && rhs.property.drop_side_effect_free(compressor); + if (!prop) return left.drop_side_effect_free(compressor, first_in_statement); + node = node.clone(); + node.right = prop; + } else if (rhs !== right) { + node = node.clone(); + node.right = rhs.drop_side_effect_free(compressor); + } + if (op == "??") return node; return (first_in_statement ? best_of_statement : best_of_expression)(node, make_node(AST_Binary, this, { - operator: node.operator == "&&" ? "||" : "&&", - left: node.left.negate(compressor, first_in_statement), - right: node.right + operator: op == "&&" ? "||" : "&&", + left: left.negate(compressor, first_in_statement), + right: node.right, })); } else { - var left = this.left.drop_side_effect_free(compressor, first_in_statement); - if (!left) return right; - return make_sequence(this, [ left, right.drop_side_effect_free(compressor) ]); + var lhs = left.drop_side_effect_free(compressor, first_in_statement); + if (!lhs) return rhs; + return make_sequence(this, [ lhs, rhs.drop_side_effect_free(compressor) ]); } }); def(AST_Call, function(compressor, first_in_statement) { |