enhance join_vars & sequences (#2697)
- nudge declarations without assignments - within `AST_BlockStatement` - across `AST_If`
This commit is contained in:
@@ -884,6 +884,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (compressor.sequences_limit > 0) {
|
if (compressor.sequences_limit > 0) {
|
||||||
sequencesize(statements, compressor);
|
sequencesize(statements, compressor);
|
||||||
|
sequencesize_2(statements, compressor);
|
||||||
}
|
}
|
||||||
if (compressor.option("join_vars")) {
|
if (compressor.option("join_vars")) {
|
||||||
join_consecutive_vars(statements, compressor);
|
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) {
|
function sequencesize(statements, compressor) {
|
||||||
if (statements.length < 2) return;
|
if (statements.length < 2) return;
|
||||||
var seq = [], n = 0;
|
var seq = [], n = 0;
|
||||||
@@ -1553,6 +1560,9 @@ merge(Compressor.prototype, {
|
|||||||
var body = stat.body;
|
var body = stat.body;
|
||||||
if (seq.length > 0) body = body.drop_side_effect_free(compressor);
|
if (seq.length > 0) body = body.drop_side_effect_free(compressor);
|
||||||
if (body) merge_sequence(seq, body);
|
if (body) merge_sequence(seq, body);
|
||||||
|
} else if (stat instanceof AST_Definitions && declarations_only(stat)
|
||||||
|
|| stat instanceof AST_Defun) {
|
||||||
|
statements[n++] = stat;
|
||||||
} else {
|
} else {
|
||||||
push_seq();
|
push_seq();
|
||||||
statements[n++] = stat;
|
statements[n++] = stat;
|
||||||
@@ -1560,13 +1570,31 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
push_seq();
|
push_seq();
|
||||||
statements.length = n;
|
statements.length = n;
|
||||||
sequencesize_2(statements, compressor);
|
if (n != len) CHANGED = true;
|
||||||
CHANGED = statements.length != len;
|
}
|
||||||
|
|
||||||
|
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 sequencesize_2(statements, compressor) {
|
||||||
function cons_seq(right) {
|
function cons_seq(right) {
|
||||||
n--;
|
n--;
|
||||||
|
CHANGED = true;
|
||||||
var left = prev.body;
|
var left = prev.body;
|
||||||
return make_sequence(left, [ left, right ]).transform(compressor);
|
return make_sequence(left, [ left, right ]).transform(compressor);
|
||||||
};
|
};
|
||||||
@@ -1588,6 +1616,7 @@ merge(Compressor.prototype, {
|
|||||||
else {
|
else {
|
||||||
stat.init = prev.body;
|
stat.init = prev.body;
|
||||||
n--;
|
n--;
|
||||||
|
CHANGED = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1607,6 +1636,22 @@ merge(Compressor.prototype, {
|
|||||||
stat.expression = cons_seq(stat.expression);
|
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;
|
statements[n++] = stat;
|
||||||
prev = stat instanceof AST_SimpleStatement ? stat : null;
|
prev = stat instanceof AST_SimpleStatement ? stat : null;
|
||||||
}
|
}
|
||||||
@@ -1614,30 +1659,43 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function join_consecutive_vars(statements, compressor) {
|
function join_consecutive_vars(statements, compressor) {
|
||||||
|
var defs;
|
||||||
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
|
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
|
||||||
var stat = statements[i];
|
var stat = statements[i];
|
||||||
var prev = statements[j];
|
var prev = statements[j];
|
||||||
if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
|
if (stat instanceof AST_Definitions) {
|
||||||
|
if (prev && prev.TYPE == stat.TYPE) {
|
||||||
prev.definitions = prev.definitions.concat(stat.definitions);
|
prev.definitions = prev.definitions.concat(stat.definitions);
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
}
|
} else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) {
|
||||||
else if (stat instanceof AST_For
|
defs.definitions = defs.definitions.concat(stat.definitions);
|
||||||
&& prev instanceof AST_Var
|
|
||||||
&& (!stat.init || stat.init.TYPE == prev.TYPE)) {
|
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
if (stat.init) {
|
|
||||||
stat.init.definitions = prev.definitions.concat(stat.init.definitions);
|
|
||||||
} else {
|
} 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;
|
stat.init = prev;
|
||||||
}
|
|
||||||
statements[j] = stat;
|
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;
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
statements[++j] = stat;
|
statements[++j] = stat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statements.length = j + 1;
|
statements.length = j + 1;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
function extract_declarations_from_unreachable_code(compressor, stat, target) {
|
||||||
|
|||||||
@@ -1203,3 +1203,24 @@ issue_2560: {
|
|||||||
"2",
|
"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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -800,12 +800,12 @@ issue_2601_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = "FAIL";
|
var a = "FAIL";
|
||||||
(function() {
|
(function() {
|
||||||
|
var b;
|
||||||
b = "foo",
|
b = "foo",
|
||||||
function(b) {
|
function(b) {
|
||||||
b && b();
|
b && b();
|
||||||
}(),
|
}(),
|
||||||
b && (a = "PASS");
|
b && (a = "PASS");
|
||||||
var b;
|
|
||||||
})(),
|
})(),
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user