From af0262b7e5fd3dbf83619cdb375ab18c41def3e7 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 3 Jul 2017 04:17:37 +0800 Subject: [PATCH] improve parenthesis emission (#2196) - eliminate `throw` usages - suppress extraneous parenthesis - `new function() {foo.bar()}.baz` - `for (function() { "foo" in bar; };;);` --- lib/compress.js | 2 +- lib/output.js | 41 +++++++++++++++++++------------------- test/compress/loops.js | 14 +++++++++++++ test/compress/new.js | 16 +++++++++++++++ test/compress/sequences.js | 9 +++++++++ 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index db45c56b..f0aedf57 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1201,7 +1201,7 @@ merge(Compressor.prototype, { if (stat instanceof AST_For && !(stat.init instanceof AST_Definitions)) { var abort = false; prev.body.walk(new TreeWalker(function(node) { - if (abort) return true; + if (abort || node instanceof AST_Scope) return true; if (node instanceof AST_Binary && node.operator == "in") { abort = true; return true; diff --git a/lib/output.js b/lib/output.js index 92c72484..9416583a 100644 --- a/lib/output.js +++ b/lib/output.js @@ -672,14 +672,15 @@ function OutputStream(options) { // parens around it too, otherwise the call will be // interpreted as passing the arguments to the upper New // expression. - try { - this.walk(new TreeWalker(function(node){ - if (node instanceof AST_Call) throw p; - })); - } catch(ex) { - if (ex !== p) throw ex; - return true; - } + var parens = false; + this.walk(new TreeWalker(function(node) { + if (parens || node instanceof AST_Scope) return true; + if (node instanceof AST_Call) { + parens = true; + return true; + } + })); + return parens; } }); @@ -1073,19 +1074,17 @@ function OutputStream(options) { }); function parenthesize_for_noin(node, output, noin) { - if (!noin) node.print(output); - else try { - // need to take some precautions here: - // https://github.com/mishoo/UglifyJS2/issues/60 - node.walk(new TreeWalker(function(node){ - if (node instanceof AST_Binary && node.operator == "in") - throw output; - })); - node.print(output); - } catch(ex) { - if (ex !== output) throw ex; - node.print(output, true); - } + var parens = false; + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + if (noin) node.walk(new TreeWalker(function(node) { + if (parens || node instanceof AST_Scope) return true; + if (node instanceof AST_Binary && node.operator == "in") { + parens = true; + return true; + } + })); + node.print(output, parens); }; DEFPRINT(AST_VarDef, function(self, output){ diff --git a/test/compress/loops.js b/test/compress/loops.js index 89c7e7e9..bac40494 100644 --- a/test/compress/loops.js +++ b/test/compress/loops.js @@ -436,3 +436,17 @@ do_switch: { } while (false); } } + +in_parenthesis_1: { + input: { + for (("foo" in {});0;); + } + expect_exact: 'for(("foo"in{});0;);' +} + +in_parenthesis_2: { + input: { + for ((function(){ "foo" in {}; });0;); + } + expect_exact: 'for(function(){"foo"in{}};0;);' +} diff --git a/test/compress/new.js b/test/compress/new.js index 83da88e6..640f201a 100644 --- a/test/compress/new.js +++ b/test/compress/new.js @@ -82,3 +82,19 @@ new_with_unary_prefix: { } expect_exact: 'var bar=(+new Date).toString(32);'; } + +dot_parenthesis_1: { + input: { + console.log(new (Math.random().constructor) instanceof Number); + } + expect_exact: "console.log(new(Math.random().constructor)instanceof Number);" + expect_stdout: "true" +} + +dot_parenthesis_2: { + input: { + console.log(typeof new function(){Math.random()}.constructor); + } + expect_exact: "console.log(typeof new function(){Math.random()}.constructor);" + expect_stdout: "function" +} diff --git a/test/compress/sequences.js b/test/compress/sequences.js index f41b603f..5ce24ac0 100644 --- a/test/compress/sequences.js +++ b/test/compress/sequences.js @@ -176,6 +176,11 @@ for_sequences: { // 4 x = (foo in bar); for (y = 5; false;); + // 5 + x = function() { + foo in bar; + }; + for (y = 5; false;); } expect: { // 1 @@ -188,6 +193,10 @@ for_sequences: { // 4 x = (foo in bar); for (y = 5; false;); + // 5 + for (x = function() { + foo in bar; + }, y = 5; false;); } } -- 2.34.1