Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 263e16aab8910925dec24d3ac121710344fb3929..5be0527f84a805324866289d30a387f734462e66 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -1528,7 +1528,7 @@ class PreParserTraits { |
| V8_INLINE void ParseArrowFunctionFormalParameters( |
| Scope* scope, PreParserExpression expression, |
| - const Scanner::Location& params_loc, bool* is_rest, |
| + const Scanner::Location& params_loc, bool* has_rest, |
| Scanner::Location* duplicate_loc, bool* ok); |
| struct TemplateLiteralState {}; |
| @@ -1752,7 +1752,7 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, |
| void PreParserTraits::ParseArrowFunctionFormalParameters( |
| Scope* scope, PreParserExpression params, |
| - const Scanner::Location& params_loc, bool* is_rest, |
| + const Scanner::Location& params_loc, bool* has_rest, |
| Scanner::Location* duplicate_loc, bool* ok) { |
| // TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter |
| // lists that are too long. |
| @@ -2159,6 +2159,24 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| bool has_rest = false; |
| result = this->ParseArrowFunctionLiteral(scope, has_rest, |
| args_classifier, CHECK_OK); |
| + } else if (allow_harmony_arrow_functions() && |
| + allow_harmony_rest_params() && Check(Token::ELLIPSIS)) { |
| + // (...x) => y |
| + Scope* scope = |
| + this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); |
| + scope->set_start_position(beg_pos); |
| + ExpressionClassifier args_classifier; |
| + const bool has_rest = true; |
| + this->ParseFormalParameter(scope, has_rest, &args_classifier, CHECK_OK); |
| + if (peek() == Token::COMMA) { |
| + ReportMessageAt(scanner()->peek_location(), |
| + MessageTemplate::kParamAfterRest); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + Expect(Token::RPAREN, CHECK_OK); |
| + result = this->ParseArrowFunctionLiteral(scope, has_rest, |
| + args_classifier, CHECK_OK); |
| } else { |
| // Heuristically try to detect immediately called functions before |
| // seeing the call parentheses. |
| @@ -2239,11 +2257,29 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); |
| classifier->Accumulate(binding_classifier, |
| ExpressionClassifier::AllProductions); |
| - while (peek() == Token::COMMA) { |
| - Expect(Token::COMMA, CHECK_OK); |
| + bool seen_rest = false; |
| + while (Check(Token::COMMA)) { |
| + if (seen_rest) { |
| + // Seeing the first rest param meant that this form wasn't a valid |
| + // expression or pattern. Now we know it's not a valid formal parameter |
| + // list either. |
| + ReportMessageAt(scanner()->peek_location(), |
|
rossberg
2015/06/10 13:43:53
Nit: Should this really be an eager error here? It
caitp (gmail)
2015/06/10 14:30:49
We should mark it in the expression classifier ins
|
| + MessageTemplate::kParamAfterRest); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + if (allow_harmony_rest_params() && Check(Token::ELLIPSIS)) { |
| + // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only |
| + // as the formal parameters of'(x, y, ...z) => foo', and is not itself a |
| + // valid expression or binding pattern. |
| + ExpressionUnexpectedToken(classifier); |
| + BindingPatternUnexpectedToken(classifier); |
| + seen_rest = true; |
| + } |
| int pos = position(); |
| ExpressionT right = this->ParseAssignmentExpression( |
| accept_IN, &binding_classifier, CHECK_OK); |
| + if (seen_rest) right = factory()->NewSpread(right, pos); |
| classifier->Accumulate(binding_classifier, |
| ExpressionClassifier::AllProductions); |
| result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); |
| @@ -2671,7 +2707,6 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| } |
| ExpressionT expression = this->ParseConditionalExpression( |
| accept_IN, &arrow_formals_classifier, CHECK_OK); |
| - classifier->Accumulate(arrow_formals_classifier); |
| if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { |
| checkpoint.Restore(); |
| @@ -2679,11 +2714,11 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| ValidateArrowFormalParameters(&arrow_formals_classifier, expression, |
| CHECK_OK); |
| Scanner::Location loc(lhs_location.beg_pos, scanner()->location().end_pos); |
| - bool has_rest = false; |
| Scope* scope = |
| this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); |
| scope->set_start_position(lhs_location.beg_pos); |
| Scanner::Location duplicate_loc = Scanner::Location::invalid(); |
| + bool has_rest = false; |
| this->ParseArrowFunctionFormalParameters(scope, expression, loc, &has_rest, |
| &duplicate_loc, CHECK_OK); |
| if (duplicate_loc.IsValid()) { |
| @@ -2698,7 +2733,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| // "expression" was not itself an arrow function parameter list, but it might |
| // form part of one. Propagate speculative formal parameter error locations. |
| classifier->Accumulate(arrow_formals_classifier, |
| - ExpressionClassifier::FormalParametersProductions); |
| + ExpressionClassifier::StandardProductions | |
| + ExpressionClassifier::FormalParametersProductions); |
| if (!Token::IsAssignmentOp(peek())) { |
| if (fni_ != NULL) fni_->Leave(); |