diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 07fad7964f..970d4acaf1 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -130,6 +130,9 @@ export default class ExpressionParser extends LValParser { return left; } + const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt; + this.state.commaAfterSpreadAt = -1; + let failOnShorthandAssign; if (refShorthandDefaultPos) { failOnShorthandAssign = false; @@ -169,21 +172,26 @@ export default class ExpressionParser extends LValParser { this.checkLVal(left, undefined, undefined, "assignment expression"); - if (left.extra && left.extra.parenthesized) { - let errorMsg; - if (left.type === "ObjectPattern") { - errorMsg = "`({a}) = 0` use `({a} = 0)`"; - } else if (left.type === "ArrayPattern") { - errorMsg = "`([a]) = 0` use `([a] = 0)`"; - } - if (errorMsg) { - this.raise( - left.start, - `You're trying to assign to a parenthesized expression, eg. instead of ${errorMsg}`, - ); - } + let patternErrorMsg; + let elementName; + if (left.type === "ObjectPattern") { + patternErrorMsg = "`({a}) = 0` use `({a} = 0)`"; + elementName = "property"; + } else if (left.type === "ArrayPattern") { + patternErrorMsg = "`([a]) = 0` use `([a] = 0)`"; + elementName = "element"; } + if (patternErrorMsg && left.extra && left.extra.parenthesized) { + this.raise( + left.start, + `You're trying to assign to a parenthesized expression, eg. instead of ${patternErrorMsg}`, + ); + } + + if (elementName) this.checkCommaAfterRestFromSpread(elementName); + this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt; + this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression"); @@ -191,6 +199,8 @@ export default class ExpressionParser extends LValParser { this.unexpected(refShorthandDefaultPos.start); } + this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt; + return left; } @@ -580,15 +590,12 @@ export default class ExpressionParser extends LValParser { let node = this.startNodeAt(startPos, startLoc); node.callee = base; - // TODO: Clean up/merge this into `this.state` or a class like acorn's - // `DestructuringErrors` alongside refShorthandDefaultPos and - // refNeedsArrowPos. - const refTrailingCommaPos: Pos = { start: -1 }; + const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt; + this.state.commaAfterSpreadAt = -1; node.arguments = this.parseCallExpressionArguments( tt.parenR, possibleAsync, - refTrailingCommaPos, ); if (!state.optionalChainMember) { this.finishCallExpression(node); @@ -599,12 +606,7 @@ export default class ExpressionParser extends LValParser { if (possibleAsync && this.shouldParseAsyncArrow()) { state.stop = true; - if (refTrailingCommaPos.start > -1) { - this.raise( - refTrailingCommaPos.start, - "A trailing comma is not permitted after the rest element", - ); - } + this.checkCommaAfterRestFromSpread("parameter"); node = this.parseAsyncArrowFromCallExpression( this.startNodeAt(startPos, startLoc), @@ -621,6 +623,7 @@ export default class ExpressionParser extends LValParser { } this.state.maybeInArrowParameters = oldMaybeInArrowParameters; + this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt; return node; } else if (this.match(tt.backQuote)) { @@ -700,7 +703,6 @@ export default class ExpressionParser extends LValParser { parseCallExpressionArguments( close: TokenType, possibleAsyncArrow: boolean, - refTrailingCommaPos?: Pos, ): $ReadOnlyArray { const elts = []; let innerParenStart; @@ -725,7 +727,6 @@ export default class ExpressionParser extends LValParser { false, possibleAsyncArrow ? { start: 0 } : undefined, possibleAsyncArrow ? { start: 0 } : undefined, - possibleAsyncArrow ? refTrailingCommaPos : undefined, ), ); } @@ -1192,14 +1193,7 @@ export default class ExpressionParser extends LValParser { ), ); - if (this.match(tt.comma)) { - const nextTokenType = this.lookahead().type; - const errorMessage = - nextTokenType === tt.parenR - ? "A trailing comma is not permitted after the rest element" - : "Rest parameter must be last formal parameter"; - this.raise(this.state.start, errorMessage); - } + this.checkCommaAfterRest(tt.parenR, "parameter"); break; } else { @@ -1398,8 +1392,6 @@ export default class ExpressionParser extends LValParser { node.properties = []; this.next(); - let firstRestLocation = null; - while (!this.eat(tt.braceR)) { if (first) { first = false; @@ -1435,34 +1427,14 @@ export default class ExpressionParser extends LValParser { if (this.match(tt.ellipsis)) { prop = this.parseSpread(isPattern ? { start: 0 } : undefined); - if (isPattern) { - this.toAssignable(prop, true, "object pattern"); - } node.properties.push(prop); if (isPattern) { - const position = this.state.start; - if (firstRestLocation !== null) { - this.unexpected( - firstRestLocation, - "Cannot have multiple rest elements when destructuring", - ); - } else if (this.eat(tt.braceR)) { - break; - } else if ( - this.match(tt.comma) && - this.lookahead().type === tt.braceR - ) { - this.unexpected( - position, - "A trailing comma is not permitted after the rest element", - ); - } else { - firstRestLocation = position; - continue; - } - } else { - continue; + this.toAssignable(prop, true, "object pattern"); + this.checkCommaAfterRest(tt.braceR, "property"); + this.expect(tt.braceR); + break; } + continue; } prop.method = false; @@ -1519,13 +1491,6 @@ export default class ExpressionParser extends LValParser { node.properties.push(prop); } - if (firstRestLocation !== null) { - this.unexpected( - firstRestLocation, - "The rest element has to be the last element when destructuring", - ); - } - if (decorators.length) { this.raise( this.state.start, @@ -1923,7 +1888,6 @@ export default class ExpressionParser extends LValParser { allowEmpty: ?boolean, refShorthandDefaultPos: ?Pos, refNeedsArrowPos: ?Pos, - refTrailingCommaPos?: Pos, ): ?N.Expression { let elt; if (allowEmpty && this.match(tt.comma)) { @@ -1936,10 +1900,6 @@ export default class ExpressionParser extends LValParser { spreadNodeStartPos, spreadNodeStartLoc, ); - - if (refTrailingCommaPos && this.match(tt.comma)) { - refTrailingCommaPos.start = this.state.start; - } } else { elt = this.parseMaybeAssign( false, diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index 5fc48b90d2..76613bba31 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -122,10 +122,7 @@ export default class LValParser extends NodeUtils { this.raise(prop.key.start, error); } else if (prop.type === "SpreadElement" && !isLast) { - this.raise( - prop.start, - "The rest element has to be the last element when destructuring", - ); + this.raiseRestNotLast(prop.start, "property"); } else { this.toAssignable(prop, isBinding, "object destructuring pattern"); } @@ -162,13 +159,12 @@ export default class LValParser extends NodeUtils { } for (let i = 0; i < end; i++) { const elt = exprList[i]; - if (elt && elt.type === "SpreadElement") { - this.raise( - elt.start, - "The rest element has to be the last element when destructuring", - ); + if (elt) { + this.toAssignable(elt, isBinding, contextDescription); + if (elt.type === "RestElement") { + this.raiseRestNotLast(elt.start, "element"); + } } - if (elt) this.toAssignable(elt, isBinding, contextDescription); } return exprList; } @@ -199,10 +195,10 @@ export default class LValParser extends NodeUtils { // Parses spread element. - parseSpread( + parseSpread( refShorthandDefaultPos: ?Pos, refNeedsArrowPos?: ?Pos, - ): T { + ): SpreadElement { const node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign( @@ -211,6 +207,11 @@ 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"); } @@ -273,20 +274,13 @@ export default class LValParser extends NodeUtils { break; } else if (this.match(tt.ellipsis)) { elts.push(this.parseAssignableListItemTypes(this.parseRest())); - if ( - this.state.inFunction && - this.state.inParameters && - this.match(tt.comma) - ) { - const nextTokenType = this.lookahead().type; - const errorMessage = - nextTokenType === tt.parenR - ? "A trailing comma is not permitted after the rest element" - : "Rest parameter must be last formal parameter"; - this.raise(this.state.start, errorMessage); - } else { - this.expect(close); - } + this.checkCommaAfterRest( + close, + this.state.inFunction && this.state.inParameters + ? "parameter" + : "element", + ); + this.expect(close); break; } else { const decorators = []; @@ -440,4 +434,28 @@ export default class LValParser extends NodeUtils { this.raise(node.argument.start, "Invalid rest operator's argument"); } + + checkCommaAfterRest(close: TokenType, kind: string): void { + if (this.match(tt.comma)) { + if (this.lookahead().type === close) { + this.raiseCommaAfterRest(this.state.start, kind); + } else { + this.raiseRestNotLast(this.state.start, kind); + } + } + } + + checkCommaAfterRestFromSpread(kind: string): void { + if (this.state.commaAfterSpreadAt > -1) { + this.raiseCommaAfterRest(this.state.commaAfterSpreadAt, kind); + } + } + + raiseCommaAfterRest(pos: number, kind: string) { + this.raise(pos, `A trailing comma is not permitted after the rest ${kind}`); + } + + raiseRestNotLast(pos: number, kind: string) { + this.raise(pos, `The rest ${kind} must be the last ${kind}`); + } } diff --git a/packages/babel-parser/src/plugins/typescript.js b/packages/babel-parser/src/plugins/typescript.js index b81ab14afc..02cdd54b89 100644 --- a/packages/babel-parser/src/plugins/typescript.js +++ b/packages/babel-parser/src/plugins/typescript.js @@ -546,17 +546,10 @@ export default (superClass: Class): Class => // No mandatory elements may follow optional elements // If there's a rest element, it must be at the end of the tuple let seenOptionalElement = false; - node.elementTypes.forEach((elementNode, i) => { - if (elementNode.type === "TSRestType") { - if (i !== node.elementTypes.length - 1) { - this.raise( - elementNode.start, - "A rest element must be last in a tuple type.", - ); - } - } else if (elementNode.type === "TSOptionalType") { + node.elementTypes.forEach(elementNode => { + if (elementNode.type === "TSOptionalType") { seenOptionalElement = true; - } else if (seenOptionalElement) { + } else if (seenOptionalElement && elementNode.type !== "TSRestType") { this.raise( elementNode.start, "A required element cannot follow an optional element.", @@ -573,6 +566,7 @@ export default (superClass: Class): Class => const restNode: N.TsRestType = this.startNode(); this.next(); // skips ellipsis restNode.typeAnnotation = this.tsParseType(); + this.checkCommaAfterRest(tt.bracketR, "type"); return this.finishNode(restNode, "TSRestType"); } diff --git a/packages/babel-parser/src/tokenizer/state.js b/packages/babel-parser/src/tokenizer/state.js index debcaacbf1..d857cea134 100644 --- a/packages/babel-parser/src/tokenizer/state.js +++ b/packages/babel-parser/src/tokenizer/state.js @@ -15,6 +15,8 @@ export default class State { this.input = input; + this.commaAfterSpreadAt = -1; + this.potentialArrowAt = -1; this.noArrowAt = []; @@ -87,6 +89,11 @@ export default class State { // TODO input: string; + // 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; + // Used to signify the start of a potential arrow function potentialArrowAt: number; diff --git a/packages/babel-parser/test/fixtures/core/uncategorised/396/options.json b/packages/babel-parser/test/fixtures/core/uncategorised/396/options.json index b8808d8a68..029befceda 100644 --- a/packages/babel-parser/test/fixtures/core/uncategorised/396/options.json +++ b/packages/babel-parser/test/fixtures/core/uncategorised/396/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (1:18)" + "throws": "The rest parameter must be the last parameter (1:18)" } diff --git a/packages/babel-parser/test/fixtures/core/uncategorised/555/options.json b/packages/babel-parser/test/fixtures/core/uncategorised/555/options.json index 837fa24c91..baad06556f 100644 --- a/packages/babel-parser/test/fixtures/core/uncategorised/555/options.json +++ b/packages/babel-parser/test/fixtures/core/uncategorised/555/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (3:13)" + "throws": "The rest parameter must be the last parameter (3:13)" } diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/input.js b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/input.js new file mode 100644 index 0000000000..d4aba7bf55 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/input.js @@ -0,0 +1 @@ +[...a,] = []; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/params-invalid-rest-trailing-comma/options.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/options.json similarity index 100% rename from packages/babel-parser/test/fixtures/es2015/arrow-functions/params-invalid-rest-trailing-comma/options.json rename to packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/options.json diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/input.js b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/input.js new file mode 100644 index 0000000000..7161cc852a --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/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/output.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json new file mode 100644 index 0000000000..5874666e26 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json @@ -0,0 +1,99 @@ +{ + "type": "File", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "expression": { + "type": "ArrayExpression", + "start": 0, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "elements": [ + { + "type": "SpreadElement", + "start": 1, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 5 + } + }, + "argument": { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + }, + "identifierName": "a" + }, + "name": "a" + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/invalid-location/options.json b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/invalid-location/options.json index beef14a214..083dcaaa2c 100644 --- a/packages/babel-parser/test/fixtures/es2015/array-rest-spread/invalid-location/options.json +++ b/packages/babel-parser/test/fixtures/es2015/array-rest-spread/invalid-location/options.json @@ -1,3 +1,3 @@ { - "throws": "The rest element has to be the last element when destructuring (1:1)" + "throws": "The rest element must be the last element (1:1)" } 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 babb96d8b7..d866b41af7 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": "A trailing comma is not permitted after the rest element (1:8)" + "throws": "A trailing comma is not permitted after the rest parameter (1:8)" } diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/invalid-rest-in-params/options.json b/packages/babel-parser/test/fixtures/es2015/arrow-functions/invalid-rest-in-params/options.json index 837fa24c91..baad06556f 100644 --- a/packages/babel-parser/test/fixtures/es2015/arrow-functions/invalid-rest-in-params/options.json +++ b/packages/babel-parser/test/fixtures/es2015/arrow-functions/invalid-rest-in-params/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (3:13)" + "throws": "The rest parameter must be the last parameter (3:13)" } diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/params-invalid-rest-trailing-comma/input.js b/packages/babel-parser/test/fixtures/es2015/arrow-functions/params-invalid-rest-trailing-comma/input.js deleted file mode 100644 index d55ef5bce0..0000000000 --- a/packages/babel-parser/test/fixtures/es2015/arrow-functions/params-invalid-rest-trailing-comma/input.js +++ /dev/null @@ -1 +0,0 @@ -(...a,) => {}; diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/277/options.json b/packages/babel-parser/test/fixtures/es2015/uncategorised/277/options.json index b8808d8a68..029befceda 100644 --- a/packages/babel-parser/test/fixtures/es2015/uncategorised/277/options.json +++ b/packages/babel-parser/test/fixtures/es2015/uncategorised/277/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (1:18)" + "throws": "The rest parameter must be the last parameter (1:18)" } diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/283/options.json b/packages/babel-parser/test/fixtures/es2015/uncategorised/283/options.json index 263bbbb080..3ead3a4299 100644 --- a/packages/babel-parser/test/fixtures/es2015/uncategorised/283/options.json +++ b/packages/babel-parser/test/fixtures/es2015/uncategorised/283/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (1:5)" + "throws": "The rest parameter must be the last parameter (1:5)" } diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/292/input.js b/packages/babel-parser/test/fixtures/es2015/uncategorised/292/input.js deleted file mode 100644 index e15ba6bf99..0000000000 --- a/packages/babel-parser/test/fixtures/es2015/uncategorised/292/input.js +++ /dev/null @@ -1 +0,0 @@ -[...a, ] = b \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/292/output.json b/packages/babel-parser/test/fixtures/es2015/uncategorised/292/output.json deleted file mode 100644 index 6a07099613..0000000000 --- a/packages/babel-parser/test/fixtures/es2015/uncategorised/292/output.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "type": "File", - "start": 0, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "program": { - "type": "Program", - "start": 0, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "sourceType": "script", - "interpreter": null, - "body": [ - { - "type": "ExpressionStatement", - "start": 0, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "expression": { - "type": "AssignmentExpression", - "start": 0, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "operator": "=", - "left": { - "type": "ArrayPattern", - "start": 0, - "end": 8, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 8 - } - }, - "elements": [ - { - "type": "RestElement", - "start": 1, - "end": 5, - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 5 - } - }, - "argument": { - "type": "Identifier", - "start": 4, - "end": 5, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 5 - }, - "identifierName": "a" - }, - "name": "a" - } - } - ] - }, - "right": { - "type": "Identifier", - "start": 11, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 12 - }, - "identifierName": "b" - }, - "name": "b" - } - } - } - ], - "directives": [] - } -} \ No newline at end of file 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 52560b0a85..231d5fccd5 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": "A trailing comma is not permitted after the rest element (1:11)" + "throws": "A trailing comma is not permitted after the rest parameter (1:11)" } diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/7/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/7/options.json index 09b3275eae..253a786581 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/7/options.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/7/options.json @@ -1,3 +1,3 @@ { - "throws": "The rest element has to be the last element when destructuring (1:10)" + "throws": "The rest property must be the last property (1:10)" } 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 4a97ac85ea..e5efb19664 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": "A trailing comma is not permitted after the rest element (1:16)" + "throws": "A trailing comma is not permitted after the rest property (1:16)" } diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/9/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/9/options.json index 03ba1e37e8..e1bf843ed1 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/9/options.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/9/options.json @@ -1,3 +1,3 @@ { - "throws": "Cannot have multiple rest elements when destructuring (1:13)" + "throws": "The rest property must be the last property (1:13)" } diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/input.js new file mode 100644 index 0000000000..aef29a7f3b --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/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-rest/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/options.json new file mode 100644 index 0000000000..a19bb078b1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/options.json @@ -0,0 +1,3 @@ +{ + "throws": "A trailing comma is not permitted after the rest property (1:6)" +} diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/input.js b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/input.js new file mode 100644 index 0000000000..d8dd574f40 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/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/output.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json new file mode 100644 index 0000000000..ffb978345c --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json @@ -0,0 +1,103 @@ +{ + "type": "File", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "expression": { + "type": "ObjectExpression", + "start": 1, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "properties": [ + { + "type": "SpreadElement", + "start": 2, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 2 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "argument": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "a" + }, + "name": "a" + } + } + ], + "extra": { + "parenthesized": true, + "parenStart": 0 + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/options.json b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/options.json index d2981263bf..015adf82cd 100644 --- a/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/options.json +++ b/packages/babel-parser/test/fixtures/es2018/object-rest-spread/expression-rest-not-last-invalid/options.json @@ -1,3 +1,3 @@ { - "throws": "The rest element has to be the last element when destructuring (1:2)" + "throws": "The rest property must be the last property (1:2)" } diff --git a/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/arrow-with-multiple-rest/options.json b/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/arrow-with-multiple-rest/options.json index 263bbbb080..3ead3a4299 100644 --- a/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/arrow-with-multiple-rest/options.json +++ b/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/arrow-with-multiple-rest/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (1:5)" + "throws": "The rest parameter must be the last parameter (1:5)" } diff --git a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0258/options.json b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0258/options.json index b8808d8a68..029befceda 100644 --- a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0258/options.json +++ b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0258/options.json @@ -1,3 +1,3 @@ { - "throws": "Rest parameter must be last formal parameter (1:18)" + "throws": "The rest parameter must be the last parameter (1:18)" } diff --git a/packages/babel-parser/test/fixtures/typescript/types/tuple-rest-invalid/options.json b/packages/babel-parser/test/fixtures/typescript/types/tuple-rest-invalid/options.json index 653f8ee827..a500c245e7 100644 --- a/packages/babel-parser/test/fixtures/typescript/types/tuple-rest-invalid/options.json +++ b/packages/babel-parser/test/fixtures/typescript/types/tuple-rest-invalid/options.json @@ -1,5 +1,5 @@ { "sourceType": "module", "plugins": ["typescript"], - "throws": "A rest element must be last in a tuple type. (1:8)" + "throws": "The rest type must be the last type (1:19)" } diff --git a/scripts/tests/test262/test262_whitelist.txt b/scripts/tests/test262/test262_whitelist.txt index 603c65360c..e0b544e952 100644 --- a/scripts/tests/test262/test262_whitelist.txt +++ b/scripts/tests/test262/test262_whitelist.txt @@ -649,10 +649,6 @@ language/block-scope/syntax/redeclaration/var-redeclaration-attempt-after-let.js language/block-scope/syntax/redeclaration/var-redeclaration-attempt-after-let.js(strict mode) language/expressions/assignment/destructuring/obj-prop-__proto__dup.js(default) language/expressions/assignment/destructuring/obj-prop-__proto__dup.js(strict mode) -language/expressions/assignment/dstr/array-rest-before-elision.js(default) -language/expressions/assignment/dstr/array-rest-before-elision.js(strict mode) -language/expressions/assignment/dstr/array-rest-elision-invalid.js(default) -language/expressions/assignment/dstr/array-rest-elision-invalid.js(strict mode) language/expressions/assignment/dstr/obj-id-identifier-yield-ident-valid.js(default) language/expressions/async-arrow-function/await-as-param-ident-nested-arrow-parameter-position.js(default) language/expressions/async-arrow-function/await-as-param-ident-nested-arrow-parameter-position.js(strict mode)