From 1aa38051fbf0bde7071041f6ac37e666aecb4c0a Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 29 May 2017 10:51:41 +0800 Subject: [PATCH] better fix for #512 & #2010 (#2019) - remove duplicated functionalities - fix similar issue with `else` --- lib/compress.js | 120 ++++++++++++++++++------------------ test/compress/if_return.js | 2 + test/compress/issue-1052.js | 24 +++++++- 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() {} } } } -- 2.34.1