diff --git a/src/org/mozilla/javascript/Parser.java b/src/org/mozilla/javascript/Parser.java index f3d5f9a60b..9cc30fe574 100644 --- a/src/org/mozilla/javascript/Parser.java +++ b/src/org/mozilla/javascript/Parser.java @@ -786,6 +786,10 @@ private void parseFunctionParams(FunctionNode fnNode) throws IOException { Set paramNames = new HashSet<>(); do { int tt = peekToken(); + if (tt == Token.RP) { + fnNode.putIntProp(Node.TRAILING_COMMA, 1); + break; + } if (tt == Token.LB || tt == Token.LC) { AstNode expr = destructuringPrimaryExpr(); markDestructuring(expr); @@ -821,7 +825,7 @@ private void parseFunctionParams(FunctionNode fnNode) throws IOException { fnNode.addParam(makeErrorNode()); } } - } while (matchToken(Token.COMMA, true) && peekToken() != Token.RP); + } while (matchToken(Token.COMMA, true)); if (destructuring != null) { Node destructuringNode = new Node(Token.COMMA); @@ -969,6 +973,9 @@ private AstNode arrowFunction(AstNode params) throws IOException { try { if (params instanceof ParenthesizedExpression) { fnNode.setParens(0, params.getLength()); + if (params.getIntProp(Node.TRAILING_COMMA, 0) == 1) { + fnNode.putIntProp(Node.TRAILING_COMMA, 1); + } AstNode p = ((ParenthesizedExpression) params).getExpression(); if (!(p instanceof EmptyExpression)) { arrowFunctionParams(fnNode, p, destructuring, paramNames); @@ -2295,7 +2302,7 @@ private AstNode expr(boolean allowTrailingComma) throws IOException { if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) addStrictWarning("msg.no.side.effects", "", pos, nodeEnd(pn) - pos); if (peekToken() == Token.YIELD) reportError("msg.yield.parenthesized"); - if (peekToken() == Token.RP && allowTrailingComma) { + if (allowTrailingComma && peekToken() == Token.RP) { pn.putIntProp(Node.TRAILING_COMMA, 1); return pn; } @@ -3170,16 +3177,14 @@ private AstNode parenExpr() throws IOException { } mustMatchToken(Token.RP, "msg.no.paren", true); - if (e.getIntProp(Node.TRAILING_COMMA, 0) == 1 && peekToken() != Token.ARROW) { - reportError("msg.syntax"); - return makeErrorNode(); - } + int length = ts.tokenEnd - begin; - if (e.getType() == Token.EMPTY && peekToken() != Token.ARROW) { + boolean hasTrailingComma = e.getIntProp(Node.TRAILING_COMMA, 0) == 1; + if ((hasTrailingComma || e.getType() == Token.EMPTY) && peekToken() != Token.ARROW) { reportError("msg.syntax"); return makeErrorNode(); } - int length = ts.tokenEnd - begin; + ParenthesizedExpression pn = new ParenthesizedExpression(begin, length, e); pn.setLineno(lineno); if (jsdocNode == null) { @@ -3188,6 +3193,9 @@ private AstNode parenExpr() throws IOException { if (jsdocNode != null) { pn.setJsDocNode(jsdocNode); } + if (hasTrailingComma) { + pn.putIntProp(Node.TRAILING_COMMA, 1); + } return pn; } finally { inForInit = wasInForInit; diff --git a/src/org/mozilla/javascript/ast/FunctionNode.java b/src/org/mozilla/javascript/ast/FunctionNode.java index e999e3d953..a19f7ce4f6 100644 --- a/src/org/mozilla/javascript/ast/FunctionNode.java +++ b/src/org/mozilla/javascript/ast/FunctionNode.java @@ -391,6 +391,9 @@ public String toSource(int depth) { } else { sb.append("("); printList(params, sb); + if (getIntProp(TRAILING_COMMA, 0) == 1) { + sb.append(", "); + } sb.append(") "); } if (isArrow) {