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; |
} |