Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(474)

Side by Side Diff: src/parsing/parser.cc

Issue 2329703002: Private fields
Patch Set: comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 ast_value_factory()->GetOneByteString(".class-field-initializer"); 156 ast_value_factory()->GetOneByteString(".class-field-initializer");
157 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name); 157 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name);
158 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); 158 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
159 args->Add(init_fn_proxy, zone()); 159 args->Add(init_fn_proxy, zone());
160 args->Add(this_expr, zone()); 160 args->Add(this_expr, zone());
161 return factory()->NewCallRuntime(Runtime::kInlineCall, args, 161 return factory()->NewCallRuntime(Runtime::kInlineCall, args,
162 kNoSourcePosition); 162 kNoSourcePosition);
163 } 163 }
164 164
165 Expression* Parser::RewriteSuperCall(Expression* super_call) { 165 Expression* Parser::RewriteSuperCall(Expression* super_call) {
166 if (!allow_harmony_class_fields()) { 166 if (!(allow_harmony_class_fields() || allow_harmony_private_class_fields())) {
167 return super_call; 167 return super_call;
168 } 168 }
169 // TODO(bakkot) The whole charade with the do expression can be replaced by a 169 // TODO(bakkot) The whole charade with the do expression can be replaced by a
170 // ternary conditional, except that the optimizer does not like it if you use 170 // ternary conditional, except that the optimizer does not like it if you use
171 // an AST node (at least, one containing a variable proxy) in two places. 171 // an AST node (at least, one containing a variable proxy) in two places.
172 Variable* var_tmp = 172 Variable* var_tmp =
173 scope()->NewTemporary(ast_value_factory()->empty_string()); 173 scope()->NewTemporary(ast_value_factory()->empty_string());
174 Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); 174 Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
175 Assignment* assignment = factory()->NewAssignment( 175 Assignment* assignment = factory()->NewAssignment(
176 Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call, 176 Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call,
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 info->isolate()->is_tail_call_elimination_enabled()); 577 info->isolate()->is_tail_call_elimination_enabled());
578 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); 578 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
579 set_allow_harmony_for_in(FLAG_harmony_for_in); 579 set_allow_harmony_for_in(FLAG_harmony_for_in);
580 set_allow_harmony_function_sent(FLAG_harmony_function_sent); 580 set_allow_harmony_function_sent(FLAG_harmony_function_sent);
581 set_allow_harmony_restrictive_declarations( 581 set_allow_harmony_restrictive_declarations(
582 FLAG_harmony_restrictive_declarations); 582 FLAG_harmony_restrictive_declarations);
583 set_allow_harmony_async_await(FLAG_harmony_async_await); 583 set_allow_harmony_async_await(FLAG_harmony_async_await);
584 set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators); 584 set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
585 set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas); 585 set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas);
586 set_allow_harmony_class_fields(FLAG_harmony_class_fields); 586 set_allow_harmony_class_fields(FLAG_harmony_class_fields);
587 set_allow_harmony_private_class_fields(FLAG_harmony_private_class_fields);
587 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; 588 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
588 ++feature) { 589 ++feature) {
589 use_counts_[feature] = 0; 590 use_counts_[feature] = 0;
590 } 591 }
591 if (info->ast_value_factory() == NULL) { 592 if (info->ast_value_factory() == NULL) {
592 // info takes ownership of AstValueFactory. 593 // info takes ownership of AstValueFactory.
593 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); 594 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
594 info->set_ast_value_factory_owned(); 595 info->set_ast_value_factory_owned();
595 ast_value_factory_ = info->ast_value_factory(); 596 ast_value_factory_ = info->ast_value_factory();
596 ast_node_factory_.set_ast_value_factory(ast_value_factory_); 597 ast_node_factory_.set_ast_value_factory(ast_value_factory_);
(...skipping 2761 matching lines...) Expand 10 before | Expand all | Expand 10 after
3358 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); 3359 Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
3359 Block* block = ParseBlock(nullptr, CHECK_OK); 3360 Block* block = ParseBlock(nullptr, CHECK_OK);
3360 DoExpression* expr = factory()->NewDoExpression(block, result, pos); 3361 DoExpression* expr = factory()->NewDoExpression(block, result, pos);
3361 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) { 3362 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
3362 *ok = false; 3363 *ok = false;
3363 return nullptr; 3364 return nullptr;
3364 } 3365 }
3365 return expr; 3366 return expr;
3366 } 3367 }
3367 3368
3369 const AstRawString* ClassPrivateFieldVariableName(
3370 AstValueFactory* ast_value_factory, const AstRawString* raw_name) {
3371 std::string name(reinterpret_cast<const char*>(raw_name->raw_data()),
3372 raw_name->length()); // TODO(bakkot) check complicated names
3373 name = "#" + name;
3374 return ast_value_factory->GetOneByteString(
3375 name.c_str()); // TODO(bakkot) sometimes two-byte probably, though maybe
3376 // doesn't matter
Dan Ehrenberg 2016/09/15 21:26:58 I'm looking forward to your fix here.
bakkot 2016/09/17 00:11:10 Done.
3377 }
3378
3379 Property* Parser::ParsePrivateFieldReference(Expression* base, bool* ok) {
3380 // PrimaryExpression ::
3381 // PrivateName
3382
3383 // This desugars a private field reference like `#a` or `obj.#a` into
3384 // %ThrowIfMissingPrivateField(obj, #a)[#a]
3385 // Here #a is a variable which will resolve to a private symbol when inside of
3386 // a class which defines a private field named #a (otherwise attempting to
3387 // resolve it will throw a reference error).
3388
3389 int pos = peek_position();
3390
3391 Expect(Token::HASH, CHECK_OK);
3392 const AstRawString* property_name =
3393 ParseIdentifierName(CHECK_OK); // TODO(bakkot) more complex names
3394 const AstRawString* symbol_var_name =
3395 ClassPrivateFieldVariableName(ast_value_factory(), property_name);
3396
3397 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3398 args->Add(base, zone());
3399 args->Add(NewUnresolved(symbol_var_name), zone());
3400 Expression* call = factory()->NewCallRuntime(
3401 Runtime::kThrowIfMissingPrivateField, args, pos);
3402 // TODO(bakkot) ideally we'd avoid this runtime function, either by adding a
3403 // flag to the load/store IC or by adding a code stub for it. Currently it
3404 // means that every private field access requires this runtime call, which is
3405 // a slowdown we'd prefer to avoid.
3406
3407 Expression* prop = NewUnresolved(symbol_var_name);
3408 return factory()->NewProperty(call, prop, pos);
3409 }
3410
3368 void Parser::ParseArrowFunctionFormalParameterList( 3411 void Parser::ParseArrowFunctionFormalParameterList(
3369 ParserFormalParameters* parameters, Expression* expr, 3412 ParserFormalParameters* parameters, Expression* expr,
3370 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, 3413 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
3371 const Scope::Snapshot& scope_snapshot, bool* ok) { 3414 const Scope::Snapshot& scope_snapshot, bool* ok) {
3372 if (expr->IsEmptyParentheses()) return; 3415 if (expr->IsEmptyParentheses()) return;
3373 3416
3374 ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos, 3417 ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos,
3375 CHECK_OK_VOID); 3418 CHECK_OK_VOID);
3376 3419
3377 scope_snapshot.Reparent(parameters->scope); 3420 scope_snapshot.Reparent(parameters->scope);
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 reusable_preparser_->set_allow_lazy(true); 4280 reusable_preparser_->set_allow_lazy(true);
4238 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); 4281 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
4239 SET_ALLOW(natives); 4282 SET_ALLOW(natives);
4240 SET_ALLOW(harmony_do_expressions); 4283 SET_ALLOW(harmony_do_expressions);
4241 SET_ALLOW(harmony_for_in); 4284 SET_ALLOW(harmony_for_in);
4242 SET_ALLOW(harmony_function_sent); 4285 SET_ALLOW(harmony_function_sent);
4243 SET_ALLOW(harmony_restrictive_declarations); 4286 SET_ALLOW(harmony_restrictive_declarations);
4244 SET_ALLOW(harmony_async_await); 4287 SET_ALLOW(harmony_async_await);
4245 SET_ALLOW(harmony_trailing_commas); 4288 SET_ALLOW(harmony_trailing_commas);
4246 SET_ALLOW(harmony_class_fields); 4289 SET_ALLOW(harmony_class_fields);
4290 SET_ALLOW(harmony_private_class_fields);
4247 #undef SET_ALLOW 4291 #undef SET_ALLOW
4248 } 4292 }
4249 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 4293 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4250 language_mode(), function_state_->kind(), 4294 language_mode(), function_state_->kind(),
4251 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, 4295 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_,
4252 logger, may_abort, use_counts_); 4296 logger, may_abort, use_counts_);
4253 if (pre_parse_timer_ != NULL) { 4297 if (pre_parse_timer_ != NULL) {
4254 pre_parse_timer_->Stop(); 4298 pre_parse_timer_->Stop();
4255 } 4299 }
4256 return result; 4300 return result;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
4408 impl()->AccumulateFormalParameterContainmentErrors(); 4452 impl()->AccumulateFormalParameterContainmentErrors();
4409 } else { 4453 } else {
4410 block_state.set_start_position(scanner()->location().end_pos); 4454 block_state.set_start_position(scanner()->location().end_pos);
4411 } 4455 }
4412 4456
4413 4457
4414 ClassLiteralChecker checker(this); 4458 ClassLiteralChecker checker(this);
4415 ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4); 4459 ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4);
4416 ZoneList<Expression*>* instance_field_initializers = 4460 ZoneList<Expression*>* instance_field_initializers =
4417 new (zone()) ZoneList<Expression*>(0, zone()); 4461 new (zone()) ZoneList<Expression*>(0, zone());
4462 ZoneList<Variable*>* private_field_symbol_vars =
4463 new (zone()) ZoneList<Variable*>(0, zone());
4464 ZoneList<Variable*>* private_field_index_vars =
4465 new (zone()) ZoneList<Variable*>(0, zone());
4418 FunctionLiteral* constructor = nullptr; 4466 FunctionLiteral* constructor = nullptr;
4419 bool has_seen_constructor = false; 4467 bool has_seen_constructor = false;
4420 Variable* static_initializer_var = nullptr; 4468 Variable* static_initializer_var = nullptr;
4421 4469
4422 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); 4470 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
4423 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); 4471 Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
4424 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); 4472 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
4425 4473
4426 Expect(Token::LBRACE, CHECK_OK); 4474 Expect(Token::LBRACE, CHECK_OK);
4427 4475
4428 const bool has_extends = extends != nullptr; 4476 const bool has_extends = extends != nullptr;
4429 while (peek() != Token::RBRACE) { 4477 while (peek() != Token::RBRACE) {
4430 if (Check(Token::SEMICOLON)) continue; 4478 if (Check(Token::SEMICOLON)) continue;
4431 FuncNameInferrer::State fni_state(fni_); 4479 FuncNameInferrer::State fni_state(fni_);
4480 const AstRawString* private_name = nullptr;
4432 bool is_computed_name = false; // Classes do not care about computed 4481 bool is_computed_name = false; // Classes do not care about computed
4433 // property names here. 4482 // property names here.
4434 ExpressionClassifier property_classifier(this); 4483 ExpressionClassifier property_classifier(this);
4435 ClassLiteral::Property* property = 4484 ClassLiteral::Property* property = ParseClassPropertyDefinition(
4436 ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name, 4485 &checker, has_extends, &private_name, &is_computed_name,
4437 &has_seen_constructor, CHECK_OK); 4486 &has_seen_constructor, CHECK_OK);
4438 RewriteNonPattern(CHECK_OK); 4487 RewriteNonPattern(CHECK_OK);
4439 impl()->AccumulateFormalParameterContainmentErrors(); 4488 impl()->AccumulateFormalParameterContainmentErrors();
4440 4489
4441 if (has_seen_constructor && constructor == nullptr) { 4490 if (has_seen_constructor && constructor == nullptr) {
4442 constructor = GetPropertyValue(property)->AsFunctionLiteral(); 4491 constructor = GetPropertyValue(property)->AsFunctionLiteral();
4443 DCHECK_NOT_NULL(constructor); 4492 DCHECK_NOT_NULL(constructor);
4444 constructor->set_raw_name( 4493 constructor->set_raw_name(
4445 name != nullptr ? name : ast_value_factory()->empty_string()); 4494 name != nullptr ? name : ast_value_factory()->empty_string());
4446 } else { 4495 } else {
4447 if (property->kind() == ClassLiteralProperty::FIELD) { 4496 if (property->kind() == ClassLiteralProperty::FIELD) {
4448 DCHECK(allow_harmony_class_fields()); 4497 if (private_name != nullptr) {
4449 if (property->is_static()) { 4498 DCHECK(allow_harmony_private_class_fields());
4499 DCHECK(property->key() == nullptr);
4500 DCHECK(!property->is_static());
4501
4502 const AstRawString* symbol_var_name =
4503 ClassPrivateFieldVariableName(ast_value_factory(), private_name);
4504 VariableProxy* symbol_var_proxy = NewUnresolved(symbol_var_name);
4505 Declaration* symbol_var_declaration =
4506 factory()->NewVariableDeclaration(symbol_var_proxy, scope(),
4507 kNoSourcePosition);
4508 Variable* symbol_var =
4509 Declare(symbol_var_declaration, DeclarationDescriptor::NORMAL,
4510 CONST, kCreatedInitialized, ok, scope());
4511 private_field_symbol_vars->Add(symbol_var, zone());
4512
4513 const AstRawString* index_var_name = ClassFieldVariableName(
4514 true, ast_value_factory(), instance_field_initializers->length());
4515 VariableProxy* index_var_proxy = NewUnresolved(index_var_name);
4516 Declaration* index_var_declaration =
4517 factory()->NewVariableDeclaration(index_var_proxy, scope(),
4518 kNoSourcePosition);
4519 Variable* index_var =
4520 Declare(index_var_declaration, DeclarationDescriptor::NORMAL,
4521 CONST, kCreatedInitialized, ok, scope());
4522 private_field_index_vars->Add(index_var, zone());
4523
4524 instance_field_initializers->Add(property->value(), zone());
4525
4526 // Does not add to properties because no action is required from the
4527 // backend during class definition.
4528 } else if (property->is_static()) {
4529 DCHECK(allow_harmony_class_fields());
4450 if (static_initializer_var == nullptr) { 4530 if (static_initializer_var == nullptr) {
4451 static_initializer_var = 4531 static_initializer_var =
4452 NewTemporary(ast_value_factory()->empty_string()); 4532 NewTemporary(ast_value_factory()->empty_string());
4453 } 4533 }
4454 // TODO(bakkot) only do this conditionally 4534 // TODO(bakkot) only do this conditionally
4455 Expression* function = InstallHomeObject( 4535 Expression* function = InstallHomeObject(
4456 property->value(), 4536 property->value(),
4457 factory()->NewVariableProxy(static_initializer_var)); 4537 factory()->NewVariableProxy(static_initializer_var));
4458 ZoneList<Expression*>* args = 4538 ZoneList<Expression*>* args =
4459 new (zone()) ZoneList<Expression*>(2, zone()); 4539 new (zone()) ZoneList<Expression*>(2, zone());
4460 args->Add(function, zone()); 4540 args->Add(function, zone());
4461 args->Add(factory()->NewVariableProxy(static_initializer_var), 4541 args->Add(factory()->NewVariableProxy(static_initializer_var),
4462 zone()); 4542 zone());
4463 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, 4543 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall,
4464 args, kNoSourcePosition); 4544 args, kNoSourcePosition);
4465 property->set_value(call); 4545 property->set_value(call);
4546 properties->Add(property, zone());
4466 } else { 4547 } else {
4548 DCHECK(allow_harmony_class_fields());
4467 // if (is_computed_name) { // TODO(bakkot) figure out why this is 4549 // if (is_computed_name) { // TODO(bakkot) figure out why this is
4468 // necessary for non-computed names in full-codegen 4550 // necessary for non-computed names in full-codegen
4469 ZoneList<Expression*>* to_name_args = 4551 ZoneList<Expression*>* to_name_args =
4470 new (zone()) ZoneList<Expression*>(1, zone()); 4552 new (zone()) ZoneList<Expression*>(1, zone());
4471 to_name_args->Add(property->key(), zone()); 4553 to_name_args->Add(property->key(), zone());
4472 property->set_key(factory()->NewCallRuntime( 4554 property->set_key(factory()->NewCallRuntime(
4473 Runtime::kToName, to_name_args, kNoSourcePosition)); 4555 Runtime::kToName, to_name_args, kNoSourcePosition));
4474 //} 4556 //}
4475 const AstRawString* name = ClassFieldVariableName( 4557 const AstRawString* name = ClassFieldVariableName(
4476 true, ast_value_factory(), instance_field_initializers->length()); 4558 true, ast_value_factory(), instance_field_initializers->length());
4477 VariableProxy* name_proxy = NewUnresolved(name); 4559 VariableProxy* name_proxy = NewUnresolved(name);
4478 Declaration* name_declaration = 4560 Declaration* name_declaration =
4479 factory() 4561 factory()
4480 ->NewVariableDeclaration( // TODO(bakkot) DeclareLocal? not 4562 ->NewVariableDeclaration( // TODO(bakkot) DeclareLocal? not
4481 // clear on the difference... 4563 // clear on the difference...
4482 name_proxy, scope(), kNoSourcePosition); 4564 name_proxy, scope(), kNoSourcePosition);
4483 Variable* name_var = 4565 Variable* index_var =
4484 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, 4566 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
4485 kNeedsInitialization, ok, scope()); 4567 kNeedsInitialization, ok, scope());
4486 DCHECK(ok); 4568 DCHECK(ok);
4487 if (!ok) return nullptr; 4569 if (!ok) return nullptr;
4488 instance_field_initializers->Add(property->value(), zone()); 4570 instance_field_initializers->Add(property->value(), zone());
4489 property->set_value(factory()->NewVariableProxy(name_var)); 4571 property->set_value(factory()->NewVariableProxy(index_var));
4572 properties->Add(property, zone());
4490 } 4573 }
4574 } else {
4575 properties->Add(property, zone());
4491 } 4576 }
4492 properties->Add(property, zone());
4493 } 4577 }
4494 4578
4495 DCHECK_NOT_NULL(fni_); 4579 DCHECK_NOT_NULL(fni_);
4496 fni_->Infer(); 4580 fni_->Infer();
4497 } 4581 }
4498 4582
4499 Expect(Token::RBRACE, CHECK_OK); 4583 Expect(Token::RBRACE, CHECK_OK);
4500 int end_pos = scanner()->location().end_pos; 4584 int end_pos = scanner()->location().end_pos;
4501 4585
4502 bool has_instance_fields = instance_field_initializers->length() > 0; 4586 bool has_instance_fields = instance_field_initializers->length() > 0;
4503 DCHECK(!has_instance_fields || allow_harmony_class_fields()); 4587 DCHECK(!has_instance_fields || allow_harmony_class_fields() ||
4588 allow_harmony_private_class_fields());
4504 bool has_default_constructor = constructor == nullptr; 4589 bool has_default_constructor = constructor == nullptr;
4505 if (has_default_constructor) { 4590 if (has_default_constructor) {
4506 constructor = DefaultConstructor(name, has_extends, has_instance_fields, 4591 constructor = DefaultConstructor(name, has_extends, has_instance_fields,
4507 pos, end_pos, block_state.language_mode()); 4592 pos, end_pos, block_state.language_mode());
4508 } 4593 }
4509 4594
4510 if (has_instance_fields && extends == nullptr) { 4595 if (has_instance_fields && extends == nullptr) {
4511 constructor = InsertClassFieldInitializer(constructor); 4596 constructor = InsertClassFieldInitializer(constructor);
4512 constructor->set_requires_class_field_init(true); 4597 constructor->set_requires_class_field_init(true);
4513 } // The derived case is handled by rewriting super calls. 4598 } // The derived case is handled by rewriting super calls.
4514 4599
4515 block_state.set_end_position(end_pos); 4600 block_state.set_end_position(end_pos);
4516 4601
4517 if (name != nullptr) { 4602 if (name != nullptr) {
4518 DCHECK_NOT_NULL(proxy); 4603 DCHECK_NOT_NULL(proxy);
4519 proxy->var()->set_initializer_position(end_pos); 4604 proxy->var()->set_initializer_position(end_pos);
4520 } 4605 }
4521 4606
4607 // The parser creates two variables for every private field, both of which
4608 // store the private symbol which serves as the key for that field. One of
4609 // them, 'symbol_var', is used when referencing private fields with '#a' in
4610 // normal code. The other, 'index_var', is used when initializing the field.
4611 // The later variable is necessary because the synthetic field initialization
4612 // function has available to it *only* the number of fields in the class.
4613 // The desugaring looks something like this:
4614 //
4615 // class C {
4616 // #foo = 0;
4617 // baz;
4618 // m(){
4619 // this.#bar = 'a';
4620 // #foo = 1;
4621 // }
4622 // #bar;
4623 // }
4624 // -- becomes --
4625 // do {
4626 // class C {
4627 // m(){
4628 // %ThrowIfMissingPrivateField(this, .bar-symbol)[.bar-symbol] = 'a';
4629 // %ThrowIfMissingPrivateField(this, .foo-symbol)[.foo-symbol] = 1;
4630 // }
4631 // constructor(){
4632 // .initialize.call(this);
4633 // }
4634 // }
4635 //
4636 // let .foo-symbol, .name-0, .init-0;
4637 // .foo-symbol = .name-0 = PrivateSymbol();
4638 // .init-0 = ()=>0;
4639 //
4640 // let .name-1, .init-1;
4641 // // .name-1 is given value 'baz' by the backends during class definition
4642 // .init-1 = ()=>undefined;
4643 //
4644 // let .bar-symbol, .name-2, .init-2;
4645 // .bar-symbol = .name-2 = PrivateSymbol();
4646 // .init-2 = ()=>undefined;
4647 //
4648 // .initialize() {
4649 // this[.name-0] = .init-0(); // Actually this is defineOwnProperty not =
4650 // this[.name-1] = .init-1();
4651 // this[.name-2] = .init-2();
4652 // }
4653 //
4654 // C;
4655 // }
4656 DCHECK(private_field_symbol_vars->length() ==
4657 private_field_index_vars->length());
4658 DCHECK(!allow_harmony_private_class_fields() ||
4659 private_field_symbol_vars->length() == 0);
4660 for (int i = 0; i < private_field_symbol_vars->length(); ++i) {
4661 VariableProxy* symbol_var_proxy =
4662 factory()->NewVariableProxy(private_field_symbol_vars->at(i));
4663 VariableProxy* index_var_proxy =
4664 factory()->NewVariableProxy(private_field_index_vars->at(i));
4665
4666 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4667 args->Add(factory()->NewUndefinedLiteral(kNoSourcePosition), zone());
4668 Expression* name =
4669 factory()->NewCallRuntime(Runtime::kCreatePrivateSymbol, args, pos);
4670
4671 Assignment* inner_assignment = factory()->NewAssignment(
4672 Token::INIT, index_var_proxy, name, kNoSourcePosition);
4673 Assignment* outer_assignment = factory()->NewAssignment(
4674 Token::INIT, symbol_var_proxy, inner_assignment, kNoSourcePosition);
4675 do_block->statements()->Add(
4676 factory()->NewExpressionStatement(outer_assignment, kNoSourcePosition),
4677 zone());
4678 }
4679
4522 ClassLiteral* class_literal = factory()->NewClassLiteral( 4680 ClassLiteral* class_literal = factory()->NewClassLiteral(
4523 proxy, extends, constructor, properties, pos, end_pos); 4681 proxy, extends, constructor, properties, pos, end_pos);
4524 4682
4525 if (static_initializer_var != nullptr) { 4683 if (static_initializer_var != nullptr) {
4526 class_literal->set_static_initializer_proxy( 4684 class_literal->set_static_initializer_proxy(
4527 factory()->NewVariableProxy(static_initializer_var)); 4685 factory()->NewVariableProxy(static_initializer_var));
4528 } 4686 }
4529 4687
4530 do_block->statements()->Add( 4688 do_block->statements()->Add(
4531 factory()->NewExpressionStatement( 4689 factory()->NewExpressionStatement(
4532 factory()->NewAssignment(Token::ASSIGN, 4690 factory()->NewAssignment(Token::ASSIGN,
4533 factory()->NewVariableProxy(result_var), 4691 factory()->NewVariableProxy(result_var),
4534 class_literal, kNoSourcePosition), 4692 class_literal, kNoSourcePosition),
4535 pos), 4693 pos),
4536 zone()); 4694 zone());
4537 if (allow_harmony_class_fields() && 4695 if ((allow_harmony_class_fields() || allow_harmony_private_class_fields()) &&
4538 (has_instance_fields || 4696 (has_instance_fields ||
4539 (extends != nullptr && !has_default_constructor))) { 4697 (extends != nullptr && !has_default_constructor))) {
4540 // Default constructors for derived classes without fields will not try to 4698 // Default constructors for derived classes without fields will not try to
4541 // read this variable, so there's no need to create it. 4699 // read this variable, so there's no need to create it.
4542 const AstRawString* init_fn_name = 4700 const AstRawString* init_fn_name =
4543 ast_value_factory()->GetOneByteString(".class-field-initializer"); 4701 ast_value_factory()->GetOneByteString(".class-field-initializer");
4544 Variable* init_fn_var = 4702 Variable* init_fn_var =
4545 scope()->DeclareLocal(init_fn_name, CONST, kCreatedInitialized, 4703 scope()->DeclareLocal(init_fn_name, CONST, kCreatedInitialized,
4546 Variable::NORMAL); // TODO(bakkot) flags 4704 Variable::NORMAL); // TODO(bakkot) flags
4547 Expression* initializer = 4705 Expression* initializer =
(...skipping 1922 matching lines...) Expand 10 before | Expand all | Expand 10 after
6470 node->Print(Isolate::Current()); 6628 node->Print(Isolate::Current());
6471 } 6629 }
6472 #endif // DEBUG 6630 #endif // DEBUG
6473 6631
6474 #undef CHECK_OK 6632 #undef CHECK_OK
6475 #undef CHECK_OK_VOID 6633 #undef CHECK_OK_VOID
6476 #undef CHECK_FAILED 6634 #undef CHECK_FAILED
6477 6635
6478 } // namespace internal 6636 } // namespace internal
6479 } // namespace v8 6637 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698