 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| OLD | NEW | 
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/v8.h" | 5 #include "src/v8.h" | 
| 6 | 6 | 
| 7 #include "src/api.h" | 7 #include "src/api.h" | 
| 8 #include "src/ast.h" | 8 #include "src/ast.h" | 
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" | 
| 10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" | 
| (...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1127 ? FunctionLiteral::ANONYMOUS_EXPRESSION | 1127 ? FunctionLiteral::ANONYMOUS_EXPRESSION | 
| 1128 : FunctionLiteral::NAMED_EXPRESSION) | 1128 : FunctionLiteral::NAMED_EXPRESSION) | 
| 1129 : FunctionLiteral::DECLARATION; | 1129 : FunctionLiteral::DECLARATION; | 
| 1130 bool ok = true; | 1130 bool ok = true; | 
| 1131 | 1131 | 
| 1132 if (shared_info->is_arrow()) { | 1132 if (shared_info->is_arrow()) { | 
| 1133 Scope* scope = NewScope(scope_, ARROW_SCOPE); | 1133 Scope* scope = NewScope(scope_, ARROW_SCOPE); | 
| 1134 scope->set_start_position(shared_info->start_position()); | 1134 scope->set_start_position(shared_info->start_position()); | 
| 1135 FormalParameterErrorLocations error_locs; | 1135 FormalParameterErrorLocations error_locs; | 
| 1136 bool has_rest = false; | 1136 bool has_rest = false; | 
| 1137 bool has_initializers = false; | |
| 1138 ZoneList<Expression*>* initializers = | |
| 1139 new (zone()) ZoneList<Expression*>(0, zone()); | |
| 1137 if (Check(Token::LPAREN)) { | 1140 if (Check(Token::LPAREN)) { | 
| 1138 // '(' StrictFormalParameters ')' | 1141 // '(' StrictFormalParameters ')' | 
| 1139 ParseFormalParameterList(scope, &error_locs, &has_rest, &ok); | 1142 ParseFormalParameterList(scope, &error_locs, initializers, | 
| 1143 &has_initializers, &has_rest, &ok); | |
| 1140 if (ok) ok = Check(Token::RPAREN); | 1144 if (ok) ok = Check(Token::RPAREN); | 
| 1141 } else { | 1145 } else { | 
| 1142 // BindingIdentifier | 1146 // BindingIdentifier | 
| 1143 ParseFormalParameter(scope, &error_locs, has_rest, &ok); | 1147 ParseFormalParameter(scope, &error_locs, nullptr, nullptr, has_rest, | 
| 1148 &ok); | |
| 1144 } | 1149 } | 
| 1145 | 1150 | 
| 1146 if (ok) { | 1151 if (ok) { | 
| 1147 ExpressionClassifier classifier; | 1152 ExpressionClassifier classifier; | 
| 1148 Expression* expression = ParseArrowFunctionLiteral( | 1153 Expression* expression = ParseArrowFunctionLiteral( | 
| 1149 scope, error_locs, has_rest, &classifier, &ok); | 1154 scope, error_locs, has_rest, &classifier, &ok); | 
| 1150 ValidateExpression(&classifier, &ok); | 1155 ValidateExpression(&classifier, &ok); | 
| 1151 if (ok) { | 1156 if (ok) { | 
| 1152 // Scanning must end at the same position that was recorded | 1157 // Scanning must end at the same position that was recorded | 
| 1153 // previously. If not, parsing has been interrupted due to a stack | 1158 // previously. If not, parsing has been interrupted due to a stack | 
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2057 // initialization code. Thus, inside the 'with' statement, we need | 2062 // initialization code. Thus, inside the 'with' statement, we need | 
| 2058 // both access to the static and the dynamic context chain; the | 2063 // both access to the static and the dynamic context chain; the | 
| 2059 // runtime needs to provide both. | 2064 // runtime needs to provide both. | 
| 2060 if (resolve && var != NULL) { | 2065 if (resolve && var != NULL) { | 
| 2061 proxy->BindTo(var); | 2066 proxy->BindTo(var); | 
| 2062 } | 2067 } | 
| 2063 return var; | 2068 return var; | 
| 2064 } | 2069 } | 
| 2065 | 2070 | 
| 2066 | 2071 | 
| 2072 void Parser::ShadowParametersForExpressions(Scope* scope) { | |
| 2073 scope->ShadowParametersForExpressions(); | |
| 2074 } | |
| 2075 | |
| 2076 | |
| 2067 // Language extension which is only enabled for source files loaded | 2077 // Language extension which is only enabled for source files loaded | 
| 2068 // through the API's extension mechanism. A native function | 2078 // through the API's extension mechanism. A native function | 
| 2069 // declaration is resolved by looking up the function through a | 2079 // declaration is resolved by looking up the function through a | 
| 2070 // callback provided by the extension. | 2080 // callback provided by the extension. | 
| 2071 Statement* Parser::ParseNativeDeclaration(bool* ok) { | 2081 Statement* Parser::ParseNativeDeclaration(bool* ok) { | 
| 2072 int pos = peek_position(); | 2082 int pos = peek_position(); | 
| 2073 Expect(Token::FUNCTION, CHECK_OK); | 2083 Expect(Token::FUNCTION, CHECK_OK); | 
| 2074 // Allow "eval" or "arguments" for backward compatibility. | 2084 // Allow "eval" or "arguments" for backward compatibility. | 
| 2075 const AstRawString* name = | 2085 const AstRawString* name = | 
| 2076 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2086 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 
| (...skipping 1438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3515 | 3525 | 
| 3516 inner_scope->set_end_position(scanner()->location().end_pos); | 3526 inner_scope->set_end_position(scanner()->location().end_pos); | 
| 3517 inner_block->set_scope(inner_scope); | 3527 inner_block->set_scope(inner_scope); | 
| 3518 scope_ = for_scope; | 3528 scope_ = for_scope; | 
| 3519 | 3529 | 
| 3520 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 3530 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 
| 3521 return outer_block; | 3531 return outer_block; | 
| 3522 } | 3532 } | 
| 3523 | 3533 | 
| 3524 | 3534 | 
| 3535 ZoneList<Statement*>* Parser::DesugarInitializeParameters( | |
| 3536 Scope* scope, bool has_initializers, ZoneList<Expression*>* initializers) { | |
| 3537 DCHECK(scope->is_function_scope()); | |
| 3538 | |
| 
arv (Not doing code reviews)
2015/05/06 20:32:38
How about adding a comment block explaining how th
 | |
| 3539 if (has_initializers) { | |
| 3540 ShadowParametersForExpressions(scope); | |
| 3541 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(0, zone()); | |
| 3542 for (int i = 0; i < initializers->length(); ++i) { | |
| 3543 Expression* initializer = initializers->at(i); | |
| 3544 | |
| 3545 // Position of parameter VariableProxy, for hole-checking | |
| 3546 int pos = scope->parameter_position(i); | |
| 3547 | |
| 3548 // Lexically declare the initialized variable | |
| 3549 static const VariableMode mode = LET; | |
| 3550 VariableProxy* proxy = | |
| 3551 NewUnresolved(scope->parameter(i)->raw_name(), mode); | |
| 3552 VariableDeclaration* declaration = factory()->NewVariableDeclaration( | |
| 3553 proxy, mode, scope, RelocInfo::kNoPosition); | |
| 3554 bool ok = true; | |
| 3555 proxy = factory()->NewVariableProxy(Declare(declaration, true, &ok), pos); | |
| 3556 DCHECK(ok); | |
| 3557 proxy->var()->set_maybe_assigned(); | |
| 3558 | |
| 3559 const AstRawString* fn_name = ast_value_factory()->empty_string(); | |
| 3560 const Runtime::Function* arguments = | |
| 3561 Runtime::FunctionForId(Runtime::kInlineArguments); | |
| 
arv (Not doing code reviews)
2015/05/06 20:32:38
I think Andreas wanted:
function f(x = expr) {}
 
caitp (gmail)
2015/05/06 20:42:55
I don't think bounds-checking is needed --- at lea
 | |
| 3562 ZoneList<Expression*>* arguments_i0 = | |
| 3563 new (zone()) ZoneList<Expression*>(0, zone()); | |
| 3564 arguments_i0->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition), | |
| 3565 zone()); | |
| 3566 | |
| 3567 // TODO(caitp): ensure proper TDZ behaviour --- need hole-check for | |
| 3568 // all parameter bindings, including ones without initializers | |
| 3569 if (initializer) { | |
| 3570 // IS_UNDEFINED(%_Arguments(i)) ? <initializer> : %_Arguments(i); | |
| 3571 ZoneList<Expression*>* arguments_i1 = | |
| 3572 new (zone()) ZoneList<Expression*>(0, zone()); | |
| 3573 arguments_i1->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition), | |
| 3574 zone()); | |
| 3575 | |
| 3576 Expression* arg_or_default = factory()->NewConditional( | |
| 3577 // condition: | |
| 3578 factory()->NewCompareOperation( | |
| 3579 Token::EQ_STRICT, | |
| 3580 factory()->NewCallRuntime(fn_name, arguments, arguments_i0, | |
| 3581 RelocInfo::kNoPosition), | |
| 3582 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | |
| 3583 RelocInfo::kNoPosition), | |
| 3584 // if true: | |
| 3585 initializer, | |
| 3586 // if false: | |
| 3587 factory()->NewCallRuntime(fn_name, arguments, arguments_i1, | |
| 3588 RelocInfo::kNoPosition), | |
| 3589 RelocInfo::kNoPosition); | |
| 3590 | |
| 3591 Expression* assign = factory()->NewAssignment( | |
| 3592 Token::INIT_LET, proxy, arg_or_default, RelocInfo::kNoPosition); | |
| 3593 | |
| 3594 body->Add( | |
| 3595 factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition), | |
| 3596 zone()); | |
| 3597 proxy->var()->set_initializer_position(initializer->position()); | |
| 3598 } else { | |
| 3599 // let <name> = %_Arguments(i) | |
| 3600 Expression* assign = factory()->NewAssignment( | |
| 3601 Token::INIT_LET, proxy, | |
| 3602 factory()->NewCallRuntime(fn_name, arguments, arguments_i0, | |
| 3603 RelocInfo::kNoPosition), | |
| 3604 RelocInfo::kNoPosition); | |
| 3605 body->Add( | |
| 3606 factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition), | |
| 3607 zone()); | |
| 3608 proxy->var()->set_initializer_position(pos); | |
| 3609 } | |
| 3610 } | |
| 3611 return body; | |
| 3612 } else { | |
| 
arv (Not doing code reviews)
2015/05/06 20:32:38
no else after return
 | |
| 3613 // If hasParameterExpressions is false, remove the unnecessary parameter | |
| 3614 // block scopes. | |
| 3615 ZoneList<Scope*>* scopes = scope->inner_scopes(); | |
| 3616 for (int i = 0; i < scopes->length(); ++i) { | |
| 3617 Scope* scope = scopes->at(i); | |
| 3618 DCHECK(scope->is_block_scope()); | |
| 3619 scope->FinalizeBlockScope(); | |
| 3620 } | |
| 3621 return nullptr; | |
| 3622 } | |
| 3623 } | |
| 3624 | |
| 3625 | |
| 3525 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3626 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 
| 3526 bool* ok) { | 3627 bool* ok) { | 
| 3527 // ForStatement :: | 3628 // ForStatement :: | 
| 3528 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3629 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 
| 3529 | 3630 | 
| 3530 int stmt_pos = peek_position(); | 3631 int stmt_pos = peek_position(); | 
| 3531 bool is_const = false; | 3632 bool is_const = false; | 
| 3532 Statement* init = NULL; | 3633 Statement* init = NULL; | 
| 3533 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | 3634 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | 
| 3534 | 3635 | 
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3925 error_locs->reserved = param_location; | 4026 error_locs->reserved = param_location; | 
| 3926 if (!error_locs->undefined.IsValid() && IsUndefined(raw_name)) | 4027 if (!error_locs->undefined.IsValid() && IsUndefined(raw_name)) | 
| 3927 error_locs->undefined = param_location; | 4028 error_locs->undefined = param_location; | 
| 3928 | 4029 | 
| 3929 // When the formal parameter was originally seen, it was parsed as a | 4030 // When the formal parameter was originally seen, it was parsed as a | 
| 3930 // VariableProxy and recorded as unresolved in the scope. Here we undo that | 4031 // VariableProxy and recorded as unresolved in the scope. Here we undo that | 
| 3931 // parse-time side-effect. | 4032 // parse-time side-effect. | 
| 3932 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); | 4033 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); | 
| 3933 | 4034 | 
| 3934 bool is_rest = false; | 4035 bool is_rest = false; | 
| 3935 bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest); | 4036 int pos = expr->position(); | 
| 4037 bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest, pos); | |
| 3936 | 4038 | 
| 3937 if (is_duplicate) { | 4039 if (is_duplicate) { | 
| 3938 // Arrow function parameter lists are parsed as StrictFormalParameters, | 4040 // Arrow function parameter lists are parsed as StrictFormalParameters, | 
| 3939 // which means that they cannot have duplicates. Note that this is a subset | 4041 // which means that they cannot have duplicates. Note that this is a subset | 
| 3940 // of the restrictions placed on parameters to functions whose body is | 4042 // of the restrictions placed on parameters to functions whose body is | 
| 3941 // strict. | 4043 // strict. | 
| 3942 ReportMessageAt(param_location, | 4044 ReportMessageAt(param_location, | 
| 3943 "duplicate_arrow_function_formal_parameter"); | 4045 "duplicate_arrow_function_formal_parameter"); | 
| 3944 *ok = false; | 4046 *ok = false; | 
| 3945 return; | 4047 return; | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4054 // expressions. This also marks the FunctionState as a generator. | 4156 // expressions. This also marks the FunctionState as a generator. | 
| 4055 Variable* temp = scope_->DeclarationScope()->NewTemporary( | 4157 Variable* temp = scope_->DeclarationScope()->NewTemporary( | 
| 4056 ast_value_factory()->dot_generator_object_string()); | 4158 ast_value_factory()->dot_generator_object_string()); | 
| 4057 function_state.set_generator_object_variable(temp); | 4159 function_state.set_generator_object_variable(temp); | 
| 4058 } | 4160 } | 
| 4059 | 4161 | 
| 4060 bool has_rest = false; | 4162 bool has_rest = false; | 
| 4061 Expect(Token::LPAREN, CHECK_OK); | 4163 Expect(Token::LPAREN, CHECK_OK); | 
| 4062 int start_position = scanner()->location().beg_pos; | 4164 int start_position = scanner()->location().beg_pos; | 
| 4063 scope_->set_start_position(start_position); | 4165 scope_->set_start_position(start_position); | 
| 4166 ZoneList<Expression*>* initializers = | |
| 4167 new (zone()) ZoneList<Expression*>(0, zone()); | |
| 4168 bool has_initializers = false; | |
| 4064 num_parameters = | 4169 num_parameters = | 
| 4065 ParseFormalParameterList(scope, &error_locs, &has_rest, CHECK_OK); | 4170 ParseFormalParameterList(scope, &error_locs, initializers, | 
| 4171 &has_initializers, &has_rest, CHECK_OK); | |
| 4066 Expect(Token::RPAREN, CHECK_OK); | 4172 Expect(Token::RPAREN, CHECK_OK); | 
| 4067 int formals_end_position = scanner()->location().end_pos; | 4173 int formals_end_position = scanner()->location().end_pos; | 
| 4068 | 4174 | 
| 4069 CheckArityRestrictions(num_parameters, arity_restriction, start_position, | 4175 CheckArityRestrictions(num_parameters, arity_restriction, start_position, | 
| 4070 formals_end_position, CHECK_OK); | 4176 formals_end_position, CHECK_OK); | 
| 4071 | 4177 | 
| 4072 Expect(Token::LBRACE, CHECK_OK); | 4178 Expect(Token::LBRACE, CHECK_OK); | 
| 4073 | 4179 | 
| 4074 // If we have a named function expression, we add a local variable | 4180 // If we have a named function expression, we add a local variable | 
| 4075 // declaration to the body of the function with the name of the | 4181 // declaration to the body of the function with the name of the | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4134 parenthesized_function_ = false; // The bit was set for this function only. | 4240 parenthesized_function_ = false; // The bit was set for this function only. | 
| 4135 | 4241 | 
| 4136 if (is_lazily_parsed) { | 4242 if (is_lazily_parsed) { | 
| 4137 for (Scope* s = scope_->outer_scope(); | 4243 for (Scope* s = scope_->outer_scope(); | 
| 4138 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { | 4244 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { | 
| 4139 s->ForceContextAllocation(); | 4245 s->ForceContextAllocation(); | 
| 4140 } | 4246 } | 
| 4141 SkipLazyFunctionBody(&materialized_literal_count, | 4247 SkipLazyFunctionBody(&materialized_literal_count, | 
| 4142 &expected_property_count, CHECK_OK); | 4248 &expected_property_count, CHECK_OK); | 
| 4143 } else { | 4249 } else { | 
| 4144 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | 4250 body = DesugarInitializeParameters(scope, has_initializers, initializers); | 
| 4145 kind, CHECK_OK); | 4251 if (has_initializers) { | 
| 4252 // TODO(caitp): Function body scope must be a declaration scope | |
| 4253 Scope* function_body_scope = NewScope(scope, BLOCK_SCOPE); | |
| 4254 function_body_scope->set_start_position(scope->start_position()); | |
| 4255 function_body_scope->SetScopeName(function_name); | |
| 4256 BlockState function_body_state(&scope_, function_body_scope); | |
| 4257 ZoneList<Statement*>* inner_body = ParseEagerFunctionBody( | |
| 4258 function_name, pos, fvar, fvar_init_op, kind, CHECK_OK); | |
| 4259 scope->set_end_position(function_body_scope->end_position()); | |
| 4260 body->AddAll(*inner_body, zone()); | |
| 4261 } else { | |
| 4262 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | |
| 4263 kind, CHECK_OK); | |
| 4264 } | |
| 4146 materialized_literal_count = function_state.materialized_literal_count(); | 4265 materialized_literal_count = function_state.materialized_literal_count(); | 
| 4147 expected_property_count = function_state.expected_property_count(); | 4266 expected_property_count = function_state.expected_property_count(); | 
| 4148 handler_count = function_state.handler_count(); | 4267 handler_count = function_state.handler_count(); | 
| 4149 | 4268 | 
| 4150 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | 4269 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | 
| 4151 if (!function_state.super_location().IsValid()) { | 4270 if (!function_state.super_location().IsValid()) { | 
| 4152 ReportMessageAt(function_name_location, | 4271 ReportMessageAt(function_name_location, | 
| 4153 "strong_super_call_missing", kReferenceError); | 4272 "strong_super_call_missing", kReferenceError); | 
| 4154 *ok = false; | 4273 *ok = false; | 
| 4155 return nullptr; | 4274 return nullptr; | 
| (...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5891 | 6010 | 
| 5892 Expression* Parser::SpreadCallNew(Expression* function, | 6011 Expression* Parser::SpreadCallNew(Expression* function, | 
| 5893 ZoneList<v8::internal::Expression*>* args, | 6012 ZoneList<v8::internal::Expression*>* args, | 
| 5894 int pos) { | 6013 int pos) { | 
| 5895 args->InsertAt(0, function, zone()); | 6014 args->InsertAt(0, function, zone()); | 
| 5896 | 6015 | 
| 5897 return factory()->NewCallRuntime( | 6016 return factory()->NewCallRuntime( | 
| 5898 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 6017 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 
| 5899 } | 6018 } | 
| 5900 } } // namespace v8::internal | 6019 } } // namespace v8::internal | 
| OLD | NEW |