From d7456a2dc220112a5fc294b102612c568395d72c Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 10 Sep 2020 15:31:34 +0100 Subject: [PATCH] enhance `if_return` (#4097) --- lib/compress.js | 69 +++++++++++++++++++++++++------------- test/compress/if_return.js | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 24 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index f744ac6a..50a37a68 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2113,18 +2113,22 @@ merge(Compressor.prototype, { eliminate_spurious_blocks(stat.body); [].splice.apply(statements, [i, 1].concat(stat.body)); i += stat.body.length; - } else if (stat instanceof AST_EmptyStatement) { - CHANGED = true; - statements.splice(i, 1); - } else if (stat instanceof AST_Directive) { - if (!member(stat.value, seen_dirs)) { - i++; - seen_dirs.push(stat.value); - } else { + continue; + } + if (stat instanceof AST_Directive) { + if (member(stat.value, seen_dirs)) { CHANGED = true; statements.splice(i, 1); + continue; } - } else i++; + seen_dirs.push(stat.value); + } + if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + statements.splice(i, 1); + continue; + } + i++; } } @@ -2295,12 +2299,32 @@ merge(Compressor.prototype, { return !value || value instanceof AST_UnaryPrefix && value.operator == "void"; } + function is_last_statement(body, stat) { + var index = body.lastIndexOf(stat); + if (index < 0) return false; + while (++index < body.length) { + if (!is_declaration(body[index])) return false; + } + return true; + } + + function match_target(target) { + var block = self, stat, level = 0; + do { + do { + if (block === target) return true; + block = compressor.parent(level++); + } while (block instanceof AST_If && (stat = block)); + } while (block instanceof AST_BlockStatement && is_last_statement(block.body, stat)); + } + 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; + if (ab instanceof AST_Return) return in_lambda && is_return_void(ab.value); + if (!(ab instanceof AST_LoopControl)) return false; + var lct = compressor.loopcontrol_target(ab); + if (ab instanceof AST_Continue) return match_target(loop_body(lct)); + if (lct instanceof AST_IterationStatement) return false; + return match_target(lct); } function extract_functions() { @@ -2327,20 +2351,14 @@ merge(Compressor.prototype, { function next_index(i) { for (var j = i + 1; j < statements.length; j++) { - var stat = statements[j]; - if (!(stat instanceof AST_Var && declarations_only(stat))) { - break; - } + if (!is_declaration(statements[j])) break; } return j; } function prev_index(i) { for (var j = i; --j >= 0;) { - var stat = statements[j]; - if (!(stat instanceof AST_Var && declarations_only(stat))) { - break; - } + if (!is_declaration(statements[j])) break; } return j; } @@ -2383,6 +2401,10 @@ merge(Compressor.prototype, { }); } + function is_declaration(stat) { + return stat instanceof AST_Defun || stat instanceof AST_Var && declarations_only(stat); + } + function sequencesize(statements, compressor) { if (statements.length < 2) return; var seq = [], n = 0; @@ -2399,8 +2421,7 @@ 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) { + } else if (is_declaration(stat)) { statements[n++] = stat; } else { push_seq(); diff --git a/test/compress/if_return.js b/test/compress/if_return.js index 836fab17..90ae1210 100644 --- a/test/compress/if_return.js +++ b/test/compress/if_return.js @@ -594,3 +594,72 @@ iife_if_return_simple: { } expect_stdout: "PASS" } + +nested_if_break: { + options = { + if_return: true, + } + input: { + for (var i = 0; i < 3; i++) + L1: if ("number" == typeof i) { + if (0 === i) break L1; + console.log(i); + } + } + expect: { + for (var i = 0; i < 3; i++) + L1: if ("number" == typeof i) + if (0 !== i) console.log(i); + } + expect_stdout: [ + "1", + "2", + ] +} + +nested_if_continue: { + options = { + conditionals: true, + if_return: true, + join_vars: true, + loops: true, + } + input: { + function f(n) { + var i = 0; + do { + if ("number" == typeof n) { + if (0 === n) { + console.log("even", i); + continue; + } + if (1 === n) { + console.log("odd", i); + continue; + } + i++; + } + } while (0 <= (n -= 2)); + } + f(37); + f(42); + } + expect: { + function f(n) { + for (var i = 0; + "number" == typeof n + && (0 !== n + ? 1 !== n + ? i++ + : console.log("odd", i) + : console.log("even", i)), + 0 <= (n -= 2);); + } + f(37); + f(42); + } + expect_stdout: [ + "odd 18", + "even 21", + ] +} -- 2.34.1