in_boolean_context: function() {
var self = this.self();
for (var i = 0, p; p = this.parent(i); i++) {
- if (p instanceof AST_SimpleStatement
- || p instanceof AST_Conditional && p.condition === self
+ if (p instanceof AST_Conditional && p.condition === self
|| p instanceof AST_DWLoop && p.condition === self
|| p instanceof AST_For && p.condition === self
|| p instanceof AST_If && p.condition === self
|| p instanceof AST_Return && p.in_bool
+ || p instanceof AST_Sequence && p.tail_node() !== self
+ || p instanceof AST_SimpleStatement
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
return true;
}
if (stat instanceof AST_If && stat.body instanceof AST_Return) {
var value = stat.body.value;
+ var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool;
//---
// pretty silly case, but:
// if (foo()) return; return; => foo(); return;
}
//---
// if (foo()) return x; return y; => return foo() ? x : y;
- if (value && !stat.alternative && next instanceof AST_Return && next.value) {
+ if ((in_bool || value) && !stat.alternative && next instanceof AST_Return) {
CHANGED = true;
stat = stat.clone();
stat.alternative = next;
}
//---
// if (foo()) return x; [ return ; ] => return foo() ? x : undefined;
- if (value && !stat.alternative
- && (!next && in_lambda && multiple_if_returns
- || next instanceof AST_Return)) {
+ if (!stat.alternative && !next && in_lambda && (in_bool || value && multiple_if_returns)) {
CHANGED = true;
stat = stat.clone();
- stat.alternative = next || make_node(AST_Return, stat, {
+ stat.alternative = make_node(AST_Return, stat, {
value: null
});
statements.splice(i, 1, stat.transform(compressor));
- if (next) statements.splice(j, 1);
continue;
}
//---
if (self.body instanceof AST_Exit
&& self.alternative instanceof AST_Exit
&& self.body.TYPE == self.alternative.TYPE) {
- return make_node(self.body.CTOR, self, {
+ var exit = 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),
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
- }).transform(compressor)
- }).optimize(compressor);
+ })
+ });
+ if (exit instanceof AST_Return) {
+ exit.in_bool = self.body.in_bool || self.alternative.in_bool;
+ }
+ return exit;
}
if (self.body instanceof AST_If
&& !self.body.alternative
&& node.expression instanceof AST_Constant
&& !node.expression.value);
}
- // AST_False or !1
+ // AST_False or !1 or void 0
function is_false(node) {
return node instanceof AST_False
|| in_bool
- && node instanceof AST_Constant
- && !node.value
+ && (node instanceof AST_Constant
+ && !node.value
+ || node instanceof AST_UnaryPrefix
+ && node.operator == "void"
+ && !node.expression.has_side_effects(compressor))
|| (node instanceof AST_UnaryPrefix
&& node.operator == "!"
&& node.expression instanceof AST_Constant