| 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| 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 Loading... |
| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4322 define_property_args->Add( | 4366 define_property_args->Add( |
| 4323 factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone()); | 4367 factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone()); |
| 4324 define_property_args->Add( | 4368 define_property_args->Add( |
| 4325 factory()->NewNumberLiteral( | 4369 factory()->NewNumberLiteral( |
| 4326 false, // TODO(bakkot) function name inference a la class { x = | 4370 false, // TODO(bakkot) function name inference a la class { x = |
| 4327 // function(){}; static y = function(){}; } | 4371 // function(){}; static y = function(){}; } |
| 4328 kNoSourcePosition), | 4372 kNoSourcePosition), |
| 4329 zone()); | 4373 zone()); |
| 4330 body->Add(factory()->NewExpressionStatement( | 4374 body->Add(factory()->NewExpressionStatement( |
| 4331 factory()->NewCallRuntime( | 4375 factory()->NewCallRuntime( |
| 4332 Runtime::kDefineDataPropertyInLiteral, | 4376 Runtime::kDefineDataProperty, |
| 4333 define_property_args, // TODO(bakkot) verify that this is | 4377 define_property_args, // TODO(bakkot) verify that this is |
| 4334 // the same as object_define_property | 4378 // the same as object_define_property |
| 4335 kNoSourcePosition), | 4379 kNoSourcePosition), |
| 4336 kNoSourcePosition), | 4380 kNoSourcePosition), |
| 4337 zone()); | 4381 zone()); |
| 4338 } | 4382 } |
| 4339 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), | 4383 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), |
| 4340 kNoSourcePosition), | 4384 kNoSourcePosition), |
| 4341 zone()); | 4385 zone()); |
| 4342 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 4386 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |