enhance inline (#5226)
This commit is contained in:
@@ -707,7 +707,8 @@ to be `false` and all symbol names will be omitted.
|
|||||||
- `1` — inline simple functions
|
- `1` — inline simple functions
|
||||||
- `2` — inline functions with arguments
|
- `2` — inline functions with arguments
|
||||||
- `3` — inline functions with arguments and variables
|
- `3` — inline functions with arguments and variables
|
||||||
- `true` — same as `3`
|
- `4` — inline functions with arguments, variables and statements
|
||||||
|
- `true` — same as `4`
|
||||||
|
|
||||||
- `join_vars` (default: `true`) — join consecutive `var` statements
|
- `join_vars` (default: `true`) — join consecutive `var` statements
|
||||||
|
|
||||||
|
|||||||
14
lib/ast.js
14
lib/ast.js
@@ -1977,27 +1977,27 @@ var AST_Atom = DEFNODE("Atom", null, {
|
|||||||
|
|
||||||
var AST_Null = DEFNODE("Null", null, {
|
var AST_Null = DEFNODE("Null", null, {
|
||||||
$documentation: "The `null` atom",
|
$documentation: "The `null` atom",
|
||||||
value: null
|
value: null,
|
||||||
}, AST_Atom);
|
}, AST_Atom);
|
||||||
|
|
||||||
var AST_NaN = DEFNODE("NaN", null, {
|
var AST_NaN = DEFNODE("NaN", null, {
|
||||||
$documentation: "The impossible value",
|
$documentation: "The impossible value",
|
||||||
value: 0/0
|
value: 0/0,
|
||||||
}, AST_Atom);
|
}, AST_Atom);
|
||||||
|
|
||||||
var AST_Undefined = DEFNODE("Undefined", null, {
|
var AST_Undefined = DEFNODE("Undefined", null, {
|
||||||
$documentation: "The `undefined` value",
|
$documentation: "The `undefined` value",
|
||||||
value: function(){}()
|
value: function(){}(),
|
||||||
}, AST_Atom);
|
}, AST_Atom);
|
||||||
|
|
||||||
var AST_Hole = DEFNODE("Hole", null, {
|
var AST_Hole = DEFNODE("Hole", null, {
|
||||||
$documentation: "A hole in an array",
|
$documentation: "A hole in an array",
|
||||||
value: function(){}()
|
value: function(){}(),
|
||||||
}, AST_Atom);
|
}, AST_Atom);
|
||||||
|
|
||||||
var AST_Infinity = DEFNODE("Infinity", null, {
|
var AST_Infinity = DEFNODE("Infinity", null, {
|
||||||
$documentation: "The `Infinity` value",
|
$documentation: "The `Infinity` value",
|
||||||
value: 1/0
|
value: 1/0,
|
||||||
}, AST_Atom);
|
}, AST_Atom);
|
||||||
|
|
||||||
var AST_Boolean = DEFNODE("Boolean", null, {
|
var AST_Boolean = DEFNODE("Boolean", null, {
|
||||||
@@ -2009,12 +2009,12 @@ var AST_Boolean = DEFNODE("Boolean", null, {
|
|||||||
|
|
||||||
var AST_False = DEFNODE("False", null, {
|
var AST_False = DEFNODE("False", null, {
|
||||||
$documentation: "The `false` atom",
|
$documentation: "The `false` atom",
|
||||||
value: false
|
value: false,
|
||||||
}, AST_Boolean);
|
}, AST_Boolean);
|
||||||
|
|
||||||
var AST_True = DEFNODE("True", null, {
|
var AST_True = DEFNODE("True", null, {
|
||||||
$documentation: "The `true` atom",
|
$documentation: "The `true` atom",
|
||||||
value: true
|
value: true,
|
||||||
}, AST_Boolean);
|
}, AST_Boolean);
|
||||||
|
|
||||||
/* -----[ TreeWalker ]----- */
|
/* -----[ TreeWalker ]----- */
|
||||||
|
|||||||
302
lib/compress.js
302
lib/compress.js
@@ -121,7 +121,7 @@ function Compressor(options, false_by_default) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.options["inline"] === true) this.options["inline"] = 3;
|
if (this.options["inline"] === true) this.options["inline"] = 4;
|
||||||
this.drop_fargs = this.options["keep_fargs"] ? return_false : function(lambda, parent) {
|
this.drop_fargs = this.options["keep_fargs"] ? return_false : function(lambda, parent) {
|
||||||
if (lambda.length_read) return false;
|
if (lambda.length_read) return false;
|
||||||
var name = lambda.name;
|
var name = lambda.name;
|
||||||
@@ -1646,9 +1646,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
function make_node_from_constant(val, orig) {
|
function make_node_from_constant(val, orig) {
|
||||||
switch (typeof val) {
|
switch (typeof val) {
|
||||||
case "string":
|
case "string":
|
||||||
return make_node(AST_String, orig, {
|
return make_node(AST_String, orig, { value: val });
|
||||||
value: val
|
|
||||||
});
|
|
||||||
case "number":
|
case "number":
|
||||||
if (isNaN(val)) return make_node(AST_NaN, orig);
|
if (isNaN(val)) return make_node(AST_NaN, orig);
|
||||||
if (isFinite(val)) {
|
if (isFinite(val)) {
|
||||||
@@ -1659,7 +1657,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
return val < 0 ? make_node(AST_UnaryPrefix, orig, {
|
return val < 0 ? make_node(AST_UnaryPrefix, orig, {
|
||||||
operator: "-",
|
operator: "-",
|
||||||
expression: make_node(AST_Infinity, orig)
|
expression: make_node(AST_Infinity, orig),
|
||||||
}) : make_node(AST_Infinity, orig);
|
}) : make_node(AST_Infinity, orig);
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return make_node(val ? AST_True : AST_False, orig);
|
return make_node(val ? AST_True : AST_False, orig);
|
||||||
@@ -1667,7 +1665,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return make_node(AST_Undefined, orig);
|
return make_node(AST_Undefined, orig);
|
||||||
default:
|
default:
|
||||||
if (val === null) {
|
if (val === null) {
|
||||||
return make_node(AST_Null, orig, { value: null });
|
return make_node(AST_Null, orig);
|
||||||
}
|
}
|
||||||
if (val instanceof RegExp) {
|
if (val instanceof RegExp) {
|
||||||
return make_node(AST_RegExp, orig, { value: val });
|
return make_node(AST_RegExp, orig, { value: val });
|
||||||
@@ -1816,6 +1814,9 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
|
var in_lambda = last_of(compressor, function(node) {
|
||||||
|
return node instanceof AST_Lambda;
|
||||||
|
});
|
||||||
var in_loop, in_try, scope;
|
var in_loop, in_try, scope;
|
||||||
find_loop_scope_try();
|
find_loop_scope_try();
|
||||||
var changed, last_changed, max_iter = 10;
|
var changed, last_changed, max_iter = 10;
|
||||||
@@ -1832,22 +1833,37 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (handle_if_return(statements, compressor)) changed = 3;
|
if (handle_if_return(statements, compressor)) changed = 3;
|
||||||
if (!changed && last_changed == 3) break;
|
if (!changed && last_changed == 3) break;
|
||||||
}
|
}
|
||||||
if (compressor.sequences_limit > 0) {
|
if (compressor.option("inline") >= 4) {
|
||||||
if (sequencesize(statements, compressor)) changed = 4;
|
if (inline_last_iife(statements, compressor)) changed = 4;
|
||||||
if (!changed && last_changed == 4) break;
|
if (!changed && last_changed == 4) break;
|
||||||
if (sequencesize_2(statements, compressor)) changed = 5;
|
|
||||||
if (!changed && last_changed == 5) break;
|
|
||||||
}
|
}
|
||||||
if (compressor.option("join_vars")) {
|
if (compressor.sequences_limit > 0) {
|
||||||
if (join_consecutive_vars(statements)) changed = 6;
|
if (sequencesize(statements, compressor)) changed = 5;
|
||||||
|
if (!changed && last_changed == 5) break;
|
||||||
|
if (sequencesize_2(statements, compressor)) changed = 6;
|
||||||
if (!changed && last_changed == 6) break;
|
if (!changed && last_changed == 6) break;
|
||||||
}
|
}
|
||||||
|
if (compressor.option("join_vars")) {
|
||||||
|
if (join_consecutive_vars(statements)) changed = 7;
|
||||||
|
if (!changed && last_changed == 7) break;
|
||||||
|
}
|
||||||
if (compressor.option("collapse_vars")) {
|
if (compressor.option("collapse_vars")) {
|
||||||
if (collapse(statements, compressor)) changed = 7;
|
if (collapse(statements, compressor)) changed = 8;
|
||||||
}
|
}
|
||||||
} while (changed && max_iter-- > 0);
|
} while (changed && max_iter-- > 0);
|
||||||
return statements;
|
return statements;
|
||||||
|
|
||||||
|
function last_of(compressor, predicate) {
|
||||||
|
var block = compressor.self(), stat, level = 0;
|
||||||
|
do {
|
||||||
|
do {
|
||||||
|
if (predicate(block)) return true;
|
||||||
|
block = compressor.parent(level++);
|
||||||
|
} while (block instanceof AST_If && (stat = block));
|
||||||
|
} while ((block instanceof AST_BlockStatement || block instanceof AST_Scope)
|
||||||
|
&& is_last_statement(block.body, stat));
|
||||||
|
}
|
||||||
|
|
||||||
function find_loop_scope_try() {
|
function find_loop_scope_try() {
|
||||||
var node = compressor.self(), level = 0;
|
var node = compressor.self(), level = 0;
|
||||||
do {
|
do {
|
||||||
@@ -3135,11 +3151,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
function handle_if_return(statements, compressor) {
|
function handle_if_return(statements, compressor) {
|
||||||
var changed = false;
|
var changed = false;
|
||||||
var self = compressor.self();
|
|
||||||
var parent = compressor.parent();
|
var parent = compressor.parent();
|
||||||
var in_lambda = last_of(function(node) {
|
|
||||||
return node instanceof AST_Lambda;
|
|
||||||
});
|
|
||||||
var in_iife = in_lambda && parent && parent.TYPE == "Call";
|
var in_iife = in_lambda && parent && parent.TYPE == "Call";
|
||||||
var multiple_if_returns = has_multiple_if_returns(statements);
|
var multiple_if_returns = has_multiple_if_returns(statements);
|
||||||
for (var i = statements.length; --i >= 0;) {
|
for (var i = statements.length; --i >= 0;) {
|
||||||
@@ -3163,9 +3175,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
body = stat.value.clone();
|
body = stat.value.clone();
|
||||||
body.expressions[body.length - 1] = tail.expression;
|
body.expressions[body.length - 1] = tail.expression;
|
||||||
}
|
}
|
||||||
statements[i] = make_node(AST_SimpleStatement, stat, {
|
statements[i] = make_node(AST_SimpleStatement, stat, { body: body });
|
||||||
body: body,
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3179,11 +3189,9 @@ Compressor.prototype.compress = function(node) {
|
|||||||
stat.condition = stat.condition.negate(compressor);
|
stat.condition = stat.condition.negate(compressor);
|
||||||
var body = as_statement_array_with_return(stat.body, ab);
|
var body = as_statement_array_with_return(stat.body, ab);
|
||||||
stat.body = make_node(AST_BlockStatement, stat, {
|
stat.body = make_node(AST_BlockStatement, stat, {
|
||||||
body: as_statement_array(stat.alternative).concat(extract_functions())
|
body: as_statement_array(stat.alternative).concat(extract_functions()),
|
||||||
});
|
|
||||||
stat.alternative = make_node(AST_BlockStatement, stat, {
|
|
||||||
body: body
|
|
||||||
});
|
});
|
||||||
|
stat.alternative = make_node(AST_BlockStatement, stat, { body: body });
|
||||||
statements[i] = stat;
|
statements[i] = stat;
|
||||||
statements[i] = stat.transform(compressor);
|
statements[i] = stat.transform(compressor);
|
||||||
continue;
|
continue;
|
||||||
@@ -3209,12 +3217,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
changed = true;
|
changed = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.body = make_node(AST_BlockStatement, stat.body, {
|
stat.body = make_node(AST_BlockStatement, stat.body, {
|
||||||
body: as_statement_array(stat.body).concat(extract_functions())
|
body: as_statement_array(stat.body).concat(extract_functions()),
|
||||||
});
|
});
|
||||||
var body = as_statement_array_with_return(stat.alternative, alt);
|
var body = as_statement_array_with_return(stat.alternative, alt);
|
||||||
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
stat.alternative = make_node(AST_BlockStatement, stat.alternative, { body: body });
|
||||||
body: body
|
|
||||||
});
|
|
||||||
statements[i] = stat;
|
statements[i] = stat;
|
||||||
statements[i] = stat.transform(compressor);
|
statements[i] = stat.transform(compressor);
|
||||||
continue;
|
continue;
|
||||||
@@ -3222,14 +3228,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
if (compressor.option("typeofs")) {
|
if (compressor.option("typeofs")) {
|
||||||
if (ab && !alt) {
|
if (ab && !alt) {
|
||||||
mark_locally_defined(stat.condition, null, make_node(AST_BlockStatement, self, {
|
var stats = make_node(AST_BlockStatement, compressor.self(), {
|
||||||
body: statements.slice(i + 1)
|
body: statements.slice(i + 1),
|
||||||
}));
|
});
|
||||||
|
mark_locally_defined(stat.condition, null, stats);
|
||||||
}
|
}
|
||||||
if (!ab && alt) {
|
if (!ab && alt) {
|
||||||
mark_locally_defined(stat.condition, make_node(AST_BlockStatement, self, {
|
var stats = make_node(AST_BlockStatement, compressor.self(), {
|
||||||
body: statements.slice(i + 1)
|
body: statements.slice(i + 1),
|
||||||
}));
|
});
|
||||||
|
mark_locally_defined(stat.condition, stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3243,9 +3251,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!value && !stat.alternative
|
if (!value && !stat.alternative
|
||||||
&& (in_lambda && !next || next instanceof AST_Return && !next.value)) {
|
&& (in_lambda && !next || next instanceof AST_Return && !next.value)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
statements[i] = make_node(AST_SimpleStatement, stat.condition, {
|
statements[i] = make_node(AST_SimpleStatement, stat.condition, { body: stat.condition });
|
||||||
body: stat.condition
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//---
|
//---
|
||||||
@@ -3263,9 +3269,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!stat.alternative && !next && in_lambda && (in_bool || value && multiple_if_returns)) {
|
if (!stat.alternative && !next && in_lambda && (in_bool || value && multiple_if_returns)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.alternative = make_node(AST_Return, stat, {
|
stat.alternative = make_node(AST_Return, stat, { value: null });
|
||||||
value: null
|
|
||||||
});
|
|
||||||
statements.splice(i, 1, stat.transform(compressor));
|
statements.splice(i, 1, stat.transform(compressor));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3284,10 +3288,8 @@ Compressor.prototype.compress = function(node) {
|
|||||||
stat.alternative = make_node(AST_BlockStatement, next, {
|
stat.alternative = make_node(AST_BlockStatement, next, {
|
||||||
body: [
|
body: [
|
||||||
next,
|
next,
|
||||||
make_node(AST_Return, next, {
|
make_node(AST_Return, next, { value: null }),
|
||||||
value: null
|
],
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
statements.splice(i, 1, stat.transform(compressor));
|
statements.splice(i, 1, stat.transform(compressor));
|
||||||
statements.splice(j, 1);
|
statements.splice(j, 1);
|
||||||
@@ -3312,19 +3314,8 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
|
return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
|
||||||
}
|
}
|
||||||
|
|
||||||
function last_of(predicate) {
|
|
||||||
var block = self, stat, level = 0;
|
|
||||||
do {
|
|
||||||
do {
|
|
||||||
if (predicate(block)) return true;
|
|
||||||
block = compressor.parent(level++);
|
|
||||||
} while (block instanceof AST_If && (stat = block));
|
|
||||||
} while ((block instanceof AST_BlockStatement || block instanceof AST_Scope)
|
|
||||||
&& is_last_statement(block.body, stat));
|
|
||||||
}
|
|
||||||
|
|
||||||
function match_target(target) {
|
function match_target(target) {
|
||||||
return last_of(function(node) {
|
return last_of(compressor, function(node) {
|
||||||
return node === target;
|
return node === target;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3426,6 +3417,25 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return statements.length != len;
|
return statements.length != len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function inline_last_iife(statements, compressor) {
|
||||||
|
if (!in_lambda) return false;
|
||||||
|
var index = statements.length - 1;
|
||||||
|
var stat = statements[index];
|
||||||
|
if (!(stat instanceof AST_SimpleStatement)) return false;
|
||||||
|
var body = stat.body;
|
||||||
|
if (body instanceof AST_UnaryPrefix) {
|
||||||
|
if (unary_side_effects[body.operator]) return false;
|
||||||
|
body = body.expression;
|
||||||
|
}
|
||||||
|
var inlined = make_node(AST_UnaryPrefix, stat, {
|
||||||
|
operator: "void",
|
||||||
|
expression: body,
|
||||||
|
}).try_inline(compressor, scope);
|
||||||
|
if (!inlined) return false;
|
||||||
|
statements[index] = inlined;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function sequencesize(statements, compressor) {
|
function sequencesize(statements, compressor) {
|
||||||
if (statements.length < 2) return;
|
if (statements.length < 2) return;
|
||||||
var seq = [], n = 0;
|
var seq = [], n = 0;
|
||||||
@@ -9351,6 +9361,26 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return avoid.length && makePredicate(avoid);
|
return avoid.length && makePredicate(avoid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function safe_from_await_yield(fn, avoid) {
|
||||||
|
if (!avoid) return true;
|
||||||
|
var safe = true;
|
||||||
|
var tw = new TreeWalker(function(node) {
|
||||||
|
if (!safe) return true;
|
||||||
|
if (node instanceof AST_Scope) {
|
||||||
|
if (node === fn) return;
|
||||||
|
if (is_arrow(node)) {
|
||||||
|
for (var i = 0; safe && i < node.argnames.length; i++) node.argnames[i].walk(tw);
|
||||||
|
} else if (node instanceof AST_LambdaDefinition && avoid[node.name.name]) {
|
||||||
|
safe = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Symbol && avoid[node.name] && node !== fn.name) safe = false;
|
||||||
|
});
|
||||||
|
fn.walk(tw);
|
||||||
|
return safe;
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_Call, function(self, compressor) {
|
OPT(AST_Call, function(self, compressor) {
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
var terminated = trim_optional_chain(self, compressor);
|
var terminated = trim_optional_chain(self, compressor);
|
||||||
@@ -9681,7 +9711,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (exp === fn
|
if (exp === fn
|
||||||
&& !fn.name
|
&& !fn.name
|
||||||
&& (!value || value.is_constant_expression())
|
&& (!value || value.is_constant_expression())
|
||||||
&& safe_from_await_yield(fn, compressor.find_parent(AST_Scope))) {
|
&& safe_from_await_yield(fn, avoid_await_yield(compressor.find_parent(AST_Scope)))) {
|
||||||
return make_sequence(self, convert_args(value)).optimize(compressor);
|
return make_sequence(self, convert_args(value)).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9693,7 +9723,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
&& !(fn.name && fn instanceof AST_LambdaExpression)
|
&& !(fn.name && fn instanceof AST_LambdaExpression)
|
||||||
&& (exp === fn || !recursive_ref(compressor, def = exp.definition(), fn)
|
&& (exp === fn || !recursive_ref(compressor, def = exp.definition(), fn)
|
||||||
&& fn.is_constant_expression(find_scope(compressor)))
|
&& fn.is_constant_expression(find_scope(compressor)))
|
||||||
&& !has_spread
|
|
||||||
&& (value = can_flatten_body(stat))
|
&& (value = can_flatten_body(stat))
|
||||||
&& !fn.contains_this()) {
|
&& !fn.contains_this()) {
|
||||||
var replacing = exp === fn || def.single_use && def.references.length - def.replaced == 1;
|
var replacing = exp === fn || def.single_use && def.references.length - def.replaced == 1;
|
||||||
@@ -9761,7 +9790,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
&& all(fn.body, is_empty)
|
&& all(fn.body, is_empty)
|
||||||
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
||||||
&& !(is_arrow(fn) && fn.value)
|
&& !(is_arrow(fn) && fn.value)
|
||||||
&& safe_from_await_yield(fn, compressor.find_parent(AST_Scope))) {
|
&& safe_from_await_yield(fn, avoid_await_yield(compressor.find_parent(AST_Scope)))) {
|
||||||
return make_sequence(self, convert_args()).optimize(compressor);
|
return make_sequence(self, convert_args()).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9869,27 +9898,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
function safe_from_await_yield(node, scope) {
|
|
||||||
var avoid = avoid_await_yield(scope);
|
|
||||||
if (!avoid) return true;
|
|
||||||
var safe = true;
|
|
||||||
var tw = new TreeWalker(function(node) {
|
|
||||||
if (!safe) return true;
|
|
||||||
if (node instanceof AST_Scope) {
|
|
||||||
if (node === fn) return;
|
|
||||||
if (is_arrow(node)) {
|
|
||||||
for (var i = 0; safe && i < node.argnames.length; i++) node.argnames[i].walk(tw);
|
|
||||||
} else if (node instanceof AST_LambdaDefinition && avoid[node.name.name]) {
|
|
||||||
safe = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_Symbol && avoid[node.name] && node !== fn.name) safe = false;
|
|
||||||
});
|
|
||||||
node.walk(tw);
|
|
||||||
return safe;
|
|
||||||
}
|
|
||||||
|
|
||||||
function noop_value() {
|
function noop_value() {
|
||||||
return self.call_only ? make_node(AST_Number, self, { value: 0 }) : make_node(AST_Undefined, self);
|
return self.call_only ? make_node(AST_Number, self, { value: 0 }) : make_node(AST_Undefined, self);
|
||||||
}
|
}
|
||||||
@@ -9941,7 +9949,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function can_substitute_directly() {
|
function can_substitute_directly() {
|
||||||
if (has_default || has_destructured || var_assigned || fn.rest) return;
|
if (has_default || has_destructured || has_spread || var_assigned || fn.rest) return;
|
||||||
if (compressor.option("inline") < 2 && fn.argnames.length) return;
|
if (compressor.option("inline") < 2 && fn.argnames.length) return;
|
||||||
if (!fn.variables.all(function(def) {
|
if (!fn.variables.all(function(def) {
|
||||||
return def.references.length - def.replaced < 2 && def.orig[0] instanceof AST_SymbolFunarg;
|
return def.references.length - def.replaced < 2 && def.orig[0] instanceof AST_SymbolFunarg;
|
||||||
@@ -10065,7 +10073,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
} while (!(scope instanceof AST_Scope));
|
} while (!(scope instanceof AST_Scope));
|
||||||
insert = scope.body.indexOf(child) + 1;
|
insert = scope.body.indexOf(child) + 1;
|
||||||
if (!insert) return false;
|
if (!insert) return false;
|
||||||
if (!safe_from_await_yield(fn, scope)) return false;
|
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return false;
|
||||||
var safe_to_inject = exp !== fn || fn.parent_scope.resolve() === scope;
|
var safe_to_inject = exp !== fn || fn.parent_scope.resolve() === scope;
|
||||||
if (scope instanceof AST_Toplevel) {
|
if (scope instanceof AST_Toplevel) {
|
||||||
if (compressor.toplevel.vars) {
|
if (compressor.toplevel.vars) {
|
||||||
@@ -10227,7 +10235,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
function flatten_fn() {
|
function flatten_fn() {
|
||||||
var decls = [];
|
var decls = [];
|
||||||
var expressions = [];
|
var expressions = [];
|
||||||
if (has_default > 1 || has_destructured || fn.rest) {
|
if (has_default > 1 || has_destructured || has_spread || fn.rest) {
|
||||||
flatten_destructured(decls, expressions);
|
flatten_destructured(decls, expressions);
|
||||||
} else {
|
} else {
|
||||||
flatten_args(decls, expressions);
|
flatten_args(decls, expressions);
|
||||||
@@ -12676,10 +12684,134 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
(function(def) {
|
||||||
|
def(AST_Node, noop);
|
||||||
|
function process(sym, argname) {
|
||||||
|
argname.definition().orig.push(sym);
|
||||||
|
}
|
||||||
|
def(AST_Call, function(compressor, scope) {
|
||||||
|
if (compressor.option("inline") < 4) return;
|
||||||
|
var call = this;
|
||||||
|
if (call.is_expr_pure(compressor)) return;
|
||||||
|
var fn = call.expression;
|
||||||
|
if (!(fn instanceof AST_Function)) return;
|
||||||
|
if (fn.name) return;
|
||||||
|
if (fn.uses_arguments) return;
|
||||||
|
if (fn.contains_this()) return;
|
||||||
|
if (!scope) scope = compressor.find_parent(AST_Scope);
|
||||||
|
var names = scope.var_names();
|
||||||
|
if (!fn.variables.all(function(def, name) {
|
||||||
|
if (!names.has(name)) return true;
|
||||||
|
if (name != "arguments") return false;
|
||||||
|
if (scope.uses_arguments) return false;
|
||||||
|
return def.references.length == def.replaced;
|
||||||
|
})) return;
|
||||||
|
var safe = true;
|
||||||
|
fn.each_argname(function(argname) {
|
||||||
|
if (!all(argname.definition().orig, function(sym) {
|
||||||
|
return !(sym instanceof AST_SymbolDefun);
|
||||||
|
})) safe = false;
|
||||||
|
});
|
||||||
|
if (!safe) return;
|
||||||
|
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return;
|
||||||
|
fn.functions.each(function(def, name) {
|
||||||
|
scope.functions.set(name, def);
|
||||||
|
});
|
||||||
|
fn.variables.each(function(def, name) {
|
||||||
|
scope.variables.set(name, def);
|
||||||
|
def.single_use = false;
|
||||||
|
});
|
||||||
|
if (fn.variables.has("NaN")) scope.transform(new TreeTransformer(function(node) {
|
||||||
|
if (node instanceof AST_NaN) return make_node(AST_Binary, node, {
|
||||||
|
operator: "/",
|
||||||
|
left: make_node(AST_Number, node, { value: 0 }),
|
||||||
|
right: make_node(AST_Number, node, { value: 0 }),
|
||||||
|
});
|
||||||
|
if (node instanceof AST_Scope && node !== scope) return node;
|
||||||
|
}));
|
||||||
|
var body = [];
|
||||||
|
if (fn.rest || !all(fn.argnames, function(argname) {
|
||||||
|
return argname instanceof AST_SymbolFunarg;
|
||||||
|
}) || !all(call.args, function(arg) {
|
||||||
|
return !(arg instanceof AST_Spread);
|
||||||
|
})) {
|
||||||
|
body.push(make_node(AST_Var, call, {
|
||||||
|
definitions: [ make_node(AST_VarDef, call, {
|
||||||
|
name: make_node(AST_DestructuredArray, call, {
|
||||||
|
elements: fn.argnames.map(function(argname) {
|
||||||
|
if (argname.unused) return make_node(AST_Hole, argname);
|
||||||
|
return argname.convert_symbol(AST_SymbolVar, process);
|
||||||
|
}),
|
||||||
|
rest: fn.rest && fn.rest.convert_symbol(AST_SymbolVar, process),
|
||||||
|
}),
|
||||||
|
value: make_node(AST_Array, call, { elements: call.args.slice() }),
|
||||||
|
}) ],
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
var values = call.args.slice();
|
||||||
|
fn.argnames.forEach(function(argname) {
|
||||||
|
var value = values.shift();
|
||||||
|
if (argname.unused) {
|
||||||
|
if (value) body.push(make_node(AST_SimpleStatement, call, { body: value }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
body.push(make_node(AST_Var, call, {
|
||||||
|
definitions: [ make_node(AST_VarDef, call, {
|
||||||
|
name: argname.convert_symbol(AST_SymbolVar, process),
|
||||||
|
value: value || make_node(AST_Undefined, call).optimize(compressor),
|
||||||
|
}) ],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
if (values.length) body.push(make_node(AST_SimpleStatement, call, {
|
||||||
|
body: make_sequence(call, values),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return make_node(AST_BlockStatement, call, {
|
||||||
|
body: body.concat(fn.body, make_node(AST_Return, call, { value: null })),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
def(AST_New, noop);
|
||||||
|
def(AST_Sequence, function(compressor, scope) {
|
||||||
|
var inlined = this.tail_node().try_inline(compressor, scope);
|
||||||
|
if (inlined) return make_node(AST_BlockStatement, this, {
|
||||||
|
body: [
|
||||||
|
make_node(AST_SimpleStatement, this, {
|
||||||
|
body: make_sequence(this, this.expressions.slice(0, -1)),
|
||||||
|
}),
|
||||||
|
inlined,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
def(AST_UnaryPrefix, function(compressor, scope) {
|
||||||
|
var self = this;
|
||||||
|
var op = self.operator;
|
||||||
|
if (unary_side_effects[op]) return;
|
||||||
|
var inlined = self.expression.try_inline(compressor, scope);
|
||||||
|
if (!inlined) return;
|
||||||
|
scan_local_returns(inlined, function(node) {
|
||||||
|
var value = node.value;
|
||||||
|
if (op == "void") {
|
||||||
|
if (!value) return;
|
||||||
|
if (is_undefined(value)) return;
|
||||||
|
}
|
||||||
|
node.value = make_node(AST_UnaryPrefix, self, {
|
||||||
|
operator: op,
|
||||||
|
expression: value || make_node(AST_Undefined, node),
|
||||||
|
}).optimize(compressor);
|
||||||
|
});
|
||||||
|
return inlined;
|
||||||
|
})
|
||||||
|
})(function(node, func) {
|
||||||
|
node.DEFMETHOD("try_inline", func);
|
||||||
|
});
|
||||||
|
|
||||||
OPT(AST_Return, function(self, compressor) {
|
OPT(AST_Return, function(self, compressor) {
|
||||||
|
var value = self.value;
|
||||||
|
if (!value) return self;
|
||||||
|
var inlined = value.try_inline(compressor);
|
||||||
|
if (inlined) return inlined;
|
||||||
if (compressor.option("side_effects")
|
if (compressor.option("side_effects")
|
||||||
&& self.value
|
&& is_undefined(value, compressor)
|
||||||
&& is_undefined(self.value, compressor)
|
|
||||||
&& !in_async_generator(compressor.find_parent(AST_Scope))) {
|
&& !in_async_generator(compressor.find_parent(AST_Scope))) {
|
||||||
self.value = null;
|
self.value = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,34 @@ dont_inline: {
|
|||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dont_inline_nested: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function await() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
(async function() {
|
||||||
|
(function() {
|
||||||
|
console.log(await("FAIL"));
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function await() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
(async function() {
|
||||||
|
(function() {
|
||||||
|
console.log(await("FAIL"));
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
inline_await_1: {
|
inline_await_1: {
|
||||||
options = {
|
options = {
|
||||||
awaits: true,
|
awaits: true,
|
||||||
|
|||||||
@@ -1310,6 +1310,7 @@ issue_4725_1: {
|
|||||||
|
|
||||||
issue_4725_2: {
|
issue_4725_2: {
|
||||||
options = {
|
options = {
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -3731,6 +3731,7 @@ issue_2437_1: {
|
|||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
@@ -3783,6 +3784,7 @@ issue_2437_2: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
|
negate_iife: true,
|
||||||
passes: 3,
|
passes: 3,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -9374,9 +9376,8 @@ inline_throw: {
|
|||||||
expect: {
|
expect: {
|
||||||
try {
|
try {
|
||||||
(function(a) {
|
(function(a) {
|
||||||
return function() {
|
throw a;
|
||||||
throw a;
|
return;
|
||||||
}();
|
|
||||||
})("PASS");
|
})("PASS");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|||||||
@@ -1219,9 +1219,9 @@ issue_4248: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_4261: {
|
issue_4261_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
@@ -1259,6 +1259,45 @@ issue_4261: {
|
|||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4261_2: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
{
|
||||||
|
const a = 42;
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
while (f());
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
while (g());
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
{
|
||||||
|
const a = 42;
|
||||||
|
(function() {
|
||||||
|
function g() {
|
||||||
|
while (void console.log(a));
|
||||||
|
}
|
||||||
|
while (g());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4274_1: {
|
issue_4274_1: {
|
||||||
options = {
|
options = {
|
||||||
loops: true,
|
loops: true,
|
||||||
|
|||||||
@@ -1866,7 +1866,7 @@ issue_5057_2: {
|
|||||||
|
|
||||||
issue_5057_3: {
|
issue_5057_3: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -1889,6 +1889,31 @@ issue_5057_3: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5057_4: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
(function f(b) {
|
||||||
|
(function(a = console.log("FAIL 1")) {})(b);
|
||||||
|
console.log(a);
|
||||||
|
})("FAIL 2");
|
||||||
|
})("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
var b = "FAIL 2";
|
||||||
|
(function(a = console.log("FAIL 1")) {})(b);
|
||||||
|
console.log(a);
|
||||||
|
})("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
issue_5065: {
|
issue_5065: {
|
||||||
options = {
|
options = {
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
|
|||||||
@@ -2069,7 +2069,7 @@ issue_4319: {
|
|||||||
|
|
||||||
issue_4321: {
|
issue_4321: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -679,6 +679,26 @@ inline_loop_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline_negate_iife: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return !function() {
|
||||||
|
while (!console);
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
while (!console);
|
||||||
|
return !void 0;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2476: {
|
issue_2476: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -1029,7 +1049,7 @@ issue_2616: {
|
|||||||
|
|
||||||
issue_2620_1: {
|
issue_2620_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1063,6 +1083,42 @@ issue_2620_1: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
issue_2620_2: {
|
issue_2620_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
function f(a) {
|
||||||
|
var b = function g(a) {
|
||||||
|
a && a();
|
||||||
|
}();
|
||||||
|
if (a) {
|
||||||
|
var d = c = "PASS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(1);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var a = 1;
|
||||||
|
if (function(a) {
|
||||||
|
a && a();
|
||||||
|
}(), a) c = "PASS";
|
||||||
|
})(),
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2620_3: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1096,10 +1152,10 @@ issue_2620_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2620_3: {
|
issue_2620_4: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -1139,7 +1195,50 @@ issue_2620_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2620_4: {
|
issue_2620_5: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
function f(a, NaN) {
|
||||||
|
function g() {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
break;
|
||||||
|
case c = "PASS", NaN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f(0/0);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var a = 0/0;
|
||||||
|
var NaN = void 0;
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
break;
|
||||||
|
case c = "PASS", NaN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2620_6: {
|
||||||
rename = true
|
rename = true
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -1636,6 +1735,28 @@ duplicate_argnames_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
duplicate_argnames_4: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
(function(a, a) {
|
||||||
|
while (console.log(a || "PASS"));
|
||||||
|
})("FAIL");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var a = "FAIL";
|
||||||
|
var a = void 0;
|
||||||
|
while (console.log(a || "PASS"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
loop_init_arg: {
|
loop_init_arg: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -2885,6 +3006,7 @@ issue_2437: {
|
|||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
functions: true,
|
functions: true,
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
@@ -3310,7 +3432,28 @@ issue_3402: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3439: {
|
issue_3439_1: {
|
||||||
|
options = {
|
||||||
|
inline: 3,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
return function(a) {
|
||||||
|
function a() {}
|
||||||
|
return a;
|
||||||
|
}(42);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function(a) {
|
||||||
|
function a() {}
|
||||||
|
return a;
|
||||||
|
}(42));
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3439_2: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
}
|
}
|
||||||
@@ -3390,7 +3533,7 @@ issue_3506_2: {
|
|||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: 3,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -3419,9 +3562,40 @@ issue_3506_2: {
|
|||||||
issue_3506_3: {
|
issue_3506_3: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
dead_code: true,
|
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
(function(c) {
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
})(b);
|
||||||
|
})(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
var c = a;
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3506_4: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: 3,
|
||||||
loops: true,
|
loops: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -3448,6 +3622,39 @@ issue_3506_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3506_5: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
(function(c) {
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
})(b);
|
||||||
|
})(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
var c = a;
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3512: {
|
issue_3512: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -3595,6 +3802,45 @@ hoisted_single_use: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inlined_single_use: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(f) {
|
||||||
|
f();
|
||||||
|
}(function() {
|
||||||
|
var a = function() {
|
||||||
|
A;
|
||||||
|
};
|
||||||
|
var b = function() {
|
||||||
|
a(B);
|
||||||
|
};
|
||||||
|
(function() {
|
||||||
|
b;
|
||||||
|
});
|
||||||
|
var c = 42;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(f) {
|
||||||
|
var a = function() {
|
||||||
|
A;
|
||||||
|
};
|
||||||
|
var b = function() {
|
||||||
|
a(B);
|
||||||
|
};
|
||||||
|
(function() {
|
||||||
|
b;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
pr_3592_1: {
|
pr_3592_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -4286,9 +4532,9 @@ substitute: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
substitute_add_farg: {
|
substitute_add_farg_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -4323,6 +4569,46 @@ substitute_add_farg: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
substitute_add_farg_2: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(g) {
|
||||||
|
console.log(g.length);
|
||||||
|
g(null, "FAIL");
|
||||||
|
}
|
||||||
|
f(function() {
|
||||||
|
return function(a, b) {
|
||||||
|
return function(c) {
|
||||||
|
do {
|
||||||
|
console.log("PASS");
|
||||||
|
} while (c);
|
||||||
|
}(a, b);
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(g) {
|
||||||
|
console.log(g.length);
|
||||||
|
g(null, "FAIL");
|
||||||
|
}
|
||||||
|
f(function(a, b) {
|
||||||
|
var c = a;
|
||||||
|
do {
|
||||||
|
console.log("PASS");
|
||||||
|
} while (c);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"2",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
substitute_arguments: {
|
substitute_arguments: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -4652,9 +4938,9 @@ substitute_use_strict: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3833: {
|
issue_3833_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
@@ -4679,6 +4965,33 @@ issue_3833: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3833_2: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return function() {
|
||||||
|
while (a);
|
||||||
|
console.log("PASS");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
while (a);
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3835: {
|
issue_3835: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -4699,9 +5012,9 @@ issue_3835: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3836: {
|
issue_3836_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: 3,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
(function() {
|
(function() {
|
||||||
@@ -4720,6 +5033,29 @@ issue_3836: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3836_2: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
for (var a in 0)
|
||||||
|
console.log(k);
|
||||||
|
}(console.log("PASS"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
for (var a in 0)
|
||||||
|
console.log(k);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3852: {
|
issue_3852: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -5208,6 +5544,7 @@ issue_4259: {
|
|||||||
|
|
||||||
issue_4261: {
|
issue_4261: {
|
||||||
options = {
|
options = {
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -5237,15 +5574,15 @@ issue_4261: {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
(function() {
|
(function() {
|
||||||
function g() {
|
function g() {
|
||||||
|
// `ReferenceError: e is not defined` on Node.js v0.10
|
||||||
while (void e.p);
|
while (void e.p);
|
||||||
}
|
}
|
||||||
(function() {
|
while (console.log(g()));
|
||||||
while (console.log(g()));
|
|
||||||
})();
|
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: "undefined"
|
||||||
|
node_version: "<0.10 || >=0.12"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_4265: {
|
issue_4265: {
|
||||||
@@ -5500,6 +5837,7 @@ issue_4655: {
|
|||||||
|
|
||||||
issue_4659_1: {
|
issue_4659_1: {
|
||||||
options = {
|
options = {
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
@@ -5524,11 +5862,9 @@ issue_4659_1: {
|
|||||||
function f() {
|
function f() {
|
||||||
return a++;
|
return a++;
|
||||||
}
|
}
|
||||||
|
f && a++;
|
||||||
(function() {
|
(function() {
|
||||||
f && a++;
|
var a = console && a;
|
||||||
(function() {
|
|
||||||
var a = console && a;
|
|
||||||
})();
|
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
console.log(a);
|
console.log(a);
|
||||||
@@ -5538,6 +5874,7 @@ issue_4659_1: {
|
|||||||
|
|
||||||
issue_4659_2: {
|
issue_4659_2: {
|
||||||
options = {
|
options = {
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
}
|
}
|
||||||
@@ -5564,11 +5901,9 @@ issue_4659_2: {
|
|||||||
function f() {
|
function f() {
|
||||||
return a++;
|
return a++;
|
||||||
}
|
}
|
||||||
|
void (f && a++);
|
||||||
(function() {
|
(function() {
|
||||||
void (f && a++);
|
var a = console && a;
|
||||||
(function() {
|
|
||||||
var a = console && a;
|
|
||||||
})();
|
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
console.log(a);
|
console.log(a);
|
||||||
@@ -5578,6 +5913,7 @@ issue_4659_2: {
|
|||||||
|
|
||||||
issue_4659_3: {
|
issue_4659_3: {
|
||||||
options = {
|
options = {
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -5607,12 +5943,10 @@ issue_4659_3: {
|
|||||||
return a++;
|
return a++;
|
||||||
}
|
}
|
||||||
(function() {
|
(function() {
|
||||||
(function() {
|
while (!console);
|
||||||
while (!console);
|
})(f && a++);
|
||||||
})(f && a++);
|
(function() {
|
||||||
(function() {
|
var a = console && a;
|
||||||
var a = console && a;
|
|
||||||
})();
|
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
console.log(a);
|
console.log(a);
|
||||||
@@ -5787,6 +6121,7 @@ issue_4725_1: {
|
|||||||
|
|
||||||
issue_4725_2: {
|
issue_4725_2: {
|
||||||
options = {
|
options = {
|
||||||
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -545,7 +545,36 @@ if_body_return_3: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3600: {
|
issue_3600_1: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: 3,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
if ([ ][c++]); else return;
|
||||||
|
return void function() {
|
||||||
|
var b = --b, a = c = 42;
|
||||||
|
return c;
|
||||||
|
}();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
if ([][c++]) b = --b, c = 42;
|
||||||
|
var b;
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3600_2: {
|
||||||
options = {
|
options = {
|
||||||
if_return: true,
|
if_return: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -566,8 +595,10 @@ issue_3600: {
|
|||||||
expect: {
|
expect: {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
(function() {
|
(function() {
|
||||||
if ([][c++]) b = --b, c = 42;
|
if ([][c++]) {
|
||||||
var b;
|
var b = --b;
|
||||||
|
c = 42;
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1217,6 +1217,7 @@ issues_3267_1: {
|
|||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
|
negate_iife: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
|||||||
@@ -6671,6 +6671,7 @@ issues_3267_1: {
|
|||||||
dead_code: true,
|
dead_code: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
negate_iife: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -6688,7 +6689,7 @@ issues_3267_1: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(i) {
|
!function(x) {
|
||||||
if (Object())
|
if (Object())
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
@@ -6705,6 +6706,7 @@ issues_3267_2: {
|
|||||||
evaluate: true,
|
evaluate: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
|
negate_iife: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ dont_inline: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
do_inline: {
|
do_inline_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
spreads: true,
|
spreads: true,
|
||||||
@@ -164,6 +164,48 @@ do_inline: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_inline_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})(..."");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[] = [ ..."" ],
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_inline_3: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
while (console.log("PASS"));
|
||||||
|
})(..."");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var [] = [ ..."" ];
|
||||||
|
while (console.log("PASS"));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
drop_empty_call_1: {
|
drop_empty_call_1: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
|||||||
@@ -784,6 +784,30 @@ inline_nested_yield: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dont_inline_nested: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var yield = "PASS";
|
||||||
|
(function*() {
|
||||||
|
(function() {
|
||||||
|
console.log(yield);
|
||||||
|
})();
|
||||||
|
})().next();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var yield = "PASS";
|
||||||
|
(function*() {
|
||||||
|
(function() {
|
||||||
|
console.log(yield);
|
||||||
|
})();
|
||||||
|
})().next();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
drop_body: {
|
drop_body: {
|
||||||
options = {
|
options = {
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user