Commit bb43d6c0 authored by wingo's avatar wingo Committed by Commit bot

Fix parsing of arrow function formal parameters

Not all parenthesized AssignmentExpressions whose components are valid
binding patterns are valid arrow function formal parameters.  In
particular (a,b,c)() is not valid, and in general the existing code
wasn't catching the tail productions of ConditionalExpression,
BinaryExpression, PostfixExpression, LeftHandSideExpression,
and MemberExpression.

Thanks to Adrian Perez for the test case.

BUG=v8:4211
LOG=Y
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/1306583002

Cr-Commit-Position: refs/heads/master@{#30286}
parent 371ad73a
......@@ -2988,6 +2988,7 @@ ParserBase<Traits>::ParseConditionalExpression(bool accept_IN,
ExpressionT expression =
this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK);
if (peek() != Token::CONDITIONAL) return expression;
ArrowFormalParametersUnexpectedToken(classifier);
BindingPatternUnexpectedToken(classifier);
Consume(Token::CONDITIONAL);
// In parsing the first assignment expression in conditional
......@@ -3013,6 +3014,7 @@ ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN,
// prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Token::Value op = Next();
Scanner::Location op_location = scanner()->location();
int pos = position();
......@@ -3075,6 +3077,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
Token::Value op = peek();
if (Token::IsUnaryOp(op)) {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
op = Next();
int pos = position();
......@@ -3097,6 +3100,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
return this->BuildUnaryExpression(expression, op, pos, factory());
} else if (Token::IsCountOp(op)) {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
op = Next();
int beg_pos = peek_position();
ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK);
......@@ -3129,6 +3133,7 @@ ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier,
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
Token::IsCountOp(peek())) {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, scanner()->location().end_pos,
......@@ -3160,6 +3165,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
switch (peek()) {
case Token::LBRACK: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::LBRACK);
int pos = position();
ExpressionT index = ParseExpression(true, classifier, CHECK_OK);
......@@ -3170,6 +3176,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
case Token::LPAREN: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
if (is_strong(language_mode()) && this->IsIdentifier(result) &&
this->IsEval(this->AsIdentifier(result))) {
......@@ -3231,6 +3238,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
case Token::PERIOD: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::PERIOD);
int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK);
......@@ -3243,6 +3251,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK);
break;
}
......@@ -3280,6 +3289,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
if (peek() == Token::NEW) {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::NEW);
int new_pos = position();
ExpressionT result = this->EmptyExpression();
......@@ -3333,6 +3343,7 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
ExpressionT result = this->EmptyExpression();
if (peek() == Token::FUNCTION) {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::FUNCTION);
int function_token_position = position();
......@@ -3576,6 +3587,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
switch (peek()) {
case Token::LBRACK: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::LBRACK);
int pos = position();
......@@ -3589,6 +3601,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
}
case Token::PERIOD: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::PERIOD);
int pos = position();
......@@ -3603,6 +3616,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL: {
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
int pos;
if (scanner()->current_token() == Token::IDENTIFIER) {
pos = position();
......
......@@ -3510,6 +3510,67 @@ TEST(UseConstLegacyCount) {
}
TEST(ErrorsArrowFormalParameters) {
const char* context_data[][2] = {
{ "()", "=>{}" },
{ "()", "=>{};" },
{ "var x = ()", "=>{}" },
{ "var x = ()", "=>{};" },
{ "a", "=>{}" },
{ "a", "=>{};" },
{ "var x = a", "=>{}" },
{ "var x = a", "=>{};" },
{ "(a)", "=>{}" },
{ "(a)", "=>{};" },
{ "var x = (a)", "=>{}" },
{ "var x = (a)", "=>{};" },
{ "(...a)", "=>{}" },
{ "(...a)", "=>{};" },
{ "var x = (...a)", "=>{}" },
{ "var x = (...a)", "=>{};" },
{ "(a,b)", "=>{}" },
{ "(a,b)", "=>{};" },
{ "var x = (a,b)", "=>{}" },
{ "var x = (a,b)", "=>{};" },
{ "(a,...b)", "=>{}" },
{ "(a,...b)", "=>{};" },
{ "var x = (a,...b)", "=>{}" },
{ "var x = (a,...b)", "=>{};" },
{ nullptr, nullptr }
};
const char* assignment_expression_suffix_data[] = {
"?c:d=>{}",
"=c=>{}",
"()",
"(c)",
"[1]",
"[c]",
".c",
"-c",
"+c",
"c++",
"`c`",
"`${c}`",
"`template-head${c}`",
"`${c}template-tail`",
"`template-head${c}template-tail`",
"`${c}template-tail`",
nullptr
};
static const ParserFlag always_flags[] = { kAllowHarmonyArrowFunctions,
kAllowHarmonyRestParameters };
RunParserSyncTest(context_data, assignment_expression_suffix_data, kError,
NULL, 0, always_flags, arraysize(always_flags));
}
TEST(ErrorsArrowFunctions) {
// Tests that parser and preparser generate the same kind of errors
// on invalid arrow function syntax.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment