Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 862b7fb40dd894b53dfcec80d36aedde5b441e3f..8c346b26681f5503545818dbef6ca9c06f0c4364 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, |
@@ -555,7 +557,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())); |
@@ -644,9 +646,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); |
@@ -658,9 +660,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, |
@@ -1252,6 +1255,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 { |
@@ -1278,6 +1290,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; |
@@ -1516,19 +1529,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 {}; |
@@ -1555,7 +1572,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) {} |
@@ -1706,6 +1723,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); |
@@ -1751,8 +1769,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. |
@@ -1760,8 +1778,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); |
@@ -1773,10 +1792,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); |
} |
@@ -2154,20 +2174,22 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
Token::String(Token::RPAREN)); |
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); |
@@ -2175,8 +2197,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. |
@@ -2391,6 +2413,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( |
// Fall through. |
default: |
*name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); |
+ if (classifier->duplicate_finder() != nullptr && !*is_get && !*is_set && |
+ scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
+ classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
arv (Not doing code reviews)
2015/06/19 19:25:26
The following is not supposed to be an error.
f
Dmitry Lomov (no reviews)
2015/06/22 10:14:10
Done.
|
+ } |
break; |
} |
@@ -2718,15 +2744,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; |
} |
@@ -3489,9 +3515,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] |
wingo
2015/06/22 10:22:14
if is_rest is true then we are parsing BindingRest
|
@@ -3508,13 +3534,19 @@ 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; |
+ 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] |
@@ -3538,12 +3570,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; |
@@ -3588,8 +3620,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. |
@@ -3600,15 +3632,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); |
@@ -3623,8 +3656,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); |
wingo
2015/06/22 10:22:14
Nit: const Variable *name = nullptr, pass by name?
|
materialized_literal_count = |
function_state.materialized_literal_count(); |
expected_property_count = function_state.expected_property_count(); |
@@ -3638,13 +3671,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 |
@@ -3656,21 +3690,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); |