Chromium Code Reviews| 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 1504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1515 ReportMessage(MessageTemplate::kParamDupe); | 1515 ReportMessage(MessageTemplate::kParamDupe); |
| 1516 } | 1516 } |
| 1517 return nullptr; | 1517 return nullptr; |
| 1518 } | 1518 } |
| 1519 if (sloppy_mode_block_scope_function_redefinition) { | 1519 if (sloppy_mode_block_scope_function_redefinition) { |
| 1520 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition]; | 1520 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition]; |
| 1521 } | 1521 } |
| 1522 return variable; | 1522 return variable; |
| 1523 } | 1523 } |
| 1524 | 1524 |
| 1525 // Language extension which is only enabled for source files loaded | |
| 1526 // through the API's extension mechanism. A native function | |
| 1527 // declaration is resolved by looking up the function through a | |
| 1528 // callback provided by the extension. | |
| 1529 Statement* Parser::ParseNativeDeclaration(bool* ok) { | |
| 1530 int pos = peek_position(); | |
| 1531 Expect(Token::FUNCTION, CHECK_OK); | |
| 1532 // Allow "eval" or "arguments" for backward compatibility. | |
| 1533 const AstRawString* name = | |
| 1534 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 1535 Expect(Token::LPAREN, CHECK_OK); | |
| 1536 bool done = (peek() == Token::RPAREN); | |
| 1537 while (!done) { | |
| 1538 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
| 1539 done = (peek() == Token::RPAREN); | |
| 1540 if (!done) { | |
| 1541 Expect(Token::COMMA, CHECK_OK); | |
| 1542 } | |
| 1543 } | |
| 1544 Expect(Token::RPAREN, CHECK_OK); | |
| 1545 Expect(Token::SEMICOLON, CHECK_OK); | |
| 1546 | |
| 1547 // Make sure that the function containing the native declaration | |
| 1548 // isn't lazily compiled. The extension structures are only | |
| 1549 // accessible while parsing the first time not when reparsing | |
| 1550 // because of lazy compilation. | |
| 1551 GetClosureScope()->ForceEagerCompilation(); | |
| 1552 | |
| 1553 // TODO(1240846): It's weird that native function declarations are | |
| 1554 // introduced dynamically when we meet their declarations, whereas | |
| 1555 // other functions are set up when entering the surrounding scope. | |
| 1556 Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK); | |
| 1557 NativeFunctionLiteral* lit = | |
| 1558 factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition); | |
| 1559 return factory()->NewExpressionStatement( | |
| 1560 factory()->NewAssignment(Token::INIT, decl->proxy(), lit, | |
| 1561 kNoSourcePosition), | |
| 1562 pos); | |
| 1563 } | |
| 1564 | |
| 1565 Statement* Parser::ParseAsyncFunctionDeclaration( | 1525 Statement* Parser::ParseAsyncFunctionDeclaration( |
| 1566 ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { | 1526 ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
| 1567 DCHECK_EQ(scanner()->current_token(), Token::ASYNC); | 1527 DCHECK_EQ(scanner()->current_token(), Token::ASYNC); |
| 1568 int pos = position(); | 1528 int pos = position(); |
| 1569 if (scanner()->HasAnyLineTerminatorBeforeNext()) { | 1529 if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 1570 *ok = false; | 1530 *ok = false; |
| 1571 ReportUnexpectedToken(scanner()->current_token()); | 1531 ReportUnexpectedToken(scanner()->current_token()); |
| 1572 return nullptr; | 1532 return nullptr; |
| 1573 } | 1533 } |
| 1574 Expect(Token::FUNCTION, CHECK_OK); | 1534 Expect(Token::FUNCTION, CHECK_OK); |
| 1575 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; | 1535 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; |
| 1576 return ParseHoistableDeclaration(pos, flags, names, default_export, ok); | 1536 return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
| 1577 } | 1537 } |
| 1578 | 1538 |
| 1579 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | |
| 1580 bool default_export, bool* ok) { | |
| 1581 // ClassDeclaration :: | |
| 1582 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' | |
| 1583 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' | |
| 1584 // | |
| 1585 // The anonymous form is allowed iff [default_export] is true. | |
| 1586 // | |
| 1587 // 'class' is expected to be consumed by the caller. | |
| 1588 // | |
| 1589 // A ClassDeclaration | |
| 1590 // | |
| 1591 // class C { ... } | |
| 1592 // | |
| 1593 // has the same semantics as: | |
| 1594 // | |
| 1595 // let C = class C { ... }; | |
| 1596 // | |
| 1597 // so rewrite it as such. | |
| 1598 | |
| 1599 int pos = position(); | |
| 1600 | |
| 1601 const AstRawString* name; | |
| 1602 bool is_strict_reserved; | |
| 1603 const AstRawString* variable_name; | |
| 1604 if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) { | |
| 1605 name = ast_value_factory()->default_string(); | |
| 1606 is_strict_reserved = false; | |
| 1607 variable_name = ast_value_factory()->star_default_star_string(); | |
| 1608 } else { | |
| 1609 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | |
| 1610 variable_name = name; | |
| 1611 } | |
| 1612 | |
| 1613 ExpressionClassifier no_classifier(this); | |
| 1614 Expression* value = ParseClassLiteral(name, scanner()->location(), | |
| 1615 is_strict_reserved, pos, CHECK_OK); | |
| 1616 | |
| 1617 Declaration* decl = DeclareVariable(variable_name, LET, pos, CHECK_OK); | |
| 1618 decl->proxy()->var()->set_initializer_position(position()); | |
| 1619 Assignment* assignment = | |
| 1620 factory()->NewAssignment(Token::INIT, decl->proxy(), value, pos); | |
| 1621 Statement* assignment_statement = | |
| 1622 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | |
| 1623 if (names) names->Add(variable_name, zone()); | |
| 1624 return assignment_statement; | |
| 1625 } | |
| 1626 | |
| 1627 Block* Parser::BuildInitializationBlock( | 1539 Block* Parser::BuildInitializationBlock( |
| 1628 DeclarationParsingResult* parsing_result, | 1540 DeclarationParsingResult* parsing_result, |
| 1629 ZoneList<const AstRawString*>* names, bool* ok) { | 1541 ZoneList<const AstRawString*>* names, bool* ok) { |
| 1630 Block* result = factory()->NewBlock( | 1542 Block* result = factory()->NewBlock( |
| 1631 NULL, 1, true, parsing_result->descriptor.declaration_pos); | 1543 NULL, 1, true, parsing_result->descriptor.declaration_pos); |
| 1632 for (auto declaration : parsing_result->declarations) { | 1544 for (auto declaration : parsing_result->declarations) { |
| 1633 PatternRewriter::DeclareAndInitializeVariables( | 1545 PatternRewriter::DeclareAndInitializeVariables( |
| 1634 this, result, &(parsing_result->descriptor), &declaration, names, | 1546 this, result, &(parsing_result->descriptor), &declaration, names, |
| 1635 CHECK_OK); | 1547 CHECK_OK); |
| 1636 } | 1548 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1672 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { | 1584 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { |
| 1673 SloppyBlockFunctionStatement* delegate = | 1585 SloppyBlockFunctionStatement* delegate = |
| 1674 factory()->NewSloppyBlockFunctionStatement(scope()); | 1586 factory()->NewSloppyBlockFunctionStatement(scope()); |
| 1675 DeclarationScope* target_scope = GetDeclarationScope(); | 1587 DeclarationScope* target_scope = GetDeclarationScope(); |
| 1676 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); | 1588 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); |
| 1677 return delegate; | 1589 return delegate; |
| 1678 } | 1590 } |
| 1679 return factory()->NewEmptyStatement(kNoSourcePosition); | 1591 return factory()->NewEmptyStatement(kNoSourcePosition); |
| 1680 } | 1592 } |
| 1681 | 1593 |
| 1594 Statement* Parser::DeclareClass(const AstRawString* variable_name, | |
| 1595 Expression* value, | |
| 1596 ZoneList<const AstRawString*>* names, | |
| 1597 int class_token_pos, bool* ok) { | |
| 1598 Declaration* decl = | |
| 1599 DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK); | |
| 1600 decl->proxy()->var()->set_initializer_position(position()); | |
|
marja
2016/09/27 06:49:21
IMO none of the Parser impl funcs should call posi
nickie
2016/09/27 08:52:17
Yes, I agree. Although position() is a const meth
| |
| 1601 Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(), | |
| 1602 value, class_token_pos); | |
| 1603 Statement* assignment_statement = | |
| 1604 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | |
| 1605 if (names) names->Add(variable_name, zone()); | |
| 1606 return assignment_statement; | |
| 1607 } | |
| 1608 | |
| 1609 Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) { | |
| 1610 // Make sure that the function containing the native declaration | |
| 1611 // isn't lazily compiled. The extension structures are only | |
| 1612 // accessible while parsing the first time not when reparsing | |
| 1613 // because of lazy compilation. | |
| 1614 GetClosureScope()->ForceEagerCompilation(); | |
| 1615 | |
| 1616 // TODO(1240846): It's weird that native function declarations are | |
| 1617 // introduced dynamically when we meet their declarations, whereas | |
| 1618 // other functions are set up when entering the surrounding scope. | |
| 1619 Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK); | |
| 1620 NativeFunctionLiteral* lit = | |
| 1621 factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition); | |
| 1622 return factory()->NewExpressionStatement( | |
| 1623 factory()->NewAssignment(Token::INIT, decl->proxy(), lit, | |
| 1624 kNoSourcePosition), | |
| 1625 pos); | |
| 1626 } | |
| 1627 | |
| 1682 ZoneList<const AstRawString*>* Parser::DeclareLabel( | 1628 ZoneList<const AstRawString*>* Parser::DeclareLabel( |
| 1683 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) { | 1629 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) { |
| 1684 const AstRawString* label = var->raw_name(); | 1630 const AstRawString* label = var->raw_name(); |
| 1685 // TODO(1240780): We don't check for redeclaration of labels | 1631 // TODO(1240780): We don't check for redeclaration of labels |
| 1686 // during preparsing since keeping track of the set of active | 1632 // during preparsing since keeping track of the set of active |
| 1687 // labels requires nontrivial changes to the way scopes are | 1633 // labels requires nontrivial changes to the way scopes are |
| 1688 // structured. However, these are probably changes we want to | 1634 // structured. However, these are probably changes we want to |
| 1689 // make later anyway so we should go back and fix this then. | 1635 // make later anyway so we should go back and fix this then. |
| 1690 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | 1636 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
| 1691 ReportMessage(MessageTemplate::kLabelRedeclaration, label); | 1637 ReportMessage(MessageTemplate::kLabelRedeclaration, label); |
| (...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3612 CallClassFieldInitializer( | 3558 CallClassFieldInitializer( |
| 3613 constructor->scope(), | 3559 constructor->scope(), |
| 3614 constructor->scope()->NewUnresolved( | 3560 constructor->scope()->NewUnresolved( |
| 3615 factory(), ast_value_factory()->this_string(), kNoSourcePosition, | 3561 factory(), ast_value_factory()->this_string(), kNoSourcePosition, |
| 3616 kNoSourcePosition + 4, THIS_VARIABLE)), | 3562 kNoSourcePosition + 4, THIS_VARIABLE)), |
| 3617 kNoSourcePosition); | 3563 kNoSourcePosition); |
| 3618 constructor->body()->InsertAt(0, call_initializer, zone()); | 3564 constructor->body()->InsertAt(0, call_initializer, zone()); |
| 3619 return constructor; | 3565 return constructor; |
| 3620 } | 3566 } |
| 3621 | 3567 |
| 3622 Expression* Parser::ParseClassLiteral(const AstRawString* name, | 3568 // If a class name is specified, this method declares the class variable |
| 3623 Scanner::Location class_name_location, | 3569 // and sets class_info->proxy to point to that name. |
| 3624 bool name_is_strict_reserved, int pos, | 3570 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, |
| 3625 bool* ok) { | 3571 ClassInfo* class_info, int class_token_pos, |
| 3626 // All parts of a ClassDeclaration and ClassExpression are strict code. | 3572 bool* ok) { |
| 3627 if (name_is_strict_reserved) { | |
| 3628 ReportMessageAt(class_name_location, | |
| 3629 MessageTemplate::kUnexpectedStrictReserved); | |
| 3630 *ok = false; | |
| 3631 return nullptr; | |
| 3632 } | |
| 3633 if (IsEvalOrArguments(name)) { | |
| 3634 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); | |
| 3635 *ok = false; | |
| 3636 return nullptr; | |
| 3637 } | |
| 3638 | |
| 3639 BlockState block_state(&scope_state_); | |
| 3640 RaiseLanguageMode(STRICT); | |
| 3641 #ifdef DEBUG | 3573 #ifdef DEBUG |
| 3642 scope()->SetScopeName(name); | 3574 scope()->SetScopeName(name); |
| 3643 #endif | 3575 #endif |
| 3644 | 3576 |
| 3645 VariableProxy* proxy = nullptr; | |
| 3646 if (name != nullptr) { | 3577 if (name != nullptr) { |
| 3647 proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); | 3578 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
| 3648 // TODO(verwaest): declare via block_state. | 3579 // TODO(verwaest): declare via block_state. |
| 3649 Declaration* declaration = | 3580 Declaration* declaration = factory()->NewVariableDeclaration( |
| 3650 factory()->NewVariableDeclaration(proxy, block_state.scope(), pos); | 3581 class_info->proxy, block_scope, class_token_pos); |
| 3651 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, | 3582 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, |
| 3652 Variable::DefaultInitializationFlag(CONST), CHECK_OK); | 3583 Variable::DefaultInitializationFlag(CONST), ok); |
| 3584 } | |
| 3585 } | |
| 3586 | |
| 3587 // This method declares a property of the given class. It updates the | |
| 3588 // following fields of class_info, as appropriate: | |
| 3589 // - constructor | |
| 3590 // - static_initializer_var | |
| 3591 // - instance_field_initializers | |
| 3592 // - properties | |
| 3593 void Parser::DeclareClassProperty(const AstRawString* class_name, | |
| 3594 ClassLiteralProperty* property, | |
| 3595 ClassInfo* class_info, bool* ok) { | |
| 3596 if (class_info->has_seen_constructor && class_info->constructor == nullptr) { | |
| 3597 class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral(); | |
| 3598 DCHECK_NOT_NULL(class_info->constructor); | |
| 3599 class_info->constructor->set_raw_name( | |
| 3600 class_name != nullptr ? class_name | |
| 3601 : ast_value_factory()->empty_string()); | |
| 3602 return; | |
| 3653 } | 3603 } |
| 3654 | 3604 |
| 3655 Expression* extends = nullptr; | 3605 if (property->kind() == ClassLiteralProperty::FIELD) { |
| 3656 if (Check(Token::EXTENDS)) { | 3606 DCHECK(allow_harmony_class_fields()); |
| 3657 block_state.set_start_position(scanner()->location().end_pos); | 3607 if (property->is_static()) { |
| 3658 ExpressionClassifier extends_classifier(this); | 3608 if (class_info->static_initializer_var == nullptr) { |
| 3659 extends = ParseLeftHandSideExpression(CHECK_OK); | 3609 class_info->static_initializer_var = |
| 3660 CheckNoTailCallExpressions(CHECK_OK); | 3610 NewTemporary(ast_value_factory()->empty_string()); |
| 3661 RewriteNonPattern(CHECK_OK); | 3611 } |
| 3662 impl()->AccumulateFormalParameterContainmentErrors(); | 3612 // TODO(bakkot) only do this conditionally |
| 3663 } else { | 3613 Expression* function = InstallHomeObject( |
| 3664 block_state.set_start_position(scanner()->location().end_pos); | 3614 property->value(), |
| 3615 factory()->NewVariableProxy(class_info->static_initializer_var)); | |
| 3616 ZoneList<Expression*>* args = | |
| 3617 new (zone()) ZoneList<Expression*>(2, zone()); | |
| 3618 args->Add(function, zone()); | |
| 3619 args->Add(factory()->NewVariableProxy(class_info->static_initializer_var), | |
| 3620 zone()); | |
| 3621 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, | |
| 3622 kNoSourcePosition); | |
| 3623 property->set_value(call); | |
| 3624 } else { | |
| 3625 // if (is_computed_name) { // TODO(bakkot) figure out why this is | |
| 3626 // necessary for non-computed names in full-codegen | |
| 3627 ZoneList<Expression*>* to_name_args = | |
| 3628 new (zone()) ZoneList<Expression*>(1, zone()); | |
| 3629 to_name_args->Add(property->key(), zone()); | |
| 3630 property->set_key(factory()->NewCallRuntime( | |
| 3631 Runtime::kToName, to_name_args, kNoSourcePosition)); | |
| 3632 //} | |
| 3633 const AstRawString* name = ClassFieldVariableName( | |
| 3634 true, ast_value_factory(), | |
| 3635 class_info->instance_field_initializers->length()); | |
| 3636 VariableProxy* name_proxy = | |
| 3637 factory()->NewVariableProxy(name, NORMAL_VARIABLE); | |
| 3638 Declaration* name_declaration = factory()->NewVariableDeclaration( | |
| 3639 name_proxy, scope(), kNoSourcePosition); | |
| 3640 Variable* name_var = | |
| 3641 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, | |
| 3642 kNeedsInitialization, ok, scope()); | |
| 3643 DCHECK(*ok); | |
| 3644 if (!*ok) return; | |
| 3645 class_info->instance_field_initializers->Add(property->value(), zone()); | |
| 3646 property->set_value(factory()->NewVariableProxy(name_var)); | |
| 3647 } | |
| 3665 } | 3648 } |
| 3649 class_info->properties->Add(property, zone()); | |
| 3650 } | |
| 3666 | 3651 |
| 3667 | 3652 // This method rewrites a class literal into a do-expression. |
| 3668 ClassLiteralChecker checker(this); | 3653 // It uses the following fields of class_info: |
| 3669 ZoneList<ClassLiteral::Property*>* properties = NewClassPropertyList(4); | 3654 // - constructor (if missing, it updates it with a default constructor) |
| 3670 ZoneList<Expression*>* instance_field_initializers = | 3655 // - proxy |
| 3671 new (zone()) ZoneList<Expression*>(0, zone()); | 3656 // - extends |
| 3672 FunctionLiteral* constructor = nullptr; | 3657 // - static_initializer_var |
| 3673 bool has_seen_constructor = false; | 3658 // - instance_field_initializers |
| 3674 Variable* static_initializer_var = nullptr; | 3659 // - properties |
| 3675 | 3660 Expression* Parser::RewriteClassLiteral(const AstRawString* name, |
| 3661 ClassInfo* class_info, int pos, | |
| 3662 bool* ok) { | |
| 3663 int end_pos = scanner()->location().end_pos; | |
| 3676 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); | 3664 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos); |
| 3677 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); | 3665 Variable* result_var = NewTemporary(ast_value_factory()->empty_string()); |
| 3678 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); | 3666 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos); |
| 3679 | 3667 |
| 3680 Expect(Token::LBRACE, CHECK_OK); | 3668 bool has_extends = class_info->extends != nullptr; |
| 3681 | 3669 bool has_instance_fields = |
| 3682 const bool has_extends = extends != nullptr; | 3670 class_info->instance_field_initializers->length() > 0; |
| 3683 while (peek() != Token::RBRACE) { | 3671 DCHECK(!has_instance_fields || allow_harmony_class_fields()); |
| 3684 if (Check(Token::SEMICOLON)) continue; | 3672 bool has_default_constructor = class_info->constructor == nullptr; |
| 3685 FuncNameInferrer::State fni_state(fni_); | 3673 if (has_default_constructor) { |
| 3686 bool is_computed_name = false; // Classes do not care about computed | 3674 class_info->constructor = |
| 3687 // property names here. | 3675 DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos, |
| 3688 ExpressionClassifier property_classifier(this); | 3676 scope()->language_mode()); |
| 3689 ClassLiteral::Property* property = | |
| 3690 ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name, | |
| 3691 &has_seen_constructor, CHECK_OK); | |
| 3692 RewriteNonPattern(CHECK_OK); | |
| 3693 impl()->AccumulateFormalParameterContainmentErrors(); | |
| 3694 | |
| 3695 if (has_seen_constructor && constructor == nullptr) { | |
| 3696 constructor = GetPropertyValue(property)->AsFunctionLiteral(); | |
| 3697 DCHECK_NOT_NULL(constructor); | |
| 3698 constructor->set_raw_name( | |
| 3699 name != nullptr ? name : ast_value_factory()->empty_string()); | |
| 3700 } else { | |
| 3701 if (property->kind() == ClassLiteralProperty::FIELD) { | |
| 3702 DCHECK(allow_harmony_class_fields()); | |
| 3703 if (property->is_static()) { | |
| 3704 if (static_initializer_var == nullptr) { | |
| 3705 static_initializer_var = | |
| 3706 NewTemporary(ast_value_factory()->empty_string()); | |
| 3707 } | |
| 3708 // TODO(bakkot) only do this conditionally | |
| 3709 Expression* function = InstallHomeObject( | |
| 3710 property->value(), | |
| 3711 factory()->NewVariableProxy(static_initializer_var)); | |
| 3712 ZoneList<Expression*>* args = | |
| 3713 new (zone()) ZoneList<Expression*>(2, zone()); | |
| 3714 args->Add(function, zone()); | |
| 3715 args->Add(factory()->NewVariableProxy(static_initializer_var), | |
| 3716 zone()); | |
| 3717 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, | |
| 3718 args, kNoSourcePosition); | |
| 3719 property->set_value(call); | |
| 3720 } else { | |
| 3721 // if (is_computed_name) { // TODO(bakkot) figure out why this is | |
| 3722 // necessary for non-computed names in full-codegen | |
| 3723 ZoneList<Expression*>* to_name_args = | |
| 3724 new (zone()) ZoneList<Expression*>(1, zone()); | |
| 3725 to_name_args->Add(property->key(), zone()); | |
| 3726 property->set_key(factory()->NewCallRuntime( | |
| 3727 Runtime::kToName, to_name_args, kNoSourcePosition)); | |
| 3728 //} | |
| 3729 const AstRawString* name = ClassFieldVariableName( | |
| 3730 true, ast_value_factory(), instance_field_initializers->length()); | |
| 3731 VariableProxy* name_proxy = | |
| 3732 factory()->NewVariableProxy(name, NORMAL_VARIABLE); | |
| 3733 Declaration* name_declaration = factory()->NewVariableDeclaration( | |
| 3734 name_proxy, scope(), kNoSourcePosition); | |
| 3735 Variable* name_var = | |
| 3736 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST, | |
| 3737 kNeedsInitialization, ok, scope()); | |
| 3738 DCHECK(ok); | |
| 3739 if (!ok) return nullptr; | |
| 3740 instance_field_initializers->Add(property->value(), zone()); | |
| 3741 property->set_value(factory()->NewVariableProxy(name_var)); | |
| 3742 } | |
| 3743 } | |
| 3744 properties->Add(property, zone()); | |
| 3745 } | |
| 3746 | |
| 3747 DCHECK_NOT_NULL(fni_); | |
| 3748 fni_->Infer(); | |
| 3749 } | 3677 } |
| 3750 | 3678 |
| 3751 Expect(Token::RBRACE, CHECK_OK); | 3679 if (has_instance_fields && !has_extends) { |
| 3752 int end_pos = scanner()->location().end_pos; | 3680 class_info->constructor = |
| 3753 | 3681 InsertClassFieldInitializer(class_info->constructor); |
| 3754 bool has_instance_fields = instance_field_initializers->length() > 0; | 3682 class_info->constructor->set_requires_class_field_init(true); |
| 3755 DCHECK(!has_instance_fields || allow_harmony_class_fields()); | |
| 3756 bool has_default_constructor = constructor == nullptr; | |
| 3757 if (has_default_constructor) { | |
| 3758 constructor = DefaultConstructor(name, has_extends, has_instance_fields, | |
| 3759 pos, end_pos, block_state.language_mode()); | |
| 3760 } | |
| 3761 | |
| 3762 if (has_instance_fields && extends == nullptr) { | |
| 3763 constructor = InsertClassFieldInitializer(constructor); | |
| 3764 constructor->set_requires_class_field_init(true); | |
| 3765 } // The derived case is handled by rewriting super calls. | 3683 } // The derived case is handled by rewriting super calls. |
| 3766 | 3684 |
| 3767 block_state.set_end_position(end_pos); | 3685 scope()->set_end_position(end_pos); |
| 3768 | 3686 |
| 3769 if (name != nullptr) { | 3687 if (name != nullptr) { |
| 3770 DCHECK_NOT_NULL(proxy); | 3688 DCHECK_NOT_NULL(class_info->proxy); |
| 3771 proxy->var()->set_initializer_position(end_pos); | 3689 class_info->proxy->var()->set_initializer_position(end_pos); |
| 3772 } | 3690 } |
| 3773 | 3691 |
| 3774 ClassLiteral* class_literal = factory()->NewClassLiteral( | 3692 ClassLiteral* class_literal = factory()->NewClassLiteral( |
| 3775 proxy, extends, constructor, properties, pos, end_pos); | 3693 class_info->proxy, class_info->extends, class_info->constructor, |
| 3694 class_info->properties, pos, end_pos); | |
| 3776 | 3695 |
| 3777 if (static_initializer_var != nullptr) { | 3696 if (class_info->static_initializer_var != nullptr) { |
| 3778 class_literal->set_static_initializer_proxy( | 3697 class_literal->set_static_initializer_proxy( |
| 3779 factory()->NewVariableProxy(static_initializer_var)); | 3698 factory()->NewVariableProxy(class_info->static_initializer_var)); |
| 3780 } | 3699 } |
| 3781 | 3700 |
| 3782 do_block->statements()->Add( | 3701 do_block->statements()->Add( |
| 3783 factory()->NewExpressionStatement( | 3702 factory()->NewExpressionStatement( |
| 3784 factory()->NewAssignment(Token::ASSIGN, | 3703 factory()->NewAssignment(Token::ASSIGN, |
| 3785 factory()->NewVariableProxy(result_var), | 3704 factory()->NewVariableProxy(result_var), |
| 3786 class_literal, kNoSourcePosition), | 3705 class_literal, kNoSourcePosition), |
| 3787 pos), | 3706 pos), |
| 3788 zone()); | 3707 zone()); |
| 3789 if (allow_harmony_class_fields() && | 3708 if (allow_harmony_class_fields() && |
| 3790 (has_instance_fields || | 3709 (has_instance_fields || (has_extends && !has_default_constructor))) { |
| 3791 (extends != nullptr && !has_default_constructor))) { | |
| 3792 // Default constructors for derived classes without fields will not try to | 3710 // Default constructors for derived classes without fields will not try to |
| 3793 // read this variable, so there's no need to create it. | 3711 // read this variable, so there's no need to create it. |
| 3794 const AstRawString* init_fn_name = | 3712 const AstRawString* init_fn_name = |
| 3795 ast_value_factory()->dot_class_field_init_string(); | 3713 ast_value_factory()->dot_class_field_init_string(); |
| 3796 Variable* init_fn_var = scope()->DeclareLocal( | 3714 Variable* init_fn_var = scope()->DeclareLocal( |
| 3797 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); | 3715 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE); |
| 3798 Expression* initializer = | 3716 Expression* initializer = |
| 3799 has_instance_fields | 3717 has_instance_fields |
| 3800 ? static_cast<Expression*>(SynthesizeClassFieldInitializer( | 3718 ? static_cast<Expression*>(SynthesizeClassFieldInitializer( |
| 3801 instance_field_initializers->length())) | 3719 class_info->instance_field_initializers->length())) |
| 3802 : factory()->NewBooleanLiteral(false, kNoSourcePosition); | 3720 : factory()->NewBooleanLiteral(false, kNoSourcePosition); |
| 3803 Assignment* assignment = factory()->NewAssignment( | 3721 Assignment* assignment = factory()->NewAssignment( |
| 3804 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer, | 3722 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer, |
| 3805 kNoSourcePosition); | 3723 kNoSourcePosition); |
| 3806 do_block->statements()->Add( | 3724 do_block->statements()->Add( |
| 3807 factory()->NewExpressionStatement(assignment, kNoSourcePosition), | 3725 factory()->NewExpressionStatement(assignment, kNoSourcePosition), |
| 3808 zone()); | 3726 zone()); |
| 3809 } | 3727 } |
| 3810 for (int i = 0; i < instance_field_initializers->length(); ++i) { | 3728 for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) { |
| 3811 const AstRawString* function_name = | 3729 const AstRawString* function_name = |
| 3812 ClassFieldVariableName(false, ast_value_factory(), i); | 3730 ClassFieldVariableName(false, ast_value_factory(), i); |
| 3813 VariableProxy* function_proxy = | 3731 VariableProxy* function_proxy = |
| 3814 factory()->NewVariableProxy(function_name, NORMAL_VARIABLE); | 3732 factory()->NewVariableProxy(function_name, NORMAL_VARIABLE); |
| 3815 Declaration* function_declaration = factory()->NewVariableDeclaration( | 3733 Declaration* function_declaration = factory()->NewVariableDeclaration( |
| 3816 function_proxy, scope(), kNoSourcePosition); | 3734 function_proxy, scope(), kNoSourcePosition); |
| 3817 Variable* function_var = | 3735 Variable* function_var = |
| 3818 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST, | 3736 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST, |
| 3819 kNeedsInitialization, ok, scope()); | 3737 kNeedsInitialization, ok, scope()); |
| 3820 DCHECK(ok); | 3738 if (!*ok) return nullptr; |
| 3821 if (!ok) return nullptr; | |
| 3822 Property* prototype_property = factory()->NewProperty( | 3739 Property* prototype_property = factory()->NewProperty( |
| 3823 factory()->NewVariableProxy(result_var), | 3740 factory()->NewVariableProxy(result_var), |
| 3824 factory()->NewStringLiteral(ast_value_factory()->prototype_string(), | 3741 factory()->NewStringLiteral(ast_value_factory()->prototype_string(), |
| 3825 kNoSourcePosition), | 3742 kNoSourcePosition), |
| 3826 kNoSourcePosition); | 3743 kNoSourcePosition); |
| 3827 Expression* function_value = InstallHomeObject( | 3744 Expression* function_value = InstallHomeObject( |
| 3828 instance_field_initializers->at(i), | 3745 class_info->instance_field_initializers->at(i), |
| 3829 prototype_property); // TODO(bakkot) ideally this would be conditional, | 3746 prototype_property); // TODO(bakkot) ideally this would be conditional, |
| 3830 // especially in trivial cases | 3747 // especially in trivial cases |
| 3831 Assignment* function_assignment = factory()->NewAssignment( | 3748 Assignment* function_assignment = factory()->NewAssignment( |
| 3832 Token::INIT, factory()->NewVariableProxy(function_var), function_value, | 3749 Token::INIT, factory()->NewVariableProxy(function_var), function_value, |
| 3833 kNoSourcePosition); | 3750 kNoSourcePosition); |
| 3834 do_block->statements()->Add(factory()->NewExpressionStatement( | 3751 do_block->statements()->Add(factory()->NewExpressionStatement( |
| 3835 function_assignment, kNoSourcePosition), | 3752 function_assignment, kNoSourcePosition), |
| 3836 zone()); | 3753 zone()); |
| 3837 } | 3754 } |
| 3838 do_block->set_scope(block_state.FinalizedBlockScope()); | 3755 do_block->set_scope(scope()->FinalizeBlockScope()); |
| 3839 do_expr->set_represented_function(constructor); | 3756 do_expr->set_represented_function(class_info->constructor); |
| 3840 | 3757 |
| 3841 return do_expr; | 3758 return do_expr; |
| 3842 } | 3759 } |
| 3843 | 3760 |
| 3844 | |
| 3845 Literal* Parser::GetLiteralUndefined(int position) { | 3761 Literal* Parser::GetLiteralUndefined(int position) { |
| 3846 return factory()->NewUndefinedLiteral(position); | 3762 return factory()->NewUndefinedLiteral(position); |
| 3847 } | 3763 } |
| 3848 | 3764 |
| 3849 | 3765 |
| 3850 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | 3766 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
| 3851 Declaration* decl = scope->CheckConflictingVarDeclarations(); | 3767 Declaration* decl = scope->CheckConflictingVarDeclarations(); |
| 3852 if (decl != NULL) { | 3768 if (decl != NULL) { |
| 3853 // In ES6, conflicting variable bindings are early errors. | 3769 // In ES6, conflicting variable bindings are early errors. |
| 3854 const AstRawString* name = decl->proxy()->raw_name(); | 3770 const AstRawString* name = decl->proxy()->raw_name(); |
| (...skipping 1751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5606 | 5522 |
| 5607 return final_loop; | 5523 return final_loop; |
| 5608 } | 5524 } |
| 5609 | 5525 |
| 5610 #undef CHECK_OK | 5526 #undef CHECK_OK |
| 5611 #undef CHECK_OK_VOID | 5527 #undef CHECK_OK_VOID |
| 5612 #undef CHECK_FAILED | 5528 #undef CHECK_FAILED |
| 5613 | 5529 |
| 5614 } // namespace internal | 5530 } // namespace internal |
| 5615 } // namespace v8 | 5531 } // namespace v8 |
| OLD | NEW |