From a7e15fe73cb8d78e7590f2d11bf18bbfe41061ea Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 25 Aug 2020 12:45:37 +0100 Subject: [PATCH] streamline parenthesis logic (#4072) --- lib/output.js | 100 +++++++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 59 deletions(-) diff --git a/lib/output.js b/lib/output.js index cf05e261..c2fc964a 100644 --- a/lib/output.js +++ b/lib/output.js @@ -682,78 +682,66 @@ function OutputStream(options) { PARENS(AST_Unary, function(output) { var p = output.parent(); - return p instanceof AST_PropAccess && p.expression === this - || p instanceof AST_Call && p.expression === this; + return (p instanceof AST_Call || p instanceof AST_PropAccess) && p.expression === this; }); PARENS(AST_Sequence, function(output) { var p = output.parent(); - // (foo, bar)() or foo(1, (2, 3), 4) - return p instanceof AST_Call - // !(foo, bar, baz) - || p instanceof AST_Unary + // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + return p instanceof AST_Array // 1 + (2, 3) + 4 ==> 8 || p instanceof AST_Binary - // var a = (1, 2), b = a + a; ==> b == 4 - || p instanceof AST_VarDef - // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 - || p instanceof AST_PropAccess && p.expression === this - // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] - || p instanceof AST_Array - // { foo: (1, 2) }.foo ==> 2 - || p instanceof AST_ObjectProperty + // new (foo, bar) or foo(1, (2, 3), 4) + || p instanceof AST_Call // (false, true) ? (a = 10, b = 20) : (c = 30) // ==> 20 (side effect, set a := 10 and b := 20) - || p instanceof AST_Conditional; + || p instanceof AST_Conditional + // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_ObjectProperty + // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 + || p instanceof AST_PropAccess && p.expression === this + // !(foo, bar, baz) + || p instanceof AST_Unary + // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_VarDef; }); PARENS(AST_Binary, function(output) { var p = output.parent(); - // (foo && bar)() - if (p instanceof AST_Call && p.expression === this) - return true; - // typeof (foo && bar) - if (p instanceof AST_Unary) - return true; - // (foo && bar)["prop"], (foo && bar).prop - if (p instanceof AST_PropAccess && p.expression === this) - return true; // this deals with precedence: 3 * (2 + 1) if (p instanceof AST_Binary) { var po = p.operator, pp = PRECEDENCE[po]; var so = this.operator, sp = PRECEDENCE[so]; - if (pp > sp - || (pp == sp - && this === p.right)) { - return true; - } + return pp > sp || (pp == sp && this === p.right); } + // (foo && bar)() + if (p instanceof AST_Call) return p.expression === this; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess) return p.expression === this; + // typeof (foo && bar) + if (p instanceof AST_Unary) return true; }); PARENS(AST_PropAccess, function(output) { + var node = this; var p = output.parent(); - if (p instanceof AST_New && p.expression === this) { - // i.e. new (foo.bar().baz) + if (p instanceof AST_New && p.expression === node) { + // i.e. new (foo().bar) // // if there's one call into this subtree, then we need // parens around it too, otherwise the call will be // interpreted as passing the arguments to the upper New // expression. - 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; + do { + node = node.expression; + } while (node instanceof AST_PropAccess); + return node.TYPE == "Call"; } }); PARENS(AST_Call, function(output) { var p = output.parent(); - if (p instanceof AST_New && p.expression === this) return true; + if (p instanceof AST_New) return p.expression === this; // https://bugs.webkit.org/show_bug.cgi?id=123506 if (output.option('webkit')) { var g = output.parent(1); @@ -766,11 +754,12 @@ function OutputStream(options) { }); PARENS(AST_New, function(output) { + if (need_constructor_parens(this, output)) return false; var p = output.parent(); - if (!need_constructor_parens(this, output) - && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() - || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) - return true; + // (new foo)(bar) + if (p instanceof AST_Call) return p.expression === this; + // (new Date).getTime(), (new Date)["getTime"]() + return p instanceof AST_PropAccess; }); PARENS(AST_Number, function(output) { @@ -779,29 +768,22 @@ function OutputStream(options) { var value = this.value; // https://github.com/mishoo/UglifyJS/issues/115 // https://github.com/mishoo/UglifyJS/pull/1009 - if (value < 0 || /^0/.test(make_num(value))) { - return true; - } + return value < 0 || /^0/.test(make_num(value)); } }); PARENS([ AST_Assign, AST_Conditional ], function(output) { var p = output.parent(); - // !(a = false) → true - if (p instanceof AST_Unary) - return true; // 1 + (a = 2) + 3 → 6, side effect setting a = 2 - if (p instanceof AST_Binary && !(p instanceof AST_Assign)) - return true; + if (p instanceof AST_Binary) return !(p instanceof AST_Assign); // (a = func)() —or— new (a = Object)() - if (p instanceof AST_Call && p.expression === this) - return true; + if (p instanceof AST_Call) return p.expression === this; // (a = foo) ? bar : baz - if (p instanceof AST_Conditional && p.condition === this) - return true; + if (p instanceof AST_Conditional) return p.condition === this; // (a = foo)["prop"] —or— (a = foo).prop - if (p instanceof AST_PropAccess && p.expression === this) - return true; + if (p instanceof AST_PropAccess) return p.expression === this; + // !(a = false) → true + if (p instanceof AST_Unary) return true; }); /* -----[ PRINTERS ]----- */ -- 2.34.1