From d7eb80b050b9d8c9d4c5067b537d80c6f2a03167 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 30 Jan 2022 22:32:25 +0000 Subject: [PATCH] enhance `if_return` (#5326) --- lib/compress.js | 41 +++++++++++++++++++++++++++----- test/compress/if_return.js | 48 +++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 3abe5ffb..e5e65022 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -3295,6 +3295,7 @@ Compressor.prototype.compress = function(node) { var changed = false; var parent = compressor.parent(); var in_iife = in_lambda && parent && parent.TYPE == "Call"; + 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]; @@ -3421,20 +3422,27 @@ Compressor.prototype.compress = function(node) { // if sequences is not enabled, this can lead to an endless loop (issue #866). // however, with sequences on this helps producing slightly better output for // the example code. - var prev = statements[prev_index(i)]; - if (compressor.option("sequences") && in_lambda && !stat.alternative - && (!prev && in_iife || prev instanceof AST_If && prev.body instanceof AST_Return) + var prev, prev_stat; + if (chain_if_returns && !stat.alternative + && (!(prev_stat = statements[prev = prev_index(i)]) && in_iife + || prev_stat instanceof AST_If && prev_stat.body instanceof AST_Return) && next_index(j) == statements.length && next instanceof AST_SimpleStatement) { changed = true; + var exprs = []; + var args = prev_stat ? trim_defns(prev, exprs) : [ i, 1 ]; stat = stat.clone(); + exprs.push(stat.condition); + stat.condition = make_sequence(stat, exprs); stat.alternative = make_node(AST_BlockStatement, next, { body: [ next, make_node(AST_Return, next, { value: null }), ], }); - statements.splice(i, 1, stat.transform(compressor)); + args.push(stat.transform(compressor)); statements.splice(j, 1); + [].splice.apply(statements, args); + i = prev + 1; continue; } } @@ -3519,10 +3527,31 @@ Compressor.prototype.compress = function(node) { function prev_index(i) { for (var j = i; --j >= 0;) { - if (!is_declaration(statements[j])) break; + if (!(statements[j] instanceof AST_Var)) break; } return j; } + + function trim_defns(j, exprs) { + var args = [ j + 1, i - j ]; + var var_defs = []; + while (++j < i) { + var stat = statements[j]; + stat.remove_initializers(compressor, var_defs); + stat.definitions.forEach(function(var_def) { + if (!var_def.value) return; + exprs.push(make_node(AST_Assign, var_def, { + operator: "=", + left: var_def.name.convert_symbol(AST_SymbolRef, function(ref) { + ref.definition().references.push(ref); + }), + right: var_def.value, + })); + }); + } + if (var_defs.length > 0) args.push(make_node(AST_Var, stat, { definitions: var_defs })); + return args; + } } function eliminate_dead_code(statements, compressor) { @@ -9223,7 +9252,7 @@ Compressor.prototype.compress = function(node) { left: var_def.name.convert_symbol(AST_SymbolRef, function(ref) { refs.push(ref); }), - right: var_def.value + right: var_def.value, })); } } diff --git a/test/compress/if_return.js b/test/compress/if_return.js index 2d139698..ac86cf80 100644 --- a/test/compress/if_return.js +++ b/test/compress/if_return.js @@ -327,7 +327,7 @@ issue_512: { } } -if_var_return: { +if_var_return_1: { options = { conditionals: true, if_return: true, @@ -373,6 +373,52 @@ if_var_return: { } } +if_var_return_2: { + options = { + conditionals: true, + if_return: true, + sequences: true, + } + input: { + (function() { + var a = w(); + if (x()) + return y(); + z(); + })(); + } + expect: { + (function() { + var a = w(); + return x() ? y() : (z(), void 0); + })(); + } +} + +if_var_return_3: { + options = { + conditionals: true, + if_return: true, + sequences: true, + } + input: { + function f() { + if (u()) + return v(); + var a = w(); + if (x()) + return y(); + z(); + } + } + expect: { + function f() { + return u() ? v() : (a = w(), x() ? y() : (z(), void 0)); + var a; + } + } +} + if_if_return_return: { options = { conditionals: true,