 Chromium Code Reviews
 Chromium Code Reviews Issue 1127063003:
  [es6] implement default parameters via desugaring  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1127063003:
  [es6] implement default parameters via desugaring  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/parser.cc | 
| diff --git a/src/parser.cc b/src/parser.cc | 
| index 5e3db128ada4d98a13861b6fcd4bfa37551fdf57..8b68a1dbad498467268702ac7645d6a4300f7a68 100644 | 
| --- a/src/parser.cc | 
| +++ b/src/parser.cc | 
| @@ -876,6 +876,7 @@ Parser::Parser(ParseInfo* info) | 
| set_allow_harmony_rest_params(FLAG_harmony_rest_parameters); | 
| set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls); | 
| set_allow_harmony_destructuring(FLAG_harmony_destructuring); | 
| + set_allow_harmony_optional_params(FLAG_harmony_optional_params); | 
| set_allow_strong_mode(FLAG_strong_mode); | 
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | 
| ++feature) { | 
| @@ -1139,13 +1140,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, | 
| 
wingo
2015/05/11 15:00:48
nit: would be easier to read with named variables
 
caitp (gmail)
2015/05/11 15:34:24
Acknowledged.
 | 
| + &ok); | 
| } | 
| if (ok) { | 
| @@ -2069,6 +2075,11 @@ Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { | 
| } | 
| +void Parser::ShadowParametersForExpressions(Scope* scope) { | 
| + scope->ShadowParametersForExpressions(); | 
| +} | 
| + | 
| + | 
| // Language extension which is only enabled for source files loaded | 
| // through the API's extension mechanism. A native function | 
| // declaration is resolved by looking up the function through a | 
| @@ -3527,6 +3538,109 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( | 
| } | 
| +ZoneList<Statement*>* Parser::DesugarInitializeParameters( | 
| + Scope* scope, bool has_initializers, ZoneList<Expression*>* initializers) { | 
| + DCHECK(scope->is_function_scope()); | 
| + | 
| + if (has_initializers) { | 
| + // If hasParameterExpressions for the function is true, each parameter is | 
| 
wingo
2015/05/11 15:00:48
has_initializers I guess?  I know hasParameterExpr
 
caitp (gmail)
2015/05/11 15:34:24
HasParameterExpressions is also true for Object bi
 | 
| + // 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 | 
| + // | 
| + | 
| + ShadowParametersForExpressions(scope); | 
| + ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(0, zone()); | 
| + 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); | 
| + | 
| + // Lexically declare the initialized variable | 
| + static const VariableMode mode = LET; | 
| + VariableProxy* proxy = | 
| + NewUnresolved(scope->parameter(i)->raw_name(), mode); | 
| + VariableDeclaration* declaration = factory()->NewVariableDeclaration( | 
| + proxy, mode, scope, RelocInfo::kNoPosition); | 
| + bool ok = true; | 
| + proxy = factory()->NewVariableProxy(Declare(declaration, true, &ok), pos); | 
| + DCHECK(ok); | 
| 
wingo
2015/05/11 15:00:48
Seems that Declare can only fail for a var redecla
 
caitp (gmail)
2015/05/11 15:34:24
Acknowledged.
 | 
| + proxy->var()->set_maybe_assigned(); | 
| + | 
| + 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()); | 
| + | 
| + // 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); | 
| + 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::INIT_LET, proxy, arg_or_default, RelocInfo::kNoPosition); | 
| + | 
| + body->Add( | 
| + 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); | 
| + body->Add( | 
| + factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition), | 
| + zone()); | 
| + proxy->var()->set_initializer_position(pos); | 
| + } | 
| + } | 
| + 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 :: | 
| @@ -3937,7 +4051,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) { | 
| // Arrow function parameter lists are parsed as StrictFormalParameters, | 
| @@ -4067,8 +4182,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral( | 
| Expect(Token::LPAREN, CHECK_OK); | 
| int start_position = scanner()->location().beg_pos; | 
| scope_->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; | 
| @@ -4169,8 +4288,21 @@ FunctionLiteral* Parser::ParseFunctionLiteral( | 
| } | 
| } | 
| if (!is_lazily_parsed) { | 
| - body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | 
| - kind, CHECK_OK); | 
| + body = DesugarInitializeParameters(scope, has_initializers, initializers); | 
| + if (has_initializers) { | 
| + // 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); | 
| + scope->set_end_position(function_body_scope->end_position()); | 
| + body->AddAll(*inner_body, 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(); | 
| @@ -4421,6 +4553,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 
| allow_harmony_spreadcalls()); | 
| reusable_preparser_->set_allow_harmony_destructuring( | 
| allow_harmony_destructuring()); | 
| + reusable_preparser_->set_allow_harmony_optional_params( | 
| + allow_harmony_optional_params()); | 
| reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); | 
| } | 
| PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |