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

Unified Diff: src/parser.cc

Issue 1104223002: [es6] implement optional parameters via desugaring (with scoping) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Finalize function body scope if it's not needed 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') | src/preparser.cc » ('J')
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 feed1e4b12fcef812309dfe4c4a7870fbcd41a13..513092ff43aa1eda742ed8f9a827c241f5a6ad3c 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1134,13 +1134,18 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
scope->set_start_position(shared_info->start_position());
FormalParameterErrorLocations error_locs;
bool has_rest = false;
+ bool has_initializers = false;
+ ZoneList<Expression*>* initializers =
+ new (zone()) ZoneList<Expression*>(0, zone());
if (Check(Token::LPAREN)) {
// '(' StrictFormalParameters ')'
- ParseFormalParameterList(scope, &error_locs, &has_rest, &ok);
+ ParseFormalParameterList(scope, &error_locs, initializers,
+ &has_initializers, &has_rest, &ok);
if (ok) ok = Check(Token::RPAREN);
} else {
// BindingIdentifier
- ParseFormalParameter(scope, &error_locs, has_rest, &ok);
+ ParseFormalParameter(scope, &error_locs, nullptr, nullptr, has_rest,
+ &ok);
}
if (ok) {
@@ -3963,6 +3968,59 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
}
+ZoneList<Statement*>* Parser::DesugarInitializeParameters(
+ Scope* scope, bool has_initializers, ZoneList<Expression*>* initializers) {
+ ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(0, zone());
+ if (has_initializers) {
+ for (int i = 0; i < initializers->length(); ++i) {
+ Expression* initializer = initializers->at(i);
+ // TODO(caitp): ensure proper TDZ behaviour --- need hole-check for
+ // all parameter bindings, including ones without initializers
+ if (initializer) {
+ // IS_UNDEFINED(%_Arguments(i)) ? <initializer> : %_Arguments(i);
+ const AstRawString* fn_name = ast_value_factory()->empty_string();
+ const Runtime::Function* arguments =
+ Runtime::FunctionForId(Runtime::kInlineArguments);
+ ZoneList<Expression*>* arguments_i0 =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ arguments_i0->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
+ zone());
+
+ ZoneList<Expression*>* arguments_i1 =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ arguments_i1->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
+ zone());
+
+ Expression* arg_or_default = factory()->NewConditional(
+ // condition:
+ factory()->NewCompareOperation(
+ Token::EQ_STRICT,
+ factory()->NewCallRuntime(fn_name, arguments, arguments_i0,
+ RelocInfo::kNoPosition),
+ factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ // if true:
+ initializer,
+ // if false:
+ factory()->NewCallRuntime(fn_name, arguments, arguments_i1,
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+
+ Expression* assign = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(scope->parameter(i),
arv (Not doing code reviews) 2015/05/01 18:31:32 Will this work correctly if someone accesses the a
+ RelocInfo::kNoPosition),
+ arg_or_default, RelocInfo::kNoPosition);
+
+ body->Add(
+ factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition),
+ zone());
+ }
+ }
+ }
+ return body;
+}
+
+
FunctionLiteral* Parser::ParseFunctionLiteral(
const AstRawString* function_name, Scanner::Location function_name_location,
bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
@@ -4028,6 +4086,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
: NewScope(scope_, FUNCTION_SCOPE, kind);
+ Scope* function_body = NewScope(scope, FUNCTION_BODY_SCOPE);
arv (Not doing code reviews) 2015/05/01 18:31:32 rename to function_body_scope
+ DCHECK_EQ(scope->function_body(), function_body);
ZoneList<Statement*>* body = NULL;
int materialized_literal_count = -1;
int expected_property_count = -1;
@@ -4042,6 +4102,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
FunctionState function_state(&function_state_, &scope_, scope, kind,
&function_factory);
scope_->SetScopeName(function_name);
+ function_body->SetScopeName(function_name);
if (is_generator) {
// For generators, allocating variables in contexts is currently a win
@@ -4061,8 +4122,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos;
scope_->set_start_position(start_position);
+ function_body->set_start_position(start_position);
+ ZoneList<Expression*>* initializers =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ bool has_initializers = false;
num_parameters =
- ParseFormalParameterList(scope, &error_locs, &has_rest, CHECK_OK);
+ ParseFormalParameterList(scope, &error_locs, initializers,
+ &has_initializers, &has_rest, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos;
@@ -4092,6 +4158,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
+ DCHECK(scope_->is_function_scope());
scope_->DeclareFunctionVar(fvar_declaration);
}
@@ -4133,26 +4200,41 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
!parenthesized_function_);
parenthesized_function_ = false; // The bit was set for this function only.
- if (is_lazily_parsed) {
- for (Scope* s = scope_->outer_scope();
- s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) {
- s->ForceContextAllocation();
+ {
+ // Use the FUNCTION_BODY scope only if it's needed
+ // TODO(caitp): This is needed when ObjectBindingPatterns with
+ // computed property keys are used as well.
+ Scope* func_scope = has_initializers ? function_body : scope_;
+ if (func_scope != function_body) {
arv (Not doing code reviews) 2015/05/01 18:31:32 use has_initializer instead?
caitp (gmail) 2015/05/01 19:03:35 Sure --- although note the comment above, it gets
+ function_body->FinalizeBlockScope();
arv (Not doing code reviews) 2015/05/01 18:31:33 These are sibling scopes then?
caitp (gmail) 2015/05/01 19:03:35 function_body is a child of scope_ (the FUNCTION_S
}
- SkipLazyFunctionBody(&materialized_literal_count,
- &expected_property_count, CHECK_OK);
- } else {
- body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
- kind, CHECK_OK);
- materialized_literal_count = function_state.materialized_literal_count();
- expected_property_count = function_state.expected_property_count();
- handler_count = function_state.handler_count();
-
- if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
- if (!function_state.super_location().IsValid()) {
- ReportMessageAt(function_name_location,
- "strong_super_call_missing", kReferenceError);
- *ok = false;
- return nullptr;
+ BlockState function_body_state(&scope_, func_scope);
+ if (is_lazily_parsed) {
+ for (Scope* s = scope_->outer_scope();
+ s != nullptr && (s != s->DeclarationScope());
+ s = s->outer_scope()) {
+ s->ForceContextAllocation();
+ }
+ SkipLazyFunctionBody(&materialized_literal_count,
+ &expected_property_count, CHECK_OK);
+ } else {
+ body =
+ DesugarInitializeParameters(scope, has_initializers, initializers);
+ ZoneList<Statement*>* inner_body = ParseEagerFunctionBody(
+ function_name, pos, fvar, fvar_init_op, kind, CHECK_OK);
+ body->AddAll(*inner_body, zone());
+ materialized_literal_count =
+ function_state.materialized_literal_count();
+ expected_property_count = function_state.expected_property_count();
+ handler_count = function_state.handler_count();
+
+ if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
+ if (!function_state.super_location().IsValid()) {
+ ReportMessageAt(function_name_location, "strong_super_call_missing",
+ kReferenceError);
+ *ok = false;
+ return nullptr;
+ }
}
}
}
@@ -4244,6 +4326,10 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
return;
}
scope_->set_end_position(logger.end());
+ if (scope_->is_function_body_scope()) {
+ DCHECK(scope_->outer_scope()->is_function_scope());
+ scope_->outer_scope()->set_end_position(scanner()->location().end_pos);
+ }
Expect(Token::RBRACE, ok);
if (!*ok) {
return;
@@ -4352,6 +4438,10 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
Expect(Token::RBRACE, CHECK_OK);
scope_->set_end_position(scanner()->location().end_pos);
+ if (scope_->is_function_body_scope()) {
+ DCHECK(scope_->outer_scope()->is_function_scope());
+ scope_->outer_scope()->set_end_position(scanner()->location().end_pos);
+ }
return body;
}
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698