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 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 ReportMessage(MessageTemplate::kParamDupe); | 1525 ReportMessage(MessageTemplate::kParamDupe); |
1526 } | 1526 } |
1527 return nullptr; | 1527 return nullptr; |
1528 } | 1528 } |
1529 if (sloppy_mode_block_scope_function_redefinition) { | 1529 if (sloppy_mode_block_scope_function_redefinition) { |
1530 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition]; | 1530 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition]; |
1531 } | 1531 } |
1532 return variable; | 1532 return variable; |
1533 } | 1533 } |
1534 | 1534 |
| 1535 // Language extension which is only enabled for source files loaded |
| 1536 // through the API's extension mechanism. A native function |
| 1537 // declaration is resolved by looking up the function through a |
| 1538 // callback provided by the extension. |
| 1539 Statement* Parser::ParseNativeDeclaration(bool* ok) { |
| 1540 int pos = peek_position(); |
| 1541 Expect(Token::FUNCTION, CHECK_OK); |
| 1542 // Allow "eval" or "arguments" for backward compatibility. |
| 1543 const AstRawString* name = |
| 1544 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 1545 Expect(Token::LPAREN, CHECK_OK); |
| 1546 bool done = (peek() == Token::RPAREN); |
| 1547 while (!done) { |
| 1548 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 1549 done = (peek() == Token::RPAREN); |
| 1550 if (!done) { |
| 1551 Expect(Token::COMMA, CHECK_OK); |
| 1552 } |
| 1553 } |
| 1554 Expect(Token::RPAREN, CHECK_OK); |
| 1555 Expect(Token::SEMICOLON, CHECK_OK); |
| 1556 |
| 1557 // Make sure that the function containing the native declaration |
| 1558 // isn't lazily compiled. The extension structures are only |
| 1559 // accessible while parsing the first time not when reparsing |
| 1560 // because of lazy compilation. |
| 1561 GetClosureScope()->ForceEagerCompilation(); |
| 1562 |
| 1563 // TODO(1240846): It's weird that native function declarations are |
| 1564 // introduced dynamically when we meet their declarations, whereas |
| 1565 // other functions are set up when entering the surrounding scope. |
| 1566 Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK); |
| 1567 NativeFunctionLiteral* lit = |
| 1568 factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition); |
| 1569 return factory()->NewExpressionStatement( |
| 1570 factory()->NewAssignment(Token::INIT, decl->proxy(), lit, |
| 1571 kNoSourcePosition), |
| 1572 pos); |
| 1573 } |
| 1574 |
| 1575 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
| 1576 bool default_export, bool* ok) { |
| 1577 // ClassDeclaration :: |
| 1578 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' |
| 1579 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' |
| 1580 // |
| 1581 // The anonymous form is allowed iff [default_export] is true. |
| 1582 // |
| 1583 // 'class' is expected to be consumed by the caller. |
| 1584 // |
| 1585 // A ClassDeclaration |
| 1586 // |
| 1587 // class C { ... } |
| 1588 // |
| 1589 // has the same semantics as: |
| 1590 // |
| 1591 // let C = class C { ... }; |
| 1592 // |
| 1593 // so rewrite it as such. |
| 1594 |
| 1595 int pos = position(); |
| 1596 |
| 1597 const AstRawString* name; |
| 1598 bool is_strict_reserved; |
| 1599 const AstRawString* variable_name; |
| 1600 if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) { |
| 1601 name = ast_value_factory()->default_string(); |
| 1602 is_strict_reserved = false; |
| 1603 variable_name = ast_value_factory()->star_default_star_string(); |
| 1604 } else { |
| 1605 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 1606 variable_name = name; |
| 1607 } |
| 1608 |
| 1609 ExpressionClassifier no_classifier(this); |
| 1610 Expression* value = ParseClassLiteral(name, scanner()->location(), |
| 1611 is_strict_reserved, pos, CHECK_OK); |
| 1612 |
| 1613 Declaration* decl = DeclareVariable(variable_name, LET, pos, CHECK_OK); |
| 1614 decl->proxy()->var()->set_initializer_position(position()); |
| 1615 Assignment* assignment = |
| 1616 factory()->NewAssignment(Token::INIT, decl->proxy(), value, pos); |
| 1617 Statement* assignment_statement = |
| 1618 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
| 1619 if (names) names->Add(variable_name, zone()); |
| 1620 return assignment_statement; |
| 1621 } |
| 1622 |
1535 Block* Parser::BuildInitializationBlock( | 1623 Block* Parser::BuildInitializationBlock( |
1536 DeclarationParsingResult* parsing_result, | 1624 DeclarationParsingResult* parsing_result, |
1537 ZoneList<const AstRawString*>* names, bool* ok) { | 1625 ZoneList<const AstRawString*>* names, bool* ok) { |
1538 Block* result = factory()->NewBlock( | 1626 Block* result = factory()->NewBlock( |
1539 NULL, 1, true, parsing_result->descriptor.declaration_pos); | 1627 NULL, 1, true, parsing_result->descriptor.declaration_pos); |
1540 for (auto declaration : parsing_result->declarations) { | 1628 for (auto declaration : parsing_result->declarations) { |
1541 PatternRewriter::DeclareAndInitializeVariables( | 1629 PatternRewriter::DeclareAndInitializeVariables( |
1542 this, result, &(parsing_result->descriptor), &declaration, names, | 1630 this, result, &(parsing_result->descriptor), &declaration, names, |
1543 CHECK_OK); | 1631 CHECK_OK); |
1544 } | 1632 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1580 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { | 1668 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { |
1581 SloppyBlockFunctionStatement* delegate = | 1669 SloppyBlockFunctionStatement* delegate = |
1582 factory()->NewSloppyBlockFunctionStatement(scope()); | 1670 factory()->NewSloppyBlockFunctionStatement(scope()); |
1583 DeclarationScope* target_scope = GetDeclarationScope(); | 1671 DeclarationScope* target_scope = GetDeclarationScope(); |
1584 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); | 1672 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); |
1585 return delegate; | 1673 return delegate; |
1586 } | 1674 } |
1587 return factory()->NewEmptyStatement(kNoSourcePosition); | 1675 return factory()->NewEmptyStatement(kNoSourcePosition); |
1588 } | 1676 } |
1589 | 1677 |
1590 Statement* Parser::DeclareClass(const AstRawString* variable_name, | |
1591 Expression* value, | |
1592 ZoneList<const AstRawString*>* names, | |
1593 int class_token_pos, int end_pos, bool* ok) { | |
1594 Declaration* decl = | |
1595 DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK); | |
1596 decl->proxy()->var()->set_initializer_position(end_pos); | |
1597 Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(), | |
1598 value, class_token_pos); | |
1599 Statement* assignment_statement = | |
1600 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | |
1601 if (names) names->Add(variable_name, zone()); | |
1602 return assignment_statement; | |
1603 } | |
1604 | |
1605 Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) { | |
1606 // Make sure that the function containing the native declaration | |
1607 // isn't lazily compiled. The extension structures are only | |
1608 // accessible while parsing the first time not when reparsing | |
1609 // because of lazy compilation. | |
1610 GetClosureScope()->ForceEagerCompilation(); | |
1611 | |
1612 // TODO(1240846): It's weird that native function declarations are | |
1613 // introduced dynamically when we meet their declarations, whereas | |
1614 // other functions are set up when entering the surrounding scope. | |
1615 Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK); | |
1616 NativeFunctionLiteral* lit = | |
1617 factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition); | |
1618 return factory()->NewExpressionStatement( | |
1619 factory()->NewAssignment(Token::INIT, decl->proxy(), lit, | |
1620 kNoSourcePosition), | |
1621 pos); | |
1622 } | |
1623 | |
1624 ZoneList<const AstRawString*>* Parser::DeclareLabel( | 1678 ZoneList<const AstRawString*>* Parser::DeclareLabel( |
1625 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) { | 1679 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) { |
1626 const AstRawString* label = var->raw_name(); | 1680 const AstRawString* label = var->raw_name(); |
1627 // TODO(1240780): We don't check for redeclaration of labels | 1681 // TODO(1240780): We don't check for redeclaration of labels |
1628 // during preparsing since keeping track of the set of active | 1682 // during preparsing since keeping track of the set of active |
1629 // labels requires nontrivial changes to the way scopes are | 1683 // labels requires nontrivial changes to the way scopes are |
1630 // structured. However, these are probably changes we want to | 1684 // structured. However, these are probably changes we want to |
1631 // make later anyway so we should go back and fix this then. | 1685 // make later anyway so we should go back and fix this then. |
1632 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | 1686 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
1633 ReportMessage(MessageTemplate::kLabelRedeclaration, label); | 1687 ReportMessage(MessageTemplate::kLabelRedeclaration, label); |
(...skipping 1817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3451 CallClassFieldInitializer( | 3505 CallClassFieldInitializer( |
3452 constructor->scope(), | 3506 constructor->scope(), |
3453 constructor->scope()->NewUnresolved( | 3507 constructor->scope()->NewUnresolved( |
3454 factory(), ast_value_factory()->this_string(), kNoSourcePosition, | 3508 factory(), ast_value_factory()->this_string(), kNoSourcePosition, |
3455 kNoSourcePosition + 4, THIS_VARIABLE)), | 3509 kNoSourcePosition + 4, THIS_VARIABLE)), |
3456 kNoSourcePosition); | 3510 kNoSourcePosition); |
3457 constructor->body()->InsertAt(0, call_initializer, zone()); | 3511 constructor->body()->InsertAt(0, call_initializer, zone()); |
3458 return constructor; | 3512 return constructor; |
3459 } | 3513 } |
3460 | 3514 |
3461 // If a class name is specified, this method declares the class variable | 3515 Expression* Parser::ParseClassLiteral(const AstRawString* name, |
3462 // and sets class_info->proxy to point to that name. | 3516 Scanner::Location class_name_location, |
3463 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, | 3517 bool name_is_strict_reserved, int pos, |
3464 ClassInfo* class_info, int class_token_pos, | 3518 bool* ok) { |
3465 bool* ok) { | 3519 // All parts of a ClassDeclaration and ClassExpression are strict code. |
| 3520 if (name_is_strict_reserved) { |
| 3521 ReportMessageAt(class_name_location, |
| 3522 MessageTemplate::kUnexpectedStrictReserved); |
| 3523 *ok = false; |
| 3524 return nullptr; |
| 3525 } |
| 3526 if (IsEvalOrArguments(name)) { |
| 3527 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); |
| 3528 *ok = false; |
| 3529 return nullptr; |
| 3530 } |
| 3531 |
| 3532 BlockState block_state(zone(), &scope_state_); |
| 3533 RaiseLanguageMode(STRICT); |
3466 #ifdef DEBUG | 3534 #ifdef DEBUG |
3467 scope()->SetScopeName(name); | 3535 scope()->SetScopeName(name); |
3468 #endif | 3536 #endif |
3469 | 3537 |
| 3538 VariableProxy* proxy = nullptr; |
3470 if (name != nullptr) { | 3539 if (name != nullptr) { |
3471 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); | 3540 proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
3472 Declaration* declaration = factory()->NewVariableDeclaration( | 3541 // TODO(verwaest): declare via block_state. |
3473 class_info->proxy, block_scope, class_token_pos); | 3542 Declaration* declaration = |
| 3543 factory()->NewVariableDeclaration(proxy, block_state.scope(), pos); |
3474 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, | 3544 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, |
3475 Variable::DefaultInitializationFlag(CONST), ok); | 3545 Variable::DefaultInitializationFlag(CONST), CHECK_OK); |
3476 } | |
3477 } | |
3478 | |
3479 // This method declares a property of the given class. It updates the | |
3480 // following fields of class_info, as appropriate: | |
3481 // - constructor | |
3482 // - static_initializer_var | |
3483 // - instance_field_initializers | |
3484 // - properties | |
3485 void Parser::DeclareClassProperty(const AstRawString* class_name, | |
3486 ClassLiteralProperty* property, | |
3487 ClassInfo* class_info, bool* ok) { | |
3488 if (class_info->has_seen_constructor && class_info->constructor == nullptr) { | |
3489 class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral(); | |
3490 DCHECK_NOT_NULL(class_info->constructor); | |
3491 class_info->constructor->set_raw_name( | |
3492 class_name != nullptr ? class_name | |
3493 : ast_value_factory()->empty_string()); | |
3494 return; | |
3495 } | 3546 } |
3496 | 3547 |
3497 if (property->kind() == ClassLiteralProperty::FIELD) { | 3548 Expression* extends = nullptr; |
3498 DCHECK(allow_harmony_class_fields()); | 3549 if (Check(Token::EXTENDS)) { |
3499 if (property->is_static()) { | 3550 block_state.set_start_position(scanner()->location().end_pos); |
3500 if (class_info->static_initializer_var == nullptr) { | 3551 ExpressionClassifier extends_classifier(this); |
3501 class_info->static_initializer_var = | 3552 extends = ParseLeftHandSideExpression(CHECK_OK); |
3502 NewTemporary(ast_value_factory()->empty_string()); | 3553 RewriteNonPattern(CHECK_OK); |
3503 } | 3554 impl()->AccumulateFormalParameterContainmentErrors(); |
3504 // TODO(bakkot) only do this conditionally | 3555 } else { |
3505 Expression* function = InstallHomeObject( | 3556 block_state.set_start_position(scanner()->location().end_pos); |
3506 property->value(), | |
3507 factory()->NewVariableProxy(class_info->static_initializer_var)); | |
3508 ZoneList<Expression*>* args = | |
3509 new (zone()) ZoneList<Expression*>(2, zone()); | |
3510 args->Add(function, zone()); | |
3511 args->Add(factory()->NewVariableProxy(class_info->static_initializer_var), | |
3512 zone()); | |
3513 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, | |
3514 kNoSourcePosition); | |
3515 property->set_value(call); | |
3516 } else { | |
3517 // if (is_computed_name) { // TODO(bakkot) figure out why this is | |
3518 // necessary for non-computed names in full-codegen | |
3519 ZoneList<Expression*>* to_name_args = | |
3520 new (zone()) ZoneList<Expression*>(1, zone()); | |
3521 to_name_args->Add(property->key(), zone()); | |
3522 property->set_key(factory()->NewCallRuntime( | |
3523 Runtime::kToName, to_name_args, kNoSourcePosition)); | |
3524 //} | |
3525 const AstRawString* name = ClassFieldVariableName( | |
3526 true, ast_value_factory(), | |
3527 class_info->instance_field_initializers->length()); | |
3528 VariableProxy* name_proxy = | |
3529 factory()->NewVariableProxy(name, NORMAL_VARIABLE); | |
3530 Declaration* name_declaration = factory()->NewVariableDeclaration( | |
3531 name_proxy, scope(), kNoSourcePosition); | |
3532 Variable* name_var = | |
3533 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, | |
3534 kNeedsInitialization, ok, scope()); | |
3535 DCHECK(*ok); | |
3536 if (!*ok) return; | |
3537 class_info->instance_field_initializers->Add(property->value(), zone()); | |
3538 property->set_value(factory()->NewVariableProxy(name_var)); | |
3539 } | |
3540 } | 3557 } |
3541 class_info->properties->Add(property, zone()); | |
3542 } | |
3543 | 3558 |
3544 // This method rewrites a class literal into a do-expression. | 3559 |
3545 // It uses the following fields of class_info: | 3560 ClassLiteralChecker checker(this); |
3546 // - constructor (if missing, it updates it with a default constructor) | 3561 ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4); |
3547 // - proxy | 3562 ZoneList<Expression*>* instance_field_initializers = |
3548 // - extends | 3563 new (zone()) ZoneList<Expression*>(0, zone()); |
3549 // - static_initializer_var | 3564 FunctionLiteral* constructor = nullptr; |
3550 // - instance_field_initializers | 3565 bool has_seen_constructor = false; |
3551 // - properties | 3566 Variable* static_initializer_var = nullptr; |
3552 Expression* Parser::RewriteClassLiteral(const AstRawString* name, | 3567 |
3553 ClassInfo* class_info, int pos, | |
3554 bool* ok) { | |
3555 int end_pos = scanner()->location().end_pos; | |
3556 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); | 3568 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); |
3557 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); | 3569 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); |
3558 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); | 3570 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); |
3559 | 3571 |
3560 bool has_extends = class_info->extends != nullptr; | 3572 Expect(Token::LBRACE, CHECK_OK); |
3561 bool has_instance_fields = | 3573 |
3562 class_info->instance_field_initializers->length() > 0; | 3574 const bool has_extends = extends != nullptr; |
3563 DCHECK(!has_instance_fields || allow_harmony_class_fields()); | 3575 while (peek() != Token::RBRACE) { |
3564 bool has_default_constructor = class_info->constructor == nullptr; | 3576 if (Check(Token::SEMICOLON)) continue; |
3565 if (has_default_constructor) { | 3577 FuncNameInferrer::State fni_state(fni_); |
3566 class_info->constructor = | 3578 bool is_computed_name = false; // Classes do not care about computed |
3567 DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos, | 3579 // property names here. |
3568 scope()->language_mode()); | 3580 ExpressionClassifier property_classifier(this); |
| 3581 ClassLiteral::Property* property = |
| 3582 ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name, |
| 3583 &has_seen_constructor, CHECK_OK); |
| 3584 RewriteNonPattern(CHECK_OK); |
| 3585 impl()->AccumulateFormalParameterContainmentErrors(); |
| 3586 |
| 3587 if (has_seen_constructor && constructor == nullptr) { |
| 3588 constructor = GetPropertyValue(property)->AsFunctionLiteral(); |
| 3589 DCHECK_NOT_NULL(constructor); |
| 3590 constructor->set_raw_name( |
| 3591 name != nullptr ? name : ast_value_factory()->empty_string()); |
| 3592 } else { |
| 3593 if (property->kind() == ClassLiteralProperty::FIELD) { |
| 3594 DCHECK(allow_harmony_class_fields()); |
| 3595 if (property->is_static()) { |
| 3596 if (static_initializer_var == nullptr) { |
| 3597 static_initializer_var = |
| 3598 NewTemporary(ast_value_factory()->empty_string()); |
| 3599 } |
| 3600 // TODO(bakkot) only do this conditionally |
| 3601 Expression* function = InstallHomeObject( |
| 3602 property->value(), |
| 3603 factory()->NewVariableProxy(static_initializer_var)); |
| 3604 ZoneList<Expression*>* args = |
| 3605 new (zone()) ZoneList<Expression*>(2, zone()); |
| 3606 args->Add(function, zone()); |
| 3607 args->Add(factory()->NewVariableProxy(static_initializer_var), |
| 3608 zone()); |
| 3609 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, |
| 3610 args, kNoSourcePosition); |
| 3611 property->set_value(call); |
| 3612 } else { |
| 3613 // if (is_computed_name) { // TODO(bakkot) figure out why this is |
| 3614 // necessary for non-computed names in full-codegen |
| 3615 ZoneList<Expression*>* to_name_args = |
| 3616 new (zone()) ZoneList<Expression*>(1, zone()); |
| 3617 to_name_args->Add(property->key(), zone()); |
| 3618 property->set_key(factory()->NewCallRuntime( |
| 3619 Runtime::kToName, to_name_args, kNoSourcePosition)); |
| 3620 //} |
| 3621 const AstRawString* name = ClassFieldVariableName( |
| 3622 true, ast_value_factory(), instance_field_initializers->length()); |
| 3623 VariableProxy* name_proxy = |
| 3624 factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
| 3625 Declaration* name_declaration = factory()->NewVariableDeclaration( |
| 3626 name_proxy, scope(), kNoSourcePosition); |
| 3627 Variable* name_var = |
| 3628 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, |
| 3629 kNeedsInitialization, ok, scope()); |
| 3630 DCHECK(ok); |
| 3631 if (!ok) return nullptr; |
| 3632 instance_field_initializers->Add(property->value(), zone()); |
| 3633 property->set_value(factory()->NewVariableProxy(name_var)); |
| 3634 } |
| 3635 } |
| 3636 properties->Add(property, zone()); |
| 3637 } |
| 3638 |
| 3639 DCHECK_NOT_NULL(fni_); |
| 3640 fni_->Infer(); |
3569 } | 3641 } |
3570 | 3642 |
3571 if (has_instance_fields && !has_extends) { | 3643 Expect(Token::RBRACE, CHECK_OK); |
3572 class_info->constructor = | 3644 int end_pos = scanner()->location().end_pos; |
3573 InsertClassFieldInitializer(class_info->constructor); | 3645 |
3574 class_info->constructor->set_requires_class_field_init(true); | 3646 bool has_instance_fields = instance_field_initializers->length() > 0; |
| 3647 DCHECK(!has_instance_fields || allow_harmony_class_fields()); |
| 3648 bool has_default_constructor = constructor == nullptr; |
| 3649 if (has_default_constructor) { |
| 3650 constructor = DefaultConstructor(name, has_extends, has_instance_fields, |
| 3651 pos, end_pos, block_state.language_mode()); |
| 3652 } |
| 3653 |
| 3654 if (has_instance_fields && extends == nullptr) { |
| 3655 constructor = InsertClassFieldInitializer(constructor); |
| 3656 constructor->set_requires_class_field_init(true); |
3575 } // The derived case is handled by rewriting super calls. | 3657 } // The derived case is handled by rewriting super calls. |
3576 | 3658 |
3577 scope()->set_end_position(end_pos); | 3659 block_state.set_end_position(end_pos); |
3578 | 3660 |
3579 if (name != nullptr) { | 3661 if (name != nullptr) { |
3580 DCHECK_NOT_NULL(class_info->proxy); | 3662 DCHECK_NOT_NULL(proxy); |
3581 class_info->proxy->var()->set_initializer_position(end_pos); | 3663 proxy->var()->set_initializer_position(end_pos); |
3582 } | 3664 } |
3583 | 3665 |
3584 ClassLiteral* class_literal = factory()->NewClassLiteral( | 3666 ClassLiteral* class_literal = factory()->NewClassLiteral( |
3585 class_info->proxy, class_info->extends, class_info->constructor, | 3667 proxy, extends, constructor, properties, pos, end_pos); |
3586 class_info->properties, pos, end_pos); | |
3587 | 3668 |
3588 if (class_info->static_initializer_var != nullptr) { | 3669 if (static_initializer_var != nullptr) { |
3589 class_literal->set_static_initializer_proxy( | 3670 class_literal->set_static_initializer_proxy( |
3590 factory()->NewVariableProxy(class_info->static_initializer_var)); | 3671 factory()->NewVariableProxy(static_initializer_var)); |
3591 } | 3672 } |
3592 | 3673 |
3593 do_block->statements()->Add( | 3674 do_block->statements()->Add( |
3594 factory()->NewExpressionStatement( | 3675 factory()->NewExpressionStatement( |
3595 factory()->NewAssignment(Token::ASSIGN, | 3676 factory()->NewAssignment(Token::ASSIGN, |
3596 factory()->NewVariableProxy(result_var), | 3677 factory()->NewVariableProxy(result_var), |
3597 class_literal, kNoSourcePosition), | 3678 class_literal, kNoSourcePosition), |
3598 pos), | 3679 pos), |
3599 zone()); | 3680 zone()); |
3600 if (allow_harmony_class_fields() && | 3681 if (allow_harmony_class_fields() && |
3601 (has_instance_fields || (has_extends && !has_default_constructor))) { | 3682 (has_instance_fields || |
| 3683 (extends != nullptr && !has_default_constructor))) { |
3602 // Default constructors for derived classes without fields will not try to | 3684 // Default constructors for derived classes without fields will not try to |
3603 // read this variable, so there's no need to create it. | 3685 // read this variable, so there's no need to create it. |
3604 const AstRawString* init_fn_name = | 3686 const AstRawString* init_fn_name = |
3605 ast_value_factory()->dot_class_field_init_string(); | 3687 ast_value_factory()->dot_class_field_init_string(); |
3606 Variable* init_fn_var = scope()->DeclareLocal( | 3688 Variable* init_fn_var = scope()->DeclareLocal( |
3607 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); | 3689 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); |
3608 Expression* initializer = | 3690 Expression* initializer = |
3609 has_instance_fields | 3691 has_instance_fields |
3610 ? static_cast<Expression*>(SynthesizeClassFieldInitializer( | 3692 ? static_cast<Expression*>(SynthesizeClassFieldInitializer( |
3611 class_info->instance_field_initializers->length())) | 3693 instance_field_initializers->length())) |
3612 : factory()->NewBooleanLiteral(false, kNoSourcePosition); | 3694 : factory()->NewBooleanLiteral(false, kNoSourcePosition); |
3613 Assignment* assignment = factory()->NewAssignment( | 3695 Assignment* assignment = factory()->NewAssignment( |
3614 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer, | 3696 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer, |
3615 kNoSourcePosition); | 3697 kNoSourcePosition); |
3616 do_block->statements()->Add( | 3698 do_block->statements()->Add( |
3617 factory()->NewExpressionStatement(assignment, kNoSourcePosition), | 3699 factory()->NewExpressionStatement(assignment, kNoSourcePosition), |
3618 zone()); | 3700 zone()); |
3619 } | 3701 } |
3620 for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) { | 3702 for (int i = 0; i < instance_field_initializers->length(); ++i) { |
3621 const AstRawString* function_name = | 3703 const AstRawString* function_name = |
3622 ClassFieldVariableName(false, ast_value_factory(), i); | 3704 ClassFieldVariableName(false, ast_value_factory(), i); |
3623 VariableProxy* function_proxy = | 3705 VariableProxy* function_proxy = |
3624 factory()->NewVariableProxy(function_name, NORMAL_VARIABLE); | 3706 factory()->NewVariableProxy(function_name, NORMAL_VARIABLE); |
3625 Declaration* function_declaration = factory()->NewVariableDeclaration( | 3707 Declaration* function_declaration = factory()->NewVariableDeclaration( |
3626 function_proxy, scope(), kNoSourcePosition); | 3708 function_proxy, scope(), kNoSourcePosition); |
3627 Variable* function_var = | 3709 Variable* function_var = |
3628 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST, | 3710 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST, |
3629 kNeedsInitialization, ok, scope()); | 3711 kNeedsInitialization, ok, scope()); |
3630 if (!*ok) return nullptr; | 3712 DCHECK(ok); |
| 3713 if (!ok) return nullptr; |
3631 Property* prototype_property = factory()->NewProperty( | 3714 Property* prototype_property = factory()->NewProperty( |
3632 factory()->NewVariableProxy(result_var), | 3715 factory()->NewVariableProxy(result_var), |
3633 factory()->NewStringLiteral(ast_value_factory()->prototype_string(), | 3716 factory()->NewStringLiteral(ast_value_factory()->prototype_string(), |
3634 kNoSourcePosition), | 3717 kNoSourcePosition), |
3635 kNoSourcePosition); | 3718 kNoSourcePosition); |
3636 Expression* function_value = InstallHomeObject( | 3719 Expression* function_value = InstallHomeObject( |
3637 class_info->instance_field_initializers->at(i), | 3720 instance_field_initializers->at(i), |
3638 prototype_property); // TODO(bakkot) ideally this would be conditional, | 3721 prototype_property); // TODO(bakkot) ideally this would be conditional, |
3639 // especially in trivial cases | 3722 // especially in trivial cases |
3640 Assignment* function_assignment = factory()->NewAssignment( | 3723 Assignment* function_assignment = factory()->NewAssignment( |
3641 Token::INIT, factory()->NewVariableProxy(function_var), function_value, | 3724 Token::INIT, factory()->NewVariableProxy(function_var), function_value, |
3642 kNoSourcePosition); | 3725 kNoSourcePosition); |
3643 do_block->statements()->Add(factory()->NewExpressionStatement( | 3726 do_block->statements()->Add(factory()->NewExpressionStatement( |
3644 function_assignment, kNoSourcePosition), | 3727 function_assignment, kNoSourcePosition), |
3645 zone()); | 3728 zone()); |
3646 } | 3729 } |
3647 do_block->set_scope(scope()->FinalizeBlockScope()); | 3730 do_block->set_scope(block_state.FinalizedBlockScope()); |
3648 do_expr->set_represented_function(class_info->constructor); | 3731 do_expr->set_represented_function(constructor); |
3649 | 3732 |
3650 return do_expr; | 3733 return do_expr; |
3651 } | 3734 } |
3652 | 3735 |
| 3736 |
3653 Literal* Parser::GetLiteralUndefined(int position) { | 3737 Literal* Parser::GetLiteralUndefined(int position) { |
3654 return factory()->NewUndefinedLiteral(position); | 3738 return factory()->NewUndefinedLiteral(position); |
3655 } | 3739 } |
3656 | 3740 |
3657 | 3741 |
3658 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | 3742 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
3659 Declaration* decl = scope->CheckConflictingVarDeclarations(); | 3743 Declaration* decl = scope->CheckConflictingVarDeclarations(); |
3660 if (decl != NULL) { | 3744 if (decl != NULL) { |
3661 // In ES6, conflicting variable bindings are early errors. | 3745 // In ES6, conflicting variable bindings are early errors. |
3662 const AstRawString* name = decl->proxy()->raw_name(); | 3746 const AstRawString* name = decl->proxy()->raw_name(); |
(...skipping 1789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5452 | 5536 |
5453 return final_loop; | 5537 return final_loop; |
5454 } | 5538 } |
5455 | 5539 |
5456 #undef CHECK_OK | 5540 #undef CHECK_OK |
5457 #undef CHECK_OK_VOID | 5541 #undef CHECK_OK_VOID |
5458 #undef CHECK_FAILED | 5542 #undef CHECK_FAILED |
5459 | 5543 |
5460 } // namespace internal | 5544 } // namespace internal |
5461 } // namespace v8 | 5545 } // namespace v8 |
OLD | NEW |