enhance booleans (#5365)
This commit is contained in:
57
lib/ast.js
57
lib/ast.js
@@ -2085,33 +2085,40 @@ TreeWalker.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
in_boolean_context: function() {
|
in_boolean_context: function() {
|
||||||
var self = this.self();
|
for (var drop = true, level = 0, parent, self = this.self(); parent = this.parent(level++); self = parent) {
|
||||||
for (var i = 0, p; p = this.parent(i); i++) {
|
if (parent instanceof AST_Binary) switch (parent.operator) {
|
||||||
if (p instanceof AST_Conditional && p.condition === self
|
case "&&":
|
||||||
|| p instanceof AST_DWLoop && p.condition === self
|
case "||":
|
||||||
|| p instanceof AST_For && p.condition === self
|
if (parent.left === self) drop = false;
|
||||||
|| p instanceof AST_If && p.condition === self
|
continue;
|
||||||
|| p instanceof AST_Return && p.in_bool
|
default:
|
||||||
|| p instanceof AST_Sequence && p.tail_node() !== self
|
|
||||||
|| p instanceof AST_SimpleStatement
|
|
||||||
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")
|
|
||||||
|| p instanceof AST_Conditional
|
|
||||||
|| p.tail_node() === self) {
|
|
||||||
self = p;
|
|
||||||
} else if (p instanceof AST_Return) {
|
|
||||||
for (var call, fn = p; call = this.parent(++i); fn = call) {
|
|
||||||
if (call.TYPE == "Call") {
|
|
||||||
if (!(fn instanceof AST_Lambda) || fn.name) return false;
|
|
||||||
} else if (fn instanceof AST_Lambda) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (parent instanceof AST_Conditional) {
|
||||||
|
if (parent.condition === self) return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_DWLoop) return parent.condition === self;
|
||||||
|
if (parent instanceof AST_For) return parent.condition === self;
|
||||||
|
if (parent instanceof AST_If) return parent.condition === self;
|
||||||
|
if (parent instanceof AST_Return) {
|
||||||
|
if (parent.in_bool) return true;
|
||||||
|
while (parent = this.parent(level++)) {
|
||||||
|
if (parent instanceof AST_Lambda) {
|
||||||
|
if (parent.name) return false;
|
||||||
|
parent = this.parent(level++);
|
||||||
|
if (parent.TYPE != "Call") return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Sequence) {
|
||||||
|
if (parent.tail_node() === self) continue;
|
||||||
|
return drop ? "d" : true;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_SimpleStatement) return drop ? "d" : true;
|
||||||
|
if (parent instanceof AST_UnaryPrefix) return parent.operator == "!";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
331
lib/compress.js
331
lib/compress.js
@@ -189,7 +189,7 @@ Compressor.prototype = new TreeTransformer(function(node, descend, in_list) {
|
|||||||
if (is_scope) {
|
if (is_scope) {
|
||||||
node.hoist_properties(this);
|
node.hoist_properties(this);
|
||||||
node.hoist_declarations(this);
|
node.hoist_declarations(this);
|
||||||
node.process_boolean_returns(this);
|
node.process_returns(this);
|
||||||
}
|
}
|
||||||
// Before https://github.com/mishoo/UglifyJS/pull/1602 AST_Node.optimize()
|
// Before https://github.com/mishoo/UglifyJS/pull/1602 AST_Node.optimize()
|
||||||
// would call AST_Node.transform() if a different instance of AST_Node is
|
// would call AST_Node.transform() if a different instance of AST_Node is
|
||||||
@@ -475,7 +475,8 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
function reset_def(tw, compressor, def) {
|
function reset_def(tw, compressor, def) {
|
||||||
def.assignments = 0;
|
def.assignments = 0;
|
||||||
def.bool_fn = 0;
|
def.bool_return = 0;
|
||||||
|
def.drop_return = 0;
|
||||||
def.cross_loop = false;
|
def.cross_loop = false;
|
||||||
def.direct_access = false;
|
def.direct_access = false;
|
||||||
def.escaped = [];
|
def.escaped = [];
|
||||||
@@ -1057,12 +1058,11 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (iife) delete exp.reduce_vars;
|
if (iife) delete exp.reduce_vars;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node.TYPE == "Call" && tw.in_boolean_context()) {
|
if (node.TYPE == "Call") switch (tw.in_boolean_context()) {
|
||||||
if (exp instanceof AST_SymbolRef) {
|
case "d":
|
||||||
exp.definition().bool_fn++;
|
var drop = true;
|
||||||
} else if (exp instanceof AST_Assign && exp.operator == "=" && exp.left instanceof AST_SymbolRef) {
|
case true:
|
||||||
exp.left.definition().bool_fn++;
|
mark_refs(exp, drop);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exp.walk(tw);
|
exp.walk(tw);
|
||||||
var optional = node.optional;
|
var optional = node.optional;
|
||||||
@@ -1078,6 +1078,25 @@ Compressor.prototype.compress = function(node) {
|
|||||||
tw.find_parent(AST_Scope).may_call_this();
|
tw.find_parent(AST_Scope).may_call_this();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
function mark_refs(node, drop) {
|
||||||
|
if (node instanceof AST_Assign) {
|
||||||
|
if (node.operator != "=") return;
|
||||||
|
mark_refs(node.left, drop);
|
||||||
|
mark_refs(node.right, drop);
|
||||||
|
} else if (node instanceof AST_Binary) {
|
||||||
|
if (!lazy_op[node.operator]) return;
|
||||||
|
mark_refs(node.left, drop);
|
||||||
|
mark_refs(node.right, drop);
|
||||||
|
} else if (node instanceof AST_Conditional) {
|
||||||
|
mark_refs(node.consequent, drop);
|
||||||
|
mark_refs(node.alternative, drop);
|
||||||
|
} else if (node instanceof AST_SymbolRef) {
|
||||||
|
var def = node.definition();
|
||||||
|
def.bool_return++;
|
||||||
|
if (drop) def.drop_return++;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_Class, function(tw, descend, compressor) {
|
def(AST_Class, function(tw, descend, compressor) {
|
||||||
var node = this;
|
var node = this;
|
||||||
@@ -7923,7 +7942,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function map_bool_returns(fn) {
|
function map_self_returns(fn) {
|
||||||
var map = Object.create(null);
|
var map = Object.create(null);
|
||||||
scan_local_returns(fn, function(node) {
|
scan_local_returns(fn, function(node) {
|
||||||
var value = node.value;
|
var value = node.value;
|
||||||
@@ -7936,9 +7955,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
function all_bool(def, bool_returns, compressor) {
|
function can_trim_returns(def, self_returns, compressor) {
|
||||||
return def.bool_fn + (bool_returns[def.id] || 0) === def.references.length - def.replaced
|
if (compressor.exposed(def)) return false;
|
||||||
&& !compressor.exposed(def);
|
switch (def.references.length - def.replaced - (self_returns[def.id] || 0)) {
|
||||||
|
case def.drop_return:
|
||||||
|
return "d";
|
||||||
|
case def.bool_return:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function process_boolean_returns(fn, compressor) {
|
function process_boolean_returns(fn, compressor) {
|
||||||
@@ -7964,39 +7988,74 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("process_boolean_returns", noop);
|
AST_Scope.DEFMETHOD("process_returns", noop);
|
||||||
AST_Defun.DEFMETHOD("process_boolean_returns", function(compressor) {
|
AST_Defun.DEFMETHOD("process_returns", function(compressor) {
|
||||||
if (!compressor.option("booleans")) return;
|
if (!compressor.option("booleans")) return;
|
||||||
var bool_returns = map_bool_returns(this);
|
|
||||||
if (!all_bool(this.name.definition(), bool_returns, compressor)) return;
|
|
||||||
if (compressor.parent() instanceof AST_ExportDefault) return;
|
if (compressor.parent() instanceof AST_ExportDefault) return;
|
||||||
process_boolean_returns(this, compressor);
|
switch (can_trim_returns(this.name.definition(), map_self_returns(this), compressor)) {
|
||||||
|
case "d":
|
||||||
|
drop_returns(compressor, this, true);
|
||||||
|
break;
|
||||||
|
case true:
|
||||||
|
process_boolean_returns(this, compressor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
AST_Function.DEFMETHOD("process_boolean_returns", function(compressor) {
|
AST_Function.DEFMETHOD("process_returns", function(compressor) {
|
||||||
if (!compressor.option("booleans")) return;
|
if (!compressor.option("booleans")) return;
|
||||||
var bool_returns = map_bool_returns(this);
|
var drop = true;
|
||||||
if (this.name && !all_bool(this.name.definition(), bool_returns, compressor)) return;
|
var self_returns = map_self_returns(this);
|
||||||
|
if (this.name && !can_trim(this.name.definition())) return;
|
||||||
var parent = compressor.parent();
|
var parent = compressor.parent();
|
||||||
if (parent instanceof AST_Assign) {
|
if (parent instanceof AST_Assign) {
|
||||||
if (parent.operator != "=") return;
|
if (parent.operator != "=") return;
|
||||||
var sym = parent.left;
|
var sym = parent.left;
|
||||||
if (!(sym instanceof AST_SymbolRef)) return;
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
if (!all_bool(sym.definition(), bool_returns, compressor)) return;
|
if (!can_trim(sym.definition())) return;
|
||||||
} else if (parent instanceof AST_Call && parent.expression !== this) {
|
} else if (parent instanceof AST_Call && parent.expression !== this) {
|
||||||
var exp = parent.expression;
|
var exp = parent.expression;
|
||||||
if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();
|
if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();
|
||||||
if (!(exp instanceof AST_Lambda)) return;
|
if (!(exp instanceof AST_Lambda)) return;
|
||||||
if (exp.uses_arguments || exp.pinned()) return;
|
if (exp.uses_arguments || exp.pinned()) return;
|
||||||
var sym = exp.argnames[parent.args.indexOf(this)];
|
var args = parent.args, sym;
|
||||||
|
for (var i = 0; i < args.length; i++) {
|
||||||
|
var arg = args[i];
|
||||||
|
if (arg === this) {
|
||||||
|
sym = exp.argnames[i];
|
||||||
|
if (!sym && exp.rest) return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (arg instanceof AST_Spread) return;
|
||||||
|
}
|
||||||
if (sym instanceof AST_DefaultValue) sym = sym.name;
|
if (sym instanceof AST_DefaultValue) sym = sym.name;
|
||||||
if (sym instanceof AST_SymbolFunarg && !all_bool(sym.definition(), bool_returns, compressor)) return;
|
if (sym instanceof AST_SymbolFunarg && !can_trim(sym.definition())) return;
|
||||||
} else if (parent.TYPE == "Call") {
|
} else if (parent.TYPE == "Call") {
|
||||||
compressor.pop();
|
compressor.pop();
|
||||||
var in_bool = compressor.in_boolean_context();
|
var in_bool = compressor.in_boolean_context();
|
||||||
compressor.push(this);
|
compressor.push(this);
|
||||||
if (!in_bool) return;
|
switch (in_bool) {
|
||||||
|
case true:
|
||||||
|
drop = false;
|
||||||
|
case "d":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else return;
|
} else return;
|
||||||
process_boolean_returns(this, compressor);
|
if (drop) {
|
||||||
|
drop_returns(compressor, this, true);
|
||||||
|
} else {
|
||||||
|
process_boolean_returns(this, compressor);
|
||||||
|
}
|
||||||
|
|
||||||
|
function can_trim(def) {
|
||||||
|
switch (can_trim_returns(def, self_returns, compressor)) {
|
||||||
|
case true:
|
||||||
|
drop = false;
|
||||||
|
case "d":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_BlockScope.DEFMETHOD("var_names", function() {
|
AST_BlockScope.DEFMETHOD("var_names", function() {
|
||||||
@@ -8155,6 +8214,118 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drop_returns(compressor, exp, ignore_name) {
|
||||||
|
if (!(exp instanceof AST_Lambda)) return;
|
||||||
|
var arrow = is_arrow(exp);
|
||||||
|
var async = is_async(exp);
|
||||||
|
var changed = false;
|
||||||
|
var drop_body = false;
|
||||||
|
if (arrow && compressor.option("arrows")) {
|
||||||
|
if (!exp.value) {
|
||||||
|
drop_body = true;
|
||||||
|
} else if (!async || is_primitive(compressor, exp.value)) {
|
||||||
|
var dropped = exp.value.drop_side_effect_free(compressor);
|
||||||
|
if (dropped !== exp.value) {
|
||||||
|
changed = true;
|
||||||
|
exp.value = dropped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!is_generator(exp)) {
|
||||||
|
if (!ignore_name && exp.name) {
|
||||||
|
var def = exp.name.definition();
|
||||||
|
drop_body = def.references.length == def.replaced;
|
||||||
|
} else {
|
||||||
|
drop_body = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (drop_body) {
|
||||||
|
exp.process_expression(false, function(node) {
|
||||||
|
var value = node.value;
|
||||||
|
if (value) {
|
||||||
|
if (async && !is_primitive(compressor, value)) return node;
|
||||||
|
value = value.drop_side_effect_free(compressor, true);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
if (!value) return make_node(AST_EmptyStatement, node);
|
||||||
|
return make_node(AST_SimpleStatement, node, { body: value });
|
||||||
|
});
|
||||||
|
scan_local_returns(exp, function(node) {
|
||||||
|
var value = node.value;
|
||||||
|
if (value) {
|
||||||
|
if (async && !is_primitive(compressor, value)) return;
|
||||||
|
var dropped = value.drop_side_effect_free(compressor);
|
||||||
|
if (dropped !== value) {
|
||||||
|
changed = true;
|
||||||
|
node.value = dropped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (async && compressor.option("awaits")) {
|
||||||
|
if (drop_body) exp.process_expression("awaits", function(node) {
|
||||||
|
var body = node.body;
|
||||||
|
if (body instanceof AST_Await) {
|
||||||
|
if (is_primitive(compressor, body.expression)) {
|
||||||
|
changed = true;
|
||||||
|
body = body.expression.drop_side_effect_free(compressor, true);
|
||||||
|
if (!body) return make_node(AST_EmptyStatement, node);
|
||||||
|
node.body = body;
|
||||||
|
}
|
||||||
|
} else if (body instanceof AST_Sequence) {
|
||||||
|
var exprs = body.expressions;
|
||||||
|
for (var i = exprs.length; --i >= 0;) {
|
||||||
|
var tail = exprs[i];
|
||||||
|
if (!(tail instanceof AST_Await)) break;
|
||||||
|
var value = tail.expression;
|
||||||
|
if (!is_primitive(compressor, value)) break;
|
||||||
|
changed = true;
|
||||||
|
if (exprs[i] = value.drop_side_effect_free(compressor)) break;
|
||||||
|
}
|
||||||
|
switch (i) {
|
||||||
|
case -1:
|
||||||
|
return make_node(AST_EmptyStatement, node);
|
||||||
|
case 0:
|
||||||
|
node.body = exprs[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exprs.length = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
var abort = !drop_body && exp.name || arrow && exp.value && !is_primitive(compressor, exp.value);
|
||||||
|
var tw = new TreeWalker(function(node) {
|
||||||
|
if (abort) return true;
|
||||||
|
if (tw.parent() === exp && node.may_throw(compressor)) return abort = true;
|
||||||
|
if (node instanceof AST_Await) return abort = true;
|
||||||
|
if (node instanceof AST_ForAwaitOf) return abort = true;
|
||||||
|
if (node instanceof AST_Return) {
|
||||||
|
if (node.value && !is_primitive(compressor, node.value)) return abort = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Scope && node !== exp) return true;
|
||||||
|
});
|
||||||
|
exp.walk(tw);
|
||||||
|
if (!abort) {
|
||||||
|
var ctor;
|
||||||
|
switch (exp.CTOR) {
|
||||||
|
case AST_AsyncArrow:
|
||||||
|
ctor = AST_Arrow;
|
||||||
|
break;
|
||||||
|
case AST_AsyncFunction:
|
||||||
|
ctor = AST_Function;
|
||||||
|
break;
|
||||||
|
case AST_AsyncGeneratorFunction:
|
||||||
|
ctor = AST_GeneratorFunction;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return make_node(ctor, exp, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed && exp.clone();
|
||||||
|
}
|
||||||
|
|
||||||
// drop_side_effect_free()
|
// drop_side_effect_free()
|
||||||
// remove side-effect-free parts which only affects return value
|
// remove side-effect-free parts which only affects return value
|
||||||
(function(def) {
|
(function(def) {
|
||||||
@@ -8261,116 +8432,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!rhs) return lhs;
|
if (!rhs) return lhs;
|
||||||
return make_sequence(this, [ lhs, rhs ]);
|
return make_sequence(this, [ lhs, rhs ]);
|
||||||
});
|
});
|
||||||
function drop_returns(compressor, exp) {
|
|
||||||
var arrow = is_arrow(exp);
|
|
||||||
var async = is_async(exp);
|
|
||||||
var changed = false;
|
|
||||||
var drop_body = false;
|
|
||||||
if (arrow && compressor.option("arrows")) {
|
|
||||||
if (!exp.value) {
|
|
||||||
drop_body = true;
|
|
||||||
} else if (!async || is_primitive(compressor, exp.value)) {
|
|
||||||
var dropped = exp.value.drop_side_effect_free(compressor);
|
|
||||||
if (dropped !== exp.value) {
|
|
||||||
changed = true;
|
|
||||||
exp.value = dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (exp instanceof AST_AsyncFunction || exp instanceof AST_Function) {
|
|
||||||
if (exp.name) {
|
|
||||||
var def = exp.name.definition();
|
|
||||||
drop_body = def.references.length == def.replaced;
|
|
||||||
} else {
|
|
||||||
drop_body = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (drop_body) {
|
|
||||||
exp.process_expression(false, function(node) {
|
|
||||||
var value = node.value;
|
|
||||||
if (value) {
|
|
||||||
if (async && !is_primitive(compressor, value)) return node;
|
|
||||||
value = value.drop_side_effect_free(compressor, true);
|
|
||||||
}
|
|
||||||
changed = true;
|
|
||||||
if (!value) return make_node(AST_EmptyStatement, node);
|
|
||||||
return make_node(AST_SimpleStatement, node, { body: value });
|
|
||||||
});
|
|
||||||
scan_local_returns(exp, function(node) {
|
|
||||||
var value = node.value;
|
|
||||||
if (value) {
|
|
||||||
if (async && !is_primitive(compressor, value)) return;
|
|
||||||
var dropped = value.drop_side_effect_free(compressor);
|
|
||||||
if (dropped !== value) {
|
|
||||||
changed = true;
|
|
||||||
node.value = dropped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (async && compressor.option("awaits")) {
|
|
||||||
if (drop_body) exp.process_expression("awaits", function(node) {
|
|
||||||
var body = node.body;
|
|
||||||
if (body instanceof AST_Await) {
|
|
||||||
if (is_primitive(compressor, body.expression)) {
|
|
||||||
changed = true;
|
|
||||||
body = body.expression.drop_side_effect_free(compressor, true);
|
|
||||||
if (!body) return make_node(AST_EmptyStatement, node);
|
|
||||||
node.body = body;
|
|
||||||
}
|
|
||||||
} else if (body instanceof AST_Sequence) {
|
|
||||||
var exprs = body.expressions;
|
|
||||||
for (var i = exprs.length; --i >= 0;) {
|
|
||||||
var tail = exprs[i];
|
|
||||||
if (!(tail instanceof AST_Await)) break;
|
|
||||||
var value = tail.expression;
|
|
||||||
if (!is_primitive(compressor, value)) break;
|
|
||||||
changed = true;
|
|
||||||
if (exprs[i] = value.drop_side_effect_free(compressor)) break;
|
|
||||||
}
|
|
||||||
switch (i) {
|
|
||||||
case -1:
|
|
||||||
return make_node(AST_EmptyStatement, node);
|
|
||||||
case 0:
|
|
||||||
node.body = exprs[0];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exprs.length = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
});
|
|
||||||
var abort = !drop_body && exp.name || arrow && exp.value && !is_primitive(compressor, exp.value);
|
|
||||||
var tw = new TreeWalker(function(node) {
|
|
||||||
if (abort) return true;
|
|
||||||
if (tw.parent() === exp && node.may_throw(compressor)) return abort = true;
|
|
||||||
if (node instanceof AST_Await) return abort = true;
|
|
||||||
if (node instanceof AST_ForAwaitOf) return abort = true;
|
|
||||||
if (node instanceof AST_Return) {
|
|
||||||
if (node.value && !is_primitive(compressor, node.value)) return abort = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_Scope && node !== exp) return true;
|
|
||||||
});
|
|
||||||
exp.walk(tw);
|
|
||||||
if (!abort) {
|
|
||||||
var ctor;
|
|
||||||
switch (exp.CTOR) {
|
|
||||||
case AST_AsyncArrow:
|
|
||||||
ctor = AST_Arrow;
|
|
||||||
break;
|
|
||||||
case AST_AsyncFunction:
|
|
||||||
ctor = AST_Function;
|
|
||||||
break;
|
|
||||||
case AST_AsyncGeneratorFunction:
|
|
||||||
ctor = AST_GeneratorFunction;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return make_node(ctor, exp, exp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return changed && exp.clone();
|
|
||||||
}
|
|
||||||
function assign_this_only(fn, compressor) {
|
function assign_this_only(fn, compressor) {
|
||||||
fn.new = true;
|
fn.new = true;
|
||||||
var result = all(fn.body, function(stat) {
|
var result = all(fn.body, function(stat) {
|
||||||
|
|||||||
@@ -448,6 +448,23 @@ concat_truthy: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process_returns: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return 42;
|
||||||
|
})() && console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
return 42;
|
||||||
|
})() && console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3465_1: {
|
issue_3465_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ funarg_inline: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
process_boolean_returns: {
|
process_returns: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
}
|
}
|
||||||
@@ -706,9 +706,7 @@ process_boolean_returns: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function({ length }) {
|
console.log(function({ length }) {
|
||||||
return length ? "FAIL" : "PASS";
|
return length ? "FAIL" : "PASS";
|
||||||
}(function() {
|
}(function() {}));
|
||||||
return 42;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
|
|||||||
@@ -6341,7 +6341,7 @@ issue_4612_4: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
console.log(function() {
|
||||||
function f() {
|
function f() {
|
||||||
return h();
|
h();
|
||||||
}
|
}
|
||||||
function g() {
|
function g() {
|
||||||
return h();
|
return h();
|
||||||
|
|||||||
@@ -1144,7 +1144,7 @@ conditional_assignments_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3856: {
|
issue_3856_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -1169,9 +1169,46 @@ issue_3856: {
|
|||||||
console.log(function() {
|
console.log(function() {
|
||||||
(function() {
|
(function() {
|
||||||
var a, b;
|
var a, b;
|
||||||
if (a) return a, 1;
|
if (a) a;
|
||||||
for (a = 0; !console;);
|
else {
|
||||||
return 0;
|
a = 0;
|
||||||
|
for (; !console;);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3856_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
(function() {
|
||||||
|
var a;
|
||||||
|
if (!a) {
|
||||||
|
a = 0;
|
||||||
|
for (var b; !console;);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (a) return 1;
|
||||||
|
})();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
(function() {
|
||||||
|
var a, b;
|
||||||
|
if (!a)
|
||||||
|
for (a = 0; !console;);
|
||||||
})();
|
})();
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user