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
46 changed files with 226 additions and 100 deletions

View File

@@ -1798,6 +1798,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
((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<Parser>): Class<Parser> =>
((node.params: any): N.Expression[]),
true,
"arrow function parameters",
node.extra?.trailingComma,
);
}
return [arrows, []];
@@ -1831,6 +1833,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
((node.params: any): N.Expression[]),
true,
"arrow function parameters",
node.extra?.trailingComma,
);
return true;
} catch (err) {
@@ -2005,6 +2008,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
exprList: N.Expression[],
isBinding: ?boolean,
contextDescription: string,
trailingCommaPos?: ?number,
): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) {
const expr = exprList[i];
@@ -2012,7 +2016,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
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

View File

@@ -363,21 +363,23 @@ export default (superClass: Class<Parser>): Class<Parser> =>
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<Parser>): Class<Parser> =>
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<Parser>): Class<Parser> =>
}
}
toAssignableList(
exprList: N.Expression[],
isBinding: ?boolean,
contextDescription: string,
): $ReadOnlyArray<N.Pattern> {
toAssignableList(exprList: N.Expression[]): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) {
const expr = exprList[i];
if (!expr) continue;
@@ -2384,7 +2382,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
break;
}
}
return super.toAssignableList(exprList, isBinding, contextDescription);
return super.toAssignableList(...arguments);
}
typeCastToParameter(node: N.TsTypeCastExpression): N.Node {