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, ...@@ -2988,6 +2988,7 @@ ParserBase<Traits>::ParseConditionalExpression(bool accept_IN,
ExpressionT expression = ExpressionT expression =
this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK); this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK);
if (peek() != Token::CONDITIONAL) return expression; if (peek() != Token::CONDITIONAL) return expression;
ArrowFormalParametersUnexpectedToken(classifier);
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
Consume(Token::CONDITIONAL); Consume(Token::CONDITIONAL);
// In parsing the first assignment expression in conditional // In parsing the first assignment expression in conditional
...@@ -3013,6 +3014,7 @@ ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, ...@@ -3013,6 +3014,7 @@ ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN,
// prec1 >= 4 // prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) { while (Precedence(peek(), accept_IN) == prec1) {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Token::Value op = Next(); Token::Value op = Next();
Scanner::Location op_location = scanner()->location(); Scanner::Location op_location = scanner()->location();
int pos = position(); int pos = position();
...@@ -3075,6 +3077,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, ...@@ -3075,6 +3077,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
Token::Value op = peek(); Token::Value op = peek();
if (Token::IsUnaryOp(op)) { if (Token::IsUnaryOp(op)) {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
op = Next(); op = Next();
int pos = position(); int pos = position();
...@@ -3097,6 +3100,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, ...@@ -3097,6 +3100,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
return this->BuildUnaryExpression(expression, op, pos, factory()); return this->BuildUnaryExpression(expression, op, pos, factory());
} else if (Token::IsCountOp(op)) { } else if (Token::IsCountOp(op)) {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
op = Next(); op = Next();
int beg_pos = peek_position(); int beg_pos = peek_position();
ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK); ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK);
...@@ -3129,6 +3133,7 @@ ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier, ...@@ -3129,6 +3133,7 @@ ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier,
if (!scanner()->HasAnyLineTerminatorBeforeNext() && if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
Token::IsCountOp(peek())) { Token::IsCountOp(peek())) {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
expression = this->CheckAndRewriteReferenceExpression( expression = this->CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, scanner()->location().end_pos, expression, lhs_beg_pos, scanner()->location().end_pos,
...@@ -3160,6 +3165,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression( ...@@ -3160,6 +3165,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
switch (peek()) { switch (peek()) {
case Token::LBRACK: { case Token::LBRACK: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::LBRACK); Consume(Token::LBRACK);
int pos = position(); int pos = position();
ExpressionT index = ParseExpression(true, classifier, CHECK_OK); ExpressionT index = ParseExpression(true, classifier, CHECK_OK);
...@@ -3170,6 +3176,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression( ...@@ -3170,6 +3176,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
case Token::LPAREN: { case Token::LPAREN: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
if (is_strong(language_mode()) && this->IsIdentifier(result) && if (is_strong(language_mode()) && this->IsIdentifier(result) &&
this->IsEval(this->AsIdentifier(result))) { this->IsEval(this->AsIdentifier(result))) {
...@@ -3231,6 +3238,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression( ...@@ -3231,6 +3238,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
case Token::PERIOD: { case Token::PERIOD: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::PERIOD); Consume(Token::PERIOD);
int pos = position(); int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK); IdentifierT name = ParseIdentifierName(CHECK_OK);
...@@ -3243,6 +3251,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression( ...@@ -3243,6 +3251,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
case Token::TEMPLATE_SPAN: case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL: { case Token::TEMPLATE_TAIL: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK); result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK);
break; break;
} }
...@@ -3280,6 +3289,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( ...@@ -3280,6 +3289,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
if (peek() == Token::NEW) { if (peek() == Token::NEW) {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::NEW); Consume(Token::NEW);
int new_pos = position(); int new_pos = position();
ExpressionT result = this->EmptyExpression(); ExpressionT result = this->EmptyExpression();
...@@ -3333,6 +3343,7 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, ...@@ -3333,6 +3343,7 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
ExpressionT result = this->EmptyExpression(); ExpressionT result = this->EmptyExpression();
if (peek() == Token::FUNCTION) { if (peek() == Token::FUNCTION) {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::FUNCTION); Consume(Token::FUNCTION);
int function_token_position = position(); int function_token_position = position();
...@@ -3576,6 +3587,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( ...@@ -3576,6 +3587,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
switch (peek()) { switch (peek()) {
case Token::LBRACK: { case Token::LBRACK: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::LBRACK); Consume(Token::LBRACK);
int pos = position(); int pos = position();
...@@ -3589,6 +3601,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( ...@@ -3589,6 +3601,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
} }
case Token::PERIOD: { case Token::PERIOD: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
Consume(Token::PERIOD); Consume(Token::PERIOD);
int pos = position(); int pos = position();
...@@ -3603,6 +3616,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( ...@@ -3603,6 +3616,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
case Token::TEMPLATE_SPAN: case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL: { case Token::TEMPLATE_TAIL: {
BindingPatternUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
int pos; int pos;
if (scanner()->current_token() == Token::IDENTIFIER) { if (scanner()->current_token() == Token::IDENTIFIER) {
pos = position(); pos = position();
......
...@@ -3510,6 +3510,67 @@ TEST(UseConstLegacyCount) { ...@@ -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) { TEST(ErrorsArrowFunctions) {
// Tests that parser and preparser generate the same kind of errors // Tests that parser and preparser generate the same kind of errors
// on invalid arrow function syntax. // 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