Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index ee0f7dc6804848109197ed9878835d791e3d77f4..358a946e1c05e73afb332c9d64d616938db970c5 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -879,6 +879,7 @@ Parser::Parser(ParseInfo* info) |
| set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls); |
| set_allow_harmony_destructuring(FLAG_harmony_destructuring); |
| set_allow_harmony_spread_arrays(FLAG_harmony_spread_arrays); |
| + set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); |
| set_allow_strong_mode(FLAG_strong_mode); |
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; |
| ++feature) { |
| @@ -1142,9 +1143,13 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, |
| scope->set_start_position(shared_info->start_position()); |
| ExpressionClassifier formals_classifier; |
| bool has_rest = false; |
| + bool hasParameterExpressions = false; |
|
adamk
2015/05/26 19:58:10
Same style nit, use_underscores. I think this show
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + ZoneList<Expression*>* initializers = |
|
adamk
2015/05/26 19:58:10
Please add a TODO here, since you're just dropping
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + new (zone()) ZoneList<Expression*>(0, zone()); |
| if (Check(Token::LPAREN)) { |
| // '(' StrictFormalParameters ')' |
| - ParseFormalParameterList(scope, &has_rest, &formals_classifier, &ok); |
| + ParseFormalParameterList(scope, initializers, &hasParameterExpressions, |
| + &has_rest, &formals_classifier, &ok); |
| if (ok) ok = Check(Token::RPAREN); |
| } else { |
| // BindingIdentifier |
| @@ -3398,6 +3403,114 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| } |
| +ZoneList<Statement*>* Parser::DesugarInitializeParameters( |
| + Scope* scope, bool hasParameterExpressions, |
| + ZoneList<Expression*>* initializers) { |
| + DCHECK(scope->is_function_scope()); |
| + |
| + if (hasParameterExpressions) { |
| + // If hasParameterExpressions for the function is true, each parameter is |
| + // desugared as follows: |
| + // |
| + // SingleNameBinding : |
| + // let <name> = %_Arguments(<index>); |
| + // SingleNameBinding Initializer |
| + // let <name> = IS_UNDEFINED(%_Arguments(<index>)) ? <initializer> |
| + // : %_Arguments(<index>); |
| + // |
| + // TODO(caitp, dslomov): support BindingPatterns & rest parameters |
| + // |
| + scope->UndeclareParametersForExpressions(); |
| + ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(0, zone()); |
|
adamk
2015/05/26 19:58:10
Don't you know how big a list you need here (initi
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + for (int i = 0; i < initializers->length(); ++i) { |
| + Expression* initializer = initializers->at(i); |
| + |
| + // Position of parameter VariableProxy, for hole-checking |
| + int pos = scope->parameter_position(i); |
| + |
| + static const int capacity = 1; |
|
adamk
2015/05/26 19:58:10
More style nits: kCapacity
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + static const bool is_initializer_block = true; // ? |
|
adamk
2015/05/26 19:58:10
kIsInitializerBlock.
Also the "// ?" should eithe
caitp (gmail)
2015/05/26 20:24:44
Done. The "?" comment is a reminder to ask what th
|
| + Block* param_block = |
| + factory()->NewBlock(nullptr, capacity, is_initializer_block, pos); |
| + |
| + static const VariableMode mode = LET; |
|
adamk
2015/05/26 19:58:10
kMode (though I'm not sure this adds much)
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + VariableProxy* proxy = |
| + NewUnresolved(scope->parameter(i)->raw_name(), mode); |
| + VariableDeclaration* declaration = factory()->NewVariableDeclaration( |
| + proxy, mode, scope, RelocInfo::kNoPosition); |
| + |
| + bool ok = true; |
| + // All formal parameters have been removed from the scope VariableMap, |
| + // and so Declare() should not be able to fail. |
| + proxy = factory()->NewVariableProxy(Declare(declaration, true, &ok), pos); |
| + DCHECK(ok); |
| + |
| + 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()); |
|
adamk
2015/05/26 19:58:10
s/0/1/ for the capacity arg here.
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + arguments_i0->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition), |
| + zone()); |
| + |
| + if (initializer) { |
|
adamk
2015/05/26 19:58:10
if (initializer != nullptr)
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + // IS_UNDEFINED(%_Arguments(i)) ? <initializer> : %_Arguments(i); |
| + ZoneList<Expression*>* arguments_i1 = |
| + new (zone()) ZoneList<Expression*>(0, zone()); |
|
adamk
2015/05/26 19:58:10
s/0/1/ again.
caitp (gmail)
2015/05/26 20:24:44
Done.
|
| + 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::INIT_LET, proxy, arg_or_default, RelocInfo::kNoPosition); |
| + |
| + param_block->AddStatement( |
| + factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition), |
| + zone()); |
| + proxy->var()->set_initializer_position(initializer->position()); |
| + } else { |
| + // let <name> = %_Arguments(i) |
| + Expression* assign = factory()->NewAssignment( |
| + Token::INIT_LET, proxy, |
| + factory()->NewCallRuntime(fn_name, arguments, arguments_i0, |
| + RelocInfo::kNoPosition), |
| + RelocInfo::kNoPosition); |
| + param_block->AddStatement( |
| + factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition), |
| + zone()); |
| + proxy->var()->set_initializer_position(pos); |
| + } |
| + body->Add(param_block, zone()); |
| + } |
| + return body; |
| + } else { |
| + // If hasParameterExpressions is false, remove the unnecessary parameter |
| + // block scopes. |
| + ZoneList<Scope*>* scopes = scope->inner_scopes(); |
| + for (int i = 0; i < scopes->length(); ++i) { |
| + Scope* scope = scopes->at(i); |
| + DCHECK(scope->is_block_scope()); |
| + scope->FinalizeBlockScope(); |
| + } |
| + return nullptr; |
| + } |
| +} |
| + |
| + |
| Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| bool* ok) { |
| // ForStatement :: |
| @@ -3768,7 +3881,8 @@ void ParserTraits::DeclareArrowFunctionParameters( |
| parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); |
| bool is_rest = false; |
| - bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest); |
| + int pos = expr->position(); |
| + bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest, pos); |
| if (is_duplicate && !duplicate_loc->IsValid()) { |
| *duplicate_loc = param_location; |
| @@ -3882,8 +3996,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| Expect(Token::LPAREN, CHECK_OK); |
| int start_position = scanner()->location().beg_pos; |
| scope_->set_start_position(start_position); |
| - num_parameters = ParseFormalParameterList(scope, &has_rest, |
| - &formals_classifier, CHECK_OK); |
| + ZoneList<Expression*>* initializers = |
| + new (zone()) ZoneList<Expression*>(0, zone()); |
| + bool hasParameterExpressions = false; |
| + num_parameters = |
| + ParseFormalParameterList(scope, initializers, &hasParameterExpressions, |
| + &has_rest, &formals_classifier, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| int formals_end_position = scanner()->location().end_pos; |
| @@ -3984,8 +4102,31 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| } |
| } |
| if (!is_lazily_parsed) { |
| - body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, |
| - kind, CHECK_OK); |
| + body = DesugarInitializeParameters(scope, hasParameterExpressions, |
| + initializers); |
| + if (hasParameterExpressions) { |
| + // TODO(caitp): Function body scope must be a declaration scope |
| + Scope* function_body_scope = NewScope(scope, BLOCK_SCOPE); |
| + function_body_scope->set_start_position(scope->start_position()); |
| + function_body_scope->SetScopeName(function_name); |
| + BlockState function_body_state(&scope_, function_body_scope); |
| + ZoneList<Statement*>* inner_body = ParseEagerFunctionBody( |
| + function_name, pos, fvar, fvar_init_op, kind, CHECK_OK); |
| + |
| + // Declare Block node |
| + Block* block = |
| + factory()->NewBlock(nullptr, inner_body->length(), false, pos); |
| + block->set_scope(function_body_scope); |
| + for (int i = 0; i < inner_body->length(); ++i) { |
| + block->AddStatement(inner_body->at(i), zone()); |
| + } |
| + |
| + scope->set_end_position(function_body_scope->end_position()); |
| + body->Add(block, zone()); |
| + } 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(); |
| @@ -4269,6 +4410,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| allow_harmony_destructuring()); |
| reusable_preparser_->set_allow_harmony_spread_arrays( |
| allow_harmony_spread_arrays()); |
| + reusable_preparser_->set_allow_harmony_default_parameters( |
| + allow_harmony_default_parameters()); |
| reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); |
| } |
| PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |