}
function is_last_node(node, parent) {
+ if (node.TYPE == "Binary") return node.operator == "in" && !is_object(node.right.tail_node());
if (node instanceof AST_Call) {
var fn = node.expression;
if (fn instanceof AST_SymbolRef) {
def(AST_Assign, return_true);
def(AST_Binary, function(compressor) {
return this.left.has_side_effects(compressor)
- || this.right.has_side_effects(compressor);
+ || this.right.has_side_effects(compressor)
+ || this.operator == "in" && !is_object(this.right.tail_node());
});
def(AST_Block, function(compressor) {
return any(this.body, compressor);
return this;
});
def(AST_Binary, function(compressor, first_in_statement) {
+ if (this.operator == "in" && !is_object(this.right.tail_node())) {
+ var left = this.left.drop_side_effect_free(compressor, first_in_statement);
+ if (left === this.left) return this;
+ var node = this.clone();
+ node.left = left || make_node(AST_Number, this.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 indexFns = makePredicate("indexOf lastIndexOf");
var commutativeOperators = makePredicate("== === != !== * & | ^");
function is_object(node) {
+ while (node instanceof AST_SymbolRef) {
+ node = node.fixed_value();
+ if (!node) return false;
+ node = node.tail_node();
+ }
return node instanceof AST_Array
|| node instanceof AST_Lambda
+ || node instanceof AST_New
|| node instanceof AST_Object;
}
else if (self.left instanceof AST_SymbolRef
&& self.right instanceof AST_SymbolRef
&& self.left.definition() === self.right.definition()
- && is_object(self.left.fixed_value())) {
+ && is_object(self.left)) {
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
}
break;
"this",
];
-var BINARY_OPS_NO_COMMA = [
+var BINARY_OPS = [
" + ", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)
" - ",
"/",
"%",
"&&",
"||",
- "^" ];
-
-var BINARY_OPS = [","].concat(BINARY_OPS_NO_COMMA);
+ "^",
+ ",",
+];
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS.push(" in ");
var ASSIGNMENTS = [
"=",
}
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
return "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
- + createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
+ + createBinaryOp(noComma, canThrow) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
}
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
// intentionally generate more hardcore ops
return VALUES[rng(VALUES.length)];
}
-function createBinaryOp(noComma) {
- if (noComma) return BINARY_OPS_NO_COMMA[rng(BINARY_OPS_NO_COMMA.length)];
- return BINARY_OPS[rng(BINARY_OPS.length)];
+function createBinaryOp(noComma, canThrow) {
+ var op;
+ do {
+ op = BINARY_OPS[rng(BINARY_OPS.length)];
+ } while (noComma && op == "," || !canThrow && op == " in ");
+ return op;
}
function createAssignment() {