Chromium Code Reviews| 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; |
| } |