From 34937f13d52f4dffcf74d10b10ac96cbeadb987d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 8 Oct 2019 23:08:50 +0200 Subject: [PATCH] Trailing comma after rest - The final fix (#10491) * [parser] Track trailing commas in extras instead of state * Update existing tests * Update test262 whitelist * Improve error message and location * nit * Use lookaheadCharCode --- .../babel-parser/src/parser/expression.js | 62 ++++++++++++------- packages/babel-parser/src/parser/lval.js | 54 +++++++++++----- packages/babel-parser/src/parser/statement.js | 1 + packages/babel-parser/src/plugins/flow.js | 11 +++- .../src/plugins/typescript/index.js | 42 ++++++------- packages/babel-parser/src/tokenizer/state.js | 5 -- .../output.json | 10 ++- .../output.json | 3 + .../basic/function-trailing-comma/output.json | 3 + .../output.json | 3 + .../output.json | 5 +- .../comments/regression/10230/output.json | 5 +- .../core/uncategorised/10/output.json | 5 +- .../core/uncategorised/12/output.json | 5 +- .../core/uncategorised/13/output.json | 5 +- .../comma-after-rest/options.json | 2 +- .../comma-after-spread-for-in/input.js | 1 + .../comma-after-spread-for-in/options.json | 3 + .../comma-after-spread-nested/input.js | 1 + .../comma-after-spread-nested/options.json | 3 + .../comma-after-spread/output.json | 5 +- .../comma-after-rest-param/options.json | 2 +- .../es2015/uncategorised/322/output.json | 5 +- .../options.json | 4 +- .../trailing-function-commas/1/output.json | 3 + .../es2018/object-rest-spread/10/output.json | 5 +- .../es2018/object-rest-spread/6/output.json | 1 + .../es2018/object-rest-spread/8/options.json | 2 +- .../comma-after-spread-for-in/input.js | 1 + .../comma-after-spread-for-in/options.json | 3 + .../comma-after-spread-nested/input.js | 1 + .../comma-after-spread-nested/options.json | 3 + .../comma-after-spread/output.json | 1 + .../elision/output.json | 5 +- .../elision/output.json | 5 +- .../proto-identifier-method/output.json | 1 + .../proto-literal-method/output.json | 1 + .../es2015-object-pattern/elision/output.json | 5 +- .../migrated_0003/output.json | 5 +- .../migrated_0005/output.json | 5 +- .../migrated_0006/output.json | 5 +- .../invalid-trailing-comma/options.json | 2 +- .../test/fixtures/flow/tuples/3/output.json | 5 +- .../object-method-type-param-jsx/output.json | 7 ++- .../object-reserved-word/output.json | 5 +- scripts/tests/test262/test262_whitelist.txt | 10 +-- 46 files changed, 226 insertions(+), 100 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/options.json create mode 100644 packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/input.js create mode 100644 packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/options.json create mode 100644 packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/input.js create mode 100644 packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/options.json create mode 100644 packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/input.js create mode 100644 packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/options.json diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 812fa605a6af..cd090b1fc890 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -168,9 +168,6 @@ export default class ExpressionParser extends LValParser { } } - const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt; - this.state.commaAfterSpreadAt = -1; - let failOnShorthandAssign; if (refShorthandDefaultPos) { failOnShorthandAssign = false; @@ -230,9 +227,6 @@ export default class ExpressionParser extends LValParser { ); } - if (patternErrorMsg) this.checkCommaAfterRestFromSpread(); - this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt; - this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression"); @@ -240,8 +234,6 @@ export default class ExpressionParser extends LValParser { this.unexpected(refShorthandDefaultPos.start); } - this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt; - return left; } @@ -680,14 +672,12 @@ export default class ExpressionParser extends LValParser { let node = this.startNodeAt(startPos, startLoc); node.callee = base; - const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt; - this.state.commaAfterSpreadAt = -1; - node.arguments = this.parseCallExpressionArguments( tt.parenR, state.maybeAsyncArrow, base.type === "Import", base.type !== "Super", + node, ); if (!state.optionalChainMember) { this.finishCallExpression(node); @@ -698,8 +688,6 @@ export default class ExpressionParser extends LValParser { if (state.maybeAsyncArrow && this.shouldParseAsyncArrow()) { state.stop = true; - this.checkCommaAfterRestFromSpread(); - node = this.parseAsyncArrowFromCallExpression( this.startNodeAt(startPos, startLoc), node, @@ -743,7 +731,6 @@ export default class ExpressionParser extends LValParser { } this.state.maybeInArrowParameters = oldMaybeInArrowParameters; - this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt; return node; } else if (this.match(tt.backQuote)) { @@ -825,6 +812,7 @@ export default class ExpressionParser extends LValParser { possibleAsyncArrow: boolean, dynamicImport?: boolean, allowPlaceholder?: boolean, + nodeForExtra?: ?N.Node, ): $ReadOnlyArray { const elts = []; let innerParenStart; @@ -837,13 +825,21 @@ export default class ExpressionParser extends LValParser { first = false; } else { this.expect(tt.comma); - if (this.eat(close)) { + if (this.match(close)) { if (dynamicImport) { this.raise( this.state.lastTokStart, "Trailing comma is disallowed inside import(...) arguments", ); } + if (nodeForExtra) { + this.addExtra( + nodeForExtra, + "trailingComma", + this.state.lastTokStart, + ); + } + this.next(); break; } } @@ -883,7 +879,12 @@ export default class ExpressionParser extends LValParser { call: N.CallExpression, ): N.ArrowFunctionExpression { this.expect(tt.arrow); - this.parseArrowExpression(node, call.arguments, true); + this.parseArrowExpression( + node, + call.arguments, + true, + call.extra?.trailingComma, + ); return node; } @@ -1046,6 +1047,7 @@ export default class ExpressionParser extends LValParser { tt.bracketR, true, refShorthandDefaultPos, + node, ); if (!this.state.maybeInArrowParameters) { // This could be an array pattern: @@ -1289,7 +1291,7 @@ export default class ExpressionParser extends LValParser { ), ); - this.checkCommaAfterRest(); + this.checkCommaAfterRest(charCodes.rightParenthesis); break; } else { @@ -1504,7 +1506,11 @@ export default class ExpressionParser extends LValParser { first = false; } else { this.expect(tt.comma); - if (this.eat(tt.braceR)) break; + if (this.match(tt.braceR)) { + this.addExtra(node, "trailingComma", this.state.lastTokStart); + this.next(); + break; + } } const prop = this.parseObjectMember(isPattern, refShorthandDefaultPos); @@ -1572,7 +1578,7 @@ export default class ExpressionParser extends LValParser { this.next(); // Don't use parseRestBinding() as we only allow Identifier here. prop.argument = this.parseIdentifier(); - this.checkCommaAfterRest(); + this.checkCommaAfterRest(charCodes.rightCurlyBrace); return this.finishNode(prop, "RestElement"); } @@ -1856,6 +1862,7 @@ export default class ExpressionParser extends LValParser { node: N.ArrowFunctionExpression, params: ?(N.Expression[]), isAsync: boolean, + trailingCommaPos: ?number, ): N.ArrowFunctionExpression { this.scope.enter(functionFlags(isAsync, false) | SCOPE_ARROW); this.initFunction(node, isAsync); @@ -1867,7 +1874,7 @@ export default class ExpressionParser extends LValParser { this.state.yieldPos = -1; this.state.awaitPos = -1; - if (params) this.setArrowFunctionParameters(node, params); + if (params) this.setArrowFunctionParameters(node, params, trailingCommaPos); this.parseFunctionBody(node, true); this.scope.exit(); @@ -1881,11 +1888,13 @@ export default class ExpressionParser extends LValParser { setArrowFunctionParameters( node: N.ArrowFunctionExpression, params: N.Expression[], + trailingCommaPos: ?number, ): void { node.params = this.toAssignableList( params, true, "arrow function parameters", + trailingCommaPos, ); } @@ -2012,6 +2021,7 @@ export default class ExpressionParser extends LValParser { close: TokenType, allowEmpty?: boolean, refShorthandDefaultPos?: ?Pos, + nodeForExtra?: ?N.Node, ): $ReadOnlyArray { const elts = []; let first = true; @@ -2021,7 +2031,17 @@ export default class ExpressionParser extends LValParser { first = false; } else { this.expect(tt.comma); - if (this.eat(close)) break; + if (this.match(close)) { + if (nodeForExtra) { + this.addExtra( + nodeForExtra, + "trailingComma", + this.state.lastTokStart, + ); + } + this.next(); + break; + } } elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos)); diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index b4281ab2ffb7..b9d98c3498ca 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -1,5 +1,6 @@ // @flow +import * as charCodes from "charcodes"; import { types as tt, type TokenType } from "../tokenizer/types"; import type { TSParameterProperty, @@ -60,6 +61,14 @@ export default class LValParser extends NodeUtils { const prop = node.properties[i]; const isLast = i === last; this.toAssignableObjectExpressionProp(prop, isBinding, isLast); + + if ( + isLast && + prop.type === "RestElement" && + node.extra?.trailingComma + ) { + this.raiseRestNotLast(node.extra.trailingComma); + } } break; @@ -78,7 +87,12 @@ export default class LValParser extends NodeUtils { case "ArrayExpression": node.type = "ArrayPattern"; - this.toAssignableList(node.elements, isBinding, contextDescription); + this.toAssignableList( + node.elements, + isBinding, + contextDescription, + node.extra?.trailingComma, + ); break; case "AssignmentExpression": @@ -142,6 +156,7 @@ export default class LValParser extends NodeUtils { exprList: Expression[], isBinding: ?boolean, contextDescription: string, + trailingCommaPos?: ?number, ): $ReadOnlyArray { let end = exprList.length; if (end) { @@ -160,6 +175,11 @@ export default class LValParser extends NodeUtils { ) { this.unexpected(arg.start); } + + if (trailingCommaPos) { + this.raiseTrailingCommaAfterRest(trailingCommaPos); + } + --end; } } @@ -213,11 +233,6 @@ export default class LValParser extends NodeUtils { undefined, refNeedsArrowPos, ); - - if (this.state.commaAfterSpreadAt === -1 && this.match(tt.comma)) { - this.state.commaAfterSpreadAt = this.state.start; - } - return this.finishNode(node, "SpreadElement"); } @@ -234,7 +249,11 @@ export default class LValParser extends NodeUtils { case tt.bracketL: { const node = this.startNode(); this.next(); - node.elements = this.parseBindingList(tt.bracketR, true); + node.elements = this.parseBindingList( + tt.bracketR, + charCodes.rightSquareBracket, + true, + ); return this.finishNode(node, "ArrayPattern"); } @@ -247,6 +266,7 @@ export default class LValParser extends NodeUtils { parseBindingList( close: TokenType, + closeCharCode: $Values, allowEmpty?: boolean, allowModifiers?: boolean, ): $ReadOnlyArray { @@ -265,7 +285,7 @@ export default class LValParser extends NodeUtils { break; } else if (this.match(tt.ellipsis)) { elts.push(this.parseAssignableListItemTypes(this.parseRestBinding())); - this.checkCommaAfterRest(); + this.checkCommaAfterRest(closeCharCode); this.expect(close); break; } else { @@ -455,19 +475,21 @@ export default class LValParser extends NodeUtils { } } - checkCommaAfterRest(): void { + checkCommaAfterRest(close: $Values): void { if (this.match(tt.comma)) { - this.raiseRestNotLast(this.state.start); - } - } - - checkCommaAfterRestFromSpread(): void { - if (this.state.commaAfterSpreadAt > -1) { - this.raiseRestNotLast(this.state.commaAfterSpreadAt); + if (this.lookaheadCharCode() === close) { + this.raiseTrailingCommaAfterRest(this.state.start); + } else { + this.raiseRestNotLast(this.state.start); + } } } raiseRestNotLast(pos: number) { this.raise(pos, `Rest element must be last element`); } + + raiseTrailingCommaAfterRest(pos: number) { + this.raise(pos, `Unexpected trailing comma after rest element`); + } } diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 8ce0c9d64418..ad7b8c0ab6a4 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1105,6 +1105,7 @@ export default class StatementParser extends ExpressionParser { this.expect(tt.parenL); node.params = this.parseBindingList( tt.parenR, + charCodes.rightParenthesis, /* allowEmpty */ false, allowModifiers, ); diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index c54f7b633d74..867c31243010 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -1798,6 +1798,7 @@ export default (superClass: Class): Class => ((node.params: any): N.Expression[]), true, "arrow function parameters", + node.extra?.trailingComma, ); // Enter scope, as checkParams defines bindings this.scope.enter(functionFlags(false, false) | SCOPE_ARROW); @@ -1820,6 +1821,7 @@ export default (superClass: Class): Class => ((node.params: any): N.Expression[]), true, "arrow function parameters", + node.extra?.trailingComma, ); } return [arrows, []]; @@ -1831,6 +1833,7 @@ export default (superClass: Class): Class => ((node.params: any): N.Expression[]), true, "arrow function parameters", + node.extra?.trailingComma, ); return true; } catch (err) { @@ -2005,6 +2008,7 @@ export default (superClass: Class): Class => exprList: N.Expression[], isBinding: ?boolean, contextDescription: string, + trailingCommaPos?: ?number, ): $ReadOnlyArray { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; @@ -2012,7 +2016,12 @@ export default (superClass: Class): Class => exprList[i] = this.typeCastToParameter(expr); } } - return super.toAssignableList(exprList, isBinding, contextDescription); + return super.toAssignableList( + exprList, + isBinding, + contextDescription, + trailingCommaPos, + ); } // this is a list of nodes, from something like a call expression, we need to filter the diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 40292c5107c8..8adf82f1568a 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -363,21 +363,23 @@ export default (superClass: Class): Class => tsParseBindingListForSignature(): $ReadOnlyArray< N.Identifier | N.RestElement | N.ObjectPattern | N.ArrayPattern, > { - return this.parseBindingList(tt.parenR).map(pattern => { - if ( - pattern.type !== "Identifier" && - pattern.type !== "RestElement" && - pattern.type !== "ObjectPattern" && - pattern.type !== "ArrayPattern" - ) { - throw this.unexpected( - pattern.start, - "Name in a signature must be an Identifier, ObjectPattern or ArrayPattern," + - `instead got ${pattern.type}`, - ); - } - return pattern; - }); + return this.parseBindingList(tt.parenR, charCodes.rightParenthesis).map( + pattern => { + if ( + pattern.type !== "Identifier" && + pattern.type !== "RestElement" && + pattern.type !== "ObjectPattern" && + pattern.type !== "ArrayPattern" + ) { + throw this.unexpected( + pattern.start, + "Name in a signature must be an Identifier, ObjectPattern or ArrayPattern," + + `instead got ${pattern.type}`, + ); + } + return pattern; + }, + ); } tsParseTypeMemberSemicolon(): void { @@ -586,7 +588,7 @@ export default (superClass: Class): Class => const restNode: N.TsRestType = this.startNode(); this.next(); // skips ellipsis restNode.typeAnnotation = this.tsParseType(); - this.checkCommaAfterRest(); + this.checkCommaAfterRest(charCodes.rightSquareBracket); return this.finishNode(restNode, "TSRestType"); } @@ -2363,11 +2365,7 @@ export default (superClass: Class): Class => } } - toAssignableList( - exprList: N.Expression[], - isBinding: ?boolean, - contextDescription: string, - ): $ReadOnlyArray { + toAssignableList(exprList: N.Expression[]): $ReadOnlyArray { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; if (!expr) continue; @@ -2384,7 +2382,7 @@ export default (superClass: Class): Class => break; } } - return super.toAssignableList(exprList, isBinding, contextDescription); + return super.toAssignableList(...arguments); } typeCastToParameter(node: N.TsTypeCastExpression): N.Node { diff --git a/packages/babel-parser/src/tokenizer/state.js b/packages/babel-parser/src/tokenizer/state.js index a9dccb2bf0e6..4ee937e1d292 100644 --- a/packages/babel-parser/src/tokenizer/state.js +++ b/packages/babel-parser/src/tokenizer/state.js @@ -55,11 +55,6 @@ export default class State { // ^ noArrowParamsConversionAt: number[] = []; - // A comma after "...a" is only allowed in spread, but not in rest. - // Since we parse destructuring patterns as array/object literals - // and then convert them, we need to track it. - commaAfterSpreadAt: number = -1; - // Flags to track inParameters: boolean = false; maybeInArrowParameters: boolean = false; diff --git a/packages/babel-parser/test/fixtures/comments/basic/array-expression-trailing-comma/output.json b/packages/babel-parser/test/fixtures/comments/basic/array-expression-trailing-comma/output.json index 90428301c81b..a1a531180079 100644 --- a/packages/babel-parser/test/fixtures/comments/basic/array-expression-trailing-comma/output.json +++ b/packages/babel-parser/test/fixtures/comments/basic/array-expression-trailing-comma/output.json @@ -373,7 +373,10 @@ } ] } - ] + ], + "extra": { + "trailingComma": 140 + } } } ], @@ -494,7 +497,10 @@ } ] } - ] + ], + "extra": { + "trailingComma": 200 + } } } ], diff --git a/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma-shorthand/output.json b/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma-shorthand/output.json index 3e22bc1678e5..b27cadb955a0 100644 --- a/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma-shorthand/output.json +++ b/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma-shorthand/output.json @@ -74,6 +74,9 @@ }, "name": "fn" }, + "extra": { + "trailingComma": 11 + }, "arguments": [ { "type": "Identifier", diff --git a/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma/output.json b/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma/output.json index 6147660b79f9..a224e1810b5d 100644 --- a/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma/output.json +++ b/packages/babel-parser/test/fixtures/comments/basic/function-trailing-comma/output.json @@ -74,6 +74,9 @@ }, "name": "fn" }, + "extra": { + "trailingComma": 7 + }, "arguments": [ { "type": "Identifier", diff --git a/packages/babel-parser/test/fixtures/comments/basic/object-expression-trailing-comma/output.json b/packages/babel-parser/test/fixtures/comments/basic/object-expression-trailing-comma/output.json index 5f2a5b29b779..8cf9693cb683 100644 --- a/packages/babel-parser/test/fixtures/comments/basic/object-expression-trailing-comma/output.json +++ b/packages/babel-parser/test/fixtures/comments/basic/object-expression-trailing-comma/output.json @@ -181,6 +181,9 @@ } } ], + "extra": { + "trailingComma": 35 + }, "trailingComments": [ { "type": "CommentBlock", diff --git a/packages/babel-parser/test/fixtures/comments/basic/object-property-trailing-comma/output.json b/packages/babel-parser/test/fixtures/comments/basic/object-property-trailing-comma/output.json index 82f13bbfed5e..1ab0eaed8cb3 100644 --- a/packages/babel-parser/test/fixtures/comments/basic/object-property-trailing-comma/output.json +++ b/packages/babel-parser/test/fixtures/comments/basic/object-property-trailing-comma/output.json @@ -309,7 +309,10 @@ } ] } - ] + ], + "extra": { + "trailingComma": 66 + } } } ], diff --git a/packages/babel-parser/test/fixtures/comments/regression/10230/output.json b/packages/babel-parser/test/fixtures/comments/regression/10230/output.json index f081d1ee65fd..fac57ee10213 100644 --- a/packages/babel-parser/test/fixtures/comments/regression/10230/output.json +++ b/packages/babel-parser/test/fixtures/comments/regression/10230/output.json @@ -163,7 +163,10 @@ } ] } - ] + ], + "extra": { + "trailingComma": 13 + } } }, "trailingComments": [ diff --git a/packages/babel-parser/test/fixtures/core/uncategorised/10/output.json b/packages/babel-parser/test/fixtures/core/uncategorised/10/output.json index 3f7e070ca3ac..d2f456d828ab 100644 --- a/packages/babel-parser/test/fixtures/core/uncategorised/10/output.json +++ b/packages/babel-parser/test/fixtures/core/uncategorised/10/output.json @@ -110,7 +110,10 @@ }, "value": 42 } - ] + ], + "extra": { + "trailingComma": 8 + } } } } diff --git a/packages/babel-parser/test/fixtures/core/uncategorised/12/output.json b/packages/babel-parser/test/fixtures/core/uncategorised/12/output.json index 573eda5bfa9f..0c39b167df03 100644 --- a/packages/babel-parser/test/fixtures/core/uncategorised/12/output.json +++ b/packages/babel-parser/test/fixtures/core/uncategorised/12/output.json @@ -150,7 +150,10 @@ }, "value": 3 } - ] + ], + "extra": { + "trailingComma": 13 + } } } } diff --git a/packages/babel-parser/test/fixtures/core/uncategorised/13/output.json b/packages/babel-parser/test/fixtures/core/uncategorised/13/output.json index 34c8d7e15c8e..c2fec5bfcf25 100644 --- a/packages/babel-parser/test/fixtures/core/uncategorised/13/output.json +++ b/packages/babel-parser/test/fixtures/core/uncategorised/13/output.json @@ -151,7 +151,10 @@ }, "value": 3 } - ] + ], + "extra": { + "trailingComma": 14 + } } } } diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/options.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/options.json index daa827f45cc4..7931fd924fcd 100644 --- a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/options.json +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest element must be last element (1:5)" + "throws": "Unexpected trailing comma after rest element (1:5)" } diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/input.js b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/input.js new file mode 100644 index 000000000000..b58efbd91c33 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/input.js @@ -0,0 +1 @@ +for ([...a,] in []); diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/options.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/options.json new file mode 100644 index 000000000000..0b0d3c532d1e --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-for-in/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected trailing comma after rest element (1:10)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/input.js b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/input.js new file mode 100644 index 000000000000..0e2c4750076e --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/input.js @@ -0,0 +1 @@ +[[...a,]] = []; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/options.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/options.json new file mode 100644 index 000000000000..95a846d785a8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread-nested/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected trailing comma after rest element (1:6)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json index 5874666e2695..0a80d6e9f99b 100644 --- a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json @@ -90,7 +90,10 @@ "name": "a" } } - ] + ], + "extra": { + "trailingComma": 5 + } } } ], diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/comma-after-rest-param/options.json b/packages/babel-parser/test/fixtures/es2015/arrow-functions/comma-after-rest-param/options.json index 65ed8c638978..38fec89ef15c 100644 --- a/packages/babel-parser/test/fixtures/es2015/arrow-functions/comma-after-rest-param/options.json +++ b/packages/babel-parser/test/fixtures/es2015/arrow-functions/comma-after-rest-param/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest element must be last element (1:8)" + "throws": "Unexpected trailing comma after rest element (1:8)" } diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/322/output.json b/packages/babel-parser/test/fixtures/es2015/uncategorised/322/output.json index 1749b8360656..68286e968b5c 100644 --- a/packages/babel-parser/test/fixtures/es2015/uncategorised/322/output.json +++ b/packages/babel-parser/test/fixtures/es2015/uncategorised/322/output.json @@ -91,7 +91,10 @@ "name": "x" }, null - ] + ], + "extra": { + "trailingComma": 3 + } }, "right": { "type": "NumericLiteral", diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/params-invalid-rest-trailing-comma/options.json b/packages/babel-parser/test/fixtures/es2017/async-functions/params-invalid-rest-trailing-comma/options.json index f686fb60b45e..bc7331763bfa 100644 --- a/packages/babel-parser/test/fixtures/es2017/async-functions/params-invalid-rest-trailing-comma/options.json +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/params-invalid-rest-trailing-comma/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest element must be last element (1:11)" -} + "throws": "Unexpected trailing comma after rest element (1:11)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2017/trailing-function-commas/1/output.json b/packages/babel-parser/test/fixtures/es2017/trailing-function-commas/1/output.json index 2373fc85c177..40aa85102591 100644 --- a/packages/babel-parser/test/fixtures/es2017/trailing-function-commas/1/output.json +++ b/packages/babel-parser/test/fixtures/es2017/trailing-function-commas/1/output.json @@ -74,6 +74,9 @@ }, "name": "log" }, + "extra": { + "trailingComma": 13 + }, "arguments": [ { "type": "Identifier", diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/10/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/10/output.json index 485e729af53e..6b852f78deea 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/10/output.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/10/output.json @@ -183,7 +183,10 @@ "shorthand": true } } - ] + ], + "extra": { + "trailingComma": 10 + } }, "init": { "type": "Identifier", diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/6/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/6/output.json index 1e1e8979748a..66bdc45dc975 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/6/output.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/6/output.json @@ -289,6 +289,7 @@ } ], "extra": { + "trailingComma": 21, "parenthesized": true, "parenStart": 0 } diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/8/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/8/options.json index c49db16e2821..c44d69275adb 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/8/options.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/8/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest element must be last element (1:16)" + "throws": "Unexpected trailing comma after rest element (1:16)" } diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/input.js new file mode 100644 index 000000000000..f06e08484719 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/input.js @@ -0,0 +1 @@ +for ({...a,} in []); diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/options.json new file mode 100644 index 000000000000..f14967a76c6c --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-for-in/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Rest element must be last element (1:10)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/input.js new file mode 100644 index 000000000000..d532e288fbaf --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/input.js @@ -0,0 +1 @@ +[{...a,}] = []; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/options.json new file mode 100644 index 000000000000..9336eba62a3e --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread-nested/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Rest element must be last element (1:6)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json index ffb978345c27..2b3910bf3a5b 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json @@ -92,6 +92,7 @@ } ], "extra": { + "trailingComma": 6, "parenthesized": true, "parenStart": 0 } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-array-binding-pattern/elision/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-array-binding-pattern/elision/output.json index 10c96101b155..2f49a3a77d71 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-array-binding-pattern/elision/output.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-array-binding-pattern/elision/output.json @@ -78,7 +78,10 @@ "elements": [ null, null - ] + ], + "extra": { + "trailingComma": 3 + } } ], "body": { diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-destructuring-assignment-array-pattern/elision/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-destructuring-assignment-array-pattern/elision/output.json index eebd569aa2e6..6032e42c2b32 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-destructuring-assignment-array-pattern/elision/output.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-destructuring-assignment-array-pattern/elision/output.json @@ -75,7 +75,10 @@ "elements": [ null, null - ] + ], + "extra": { + "trailingComma": 2 + } }, "right": { "type": "NumericLiteral", diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-identifier-method/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-identifier-method/output.json index d6a917129034..76754ed85da4 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-identifier-method/output.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-identifier-method/output.json @@ -166,6 +166,7 @@ } ], "extra": { + "trailingComma": 33, "parenthesized": true, "parenStart": 0 } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-literal-method/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-literal-method/output.json index 0995b435bf70..cd0e7970cac6 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-literal-method/output.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-object-initialiser/proto-literal-method/output.json @@ -169,6 +169,7 @@ } ], "extra": { + "trailingComma": 35, "parenthesized": true, "parenStart": 0 } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-object-pattern/elision/output.json b/packages/babel-parser/test/fixtures/esprima/es2015-object-pattern/elision/output.json index 4f6c7b8f2be5..243668c0d0ad 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-object-pattern/elision/output.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-object-pattern/elision/output.json @@ -128,7 +128,10 @@ "shorthand": true } } - ] + ], + "extra": { + "trailingComma": 6 + } }, "init": { "type": "NumericLiteral", diff --git a/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0003/output.json b/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0003/output.json index 3f7e070ca3ac..d2f456d828ab 100644 --- a/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0003/output.json +++ b/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0003/output.json @@ -110,7 +110,10 @@ }, "value": 42 } - ] + ], + "extra": { + "trailingComma": 8 + } } } } diff --git a/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0005/output.json b/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0005/output.json index 573eda5bfa9f..0c39b167df03 100644 --- a/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0005/output.json +++ b/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0005/output.json @@ -150,7 +150,10 @@ }, "value": 3 } - ] + ], + "extra": { + "trailingComma": 13 + } } } } diff --git a/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0006/output.json b/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0006/output.json index 34c8d7e15c8e..c2fec5bfcf25 100644 --- a/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0006/output.json +++ b/packages/babel-parser/test/fixtures/esprima/expression-primary-array/migrated_0006/output.json @@ -151,7 +151,10 @@ }, "value": 3 } - ] + ], + "extra": { + "trailingComma": 14 + } } } } diff --git a/packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-trailing-comma/options.json b/packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-trailing-comma/options.json index 770750c7f91f..ae6f5f18ff31 100644 --- a/packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-trailing-comma/options.json +++ b/packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-trailing-comma/options.json @@ -1,3 +1,3 @@ { - "throws": "Trailing comma is disallowed inside import(...) arguments (1:13)" + "throws": "Trailing comma is disallowed inside import(...) arguments (1:12)" } diff --git a/packages/babel-parser/test/fixtures/flow/tuples/3/output.json b/packages/babel-parser/test/fixtures/flow/tuples/3/output.json index 2c61f6b164a0..dada487fe124 100644 --- a/packages/babel-parser/test/fixtures/flow/tuples/3/output.json +++ b/packages/babel-parser/test/fixtures/flow/tuples/3/output.json @@ -157,7 +157,10 @@ }, "value": 123 } - ] + ], + "extra": { + "trailingComma": 24 + } } } ], diff --git a/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-method-type-param-jsx/output.json b/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-method-type-param-jsx/output.json index 9cbc275b184b..5e5de02ff3c2 100644 --- a/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-method-type-param-jsx/output.json +++ b/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-method-type-param-jsx/output.json @@ -187,7 +187,6 @@ "column": 23 } }, - "attributes": [], "name": { "type": "JSXIdentifier", "start": 29, @@ -204,6 +203,7 @@ }, "name": "Foo" }, + "attributes": [], "selfClosing": true }, "closingElement": null, @@ -263,7 +263,10 @@ ] } } - ] + ], + "extra": { + "trailingComma": 39 + } } } ], diff --git a/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-reserved-word/output.json b/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-reserved-word/output.json index 5a8cfcc689b0..bd86fd173803 100644 --- a/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-reserved-word/output.json +++ b/packages/babel-parser/test/fixtures/flow/type-parameter-declaration/object-reserved-word/output.json @@ -450,7 +450,10 @@ ] } } - ] + ], + "extra": { + "trailingComma": 77 + } } } ], diff --git a/scripts/tests/test262/test262_whitelist.txt b/scripts/tests/test262/test262_whitelist.txt index 6ad39b56b688..977cd38ed79a 100644 --- a/scripts/tests/test262/test262_whitelist.txt +++ b/scripts/tests/test262/test262_whitelist.txt @@ -645,12 +645,4 @@ language/statements/class/elements/syntax/early-errors/invalid-names/method-outt language/statements/class/elements/syntax/early-errors/invalid-names/method-outter-member-expression-bad-reference.js(default) language/statements/class/elements/syntax/early-errors/invalid-names/method-outter-member-expression-bad-reference.js(strict mode) language/statements/class/elements/syntax/early-errors/invalid-names/method-outter-member-expression-this.js(default) -language/statements/class/elements/syntax/early-errors/invalid-names/method-outter-member-expression-this.js(strict mode) -language/statements/for-in/dstr/array-rest-before-elision.js(default) -language/statements/for-in/dstr/array-rest-before-elision.js(strict mode) -language/statements/for-in/dstr/array-rest-elision-invalid.js(default) -language/statements/for-in/dstr/array-rest-elision-invalid.js(strict mode) -language/statements/for-of/dstr/array-rest-before-elision.js(default) -language/statements/for-of/dstr/array-rest-before-elision.js(strict mode) -language/statements/for-of/dstr/array-rest-elision-invalid.js(default) -language/statements/for-of/dstr/array-rest-elision-invalid.js(strict mode) \ No newline at end of file +language/statements/class/elements/syntax/early-errors/invalid-names/method-outter-member-expression-this.js(strict mode) \ No newline at end of file