Merge branch 'master' into harmony-v3.2.1
This commit is contained in:
18
lib/ast.js
18
lib/ast.js
@@ -1203,24 +1203,6 @@ TreeWalker.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
in_boolean_context: function() {
|
|
||||||
var stack = this.stack;
|
|
||||||
var i = stack.length, self = stack[--i];
|
|
||||||
while (i > 0) {
|
|
||||||
var p = stack[--i];
|
|
||||||
if ((p instanceof AST_If && p.condition === self) ||
|
|
||||||
(p instanceof AST_Conditional && p.condition === self) ||
|
|
||||||
(p instanceof AST_DWLoop && p.condition === self) ||
|
|
||||||
(p instanceof AST_For && p.condition === self) ||
|
|
||||||
(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
|
|
||||||
return false;
|
|
||||||
self = p;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loopcontrol_target: function(node) {
|
loopcontrol_target: function(node) {
|
||||||
var stack = this.stack;
|
var stack = this.stack;
|
||||||
if (node.label) for (var i = stack.length; --i >= 0;) {
|
if (node.label) for (var i = stack.length; --i >= 0;) {
|
||||||
|
|||||||
440
lib/compress.js
440
lib/compress.js
@@ -152,6 +152,27 @@ merge(Compressor.prototype, {
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
in_boolean_context: function() {
|
||||||
|
if (!this.option("booleans")) return false;
|
||||||
|
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
|
||||||
|
|| p instanceof AST_DWLoop && p.condition === self
|
||||||
|
|| p instanceof AST_For && p.condition === self
|
||||||
|
|| p instanceof AST_If && p.condition === self
|
||||||
|
|| 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 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
compress: function(node) {
|
compress: function(node) {
|
||||||
if (this.option("expression")) {
|
if (this.option("expression")) {
|
||||||
node.process_expression(true);
|
node.process_expression(true);
|
||||||
@@ -741,7 +762,7 @@ merge(Compressor.prototype, {
|
|||||||
function make_sequence(orig, expressions) {
|
function make_sequence(orig, expressions) {
|
||||||
if (expressions.length == 1) return expressions[0];
|
if (expressions.length == 1) return expressions[0];
|
||||||
return make_node(AST_Sequence, orig, {
|
return make_node(AST_Sequence, orig, {
|
||||||
expressions: expressions
|
expressions: expressions.reduce(merge_sequence, [])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,6 +819,7 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
array.push(node);
|
array.push(node);
|
||||||
}
|
}
|
||||||
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
function as_statement_array(thing) {
|
function as_statement_array(thing) {
|
||||||
@@ -851,14 +873,6 @@ merge(Compressor.prototype, {
|
|||||||
|| compressor.option("unsafe") && global_names(this.name);
|
|| compressor.option("unsafe") && global_names(this.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
function drop_decl(def) {
|
|
||||||
def.eliminated++;
|
|
||||||
if (def.orig.length == def.eliminated) {
|
|
||||||
def.scope.functions.del(def.name);
|
|
||||||
def.scope.variables.del(def.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_identifier_atom(node) {
|
function is_identifier_atom(node) {
|
||||||
return node instanceof AST_Infinity
|
return node instanceof AST_Infinity
|
||||||
|| node instanceof AST_NaN
|
|| node instanceof AST_NaN
|
||||||
@@ -1169,6 +1183,7 @@ merge(Compressor.prototype, {
|
|||||||
function get_lhs(expr) {
|
function get_lhs(expr) {
|
||||||
if (expr instanceof AST_VarDef && expr.name instanceof AST_SymbolDeclaration) {
|
if (expr instanceof AST_VarDef && expr.name instanceof AST_SymbolDeclaration) {
|
||||||
var def = expr.name.definition();
|
var def = expr.name.definition();
|
||||||
|
if (!member(expr.name, def.orig)) return;
|
||||||
var declared = def.orig.length - def.eliminated;
|
var declared = def.orig.length - def.eliminated;
|
||||||
var referenced = def.references.length - def.replaced;
|
var referenced = def.references.length - def.replaced;
|
||||||
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
||||||
@@ -1224,7 +1239,6 @@ merge(Compressor.prototype, {
|
|||||||
if (node === expr || node.body === expr) {
|
if (node === expr || node.body === expr) {
|
||||||
found = true;
|
found = true;
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_VarDef) {
|
||||||
drop_decl(node.name.definition());
|
|
||||||
node.value = null;
|
node.value = null;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -1496,13 +1510,7 @@ merge(Compressor.prototype, {
|
|||||||
function cons_seq(right) {
|
function cons_seq(right) {
|
||||||
n--;
|
n--;
|
||||||
var left = prev.body;
|
var left = prev.body;
|
||||||
if (!(left instanceof AST_Sequence)) {
|
return make_sequence(left, [ left, right ]).transform(compressor);
|
||||||
left = make_node(AST_Sequence, left, {
|
|
||||||
expressions: [ left ]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
merge_sequence(left.expressions, right);
|
|
||||||
return left.transform(compressor);
|
|
||||||
};
|
};
|
||||||
var n = 0, prev;
|
var n = 0, prev;
|
||||||
for (var i = 0, len = statements.length; i < len; i++) {
|
for (var i = 0, len = statements.length; i < len; i++) {
|
||||||
@@ -1520,7 +1528,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!abort) {
|
if (!abort) {
|
||||||
if (stat.init) stat.init = cons_seq(stat.init);
|
if (stat.init) stat.init = cons_seq(stat.init);
|
||||||
else {
|
else {
|
||||||
stat.init = prev.body.drop_side_effect_free(compressor);
|
stat.init = prev.body;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1664,7 +1672,7 @@ merge(Compressor.prototype, {
|
|||||||
|| this.alternative._dot_throw(compressor);
|
|| this.alternative._dot_throw(compressor);
|
||||||
})
|
})
|
||||||
def(AST_Sequence, function(compressor) {
|
def(AST_Sequence, function(compressor) {
|
||||||
return this.expressions[this.expressions.length - 1]._dot_throw(compressor);
|
return this.tail_node()._dot_throw(compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
if (this.is_undefined) return true;
|
if (this.is_undefined) return true;
|
||||||
@@ -1701,7 +1709,7 @@ merge(Compressor.prototype, {
|
|||||||
return this.operator == "=" && this.right.is_boolean();
|
return this.operator == "=" && this.right.is_boolean();
|
||||||
});
|
});
|
||||||
def(AST_Sequence, function(){
|
def(AST_Sequence, function(){
|
||||||
return this.expressions[this.expressions.length - 1].is_boolean();
|
return this.tail_node().is_boolean();
|
||||||
});
|
});
|
||||||
def(AST_True, return_true);
|
def(AST_True, return_true);
|
||||||
def(AST_False, return_true);
|
def(AST_False, return_true);
|
||||||
@@ -1728,7 +1736,7 @@ merge(Compressor.prototype, {
|
|||||||
|| this.operator == "=" && this.right.is_number(compressor);
|
|| this.operator == "=" && this.right.is_number(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Sequence, function(compressor){
|
def(AST_Sequence, function(compressor){
|
||||||
return this.expressions[this.expressions.length - 1].is_number(compressor);
|
return this.tail_node().is_number(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(compressor){
|
def(AST_Conditional, function(compressor){
|
||||||
return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);
|
return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);
|
||||||
@@ -1755,7 +1763,7 @@ merge(Compressor.prototype, {
|
|||||||
return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
|
return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Sequence, function(compressor){
|
def(AST_Sequence, function(compressor){
|
||||||
return this.expressions[this.expressions.length - 1].is_string(compressor);
|
return this.tail_node().is_string(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(compressor){
|
def(AST_Conditional, function(compressor){
|
||||||
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
|
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
|
||||||
@@ -1933,12 +1941,17 @@ merge(Compressor.prototype, {
|
|||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
def(AST_UnaryPrefix, function(compressor){
|
def(AST_UnaryPrefix, function(compressor){
|
||||||
|
var e = this.expression;
|
||||||
// Function would be evaluated to an array and so typeof would
|
// Function would be evaluated to an array and so typeof would
|
||||||
// incorrectly return 'object'. Hence making is a special case.
|
// incorrectly return 'object'. Hence making is a special case.
|
||||||
if (this.operator == "typeof" && is_func_expr(this.expression)) {
|
if (compressor.option("typeofs")
|
||||||
|
&& this.operator == "typeof"
|
||||||
|
&& (e instanceof AST_Lambda
|
||||||
|
|| e instanceof AST_SymbolRef
|
||||||
|
&& e.fixed_value() instanceof AST_Lambda)) {
|
||||||
return typeof function(){};
|
return typeof function(){};
|
||||||
}
|
}
|
||||||
var e = ev(this.expression, compressor);
|
e = ev(e, compressor);
|
||||||
if (e === this.expression) return this;
|
if (e === this.expression) return this;
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case "!": return !e;
|
case "!": return !e;
|
||||||
@@ -2000,7 +2013,6 @@ merge(Compressor.prototype, {
|
|||||||
return value === node ? this : value;
|
return value === node ? this : value;
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor){
|
def(AST_SymbolRef, function(compressor){
|
||||||
if (!compressor.option("reduce_vars")) return this;
|
|
||||||
var fixed = this.fixed_value();
|
var fixed = this.fixed_value();
|
||||||
if (!fixed) return this;
|
if (!fixed) return this;
|
||||||
this._eval = return_this;
|
this._eval = return_this;
|
||||||
@@ -2402,6 +2414,10 @@ merge(Compressor.prototype, {
|
|||||||
self.walk(new TreeWalker(function(node) {
|
self.walk(new TreeWalker(function(node) {
|
||||||
if (!result) return true;
|
if (!result) return true;
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
|
if (self.inlined) {
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
var def = node.definition();
|
var def = node.definition();
|
||||||
if (member(def, self.enclosed)
|
if (member(def, self.enclosed)
|
||||||
&& !self.variables.has(def.name)) {
|
&& !self.variables.has(def.name)) {
|
||||||
@@ -2589,51 +2605,21 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var sym;
|
|
||||||
if (scope === self
|
|
||||||
&& (sym = assign_as_unused(node)) instanceof AST_SymbolRef
|
|
||||||
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)
|
|
||||||
&& self.variables.get(sym.name) === sym.definition()) {
|
|
||||||
if (node instanceof AST_Assign) node.right.walk(tw);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_SymbolRef) {
|
|
||||||
var node_def = node.definition();
|
|
||||||
if (!(node_def.id in in_use_ids)) {
|
|
||||||
in_use_ids[node_def.id] = true;
|
|
||||||
in_use.push(node_def);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_Scope) {
|
|
||||||
var save_scope = scope;
|
|
||||||
scope = node;
|
|
||||||
descend();
|
|
||||||
scope = save_scope;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node.destructuring && destructuring_value) {
|
if (node.destructuring && destructuring_value) {
|
||||||
initializations.add(node.name, destructuring_value);
|
initializations.add(node.name, destructuring_value);
|
||||||
}
|
}
|
||||||
|
return scan_ref_scoped(node, descend);
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
// pass 2: for every used symbol we need to walk its
|
// pass 2: for every used symbol we need to walk its
|
||||||
// initialization code to figure out if it uses other
|
// initialization code to figure out if it uses other
|
||||||
// symbols (that may not be in_use).
|
// symbols (that may not be in_use).
|
||||||
|
tw = new TreeWalker(scan_ref_scoped);
|
||||||
for (var i = 0; i < in_use.length; ++i) {
|
for (var i = 0; i < in_use.length; ++i) {
|
||||||
in_use[i].orig.forEach(function(decl){
|
in_use[i].orig.forEach(function(decl){
|
||||||
// undeclared globals will be instanceof AST_SymbolRef
|
// undeclared globals will be instanceof AST_SymbolRef
|
||||||
var init = initializations.get(decl.name);
|
var init = initializations.get(decl.name);
|
||||||
if (init) init.forEach(function(init){
|
if (init) init.forEach(function(init){
|
||||||
var tw = new TreeWalker(function(node){
|
|
||||||
if (node instanceof AST_SymbolRef) {
|
|
||||||
var node_def = node.definition();
|
|
||||||
if (!(node_def.id in in_use_ids)) {
|
|
||||||
in_use_ids[node_def.id] = true;
|
|
||||||
in_use.push(node_def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
init.walk(tw);
|
init.walk(tw);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -2683,7 +2669,7 @@ merge(Compressor.prototype, {
|
|||||||
var keep = (def.id in in_use_ids) || !drop_funcs && def.global;
|
var keep = (def.id in in_use_ids) || !drop_funcs && def.global;
|
||||||
if (!keep) {
|
if (!keep) {
|
||||||
compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
|
compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
|
||||||
drop_decl(def);
|
def.eliminated++;
|
||||||
return make_node(AST_EmptyStatement, node);
|
return make_node(AST_EmptyStatement, node);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
@@ -2705,17 +2691,24 @@ merge(Compressor.prototype, {
|
|||||||
if (!(drop_vars || drop_block) || sym.id in in_use_ids) {
|
if (!(drop_vars || drop_block) || sym.id in in_use_ids) {
|
||||||
if (def.name instanceof AST_SymbolVar) {
|
if (def.name instanceof AST_SymbolVar) {
|
||||||
var var_defs = var_defs_by_id.get(sym.id);
|
var var_defs = var_defs_by_id.get(sym.id);
|
||||||
if (var_defs.length > 1 && !def.value) {
|
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
|
||||||
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
|
if (def.value) {
|
||||||
|
side_effects.push(make_node(AST_Assign, def, {
|
||||||
|
operator: "=",
|
||||||
|
left: make_node(AST_SymbolRef, def.name, def.name),
|
||||||
|
right: def.value
|
||||||
|
}));
|
||||||
|
}
|
||||||
remove(var_defs, def);
|
remove(var_defs, def);
|
||||||
drop_decl(sym);
|
sym.eliminated++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def.value) {
|
if (def.value) {
|
||||||
if (side_effects.length > 0) {
|
if (side_effects.length > 0) {
|
||||||
if (tail.length > 0) {
|
if (tail.length > 0) {
|
||||||
merge_sequence(side_effects, def.value);
|
side_effects.push(def.value);
|
||||||
def.value = make_sequence(def.value, side_effects);
|
def.value = make_sequence(def.value, side_effects);
|
||||||
} else {
|
} else {
|
||||||
body.push(make_node(AST_SimpleStatement, node, {
|
body.push(make_node(AST_SimpleStatement, node, {
|
||||||
@@ -2730,36 +2723,20 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
} else if (sym.orig[0] instanceof AST_SymbolCatch) {
|
} else if (sym.orig[0] instanceof AST_SymbolCatch) {
|
||||||
var value = def.value && def.value.drop_side_effect_free(compressor);
|
var value = def.value && def.value.drop_side_effect_free(compressor);
|
||||||
if (value) merge_sequence(side_effects, value);
|
if (value) side_effects.push(value);
|
||||||
def.value = null;
|
def.value = null;
|
||||||
head.push(def);
|
head.push(def);
|
||||||
} else {
|
} else {
|
||||||
var value = def.value && def.value.drop_side_effect_free(compressor);
|
var value = def.value && def.value.drop_side_effect_free(compressor);
|
||||||
if (value) {
|
if (value) {
|
||||||
compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
merge_sequence(side_effects, value);
|
side_effects.push(value);
|
||||||
} else {
|
} else {
|
||||||
compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
|
compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
}
|
}
|
||||||
drop_decl(sym);
|
sym.eliminated++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (head.length == 0 && tail.length == 1 && tail[0].name instanceof AST_SymbolVar) {
|
|
||||||
var var_defs = var_defs_by_id.get(tail[0].name.definition().id);
|
|
||||||
if (var_defs.length > 1) {
|
|
||||||
var def = tail.pop();
|
|
||||||
compressor.warn("Converting duplicated definition of variable {name} to assignment [{file}:{line},{col}]", template(def.name));
|
|
||||||
remove(var_defs, def);
|
|
||||||
side_effects.unshift(make_node(AST_Assign, def, {
|
|
||||||
operator: "=",
|
|
||||||
left: make_node(AST_SymbolRef, def.name, def.name),
|
|
||||||
right: def.value
|
|
||||||
}));
|
|
||||||
def = def.name.definition();
|
|
||||||
drop_decl(def);
|
|
||||||
def.replaced--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (head.length > 0 || tail.length > 0) {
|
if (head.length > 0 || tail.length > 0) {
|
||||||
node.definitions = head.concat(tail);
|
node.definitions = head.concat(tail);
|
||||||
body.push(node);
|
body.push(node);
|
||||||
@@ -2844,6 +2821,32 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
self.transform(tt);
|
self.transform(tt);
|
||||||
|
|
||||||
|
function scan_ref_scoped(node, descend) {
|
||||||
|
var sym;
|
||||||
|
if (scope === self
|
||||||
|
&& (sym = assign_as_unused(node)) instanceof AST_SymbolRef
|
||||||
|
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)
|
||||||
|
&& self.variables.get(sym.name) === sym.definition()) {
|
||||||
|
if (node instanceof AST_Assign) node.right.walk(tw);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_SymbolRef) {
|
||||||
|
var node_def = node.definition();
|
||||||
|
if (!(node_def.id in in_use_ids)) {
|
||||||
|
in_use_ids[node_def.id] = true;
|
||||||
|
in_use.push(node_def);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Scope) {
|
||||||
|
var save_scope = scope;
|
||||||
|
scope = node;
|
||||||
|
descend();
|
||||||
|
scope = save_scope;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
|
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
|
||||||
@@ -3005,7 +3008,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return self;
|
if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return self;
|
||||||
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||||
var defs_by_id = Object.create(null);
|
var defs_by_id = Object.create(null);
|
||||||
var tt = new TreeTransformer(function(node) {
|
var tt = new TreeTransformer(function(node, descend) {
|
||||||
if (node instanceof AST_Definitions && tt.parent() instanceof AST_Export) return node;
|
if (node instanceof AST_Definitions && tt.parent() instanceof AST_Export) return node;
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_VarDef) {
|
||||||
var sym = node.name, def, value;
|
var sym = node.name, def, value;
|
||||||
@@ -3016,6 +3019,7 @@ merge(Compressor.prototype, {
|
|||||||
&& !top_retain(def)
|
&& !top_retain(def)
|
||||||
&& (value = sym.fixed_value()) === node.value
|
&& (value = sym.fixed_value()) === node.value
|
||||||
&& value instanceof AST_Object) {
|
&& value instanceof AST_Object) {
|
||||||
|
descend(node, this);
|
||||||
var defs = new Dictionary();
|
var defs = new Dictionary();
|
||||||
var assignments = [];
|
var assignments = [];
|
||||||
value.properties.forEach(function(prop) {
|
value.properties.forEach(function(prop) {
|
||||||
@@ -3073,7 +3077,7 @@ merge(Compressor.prototype, {
|
|||||||
var node = nodes[i].drop_side_effect_free(compressor, first_in_statement);
|
var node = nodes[i].drop_side_effect_free(compressor, first_in_statement);
|
||||||
changed |= node !== nodes[i];
|
changed |= node !== nodes[i];
|
||||||
if (node) {
|
if (node) {
|
||||||
merge_sequence(ret, node);
|
ret.push(node);
|
||||||
first_in_statement = false;
|
first_in_statement = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3186,11 +3190,11 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(this, [ expression, property ]);
|
return make_sequence(this, [ expression, property ]);
|
||||||
});
|
});
|
||||||
def(AST_Sequence, function(compressor){
|
def(AST_Sequence, function(compressor){
|
||||||
var last = this.expressions[this.expressions.length - 1];
|
var last = this.tail_node();
|
||||||
var expr = last.drop_side_effect_free(compressor);
|
var expr = last.drop_side_effect_free(compressor);
|
||||||
if (expr === last) return this;
|
if (expr === last) return this;
|
||||||
var expressions = this.expressions.slice(0, -1);
|
var expressions = this.expressions.slice(0, -1);
|
||||||
if (expr) merge_sequence(expressions, expr);
|
if (expr) expressions.push(expr);
|
||||||
return make_sequence(this, expressions);
|
return make_sequence(this, expressions);
|
||||||
});
|
});
|
||||||
def(AST_Expansion, function(compressor, first_in_statement){
|
def(AST_Expansion, function(compressor, first_in_statement){
|
||||||
@@ -3220,34 +3224,40 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_DWLoop, function(self, compressor){
|
OPT(AST_While, function(self, compressor){
|
||||||
|
return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
|
||||||
|
});
|
||||||
|
|
||||||
|
OPT(AST_Do, function(self, compressor){
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
var cond = self.condition.evaluate(compressor);
|
var cond = self.condition.tail_node().evaluate(compressor);
|
||||||
if (cond !== self.condition) {
|
if (!(cond instanceof AST_Node)) {
|
||||||
if (cond) {
|
if (cond) return make_node(AST_For, self, {
|
||||||
return make_node(AST_For, self, {
|
body: make_node(AST_BlockStatement, self.body, {
|
||||||
body: self.body
|
body: [
|
||||||
});
|
self.body,
|
||||||
}
|
make_node(AST_SimpleStatement, self.condition, {
|
||||||
if (compressor.option("dead_code") && self instanceof AST_While) {
|
body: self.condition
|
||||||
var a = [];
|
})
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
]
|
||||||
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
})
|
||||||
}
|
}).optimize(compressor);
|
||||||
if (self instanceof AST_Do) {
|
var has_loop_control = false;
|
||||||
var has_loop_control = false;
|
var tw = new TreeWalker(function(node) {
|
||||||
var tw = new TreeWalker(function(node) {
|
if (node instanceof AST_Scope || has_loop_control) return true;
|
||||||
if (node instanceof AST_Scope || has_loop_control) return true;
|
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
|
||||||
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
|
return has_loop_control = true;
|
||||||
return has_loop_control = true;
|
});
|
||||||
});
|
var parent = compressor.parent();
|
||||||
var parent = compressor.parent();
|
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
|
||||||
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
|
if (!has_loop_control) return make_node(AST_BlockStatement, self.body, {
|
||||||
if (!has_loop_control) return self.body;
|
body: [
|
||||||
}
|
self.body,
|
||||||
}
|
make_node(AST_SimpleStatement, self.condition, {
|
||||||
if (self instanceof AST_While) {
|
body: self.condition
|
||||||
return make_node(AST_For, self, self).optimize(compressor);
|
})
|
||||||
|
]
|
||||||
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
@@ -3299,24 +3309,36 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
OPT(AST_For, function(self, compressor){
|
OPT(AST_For, function(self, compressor){
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
|
if (compressor.option("side_effects") && self.init) {
|
||||||
|
self.init = self.init.drop_side_effect_free(compressor);
|
||||||
|
}
|
||||||
if (self.condition) {
|
if (self.condition) {
|
||||||
var cond = self.condition.evaluate(compressor);
|
var cond = self.condition.evaluate(compressor);
|
||||||
if (compressor.option("dead_code") && !cond) {
|
if (!(cond instanceof AST_Node)) {
|
||||||
var a = [];
|
if (cond) self.condition = null;
|
||||||
if (self.init instanceof AST_Statement) {
|
else if (!compressor.option("dead_code")) {
|
||||||
a.push(self.init);
|
var orig = self.condition;
|
||||||
|
self.condition = make_node_from_constant(cond, self.condition);
|
||||||
|
self.condition = best_of_expression(self.condition.transform(compressor), orig);
|
||||||
}
|
}
|
||||||
else if (self.init) {
|
|
||||||
a.push(make_node(AST_SimpleStatement, self.init, {
|
|
||||||
body: self.init
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
|
||||||
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
|
||||||
}
|
}
|
||||||
if (cond !== self.condition) {
|
if (compressor.option("dead_code")) {
|
||||||
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
||||||
self.condition = best_of_expression(cond, self.condition);
|
if (!cond) {
|
||||||
|
var body = [];
|
||||||
|
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
||||||
|
if (self.init instanceof AST_Statement) {
|
||||||
|
body.push(self.init);
|
||||||
|
} else if (self.init) {
|
||||||
|
body.push(make_node(AST_SimpleStatement, self.init, {
|
||||||
|
body: self.init
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
|
body: self.condition
|
||||||
|
}));
|
||||||
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if_break_in_loop(self, compressor);
|
if_break_in_loop(self, compressor);
|
||||||
@@ -3332,28 +3354,34 @@ merge(Compressor.prototype, {
|
|||||||
// “has no side effects”; also it doesn't work for cases like
|
// “has no side effects”; also it doesn't work for cases like
|
||||||
// `x && true`, though it probably should.
|
// `x && true`, though it probably should.
|
||||||
var cond = self.condition.evaluate(compressor);
|
var cond = self.condition.evaluate(compressor);
|
||||||
if (cond !== self.condition) {
|
if (!compressor.option("dead_code") && !(cond instanceof AST_Node)) {
|
||||||
if (cond) {
|
var orig = self.condition;
|
||||||
compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
self.condition = make_node_from_constant(cond, orig);
|
||||||
if (compressor.option("dead_code")) {
|
self.condition = best_of_expression(self.condition.transform(compressor), orig);
|
||||||
var a = [];
|
}
|
||||||
if (self.alternative) {
|
if (compressor.option("dead_code")) {
|
||||||
extract_declarations_from_unreachable_code(compressor, self.alternative, a);
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
||||||
}
|
if (!cond) {
|
||||||
a.push(self.body);
|
|
||||||
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
||||||
if (compressor.option("dead_code")) {
|
var body = [];
|
||||||
var a = [];
|
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
if (self.alternative) a.push(self.alternative);
|
body: self.condition
|
||||||
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
}));
|
||||||
|
if (self.alternative) body.push(self.alternative);
|
||||||
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||||
|
} else if (!(cond instanceof AST_Node)) {
|
||||||
|
compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
||||||
|
var body = [];
|
||||||
|
if (self.alternative) {
|
||||||
|
extract_declarations_from_unreachable_code(compressor, self.alternative, body);
|
||||||
}
|
}
|
||||||
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
|
body: self.condition
|
||||||
|
}));
|
||||||
|
body.push(self.body);
|
||||||
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||||
}
|
}
|
||||||
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
|
||||||
self.condition = best_of_expression(cond, self.condition);
|
|
||||||
}
|
}
|
||||||
var negated = self.condition.negate(compressor);
|
var negated = self.condition.negate(compressor);
|
||||||
var self_condition_length = self.condition.print_to_string().length;
|
var self_condition_length = self.condition.print_to_string().length;
|
||||||
@@ -3465,11 +3493,15 @@ merge(Compressor.prototype, {
|
|||||||
if (!compressor.option("switches")) return self;
|
if (!compressor.option("switches")) return self;
|
||||||
var branch;
|
var branch;
|
||||||
var value = self.expression.evaluate(compressor);
|
var value = self.expression.evaluate(compressor);
|
||||||
if (value !== self.expression) {
|
if (!(value instanceof AST_Node)) {
|
||||||
var expression = make_node_from_constant(value, self.expression).transform(compressor);
|
var orig = self.expression;
|
||||||
self.expression = best_of_expression(expression, self.expression);
|
self.expression = make_node_from_constant(value, orig);
|
||||||
|
self.expression = best_of_expression(self.expression.transform(compressor), orig);
|
||||||
}
|
}
|
||||||
if (!compressor.option("dead_code")) return self;
|
if (!compressor.option("dead_code")) return self;
|
||||||
|
if (value instanceof AST_Node) {
|
||||||
|
value = self.expression.tail_node().evaluate(compressor);
|
||||||
|
}
|
||||||
var decl = [];
|
var decl = [];
|
||||||
var body = [];
|
var body = [];
|
||||||
var default_branch;
|
var default_branch;
|
||||||
@@ -3482,8 +3514,13 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
eliminate_branch(branch, body[body.length - 1]);
|
eliminate_branch(branch, body[body.length - 1]);
|
||||||
}
|
}
|
||||||
} else if (value !== self.expression) {
|
} else if (!(value instanceof AST_Node)) {
|
||||||
var exp = branch.expression.evaluate(compressor);
|
var exp = branch.expression.evaluate(compressor);
|
||||||
|
if (!(exp instanceof AST_Node) && exp !== value) {
|
||||||
|
eliminate_branch(branch, body[body.length - 1]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (exp instanceof AST_Node) exp = branch.expression.tail_node().evaluate(compressor);
|
||||||
if (exp === value) {
|
if (exp === value) {
|
||||||
exact_match = branch;
|
exact_match = branch;
|
||||||
if (default_branch) {
|
if (default_branch) {
|
||||||
@@ -3492,9 +3529,6 @@ merge(Compressor.prototype, {
|
|||||||
eliminate_branch(default_branch, body[default_index - 1]);
|
eliminate_branch(default_branch, body[default_index - 1]);
|
||||||
default_branch = null;
|
default_branch = null;
|
||||||
}
|
}
|
||||||
} else if (exp !== branch.expression) {
|
|
||||||
eliminate_branch(branch, body[body.length - 1]);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aborts(branch)) {
|
if (aborts(branch)) {
|
||||||
@@ -3537,12 +3571,16 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
if (!has_break) {
|
if (!has_break) {
|
||||||
body = body[0].body.slice();
|
var statements = body[0].body.slice();
|
||||||
body.unshift(make_node(AST_SimpleStatement, self.expression, {
|
var exp = body[0].expression;
|
||||||
body: self.expression
|
if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, {
|
||||||
|
body: exp
|
||||||
|
}));
|
||||||
|
statements.unshift(make_node(AST_SimpleStatement, self.expression, {
|
||||||
|
body:self.expression
|
||||||
}));
|
}));
|
||||||
return make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, {
|
||||||
body: body
|
body: statements
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3611,7 +3649,9 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
a.push(var_);
|
a.push(var_);
|
||||||
}
|
}
|
||||||
drop_decl(def.name.definition());
|
def = def.name.definition();
|
||||||
|
def.eliminated++;
|
||||||
|
def.replaced--;
|
||||||
return a;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
if (assignments.length == 0) return null;
|
if (assignments.length == 0) return null;
|
||||||
@@ -3971,7 +4011,7 @@ merge(Compressor.prototype, {
|
|||||||
trim_right_for_undefined();
|
trim_right_for_undefined();
|
||||||
if (end > 0 && compressor.option("cascade")) trim_left_for_assignment();
|
if (end > 0 && compressor.option("cascade")) trim_left_for_assignment();
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
self = maintain_this_binding(compressor.parent(), self, expressions[0]);
|
self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);
|
||||||
if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
|
if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -4113,7 +4153,7 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Undefined, self).optimize(compressor);
|
return make_node(AST_Undefined, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
if (compressor.in_boolean_context()) {
|
||||||
switch (self.operator) {
|
switch (self.operator) {
|
||||||
case "!":
|
case "!":
|
||||||
if (e instanceof AST_UnaryPrefix && e.operator == "!") {
|
if (e instanceof AST_UnaryPrefix && e.operator == "!") {
|
||||||
@@ -4267,7 +4307,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (compressor.option("booleans") && self.operator == "+" && compressor.in_boolean_context()) {
|
if (self.operator == "+" && compressor.in_boolean_context()) {
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
var rr = self.right.evaluate(compressor);
|
var rr = self.right.evaluate(compressor);
|
||||||
if (ll && typeof ll == "string") {
|
if (ll && typeof ll == "string") {
|
||||||
@@ -4324,49 +4364,72 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("evaluate")) {
|
if (compressor.option("evaluate")) {
|
||||||
switch (self.operator) {
|
switch (self.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.truthy ? true : self.left.falsy ? false : self.left.evaluate(compressor);
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor);
|
return maintain_this_binding(compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
||||||
} else if (ll !== self.left) {
|
} else if (!(ll instanceof AST_Node)) {
|
||||||
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor);
|
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
var rr = self.right.evaluate(compressor);
|
||||||
var rr = self.right.evaluate(compressor);
|
if (!rr) {
|
||||||
if (!rr) {
|
if (compressor.in_boolean_context()) {
|
||||||
compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
|
||||||
return make_sequence(self, [
|
return make_sequence(self, [
|
||||||
self.left,
|
self.left,
|
||||||
make_node(AST_False, self)
|
make_node(AST_False, self)
|
||||||
]).optimize(compressor);
|
]).optimize(compressor);
|
||||||
} else if (rr !== self.right) {
|
} else self.falsy = true;
|
||||||
compressor.warn("Dropping side-effect-free && in boolean context [{file}:{line},{col}]", self.start);
|
} else if (!(rr instanceof AST_Node)) {
|
||||||
|
var parent = compressor.parent();
|
||||||
|
if (parent.operator == "&&" && parent.left === compressor.self() || compressor.in_boolean_context()) {
|
||||||
|
compressor.warn("Dropping side-effect-free && [{file}:{line},{col}]", self.start);
|
||||||
return self.left.optimize(compressor);
|
return self.left.optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// x || false && y ---> x ? y : false
|
||||||
|
if (self.left.operator == "||") {
|
||||||
|
var lr = self.left.right.evaluate(compressor);
|
||||||
|
if (!lr) return make_node(AST_Conditional, self, {
|
||||||
|
condition: self.left.left,
|
||||||
|
consequent: self.right,
|
||||||
|
alternative: self.left.right
|
||||||
|
}).optimize(compressor);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "||":
|
case "||":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.truthy ? true : self.left.falsy ? false : self.left.evaluate(compressor);
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor);
|
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||||
} else if (ll !== self.left) {
|
} else if (!(ll instanceof AST_Node)) {
|
||||||
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor);
|
return maintain_this_binding(compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
var rr = self.right.evaluate(compressor);
|
||||||
var rr = self.right.evaluate(compressor);
|
if (!rr) {
|
||||||
if (!rr) {
|
var parent = compressor.parent();
|
||||||
compressor.warn("Dropping side-effect-free || in boolean context [{file}:{line},{col}]", self.start);
|
if (parent.operator == "||" && parent.left === compressor.self() || compressor.in_boolean_context()) {
|
||||||
|
compressor.warn("Dropping side-effect-free || [{file}:{line},{col}]", self.start);
|
||||||
return self.left.optimize(compressor);
|
return self.left.optimize(compressor);
|
||||||
} else if (rr !== self.right) {
|
}
|
||||||
|
} else if (!(rr instanceof AST_Node)) {
|
||||||
|
if (compressor.in_boolean_context()) {
|
||||||
compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
|
||||||
return make_sequence(self, [
|
return make_sequence(self, [
|
||||||
self.left,
|
self.left,
|
||||||
make_node(AST_True, self)
|
make_node(AST_True, self)
|
||||||
]).optimize(compressor);
|
]).optimize(compressor);
|
||||||
}
|
} else self.truthy = true;
|
||||||
|
}
|
||||||
|
if (self.left.operator == "&&") {
|
||||||
|
var lr = self.left.right.evaluate(compressor);
|
||||||
|
if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {
|
||||||
|
condition: self.left.left,
|
||||||
|
consequent: self.left.right,
|
||||||
|
alternative: self.right
|
||||||
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4818,10 +4881,10 @@ merge(Compressor.prototype, {
|
|||||||
if (cond !== self.condition) {
|
if (cond !== self.condition) {
|
||||||
if (cond) {
|
if (cond) {
|
||||||
compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.consequent);
|
return maintain_this_binding(compressor.parent(), compressor.self(), self.consequent);
|
||||||
} else {
|
} else {
|
||||||
compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.alternative);
|
return maintain_this_binding(compressor.parent(), compressor.self(), self.alternative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var negated = cond.negate(compressor, first_in_statement(compressor));
|
var negated = cond.negate(compressor, first_in_statement(compressor));
|
||||||
@@ -4902,7 +4965,7 @@ merge(Compressor.prototype, {
|
|||||||
consequent
|
consequent
|
||||||
]).optimize(compressor);
|
]).optimize(compressor);
|
||||||
}
|
}
|
||||||
|
var in_bool = compressor.in_boolean_context();
|
||||||
if (is_true(self.consequent)) {
|
if (is_true(self.consequent)) {
|
||||||
if (is_false(self.alternative)) {
|
if (is_false(self.alternative)) {
|
||||||
// c ? true : false ---> !!c
|
// c ? true : false ---> !!c
|
||||||
@@ -4958,22 +5021,31 @@ merge(Compressor.prototype, {
|
|||||||
// AST_True or !0
|
// AST_True or !0
|
||||||
function is_true(node) {
|
function is_true(node) {
|
||||||
return node instanceof AST_True
|
return node instanceof AST_True
|
||||||
|
|| in_bool
|
||||||
|
&& node instanceof AST_Constant
|
||||||
|
&& node.getValue()
|
||||||
|| (node instanceof AST_UnaryPrefix
|
|| (node instanceof AST_UnaryPrefix
|
||||||
&& node.operator == "!"
|
&& node.operator == "!"
|
||||||
&& node.expression instanceof AST_Constant
|
&& node.expression instanceof AST_Constant
|
||||||
&& !node.expression.value);
|
&& !node.expression.getValue());
|
||||||
}
|
}
|
||||||
// AST_False or !1
|
// AST_False or !1
|
||||||
function is_false(node) {
|
function is_false(node) {
|
||||||
return node instanceof AST_False
|
return node instanceof AST_False
|
||||||
|
|| in_bool
|
||||||
|
&& node instanceof AST_Constant
|
||||||
|
&& !node.getValue()
|
||||||
|| (node instanceof AST_UnaryPrefix
|
|| (node instanceof AST_UnaryPrefix
|
||||||
&& node.operator == "!"
|
&& node.operator == "!"
|
||||||
&& node.expression instanceof AST_Constant
|
&& node.expression instanceof AST_Constant
|
||||||
&& !!node.expression.value);
|
&& node.expression.getValue());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Boolean, function(self, compressor){
|
OPT(AST_Boolean, function(self, compressor){
|
||||||
|
if (compressor.in_boolean_context()) return make_node(AST_Number, self, {
|
||||||
|
value: +self.value
|
||||||
|
});
|
||||||
if (compressor.option("booleans")) {
|
if (compressor.option("booleans")) {
|
||||||
var p = compressor.parent();
|
var p = compressor.parent();
|
||||||
if (p instanceof AST_Binary && (p.operator == "=="
|
if (p instanceof AST_Binary && (p.operator == "=="
|
||||||
@@ -5168,7 +5240,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function literals_in_boolean_context(self, compressor) {
|
function literals_in_boolean_context(self, compressor) {
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
if (compressor.in_boolean_context()) {
|
||||||
return best_of(compressor, self, make_sequence(self, [
|
return best_of(compressor, self, make_sequence(self, [
|
||||||
self,
|
self,
|
||||||
make_node(AST_True, self)
|
make_node(AST_True, self)
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ function reserve_quoted_keys(ast, reserved) {
|
|||||||
function addStrings(node, add) {
|
function addStrings(node, add) {
|
||||||
node.walk(new TreeWalker(function(node) {
|
node.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
addStrings(node.expressions[node.expressions.length - 1], add);
|
addStrings(node.tail_node(), add);
|
||||||
} else if (node instanceof AST_String) {
|
} else if (node instanceof AST_String) {
|
||||||
add(node.value);
|
add(node.value);
|
||||||
} else if (node instanceof AST_Conditional) {
|
} else if (node instanceof AST_Conditional) {
|
||||||
|
|||||||
@@ -615,6 +615,11 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Node.DEFMETHOD("tail_node", return_this);
|
||||||
|
AST_Sequence.DEFMETHOD("tail_node", function() {
|
||||||
|
return this.expressions[this.expressions.length - 1];
|
||||||
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||||
options = this._default_mangler_options(options);
|
options = this._default_mangler_options(options);
|
||||||
try {
|
try {
|
||||||
@@ -643,7 +648,7 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
|||||||
skip_string(node.consequent);
|
skip_string(node.consequent);
|
||||||
skip_string(node.alternative);
|
skip_string(node.alternative);
|
||||||
} else if (node instanceof AST_Sequence) {
|
} else if (node instanceof AST_Sequence) {
|
||||||
skip_string(node.expressions[node.expressions.length - 1]);
|
skip_string(node.tail_node());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.2.0",
|
"version": "3.2.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -705,7 +705,7 @@ collapse_vars_lvalues_drop_assign: {
|
|||||||
function f2(x) { var z = x, a = ++z; return z += a; }
|
function f2(x) { var z = x, a = ++z; return z += a; }
|
||||||
function f3(x) { var a = (x -= 3); return x + a; }
|
function f3(x) { var a = (x -= 3); return x + a; }
|
||||||
function f4(x) { var a = (x -= 3); return x + a; }
|
function f4(x) { var a = (x -= 3); return x + a; }
|
||||||
function f5(x) { e1(); var v = e2(), c = v = --x; return x - c; }
|
function f5(x) { e1(), e2(); var c = --x; return x - c; }
|
||||||
function f6(x) { e1(), e2(); return --x - x; }
|
function f6(x) { e1(), e2(); return --x - x; }
|
||||||
function f7(x) { e1(); return x - (e2() - x); }
|
function f7(x) { e1(); return x - (e2() - x); }
|
||||||
function f8(x) { e1(); return x - (e2() - x); }
|
function f8(x) { e1(); return x - (e2() - x); }
|
||||||
@@ -2112,7 +2112,8 @@ chained_3: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(a, b) {
|
console.log(function(a, b) {
|
||||||
var c = 1, c = b;
|
var c = 1;
|
||||||
|
c = b;
|
||||||
b++;
|
b++;
|
||||||
return c;
|
return c;
|
||||||
}(0, 2));
|
}(0, 2));
|
||||||
@@ -2180,7 +2181,7 @@ inner_lvalues: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
double_def: {
|
double_def_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -2190,8 +2191,23 @@ double_def: {
|
|||||||
a();
|
a();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = x;
|
var a;
|
||||||
(a = a && y)();
|
(a = (a = x) && y)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double_def_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = x, a = a && y;
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(x && y)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2300,7 +2316,7 @@ lvalues_def: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = 0, b = 1;
|
var a = 0, b = 1;
|
||||||
var a = b++, b = +void 0;
|
a = b++, b = +void 0;
|
||||||
a && a[a++];
|
a && a[a++];
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
@@ -2666,6 +2682,7 @@ issue_2250_2: {
|
|||||||
issue_2298: {
|
issue_2298: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
passes: 2,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -3353,10 +3370,9 @@ issue_2437: {
|
|||||||
var result = !!req.onreadystatechange;
|
var result = !!req.onreadystatechange;
|
||||||
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
|
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
|
||||||
return result;
|
return result;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
var detectFunc = function () { };
|
var detectFunc = function () {};
|
||||||
req.onreadystatechange = detectFunc;
|
req.onreadystatechange = detectFunc;
|
||||||
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
||||||
req.onreadystatechange = null;
|
req.onreadystatechange = null;
|
||||||
@@ -3367,13 +3383,14 @@ issue_2437: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
if (xhrDesc)
|
if (xhrDesc) {
|
||||||
return result = !!(req = new XMLHttpRequest()).onreadystatechange,
|
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
|
||||||
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
||||||
result;
|
result;
|
||||||
var req = new XMLHttpRequest(), detectFunc = function() {};
|
}
|
||||||
req.onreadystatechange = detectFunc;
|
var req, detectFunc = function() {};
|
||||||
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
(req = new XMLHttpRequest()).onreadystatechange = detectFunc;
|
||||||
|
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
||||||
req.onreadystatechange = null;
|
req.onreadystatechange = null;
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -3824,6 +3841,7 @@ issue_2436_12: {
|
|||||||
issue_2436_13: {
|
issue_2436_13: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
passes: 2,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -3908,15 +3926,15 @@ issue_2497: {
|
|||||||
expect: {
|
expect: {
|
||||||
function sample() {
|
function sample() {
|
||||||
if (true)
|
if (true)
|
||||||
for (i = 0; i < 1; ++i)
|
for (var i = 0; i < 1; ++i)
|
||||||
for (k = 0; k < 1; ++k) {
|
for (var k = 0; k < 1; ++k) {
|
||||||
value = 1;
|
value = 1;
|
||||||
value = value ? value + 1 : 0;
|
value = value ? value + 1 : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (var i = 0; i < 1; ++i)
|
for (i = 0; i < 1; ++i)
|
||||||
for (var k = 0; k < 1; ++k)
|
for (k = 0; k < 1; ++k)
|
||||||
var value=1;
|
var value = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3924,6 +3942,7 @@ issue_2497: {
|
|||||||
issue_2506: {
|
issue_2506: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
passes: 2,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1015,3 +1015,103 @@ delete_conditional_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2535_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (true || x()) y();
|
||||||
|
if (true && x()) y();
|
||||||
|
if (x() || true) y();
|
||||||
|
if (x() && true) y();
|
||||||
|
if (false || x()) y();
|
||||||
|
if (false && x()) y();
|
||||||
|
if (x() || false) y();
|
||||||
|
if (x() && false) y();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
y();
|
||||||
|
x() && y();
|
||||||
|
(x(), 1) && y();
|
||||||
|
x() && y();
|
||||||
|
x() && y();
|
||||||
|
x() && y();
|
||||||
|
(x(), 0) && y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2535_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function x() {}
|
||||||
|
function y() {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
console.log((x() || true) || y());
|
||||||
|
console.log((y() || true) || x());
|
||||||
|
console.log((x() || true) && y());
|
||||||
|
console.log((y() || true) && x());
|
||||||
|
console.log((x() && true) || y());
|
||||||
|
console.log((y() && true) || x());
|
||||||
|
console.log((x() && true) && y());
|
||||||
|
console.log((y() && true) && x());
|
||||||
|
console.log((x() || false) || y());
|
||||||
|
console.log((y() || false) || x());
|
||||||
|
console.log((x() || false) && y());
|
||||||
|
console.log((y() || false) && x());
|
||||||
|
console.log((x() && false) || y());
|
||||||
|
console.log((y() && false) || x());
|
||||||
|
console.log((x() && false) && y());
|
||||||
|
console.log((y() && false) && x());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function x() {}
|
||||||
|
function y() {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
console.log(x() || !0);
|
||||||
|
console.log(y() || !0);
|
||||||
|
console.log((x(), y()));
|
||||||
|
console.log((y(), x()));
|
||||||
|
console.log(!!x() || y());
|
||||||
|
console.log(!!y() || x());
|
||||||
|
console.log(x() && y());
|
||||||
|
console.log(y() && x());
|
||||||
|
console.log(x() || y());
|
||||||
|
console.log(y() || x());
|
||||||
|
console.log(!!x() && y());
|
||||||
|
console.log(!!y() && x());
|
||||||
|
console.log((x(), y()));
|
||||||
|
console.log((y(), x()));
|
||||||
|
console.log(x() && !1);
|
||||||
|
console.log(y() && !1);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"true",
|
||||||
|
"foo",
|
||||||
|
"foo",
|
||||||
|
"undefined",
|
||||||
|
"foo",
|
||||||
|
"true",
|
||||||
|
"undefined",
|
||||||
|
"undefined",
|
||||||
|
"foo",
|
||||||
|
"foo",
|
||||||
|
"false",
|
||||||
|
"undefined",
|
||||||
|
"foo",
|
||||||
|
"undefined",
|
||||||
|
"undefined",
|
||||||
|
"false",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -129,8 +129,8 @@ dead_code_constant_boolean_should_warn_more: {
|
|||||||
var bar;
|
var bar;
|
||||||
// nothing for the while
|
// nothing for the while
|
||||||
// as for the for, it should keep:
|
// as for the for, it should keep:
|
||||||
var x = 10, y;
|
|
||||||
var moo;
|
var moo;
|
||||||
|
var x = 10, y;
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -165,8 +165,8 @@ dead_code_constant_boolean_should_warn_more_strict: {
|
|||||||
var foo;
|
var foo;
|
||||||
// nothing for the while
|
// nothing for the while
|
||||||
// as for the for, it should keep:
|
// as for the for, it should keep:
|
||||||
var x = 10, y;
|
|
||||||
var moo;
|
var moo;
|
||||||
|
var x = 10, y;
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -328,6 +328,8 @@ try_catch_finally: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = 1;
|
var a = 1;
|
||||||
|
|||||||
@@ -1569,12 +1569,92 @@ issue_2288: {
|
|||||||
expect: {
|
expect: {
|
||||||
function foo(o) {
|
function foo(o) {
|
||||||
o.a;
|
o.a;
|
||||||
for (i = 0; i < 0; i++);
|
|
||||||
for (var i = 0; i < 0; i++);
|
for (var i = 0; i < 0; i++);
|
||||||
|
for (i = 0; i < 0; i++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2516_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
function qux(x) {
|
||||||
|
bar.call(null, x);
|
||||||
|
}
|
||||||
|
function bar(x) {
|
||||||
|
var FOUR = 4;
|
||||||
|
var trouble = x || never_called();
|
||||||
|
var value = (FOUR - 1) * trouble;
|
||||||
|
console.log(value == 6 ? "PASS" : value);
|
||||||
|
}
|
||||||
|
Baz = qux;
|
||||||
|
}
|
||||||
|
var Baz;
|
||||||
|
foo();
|
||||||
|
Baz(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
Baz = function(x) {
|
||||||
|
(function(x) {
|
||||||
|
var trouble = x || never_called();
|
||||||
|
var value = (4 - 1) * trouble;
|
||||||
|
console.log(6 == value ? "PASS" : value);
|
||||||
|
}).call(null, x);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var Baz;
|
||||||
|
foo();
|
||||||
|
Baz(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2516_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
function qux(x) {
|
||||||
|
bar.call(null, x);
|
||||||
|
}
|
||||||
|
function bar(x) {
|
||||||
|
var FOUR = 4;
|
||||||
|
var trouble = x || never_called();
|
||||||
|
var value = (FOUR - 1) * trouble;
|
||||||
|
console.log(value == 6 ? "PASS" : value);
|
||||||
|
}
|
||||||
|
Baz = qux;
|
||||||
|
}
|
||||||
|
var Baz;
|
||||||
|
foo();
|
||||||
|
Baz(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
Baz = function(x) {
|
||||||
|
(function(x) {
|
||||||
|
var value = (4 - 1) * (x || never_called());
|
||||||
|
console.log(6 == value ? "PASS" : value);
|
||||||
|
}).call(null, x);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var Baz;
|
||||||
|
foo();
|
||||||
|
Baz(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
issue_2418_1: {
|
issue_2418_1: {
|
||||||
options = {
|
options = {
|
||||||
unused: true,
|
unused: true,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
and: {
|
and: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a;
|
var a;
|
||||||
@@ -76,7 +77,8 @@ and: {
|
|||||||
|
|
||||||
or: {
|
or: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a;
|
var a;
|
||||||
@@ -158,7 +160,8 @@ or: {
|
|||||||
|
|
||||||
unary_prefix: {
|
unary_prefix: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
a = !0 && b;
|
a = !0 && b;
|
||||||
@@ -1338,3 +1341,95 @@ self_comparison_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "false false true true 'number'"
|
expect_stdout: "false false true true 'number'"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2535_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if ((x() || true) || y()) z();
|
||||||
|
if ((x() || true) && y()) z();
|
||||||
|
if ((x() && true) || y()) z();
|
||||||
|
if ((x() && true) && y()) z();
|
||||||
|
if ((x() || false) || y()) z();
|
||||||
|
if ((x() || false) && y()) z();
|
||||||
|
if ((x() && false) || y()) z();
|
||||||
|
if ((x() && false) && y()) z();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (x(), 1) z();
|
||||||
|
if (x(), y()) z();
|
||||||
|
if (x() || y()) z();
|
||||||
|
if (x() && y()) z();
|
||||||
|
if (x() || y()) z();
|
||||||
|
if (x() && y()) z();
|
||||||
|
if (x(), y()) z();
|
||||||
|
if (x(), 0) z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2535_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(x() || true) || y();
|
||||||
|
(x() || true) && y();
|
||||||
|
(x() && true) || y();
|
||||||
|
(x() && true) && y();
|
||||||
|
(x() || false) || y();
|
||||||
|
(x() || false) && y();
|
||||||
|
(x() && false) || y();
|
||||||
|
(x() && false) && y();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x(),
|
||||||
|
x(), y(),
|
||||||
|
x() || y(),
|
||||||
|
x() && y(),
|
||||||
|
x() || y(),
|
||||||
|
x() && y(),
|
||||||
|
x(), y(),
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2535_3: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Object(1) && 1 && 2);
|
||||||
|
console.log(Object(1) && true && 1 && 2 && Object(2));
|
||||||
|
console.log(Object(1) && true && 1 && null && 2 && Object(2));
|
||||||
|
console.log(2 == Object(1) || 0 || void 0 || null);
|
||||||
|
console.log(2 == Object(1) || 0 || void 0 || null || Object(2));
|
||||||
|
console.log(2 == Object(1) || 0 || void 0 || "ok" || null || Object(2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(Object(1) && 2);
|
||||||
|
console.log(Object(1) && Object(2));
|
||||||
|
console.log(Object(1) && null);
|
||||||
|
console.log(2 == Object(1) || null);
|
||||||
|
console.log(2 == Object(1) || Object(2));
|
||||||
|
console.log(2 == Object(1) || "ok");
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1316,20]",
|
||||||
|
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1317,20]",
|
||||||
|
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1318,20]",
|
||||||
|
"WARN: Condition left of && always false [test/compress/evaluate.js:1318,20]",
|
||||||
|
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1319,20]",
|
||||||
|
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1320,20]",
|
||||||
|
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1321,20]",
|
||||||
|
"WARN: Condition left of || always true [test/compress/evaluate.js:1321,20]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ issue_485_crashing_1530: {
|
|||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
(function(a) {
|
(function(a) {
|
||||||
@@ -94,9 +95,7 @@ issue_485_crashing_1530: {
|
|||||||
var b = 42;
|
var b = 42;
|
||||||
})(this);
|
})(this);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {}
|
||||||
this, void 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1841_1: {
|
issue_1841_1: {
|
||||||
@@ -554,3 +553,102 @@ issue_2428: {
|
|||||||
"PASS",
|
"PASS",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2531_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function outer() {
|
||||||
|
function inner(value) {
|
||||||
|
function closure() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
return closure();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return inner("Hello");
|
||||||
|
}
|
||||||
|
console.log("Greeting:", outer()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function outer() {
|
||||||
|
return function(value) {
|
||||||
|
return function() {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
}("Hello");
|
||||||
|
}
|
||||||
|
console.log("Greeting:", outer()());
|
||||||
|
}
|
||||||
|
expect_stdout: "Greeting: Hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2531_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function outer() {
|
||||||
|
function inner(value) {
|
||||||
|
function closure() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
return closure();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return inner("Hello");
|
||||||
|
}
|
||||||
|
console.log("Greeting:", outer()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function outer() {
|
||||||
|
return function() {
|
||||||
|
return "Hello";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log("Greeting:", outer()());
|
||||||
|
}
|
||||||
|
expect_stdout: "Greeting: Hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2531_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function outer() {
|
||||||
|
function inner(value) {
|
||||||
|
function closure() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
return closure();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return inner("Hello");
|
||||||
|
}
|
||||||
|
console.log("Greeting:", outer()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("Greeting:", "Hello");
|
||||||
|
}
|
||||||
|
expect_stdout: "Greeting: Hello"
|
||||||
|
}
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ issue_2167: {
|
|||||||
global_defs: {
|
global_defs: {
|
||||||
"@isDevMode": "function(){}",
|
"@isDevMode": "function(){}",
|
||||||
},
|
},
|
||||||
|
passes: 2,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -792,3 +792,34 @@ issue_2508_6: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2519: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function testFunc() {
|
||||||
|
var dimensions = {
|
||||||
|
minX: 5,
|
||||||
|
maxX: 6,
|
||||||
|
};
|
||||||
|
var scale = 1;
|
||||||
|
var d = {
|
||||||
|
x: (dimensions.maxX + dimensions.minX) / 2,
|
||||||
|
};
|
||||||
|
return d.x * scale;
|
||||||
|
}
|
||||||
|
console.log(testFunc());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function testFunc() {
|
||||||
|
return 1 * ((6 + 5) / 2);
|
||||||
|
}
|
||||||
|
console.log(testFunc());
|
||||||
|
}
|
||||||
|
expect_stdout: "5.5"
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ issue_1639_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
||||||
if (--b, !1) var ignore = 0;
|
if (--b, 0) var ignore = 0;
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -57,7 +57,7 @@ issue_1639_2: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 100, b = 10;
|
var a = 100, b = 10;
|
||||||
function f19() {
|
function f19() {
|
||||||
++a, 1;
|
++a, 0;
|
||||||
}
|
}
|
||||||
f19(),
|
f19(),
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ f7: {
|
|||||||
"var b = 10;",
|
"var b = 10;",
|
||||||
"",
|
"",
|
||||||
"!function() {",
|
"!function() {",
|
||||||
" for (;b = 100, !1; ) ;",
|
" b = 100;",
|
||||||
"}(), console.log(100, b);",
|
"}(), console.log(100, b);",
|
||||||
]
|
]
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ case_1: {
|
|||||||
input: {
|
input: {
|
||||||
var a = 0, b = 1;
|
var a = 0, b = 1;
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case a, true:
|
case a || true:
|
||||||
default:
|
default:
|
||||||
b = 2;
|
b = 2;
|
||||||
case true:
|
case true:
|
||||||
@@ -17,7 +17,7 @@ case_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 0, b = 1;
|
var a = 0, b = 1;
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case a, true:
|
case a || true:
|
||||||
b = 2;
|
b = 2;
|
||||||
}
|
}
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
|
|||||||
@@ -134,5 +134,5 @@ label_while: {
|
|||||||
L: while (0) continue L;
|
L: while (0) continue L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: "function f(){L:;}"
|
expect_exact: "function f(){L:0}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ wrongly_optimized: {
|
|||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
// TODO: optimize to `func(), bar()`
|
// TODO: optimize to `func(), bar()`
|
||||||
(func(), 0) || bar();
|
(func(), 1) && bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ wrongly_optimized: {
|
|||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
// TODO: optimize to `func(), bar()`
|
// TODO: optimize to `func(), bar()`
|
||||||
if (func(), !0) bar();
|
if (func(), 1) bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
this_binding_conditionals: {
|
this_binding_conditionals: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate : true
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(1 && a)();
|
(1 && a)();
|
||||||
|
|||||||
@@ -192,9 +192,11 @@ keep_collapse_const_in_own_block_scope_2: {
|
|||||||
|
|
||||||
evaluate: {
|
evaluate: {
|
||||||
options = {
|
options = {
|
||||||
loops: true,
|
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -494,3 +496,43 @@ in_parenthesis_2: {
|
|||||||
}
|
}
|
||||||
expect_exact: 'for(function(){"foo"in{}};0;);'
|
expect_exact: 'for(function(){"foo"in{}};0;);'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_side_effects: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
side_effects: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
for (function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||||
|
for (function() {}(); i < 10; i++) console.log(i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (i = 0; i < 5; i++) console.log(i);
|
||||||
|
for (; i < 10; i++) console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
dead_code_condition: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var a = 0, b = 5; (a += 1, 3) - 3 && b > 0; b--) {
|
||||||
|
var c = function() {
|
||||||
|
b--;
|
||||||
|
}(a++);
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c;
|
||||||
|
var a = 0, b = 5;
|
||||||
|
a += 1, 0,
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -972,8 +972,8 @@ inner_var_for_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
a = 1;
|
var a = 1;
|
||||||
for (var b = 1; --b;) var a = 2;
|
for (var b = 1; --b;) a = 2;
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -1209,6 +1209,7 @@ toplevel_on_loops_2: {
|
|||||||
loops: true,
|
loops: true,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
toplevel:true,
|
toplevel:true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2346,7 +2347,7 @@ booleans: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(a) {
|
console.log(function(a) {
|
||||||
if (!1);
|
if (0);
|
||||||
switch (!1) {
|
switch (!1) {
|
||||||
case 0:
|
case 0:
|
||||||
return "FAIL";
|
return "FAIL";
|
||||||
|
|||||||
@@ -252,13 +252,12 @@ negate_iife_for: {
|
|||||||
input: {
|
input: {
|
||||||
(function() {})();
|
(function() {})();
|
||||||
for (i = 0; i < 5; i++) console.log(i);
|
for (i = 0; i < 5; i++) console.log(i);
|
||||||
|
|
||||||
(function() {})();
|
(function() {})();
|
||||||
for (; i < 5; i++) console.log(i);
|
for (; i < 10; i++) console.log(i);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||||
for (function() {}(); i < 5; i++) console.log(i);
|
for (!function() {}(); i < 10; i++) console.log(i);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -817,3 +817,50 @@ issue_1758: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0 3"
|
expect_stdout: "0 3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2535: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch(w(), 42) {
|
||||||
|
case 13: x();
|
||||||
|
case 42: y();
|
||||||
|
default: z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w(), 42;
|
||||||
|
42;
|
||||||
|
y();
|
||||||
|
z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1750: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 1;
|
||||||
|
switch (true) {
|
||||||
|
case a, true:
|
||||||
|
default:
|
||||||
|
b = 2;
|
||||||
|
case true:
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b = 1;
|
||||||
|
true;
|
||||||
|
a, true;
|
||||||
|
b = 2;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 2"
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ condition_evaluate: {
|
|||||||
if (void 0 == null);
|
if (void 0 == null);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
while (!1);
|
while (0);
|
||||||
for (; !0;);
|
for (; 1;);
|
||||||
if (!0);
|
if (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +68,7 @@ label_if_break: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
L: if (true) {
|
L: if (true) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
typeof_evaluation: {
|
typeof_evaluation: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true,
|
||||||
|
typeofs: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
a = typeof 1;
|
a = typeof 1;
|
||||||
@@ -44,7 +45,7 @@ typeof_in_boolean_context: {
|
|||||||
function f2() { return g(), "Yes"; }
|
function f2() { return g(), "Yes"; }
|
||||||
foo();
|
foo();
|
||||||
console.log(1);
|
console.log(1);
|
||||||
var a = !(console.log(2), !0);
|
var a = !(console.log(2), 1);
|
||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +58,83 @@ issue_1668: {
|
|||||||
if (typeof bar);
|
if (typeof bar);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
if (!0);
|
if (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeof_defun_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log("YES");
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
h = 42;
|
||||||
|
console.log("NOPE");
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
console.log("YUP");
|
||||||
|
}
|
||||||
|
g = 42;
|
||||||
|
"function" == typeof f && f();
|
||||||
|
"function" == typeof g && g();
|
||||||
|
"function" == typeof h && h();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function g() {
|
||||||
|
h = 42;
|
||||||
|
console.log("NOPE");
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
console.log("YUP");
|
||||||
|
}
|
||||||
|
g = 42;
|
||||||
|
console.log("YES");
|
||||||
|
"function" == typeof g && g();
|
||||||
|
h();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"YES",
|
||||||
|
"YUP",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defun_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = function() {
|
||||||
|
console.log(x);
|
||||||
|
};
|
||||||
|
var x = 0;
|
||||||
|
x++ < 2 && typeof f == "function" && f();
|
||||||
|
x++ < 2 && typeof f == "function" && f();
|
||||||
|
x++ < 2 && typeof f == "function" && f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = function() {
|
||||||
|
console.log(x);
|
||||||
|
};
|
||||||
|
var x = 0;
|
||||||
|
x++ < 2 && f();
|
||||||
|
x++ < 2 && f();
|
||||||
|
x++ < 2 && f();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user