extend inline (#2714)
- compress `function` with variables within loops - restrict to `AST_Var` for better compatibility with ES6+
This commit is contained in:
@@ -4109,7 +4109,7 @@ merge(Compressor.prototype, {
|
|||||||
stat = null;
|
stat = null;
|
||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
var line = fn.body[i];
|
var line = fn.body[i];
|
||||||
if (line instanceof AST_Definitions) {
|
if (line instanceof AST_Var) {
|
||||||
if (stat && !all(line.definitions, function(var_def) {
|
if (stat && !all(line.definitions, function(var_def) {
|
||||||
return !var_def.value;
|
return !var_def.value;
|
||||||
})) {
|
})) {
|
||||||
@@ -4124,7 +4124,7 @@ merge(Compressor.prototype, {
|
|||||||
return return_value(stat);
|
return return_value(stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
function can_inject_args(catches, defs, safe_to_inject) {
|
function can_inject_args(catches, safe_to_inject) {
|
||||||
for (var i = 0, len = fn.argnames.length; i < len; i++) {
|
for (var i = 0, len = fn.argnames.length; i < len; i++) {
|
||||||
var arg = fn.argnames[i];
|
var arg = fn.argnames[i];
|
||||||
if (arg.__unused) continue;
|
if (arg.__unused) continue;
|
||||||
@@ -4143,7 +4143,7 @@ merge(Compressor.prototype, {
|
|||||||
var len = fn.body.length;
|
var len = fn.body.length;
|
||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
var stat = fn.body[i];
|
var stat = fn.body[i];
|
||||||
if (!(stat instanceof AST_Definitions)) continue;
|
if (!(stat instanceof AST_Var)) continue;
|
||||||
if (!safe_to_inject) return false;
|
if (!safe_to_inject) return false;
|
||||||
for (var j = stat.definitions.length; --j >= 0;) {
|
for (var j = stat.definitions.length; --j >= 0;) {
|
||||||
var name = stat.definitions[j].name;
|
var name = stat.definitions[j].name;
|
||||||
@@ -4152,6 +4152,7 @@ merge(Compressor.prototype, {
|
|||||||
|| scope.var_names()[name.name]) {
|
|| scope.var_names()[name.name]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (in_loop) in_loop.push(name.definition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -4171,8 +4172,8 @@ merge(Compressor.prototype, {
|
|||||||
} while (!(scope instanceof AST_Scope));
|
} while (!(scope instanceof AST_Scope));
|
||||||
var safe_to_inject = !(scope instanceof AST_Toplevel) || compressor.toplevel.vars;
|
var safe_to_inject = !(scope instanceof AST_Toplevel) || compressor.toplevel.vars;
|
||||||
var inline = compressor.option("inline");
|
var inline = compressor.option("inline");
|
||||||
if (!can_inject_vars(catches, !in_loop && inline >= 3 && safe_to_inject)) return false;
|
if (!can_inject_vars(catches, inline >= 3 && safe_to_inject)) return false;
|
||||||
if (!can_inject_args(catches, in_loop, inline >= 2 && safe_to_inject)) return false;
|
if (!can_inject_args(catches, inline >= 2 && safe_to_inject)) return false;
|
||||||
return !in_loop || in_loop.length == 0 || !is_reachable(fn, in_loop);
|
return !in_loop || in_loop.length == 0 || !is_reachable(fn, in_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4181,13 +4182,13 @@ merge(Compressor.prototype, {
|
|||||||
scope.var_names()[name.name] = true;
|
scope.var_names()[name.name] = true;
|
||||||
scope.variables.set(name.name, def);
|
scope.variables.set(name.name, def);
|
||||||
scope.enclosed.push(def);
|
scope.enclosed.push(def);
|
||||||
decls.push(make_node(AST_VarDef, name, {
|
decls.unshift(make_node(AST_VarDef, name, {
|
||||||
name: name,
|
name: name,
|
||||||
value: null
|
value: null
|
||||||
}));
|
}));
|
||||||
var sym = make_node(AST_SymbolRef, name, name);
|
var sym = make_node(AST_SymbolRef, name, name);
|
||||||
def.references.push(sym);
|
def.references.push(sym);
|
||||||
if (value) expressions.push(make_node(AST_Assign, self, {
|
if (value) expressions.unshift(make_node(AST_Assign, self, {
|
||||||
operator: "=",
|
operator: "=",
|
||||||
left: sym,
|
left: sym,
|
||||||
right: value
|
right: value
|
||||||
@@ -4195,11 +4196,15 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function flatten_args(decls, expressions) {
|
function flatten_args(decls, expressions) {
|
||||||
for (var len = fn.argnames.length, i = len; --i >= 0;) {
|
var len = fn.argnames.length;
|
||||||
|
for (var i = self.args.length; --i >= len;) {
|
||||||
|
expressions.unshift(self.args[i]);
|
||||||
|
}
|
||||||
|
for (i = len; --i >= 0;) {
|
||||||
var name = fn.argnames[i];
|
var name = fn.argnames[i];
|
||||||
var value = self.args[i];
|
var value = self.args[i];
|
||||||
if (name.__unused || scope.var_names()[name.name]) {
|
if (name.__unused || scope.var_names()[name.name]) {
|
||||||
if (value) expressions.push(value);
|
if (value) expressions.unshift(value);
|
||||||
} else {
|
} else {
|
||||||
var symbol = make_node(AST_SymbolVar, name, name);
|
var symbol = make_node(AST_SymbolVar, name, name);
|
||||||
name.definition().orig.push(symbol);
|
name.definition().orig.push(symbol);
|
||||||
@@ -4207,30 +4212,38 @@ merge(Compressor.prototype, {
|
|||||||
append_var(decls, expressions, symbol, value);
|
append_var(decls, expressions, symbol, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decls.reverse();
|
|
||||||
expressions.reverse();
|
|
||||||
for (i = len, len = self.args.length; i < len; i++) {
|
|
||||||
expressions.push(self.args[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function flatten_body(decls, expressions) {
|
function flatten_vars(decls, expressions) {
|
||||||
for (i = 0, len = fn.body.length; i < len; i++) {
|
if (in_loop) in_loop.length = 0;
|
||||||
|
for (var i = fn.body.length; --i >= 0;) {
|
||||||
var stat = fn.body[i];
|
var stat = fn.body[i];
|
||||||
if (stat instanceof AST_Definitions) {
|
if (!(stat instanceof AST_Var)) continue;
|
||||||
stat.definitions.forEach(function(var_def) {
|
for (var j = stat.definitions.length; --j >= 0;) {
|
||||||
append_var(decls, expressions, var_def.name, var_def.value);
|
var var_def = stat.definitions[j];
|
||||||
});
|
var name = var_def.name;
|
||||||
|
append_var(decls, expressions, name, var_def.value);
|
||||||
|
if (in_loop) {
|
||||||
|
var def = name.definition();
|
||||||
|
var sym = make_node(AST_SymbolRef, name, name);
|
||||||
|
def.references.push(sym);
|
||||||
|
in_loop.unshift(make_node(AST_Assign, var_def, {
|
||||||
|
operator: "=",
|
||||||
|
left: sym,
|
||||||
|
right: make_node(AST_Undefined, name)
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expressions.push(value);
|
if (in_loop) [].unshift.apply(expressions, in_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
function flatten_fn() {
|
function flatten_fn() {
|
||||||
var decls = [];
|
var decls = [];
|
||||||
var expressions = [];
|
var expressions = [];
|
||||||
|
flatten_vars(decls, expressions);
|
||||||
flatten_args(decls, expressions);
|
flatten_args(decls, expressions);
|
||||||
flatten_body(decls, expressions);
|
expressions.push(value);
|
||||||
if (decls.length) {
|
if (decls.length) {
|
||||||
i = scope.body.indexOf(compressor.parent(level - 1)) + 1;
|
i = scope.body.indexOf(compressor.parent(level - 1)) + 1;
|
||||||
scope.body.splice(i, 0, make_node(AST_Var, fn, {
|
scope.body.splice(i, 0, make_node(AST_Var, fn, {
|
||||||
|
|||||||
@@ -1299,6 +1299,7 @@ issue_2630_2: {
|
|||||||
passes: 2,
|
passes: 2,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -1905,6 +1906,7 @@ inline_true: {
|
|||||||
use_before_init_in_loop: {
|
use_before_init_in_loop: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -1918,9 +1920,9 @@ use_before_init_in_loop: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "PASS";
|
var a = "PASS";
|
||||||
for (var b = 2; --b >= 0;) (function() {
|
for (var b = 2; --b >= 0;)
|
||||||
var c = (c && (a = "FAIL"), 1);
|
c = void 0, c = (c && (a = "FAIL"), 1);
|
||||||
})();
|
var c;
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
|||||||
Reference in New Issue
Block a user