Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index ce2c6c429239742a3cca7c4438f377a14c348111..b66053b94697a7d82a59969e1f06a6cd4fd1b3fc 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -70,6 +70,8 @@ class ParserBase : public Traits { |
typedef typename Traits::Type::FunctionLiteral FunctionLiteralT; |
typedef typename Traits::Type::Literal LiteralT; |
typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT; |
+ typedef typename Traits::Type::FormalParameterParsingState |
+ FormalParameterParsingStateT; |
ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, |
v8::Extension* extension, AstValueFactory* ast_value_factory, |
@@ -557,7 +559,7 @@ class ParserBase : public Traits { |
ExpressionT expr, bool* ok) { |
if (classifier->is_valid_binding_pattern()) { |
// A simple arrow formal parameter: IDENTIFIER => BODY. |
- if (!allow_harmony_destructuring() && !this->IsIdentifier(expr)) { |
+ if (!this->IsIdentifier(expr)) { |
Traits::ReportMessageAt(scanner()->location(), |
MessageTemplate::kUnexpectedToken, |
Token::String(scanner()->current_token())); |
@@ -646,9 +648,9 @@ class ParserBase : public Traits { |
ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok); |
ExpressionT ParseMemberExpressionContinuation( |
ExpressionT expression, ExpressionClassifier* classifier, bool* ok); |
- ExpressionT ParseArrowFunctionLiteral(Scope* function_scope, bool has_rest, |
- const ExpressionClassifier& classifier, |
- bool* ok); |
+ ExpressionT ParseArrowFunctionLiteral( |
+ const FormalParameterParsingStateT& parsing_state, |
+ const ExpressionClassifier& classifier, bool* ok); |
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, |
ExpressionClassifier* classifier, bool* ok); |
void AddTemplateExpression(ExpressionT); |
@@ -660,9 +662,10 @@ class ParserBase : public Traits { |
ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier, |
bool* ok); |
- void ParseFormalParameter(Scope* scope, bool is_rest, |
+ void ParseFormalParameter(bool is_rest, |
+ FormalParameterParsingStateT* parsing_result, |
ExpressionClassifier* classifier, bool* ok); |
- int ParseFormalParameterList(Scope* scope, bool* has_rest, |
+ int ParseFormalParameterList(FormalParameterParsingStateT* parsing_state, |
ExpressionClassifier* classifier, bool* ok); |
void CheckArityRestrictions( |
int param_count, FunctionLiteral::ArityRestriction arity_restriction, |
@@ -1254,6 +1257,15 @@ class PreParserFactory { |
}; |
+struct PreParserFormalParameterParsingState { |
+ explicit PreParserFormalParameterParsingState(Scope* scope) |
+ : scope(scope), has_rest(false), is_simple_parameter_list(true) {} |
+ Scope* scope; |
+ bool has_rest; |
+ bool is_simple_parameter_list; |
+}; |
+ |
+ |
class PreParser; |
class PreParserTraits { |
@@ -1280,6 +1292,7 @@ class PreParserTraits { |
typedef PreParserExpressionList PropertyList; |
typedef PreParserIdentifier FormalParameter; |
typedef PreParserStatementList StatementList; |
+ typedef PreParserFormalParameterParsingState FormalParameterParsingState; |
// For constructing objects returned by the traversing functions. |
typedef PreParserFactory Factory; |
@@ -1518,19 +1531,23 @@ class PreParserTraits { |
return PreParserExpressionList(); |
} |
+ static void AddParameterInitializationBlock( |
+ const PreParserFormalParameterParsingState& formal_parameters, |
+ PreParserStatementList list, bool* ok) {} |
+ |
V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, |
int* expected_property_count, bool* ok) { |
UNREACHABLE(); |
} |
- V8_INLINE PreParserStatementList |
- ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, |
- Variable* fvar, Token::Value fvar_init_op, |
- FunctionKind kind, bool* ok); |
+ V8_INLINE PreParserStatementList ParseEagerFunctionBody( |
+ PreParserIdentifier function_name, int pos, |
+ const PreParserFormalParameterParsingState& formal_parameters, |
+ Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok); |
V8_INLINE void ParseArrowFunctionFormalParameters( |
- Scope* scope, PreParserExpression expression, |
- const Scanner::Location& params_loc, bool* has_rest, |
+ PreParserFormalParameterParsingState* parsing_state, |
+ PreParserExpression expression, const Scanner::Location& params_loc, |
Scanner::Location* duplicate_loc, bool* ok); |
struct TemplateLiteralState {}; |
@@ -1557,7 +1574,7 @@ class PreParserTraits { |
return !tag.IsNoTemplateTag(); |
} |
- void DeclareFormalParameter(Scope* scope, PreParserExpression pattern, |
+ void DeclareFormalParameter(void* parsing_state, PreParserExpression pattern, |
ExpressionClassifier* classifier, bool is_rest) {} |
void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} |
@@ -1708,6 +1725,7 @@ class PreParser : public ParserBase<PreParserTraits> { |
int* expected_property_count, bool* ok); |
V8_INLINE PreParserStatementList |
ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, |
+ const FormalParameterParsingStateT& formal_parameters, |
Variable* fvar, Token::Value fvar_init_op, |
FunctionKind kind, bool* ok); |
@@ -1753,8 +1771,8 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, |
void PreParserTraits::ParseArrowFunctionFormalParameters( |
- Scope* scope, PreParserExpression params, |
- const Scanner::Location& params_loc, bool* has_rest, |
+ PreParserFormalParameterParsingState* parsing_state, |
+ PreParserExpression params, const Scanner::Location& params_loc, |
Scanner::Location* duplicate_loc, bool* ok) { |
// TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter |
// lists that are too long. |
@@ -1762,8 +1780,9 @@ void PreParserTraits::ParseArrowFunctionFormalParameters( |
PreParserStatementList PreParser::ParseEagerFunctionBody( |
- PreParserIdentifier function_name, int pos, Variable* fvar, |
- Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
+ PreParserIdentifier function_name, int pos, |
+ const PreParserFormalParameterParsingState& formal_parameters, |
+ Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
ParseStatementList(Token::RBRACE, ok); |
@@ -1775,10 +1794,11 @@ PreParserStatementList PreParser::ParseEagerFunctionBody( |
PreParserStatementList PreParserTraits::ParseEagerFunctionBody( |
- PreParserIdentifier function_name, int pos, Variable* fvar, |
- Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
- return pre_parser_->ParseEagerFunctionBody(function_name, pos, fvar, |
- fvar_init_op, kind, ok); |
+ PreParserIdentifier function_name, int pos, |
+ const PreParserFormalParameterParsingState& formal_parameters, |
+ Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
+ return pre_parser_->ParseEagerFunctionBody( |
+ function_name, pos, formal_parameters, fvar, fvar_init_op, kind, ok); |
} |
@@ -2162,20 +2182,22 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
} |
Scope* scope = |
this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); |
+ FormalParameterParsingStateT parsing_state(scope); |
scope->set_start_position(beg_pos); |
ExpressionClassifier args_classifier; |
- bool has_rest = false; |
- result = this->ParseArrowFunctionLiteral(scope, has_rest, |
- args_classifier, CHECK_OK); |
+ result = this->ParseArrowFunctionLiteral(parsing_state, 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); |
+ FormalParameterParsingStateT parsing_state(scope); |
scope->set_start_position(beg_pos); |
ExpressionClassifier args_classifier; |
- const bool has_rest = true; |
- this->ParseFormalParameter(scope, has_rest, &args_classifier, CHECK_OK); |
+ const bool is_rest = true; |
+ this->ParseFormalParameter(is_rest, &parsing_state, &args_classifier, |
+ CHECK_OK); |
if (peek() == Token::COMMA) { |
ReportMessageAt(scanner()->peek_location(), |
MessageTemplate::kParamAfterRest); |
@@ -2183,8 +2205,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
return this->EmptyExpression(); |
} |
Expect(Token::RPAREN, CHECK_OK); |
- result = this->ParseArrowFunctionLiteral(scope, has_rest, |
- args_classifier, CHECK_OK); |
+ result = this->ParseArrowFunctionLiteral(parsing_state, args_classifier, |
+ CHECK_OK); |
} else { |
// Heuristically try to detect immediately called functions before |
// seeing the call parentheses. |
@@ -2524,6 +2546,11 @@ ParserBase<Traits>::ParsePropertyDefinition( |
DCHECK(!*is_computed_name); |
DCHECK(!is_static); |
+ if (classifier->duplicate_finder() != nullptr && |
+ scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
+ classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
+ } |
+ |
ExpressionT lhs = this->ExpressionFromIdentifier( |
name, next_beg_pos, next_end_pos, scope_, factory()); |
if (peek() == Token::ASSIGN) { |
@@ -2707,7 +2734,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
if (fni_ != NULL) fni_->Enter(); |
ParserBase<Traits>::Checkpoint checkpoint(this); |
- ExpressionClassifier arrow_formals_classifier; |
+ ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder()); |
if (peek() != Token::LPAREN) { |
// The expression we are going to read is not a parenthesized arrow function |
// formal parameter list. |
@@ -2726,15 +2753,15 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
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, |
+ FormalParameterParsingStateT parsing_state(scope); |
+ this->ParseArrowFunctionFormalParameters(&parsing_state, expression, loc, |
&duplicate_loc, CHECK_OK); |
if (duplicate_loc.IsValid()) { |
arrow_formals_classifier.RecordDuplicateFormalParameterError( |
duplicate_loc); |
} |
expression = this->ParseArrowFunctionLiteral( |
- scope, has_rest, arrow_formals_classifier, CHECK_OK); |
+ parsing_state, arrow_formals_classifier, CHECK_OK); |
return expression; |
} |
@@ -3497,9 +3524,9 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
template <class Traits> |
-void ParserBase<Traits>::ParseFormalParameter(Scope* scope, bool is_rest, |
- ExpressionClassifier* classifier, |
- bool* ok) { |
+void ParserBase<Traits>::ParseFormalParameter( |
+ bool is_rest, FormalParameterParsingStateT* parsing_state, |
+ ExpressionClassifier* classifier, bool* ok) { |
// FormalParameter[Yield,GeneratorParameter] : |
// BindingElement[?Yield, ?GeneratorParameter] |
@@ -3516,13 +3543,24 @@ void ParserBase<Traits>::ParseFormalParameter(Scope* scope, bool is_rest, |
return; |
} |
- Traits::DeclareFormalParameter(scope, pattern, classifier, is_rest); |
+ if (parsing_state->is_simple_parameter_list) { |
+ parsing_state->is_simple_parameter_list = |
+ !is_rest && Traits::IsIdentifier(pattern); |
+ } |
+ parsing_state->has_rest = is_rest; |
+ if (is_rest && !Traits::IsIdentifier(pattern)) { |
+ ReportUnexpectedToken(next); |
+ *ok = false; |
+ return; |
+ } |
+ Traits::DeclareFormalParameter(parsing_state, pattern, classifier, is_rest); |
} |
template <class Traits> |
int ParserBase<Traits>::ParseFormalParameterList( |
- Scope* scope, bool* is_rest, ExpressionClassifier* classifier, bool* ok) { |
+ FormalParameterParsingStateT* parsing_state, |
+ ExpressionClassifier* classifier, bool* ok) { |
// FormalParameters[Yield,GeneratorParameter] : |
// [empty] |
// FormalParameterList[?Yield, ?GeneratorParameter] |
@@ -3546,12 +3584,12 @@ int ParserBase<Traits>::ParseFormalParameterList( |
*ok = false; |
return -1; |
} |
- *is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS); |
- ParseFormalParameter(scope, *is_rest, classifier, ok); |
+ bool is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS); |
+ ParseFormalParameter(is_rest, parsing_state, classifier, ok); |
if (!*ok) return -1; |
- } while (!*is_rest && Check(Token::COMMA)); |
+ } while (!parsing_state->has_rest && Check(Token::COMMA)); |
- if (*is_rest && peek() == Token::COMMA) { |
+ if (parsing_state->has_rest && peek() == Token::COMMA) { |
ReportMessageAt(scanner()->peek_location(), |
MessageTemplate::kParamAfterRest); |
*ok = false; |
@@ -3596,8 +3634,8 @@ void ParserBase<Traits>::CheckArityRestrictions( |
template <class Traits> |
typename ParserBase<Traits>::ExpressionT |
ParserBase<Traits>::ParseArrowFunctionLiteral( |
- Scope* scope, bool has_rest, const ExpressionClassifier& formals_classifier, |
- bool* ok) { |
+ const FormalParameterParsingStateT& formal_parameters, |
+ const ExpressionClassifier& formals_classifier, 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. |
@@ -3608,15 +3646,16 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
} |
typename Traits::Type::StatementList body; |
- int num_parameters = scope->num_parameters(); |
+ int num_parameters = formal_parameters.scope->num_parameters(); |
int materialized_literal_count = -1; |
int expected_property_count = -1; |
Scanner::Location super_loc; |
{ |
typename Traits::Type::Factory function_factory(ast_value_factory()); |
- FunctionState function_state(&function_state_, &scope_, scope, |
- kArrowFunction, &function_factory); |
+ FunctionState function_state(&function_state_, &scope_, |
+ formal_parameters.scope, kArrowFunction, |
+ &function_factory); |
Expect(Token::ARROW, CHECK_OK); |
@@ -3631,8 +3670,8 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
&expected_property_count, CHECK_OK); |
} else { |
body = this->ParseEagerFunctionBody( |
- this->EmptyIdentifier(), RelocInfo::kNoPosition, NULL, |
- Token::INIT_VAR, kArrowFunction, CHECK_OK); |
+ this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters, |
+ NULL, Token::INIT_VAR, kArrowFunction, CHECK_OK); |
materialized_literal_count = |
function_state.materialized_literal_count(); |
expected_property_count = function_state.expected_property_count(); |
@@ -3646,13 +3685,14 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
ParseAssignmentExpression(true, &classifier, CHECK_OK); |
ValidateExpression(&classifier, CHECK_OK); |
body = this->NewStatementList(1, zone()); |
+ this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK); |
body->Add(factory()->NewReturnStatement(expression, pos), zone()); |
materialized_literal_count = function_state.materialized_literal_count(); |
expected_property_count = function_state.expected_property_count(); |
} |
super_loc = function_state.super_location(); |
- scope->set_end_position(scanner()->location().end_pos); |
+ formal_parameters.scope->set_end_position(scanner()->location().end_pos); |
// Arrow function formal parameters are parsed as StrictFormalParameterList, |
// which is not the same as "parameters of a strict function"; it only means |
@@ -3664,21 +3704,23 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
// Validate strict mode. |
if (is_strict(language_mode())) { |
- CheckStrictOctalLiteral(scope->start_position(), |
+ CheckStrictOctalLiteral(formal_parameters.scope->start_position(), |
scanner()->location().end_pos, CHECK_OK); |
- this->CheckConflictingVarDeclarations(scope, CHECK_OK); |
+ this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); |
} |
} |
FunctionLiteralT function_literal = factory()->NewFunctionLiteral( |
- this->EmptyIdentifierString(), ast_value_factory(), scope, body, |
- materialized_literal_count, expected_property_count, num_parameters, |
+ this->EmptyIdentifierString(), ast_value_factory(), |
+ formal_parameters.scope, body, materialized_literal_count, |
+ expected_property_count, num_parameters, |
FunctionLiteral::kNoDuplicateParameters, |
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, |
FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction, |
- scope->start_position()); |
+ formal_parameters.scope->start_position()); |
- function_literal->set_function_token_position(scope->start_position()); |
+ function_literal->set_function_token_position( |
+ formal_parameters.scope->start_position()); |
if (super_loc.IsValid()) function_state_->set_super_location(super_loc); |
if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); |