diff --git a/lib/compress.js b/lib/compress.js index 25e46596..ce9953cc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -3452,16 +3452,15 @@ Compressor.prototype.compress = function(node) { var parent = compressor.parent(); var self = compressor.self(); var declare_only, jump, merge_jump; - var in_tail = in_lambda && self instanceof AST_Block && self.body === statements; - var in_iife = in_tail && parent && parent.TYPE == "Call" && parent.expression === self; - var chain_if_returns = in_tail && compressor.option("conditionals") && compressor.option("sequences"); + var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self; + var chain_if_returns = in_lambda && compressor.option("conditionals") && compressor.option("sequences"); var multiple_if_returns = has_multiple_if_returns(statements); for (var i = statements.length; --i >= 0;) { var stat = statements[i]; var j = next_index(i); var next = statements[j]; - if (in_tail && declare_only && !next && stat instanceof AST_Return + if (in_lambda && declare_only && !next && stat instanceof AST_Return && !(self instanceof AST_SwitchBranch) && !(in_try && in_try.bfinally && in_async_generator(in_lambda))) { var body = stat.value; @@ -3486,6 +3485,7 @@ Compressor.prototype.compress = function(node) { if (stat instanceof AST_If) { var ab = aborts(stat.body); + // if (foo()) { bar(); return; } else baz(); moo(); ---> if (foo()) bar(); else { baz(); moo(); } if (can_merge_flow(ab)) { if (ab.label) remove(ab.label.thedef.references, ab); changed = true; @@ -3500,7 +3500,7 @@ Compressor.prototype.compress = function(node) { statements[i] = stat.transform(compressor); continue; } - + // if (foo()) { bar(); return x; } return y; ---> if (!foo()) return y; bar(); return x; if (ab && !stat.alternative && next instanceof AST_Jump) { var cond = stat.condition; var preference = i + 1 == j && stat.body instanceof AST_BlockStatement; @@ -3514,12 +3514,17 @@ Compressor.prototype.compress = function(node) { body: extract_functions(true, null, j + 1), }); statements.splice(i, 1, stat, body); - statements[i] = stat.transform(compressor); + // proceed further only if `TreeWalker.stack` is in a consistent state + // https://github.com/mishoo/UglifyJS/issues/5595 + // https://github.com/mishoo/UglifyJS/issues/5597 + if (!in_lambda || self instanceof AST_Block && self.body === statements) { + statements[i] = stat.transform(compressor); + } continue; } } - var alt = aborts(stat.alternative); + // if (foo()) bar(); else { baz(); return; } moo(); ---> if (foo()) { bar(); moo(); } else baz(); if (can_merge_flow(alt)) { if (alt.label) remove(alt.label.thedef.references, alt); changed = true; @@ -3534,7 +3539,6 @@ Compressor.prototype.compress = function(node) { statements[i] = stat.transform(compressor); continue; } - if (compressor.option("typeofs")) { if (ab && !alt) { var stats = make_node(AST_BlockStatement, self, { body: statements.slice(i + 1) }); @@ -3564,7 +3568,7 @@ Compressor.prototype.compress = function(node) { // if (foo()) return x; [ return ; ] ---> return foo() ? x : undefined; // if (foo()) return bar() ? x : void 0; ---> return foo() && bar() ? x : void 0; // if (foo()) return bar() ? void 0 : x; ---> return !foo() || bar() ? void 0 : x; - if (in_tail && declare_only && !next && !stat.alternative && (in_bool + if (in_lambda && declare_only && !next && !stat.alternative && (in_bool || value && multiple_if_returns || value instanceof AST_Conditional && (is_undefined(value.consequent, compressor) || is_undefined(value.alternative, compressor)))) { @@ -3645,7 +3649,7 @@ Compressor.prototype.compress = function(node) { function can_drop_abort(ab) { if (ab instanceof AST_Exit) { if (merge_jump = match_return(ab)) return true; - if (!in_tail) return false; + if (!in_lambda) return false; if (!(ab instanceof AST_Return)) return false; var value = ab.value; if (value && !is_undefined(value.tail_node())) return false; @@ -3658,7 +3662,7 @@ Compressor.prototype.compress = function(node) { if (!(ab instanceof AST_LoopControl)) return false; if (jump && self instanceof AST_SwitchBranch) { if (jump instanceof AST_Exit) { - if (!in_tail) return false; + if (!in_lambda) return false; if (jump.value) return false; } else if (compressor.loopcontrol_target(jump) !== parent) { return false; diff --git a/test/compress/if_return.js b/test/compress/if_return.js index 40c6f2d8..abe26073 100644 --- a/test/compress/if_return.js +++ b/test/compress/if_return.js @@ -2279,3 +2279,29 @@ issue_5595: { } expect_stdout: "PASS" } + +issue_5597: { + options = { + conditionals: true, + if_return: true, + unused: true, + } + input: { + function f(a) { + if (a) L: { + return; + var b; + } else + return "FAIL"; + } + console.log(f(42) || "PASS"); + } + expect: { + function f(a) { + if (!a) + return "FAIL"; + } + console.log(f(42) || "PASS"); + } + expect_stdout: "PASS" +}