enhance conditionals (#5593)
This commit is contained in:
183
lib/compress.js
183
lib/compress.js
@@ -1749,7 +1749,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
}
|
||||
|
||||
function needs_unbinding(compressor, val) {
|
||||
function needs_unbinding(val) {
|
||||
return val instanceof AST_PropAccess
|
||||
|| is_undeclared_ref(val) && val.name == "eval";
|
||||
}
|
||||
@@ -1757,12 +1757,12 @@ Compressor.prototype.compress = function(node) {
|
||||
// we shouldn't compress (1,func)(something) to
|
||||
// func(something) because that changes the meaning of
|
||||
// the func (becomes lexical instead of global).
|
||||
function maintain_this_binding(compressor, parent, orig, val) {
|
||||
function maintain_this_binding(parent, orig, val) {
|
||||
var wrap = false;
|
||||
if (parent.TYPE == "Call") {
|
||||
wrap = parent.expression === orig && needs_unbinding(compressor, val);
|
||||
wrap = parent.expression === orig && needs_unbinding(val);
|
||||
} else if (parent instanceof AST_Template) {
|
||||
wrap = parent.tag === orig && needs_unbinding(compressor, val);
|
||||
wrap = parent.tag === orig && needs_unbinding(val);
|
||||
} else if (parent instanceof AST_UnaryPrefix) {
|
||||
wrap = parent.operator == "delete"
|
||||
|| parent.operator == "typeof" && is_undeclared_ref(val);
|
||||
@@ -2154,7 +2154,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var def = candidate.name.definition();
|
||||
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
||||
def.replaced++;
|
||||
return maintain_this_binding(compressor, parent, node, rvalue);
|
||||
return maintain_this_binding(parent, node, rvalue);
|
||||
}
|
||||
return make_node(AST_Assign, candidate, {
|
||||
operator: "=",
|
||||
@@ -3340,7 +3340,7 @@ Compressor.prototype.compress = function(node) {
|
||||
function patch_sequence(node, tt) {
|
||||
if (node instanceof AST_Sequence) switch (node.expressions.length) {
|
||||
case 0: return null;
|
||||
case 1: return maintain_this_binding(compressor, tt.parent(), node, node.expressions[0]);
|
||||
case 1: return maintain_this_binding(tt.parent(), node, node.expressions[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7110,7 +7110,7 @@ Compressor.prototype.compress = function(node) {
|
||||
case 0:
|
||||
return List.skip;
|
||||
case 1:
|
||||
return maintain_this_binding(compressor, parent, node, props[0].transform(tt));
|
||||
return maintain_this_binding(parent, node, props[0].transform(tt));
|
||||
default:
|
||||
return make_sequence(node, props.map(function(prop) {
|
||||
return prop.transform(tt);
|
||||
@@ -7599,7 +7599,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (node instanceof AST_Sequence) {
|
||||
if (node.expressions.length > 1) return;
|
||||
return maintain_this_binding(compressor, tt.parent(), node, node.expressions[0]);
|
||||
return maintain_this_binding(tt.parent(), node, node.expressions[0]);
|
||||
}
|
||||
});
|
||||
tt.push(compressor.parent());
|
||||
@@ -10316,7 +10316,7 @@ Compressor.prototype.compress = function(node) {
|
||||
seq.expressions.push(call);
|
||||
return seq.optimize(compressor);
|
||||
}
|
||||
} else if (!needs_unbinding(compressor, exp.tail_node())) {
|
||||
} else if (!needs_unbinding(exp.tail_node())) {
|
||||
var seq = lift_sequence_in_expression(self, compressor);
|
||||
if (seq !== self) return seq.optimize(compressor);
|
||||
}
|
||||
@@ -10549,7 +10549,7 @@ Compressor.prototype.compress = function(node) {
|
||||
&& is_undeclared_ref(exp.expression)
|
||||
&& exp.expression.name == "Object") {
|
||||
var call = self.clone();
|
||||
call.expression = maintain_this_binding(compressor, self, exp, exp.args[0]);
|
||||
call.expression = maintain_this_binding(self, exp, exp.args[0]);
|
||||
return call.optimize(compressor);
|
||||
}
|
||||
}
|
||||
@@ -10673,7 +10673,7 @@ Compressor.prototype.compress = function(node) {
|
||||
if (!arg) return make_node(AST_Undefined, self);
|
||||
args[index] = null;
|
||||
var parent = this.parent();
|
||||
return parent ? maintain_this_binding(compressor, parent, node, arg) : arg;
|
||||
return parent ? maintain_this_binding(parent, node, arg) : arg;
|
||||
}
|
||||
}));
|
||||
var save_inlined = fn.inlined;
|
||||
@@ -10690,7 +10690,7 @@ Compressor.prototype.compress = function(node) {
|
||||
exprs.push(retValue);
|
||||
var node = make_sequence(self, exprs).optimize(compressor);
|
||||
fn.inlined = save_inlined;
|
||||
node = maintain_this_binding(compressor, parent, current, node);
|
||||
node = maintain_this_binding(parent, current, node);
|
||||
if (replacing || best_of_expression(node, self) === node) {
|
||||
refs.forEach(function(ref) {
|
||||
ref.scope = exp === fn ? fn.parent_scope : exp.scope;
|
||||
@@ -10714,7 +10714,7 @@ Compressor.prototype.compress = function(node) {
|
||||
fn._squeezed = true;
|
||||
if (exp !== fn) fn.parent_scope = exp.scope;
|
||||
var node = make_sequence(self, flatten_fn()).optimize(compressor);
|
||||
return maintain_this_binding(compressor, parent, current, node);
|
||||
return maintain_this_binding(parent, current, node);
|
||||
}
|
||||
}
|
||||
if (compressor.option("side_effects")
|
||||
@@ -11244,7 +11244,7 @@ Compressor.prototype.compress = function(node) {
|
||||
merge_assignments();
|
||||
trim_right_for_undefined();
|
||||
if (end == 0) {
|
||||
self = maintain_this_binding(compressor, compressor.parent(), compressor.self(), expressions[0]);
|
||||
self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);
|
||||
if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
|
||||
return self;
|
||||
}
|
||||
@@ -11674,7 +11674,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var lhs = self.left;
|
||||
if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
|
||||
if (lhs.equals(self.right)) {
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), lhs).optimize(compressor);
|
||||
return maintain_this_binding(parent, compressor.self(), lhs).optimize(compressor);
|
||||
}
|
||||
mark_duplicate_condition(compressor, lhs);
|
||||
}
|
||||
@@ -11770,7 +11770,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var ll = fuzzy_eval(compressor, self.left);
|
||||
if (!ll) {
|
||||
AST_Node.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||
return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);
|
||||
} else if (!(ll instanceof AST_Node)) {
|
||||
AST_Node.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||
@@ -11816,7 +11816,7 @@ Compressor.prototype.compress = function(node) {
|
||||
line: self.start.line,
|
||||
col: self.start.col,
|
||||
});
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||
return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);
|
||||
}
|
||||
var rr;
|
||||
if (!nullish && (rr = self.right.evaluate(compressor, true)) && !(rr instanceof AST_Node)) {
|
||||
@@ -12781,16 +12781,17 @@ Compressor.prototype.compress = function(node) {
|
||||
operator: self.operator.slice(0, -1),
|
||||
left: self.left,
|
||||
right: self.right,
|
||||
}) : maintain_this_binding(compressor, compressor.parent(), self, self.right)).optimize(compressor);
|
||||
}) : maintain_this_binding(compressor.parent(), self, self.right)).optimize(compressor);
|
||||
}
|
||||
});
|
||||
|
||||
OPT(AST_Conditional, function(self, compressor) {
|
||||
if (compressor.option("sequences") && self.condition instanceof AST_Sequence) {
|
||||
var expressions = self.condition.expressions.slice();
|
||||
self.condition = expressions.pop();
|
||||
expressions.push(self);
|
||||
return make_sequence(self, expressions);
|
||||
var node = self.clone();
|
||||
node.condition = expressions.pop();
|
||||
expressions.push(node);
|
||||
return make_sequence(self, expressions).optimize(compressor);
|
||||
}
|
||||
if (!compressor.option("conditionals")) return self;
|
||||
var condition = self.condition;
|
||||
@@ -12854,16 +12855,27 @@ Compressor.prototype.compress = function(node) {
|
||||
right: make_node(AST_Conditional, self, {
|
||||
condition: condition,
|
||||
consequent: pop_lhs(consequent),
|
||||
alternative: pop_lhs(alternative)
|
||||
})
|
||||
alternative: pop_lhs(alternative),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
var alt_tail = alternative.tail_node();
|
||||
// x ? y : y ---> x, y
|
||||
if (consequent.equals(alternative)) return make_sequence(self, [
|
||||
condition,
|
||||
consequent
|
||||
]).optimize(compressor);
|
||||
// x ? (a, c) : (b, c) ---> x ? a : b, c
|
||||
if (seq_tail.equals(alt_tail)) {
|
||||
return make_sequence(self, consequent.equals(alternative) ? [
|
||||
condition,
|
||||
consequent,
|
||||
] : [
|
||||
make_node(AST_Conditional, self, {
|
||||
condition: condition,
|
||||
consequent: pop_seq(consequent),
|
||||
alternative: pop_seq(alternative),
|
||||
}),
|
||||
seq_tail,
|
||||
]).optimize(compressor);
|
||||
}
|
||||
// x ? y.p : z.p ---> (x ? y : z).p
|
||||
// x ? y(a) : z(a) ---> (x ? y : z)(a)
|
||||
// x ? y.f(a) : z.f(a) ---> (x ? y : z).f(a)
|
||||
@@ -12893,123 +12905,111 @@ Compressor.prototype.compress = function(node) {
|
||||
return node;
|
||||
}
|
||||
// x ? (y ? a : b) : b ---> x && y ? a : b
|
||||
if (consequent instanceof AST_Conditional
|
||||
&& consequent.alternative.equals(alternative)) {
|
||||
if (seq_tail instanceof AST_Conditional
|
||||
&& seq_tail.alternative.equals(alternative)) {
|
||||
return make_node(AST_Conditional, self, {
|
||||
condition: make_node(AST_Binary, self, {
|
||||
left: condition,
|
||||
operator: "&&",
|
||||
right: consequent.condition
|
||||
right: fuse(consequent, seq_tail, "condition"),
|
||||
}),
|
||||
consequent: consequent.consequent,
|
||||
alternative: alternative
|
||||
consequent: seq_tail.consequent,
|
||||
alternative: alternative,
|
||||
});
|
||||
}
|
||||
// x ? (y ? a : b) : a ---> !x || y ? a : b
|
||||
if (consequent instanceof AST_Conditional
|
||||
&& consequent.consequent.equals(alternative)) {
|
||||
if (seq_tail instanceof AST_Conditional
|
||||
&& seq_tail.consequent.equals(alternative)) {
|
||||
return make_node(AST_Conditional, self, {
|
||||
condition: make_node(AST_Binary, self, {
|
||||
left: negated,
|
||||
operator: "||",
|
||||
right: consequent.condition
|
||||
right: fuse(consequent, seq_tail, "condition"),
|
||||
}),
|
||||
consequent: alternative,
|
||||
alternative: consequent.alternative
|
||||
alternative: seq_tail.alternative,
|
||||
});
|
||||
}
|
||||
// x ? a : (y ? a : b) ---> x || y ? a : b
|
||||
if (alternative instanceof AST_Conditional
|
||||
&& consequent.equals(alternative.consequent)) {
|
||||
if (alt_tail instanceof AST_Conditional
|
||||
&& consequent.equals(alt_tail.consequent)) {
|
||||
return make_node(AST_Conditional, self, {
|
||||
condition: make_node(AST_Binary, self, {
|
||||
left: condition,
|
||||
operator: "||",
|
||||
right: alternative.condition
|
||||
right: fuse(alternative, alt_tail, "condition"),
|
||||
}),
|
||||
consequent: consequent,
|
||||
alternative: alternative.alternative
|
||||
alternative: alt_tail.alternative,
|
||||
});
|
||||
}
|
||||
// x ? b : (y ? a : b) ---> !x && y ? a : b
|
||||
if (alternative instanceof AST_Conditional
|
||||
&& consequent.equals(alternative.alternative)) {
|
||||
if (alt_tail instanceof AST_Conditional
|
||||
&& consequent.equals(alt_tail.alternative)) {
|
||||
return make_node(AST_Conditional, self, {
|
||||
condition: make_node(AST_Binary, self, {
|
||||
left: negated,
|
||||
operator: "&&",
|
||||
right: alternative.condition
|
||||
right: fuse(alternative, alt_tail, "condition"),
|
||||
}),
|
||||
consequent: alternative.consequent,
|
||||
alternative: consequent
|
||||
consequent: alt_tail.consequent,
|
||||
alternative: consequent,
|
||||
});
|
||||
}
|
||||
// x ? (a, c) : (b, c) ---> x ? a : b, c
|
||||
if ((consequent instanceof AST_Sequence || alternative instanceof AST_Sequence)
|
||||
&& consequent.tail_node().equals(alternative.tail_node())) {
|
||||
return make_sequence(self, [
|
||||
make_node(AST_Conditional, self, {
|
||||
condition: condition,
|
||||
consequent: pop_seq(consequent),
|
||||
alternative: pop_seq(alternative)
|
||||
}),
|
||||
consequent.tail_node()
|
||||
]).optimize(compressor);
|
||||
}
|
||||
// x ? y && a : a ---> (!x || y) && a
|
||||
if (consequent instanceof AST_Binary
|
||||
&& consequent.operator == "&&"
|
||||
&& consequent.right.equals(alternative)) {
|
||||
if (seq_tail instanceof AST_Binary
|
||||
&& seq_tail.operator == "&&"
|
||||
&& seq_tail.right.equals(alternative)) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: negated,
|
||||
right: consequent.left
|
||||
right: fuse(consequent, seq_tail, "left"),
|
||||
}),
|
||||
right: alternative
|
||||
right: alternative,
|
||||
}).optimize(compressor);
|
||||
}
|
||||
// x ? y || a : a ---> x && y || a
|
||||
if (consequent instanceof AST_Binary
|
||||
&& consequent.operator == "||"
|
||||
&& consequent.right.equals(alternative)) {
|
||||
if (seq_tail instanceof AST_Binary
|
||||
&& seq_tail.operator == "||"
|
||||
&& seq_tail.right.equals(alternative)) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: condition,
|
||||
right: consequent.left
|
||||
right: fuse(consequent, seq_tail, "left"),
|
||||
}),
|
||||
right: alternative
|
||||
right: alternative,
|
||||
}).optimize(compressor);
|
||||
}
|
||||
// x ? a : y && a ---> (x || y) && a
|
||||
if (alternative instanceof AST_Binary
|
||||
&& alternative.operator == "&&"
|
||||
&& alternative.right.equals(consequent)) {
|
||||
if (alt_tail instanceof AST_Binary
|
||||
&& alt_tail.operator == "&&"
|
||||
&& alt_tail.right.equals(consequent)) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: condition,
|
||||
right: alternative.left
|
||||
right: fuse(alternative, alt_tail, "left"),
|
||||
}),
|
||||
right: consequent
|
||||
right: consequent,
|
||||
}).optimize(compressor);
|
||||
}
|
||||
// x ? a : y || a ---> !x && y || a
|
||||
if (alternative instanceof AST_Binary
|
||||
&& alternative.operator == "||"
|
||||
&& alternative.right.equals(consequent)) {
|
||||
if (alt_tail instanceof AST_Binary
|
||||
&& alt_tail.operator == "||"
|
||||
&& alt_tail.right.equals(consequent)) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: negated,
|
||||
right: alternative.left
|
||||
right: fuse(alternative, alt_tail, "left"),
|
||||
}),
|
||||
right: consequent
|
||||
right: consequent,
|
||||
}).optimize(compressor);
|
||||
}
|
||||
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
||||
@@ -13022,7 +13022,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: booleanize(condition),
|
||||
right: alternative
|
||||
right: alternative,
|
||||
});
|
||||
}
|
||||
if (is_false(consequent)) {
|
||||
@@ -13034,7 +13034,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: booleanize(condition.negate(compressor)),
|
||||
right: alternative
|
||||
right: alternative,
|
||||
});
|
||||
}
|
||||
if (is_true(alternative)) {
|
||||
@@ -13042,7 +13042,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: booleanize(condition.negate(compressor)),
|
||||
right: consequent
|
||||
right: consequent,
|
||||
});
|
||||
}
|
||||
if (is_false(alternative)) {
|
||||
@@ -13050,7 +13050,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: booleanize(condition),
|
||||
right: consequent
|
||||
right: consequent,
|
||||
});
|
||||
}
|
||||
if (compressor.option("typeofs")) mark_locally_defined(condition, consequent, alternative);
|
||||
@@ -13108,6 +13108,13 @@ Compressor.prototype.compress = function(node) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function fuse(node, tail, prop) {
|
||||
if (node === tail) return tail[prop];
|
||||
var exprs = node.expressions.slice(0, -1);
|
||||
exprs.push(tail[prop]);
|
||||
return make_sequence(node, exprs);
|
||||
}
|
||||
|
||||
function is_tail_equivalent(consequent, alternative) {
|
||||
if (consequent.TYPE != alternative.TYPE) return;
|
||||
if (consequent.optional != alternative.optional) return;
|
||||
@@ -13126,13 +13133,21 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
|
||||
function combine_tail(consequent, alternative, top) {
|
||||
if (!is_tail_equivalent(consequent, alternative)) return !top && make_node(AST_Conditional, self, {
|
||||
var seq_tail = consequent.tail_node();
|
||||
var alt_tail = alternative.tail_node();
|
||||
if (!is_tail_equivalent(seq_tail, alt_tail)) return !top && make_node(AST_Conditional, self, {
|
||||
condition: condition,
|
||||
consequent: consequent,
|
||||
alternative: alternative,
|
||||
});
|
||||
var node = consequent.clone();
|
||||
node.expression = combine_tail(consequent.expression, alternative.expression);
|
||||
var node = seq_tail.clone();
|
||||
var seq_expr = fuse(consequent, seq_tail, "expression");
|
||||
var alt_expr = fuse(alternative, alt_tail, "expression");
|
||||
var combined = combine_tail(seq_expr, alt_expr);
|
||||
if (seq_tail.expression instanceof AST_Sequence) {
|
||||
combined = maintain_this_binding(seq_tail, seq_tail.expression, combined);
|
||||
}
|
||||
node.expression = combined;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -1433,6 +1433,398 @@ condition_matches_alternative: {
|
||||
expect_stdout: "null 0 false 5"
|
||||
}
|
||||
|
||||
condition_sequence_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
return (console.log(x), x) ? x : y;
|
||||
}
|
||||
console.log(f("foo", "bar"));
|
||||
console.log(f(null, "baz"));
|
||||
console.log(f(42));
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f(x, y) {
|
||||
return console.log(x), x || y;
|
||||
}
|
||||
console.log(f("foo", "bar")),
|
||||
console.log(f(null, "baz")),
|
||||
console.log(f(42)),
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"foo",
|
||||
"null",
|
||||
"baz",
|
||||
"42",
|
||||
"42",
|
||||
"undefined",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
condition_sequence_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
return (console.log(y), y) ? x : y;
|
||||
}
|
||||
console.log(f("foo", "bar"));
|
||||
console.log(f(null, "baz"));
|
||||
console.log(f(42));
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f(x, y) {
|
||||
return console.log(y), y && x;
|
||||
}
|
||||
console.log(f("foo", "bar")),
|
||||
console.log(f(null, "baz")),
|
||||
console.log(f(42)),
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: [
|
||||
"bar",
|
||||
"foo",
|
||||
"baz",
|
||||
"null",
|
||||
"undefined",
|
||||
"undefined",
|
||||
"undefined",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
combine_tail_sequence: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var n = {
|
||||
f: function() {
|
||||
console.log("foo");
|
||||
return this.p;
|
||||
},
|
||||
p: "FAIL 1",
|
||||
};
|
||||
var o = {
|
||||
f: function() {
|
||||
console.log("foz");
|
||||
return this.p;
|
||||
},
|
||||
p: "FAIL 2",
|
||||
};
|
||||
var p = "PASS";
|
||||
function g(a) {
|
||||
return a
|
||||
? (console.log("baa"), (console.log("bar"), (console.log("baz"), n).f)())
|
||||
: (console.log("moo"), (console.log("mor"), (console.log("moz"), o).f)());
|
||||
}
|
||||
console.log(g());
|
||||
console.log(g(42));
|
||||
}
|
||||
expect: {
|
||||
var n = {
|
||||
f: function() {
|
||||
console.log("foo");
|
||||
return this.p;
|
||||
},
|
||||
p: "FAIL 1",
|
||||
};
|
||||
var o = {
|
||||
f: function() {
|
||||
console.log("foz");
|
||||
return this.p;
|
||||
},
|
||||
p: "FAIL 2",
|
||||
};
|
||||
var p = "PASS";
|
||||
function g(a) {
|
||||
return (0, (a
|
||||
? (console.log("baa"), console.log("bar"), console.log("baz"), n)
|
||||
: (console.log("moo"), console.log("mor"), console.log("moz"), o)).f)();
|
||||
}
|
||||
console.log(g());
|
||||
console.log(g(42));
|
||||
}
|
||||
expect_stdout: [
|
||||
"moo",
|
||||
"mor",
|
||||
"moz",
|
||||
"foz",
|
||||
"PASS",
|
||||
"baa",
|
||||
"bar",
|
||||
"baz",
|
||||
"foo",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
consequent_sequence_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a) {
|
||||
return x ? (console.log("seq"), y && a) : a;
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a) {
|
||||
return (!x || (console.log("seq"), y)) && a;
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"seq",
|
||||
"false",
|
||||
"seq",
|
||||
"4",
|
||||
]
|
||||
}
|
||||
|
||||
consequent_sequence_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a) {
|
||||
return x ? (console.log("seq"), y || a) : a;
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a) {
|
||||
return x && (console.log("seq"), y) || a;
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"seq",
|
||||
"3",
|
||||
"seq",
|
||||
"true",
|
||||
]
|
||||
}
|
||||
|
||||
consequent_sequence_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a, b) {
|
||||
return x ? (console.log("seq"), y ? a : b) : b;
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a, b) {
|
||||
return x && (console.log("seq"), y) ? a : b;
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"-1",
|
||||
"-2",
|
||||
"seq",
|
||||
"-3",
|
||||
"seq",
|
||||
"4",
|
||||
]
|
||||
}
|
||||
|
||||
consequent_sequence_4: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a, b) {
|
||||
return x ? (console.log("seq"), y ? a : b) : a;
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a, b) {
|
||||
return !x || (console.log("seq"), y) ? a : b;
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"seq",
|
||||
"-3",
|
||||
"seq",
|
||||
"4",
|
||||
]
|
||||
}
|
||||
|
||||
alternative_sequence_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a) {
|
||||
return x ? a : (console.log("seq"), y && a);
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a) {
|
||||
return (x || (console.log("seq"), y)) && a;
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"seq",
|
||||
"false",
|
||||
"seq",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
]
|
||||
}
|
||||
|
||||
alternative_sequence_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a) {
|
||||
return x ? a : (console.log("seq"), y || a);
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a) {
|
||||
return !x && (console.log("seq"), y) || a;
|
||||
}
|
||||
console.log(f(false, false, 1));
|
||||
console.log(f(false, true, 2));
|
||||
console.log(f(true, false, 3));
|
||||
console.log(f(true, true, 4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"seq",
|
||||
"1",
|
||||
"seq",
|
||||
"true",
|
||||
"3",
|
||||
"4",
|
||||
]
|
||||
}
|
||||
|
||||
alternative_sequence_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a, b) {
|
||||
return x ? a : (console.log("seq"), y ? a : b);
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a, b) {
|
||||
return x || (console.log("seq"), y) ? a : b;
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"seq",
|
||||
"-1",
|
||||
"seq",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
]
|
||||
}
|
||||
|
||||
alternative_sequence_4: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y, a, b) {
|
||||
return x ? b : (console.log("seq"), y ? a : b);
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect: {
|
||||
function f(x, y, a, b) {
|
||||
return !x && (console.log("seq"), y) ? a : b;
|
||||
}
|
||||
console.log(f(false, false, 1, -1));
|
||||
console.log(f(false, true, 2, -2));
|
||||
console.log(f(true, false, 3, -3));
|
||||
console.log(f(true, true, 4, -4));
|
||||
}
|
||||
expect_stdout: [
|
||||
"seq",
|
||||
"-1",
|
||||
"seq",
|
||||
"2",
|
||||
"-3",
|
||||
"-4",
|
||||
]
|
||||
}
|
||||
|
||||
delete_conditional_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
|
||||
Reference in New Issue
Block a user