Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 0b00f819abe1f1bcc0543c7f823b8981ee3a2cfb..c4d397cba0a03f57413e919b53a4d05befdaba18 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -527,6 +527,11 @@ class ParserBase : public Traits { |
*ok = false; |
return; |
} |
+ if (is_strict(language_mode) && locs.reserved_.IsValid()) { |
+ Traits::ReportMessageAt(locs.reserved_, "unexpected_strict_reserved"); |
+ *ok = false; |
+ return; |
+ } |
if (is_strong(language_mode) && locs.undefined_.IsValid()) { |
Traits::ReportMessageAt(locs.undefined_, "strong_undefined"); |
*ok = false; |
@@ -539,11 +544,6 @@ class ParserBase : public Traits { |
*ok = false; |
return; |
} |
- if (locs.reserved_.IsValid()) { |
- Traits::ReportMessageAt(locs.reserved_, "unexpected_strict_reserved"); |
- *ok = false; |
- return; |
- } |
} |
// Determine precedence of given token. |
@@ -621,8 +621,9 @@ class ParserBase : public Traits { |
ExpressionT ParseMemberExpression(bool* ok); |
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, |
bool* ok); |
- ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, |
- bool* ok); |
+ ExpressionT ParseArrowFunctionLiteral( |
+ int start_pos, FormalParameterListT params, |
+ const FormalParameterErrorLocations& error_locs, bool has_rest, bool* ok); |
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); |
void AddTemplateExpression(ExpressionT); |
ExpressionT ParseSuperExpression(bool is_new, bool* ok); |
@@ -845,12 +846,6 @@ class PreParserExpression { |
IsValidArrowParamListField::encode(valid_arrow_param_list)); |
} |
- static PreParserExpression EmptyArrowParamList() { |
- // Any expression for which IsValidArrowParamList() returns true |
- // will work here. |
- return FromIdentifier(PreParserIdentifier::Default()); |
- } |
- |
static PreParserExpression StringLiteral() { |
return PreParserExpression(TypeField::encode(kStringLiteralExpression)); |
} |
@@ -941,20 +936,27 @@ class PreParserExpression { |
return IsIdentifier() || IsProperty(); |
} |
- bool IsValidArrowParamList(FormalParameterErrorLocations* locs) const { |
+ bool IsValidArrowParamList(FormalParameterErrorLocations* locs, |
+ const Scanner::Location& params_loc) const { |
ValidArrowParam valid = ValidateArrowParams(); |
if (ParenthesizationField::decode(code_) == kMultiParenthesizedExpression) { |
return false; |
} |
- if (valid == kValidArrowParam) { |
- return true; |
- } else if (valid == kInvalidStrongArrowParam) { |
- // Return true for now regardless of strong mode for compatibility with |
- // parser. |
- locs->undefined_ = Scanner::Location(); |
- return true; |
- } else { |
- return false; |
+ switch (valid) { |
+ case kInvalidArrowParam: |
+ return false; |
+ case kInvalidStrongArrowParam: |
+ locs->undefined_ = params_loc; |
+ return true; |
+ case kInvalidStrictReservedArrowParam: |
+ locs->reserved_ = params_loc; |
+ return true; |
+ case kInvalidStrictEvalArgumentsArrowParam: |
+ locs->eval_or_arguments_ = params_loc; |
+ return true; |
+ default: |
+ DCHECK_EQ(valid, kValidArrowParam); |
+ return true; |
} |
} |
@@ -1021,8 +1023,12 @@ class PreParserExpression { |
kNoTemplateTagExpression |
}; |
+ // These validity constraints are ordered such that a value of N implies lack |
+ // of errors M < N. |
enum ValidArrowParam { |
kInvalidArrowParam, |
+ kInvalidStrictEvalArgumentsArrowParam, |
+ kInvalidStrictReservedArrowParam, |
kInvalidStrongArrowParam, |
kValidArrowParam |
}; |
@@ -1038,13 +1044,16 @@ class PreParserExpression { |
return kInvalidArrowParam; |
} |
PreParserIdentifier ident = AsIdentifier(); |
- // A valid identifier can be an arrow function parameter |
- // except for eval, arguments, yield, and reserved keywords. |
- if (ident.IsEval() || ident.IsArguments() || |
- ident.IsFutureStrictReserved()) { |
- return kInvalidArrowParam; |
+ // In strict mode, eval and arguments are not valid formal parameter names. |
+ if (ident.IsEval() || ident.IsArguments()) { |
+ return kInvalidStrictEvalArgumentsArrowParam; |
+ } |
+ // In strict mode, future reserved words are not valid either, and as they |
+ // produce different errors we allot them their own error code. |
+ if (ident.IsFutureStrictReserved()) { |
+ return kInvalidStrictReservedArrowParam; |
} |
- // In strong mode, 'undefined' is similarly restricted. |
+ // In strong mode, 'undefined' isn't a valid formal parameter name either. |
if (ident.IsUndefined()) { |
return kInvalidStrongArrowParam; |
} |
@@ -1061,7 +1070,7 @@ class PreParserExpression { |
ExpressionTypeField; |
typedef BitField<bool, ParenthesizationField::kNext, 1> IsUseStrictField; |
typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField; |
- typedef BitField<ValidArrowParam, ParenthesizationField::kNext, 2> |
+ typedef BitField<ValidArrowParam, ParenthesizationField::kNext, 3> |
IsValidArrowParamListField; |
typedef BitField<PreParserIdentifier::Type, ParenthesizationField::kNext, 10> |
IdentifierTypeField; |
@@ -1454,9 +1463,6 @@ class PreParserTraits { |
static PreParserExpression EmptyExpression() { |
return PreParserExpression::Default(); |
} |
- static PreParserExpression EmptyArrowParamList() { |
- return PreParserExpression::EmptyArrowParamList(); |
- } |
static PreParserExpression EmptyLiteral() { |
return PreParserExpression::Default(); |
} |
@@ -1555,15 +1561,9 @@ class PreParserTraits { |
Variable* fvar, Token::Value fvar_init_op, |
FunctionKind kind, bool* ok); |
- // Utility functions |
- V8_INLINE int DeclareArrowParametersFromExpression( |
- PreParserExpression expression, Scope* scope, |
- FormalParameterErrorLocations* locs, bool* ok) { |
- // TODO(wingo): Detect duplicated identifiers in paramlists. Detect eval or |
- // arguments. Detect reserved words. |
- *ok = expression.IsValidArrowParamList(locs); |
- return 0; |
- } |
+ V8_INLINE PreParserFormalParameterList ParseArrowFunctionFormalParameterList( |
+ PreParserExpression expression, const Scanner::Location& params_loc, |
+ FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok); |
struct TemplateLiteralState {}; |
@@ -1589,6 +1589,11 @@ class PreParserTraits { |
return !tag.IsNoTemplateTag(); |
} |
+ int DeclareFormalParameters(PreParserFormalParameterList params, Scope* scope, |
+ bool has_rest) { |
+ return params->length(); |
+ } |
+ |
void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} |
// Temporary glue; these functions will move to ParserBase. |
@@ -1777,6 +1782,22 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, |
} |
+PreParserFormalParameterList |
+PreParserTraits::ParseArrowFunctionFormalParameterList( |
+ PreParserExpression params, const Scanner::Location& params_loc, |
+ FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok) { |
+ // TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter |
+ // lists that are too long. |
+ if (!params.IsValidArrowParamList(error_locs, params_loc)) { |
+ *ok = false; |
+ ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list"); |
+ return this->NullFormalParameterList(); |
+ } |
+ |
+ return PreParserFormalParameterList(); |
+} |
+ |
+ |
PreParserStatementList PreParser::ParseEagerFunctionBody( |
PreParserIdentifier function_name, int pos, Variable* fvar, |
Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
@@ -2072,12 +2093,13 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
case Token::LPAREN: |
Consume(Token::LPAREN); |
- if (allow_harmony_arrow_functions() && peek() == Token::RPAREN) { |
- // Arrow functions are the only expression type constructions |
- // for which an empty parameter list "()" is valid input. |
- Consume(Token::RPAREN); |
- result = this->ParseArrowFunctionLiteral( |
- beg_pos, this->EmptyArrowParamList(), CHECK_OK); |
+ if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) { |
+ // As a primary expression, the only thing that can follow "()" is "=>". |
+ FormalParameterListT params = this->NewFormalParameterList(0, zone()); |
+ FormalParameterErrorLocations error_locs; |
+ bool has_rest = false; |
+ result = this->ParseArrowFunctionLiteral(beg_pos, params, error_locs, |
+ has_rest, CHECK_OK); |
} else { |
// Heuristically try to detect immediately called functions before |
// seeing the call parentheses. |
@@ -2535,8 +2557,13 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { |
checkpoint.Restore(); |
- expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos, |
- expression, CHECK_OK); |
+ FormalParameterErrorLocations error_locs; |
+ Scanner::Location loc(lhs_location.beg_pos, scanner()->location().end_pos); |
+ bool has_rest = false; |
+ FormalParameterListT params = this->ParseArrowFunctionFormalParameterList( |
+ expression, loc, &error_locs, &has_rest, CHECK_OK); |
+ expression = this->ParseArrowFunctionLiteral( |
+ lhs_location.beg_pos, params, error_locs, has_rest, CHECK_OK); |
return expression; |
} |
@@ -3085,7 +3112,7 @@ ParserBase<Traits>::ParseFormalParameter(DuplicateFinder* duplicate_finder, |
if (!locs->reserved_.IsValid() && is_strict_reserved) { |
locs->reserved_ = scanner()->location(); |
} |
- if (!locs->duplicate_.IsValid()) { |
+ if (!locs->duplicate_.IsValid() && duplicate_finder != nullptr) { |
int prev_value = scanner()->FindSymbol(duplicate_finder, 1); |
if (prev_value != 0) locs->duplicate_ = scanner()->location(); |
} |
@@ -3164,11 +3191,12 @@ void ParserBase<Traits>::CheckArityRestrictions( |
} |
} |
+ |
template <class Traits> |
typename ParserBase<Traits>::ExpressionT |
-ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
- ExpressionT params_ast, |
- bool* ok) { |
+ParserBase<Traits>::ParseArrowFunctionLiteral( |
+ int start_pos, FormalParameterListT params, |
+ const FormalParameterErrorLocations& error_locs, bool has_rest, bool* ok) { |
if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { |
// ASI inserts `;` after arrow parameters if a line terminator is found. |
// `=> ...` is never a valid expression, so report as syntax error. |
@@ -3190,27 +3218,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
typename Traits::Type::Factory function_factory(ast_value_factory()); |
FunctionState function_state(&function_state_, &scope_, scope, |
kArrowFunction, &function_factory); |
- FormalParameterErrorLocations error_locs; |
- num_parameters = Traits::DeclareArrowParametersFromExpression( |
- params_ast, scope_, &error_locs, ok); |
- if (!*ok) { |
- ReportMessageAt( |
- Scanner::Location(start_pos, scanner()->location().beg_pos), |
- "malformed_arrow_function_parameter_list"); |
- return this->EmptyExpression(); |
- } |
- |
- if (error_locs.undefined_.IsValid()) { |
- // Workaround for preparser not keeping track of positions. |
- error_locs.undefined_ = |
- Scanner::Location(start_pos, scanner()->location().end_pos); |
- } |
- if (num_parameters > Code::kMaxArguments) { |
- ReportMessageAt(Scanner::Location(params_ast->position(), position()), |
- "too_many_parameters"); |
- *ok = false; |
- return this->EmptyExpression(); |
- } |
+ num_parameters = this->DeclareFormalParameters(params, scope_, has_rest); |
Expect(Token::ARROW, CHECK_OK); |