From: Alex Lam S.L Date: Mon, 5 Oct 2020 00:26:59 +0000 (+0100) Subject: enhance `loops` (#4180) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=813ac3ba9663d4123043aa823da59b6c3387f30f;p=UglifyJS.git enhance `loops` (#4180) --- diff --git a/lib/compress.js b/lib/compress.js index cb8b0caf..4534d9c8 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1180,6 +1180,16 @@ merge(Compressor.prototype, { || node instanceof AST_Undefined; } + function declarations_only(node) { + return all(node.definitions, function(var_def) { + return !var_def.value; + }); + } + + function is_declaration(stat) { + return stat instanceof AST_Defun || stat instanceof AST_Var && declarations_only(stat); + } + function tighten_body(statements, compressor) { var in_loop, in_try, scope; find_loop_scope_try(); @@ -2407,16 +2417,6 @@ merge(Compressor.prototype, { }); } - function declarations_only(node) { - return all(node.definitions, function(var_def) { - return !var_def.value; - }); - } - - 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; @@ -4268,13 +4268,17 @@ merge(Compressor.prototype, { return self; }); + function trim_block(stat) { + switch (stat.body.length) { + case 1: return stat.body[0]; + case 0: return make_node(AST_EmptyStatement, stat); + } + return stat; + } + OPT(AST_BlockStatement, function(self, compressor) { self.body = tighten_body(self.body, compressor); - switch (self.body.length) { - case 1: return self.body[0]; - case 0: return make_node(AST_EmptyStatement, self); - } - return self; + return trim_block(self); }); OPT(AST_Function, function(self, compressor) { @@ -5847,6 +5851,33 @@ merge(Compressor.prototype, { }).optimize(compressor); } } + if (self.body instanceof AST_BlockStatement) { + var body = self.body.body; + for (var i = body.length; --i >= 0;) { + var stat = body[i]; + if (stat instanceof AST_If + && !stat.alternative + && stat.body instanceof AST_Break + && compressor.loopcontrol_target(stat.body) === compressor.self()) { + self.condition = make_node(AST_Binary, self, { + operator: "&&", + left: stat.condition.negate(compressor), + right: self.condition, + }); + body.splice(i, 1); + } else if (stat instanceof AST_SimpleStatement) { + self.condition = make_sequence(self, [ + stat.body, + self.condition, + ]); + body.splice(i, 1); + } else if (!is_declaration(stat)) { + break; + } + } + self.body = trim_block(self.body); + } + if (self.body instanceof AST_EmptyStatement) return make_node(AST_For, self, self).optimize(compressor); if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, { condition: make_sequence(self.condition, [ self.body.body, diff --git a/test/compress/loops.js b/test/compress/loops.js index cbc1166f..b8d351ad 100644 --- a/test/compress/loops.js +++ b/test/compress/loops.js @@ -201,7 +201,7 @@ evaluate: { } } -issue_1532: { +issue_1532_1: { options = { evaluate: true, loops: true, @@ -210,18 +210,56 @@ issue_1532: { function f(x, y) { do { if (x) break; - foo(); + console.log(y); } while (false); } + f(null, "PASS"); + f(42, "FAIL"); } expect: { + function f(x, y) { + for (; !x && (console.log(y), false);); + } + f(null, "PASS"); + f(42, "FAIL"); + } + expect_stdout: "PASS" +} + +issue_1532_2: { + options = { + evaluate: true, + loops: true, + } + input: { function f(x, y) { do { - if (x) break; - foo(); + if (x) { + console.log(x); + break; + } + console.log(y); } while (false); } + f(null, "PASS"); + f(42, "FAIL"); + } + expect: { + function f(x, y) { + do { + if (x) { + console.log(x); + break; + } + } while (console.log(y), false); + } + f(null, "PASS"); + f(42, "FAIL"); } + expect_stdout: [ + "PASS", + "42", + ] } issue_186: {