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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 if (compile_options_ == ScriptCompiler::kNoCompileOptions) { | 143 if (compile_options_ == ScriptCompiler::kNoCompileOptions) { |
144 cached_parse_data_ = NULL; | 144 cached_parse_data_ = NULL; |
145 } else { | 145 } else { |
146 DCHECK(info->cached_data() != NULL); | 146 DCHECK(info->cached_data() != NULL); |
147 if (compile_options_ == ScriptCompiler::kConsumeParserCache) { | 147 if (compile_options_ == ScriptCompiler::kConsumeParserCache) { |
148 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); | 148 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); |
149 } | 149 } |
150 } | 150 } |
151 } | 151 } |
152 | 152 |
| 153 Expression* Parser::CallClassFieldInitializer(Scope* scope, |
| 154 Expression* this_expr) { |
| 155 // This produces the expression |
| 156 // `.class_field_intializer(this_expr)`, where '.class_field_intializer' is |
| 157 // the name |
| 158 // of a synthetic variable. |
| 159 // 'this_expr' will be 'this' in a base constructor and the result of calling |
| 160 // 'super' in a derived one. |
| 161 const AstRawString* init_fn_name = |
| 162 ast_value_factory()->dot_class_field_init_string(); |
| 163 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name); |
| 164 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 165 args->Add(init_fn_proxy, zone()); |
| 166 args->Add(this_expr, zone()); |
| 167 return factory()->NewCallRuntime(Runtime::kInlineCall, args, |
| 168 kNoSourcePosition); |
| 169 } |
| 170 |
| 171 Expression* Parser::RewriteSuperCall(Expression* super_call) { |
| 172 // TODO(bakkot) find a way to avoid this for classes without fields. |
| 173 if (!allow_harmony_class_fields()) { |
| 174 return super_call; |
| 175 } |
| 176 // This turns a super call `super()` into a do expression of the form |
| 177 // do { |
| 178 // tmp x = super(); |
| 179 // if (.class-field-init) |
| 180 // .class-field-init(x) |
| 181 // x; // This isn't actually present; our do-expression representation |
| 182 // allows specifying that the expression returns x directly. |
| 183 // } |
| 184 Variable* var_tmp = |
| 185 scope()->NewTemporary(ast_value_factory()->empty_string()); |
| 186 Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 187 Assignment* assignment = factory()->NewAssignment( |
| 188 Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call, |
| 189 kNoSourcePosition); |
| 190 block->statements()->Add( |
| 191 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone()); |
| 192 const AstRawString* init_fn_name = |
| 193 ast_value_factory()->dot_class_field_init_string(); |
| 194 VariableProxy* init_fn_proxy = |
| 195 scope()->NewUnresolved(factory(), init_fn_name); |
| 196 Expression* condition = init_fn_proxy; |
| 197 Statement* initialize = factory()->NewExpressionStatement( |
| 198 CallClassFieldInitializer(scope(), factory()->NewVariableProxy(var_tmp)), |
| 199 kNoSourcePosition); |
| 200 IfStatement* if_statement = factory()->NewIfStatement( |
| 201 condition, initialize, factory()->NewEmptyStatement(kNoSourcePosition), |
| 202 kNoSourcePosition); |
| 203 block->statements()->Add(if_statement, zone()); |
| 204 return factory()->NewDoExpression(block, var_tmp, kNoSourcePosition); |
| 205 } |
| 206 |
153 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, | 207 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, |
154 bool call_super, | 208 bool call_super, |
155 bool requires_class_field_init, | 209 bool requires_class_field_init, |
156 int pos, int end_pos, | 210 int pos, int end_pos, |
157 LanguageMode language_mode) { | 211 LanguageMode language_mode) { |
158 int materialized_literal_count = -1; | 212 int materialized_literal_count = -1; |
159 int expected_property_count = -1; | 213 int expected_property_count = -1; |
160 int parameter_count = 0; | 214 int parameter_count = 0; |
161 if (name == nullptr) name = ast_value_factory()->empty_string(); | 215 if (name == nullptr) name = ast_value_factory()->empty_string(); |
162 | 216 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 args->Add(super_constructor, zone()); | 253 args->Add(super_constructor, zone()); |
200 Spread* spread_args = factory()->NewSpread( | 254 Spread* spread_args = factory()->NewSpread( |
201 factory()->NewVariableProxy(constructor_args), pos, pos); | 255 factory()->NewVariableProxy(constructor_args), pos, pos); |
202 ZoneList<Expression*>* spread_args_expr = | 256 ZoneList<Expression*>* spread_args_expr = |
203 new (zone()) ZoneList<Expression*>(1, zone()); | 257 new (zone()) ZoneList<Expression*>(1, zone()); |
204 spread_args_expr->Add(spread_args, zone()); | 258 spread_args_expr->Add(spread_args, zone()); |
205 args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone()); | 259 args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone()); |
206 VariableProxy* new_target_proxy = | 260 VariableProxy* new_target_proxy = |
207 NewUnresolved(ast_value_factory()->new_target_string(), pos); | 261 NewUnresolved(ast_value_factory()->new_target_string(), pos); |
208 args->Add(new_target_proxy, zone()); | 262 args->Add(new_target_proxy, zone()); |
209 CallRuntime* call = factory()->NewCallRuntime( | 263 Expression* call = factory()->NewCallRuntime( |
210 Context::REFLECT_CONSTRUCT_INDEX, args, pos); | 264 Context::REFLECT_CONSTRUCT_INDEX, args, pos); |
| 265 if (requires_class_field_init) { |
| 266 call = CallClassFieldInitializer(scope(), call); |
| 267 } |
211 body->Add(factory()->NewReturnStatement(call, pos), zone()); | 268 body->Add(factory()->NewReturnStatement(call, pos), zone()); |
212 } | 269 } |
213 | 270 |
214 materialized_literal_count = function_state.materialized_literal_count(); | 271 materialized_literal_count = function_state.materialized_literal_count(); |
215 expected_property_count = function_state.expected_property_count(); | 272 expected_property_count = function_state.expected_property_count(); |
216 } | 273 } |
217 | 274 |
218 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 275 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
219 name, function_scope, body, materialized_literal_count, | 276 name, function_scope, body, materialized_literal_count, |
220 expected_property_count, parameter_count, | 277 expected_property_count, parameter_count, |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 // must produce a FunctionLiteral. | 961 // must produce a FunctionLiteral. |
905 DCHECK(expression->IsFunctionLiteral()); | 962 DCHECK(expression->IsFunctionLiteral()); |
906 result = expression->AsFunctionLiteral(); | 963 result = expression->AsFunctionLiteral(); |
907 } else { | 964 } else { |
908 ok = false; | 965 ok = false; |
909 } | 966 } |
910 } | 967 } |
911 } | 968 } |
912 } else if (info->is_default_constructor()) { | 969 } else if (info->is_default_constructor()) { |
913 DCHECK_EQ(scope(), outer); | 970 DCHECK_EQ(scope(), outer); |
| 971 bool is_subclass_constructor = |
| 972 IsSubclassConstructor(info->function_kind()); |
914 result = DefaultConstructor( | 973 result = DefaultConstructor( |
915 raw_name, IsSubclassConstructor(info->function_kind()), | 974 raw_name, is_subclass_constructor, info->requires_class_field_init(), |
916 info->requires_class_field_init(), info->start_position(), | 975 info->start_position(), info->end_position(), info->language_mode()); |
917 info->end_position(), info->language_mode()); | 976 if (!is_subclass_constructor && info->requires_class_field_init()) { |
| 977 result = InsertClassFieldInitializer(result); |
| 978 } |
| 979 } else if (info->is_class_field_initializer()) { |
| 980 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 981 DCHECK(!shared_info.is_null()); |
| 982 if (shared_info->length() == 0) { |
| 983 result = ParseClassFieldForInitializer( |
| 984 info->start_position() != info->end_position(), &ok); |
| 985 } else { |
| 986 result = SynthesizeClassFieldInitializer(shared_info->length()); |
| 987 } |
918 } else { | 988 } else { |
919 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), | 989 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), |
920 kSkipFunctionNameCheck, | 990 kSkipFunctionNameCheck, |
921 info->function_kind(), kNoSourcePosition, | 991 info->function_kind(), kNoSourcePosition, |
922 function_type, info->language_mode(), &ok); | 992 function_type, info->language_mode(), &ok); |
| 993 if (info->requires_class_field_init()) { |
| 994 result = InsertClassFieldInitializer(result); |
| 995 } |
923 } | 996 } |
924 // Make sure the results agree. | 997 // Make sure the results agree. |
925 DCHECK(ok == (result != nullptr)); | 998 DCHECK(ok == (result != nullptr)); |
926 } | 999 } |
927 | 1000 |
928 // Make sure the target stack is empty. | 1001 // Make sure the target stack is empty. |
929 DCHECK_NULL(target_stack_); | 1002 DCHECK_NULL(target_stack_); |
930 return result; | 1003 return result; |
931 } | 1004 } |
932 | 1005 |
(...skipping 3255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4188 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 4261 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
4189 language_mode(), function_state_->kind(), | 4262 language_mode(), function_state_->kind(), |
4190 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, | 4263 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, |
4191 logger, may_abort, use_counts_); | 4264 logger, may_abort, use_counts_); |
4192 if (pre_parse_timer_ != NULL) { | 4265 if (pre_parse_timer_ != NULL) { |
4193 pre_parse_timer_->Stop(); | 4266 pre_parse_timer_->Stop(); |
4194 } | 4267 } |
4195 return result; | 4268 return result; |
4196 } | 4269 } |
4197 | 4270 |
| 4271 Expression* Parser::InstallHomeObject(Expression* function_literal, |
| 4272 Expression* home_object) { |
| 4273 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 4274 Variable* result_var = |
| 4275 scope()->NewTemporary(ast_value_factory()->empty_string()); |
| 4276 DoExpression* do_expr = |
| 4277 factory()->NewDoExpression(do_block, result_var, kNoSourcePosition); |
| 4278 Assignment* init = factory()->NewAssignment( |
| 4279 Token::ASSIGN, factory()->NewVariableProxy(result_var), function_literal, |
| 4280 kNoSourcePosition); |
| 4281 do_block->statements()->Add( |
| 4282 factory()->NewExpressionStatement(init, kNoSourcePosition), zone()); |
| 4283 Property* home_object_property = factory()->NewProperty( |
| 4284 factory()->NewVariableProxy(result_var), |
| 4285 factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition), |
| 4286 kNoSourcePosition); |
| 4287 Assignment* assignment = factory()->NewAssignment( |
| 4288 Token::ASSIGN, home_object_property, home_object, kNoSourcePosition); |
| 4289 do_block->statements()->Add( |
| 4290 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone()); |
| 4291 return do_expr; |
| 4292 } |
| 4293 |
| 4294 const AstRawString* ClassFieldVariableName(bool is_name, |
| 4295 AstValueFactory* ast_value_factory, |
| 4296 int index) { |
| 4297 std::string name = |
| 4298 ".class-field-" + std::to_string(index) + (is_name ? "-name" : "-func"); |
| 4299 return ast_value_factory->GetOneByteString(name.c_str()); |
| 4300 } |
| 4301 |
| 4302 FunctionLiteral* Parser::SynthesizeClassFieldInitializer(int count) { |
| 4303 DCHECK(count > 0); |
| 4304 // Makes a function which reads the names and initializers for each class |
| 4305 // field out of deterministically named local variables and sets each property |
| 4306 // to the result of evaluating its corresponding initializer in turn. |
| 4307 |
| 4308 // This produces a function which looks like |
| 4309 // function () { |
| 4310 // this[.class-field-0-name] = .class-field-0-func(); |
| 4311 // this[.class-field-1-name] = .class-field-1-func(); |
| 4312 // [...] |
| 4313 // this[.class-field-n-name] = .class-field-n-func(); |
| 4314 // return this; |
| 4315 // } |
| 4316 // except that it performs defineProperty, so that instead of '=' it has |
| 4317 // %DefineDataPropertyInLiteral(this, .class-field-0-name, |
| 4318 // .class-field-0-func(), |
| 4319 // DONT_ENUM, false) |
| 4320 |
| 4321 RaiseLanguageMode(STRICT); |
| 4322 FunctionKind kind = FunctionKind::kConciseMethod; |
| 4323 DeclarationScope* initializer_scope = NewFunctionScope(kind); |
| 4324 SetLanguageMode(initializer_scope, language_mode()); |
| 4325 initializer_scope->set_start_position(scanner()->location().end_pos); |
| 4326 initializer_scope->set_end_position(scanner()->location().end_pos); |
| 4327 FunctionState initializer_state(&function_state_, &scope_state_, |
| 4328 initializer_scope, kind); |
| 4329 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(count, zone()); |
| 4330 for (int i = 0; i < count; ++i) { |
| 4331 const AstRawString* name = |
| 4332 ClassFieldVariableName(true, ast_value_factory(), i); |
| 4333 VariableProxy* name_proxy = scope()->NewUnresolved(factory(), name); |
| 4334 const AstRawString* function_name = |
| 4335 ClassFieldVariableName(false, ast_value_factory(), i); |
| 4336 VariableProxy* function_proxy = |
| 4337 scope()->NewUnresolved(factory(), function_name); |
| 4338 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 4339 args->Add(function_proxy, zone()); |
| 4340 args->Add(ThisExpression(kNoSourcePosition), zone()); |
| 4341 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, |
| 4342 kNoSourcePosition); |
| 4343 ZoneList<Expression*>* define_property_args = |
| 4344 new (zone()) ZoneList<Expression*>(5, zone()); |
| 4345 define_property_args->Add(ThisExpression(kNoSourcePosition), zone()); |
| 4346 define_property_args->Add(name_proxy, zone()); |
| 4347 define_property_args->Add(call, zone()); |
| 4348 define_property_args->Add( |
| 4349 factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone()); |
| 4350 define_property_args->Add( |
| 4351 factory()->NewNumberLiteral( |
| 4352 false, // TODO(bakkot) function name inference a la class { x = |
| 4353 // function(){}; static y = function(){}; } |
| 4354 kNoSourcePosition), |
| 4355 zone()); |
| 4356 body->Add(factory()->NewExpressionStatement( |
| 4357 factory()->NewCallRuntime( |
| 4358 Runtime::kDefineDataProperty, |
| 4359 define_property_args, // TODO(bakkot) verify that this is |
| 4360 // the same as object_define_property |
| 4361 kNoSourcePosition), |
| 4362 kNoSourcePosition), |
| 4363 zone()); |
| 4364 } |
| 4365 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), |
| 4366 kNoSourcePosition), |
| 4367 zone()); |
| 4368 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
| 4369 ast_value_factory()->empty_string(), initializer_scope, body, |
| 4370 initializer_state.materialized_literal_count(), |
| 4371 initializer_state.expected_property_count(), 0, |
| 4372 FunctionLiteral::kNoDuplicateParameters, |
| 4373 FunctionLiteral::kAnonymousExpression, |
| 4374 FunctionLiteral::kShouldLazyCompile, kind, |
| 4375 initializer_scope->start_position()); |
| 4376 function_literal->set_is_class_field_initializer(true); |
| 4377 function_literal->scope()->set_arity(count); |
| 4378 return function_literal; |
| 4379 } |
| 4380 |
| 4381 FunctionLiteral* Parser::InsertClassFieldInitializer( |
| 4382 FunctionLiteral* constructor) { |
| 4383 Statement* call_initializer = factory()->NewExpressionStatement( |
| 4384 CallClassFieldInitializer( |
| 4385 constructor->scope(), |
| 4386 constructor->scope()->NewUnresolved( |
| 4387 factory(), ast_value_factory()->this_string(), kNoSourcePosition, |
| 4388 kNoSourcePosition + 4, THIS_VARIABLE)), |
| 4389 kNoSourcePosition); |
| 4390 constructor->body()->InsertAt(0, call_initializer, zone()); |
| 4391 return constructor; |
| 4392 } |
| 4393 |
4198 Expression* Parser::ParseClassLiteral(const AstRawString* name, | 4394 Expression* Parser::ParseClassLiteral(const AstRawString* name, |
4199 Scanner::Location class_name_location, | 4395 Scanner::Location class_name_location, |
4200 bool name_is_strict_reserved, int pos, | 4396 bool name_is_strict_reserved, int pos, |
4201 bool* ok) { | 4397 bool* ok) { |
4202 // All parts of a ClassDeclaration and ClassExpression are strict code. | 4398 // All parts of a ClassDeclaration and ClassExpression are strict code. |
4203 if (name_is_strict_reserved) { | 4399 if (name_is_strict_reserved) { |
4204 ReportMessageAt(class_name_location, | 4400 ReportMessageAt(class_name_location, |
4205 MessageTemplate::kUnexpectedStrictReserved); | 4401 MessageTemplate::kUnexpectedStrictReserved); |
4206 *ok = false; | 4402 *ok = false; |
4207 return nullptr; | 4403 return nullptr; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4269 impl()->AccumulateFormalParameterContainmentErrors(); | 4465 impl()->AccumulateFormalParameterContainmentErrors(); |
4270 | 4466 |
4271 if (has_seen_constructor && constructor == nullptr) { | 4467 if (has_seen_constructor && constructor == nullptr) { |
4272 constructor = GetPropertyValue(property)->AsFunctionLiteral(); | 4468 constructor = GetPropertyValue(property)->AsFunctionLiteral(); |
4273 DCHECK_NOT_NULL(constructor); | 4469 DCHECK_NOT_NULL(constructor); |
4274 constructor->set_raw_name( | 4470 constructor->set_raw_name( |
4275 name != nullptr ? name : ast_value_factory()->empty_string()); | 4471 name != nullptr ? name : ast_value_factory()->empty_string()); |
4276 } else { | 4472 } else { |
4277 if (property->kind() == ClassLiteralProperty::FIELD) { | 4473 if (property->kind() == ClassLiteralProperty::FIELD) { |
4278 DCHECK(allow_harmony_class_fields()); | 4474 DCHECK(allow_harmony_class_fields()); |
4279 continue; // TODO(bakkot) implementation | 4475 if (property->is_static()) { |
| 4476 if (static_initializer_var == nullptr) { |
| 4477 static_initializer_var = |
| 4478 NewTemporary(ast_value_factory()->empty_string()); |
| 4479 } |
| 4480 // TODO(bakkot) only do this conditionally |
| 4481 Expression* function = InstallHomeObject( |
| 4482 property->value(), |
| 4483 factory()->NewVariableProxy(static_initializer_var)); |
| 4484 ZoneList<Expression*>* args = |
| 4485 new (zone()) ZoneList<Expression*>(2, zone()); |
| 4486 args->Add(function, zone()); |
| 4487 args->Add(factory()->NewVariableProxy(static_initializer_var), |
| 4488 zone()); |
| 4489 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, |
| 4490 args, kNoSourcePosition); |
| 4491 property->set_value(call); |
| 4492 } else { |
| 4493 // if (is_computed_name) { // TODO(bakkot) figure out why this is |
| 4494 // necessary for non-computed names in full-codegen |
| 4495 ZoneList<Expression*>* to_name_args = |
| 4496 new (zone()) ZoneList<Expression*>(1, zone()); |
| 4497 to_name_args->Add(property->key(), zone()); |
| 4498 property->set_key(factory()->NewCallRuntime( |
| 4499 Runtime::kToName, to_name_args, kNoSourcePosition)); |
| 4500 //} |
| 4501 const AstRawString* name = ClassFieldVariableName( |
| 4502 true, ast_value_factory(), instance_field_initializers->length()); |
| 4503 VariableProxy* name_proxy = NewUnresolved(name); |
| 4504 Declaration* name_declaration = factory()->NewVariableDeclaration( |
| 4505 name_proxy, scope(), kNoSourcePosition); |
| 4506 Variable* name_var = |
| 4507 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, |
| 4508 kNeedsInitialization, ok, scope()); |
| 4509 DCHECK(ok); |
| 4510 if (!ok) return nullptr; |
| 4511 instance_field_initializers->Add(property->value(), zone()); |
| 4512 property->set_value(factory()->NewVariableProxy(name_var)); |
| 4513 } |
4280 } | 4514 } |
4281 properties->Add(property, zone()); | 4515 properties->Add(property, zone()); |
4282 } | 4516 } |
4283 | 4517 |
4284 DCHECK_NOT_NULL(fni_); | 4518 DCHECK_NOT_NULL(fni_); |
4285 fni_->Infer(); | 4519 fni_->Infer(); |
4286 } | 4520 } |
4287 | 4521 |
4288 Expect(Token::RBRACE, CHECK_OK); | 4522 Expect(Token::RBRACE, CHECK_OK); |
4289 int end_pos = scanner()->location().end_pos; | 4523 int end_pos = scanner()->location().end_pos; |
4290 | 4524 |
4291 bool has_instance_fields = instance_field_initializers->length() > 0; | 4525 bool has_instance_fields = instance_field_initializers->length() > 0; |
4292 DCHECK(!has_instance_fields || allow_harmony_class_fields()); | 4526 DCHECK(!has_instance_fields || allow_harmony_class_fields()); |
4293 bool has_default_constructor = constructor == nullptr; | 4527 bool has_default_constructor = constructor == nullptr; |
4294 if (has_default_constructor) { | 4528 if (has_default_constructor) { |
4295 constructor = DefaultConstructor(name, has_extends, has_instance_fields, | 4529 constructor = DefaultConstructor(name, has_extends, has_instance_fields, |
4296 pos, end_pos, block_state.language_mode()); | 4530 pos, end_pos, block_state.language_mode()); |
4297 } | 4531 } |
4298 | 4532 |
4299 if (has_instance_fields && extends == nullptr) { | 4533 if (has_instance_fields && extends == nullptr) { |
| 4534 constructor = InsertClassFieldInitializer(constructor); |
4300 constructor->set_requires_class_field_init(true); | 4535 constructor->set_requires_class_field_init(true); |
4301 } // The derived case is handled by rewriting super calls. | 4536 } // The derived case is handled by rewriting super calls. |
4302 | 4537 |
4303 block_state.set_end_position(end_pos); | 4538 block_state.set_end_position(end_pos); |
4304 | 4539 |
4305 if (name != nullptr) { | 4540 if (name != nullptr) { |
4306 DCHECK_NOT_NULL(proxy); | 4541 DCHECK_NOT_NULL(proxy); |
4307 proxy->var()->set_initializer_position(end_pos); | 4542 proxy->var()->set_initializer_position(end_pos); |
4308 } | 4543 } |
4309 | 4544 |
4310 ClassLiteral* class_literal = factory()->NewClassLiteral( | 4545 ClassLiteral* class_literal = factory()->NewClassLiteral( |
4311 proxy, extends, constructor, properties, pos, end_pos); | 4546 proxy, extends, constructor, properties, pos, end_pos); |
4312 | 4547 |
4313 if (static_initializer_var != nullptr) { | 4548 if (static_initializer_var != nullptr) { |
4314 class_literal->set_static_initializer_proxy( | 4549 class_literal->set_static_initializer_proxy( |
4315 factory()->NewVariableProxy(static_initializer_var)); | 4550 factory()->NewVariableProxy(static_initializer_var)); |
4316 } | 4551 } |
4317 | 4552 |
4318 do_block->statements()->Add( | 4553 do_block->statements()->Add( |
4319 factory()->NewExpressionStatement( | 4554 factory()->NewExpressionStatement( |
4320 factory()->NewAssignment(Token::ASSIGN, | 4555 factory()->NewAssignment(Token::ASSIGN, |
4321 factory()->NewVariableProxy(result_var), | 4556 factory()->NewVariableProxy(result_var), |
4322 class_literal, kNoSourcePosition), | 4557 class_literal, kNoSourcePosition), |
4323 pos), | 4558 pos), |
4324 zone()); | 4559 zone()); |
| 4560 if (allow_harmony_class_fields() && |
| 4561 (has_instance_fields || |
| 4562 (extends != nullptr && !has_default_constructor))) { |
| 4563 // Default constructors for derived classes without fields will not try to |
| 4564 // read this variable, so there's no need to create it. |
| 4565 const AstRawString* init_fn_name = |
| 4566 ast_value_factory()->dot_class_field_init_string(); |
| 4567 Variable* init_fn_var = scope()->DeclareLocal( |
| 4568 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); |
| 4569 Expression* initializer = |
| 4570 has_instance_fields |
| 4571 ? static_cast<Expression*>(SynthesizeClassFieldInitializer( |
| 4572 instance_field_initializers->length())) |
| 4573 : factory()->NewBooleanLiteral(false, kNoSourcePosition); |
| 4574 Assignment* assignment = factory()->NewAssignment( |
| 4575 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer, |
| 4576 kNoSourcePosition); |
| 4577 do_block->statements()->Add( |
| 4578 factory()->NewExpressionStatement(assignment, kNoSourcePosition), |
| 4579 zone()); |
| 4580 } |
| 4581 for (int i = 0; i < instance_field_initializers->length(); ++i) { |
| 4582 const AstRawString* function_name = |
| 4583 ClassFieldVariableName(false, ast_value_factory(), i); |
| 4584 VariableProxy* function_proxy = NewUnresolved(function_name); |
| 4585 Declaration* function_declaration = factory()->NewVariableDeclaration( |
| 4586 function_proxy, scope(), kNoSourcePosition); |
| 4587 Variable* function_var = |
| 4588 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST, |
| 4589 kNeedsInitialization, ok, scope()); |
| 4590 DCHECK(ok); |
| 4591 if (!ok) return nullptr; |
| 4592 Property* prototype_property = factory()->NewProperty( |
| 4593 factory()->NewVariableProxy(result_var), |
| 4594 factory()->NewStringLiteral(ast_value_factory()->prototype_string(), |
| 4595 kNoSourcePosition), |
| 4596 kNoSourcePosition); |
| 4597 Expression* function_value = InstallHomeObject( |
| 4598 instance_field_initializers->at(i), |
| 4599 prototype_property); // TODO(bakkot) ideally this would be conditional, |
| 4600 // especially in trivial cases |
| 4601 Assignment* function_assignment = factory()->NewAssignment( |
| 4602 Token::INIT, factory()->NewVariableProxy(function_var), function_value, |
| 4603 kNoSourcePosition); |
| 4604 do_block->statements()->Add(factory()->NewExpressionStatement( |
| 4605 function_assignment, kNoSourcePosition), |
| 4606 zone()); |
| 4607 } |
4325 do_block->set_scope(block_state.FinalizedBlockScope()); | 4608 do_block->set_scope(block_state.FinalizedBlockScope()); |
4326 do_expr->set_represented_function(constructor); | 4609 do_expr->set_represented_function(constructor); |
4327 | 4610 |
4328 return do_expr; | 4611 return do_expr; |
4329 } | 4612 } |
4330 | 4613 |
4331 | 4614 |
4332 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 4615 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
4333 // CallRuntime :: | 4616 // CallRuntime :: |
4334 // '%' Identifier Arguments | 4617 // '%' Identifier Arguments |
(...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6208 node->Print(Isolate::Current()); | 6491 node->Print(Isolate::Current()); |
6209 } | 6492 } |
6210 #endif // DEBUG | 6493 #endif // DEBUG |
6211 | 6494 |
6212 #undef CHECK_OK | 6495 #undef CHECK_OK |
6213 #undef CHECK_OK_VOID | 6496 #undef CHECK_OK_VOID |
6214 #undef CHECK_FAILED | 6497 #undef CHECK_FAILED |
6215 | 6498 |
6216 } // namespace internal | 6499 } // namespace internal |
6217 } // namespace v8 | 6500 } // namespace v8 |
OLD | NEW |