aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-01-01 00:09:26 +0800
committerGitHub <noreply@github.com>2018-01-01 00:09:26 +0800
commit673b0716379e261008b6cbf187e6b212104fb69e (patch)
tree5346618caed4b6e09e9f9131b7d1a359ab893fe0
parentda82fa59a723b22ad5d8dec42cd2ca0d070f2359 (diff)
downloadtracifyjs-673b0716379e261008b6cbf187e6b212104fb69e.tar.gz
tracifyjs-673b0716379e261008b6cbf187e6b212104fb69e.zip
enhance `join_vars` & `sequences` (#2697)
- nudge declarations without assignments - within `AST_BlockStatement` - across `AST_If`
-rw-r--r--lib/compress.js90
-rw-r--r--test/compress/conditionals.js21
-rw-r--r--test/compress/functions.js2
-rw-r--r--test/compress/sequences.js63
4 files changed, 159 insertions, 17 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 56176e55..ee80901e 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -884,6 +884,7 @@ merge(Compressor.prototype, {
}
if (compressor.sequences_limit > 0) {
sequencesize(statements, compressor);
+ sequencesize_2(statements, compressor);
}
if (compressor.option("join_vars")) {
join_consecutive_vars(statements, compressor);
@@ -1537,6 +1538,12 @@ merge(Compressor.prototype, {
});
}
+ function declarations_only(node) {
+ return all(node.definitions, function(var_def) {
+ return !var_def.value;
+ });
+ }
+
function sequencesize(statements, compressor) {
if (statements.length < 2) return;
var seq = [], n = 0;
@@ -1553,6 +1560,9 @@ merge(Compressor.prototype, {
var body = stat.body;
if (seq.length > 0) body = body.drop_side_effect_free(compressor);
if (body) merge_sequence(seq, body);
+ } else if (stat instanceof AST_Definitions && declarations_only(stat)
+ || stat instanceof AST_Defun) {
+ statements[n++] = stat;
} else {
push_seq();
statements[n++] = stat;
@@ -1560,13 +1570,31 @@ merge(Compressor.prototype, {
}
push_seq();
statements.length = n;
- sequencesize_2(statements, compressor);
- CHANGED = statements.length != len;
+ if (n != len) CHANGED = true;
+ }
+
+ function to_simple_statement(block, decls) {
+ if (!(block instanceof AST_BlockStatement)) return block;
+ var defs = [];
+ var stat = null;
+ for (var i = 0, len = block.body.length; i < len; i++) {
+ var line = block.body[i];
+ if (line instanceof AST_Definitions && declarations_only(line)) {
+ defs.push(line);
+ } else if (stat) {
+ return false;
+ } else {
+ stat = line;
+ }
+ }
+ [].push.apply(decls, defs);
+ return stat;
}
function sequencesize_2(statements, compressor) {
function cons_seq(right) {
n--;
+ CHANGED = true;
var left = prev.body;
return make_sequence(left, [ left, right ]).transform(compressor);
};
@@ -1588,6 +1616,7 @@ merge(Compressor.prototype, {
else {
stat.init = prev.body;
n--;
+ CHANGED = true;
}
}
}
@@ -1607,6 +1636,22 @@ merge(Compressor.prototype, {
stat.expression = cons_seq(stat.expression);
}
}
+ if (compressor.option("conditionals") && stat instanceof AST_If) {
+ var decls = [];
+ var body = to_simple_statement(stat.body, decls);
+ var alt = to_simple_statement(stat.alternative, decls);
+ if (body !== false && alt !== false && decls.length > 0) {
+ decls.push(make_node(AST_If, stat, {
+ condition: stat.condition,
+ body: body || make_node(AST_EmptyStatement, stat.body),
+ alternative: alt
+ }));
+ stat = make_node(AST_BlockStatement, stat, {
+ body: decls
+ });
+ CHANGED = true;
+ }
+ }
statements[n++] = stat;
prev = stat instanceof AST_SimpleStatement ? stat : null;
}
@@ -1614,30 +1659,43 @@ merge(Compressor.prototype, {
}
function join_consecutive_vars(statements, compressor) {
+ var defs;
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
var stat = statements[i];
var prev = statements[j];
- if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
- prev.definitions = prev.definitions.concat(stat.definitions);
- CHANGED = true;
- }
- else if (stat instanceof AST_For
- && prev instanceof AST_Var
- && (!stat.init || stat.init.TYPE == prev.TYPE)) {
- CHANGED = true;
- if (stat.init) {
- stat.init.definitions = prev.definitions.concat(stat.init.definitions);
+ if (stat instanceof AST_Definitions) {
+ if (prev && prev.TYPE == stat.TYPE) {
+ prev.definitions = prev.definitions.concat(stat.definitions);
+ CHANGED = true;
+ } else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) {
+ defs.definitions = defs.definitions.concat(stat.definitions);
+ CHANGED = true;
} else {
+ statements[++j] = stat;
+ defs = stat;
+ }
+ } else if (stat instanceof AST_For) {
+ if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
+ if (stat.init) {
+ prev.definitions = prev.definitions.concat(stat.init.definitions);
+ }
stat.init = prev;
+ statements[j] = stat;
+ CHANGED = true;
+ } else if (defs && stat.init && defs.TYPE == stat.init.TYPE && declarations_only(stat.init)) {
+ defs.definitions = defs.definitions.concat(stat.init.definitions);
+ stat.init = null;
+ statements[++j] = stat;
+ CHANGED = true;
+ } else {
+ statements[++j] = stat;
}
- statements[j] = stat;
- }
- else {
+ } else {
statements[++j] = stat;
}
}
statements.length = j + 1;
- };
+ }
}
function extract_declarations_from_unreachable_code(compressor, stat, target) {
diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js
index 4d61d39f..7838fdbb 100644
--- a/test/compress/conditionals.js
+++ b/test/compress/conditionals.js
@@ -1203,3 +1203,24 @@ issue_2560: {
"2",
]
}
+
+hoist_decl: {
+ options = {
+ conditionals: true,
+ join_vars: true,
+ sequences: true,
+ }
+ input: {
+ if (x()) {
+ var a;
+ y();
+ } else {
+ z();
+ var b;
+ }
+ }
+ expect: {
+ var a, b;
+ x() ? y() : z();
+ }
+}
diff --git a/test/compress/functions.js b/test/compress/functions.js
index e6c4301c..0e37b78a 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -800,12 +800,12 @@ issue_2601_1: {
expect: {
var a = "FAIL";
(function() {
+ var b;
b = "foo",
function(b) {
b && b();
}(),
b && (a = "PASS");
- var b;
})(),
console.log(a);
}
diff --git a/test/compress/sequences.js b/test/compress/sequences.js
index 81b06881..3d12fb0b 100644
--- a/test/compress/sequences.js
+++ b/test/compress/sequences.js
@@ -796,3 +796,66 @@ cascade_assignment_in_return: {
}
}
}
+
+hoist_defun: {
+ options = {
+ join_vars: true,
+ sequences: true,
+ }
+ input: {
+ x();
+ function f() {}
+ y();
+ }
+ expect: {
+ function f() {}
+ x(), y();
+ }
+}
+
+hoist_decl: {
+ options = {
+ join_vars: true,
+ sequences: true,
+ }
+ input: {
+ var a;
+ w();
+ var b = x();
+ y();
+ for (var c; 0;) z();
+ var d;
+ }
+ expect: {
+ var a;
+ w();
+ var b = x(), c, d;
+ for (y(); 0;) z();
+ }
+}
+
+for_init_var: {
+ options = {
+ join_vars: true,
+ unused: false,
+ }
+ input: {
+ var a = "PASS";
+ (function() {
+ var b = 42;
+ for (var c = 5; c > 0;) c--;
+ a = "FAIL";
+ var a;
+ })();
+ console.log(a);
+ }
+ expect: {
+ var a = "PASS";
+ (function() {
+ for (var b = 42, c = 5, a; c > 0;) c--;
+ a = "FAIL";
+ })();
+ console.log(a);
+ }
+ expect_stdout: "PASS"
+}