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
This commit is contained in:
Nicolò Ribaudo 2019-10-08 23:08:50 +02:00 committed by GitHub
parent c7add11fdc
commit 34937f13d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 226 additions and 100 deletions

View File

@ -168,9 +168,6 @@ export default class ExpressionParser extends LValParser {
} }
} }
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
this.state.commaAfterSpreadAt = -1;
let failOnShorthandAssign; let failOnShorthandAssign;
if (refShorthandDefaultPos) { if (refShorthandDefaultPos) {
failOnShorthandAssign = false; failOnShorthandAssign = false;
@ -230,9 +227,6 @@ export default class ExpressionParser extends LValParser {
); );
} }
if (patternErrorMsg) this.checkCommaAfterRestFromSpread();
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
this.next(); this.next();
node.right = this.parseMaybeAssign(noIn); node.right = this.parseMaybeAssign(noIn);
return this.finishNode(node, "AssignmentExpression"); return this.finishNode(node, "AssignmentExpression");
@ -240,8 +234,6 @@ export default class ExpressionParser extends LValParser {
this.unexpected(refShorthandDefaultPos.start); this.unexpected(refShorthandDefaultPos.start);
} }
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
return left; return left;
} }
@ -680,14 +672,12 @@ export default class ExpressionParser extends LValParser {
let node = this.startNodeAt(startPos, startLoc); let node = this.startNodeAt(startPos, startLoc);
node.callee = base; node.callee = base;
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
this.state.commaAfterSpreadAt = -1;
node.arguments = this.parseCallExpressionArguments( node.arguments = this.parseCallExpressionArguments(
tt.parenR, tt.parenR,
state.maybeAsyncArrow, state.maybeAsyncArrow,
base.type === "Import", base.type === "Import",
base.type !== "Super", base.type !== "Super",
node,
); );
if (!state.optionalChainMember) { if (!state.optionalChainMember) {
this.finishCallExpression(node); this.finishCallExpression(node);
@ -698,8 +688,6 @@ export default class ExpressionParser extends LValParser {
if (state.maybeAsyncArrow && this.shouldParseAsyncArrow()) { if (state.maybeAsyncArrow && this.shouldParseAsyncArrow()) {
state.stop = true; state.stop = true;
this.checkCommaAfterRestFromSpread();
node = this.parseAsyncArrowFromCallExpression( node = this.parseAsyncArrowFromCallExpression(
this.startNodeAt(startPos, startLoc), this.startNodeAt(startPos, startLoc),
node, node,
@ -743,7 +731,6 @@ export default class ExpressionParser extends LValParser {
} }
this.state.maybeInArrowParameters = oldMaybeInArrowParameters; this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
return node; return node;
} else if (this.match(tt.backQuote)) { } else if (this.match(tt.backQuote)) {
@ -825,6 +812,7 @@ export default class ExpressionParser extends LValParser {
possibleAsyncArrow: boolean, possibleAsyncArrow: boolean,
dynamicImport?: boolean, dynamicImport?: boolean,
allowPlaceholder?: boolean, allowPlaceholder?: boolean,
nodeForExtra?: ?N.Node,
): $ReadOnlyArray<?N.Expression> { ): $ReadOnlyArray<?N.Expression> {
const elts = []; const elts = [];
let innerParenStart; let innerParenStart;
@ -837,13 +825,21 @@ export default class ExpressionParser extends LValParser {
first = false; first = false;
} else { } else {
this.expect(tt.comma); this.expect(tt.comma);
if (this.eat(close)) { if (this.match(close)) {
if (dynamicImport) { if (dynamicImport) {
this.raise( this.raise(
this.state.lastTokStart, this.state.lastTokStart,
"Trailing comma is disallowed inside import(...) arguments", "Trailing comma is disallowed inside import(...) arguments",
); );
} }
if (nodeForExtra) {
this.addExtra(
nodeForExtra,
"trailingComma",
this.state.lastTokStart,
);
}
this.next();
break; break;
} }
} }
@ -883,7 +879,12 @@ export default class ExpressionParser extends LValParser {
call: N.CallExpression, call: N.CallExpression,
): N.ArrowFunctionExpression { ): N.ArrowFunctionExpression {
this.expect(tt.arrow); this.expect(tt.arrow);
this.parseArrowExpression(node, call.arguments, true); this.parseArrowExpression(
node,
call.arguments,
true,
call.extra?.trailingComma,
);
return node; return node;
} }
@ -1046,6 +1047,7 @@ export default class ExpressionParser extends LValParser {
tt.bracketR, tt.bracketR,
true, true,
refShorthandDefaultPos, refShorthandDefaultPos,
node,
); );
if (!this.state.maybeInArrowParameters) { if (!this.state.maybeInArrowParameters) {
// This could be an array pattern: // This could be an array pattern:
@ -1289,7 +1291,7 @@ export default class ExpressionParser extends LValParser {
), ),
); );
this.checkCommaAfterRest(); this.checkCommaAfterRest(charCodes.rightParenthesis);
break; break;
} else { } else {
@ -1504,7 +1506,11 @@ export default class ExpressionParser extends LValParser {
first = false; first = false;
} else { } else {
this.expect(tt.comma); 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); const prop = this.parseObjectMember(isPattern, refShorthandDefaultPos);
@ -1572,7 +1578,7 @@ export default class ExpressionParser extends LValParser {
this.next(); this.next();
// Don't use parseRestBinding() as we only allow Identifier here. // Don't use parseRestBinding() as we only allow Identifier here.
prop.argument = this.parseIdentifier(); prop.argument = this.parseIdentifier();
this.checkCommaAfterRest(); this.checkCommaAfterRest(charCodes.rightCurlyBrace);
return this.finishNode(prop, "RestElement"); return this.finishNode(prop, "RestElement");
} }
@ -1856,6 +1862,7 @@ export default class ExpressionParser extends LValParser {
node: N.ArrowFunctionExpression, node: N.ArrowFunctionExpression,
params: ?(N.Expression[]), params: ?(N.Expression[]),
isAsync: boolean, isAsync: boolean,
trailingCommaPos: ?number,
): N.ArrowFunctionExpression { ): N.ArrowFunctionExpression {
this.scope.enter(functionFlags(isAsync, false) | SCOPE_ARROW); this.scope.enter(functionFlags(isAsync, false) | SCOPE_ARROW);
this.initFunction(node, isAsync); this.initFunction(node, isAsync);
@ -1867,7 +1874,7 @@ export default class ExpressionParser extends LValParser {
this.state.yieldPos = -1; this.state.yieldPos = -1;
this.state.awaitPos = -1; this.state.awaitPos = -1;
if (params) this.setArrowFunctionParameters(node, params); if (params) this.setArrowFunctionParameters(node, params, trailingCommaPos);
this.parseFunctionBody(node, true); this.parseFunctionBody(node, true);
this.scope.exit(); this.scope.exit();
@ -1881,11 +1888,13 @@ export default class ExpressionParser extends LValParser {
setArrowFunctionParameters( setArrowFunctionParameters(
node: N.ArrowFunctionExpression, node: N.ArrowFunctionExpression,
params: N.Expression[], params: N.Expression[],
trailingCommaPos: ?number,
): void { ): void {
node.params = this.toAssignableList( node.params = this.toAssignableList(
params, params,
true, true,
"arrow function parameters", "arrow function parameters",
trailingCommaPos,
); );
} }
@ -2012,6 +2021,7 @@ export default class ExpressionParser extends LValParser {
close: TokenType, close: TokenType,
allowEmpty?: boolean, allowEmpty?: boolean,
refShorthandDefaultPos?: ?Pos, refShorthandDefaultPos?: ?Pos,
nodeForExtra?: ?N.Node,
): $ReadOnlyArray<?N.Expression> { ): $ReadOnlyArray<?N.Expression> {
const elts = []; const elts = [];
let first = true; let first = true;
@ -2021,7 +2031,17 @@ export default class ExpressionParser extends LValParser {
first = false; first = false;
} else { } else {
this.expect(tt.comma); 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)); elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos));

View File

@ -1,5 +1,6 @@
// @flow // @flow
import * as charCodes from "charcodes";
import { types as tt, type TokenType } from "../tokenizer/types"; import { types as tt, type TokenType } from "../tokenizer/types";
import type { import type {
TSParameterProperty, TSParameterProperty,
@ -60,6 +61,14 @@ export default class LValParser extends NodeUtils {
const prop = node.properties[i]; const prop = node.properties[i];
const isLast = i === last; const isLast = i === last;
this.toAssignableObjectExpressionProp(prop, isBinding, isLast); this.toAssignableObjectExpressionProp(prop, isBinding, isLast);
if (
isLast &&
prop.type === "RestElement" &&
node.extra?.trailingComma
) {
this.raiseRestNotLast(node.extra.trailingComma);
}
} }
break; break;
@ -78,7 +87,12 @@ export default class LValParser extends NodeUtils {
case "ArrayExpression": case "ArrayExpression":
node.type = "ArrayPattern"; node.type = "ArrayPattern";
this.toAssignableList(node.elements, isBinding, contextDescription); this.toAssignableList(
node.elements,
isBinding,
contextDescription,
node.extra?.trailingComma,
);
break; break;
case "AssignmentExpression": case "AssignmentExpression":
@ -142,6 +156,7 @@ export default class LValParser extends NodeUtils {
exprList: Expression[], exprList: Expression[],
isBinding: ?boolean, isBinding: ?boolean,
contextDescription: string, contextDescription: string,
trailingCommaPos?: ?number,
): $ReadOnlyArray<Pattern> { ): $ReadOnlyArray<Pattern> {
let end = exprList.length; let end = exprList.length;
if (end) { if (end) {
@ -160,6 +175,11 @@ export default class LValParser extends NodeUtils {
) { ) {
this.unexpected(arg.start); this.unexpected(arg.start);
} }
if (trailingCommaPos) {
this.raiseTrailingCommaAfterRest(trailingCommaPos);
}
--end; --end;
} }
} }
@ -213,11 +233,6 @@ export default class LValParser extends NodeUtils {
undefined, undefined,
refNeedsArrowPos, refNeedsArrowPos,
); );
if (this.state.commaAfterSpreadAt === -1 && this.match(tt.comma)) {
this.state.commaAfterSpreadAt = this.state.start;
}
return this.finishNode(node, "SpreadElement"); return this.finishNode(node, "SpreadElement");
} }
@ -234,7 +249,11 @@ export default class LValParser extends NodeUtils {
case tt.bracketL: { case tt.bracketL: {
const node = this.startNode(); const node = this.startNode();
this.next(); this.next();
node.elements = this.parseBindingList(tt.bracketR, true); node.elements = this.parseBindingList(
tt.bracketR,
charCodes.rightSquareBracket,
true,
);
return this.finishNode(node, "ArrayPattern"); return this.finishNode(node, "ArrayPattern");
} }
@ -247,6 +266,7 @@ export default class LValParser extends NodeUtils {
parseBindingList( parseBindingList(
close: TokenType, close: TokenType,
closeCharCode: $Values<typeof charCodes>,
allowEmpty?: boolean, allowEmpty?: boolean,
allowModifiers?: boolean, allowModifiers?: boolean,
): $ReadOnlyArray<Pattern | TSParameterProperty> { ): $ReadOnlyArray<Pattern | TSParameterProperty> {
@ -265,7 +285,7 @@ export default class LValParser extends NodeUtils {
break; break;
} else if (this.match(tt.ellipsis)) { } else if (this.match(tt.ellipsis)) {
elts.push(this.parseAssignableListItemTypes(this.parseRestBinding())); elts.push(this.parseAssignableListItemTypes(this.parseRestBinding()));
this.checkCommaAfterRest(); this.checkCommaAfterRest(closeCharCode);
this.expect(close); this.expect(close);
break; break;
} else { } else {
@ -455,19 +475,21 @@ export default class LValParser extends NodeUtils {
} }
} }
checkCommaAfterRest(): void { checkCommaAfterRest(close: $Values<typeof charCodes>): void {
if (this.match(tt.comma)) { if (this.match(tt.comma)) {
this.raiseRestNotLast(this.state.start); if (this.lookaheadCharCode() === close) {
} this.raiseTrailingCommaAfterRest(this.state.start);
} } else {
this.raiseRestNotLast(this.state.start);
checkCommaAfterRestFromSpread(): void { }
if (this.state.commaAfterSpreadAt > -1) {
this.raiseRestNotLast(this.state.commaAfterSpreadAt);
} }
} }
raiseRestNotLast(pos: number) { raiseRestNotLast(pos: number) {
this.raise(pos, `Rest element must be last element`); this.raise(pos, `Rest element must be last element`);
} }
raiseTrailingCommaAfterRest(pos: number) {
this.raise(pos, `Unexpected trailing comma after rest element`);
}
} }

View File

@ -1105,6 +1105,7 @@ export default class StatementParser extends ExpressionParser {
this.expect(tt.parenL); this.expect(tt.parenL);
node.params = this.parseBindingList( node.params = this.parseBindingList(
tt.parenR, tt.parenR,
charCodes.rightParenthesis,
/* allowEmpty */ false, /* allowEmpty */ false,
allowModifiers, allowModifiers,
); );

View File

@ -1798,6 +1798,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
((node.params: any): N.Expression[]), ((node.params: any): N.Expression[]),
true, true,
"arrow function parameters", "arrow function parameters",
node.extra?.trailingComma,
); );
// Enter scope, as checkParams defines bindings // Enter scope, as checkParams defines bindings
this.scope.enter(functionFlags(false, false) | SCOPE_ARROW); this.scope.enter(functionFlags(false, false) | SCOPE_ARROW);
@ -1820,6 +1821,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
((node.params: any): N.Expression[]), ((node.params: any): N.Expression[]),
true, true,
"arrow function parameters", "arrow function parameters",
node.extra?.trailingComma,
); );
} }
return [arrows, []]; return [arrows, []];
@ -1831,6 +1833,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
((node.params: any): N.Expression[]), ((node.params: any): N.Expression[]),
true, true,
"arrow function parameters", "arrow function parameters",
node.extra?.trailingComma,
); );
return true; return true;
} catch (err) { } catch (err) {
@ -2005,6 +2008,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
exprList: N.Expression[], exprList: N.Expression[],
isBinding: ?boolean, isBinding: ?boolean,
contextDescription: string, contextDescription: string,
trailingCommaPos?: ?number,
): $ReadOnlyArray<N.Pattern> { ): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) { for (let i = 0; i < exprList.length; i++) {
const expr = exprList[i]; const expr = exprList[i];
@ -2012,7 +2016,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
exprList[i] = this.typeCastToParameter(expr); 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 // this is a list of nodes, from something like a call expression, we need to filter the

View File

@ -363,21 +363,23 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseBindingListForSignature(): $ReadOnlyArray< tsParseBindingListForSignature(): $ReadOnlyArray<
N.Identifier | N.RestElement | N.ObjectPattern | N.ArrayPattern, N.Identifier | N.RestElement | N.ObjectPattern | N.ArrayPattern,
> { > {
return this.parseBindingList(tt.parenR).map(pattern => { return this.parseBindingList(tt.parenR, charCodes.rightParenthesis).map(
if ( pattern => {
pattern.type !== "Identifier" && if (
pattern.type !== "RestElement" && pattern.type !== "Identifier" &&
pattern.type !== "ObjectPattern" && pattern.type !== "RestElement" &&
pattern.type !== "ArrayPattern" pattern.type !== "ObjectPattern" &&
) { pattern.type !== "ArrayPattern"
throw this.unexpected( ) {
pattern.start, throw this.unexpected(
"Name in a signature must be an Identifier, ObjectPattern or ArrayPattern," + pattern.start,
`instead got ${pattern.type}`, "Name in a signature must be an Identifier, ObjectPattern or ArrayPattern," +
); `instead got ${pattern.type}`,
} );
return pattern; }
}); return pattern;
},
);
} }
tsParseTypeMemberSemicolon(): void { tsParseTypeMemberSemicolon(): void {
@ -586,7 +588,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const restNode: N.TsRestType = this.startNode(); const restNode: N.TsRestType = this.startNode();
this.next(); // skips ellipsis this.next(); // skips ellipsis
restNode.typeAnnotation = this.tsParseType(); restNode.typeAnnotation = this.tsParseType();
this.checkCommaAfterRest(); this.checkCommaAfterRest(charCodes.rightSquareBracket);
return this.finishNode(restNode, "TSRestType"); return this.finishNode(restNode, "TSRestType");
} }
@ -2363,11 +2365,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
} }
toAssignableList( toAssignableList(exprList: N.Expression[]): $ReadOnlyArray<N.Pattern> {
exprList: N.Expression[],
isBinding: ?boolean,
contextDescription: string,
): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) { for (let i = 0; i < exprList.length; i++) {
const expr = exprList[i]; const expr = exprList[i];
if (!expr) continue; if (!expr) continue;
@ -2384,7 +2382,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
break; break;
} }
} }
return super.toAssignableList(exprList, isBinding, contextDescription); return super.toAssignableList(...arguments);
} }
typeCastToParameter(node: N.TsTypeCastExpression): N.Node { typeCastToParameter(node: N.TsTypeCastExpression): N.Node {

View File

@ -55,11 +55,6 @@ export default class State {
// ^ // ^
noArrowParamsConversionAt: number[] = []; 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 // Flags to track
inParameters: boolean = false; inParameters: boolean = false;
maybeInArrowParameters: boolean = false; maybeInArrowParameters: boolean = false;

View File

@ -373,7 +373,10 @@
} }
] ]
} }
] ],
"extra": {
"trailingComma": 140
}
} }
} }
], ],
@ -494,7 +497,10 @@
} }
] ]
} }
] ],
"extra": {
"trailingComma": 200
}
} }
} }
], ],

View File

@ -74,6 +74,9 @@
}, },
"name": "fn" "name": "fn"
}, },
"extra": {
"trailingComma": 11
},
"arguments": [ "arguments": [
{ {
"type": "Identifier", "type": "Identifier",

View File

@ -74,6 +74,9 @@
}, },
"name": "fn" "name": "fn"
}, },
"extra": {
"trailingComma": 7
},
"arguments": [ "arguments": [
{ {
"type": "Identifier", "type": "Identifier",

View File

@ -181,6 +181,9 @@
} }
} }
], ],
"extra": {
"trailingComma": 35
},
"trailingComments": [ "trailingComments": [
{ {
"type": "CommentBlock", "type": "CommentBlock",

View File

@ -309,7 +309,10 @@
} }
] ]
} }
] ],
"extra": {
"trailingComma": 66
}
} }
} }
], ],

View File

@ -163,7 +163,10 @@
} }
] ]
} }
] ],
"extra": {
"trailingComma": 13
}
} }
}, },
"trailingComments": [ "trailingComments": [

View File

@ -110,7 +110,10 @@
}, },
"value": 42 "value": 42
} }
] ],
"extra": {
"trailingComma": 8
}
} }
} }
} }

View File

@ -150,7 +150,10 @@
}, },
"value": 3 "value": 3
} }
] ],
"extra": {
"trailingComma": 13
}
} }
} }
} }

View File

@ -151,7 +151,10 @@
}, },
"value": 3 "value": 3
} }
] ],
"extra": {
"trailingComma": 14
}
} }
} }
} }

View File

@ -1,3 +1,3 @@
{ {
"throws": "Rest element must be last element (1:5)" "throws": "Unexpected trailing comma after rest element (1:5)"
} }

View File

@ -0,0 +1 @@
for ([...a,] in []);

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected trailing comma after rest element (1:10)"
}

View File

@ -0,0 +1 @@
[[...a,]] = [];

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected trailing comma after rest element (1:6)"
}

View File

@ -90,7 +90,10 @@
"name": "a" "name": "a"
} }
} }
] ],
"extra": {
"trailingComma": 5
}
} }
} }
], ],

View File

@ -1,3 +1,3 @@
{ {
"throws": "Rest element must be last element (1:8)" "throws": "Unexpected trailing comma after rest element (1:8)"
} }

View File

@ -91,7 +91,10 @@
"name": "x" "name": "x"
}, },
null null
] ],
"extra": {
"trailingComma": 3
}
}, },
"right": { "right": {
"type": "NumericLiteral", "type": "NumericLiteral",

View File

@ -1,3 +1,3 @@
{ {
"throws": "Rest element must be last element (1:11)" "throws": "Unexpected trailing comma after rest element (1:11)"
} }

View File

@ -74,6 +74,9 @@
}, },
"name": "log" "name": "log"
}, },
"extra": {
"trailingComma": 13
},
"arguments": [ "arguments": [
{ {
"type": "Identifier", "type": "Identifier",

View File

@ -183,7 +183,10 @@
"shorthand": true "shorthand": true
} }
} }
] ],
"extra": {
"trailingComma": 10
}
}, },
"init": { "init": {
"type": "Identifier", "type": "Identifier",

View File

@ -289,6 +289,7 @@
} }
], ],
"extra": { "extra": {
"trailingComma": 21,
"parenthesized": true, "parenthesized": true,
"parenStart": 0 "parenStart": 0
} }

View File

@ -1,3 +1,3 @@
{ {
"throws": "Rest element must be last element (1:16)" "throws": "Unexpected trailing comma after rest element (1:16)"
} }

View File

@ -0,0 +1 @@
for ({...a,} in []);

View File

@ -0,0 +1,3 @@
{
"throws": "Rest element must be last element (1:10)"
}

View File

@ -0,0 +1 @@
[{...a,}] = [];

View File

@ -0,0 +1,3 @@
{
"throws": "Rest element must be last element (1:6)"
}

View File

@ -92,6 +92,7 @@
} }
], ],
"extra": { "extra": {
"trailingComma": 6,
"parenthesized": true, "parenthesized": true,
"parenStart": 0 "parenStart": 0
} }

View File

@ -78,7 +78,10 @@
"elements": [ "elements": [
null, null,
null null
] ],
"extra": {
"trailingComma": 3
}
} }
], ],
"body": { "body": {

View File

@ -75,7 +75,10 @@
"elements": [ "elements": [
null, null,
null null
] ],
"extra": {
"trailingComma": 2
}
}, },
"right": { "right": {
"type": "NumericLiteral", "type": "NumericLiteral",

View File

@ -166,6 +166,7 @@
} }
], ],
"extra": { "extra": {
"trailingComma": 33,
"parenthesized": true, "parenthesized": true,
"parenStart": 0 "parenStart": 0
} }

View File

@ -169,6 +169,7 @@
} }
], ],
"extra": { "extra": {
"trailingComma": 35,
"parenthesized": true, "parenthesized": true,
"parenStart": 0 "parenStart": 0
} }

View File

@ -128,7 +128,10 @@
"shorthand": true "shorthand": true
} }
} }
] ],
"extra": {
"trailingComma": 6
}
}, },
"init": { "init": {
"type": "NumericLiteral", "type": "NumericLiteral",

View File

@ -110,7 +110,10 @@
}, },
"value": 42 "value": 42
} }
] ],
"extra": {
"trailingComma": 8
}
} }
} }
} }

View File

@ -150,7 +150,10 @@
}, },
"value": 3 "value": 3
} }
] ],
"extra": {
"trailingComma": 13
}
} }
} }
} }

View File

@ -151,7 +151,10 @@
}, },
"value": 3 "value": 3
} }
] ],
"extra": {
"trailingComma": 14
}
} }
} }
} }

View File

@ -1,3 +1,3 @@
{ {
"throws": "Trailing comma is disallowed inside import(...) arguments (1:13)" "throws": "Trailing comma is disallowed inside import(...) arguments (1:12)"
} }

View File

@ -157,7 +157,10 @@
}, },
"value": 123 "value": 123
} }
] ],
"extra": {
"trailingComma": 24
}
} }
} }
], ],

View File

@ -187,7 +187,6 @@
"column": 23 "column": 23
} }
}, },
"attributes": [],
"name": { "name": {
"type": "JSXIdentifier", "type": "JSXIdentifier",
"start": 29, "start": 29,
@ -204,6 +203,7 @@
}, },
"name": "Foo" "name": "Foo"
}, },
"attributes": [],
"selfClosing": true "selfClosing": true
}, },
"closingElement": null, "closingElement": null,
@ -263,7 +263,10 @@
] ]
} }
} }
] ],
"extra": {
"trailingComma": 39
}
} }
} }
], ],

View File

@ -450,7 +450,10 @@
] ]
} }
} }
] ],
"extra": {
"trailingComma": 77
}
} }
} }
], ],

View File

@ -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(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-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(default)
language/statements/class/elements/syntax/early-errors/invalid-names/method-outter-member-expression-this.js(strict mode) 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)