Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(465)

Unified Diff: src/parser.cc

Issue 1077153005: Allow eval/arguments in arrow functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index b7bead792f3db8df128955cc896997d4b5a88520..c73b6d841cdb41a5d8d0fcf1db725d9997db0c5d 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -787,16 +787,7 @@ Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
Scope* scope,
AstNodeFactory* factory) {
if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
-
- // Arrow function parameters are parsed as an expression. When
- // parsing lazily, it is enough to create a VariableProxy in order
- // for Traits::DeclareArrowParametersFromExpression() to be able to
- // pick the names of the parameters.
- return parser_->parsing_lazy_arrow_parameters_
- ? factory->NewVariableProxy(name, Variable::NORMAL, start_position,
- end_position)
- : scope->NewUnresolved(factory, name, start_position,
- end_position);
+ return scope->NewUnresolved(factory, name, start_position, end_position);
}
@@ -861,7 +852,6 @@ Parser::Parser(ParseInfo* info)
target_stack_(NULL),
compile_options_(info->compile_options()),
cached_parse_data_(NULL),
- parsing_lazy_arrow_parameters_(false),
total_preparse_skipped_(0),
pre_parse_timer_(NULL),
parsing_on_main_thread_(true) {
@@ -1142,27 +1132,37 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
bool ok = true;
if (shared_info->is_arrow()) {
- // The first expression being parsed is the parameter list of the arrow
- // function. Setting this avoids prevents ExpressionFromIdentifier()
- // from creating unresolved variables in already-resolved scopes.
- parsing_lazy_arrow_parameters_ = true;
- Expression* expression = ParseExpression(false, &ok);
+ Scope* scope = NewScope(scope_, ARROW_SCOPE);
+ scope->set_start_position(shared_info->start_position());
+ FormalParameterErrorLocations error_locs;
+ bool has_rest = false;
+ if (Check(Token::LPAREN)) {
+ // '(' StrictFormalParameters ')'
+ ParseFormalParameterList(scope, &error_locs, &has_rest, &ok);
+ if (ok) ok = Check(Token::RPAREN);
+ } else {
+ // BindingIdentifier
+ ParseFormalParameter(scope, &error_locs, has_rest, &ok);
+ }
+
if (ok) {
- // Scanning must end at the same position that was recorded
- // previously. If not, parsing has been interrupted due to a
- // stack overflow, at which point the partially parsed arrow
- // function concise body happens to be a valid expression. This
- // is a problem only for arrow functions with single statement
- // bodies, since there is no end token such as "}" for normal
- // functions.
- if (scanner()->location().end_pos == shared_info->end_position()) {
- // The pre-parser saw an arrow function here, so the full parser
- // must produce a FunctionLiteral.
- DCHECK(expression->IsFunctionLiteral());
- result = expression->AsFunctionLiteral();
- } else {
- result = NULL;
- ok = false;
+ Expression* expression =
+ ParseArrowFunctionLiteral(scope, error_locs, has_rest, &ok);
+ if (ok) {
+ // Scanning must end at the same position that was recorded
+ // previously. If not, parsing has been interrupted due to a stack
+ // overflow, at which point the partially parsed arrow function
+ // concise body happens to be a valid expression. This is a problem
+ // only for arrow functions with single expression bodies, since there
+ // is no end token such as "}" for normal functions.
+ if (scanner()->location().end_pos == shared_info->end_position()) {
+ // The pre-parser saw an arrow function here, so the full parser
+ // must produce a FunctionLiteral.
+ DCHECK(expression->IsFunctionLiteral());
+ result = expression->AsFunctionLiteral();
+ } else {
+ ok = false;
+ }
}
}
} else if (shared_info->is_default_constructor()) {
@@ -3732,79 +3732,103 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
}
-bool CheckAndDeclareArrowParameter(ParserTraits* traits, Expression* expression,
- Scope* scope, int* num_params,
- FormalParameterErrorLocations* locs) {
- // Case for empty parameter lists:
- // () => ...
- if (expression == NULL) return true;
-
- // Too many parentheses around expression:
- // (( ... )) => ...
- if (expression->is_multi_parenthesized()) return false;
-
- // Case for a single parameter:
- // (foo) => ...
- // foo => ...
- if (expression->IsVariableProxy()) {
- if (expression->AsVariableProxy()->is_this()) return false;
+void ParserTraits::DeclareArrowFunctionParameters(
+ Scope* scope, Expression* expr, const Scanner::Location& params_loc,
+ FormalParameterErrorLocations* error_locs, bool* ok) {
+ if (scope->num_parameters() >= Code::kMaxArguments) {
+ ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
+ *ok = false;
+ return;
+ }
- const AstRawString* raw_name = expression->AsVariableProxy()->raw_name();
- if (traits->IsEvalOrArguments(raw_name) ||
- traits->IsFutureStrictReserved(raw_name))
- return false;
- if (traits->IsUndefined(raw_name) && !locs->undefined.IsValid()) {
- locs->undefined = Scanner::Location(
- expression->position(), expression->position() + raw_name->length());
+ // ArrowFunctionFormals ::
+ // Binary(Token::COMMA, ArrowFunctionFormals, VariableProxy)
+ // VariableProxy
+ //
+ // As we need to visit the parameters in left-to-right order, we recurse on
+ // the left-hand side of comma expressions.
+ //
+ // Sadly, for the various malformed_arrow_function_parameter_list errors, we
+ // can't be more specific on the error message or on the location because we
+ // need to match the pre-parser's behavior.
+ if (expr->IsBinaryOperation()) {
+ BinaryOperation* binop = expr->AsBinaryOperation();
+ if (binop->op() != Token::COMMA) {
+ ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
+ *ok = false;
+ return;
}
-
- // When the variable was seen, it was recorded as unresolved in the outer
- // scope. But it's really not unresolved.
- scope->outer_scope()->RemoveUnresolved(expression->AsVariableProxy());
-
- bool is_rest = false;
- bool is_duplicate = false;
- scope->DeclareParameter(raw_name, VAR, is_rest, &is_duplicate);
- if (is_duplicate) {
- locs->duplicate = Scanner::Location(
- expression->position(), expression->position() + raw_name->length());
- return false;
+ Expression* left = binop->left();
+ Expression* right = binop->right();
+ if (left->is_parenthesized() || right->is_parenthesized()) {
+ ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
+ *ok = false;
+ return;
}
+ DeclareArrowFunctionParameters(scope, left, params_loc, error_locs, ok);
+ if (!*ok) return;
+ // LHS of comma expression should be unparenthesized.
+ expr = right;
+ }
- ++(*num_params);
- return true;
+ // TODO(wingo): Support rest parameters.
+ if (!expr->IsVariableProxy()) {
+ ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
+ *ok = false;
+ return;
}
- // Case for more than one parameter:
- // (foo, bar [, ...]) => ...
- if (expression->IsBinaryOperation()) {
- BinaryOperation* binop = expression->AsBinaryOperation();
- if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() ||
- binop->right()->is_parenthesized())
- return false;
+ const AstRawString* raw_name = expr->AsVariableProxy()->raw_name();
+ Scanner::Location param_location(expr->position(),
+ expr->position() + raw_name->length());
- return CheckAndDeclareArrowParameter(traits, binop->left(), scope,
- num_params, locs) &&
- CheckAndDeclareArrowParameter(traits, binop->right(), scope,
- num_params, locs);
+ if (expr->AsVariableProxy()->is_this()) {
+ ReportMessageAt(param_location, "this_formal_parameter");
+ *ok = false;
+ return;
}
- // Any other kind of expression is not a valid parameter list.
- return false;
+ if (!error_locs->eval_or_arguments.IsValid() && IsEvalOrArguments(raw_name))
+ error_locs->eval_or_arguments = param_location;
+ if (!error_locs->reserved.IsValid() && IsFutureStrictReserved(raw_name))
+ error_locs->reserved = param_location;
+ if (!error_locs->undefined.IsValid() && IsUndefined(raw_name))
+ error_locs->undefined = param_location;
+
+ // When the formal parameter was originally seen, it was parsed as a
+ // VariableProxy and recorded as unresolved in the scope. Here we undo that
+ // parse-time side-effect.
+ parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
+
+ bool is_rest = false;
+ bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest);
+
+ if (is_duplicate) {
+ // Arrow function parameter lists are parsed as StrictFormalParameters,
+ // which means that they cannot have duplicates. Note that this is a subset
+ // of the restrictions placed on parameters to functions whose body is
+ // strict.
+ ReportMessageAt(param_location,
+ "duplicate_arrow_function_formal_parameter");
+ *ok = false;
+ return;
+ }
}
-int ParserTraits::DeclareArrowParametersFromExpression(
- Expression* expression, Scope* scope, FormalParameterErrorLocations* locs,
- bool* ok) {
- int num_params = 0;
- // Always reset the flag: It only needs to be set for the first expression
- // parsed as arrow function parameter list, because only top-level functions
- // are parsed lazily.
- parser_->parsing_lazy_arrow_parameters_ = false;
- *ok =
- CheckAndDeclareArrowParameter(this, expression, scope, &num_params, locs);
- return num_params;
+void ParserTraits::ParseArrowFunctionFormalParameters(
+ Scope* scope, Expression* params, const Scanner::Location& params_loc,
+ FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok) {
+ // Too many parentheses around expression:
+ // (( ... )) => ...
+ if (params->is_multi_parenthesized()) {
+ // TODO(wingo): Make a better message.
+ ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
+ *ok = false;
+ return;
+ }
+
+ DeclareArrowFunctionParameters(scope, params, params_loc, error_locs, ok);
}
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698