Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for trailing commas in function parameters #1416

Merged
merged 3 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/org/mozilla/javascript/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public class Node implements Iterable<Node> {
SHORTHAND_PROPERTY_NAME = 26,
ARROW_FUNCTION_PROP = 27,
TEMPLATE_LITERAL_PROP = 28,
LAST_PROP = 28;
TRAILING_COMMA = 29,
LAST_PROP = 29;

// values of ISNUMBER_PROP to specify
// which of the children are Number types
Expand Down Expand Up @@ -429,6 +430,8 @@ private static final String propToString(int propType) {
return "expression_closure_prop";
case TEMPLATE_LITERAL_PROP:
return "template_literal";
case TRAILING_COMMA:
return "trailing comma";

default:
Kit.codeBug();
Expand Down
18 changes: 16 additions & 2 deletions src/org/mozilla/javascript/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ private void parseFunctionParams(FunctionNode fnNode) throws IOException {
fnNode.addParam(makeErrorNode());
}
}
} while (matchToken(Token.COMMA, true));
} while (matchToken(Token.COMMA, true) && peekToken() != Token.RP);

if (destructuring != null) {
Node destructuringNode = new Node(Token.COMMA);
Expand Down Expand Up @@ -2288,13 +2288,21 @@ else if (symDeclType == Token.LP) {
}

private AstNode expr() throws IOException {
return expr(false);
p-bakker marked this conversation as resolved.
Show resolved Hide resolved
}

private AstNode expr(boolean allowTrailingComma) throws IOException {
gbrail marked this conversation as resolved.
Show resolved Hide resolved
AstNode pn = assignExpr();
int pos = pn.getPosition();
while (matchToken(Token.COMMA, true)) {
int opPos = ts.tokenBeg;
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) {
pn.putIntProp(Node.TRAILING_COMMA, 1);
return pn;
}
pn = new InfixExpression(Token.COMMA, pn, assignExpr(), opPos);
}
return pn;
Expand Down Expand Up @@ -3160,11 +3168,17 @@ private AstNode parenExpr() throws IOException {
Comment jsdocNode = getAndResetJsDoc();
int lineno = ts.lineno;
int begin = ts.tokenBeg;
AstNode e = (peekToken() == Token.RP ? new EmptyExpression(begin) : expr());
AstNode e = (peekToken() == Token.RP ? new EmptyExpression(begin) : expr(true));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my points above, if this is the only place where we pass "true," does it make more sense to add a new function instead?

if (peekToken() == Token.FOR) {
return generatorExpression(e, begin);
}
mustMatchToken(Token.RP, "msg.no.paren", true);

if (e.getIntProp(Node.TRAILING_COMMA, 0) == 1 && peekToken() != Token.ARROW) {
reportError("msg.syntax");
return makeErrorNode();
}

if (e.getType() == Token.EMPTY && peekToken() != Token.ARROW) {
reportError("msg.syntax");
return makeErrorNode();
Expand Down
20 changes: 7 additions & 13 deletions testsrc/test262.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3029,7 +3029,7 @@ language/expressions/addition 9/48 (18.75%)
get-symbol-to-prim-err.js
order-of-evaluation.js

language/expressions/arrow-function 212/333 (63.66%)
language/expressions/arrow-function 210/333 (63.06%)
dstr/ary-init-iter-close.js
dstr/ary-init-iter-get-err.js
dstr/ary-init-iter-get-err-array-prototype.js
Expand Down Expand Up @@ -3232,8 +3232,6 @@ language/expressions/arrow-function 212/333 (63.66%)
param-dflt-yield-id-non-strict.js {unsupported: [default-parameters]}
param-dflt-yield-id-strict.js {unsupported: [default-parameters]}
params-duplicate.js non-strict
params-trailing-comma-multiple.js
params-trailing-comma-single.js
rest-param-strict-body.js {unsupported: [rest-parameters]}
scope-body-lex-distinct.js non-strict
scope-param-elem-var-close.js non-strict
Expand Down Expand Up @@ -3463,7 +3461,7 @@ language/expressions/exponentiation 4/44 (9.09%)
bigint-wrapped-values.js {unsupported: [computed-property-names]}
order-of-evaluation.js

language/expressions/function 205/248 (82.66%)
language/expressions/function 203/248 (81.85%)
dstr/ary-init-iter-close.js
dstr/ary-init-iter-get-err.js
dstr/ary-init-iter-get-err-array-prototype.js
Expand Down Expand Up @@ -3654,8 +3652,6 @@ language/expressions/function 205/248 (82.66%)
param-eval-strict-body.js non-strict
params-dflt-args-unmapped.js {unsupported: [default-parameters]}
params-dflt-ref-arguments.js {unsupported: [default-parameters]}
params-trailing-comma-multiple.js
params-trailing-comma-single.js
rest-param-strict-body.js {unsupported: [rest-parameters]}
scope-body-lex-distinct.js non-strict
scope-name-var-open-non-strict.js non-strict
Expand Down Expand Up @@ -3870,8 +3866,8 @@ language/expressions/generators 227/275 (82.55%)
param-dflt-yield.js {unsupported: [default-parameters]}
params-dflt-args-unmapped.js {unsupported: [default-parameters]}
params-dflt-ref-arguments.js {unsupported: [default-parameters]}
params-trailing-comma-multiple.js
params-trailing-comma-single.js
params-trailing-comma-multiple.js non-interpreted
params-trailing-comma-single.js non-interpreted
prototype-own-properties.js
prototype-relation-to-function.js
prototype-value.js
Expand Down Expand Up @@ -3950,7 +3946,7 @@ language/expressions/multiplication 4/40 (10.0%)
bigint-wrapped-values.js {unsupported: [computed-property-names]}
order-of-evaluation.js

language/expressions/object 841/1081 (77.8%)
language/expressions/object 839/1081 (77.61%)
dstr/async-gen-meth-ary-init-iter-close.js {unsupported: [async-iteration, async]}
dstr/async-gen-meth-ary-init-iter-get-err.js {unsupported: [async-iteration]}
dstr/async-gen-meth-ary-init-iter-get-err-array-prototype.js {unsupported: [async-iteration]}
Expand Down Expand Up @@ -4666,8 +4662,6 @@ language/expressions/object 841/1081 (77.8%)
method-definition/meth-dflt-params-trailing-comma.js
method-definition/meth-eval-var-scope-syntax-err.js {unsupported: [default-parameters]}
method-definition/meth-object-destructuring-param-strict-body.js {unsupported: [rest-parameters]}
method-definition/meth-params-trailing-comma-multiple.js
method-definition/meth-params-trailing-comma-single.js
method-definition/meth-rest-param-strict-body.js {unsupported: [rest-parameters]}
method-definition/name-invoke-ctor.js
method-definition/name-invoke-fn-strict.js non-strict
Expand Down Expand Up @@ -6151,8 +6145,8 @@ language/statements/generators 220/259 (84.94%)
param-dflt-yield.js {unsupported: [default-parameters]}
params-dflt-args-unmapped.js {unsupported: [default-parameters]}
params-dflt-ref-arguments.js {unsupported: [default-parameters]}
params-trailing-comma-multiple.js
params-trailing-comma-single.js
params-trailing-comma-multiple.js non-interpreted
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean it fails in compiled mode?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The testcase fails due to #1412 now, but the params-trailing-comma part is fixed

params-trailing-comma-single.js non-interpreted
prototype-own-properties.js
prototype-relation-to-function.js
prototype-value.js
Expand Down