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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name); | 163 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name); |
164 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | 164 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
165 args->Add(init_fn_proxy, zone()); | 165 args->Add(init_fn_proxy, zone()); |
166 args->Add(this_expr, zone()); | 166 args->Add(this_expr, zone()); |
167 return factory()->NewCallRuntime(Runtime::kInlineCall, args, | 167 return factory()->NewCallRuntime(Runtime::kInlineCall, args, |
168 kNoSourcePosition); | 168 kNoSourcePosition); |
169 } | 169 } |
170 | 170 |
171 Expression* Parser::RewriteSuperCall(Expression* super_call) { | 171 Expression* Parser::RewriteSuperCall(Expression* super_call) { |
172 // TODO(bakkot) find a way to avoid this for classes without fields. | 172 // TODO(bakkot) find a way to avoid this for classes without fields. |
173 if (!allow_harmony_class_fields()) { | 173 if (!(allow_harmony_class_fields() || allow_harmony_private_class_fields())) { |
174 return super_call; | 174 return super_call; |
175 } | 175 } |
176 // This turns a super call `super()` into a do expression of the form | 176 // This turns a super call `super()` into a do expression of the form |
177 // do { | 177 // do { |
178 // tmp x = super(); | 178 // tmp x = super(); |
179 // if (.class-field-init) | 179 // if (.class-field-init) |
180 // .class-field-init(x) | 180 // .class-field-init(x) |
181 // x; // This isn't actually present; our do-expression representation | 181 // x; // This isn't actually present; our do-expression representation |
182 // allows specifying that the expression returns x directly. | 182 // allows specifying that the expression returns x directly. |
183 // } | 183 // } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 info->isolate()->is_tail_call_elimination_enabled()); | 589 info->isolate()->is_tail_call_elimination_enabled()); |
590 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); | 590 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); |
591 set_allow_harmony_for_in(FLAG_harmony_for_in); | 591 set_allow_harmony_for_in(FLAG_harmony_for_in); |
592 set_allow_harmony_function_sent(FLAG_harmony_function_sent); | 592 set_allow_harmony_function_sent(FLAG_harmony_function_sent); |
593 set_allow_harmony_restrictive_declarations( | 593 set_allow_harmony_restrictive_declarations( |
594 FLAG_harmony_restrictive_declarations); | 594 FLAG_harmony_restrictive_declarations); |
595 set_allow_harmony_async_await(FLAG_harmony_async_await); | 595 set_allow_harmony_async_await(FLAG_harmony_async_await); |
596 set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators); | 596 set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators); |
597 set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas); | 597 set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas); |
598 set_allow_harmony_class_fields(FLAG_harmony_class_fields); | 598 set_allow_harmony_class_fields(FLAG_harmony_class_fields); |
| 599 set_allow_harmony_private_class_fields(FLAG_harmony_private_class_fields); |
599 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | 600 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; |
600 ++feature) { | 601 ++feature) { |
601 use_counts_[feature] = 0; | 602 use_counts_[feature] = 0; |
602 } | 603 } |
603 if (info->ast_value_factory() == NULL) { | 604 if (info->ast_value_factory() == NULL) { |
604 // info takes ownership of AstValueFactory. | 605 // info takes ownership of AstValueFactory. |
605 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); | 606 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); |
606 info->set_ast_value_factory_owned(); | 607 info->set_ast_value_factory_owned(); |
607 ast_value_factory_ = info->ast_value_factory(); | 608 ast_value_factory_ = info->ast_value_factory(); |
608 ast_node_factory_.set_ast_value_factory(ast_value_factory_); | 609 ast_node_factory_.set_ast_value_factory(ast_value_factory_); |
(...skipping 2761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3370 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); | 3371 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); |
3371 Block* block = ParseBlock(nullptr, CHECK_OK); | 3372 Block* block = ParseBlock(nullptr, CHECK_OK); |
3372 DoExpression* expr = factory()->NewDoExpression(block, result, pos); | 3373 DoExpression* expr = factory()->NewDoExpression(block, result, pos); |
3373 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) { | 3374 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) { |
3374 *ok = false; | 3375 *ok = false; |
3375 return nullptr; | 3376 return nullptr; |
3376 } | 3377 } |
3377 return expr; | 3378 return expr; |
3378 } | 3379 } |
3379 | 3380 |
| 3381 const AstRawString* ClassPrivateFieldVariableName( |
| 3382 AstValueFactory* ast_value_factory, const AstRawString* raw_name) { |
| 3383 // Prepends '#' |
| 3384 return ast_value_factory->ConcatStrings( |
| 3385 ast_value_factory->number_sign_string(), raw_name); |
| 3386 } |
| 3387 |
| 3388 Property* Parser::ParsePrivateFieldReference(Expression* base, bool* ok) { |
| 3389 // PrimaryExpression :: |
| 3390 // PrivateName |
| 3391 |
| 3392 // This desugars a private field reference like `#a` or `obj.#a` into |
| 3393 // %ThrowIfMissingPrivateField(obj, #a)[#a] |
| 3394 // Here #a is a variable which will resolve to a private symbol when inside of |
| 3395 // a class which defines a private field named #a (otherwise attempting to |
| 3396 // resolve it will throw a reference error). |
| 3397 |
| 3398 int pos = peek_position(); |
| 3399 |
| 3400 Expect(Token::HASH, CHECK_OK); |
| 3401 const AstRawString* property_name = |
| 3402 ParseIdentifierName(CHECK_OK); // TODO(bakkot) more complex names |
| 3403 const AstRawString* symbol_var_name = |
| 3404 ClassPrivateFieldVariableName(ast_value_factory(), property_name); |
| 3405 |
| 3406 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 3407 args->Add(base, zone()); |
| 3408 args->Add(NewUnresolved(symbol_var_name), zone()); |
| 3409 Expression* call = factory()->NewCallRuntime( |
| 3410 Runtime::kThrowIfMissingPrivateField, args, pos); |
| 3411 // TODO(bakkot) ideally we'd avoid this runtime function, either by adding a |
| 3412 // flag to the load/store IC or by adding a code stub for it. Currently it |
| 3413 // means that every private field access requires this runtime call, which is |
| 3414 // a slowdown we'd prefer to avoid. |
| 3415 |
| 3416 Expression* prop = NewUnresolved(symbol_var_name); |
| 3417 return factory()->NewProperty(call, prop, pos); |
| 3418 } |
| 3419 |
3380 void Parser::ParseArrowFunctionFormalParameterList( | 3420 void Parser::ParseArrowFunctionFormalParameterList( |
3381 ParserFormalParameters* parameters, Expression* expr, | 3421 ParserFormalParameters* parameters, Expression* expr, |
3382 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, | 3422 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, |
3383 const Scope::Snapshot& scope_snapshot, bool* ok) { | 3423 const Scope::Snapshot& scope_snapshot, bool* ok) { |
3384 if (expr->IsEmptyParentheses()) return; | 3424 if (expr->IsEmptyParentheses()) return; |
3385 | 3425 |
3386 ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos, | 3426 ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos, |
3387 CHECK_OK_VOID); | 3427 CHECK_OK_VOID); |
3388 | 3428 |
3389 scope_snapshot.Reparent(parameters->scope); | 3429 scope_snapshot.Reparent(parameters->scope); |
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4249 reusable_preparser_->set_allow_lazy(true); | 4289 reusable_preparser_->set_allow_lazy(true); |
4250 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); | 4290 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); |
4251 SET_ALLOW(natives); | 4291 SET_ALLOW(natives); |
4252 SET_ALLOW(harmony_do_expressions); | 4292 SET_ALLOW(harmony_do_expressions); |
4253 SET_ALLOW(harmony_for_in); | 4293 SET_ALLOW(harmony_for_in); |
4254 SET_ALLOW(harmony_function_sent); | 4294 SET_ALLOW(harmony_function_sent); |
4255 SET_ALLOW(harmony_restrictive_declarations); | 4295 SET_ALLOW(harmony_restrictive_declarations); |
4256 SET_ALLOW(harmony_async_await); | 4296 SET_ALLOW(harmony_async_await); |
4257 SET_ALLOW(harmony_trailing_commas); | 4297 SET_ALLOW(harmony_trailing_commas); |
4258 SET_ALLOW(harmony_class_fields); | 4298 SET_ALLOW(harmony_class_fields); |
| 4299 SET_ALLOW(harmony_private_class_fields); |
4259 #undef SET_ALLOW | 4300 #undef SET_ALLOW |
4260 } | 4301 } |
4261 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 4302 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
4262 language_mode(), function_state_->kind(), | 4303 language_mode(), function_state_->kind(), |
4263 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, | 4304 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, |
4264 logger, may_abort, use_counts_); | 4305 logger, may_abort, use_counts_); |
4265 if (pre_parse_timer_ != NULL) { | 4306 if (pre_parse_timer_ != NULL) { |
4266 pre_parse_timer_->Stop(); | 4307 pre_parse_timer_->Stop(); |
4267 } | 4308 } |
4268 return result; | 4309 return result; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4434 impl()->AccumulateFormalParameterContainmentErrors(); | 4475 impl()->AccumulateFormalParameterContainmentErrors(); |
4435 } else { | 4476 } else { |
4436 block_state.set_start_position(scanner()->location().end_pos); | 4477 block_state.set_start_position(scanner()->location().end_pos); |
4437 } | 4478 } |
4438 | 4479 |
4439 | 4480 |
4440 ClassLiteralChecker checker(this); | 4481 ClassLiteralChecker checker(this); |
4441 ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4); | 4482 ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4); |
4442 ZoneList<Expression*>* instance_field_initializers = | 4483 ZoneList<Expression*>* instance_field_initializers = |
4443 new (zone()) ZoneList<Expression*>(0, zone()); | 4484 new (zone()) ZoneList<Expression*>(0, zone()); |
| 4485 ZoneList<Variable*>* private_field_symbol_vars = |
| 4486 new (zone()) ZoneList<Variable*>(0, zone()); |
| 4487 ZoneList<Variable*>* private_field_index_vars = |
| 4488 new (zone()) ZoneList<Variable*>(0, zone()); |
4444 FunctionLiteral* constructor = nullptr; | 4489 FunctionLiteral* constructor = nullptr; |
4445 bool has_seen_constructor = false; | 4490 bool has_seen_constructor = false; |
4446 Variable* static_initializer_var = nullptr; | 4491 Variable* static_initializer_var = nullptr; |
4447 | 4492 |
4448 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); | 4493 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); |
4449 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); | 4494 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); |
4450 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); | 4495 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); |
4451 | 4496 |
4452 Expect(Token::LBRACE, CHECK_OK); | 4497 Expect(Token::LBRACE, CHECK_OK); |
4453 | 4498 |
4454 const bool has_extends = extends != nullptr; | 4499 const bool has_extends = extends != nullptr; |
4455 while (peek() != Token::RBRACE) { | 4500 while (peek() != Token::RBRACE) { |
4456 if (Check(Token::SEMICOLON)) continue; | 4501 if (Check(Token::SEMICOLON)) continue; |
4457 FuncNameInferrer::State fni_state(fni_); | 4502 FuncNameInferrer::State fni_state(fni_); |
| 4503 const AstRawString* private_name = nullptr; |
4458 bool is_computed_name = false; // Classes do not care about computed | 4504 bool is_computed_name = false; // Classes do not care about computed |
4459 // property names here. | 4505 // property names here. |
4460 ExpressionClassifier property_classifier(this); | 4506 ExpressionClassifier property_classifier(this); |
4461 ClassLiteral::Property* property = | 4507 ClassLiteral::Property* property = ParseClassPropertyDefinition( |
4462 ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name, | 4508 &checker, has_extends, &private_name, &is_computed_name, |
4463 &has_seen_constructor, CHECK_OK); | 4509 &has_seen_constructor, CHECK_OK); |
4464 RewriteNonPattern(CHECK_OK); | 4510 RewriteNonPattern(CHECK_OK); |
4465 impl()->AccumulateFormalParameterContainmentErrors(); | 4511 impl()->AccumulateFormalParameterContainmentErrors(); |
4466 | 4512 |
4467 if (has_seen_constructor && constructor == nullptr) { | 4513 if (has_seen_constructor && constructor == nullptr) { |
4468 constructor = GetPropertyValue(property)->AsFunctionLiteral(); | 4514 constructor = GetPropertyValue(property)->AsFunctionLiteral(); |
4469 DCHECK_NOT_NULL(constructor); | 4515 DCHECK_NOT_NULL(constructor); |
4470 constructor->set_raw_name( | 4516 constructor->set_raw_name( |
4471 name != nullptr ? name : ast_value_factory()->empty_string()); | 4517 name != nullptr ? name : ast_value_factory()->empty_string()); |
4472 } else { | 4518 } else { |
4473 if (property->kind() == ClassLiteralProperty::FIELD) { | 4519 if (property->kind() == ClassLiteralProperty::FIELD) { |
4474 DCHECK(allow_harmony_class_fields()); | 4520 if (private_name != nullptr) { |
4475 if (property->is_static()) { | 4521 DCHECK(allow_harmony_private_class_fields()); |
| 4522 DCHECK(property->key() == nullptr); |
| 4523 DCHECK(!property->is_static()); |
| 4524 |
| 4525 const AstRawString* symbol_var_name = |
| 4526 ClassPrivateFieldVariableName(ast_value_factory(), private_name); |
| 4527 VariableProxy* symbol_var_proxy = NewUnresolved(symbol_var_name); |
| 4528 Declaration* symbol_var_declaration = |
| 4529 factory()->NewVariableDeclaration(symbol_var_proxy, scope(), |
| 4530 kNoSourcePosition); |
| 4531 Variable* symbol_var = |
| 4532 Declare(symbol_var_declaration, DeclarationDescriptor::NORMAL, |
| 4533 CONST, kCreatedInitialized, ok, scope()); |
| 4534 private_field_symbol_vars->Add(symbol_var, zone()); |
| 4535 |
| 4536 const AstRawString* index_var_name = ClassFieldVariableName( |
| 4537 true, ast_value_factory(), instance_field_initializers->length()); |
| 4538 VariableProxy* index_var_proxy = NewUnresolved(index_var_name); |
| 4539 Declaration* index_var_declaration = |
| 4540 factory()->NewVariableDeclaration(index_var_proxy, scope(), |
| 4541 kNoSourcePosition); |
| 4542 Variable* index_var = |
| 4543 Declare(index_var_declaration, DeclarationDescriptor::NORMAL, |
| 4544 CONST, kCreatedInitialized, ok, scope()); |
| 4545 private_field_index_vars->Add(index_var, zone()); |
| 4546 |
| 4547 instance_field_initializers->Add(property->value(), zone()); |
| 4548 |
| 4549 // Does not add to properties because no action is required from the |
| 4550 // backend during class definition. |
| 4551 } else if (property->is_static()) { |
| 4552 DCHECK(allow_harmony_class_fields()); |
4476 if (static_initializer_var == nullptr) { | 4553 if (static_initializer_var == nullptr) { |
4477 static_initializer_var = | 4554 static_initializer_var = |
4478 NewTemporary(ast_value_factory()->empty_string()); | 4555 NewTemporary(ast_value_factory()->empty_string()); |
4479 } | 4556 } |
4480 // TODO(bakkot) only do this conditionally | 4557 // TODO(bakkot) only do this conditionally |
4481 Expression* function = InstallHomeObject( | 4558 Expression* function = InstallHomeObject( |
4482 property->value(), | 4559 property->value(), |
4483 factory()->NewVariableProxy(static_initializer_var)); | 4560 factory()->NewVariableProxy(static_initializer_var)); |
4484 ZoneList<Expression*>* args = | 4561 ZoneList<Expression*>* args = |
4485 new (zone()) ZoneList<Expression*>(2, zone()); | 4562 new (zone()) ZoneList<Expression*>(2, zone()); |
4486 args->Add(function, zone()); | 4563 args->Add(function, zone()); |
4487 args->Add(factory()->NewVariableProxy(static_initializer_var), | 4564 args->Add(factory()->NewVariableProxy(static_initializer_var), |
4488 zone()); | 4565 zone()); |
4489 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, | 4566 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, |
4490 args, kNoSourcePosition); | 4567 args, kNoSourcePosition); |
4491 property->set_value(call); | 4568 property->set_value(call); |
| 4569 properties->Add(property, zone()); |
4492 } else { | 4570 } else { |
| 4571 DCHECK(allow_harmony_class_fields()); |
4493 // if (is_computed_name) { // TODO(bakkot) figure out why this is | 4572 // if (is_computed_name) { // TODO(bakkot) figure out why this is |
4494 // necessary for non-computed names in full-codegen | 4573 // necessary for non-computed names in full-codegen |
4495 ZoneList<Expression*>* to_name_args = | 4574 ZoneList<Expression*>* to_name_args = |
4496 new (zone()) ZoneList<Expression*>(1, zone()); | 4575 new (zone()) ZoneList<Expression*>(1, zone()); |
4497 to_name_args->Add(property->key(), zone()); | 4576 to_name_args->Add(property->key(), zone()); |
4498 property->set_key(factory()->NewCallRuntime( | 4577 property->set_key(factory()->NewCallRuntime( |
4499 Runtime::kToName, to_name_args, kNoSourcePosition)); | 4578 Runtime::kToName, to_name_args, kNoSourcePosition)); |
4500 //} | 4579 //} |
4501 const AstRawString* name = ClassFieldVariableName( | 4580 const AstRawString* name = ClassFieldVariableName( |
4502 true, ast_value_factory(), instance_field_initializers->length()); | 4581 true, ast_value_factory(), instance_field_initializers->length()); |
4503 VariableProxy* name_proxy = NewUnresolved(name); | 4582 VariableProxy* name_proxy = NewUnresolved(name); |
4504 Declaration* name_declaration = factory()->NewVariableDeclaration( | 4583 Declaration* name_declaration = factory()->NewVariableDeclaration( |
4505 name_proxy, scope(), kNoSourcePosition); | 4584 name_proxy, scope(), kNoSourcePosition); |
4506 Variable* name_var = | 4585 Variable* name_var = |
4507 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, | 4586 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, |
4508 kNeedsInitialization, ok, scope()); | 4587 kNeedsInitialization, ok, scope()); |
4509 DCHECK(ok); | 4588 DCHECK(ok); |
4510 if (!ok) return nullptr; | 4589 if (!ok) return nullptr; |
4511 instance_field_initializers->Add(property->value(), zone()); | 4590 instance_field_initializers->Add(property->value(), zone()); |
4512 property->set_value(factory()->NewVariableProxy(name_var)); | 4591 property->set_value(factory()->NewVariableProxy(name_var)); |
| 4592 properties->Add(property, zone()); |
4513 } | 4593 } |
| 4594 } else { |
| 4595 properties->Add(property, zone()); |
4514 } | 4596 } |
4515 properties->Add(property, zone()); | |
4516 } | 4597 } |
4517 | 4598 |
4518 DCHECK_NOT_NULL(fni_); | 4599 DCHECK_NOT_NULL(fni_); |
4519 fni_->Infer(); | 4600 fni_->Infer(); |
4520 } | 4601 } |
4521 | 4602 |
4522 Expect(Token::RBRACE, CHECK_OK); | 4603 Expect(Token::RBRACE, CHECK_OK); |
4523 int end_pos = scanner()->location().end_pos; | 4604 int end_pos = scanner()->location().end_pos; |
4524 | 4605 |
4525 bool has_instance_fields = instance_field_initializers->length() > 0; | 4606 bool has_instance_fields = instance_field_initializers->length() > 0; |
4526 DCHECK(!has_instance_fields || allow_harmony_class_fields()); | 4607 DCHECK(!has_instance_fields || allow_harmony_class_fields() || |
| 4608 allow_harmony_private_class_fields()); |
4527 bool has_default_constructor = constructor == nullptr; | 4609 bool has_default_constructor = constructor == nullptr; |
4528 if (has_default_constructor) { | 4610 if (has_default_constructor) { |
4529 constructor = DefaultConstructor(name, has_extends, has_instance_fields, | 4611 constructor = DefaultConstructor(name, has_extends, has_instance_fields, |
4530 pos, end_pos, block_state.language_mode()); | 4612 pos, end_pos, block_state.language_mode()); |
4531 } | 4613 } |
4532 | 4614 |
4533 if (has_instance_fields && extends == nullptr) { | 4615 if (has_instance_fields && extends == nullptr) { |
4534 constructor = InsertClassFieldInitializer(constructor); | 4616 constructor = InsertClassFieldInitializer(constructor); |
4535 constructor->set_requires_class_field_init(true); | 4617 constructor->set_requires_class_field_init(true); |
4536 } // The derived case is handled by rewriting super calls. | 4618 } // The derived case is handled by rewriting super calls. |
4537 | 4619 |
4538 block_state.set_end_position(end_pos); | 4620 block_state.set_end_position(end_pos); |
4539 | 4621 |
4540 if (name != nullptr) { | 4622 if (name != nullptr) { |
4541 DCHECK_NOT_NULL(proxy); | 4623 DCHECK_NOT_NULL(proxy); |
4542 proxy->var()->set_initializer_position(end_pos); | 4624 proxy->var()->set_initializer_position(end_pos); |
4543 } | 4625 } |
4544 | 4626 |
| 4627 // The parser creates two variables for every private field, both of which |
| 4628 // store the private symbol which serves as the key for that field. One of |
| 4629 // them, 'symbol_var', is used when referencing private fields with '#a' in |
| 4630 // normal code. The other, 'index_var', is used when initializing the field. |
| 4631 // The later variable is necessary because the synthetic field initialization |
| 4632 // function has available to it *only* the number of fields in the class. |
| 4633 // The desugaring looks something like this: |
| 4634 // |
| 4635 // class C { |
| 4636 // #foo = 0; |
| 4637 // baz; |
| 4638 // m(){ |
| 4639 // this.#bar = 'a'; |
| 4640 // #foo = 1; |
| 4641 // } |
| 4642 // #bar; |
| 4643 // } |
| 4644 // -- becomes -- |
| 4645 // do { |
| 4646 // class C { |
| 4647 // m(){ |
| 4648 // %ThrowIfMissingPrivateField(this, .bar-symbol)[.bar-symbol] = 'a'; |
| 4649 // %ThrowIfMissingPrivateField(this, .foo-symbol)[.foo-symbol] = 1; |
| 4650 // } |
| 4651 // constructor(){ |
| 4652 // .initialize.call(this); |
| 4653 // } |
| 4654 // } |
| 4655 // |
| 4656 // let .foo-symbol, .name-0, .init-0; |
| 4657 // .foo-symbol = .name-0 = PrivateSymbol(); |
| 4658 // .init-0 = ()=>0; |
| 4659 // |
| 4660 // let .name-1, .init-1; |
| 4661 // // .name-1 is given value 'baz' by the backends during class definition |
| 4662 // .init-1 = ()=>undefined; |
| 4663 // |
| 4664 // let .bar-symbol, .name-2, .init-2; |
| 4665 // .bar-symbol = .name-2 = PrivateSymbol(); |
| 4666 // .init-2 = ()=>undefined; |
| 4667 // |
| 4668 // .initialize() { |
| 4669 // this[.name-0] = .init-0(); // Actually this is defineOwnProperty not = |
| 4670 // this[.name-1] = .init-1(); |
| 4671 // this[.name-2] = .init-2(); |
| 4672 // } |
| 4673 // |
| 4674 // C; |
| 4675 // } |
| 4676 DCHECK(private_field_symbol_vars->length() == |
| 4677 private_field_index_vars->length()); |
| 4678 DCHECK(allow_harmony_private_class_fields() || |
| 4679 private_field_symbol_vars->length() == 0); |
| 4680 for (int i = 0; i < private_field_symbol_vars->length(); ++i) { |
| 4681 VariableProxy* symbol_var_proxy = |
| 4682 factory()->NewVariableProxy(private_field_symbol_vars->at(i)); |
| 4683 VariableProxy* index_var_proxy = |
| 4684 factory()->NewVariableProxy(private_field_index_vars->at(i)); |
| 4685 |
| 4686 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
| 4687 args->Add(factory()->NewUndefinedLiteral(kNoSourcePosition), zone()); |
| 4688 Expression* name = |
| 4689 factory()->NewCallRuntime(Runtime::kCreatePrivateSymbol, args, pos); |
| 4690 |
| 4691 Assignment* inner_assignment = factory()->NewAssignment( |
| 4692 Token::INIT, index_var_proxy, name, kNoSourcePosition); |
| 4693 Assignment* outer_assignment = factory()->NewAssignment( |
| 4694 Token::INIT, symbol_var_proxy, inner_assignment, kNoSourcePosition); |
| 4695 do_block->statements()->Add( |
| 4696 factory()->NewExpressionStatement(outer_assignment, kNoSourcePosition), |
| 4697 zone()); |
| 4698 } |
| 4699 |
4545 ClassLiteral* class_literal = factory()->NewClassLiteral( | 4700 ClassLiteral* class_literal = factory()->NewClassLiteral( |
4546 proxy, extends, constructor, properties, pos, end_pos); | 4701 proxy, extends, constructor, properties, pos, end_pos); |
4547 | 4702 |
4548 if (static_initializer_var != nullptr) { | 4703 if (static_initializer_var != nullptr) { |
4549 class_literal->set_static_initializer_proxy( | 4704 class_literal->set_static_initializer_proxy( |
4550 factory()->NewVariableProxy(static_initializer_var)); | 4705 factory()->NewVariableProxy(static_initializer_var)); |
4551 } | 4706 } |
4552 | 4707 |
4553 do_block->statements()->Add( | 4708 do_block->statements()->Add( |
4554 factory()->NewExpressionStatement( | 4709 factory()->NewExpressionStatement( |
4555 factory()->NewAssignment(Token::ASSIGN, | 4710 factory()->NewAssignment(Token::ASSIGN, |
4556 factory()->NewVariableProxy(result_var), | 4711 factory()->NewVariableProxy(result_var), |
4557 class_literal, kNoSourcePosition), | 4712 class_literal, kNoSourcePosition), |
4558 pos), | 4713 pos), |
4559 zone()); | 4714 zone()); |
4560 if (allow_harmony_class_fields() && | 4715 if ((allow_harmony_class_fields() || allow_harmony_private_class_fields()) && |
4561 (has_instance_fields || | 4716 (has_instance_fields || |
4562 (extends != nullptr && !has_default_constructor))) { | 4717 (extends != nullptr && !has_default_constructor))) { |
4563 // Default constructors for derived classes without fields will not try to | 4718 // Default constructors for derived classes without fields will not try to |
4564 // read this variable, so there's no need to create it. | 4719 // read this variable, so there's no need to create it. |
4565 const AstRawString* init_fn_name = | 4720 const AstRawString* init_fn_name = |
4566 ast_value_factory()->dot_class_field_init_string(); | 4721 ast_value_factory()->dot_class_field_init_string(); |
4567 Variable* init_fn_var = scope()->DeclareLocal( | 4722 Variable* init_fn_var = scope()->DeclareLocal( |
4568 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); | 4723 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); |
4569 Expression* initializer = | 4724 Expression* initializer = |
4570 has_instance_fields | 4725 has_instance_fields |
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6491 node->Print(Isolate::Current()); | 6646 node->Print(Isolate::Current()); |
6492 } | 6647 } |
6493 #endif // DEBUG | 6648 #endif // DEBUG |
6494 | 6649 |
6495 #undef CHECK_OK | 6650 #undef CHECK_OK |
6496 #undef CHECK_OK_VOID | 6651 #undef CHECK_OK_VOID |
6497 #undef CHECK_FAILED | 6652 #undef CHECK_FAILED |
6498 | 6653 |
6499 } // namespace internal | 6654 } // namespace internal |
6500 } // namespace v8 | 6655 } // namespace v8 |
OLD | NEW |