Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 0440d831eea5105552c2c268534faead9ff44f0e..920052daf2550a7b3bac500b391785a6a7a734e3 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -17,6 +17,26 @@ |
| namespace v8 { |
| namespace internal { |
| + |
| +// When parsing the formal parameters of a function, we usually don't yet know |
| +// if the function will be strict, so we cannot yet produce errors for |
| +// parameter names or duplicates. Instead, we remember the locations of these |
| +// errors if they occur and produce the errors later. |
| +class FormalParameterErrorLocations BASE_EMBEDDED { |
| + public: |
| + FormalParameterErrorLocations() |
| + : eval_or_arguments(Scanner::Location::invalid()), |
| + undefined(Scanner::Location::invalid()), |
| + duplicate(Scanner::Location::invalid()), |
| + reserved(Scanner::Location::invalid()) {} |
| + |
| + Scanner::Location eval_or_arguments; |
| + Scanner::Location undefined; |
| + Scanner::Location duplicate; |
| + Scanner::Location reserved; |
| +}; |
| + |
| + |
| // Common base class shared between parser and pre-parser. Traits encapsulate |
| // the differences between Parser and PreParser: |
| @@ -51,6 +71,8 @@ namespace internal { |
| // typedef Literal; |
| // typedef ExpressionList; |
| // typedef PropertyList; |
| +// typedef FormalParameter; |
| +// typedef FormalParameterScope; |
| // // For constructing objects returned by the traversing functions. |
| // typedef Factory; |
| // }; |
| @@ -63,6 +85,8 @@ class ParserBase : public Traits { |
| // Shorten type names defined by Traits. |
| typedef typename Traits::Type::Expression ExpressionT; |
| typedef typename Traits::Type::Identifier IdentifierT; |
| + typedef typename Traits::Type::FormalParameter FormalParameterT; |
| + typedef typename Traits::Type::FormalParameterScope FormalParameterScopeT; |
| typedef typename Traits::Type::FunctionLiteral FunctionLiteralT; |
| typedef typename Traits::Type::Literal LiteralT; |
| typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT; |
| @@ -495,31 +519,28 @@ class ParserBase : public Traits { |
| // after parsing the function, since the function can declare itself strict. |
| void CheckFunctionParameterNames(LanguageMode language_mode, |
| bool strict_params, |
| - const Scanner::Location& eval_args_loc, |
| - const Scanner::Location& undefined_loc, |
| - const Scanner::Location& dupe_loc, |
| - const Scanner::Location& reserved_loc, |
| + const FormalParameterErrorLocations& locs, |
| bool* ok) { |
| if (is_sloppy(language_mode) && !strict_params) return; |
| - if (is_strict(language_mode) && eval_args_loc.IsValid()) { |
| - Traits::ReportMessageAt(eval_args_loc, "strict_eval_arguments"); |
| + if (is_strict(language_mode) && locs.eval_or_arguments.IsValid()) { |
| + Traits::ReportMessageAt(locs.eval_or_arguments, "strict_eval_arguments"); |
| *ok = false; |
| return; |
| } |
| - if (is_strong(language_mode) && undefined_loc.IsValid()) { |
| - Traits::ReportMessageAt(undefined_loc, "strong_undefined"); |
| + if (is_strict(language_mode) && locs.reserved.IsValid()) { |
| + Traits::ReportMessageAt(locs.reserved, "unexpected_strict_reserved"); |
| *ok = false; |
| return; |
| } |
| - // TODO(arv): When we add support for destructuring in setters we also need |
| - // to check for duplicate names. |
| - if (dupe_loc.IsValid()) { |
| - Traits::ReportMessageAt(dupe_loc, "strict_param_dupe"); |
| + if (is_strong(language_mode) && locs.undefined.IsValid()) { |
| + Traits::ReportMessageAt(locs.undefined, "strong_undefined"); |
| *ok = false; |
| return; |
| } |
| - if (reserved_loc.IsValid()) { |
| - Traits::ReportMessageAt(reserved_loc, "unexpected_strict_reserved"); |
| + // TODO(arv): When we add support for destructuring in setters we also need |
| + // to check for duplicate names. |
| + if (locs.duplicate.IsValid()) { |
| + Traits::ReportMessageAt(locs.duplicate, "strict_param_dupe"); |
| *ok = false; |
| return; |
| } |
| @@ -600,12 +621,23 @@ 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( |
| + Scope* function_scope, 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); |
| + void ParseFormalParameter(FormalParameterScopeT* scope, |
| + FormalParameterErrorLocations* locs, bool is_rest, |
| + bool* ok); |
| + int ParseFormalParameterList(FormalParameterScopeT* scope, |
| + FormalParameterErrorLocations* locs, |
| + bool* has_rest, bool* ok); |
| + void CheckArityRestrictions( |
| + int param_count, FunctionLiteral::ArityRestriction arity_restriction, |
| + int formals_start_pos, int formals_end_pos, bool* ok); |
| + |
| // Checks if the expression is a valid reference expression (e.g., on the |
| // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| // we allow calls for web compatibility and rewrite them to a runtime throw. |
| @@ -815,12 +847,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)); |
| } |
| @@ -911,20 +937,27 @@ class PreParserExpression { |
| return IsIdentifier() || IsProperty(); |
| } |
| - bool IsValidArrowParamList(Scanner::Location* undefined_loc) 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. |
| - *undefined_loc = 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; |
| } |
| } |
| @@ -991,8 +1024,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 |
| }; |
| @@ -1008,13 +1045,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; |
| } |
| @@ -1031,7 +1071,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; |
| @@ -1040,20 +1080,24 @@ class PreParserExpression { |
| }; |
| -// PreParserExpressionList doesn't actually store the expressions because |
| -// PreParser doesn't need to. |
| -class PreParserExpressionList { |
| +// The pre-parser doesn't need to build lists of expressions, identifiers, or |
| +// the like. |
| +template <typename T> |
| +class PreParserList { |
| public: |
| // These functions make list->Add(some_expression) work (and do nothing). |
| - PreParserExpressionList() : length_(0) {} |
| - PreParserExpressionList* operator->() { return this; } |
| - void Add(PreParserExpression, void*) { ++length_; } |
| + PreParserList() : length_(0) {} |
| + PreParserList* operator->() { return this; } |
| + void Add(T, void*) { ++length_; } |
| int length() const { return length_; } |
| private: |
| int length_; |
| }; |
| +typedef PreParserList<PreParserExpression> PreParserExpressionList; |
| + |
| + |
| class PreParserStatement { |
| public: |
| static PreParserStatement Default() { |
| @@ -1118,16 +1162,7 @@ class PreParserStatement { |
| }; |
| - |
| -// PreParserStatementList doesn't actually store the statements because |
| -// the PreParser does not need them. |
| -class PreParserStatementList { |
| - public: |
| - // These functions make list->Add(some_expression) work as no-ops. |
| - PreParserStatementList() {} |
| - PreParserStatementList* operator->() { return this; } |
| - void Add(PreParserStatement, void*) {} |
| -}; |
| +typedef PreParserList<PreParserStatement> PreParserStatementList; |
| class PreParserFactory { |
| @@ -1292,6 +1327,8 @@ class PreParserTraits { |
| typedef PreParserExpression Literal; |
| typedef PreParserExpressionList ExpressionList; |
| typedef PreParserExpressionList PropertyList; |
| + typedef PreParserIdentifier FormalParameter; |
| + typedef DuplicateFinder FormalParameterScope; |
| typedef PreParserStatementList StatementList; |
| // For constructing objects returned by the traversing functions. |
| @@ -1391,6 +1428,9 @@ class PreParserTraits { |
| return expression; |
| } |
| + V8_INLINE bool IsDeclared(DuplicateFinder* duplicate_finder, |
|
wingo
2015/04/21 09:32:25
This decl is vestigial, will remove.
|
| + PreParserIdentifier current_identifier); |
| + |
| bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, |
| PreParserExpression y, |
| Token::Value op, |
| @@ -1435,9 +1475,6 @@ class PreParserTraits { |
| static PreParserExpression EmptyExpression() { |
| return PreParserExpression::Default(); |
| } |
| - static PreParserExpression EmptyArrowParamList() { |
| - return PreParserExpression::EmptyArrowParamList(); |
| - } |
| static PreParserExpression EmptyLiteral() { |
| return PreParserExpression::Default(); |
| } |
| @@ -1525,16 +1562,10 @@ class PreParserTraits { |
| Variable* fvar, Token::Value fvar_init_op, |
| FunctionKind kind, bool* ok); |
| - // Utility functions |
| - int DeclareArrowParametersFromExpression(PreParserExpression expression, |
| - Scope* scope, |
| - Scanner::Location* undefined_loc, |
| - Scanner::Location* dupe_loc, |
| - bool* ok) { |
| - // TODO(aperez): Detect duplicated identifiers in paramlists. |
| - *ok = expression.IsValidArrowParamList(undefined_loc); |
| - return 0; |
| - } |
| + V8_INLINE void ParseArrowFunctionFormalParameters( |
| + Scope* scope, PreParserExpression expression, |
| + const Scanner::Location& params_loc, |
| + FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok); |
| struct TemplateLiteralState {}; |
| @@ -1560,6 +1591,10 @@ class PreParserTraits { |
| return !tag.IsNoTemplateTag(); |
| } |
| + V8_INLINE bool DeclareFormalParameter(DuplicateFinder* scope, |
| + PreParserIdentifier param, |
| + bool is_rest); |
| + |
| void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} |
| // Temporary glue; these functions will move to ParserBase. |
| @@ -1748,6 +1783,27 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, |
| } |
| +bool PreParserTraits::DeclareFormalParameter( |
| + DuplicateFinder* duplicate_finder, PreParserIdentifier current_identifier, |
| + bool is_rest) { |
| + return pre_parser_->scanner()->FindSymbol(duplicate_finder, 1) != 0; |
| +} |
| + |
| + |
| +void PreParserTraits::ParseArrowFunctionFormalParameters( |
| + Scope* scope, 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; |
| + } |
| +} |
| + |
| + |
| PreParserStatementList PreParser::ParseEagerFunctionBody( |
| PreParserIdentifier function_name, int pos, Variable* fvar, |
| Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
| @@ -2043,12 +2099,14 @@ 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 "=>". |
| + Scope* scope = this->NewScope(scope_, ARROW_SCOPE); |
| + scope->set_start_position(beg_pos); |
| + FormalParameterErrorLocations error_locs; |
| + bool has_rest = false; |
| + result = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, |
| + CHECK_OK); |
| } else { |
| // Heuristically try to detect immediately called functions before |
| // seeing the call parentheses. |
| @@ -2506,8 +2564,15 @@ 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; |
| + Scope* scope = this->NewScope(scope_, ARROW_SCOPE); |
| + scope->set_start_position(lhs_location.beg_pos); |
| + this->ParseArrowFunctionFormalParameters(scope, expression, loc, |
| + &error_locs, &has_rest, CHECK_OK); |
| + expression = |
| + this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, CHECK_OK); |
| return expression; |
| } |
| @@ -3041,10 +3106,106 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression, |
| template <class Traits> |
| +void ParserBase<Traits>::ParseFormalParameter( |
| + FormalParameterScopeT* scope, FormalParameterErrorLocations* locs, |
| + bool is_rest, bool* ok) { |
| + // FormalParameter[Yield,GeneratorParameter] : |
| + // BindingElement[?Yield, ?GeneratorParameter] |
| + bool is_strict_reserved; |
| + IdentifierT name = |
| + ParseIdentifierOrStrictReservedWord(&is_strict_reserved, ok); |
| + if (!*ok) return; |
| + |
| + // Store locations for possible future error reports. |
| + if (!locs->eval_or_arguments.IsValid() && this->IsEvalOrArguments(name)) { |
| + locs->eval_or_arguments = scanner()->location(); |
| + } |
| + if (!locs->undefined.IsValid() && this->IsUndefined(name)) { |
| + locs->undefined = scanner()->location(); |
| + } |
| + if (!locs->reserved.IsValid() && is_strict_reserved) { |
| + locs->reserved = scanner()->location(); |
| + } |
| + bool was_declared = Traits::DeclareFormalParameter(scope, name, is_rest); |
| + if (!locs->duplicate.IsValid() && was_declared) { |
| + locs->duplicate = scanner()->location(); |
| + } |
| +} |
| + |
| + |
| +template <class Traits> |
| +int ParserBase<Traits>::ParseFormalParameterList( |
| + FormalParameterScopeT* scope, FormalParameterErrorLocations* locs, |
| + bool* is_rest, bool* ok) { |
| + // FormalParameters[Yield,GeneratorParameter] : |
| + // [empty] |
| + // FormalParameterList[?Yield, ?GeneratorParameter] |
| + // |
| + // FormalParameterList[Yield,GeneratorParameter] : |
| + // FunctionRestParameter[?Yield] |
| + // FormalsList[?Yield, ?GeneratorParameter] |
| + // FormalsList[?Yield, ?GeneratorParameter] , FunctionRestParameter[?Yield] |
| + // |
| + // FormalsList[Yield,GeneratorParameter] : |
| + // FormalParameter[?Yield, ?GeneratorParameter] |
| + // FormalsList[?Yield, ?GeneratorParameter] , |
| + // FormalParameter[?Yield,?GeneratorParameter] |
| + |
| + int parameter_count = 0; |
| + |
| + if (peek() != Token::RPAREN) { |
| + do { |
| + if (++parameter_count > Code::kMaxArguments) { |
| + ReportMessage("too_many_parameters"); |
| + *ok = false; |
| + return -1; |
| + } |
| + *is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS); |
| + ParseFormalParameter(scope, locs, *is_rest, ok); |
| + if (!*ok) return -1; |
| + } while (!*is_rest && Check(Token::COMMA)); |
| + |
| + if (*is_rest && peek() == Token::COMMA) { |
| + ReportMessageAt(scanner()->peek_location(), "param_after_rest"); |
| + *ok = false; |
| + return -1; |
| + } |
| + } |
| + |
| + return parameter_count; |
| +} |
| + |
| + |
| +template <class Traits> |
| +void ParserBase<Traits>::CheckArityRestrictions( |
| + int param_count, FunctionLiteral::ArityRestriction arity_restriction, |
| + int formals_start_pos, int formals_end_pos, bool* ok) { |
| + switch (arity_restriction) { |
| + case FunctionLiteral::GETTER_ARITY: |
| + if (param_count != 0) { |
| + ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), |
| + "bad_getter_arity"); |
| + *ok = false; |
| + } |
| + break; |
| + case FunctionLiteral::SETTER_ARITY: |
| + if (param_count != 1) { |
| + ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), |
| + "bad_setter_arity"); |
| + *ok = false; |
| + } |
| + break; |
| + default: |
| + break; |
| + } |
| +} |
| + |
| + |
| +template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| -ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| - ExpressionT params_ast, |
| - bool* ok) { |
| +ParserBase<Traits>::ParseArrowFunctionLiteral( |
| + Scope* scope, 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. |
| @@ -3054,9 +3215,8 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| return this->EmptyExpression(); |
| } |
| - Scope* scope = this->NewScope(scope_, ARROW_SCOPE); |
| typename Traits::Type::StatementList body; |
| - int num_parameters = -1; |
| + int num_parameters = scope->num_parameters(); |
| int materialized_literal_count = -1; |
| int expected_property_count = -1; |
| int handler_count = 0; |
| @@ -3066,29 +3226,6 @@ 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); |
| - Scanner::Location undefined_loc = Scanner::Location::invalid(); |
| - Scanner::Location dupe_loc = Scanner::Location::invalid(); |
| - // TODO(arv): Pass in eval_args_loc and reserved_loc here. |
| - num_parameters = Traits::DeclareArrowParametersFromExpression( |
| - params_ast, scope_, &undefined_loc, &dupe_loc, ok); |
| - if (!*ok) { |
| - ReportMessageAt( |
| - Scanner::Location(start_pos, scanner()->location().beg_pos), |
| - "malformed_arrow_function_parameter_list"); |
| - return this->EmptyExpression(); |
| - } |
| - |
| - if (undefined_loc.IsValid()) { |
| - // Workaround for preparser not keeping track of positions. |
| - undefined_loc = 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(); |
| - } |
| Expect(Token::ARROW, CHECK_OK); |
| @@ -3124,23 +3261,20 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| } |
| super_loc = function_state.super_call_location(); |
| - scope->set_start_position(start_pos); |
| scope->set_end_position(scanner()->location().end_pos); |
| - // Arrow function *parameter lists* are always checked as in strict mode. |
| - // TODO(arv): eval_args_loc and reserved_loc needs to be set by |
| - // DeclareArrowParametersFromExpression. |
| - Scanner::Location eval_args_loc = Scanner::Location::invalid(); |
| - Scanner::Location reserved_loc = Scanner::Location::invalid(); |
| + // Arrow function formal parameters are parsed as StrictFormalParameterList, |
| + // which is not the same as "parameters of a strict function"; it only means |
| + // that duplicates are not allowed. Of course, the arrow function may |
| + // itself be strict as well. |
| const bool use_strict_params = true; |
| this->CheckFunctionParameterNames(language_mode(), use_strict_params, |
| - eval_args_loc, undefined_loc, dupe_loc, |
| - reserved_loc, CHECK_OK); |
| + error_locs, CHECK_OK); |
| // Validate strict mode. |
| if (is_strict(language_mode())) { |
| - CheckStrictOctalLiteral(start_pos, scanner()->location().end_pos, |
| - CHECK_OK); |
| + CheckStrictOctalLiteral(scope->start_position(), |
| + scanner()->location().end_pos, CHECK_OK); |
| this->CheckConflictingVarDeclarations(scope, CHECK_OK); |
| } |
| } |
| @@ -3151,9 +3285,9 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| num_parameters, FunctionLiteral::kNoDuplicateParameters, |
| FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, |
| FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction, |
| - start_pos); |
| + scope->start_position()); |
| - function_literal->set_function_token_position(start_pos); |
| + function_literal->set_function_token_position(scope->start_position()); |
| if (super_loc.IsValid()) function_state_->set_super_call_location(super_loc); |
| if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); |