aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-01-04 12:58:40 +0800
committerGitHub <noreply@github.com>2018-01-04 12:58:40 +0800
commit9b58b54e2d7ce4ab2c015611add52c7475de9eab (patch)
tree0c287e5a558a71debcb187ec5f3d33bb2e795763
parentc598a12af956a939587059f0f4753a0631b5b372 (diff)
downloadtracifyjs-9b58b54e2d7ce4ab2c015611add52c7475de9eab.tar.gz
tracifyjs-9b58b54e2d7ce4ab2c015611add52c7475de9eab.zip
extend `inline` (#2714)
- compress `function` with variables within loops - restrict to `AST_Var` for better compatibility with ES6+
-rw-r--r--lib/compress.js57
-rw-r--r--test/compress/functions.js8
2 files changed, 40 insertions, 25 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 300bc61d..85bb0910 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -4109,7 +4109,7 @@ merge(Compressor.prototype, {
stat = null;
for (var i = 0; i < len; i++) {
var line = fn.body[i];
- if (line instanceof AST_Definitions) {
+ if (line instanceof AST_Var) {
if (stat && !all(line.definitions, function(var_def) {
return !var_def.value;
})) {
@@ -4124,7 +4124,7 @@ merge(Compressor.prototype, {
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++) {
var arg = fn.argnames[i];
if (arg.__unused) continue;
@@ -4143,7 +4143,7 @@ merge(Compressor.prototype, {
var len = fn.body.length;
for (var i = 0; i < len; i++) {
var stat = fn.body[i];
- if (!(stat instanceof AST_Definitions)) continue;
+ if (!(stat instanceof AST_Var)) continue;
if (!safe_to_inject) return false;
for (var j = stat.definitions.length; --j >= 0;) {
var name = stat.definitions[j].name;
@@ -4152,6 +4152,7 @@ merge(Compressor.prototype, {
|| scope.var_names()[name.name]) {
return false;
}
+ if (in_loop) in_loop.push(name.definition());
}
}
return true;
@@ -4171,8 +4172,8 @@ merge(Compressor.prototype, {
} while (!(scope instanceof AST_Scope));
var safe_to_inject = !(scope instanceof AST_Toplevel) || compressor.toplevel.vars;
var inline = compressor.option("inline");
- if (!can_inject_vars(catches, !in_loop && inline >= 3 && safe_to_inject)) return false;
- if (!can_inject_args(catches, in_loop, inline >= 2 && safe_to_inject)) return false;
+ if (!can_inject_vars(catches, inline >= 3 && 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);
}
@@ -4181,13 +4182,13 @@ merge(Compressor.prototype, {
scope.var_names()[name.name] = true;
scope.variables.set(name.name, def);
scope.enclosed.push(def);
- decls.push(make_node(AST_VarDef, name, {
+ decls.unshift(make_node(AST_VarDef, name, {
name: name,
value: null
}));
var sym = make_node(AST_SymbolRef, name, name);
def.references.push(sym);
- if (value) expressions.push(make_node(AST_Assign, self, {
+ if (value) expressions.unshift(make_node(AST_Assign, self, {
operator: "=",
left: sym,
right: value
@@ -4195,11 +4196,15 @@ merge(Compressor.prototype, {
}
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 value = self.args[i];
if (name.__unused || scope.var_names()[name.name]) {
- if (value) expressions.push(value);
+ if (value) expressions.unshift(value);
} else {
var symbol = make_node(AST_SymbolVar, name, name);
name.definition().orig.push(symbol);
@@ -4207,30 +4212,38 @@ merge(Compressor.prototype, {
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) {
- for (i = 0, len = fn.body.length; i < len; i++) {
+ function flatten_vars(decls, expressions) {
+ if (in_loop) in_loop.length = 0;
+ for (var i = fn.body.length; --i >= 0;) {
var stat = fn.body[i];
- if (stat instanceof AST_Definitions) {
- stat.definitions.forEach(function(var_def) {
- append_var(decls, expressions, var_def.name, var_def.value);
- });
+ if (!(stat instanceof AST_Var)) continue;
+ for (var j = stat.definitions.length; --j >= 0;) {
+ 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() {
var decls = [];
var expressions = [];
+ flatten_vars(decls, expressions);
flatten_args(decls, expressions);
- flatten_body(decls, expressions);
+ expressions.push(value);
if (decls.length) {
i = scope.body.indexOf(compressor.parent(level - 1)) + 1;
scope.body.splice(i, 0, make_node(AST_Var, fn, {
diff --git a/test/compress/functions.js b/test/compress/functions.js
index b6b68982..ff3baeb2 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -1299,6 +1299,7 @@ issue_2630_2: {
passes: 2,
reduce_vars: true,
sequences: true,
+ side_effects: true,
unused: true,
}
input: {
@@ -1905,6 +1906,7 @@ inline_true: {
use_before_init_in_loop: {
options = {
inline: true,
+ side_effects: true,
toplevel: true,
}
input: {
@@ -1918,9 +1920,9 @@ use_before_init_in_loop: {
}
expect: {
var a = "PASS";
- for (var b = 2; --b >= 0;) (function() {
- var c = (c && (a = "FAIL"), 1);
- })();
+ for (var b = 2; --b >= 0;)
+ c = void 0, c = (c && (a = "FAIL"), 1);
+ var c;
console.log(a);
}
expect_stdout: "PASS"