aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js120
-rw-r--r--test/compress/if_return.js2
-rw-r--r--test/compress/issue-1052.js24
3 files changed, 86 insertions, 60 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 6359696b..374d14d4 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -924,6 +924,45 @@ merge(Compressor.prototype, {
// step. nevertheless, it's good to check.
continue loop;
case stat instanceof AST_If:
+ var ab = aborts(stat.body);
+ if (can_merge_flow(ab)) {
+ if (ab.label) {
+ remove(ab.label.thedef.references, ab);
+ }
+ CHANGED = true;
+ var funs = extract_functions_from_statement_array(ret);
+ var body = as_statement_array_with_return(stat.body, ab);
+ stat = stat.clone();
+ stat.condition = stat.condition.negate(compressor);
+ stat.body = make_node(AST_BlockStatement, stat, {
+ body: as_statement_array(stat.alternative).concat(ret)
+ });
+ stat.alternative = make_node(AST_BlockStatement, stat, {
+ body: body
+ });
+ ret = [ stat.transform(compressor) ].concat(funs);
+ continue loop;
+ }
+
+ var ab = aborts(stat.alternative);
+ if (can_merge_flow(ab)) {
+ if (ab.label) {
+ remove(ab.label.thedef.references, ab);
+ }
+ CHANGED = true;
+ var funs = extract_functions_from_statement_array(ret);
+ stat = stat.clone();
+ stat.body = make_node(AST_BlockStatement, stat.body, {
+ body: as_statement_array(stat.body).concat(ret)
+ });
+ var body = as_statement_array_with_return(stat.alternative, ab);
+ stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
+ body: body
+ });
+ ret = [ stat.transform(compressor) ].concat(funs);
+ continue loop;
+ }
+
if (stat.body instanceof AST_Return) {
var value = stat.body.value;
//---
@@ -960,23 +999,6 @@ merge(Compressor.prototype, {
continue loop;
}
//---
- // if (foo()) return [ void bar() ]; [ else x...; ] y... ==> if (!foo()) { x...; y... } else bar();
- if (in_lambda && (!value || value instanceof AST_UnaryPrefix && value.operator == "void")) {
- CHANGED = true;
- stat = stat.clone();
- stat.condition = stat.condition.negate(compressor);
- var funs = extract_functions_from_statement_array(ret);
- var body = as_statement_array(stat.alternative).concat(ret);
- stat.body = make_node(AST_BlockStatement, stat, {
- body: body
- });
- stat.alternative = value ? make_node(AST_SimpleStatement, value, {
- body: value.expression
- }) : null;
- ret = [ stat.transform(compressor) ].concat(funs);
- continue loop;
- }
- //---
// if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
//
// if sequences is not enabled, this can lead to an endless loop (issue #866).
@@ -995,48 +1017,6 @@ merge(Compressor.prototype, {
}
}
- var ab = aborts(stat.body);
- var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
- if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
- || (ab instanceof AST_Continue && self === loop_body(lct))
- || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
- if (ab.label) {
- remove(ab.label.thedef.references, ab);
- }
- CHANGED = true;
- var body = as_statement_array(stat.body).slice(0, -1);
- stat = stat.clone();
- stat.condition = stat.condition.negate(compressor);
- stat.body = make_node(AST_BlockStatement, stat, {
- body: as_statement_array(stat.alternative).concat(ret)
- });
- stat.alternative = make_node(AST_BlockStatement, stat, {
- body: body
- });
- ret = [ stat.transform(compressor) ];
- continue loop;
- }
-
- var ab = aborts(stat.alternative);
- var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
- if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
- || (ab instanceof AST_Continue && self === loop_body(lct))
- || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
- if (ab.label) {
- remove(ab.label.thedef.references, ab);
- }
- CHANGED = true;
- stat = stat.clone();
- stat.body = make_node(AST_BlockStatement, stat.body, {
- body: as_statement_array(stat.body).concat(ret)
- });
- stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
- body: as_statement_array(stat.alternative).slice(0, -1)
- });
- ret = [ stat.transform(compressor) ];
- continue loop;
- }
-
ret.unshift(stat);
break;
default:
@@ -1056,6 +1036,28 @@ merge(Compressor.prototype, {
}
return false;
}
+
+ function is_return_void(value) {
+ return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
+ }
+
+ function can_merge_flow(ab) {
+ if (!ab) return false;
+ var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
+ return ab instanceof AST_Return && in_lambda && is_return_void(ab.value)
+ || ab instanceof AST_Continue && self === loop_body(lct)
+ || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct;
+ }
+
+ function as_statement_array_with_return(node, ab) {
+ var body = as_statement_array(node).slice(0, -1);
+ if (ab.value) {
+ body.push(make_node(AST_SimpleStatement, ab.value, {
+ body: ab.value.expression
+ }));
+ }
+ return body;
+ }
};
function eliminate_dead_code(statements, compressor) {
diff --git a/test/compress/if_return.js b/test/compress/if_return.js
index c09d67b6..72b69e70 100644
--- a/test/compress/if_return.js
+++ b/test/compress/if_return.js
@@ -307,6 +307,8 @@ issue_512: {
options = {
conditionals: true,
if_return: true,
+ sequences: true,
+ side_effects: true,
}
input: {
function a() {
diff --git a/test/compress/issue-1052.js b/test/compress/issue-1052.js
index e3dc7322..30a563fe 100644
--- a/test/compress/issue-1052.js
+++ b/test/compress/issue-1052.js
@@ -136,7 +136,29 @@ defun_hoist_funs: {
function f() {}
function g() {}
function h() {}
- !window;
+ if (window);
+ }
+ }
+}
+
+defun_else_if_return: {
+ options = {
+ hoist_funs: false,
+ if_return: true,
+ }
+ input: {
+ function e() {
+ function f() {}
+ if (window) function g() {}
+ else return;
+ function h() {}
+ }
+ }
+ expect: {
+ function e() {
+ function f() {}
+ if (window) function g() {}
+ function h() {}
}
}
}