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

Side by Side Diff: src/parser.cc

Issue 883823002: Implement proper scoping for "this" in arrow functions Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased against master, plus fixes. Only 4 tests failing (+2 in TurboFan) Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ast-graph-builder.cc ('k') | src/scopeinfo.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 } 666 }
667 667
668 668
669 const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) { 669 const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
670 return parser_->scanner()->NextSymbol(parser_->ast_value_factory()); 670 return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
671 } 671 }
672 672
673 673
674 Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory, 674 Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
675 int pos) { 675 int pos) {
676 return factory->NewVariableProxy(scope->receiver(), pos); 676 return scope->NewUnresolved(factory,
677 parser_->ast_value_factory()->this_string(),
678 Variable::THIS, pos);
677 } 679 }
678 680
679 Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory, 681 Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory,
680 int pos) { 682 int pos) {
681 return factory->NewSuperReference( 683 return factory->NewSuperReference(
682 ThisExpression(scope, factory, pos)->AsVariableProxy(), 684 ThisExpression(scope, factory, pos)->AsVariableProxy(),
683 pos); 685 pos);
684 } 686 }
685 687
686 688
(...skipping 27 matching lines...) Expand all
714 Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name, 716 Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
715 int pos, Scope* scope, 717 int pos, Scope* scope,
716 AstNodeFactory* factory) { 718 AstNodeFactory* factory) {
717 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name); 719 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
718 720
719 // Arrow function parameters are parsed as an expression. When 721 // Arrow function parameters are parsed as an expression. When
720 // parsing lazily, it is enough to create a VariableProxy in order 722 // parsing lazily, it is enough to create a VariableProxy in order
721 // for Traits::DeclareArrowParametersFromExpression() to be able to 723 // for Traits::DeclareArrowParametersFromExpression() to be able to
722 // pick the names of the parameters. 724 // pick the names of the parameters.
723 return parser_->parsing_lazy_arrow_parameters_ 725 return parser_->parsing_lazy_arrow_parameters_
724 ? factory->NewVariableProxy(name, false, pos) 726 ? factory->NewVariableProxy(name, Variable::NORMAL, pos)
725 : scope->NewUnresolved(factory, name, pos); 727 : scope->NewUnresolved(factory, name, Variable::NORMAL, pos);
726 } 728 }
727 729
728 730
729 Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner, 731 Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
730 AstNodeFactory* factory) { 732 AstNodeFactory* factory) {
731 const AstRawString* symbol = GetSymbol(scanner); 733 const AstRawString* symbol = GetSymbol(scanner);
732 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol); 734 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
733 return factory->NewStringLiteral(symbol, pos); 735 return factory->NewStringLiteral(symbol, pos);
734 } 736 }
735 737
(...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 } 1787 }
1786 1788
1787 1789
1788 VariableProxy* Parser::NewUnresolved(const AstRawString* name, 1790 VariableProxy* Parser::NewUnresolved(const AstRawString* name,
1789 VariableMode mode) { 1791 VariableMode mode) {
1790 // If we are inside a function, a declaration of a var/const variable is a 1792 // If we are inside a function, a declaration of a var/const variable is a
1791 // truly local variable, and the scope of the variable is always the function 1793 // truly local variable, and the scope of the variable is always the function
1792 // scope. 1794 // scope.
1793 // Let/const variables in harmony mode are always added to the immediately 1795 // Let/const variables in harmony mode are always added to the immediately
1794 // enclosing scope. 1796 // enclosing scope.
1795 return DeclarationScope(mode)->NewUnresolved(factory(), name, position()); 1797 return DeclarationScope(mode)
1798 ->NewUnresolved(factory(), name, Variable::NORMAL, position());
1796 } 1799 }
1797 1800
1798 1801
1799 void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { 1802 void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
1800 VariableProxy* proxy = declaration->proxy(); 1803 VariableProxy* proxy = declaration->proxy();
1801 DCHECK(proxy->raw_name() != NULL); 1804 DCHECK(proxy->raw_name() != NULL);
1802 const AstRawString* name = proxy->raw_name(); 1805 const AstRawString* name = proxy->raw_name();
1803 VariableMode mode = declaration->mode(); 1806 VariableMode mode = declaration->mode();
1804 Scope* declaration_scope = DeclarationScope(mode); 1807 Scope* declaration_scope = DeclarationScope(mode);
1805 Variable* var = NULL; 1808 Variable* var = NULL;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1870 // same variable if it is declared several times. This is not a 1873 // same variable if it is declared several times. This is not a
1871 // semantic issue as long as we keep the source order, but it may be 1874 // semantic issue as long as we keep the source order, but it may be
1872 // a performance issue since it may lead to repeated 1875 // a performance issue since it may lead to repeated
1873 // RuntimeHidden_DeclareLookupSlot calls. 1876 // RuntimeHidden_DeclareLookupSlot calls.
1874 declaration_scope->AddDeclaration(declaration); 1877 declaration_scope->AddDeclaration(declaration);
1875 1878
1876 if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) { 1879 if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) {
1877 // For global const variables we bind the proxy to a variable. 1880 // For global const variables we bind the proxy to a variable.
1878 DCHECK(resolve); // should be set by all callers 1881 DCHECK(resolve); // should be set by all callers
1879 Variable::Kind kind = Variable::NORMAL; 1882 Variable::Kind kind = Variable::NORMAL;
1880 var = new (zone()) Variable(declaration_scope, name, mode, true, kind, 1883 var = new (zone()) Variable(declaration_scope, name, mode, kind,
1881 kNeedsInitialization, kNotAssigned); 1884 kNeedsInitialization, kNotAssigned);
1882 } else if (declaration_scope->is_eval_scope() && 1885 } else if (declaration_scope->is_eval_scope() &&
1883 is_sloppy(declaration_scope->language_mode())) { 1886 is_sloppy(declaration_scope->language_mode())) {
1884 // For variable declarations in a sloppy eval scope the proxy is bound 1887 // For variable declarations in a sloppy eval scope the proxy is bound
1885 // to a lookup variable to force a dynamic declaration using the 1888 // to a lookup variable to force a dynamic declaration using the
1886 // DeclareLookupSlot runtime function. 1889 // DeclareLookupSlot runtime function.
1887 Variable::Kind kind = Variable::NORMAL; 1890 Variable::Kind kind = Variable::NORMAL;
1888 // TODO(sigurds) figure out if kNotAssigned is OK here 1891 // TODO(sigurds) figure out if kNotAssigned is OK here
1889 var = new (zone()) Variable(declaration_scope, name, mode, true, kind, 1892 var = new (zone()) Variable(declaration_scope, name, mode, kind,
1890 declaration->initialization(), kNotAssigned); 1893 declaration->initialization(), kNotAssigned);
1891 var->AllocateTo(Variable::LOOKUP, -1); 1894 var->AllocateTo(Variable::LOOKUP, -1);
1892 resolve = true; 1895 resolve = true;
1893 } 1896 }
1894 1897
1895 // If requested and we have a local variable, bind the proxy to the variable 1898 // If requested and we have a local variable, bind the proxy to the variable
1896 // at parse-time. This is used for functions (and consts) declared inside 1899 // at parse-time. This is used for functions (and consts) declared inside
1897 // statements: the corresponding function (or const) variable must be in the 1900 // statements: the corresponding function (or const) variable must be in the
1898 // function scope and not a statement-local scope, e.g. as provided with a 1901 // function scope and not a statement-local scope, e.g. as provided with a
1899 // 'with' statement: 1902 // 'with' statement:
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 value = NULL; 2404 value = NULL;
2402 } 2405 }
2403 2406
2404 // Add an assignment node to the initialization statement block if we still 2407 // Add an assignment node to the initialization statement block if we still
2405 // have a pending initialization value. 2408 // have a pending initialization value.
2406 if (value != NULL) { 2409 if (value != NULL) {
2407 DCHECK(mode == VAR); 2410 DCHECK(mode == VAR);
2408 // 'var' initializations are simply assignments (with all the consequences 2411 // 'var' initializations are simply assignments (with all the consequences
2409 // if they are inside a 'with' statement - they may change a 'with' object 2412 // if they are inside a 'with' statement - they may change a 'with' object
2410 // property). 2413 // property).
2411 VariableProxy* proxy = 2414 VariableProxy* proxy = initialization_scope->NewUnresolved(
2412 initialization_scope->NewUnresolved(factory(), name); 2415 factory(), name, Variable::NORMAL);
2413 Assignment* assignment = 2416 Assignment* assignment =
2414 factory()->NewAssignment(init_op, proxy, value, pos); 2417 factory()->NewAssignment(init_op, proxy, value, pos);
2415 block->AddStatement( 2418 block->AddStatement(
2416 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), 2419 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2417 zone()); 2420 zone());
2418 } 2421 }
2419 2422
2420 if (fni_ != NULL) fni_->Leave(); 2423 if (fni_ != NULL) fni_->Leave();
2421 } while (peek() == Token::COMMA); 2424 } while (peek() == Token::COMMA);
2422 2425
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
3264 3267
3265 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) { 3268 if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) {
3266 if (!*ok) return nullptr; 3269 if (!*ok) return nullptr;
3267 ForEachStatement* loop = 3270 ForEachStatement* loop =
3268 factory()->NewForEachStatement(mode, labels, stmt_pos); 3271 factory()->NewForEachStatement(mode, labels, stmt_pos);
3269 Target target(&this->target_stack_, loop); 3272 Target target(&this->target_stack_, loop);
3270 3273
3271 Expression* enumerable = ParseExpression(true, CHECK_OK); 3274 Expression* enumerable = ParseExpression(true, CHECK_OK);
3272 Expect(Token::RPAREN, CHECK_OK); 3275 Expect(Token::RPAREN, CHECK_OK);
3273 3276
3274 VariableProxy* each = scope_->NewUnresolved(factory(), name, each_pos); 3277 VariableProxy* each =
3278 scope_->NewUnresolved(factory(), name, Variable::NORMAL, each_pos);
3275 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3279 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3276 InitializeForEachStatement(loop, each, enumerable, body); 3280 InitializeForEachStatement(loop, each, enumerable, body);
3277 Block* result = 3281 Block* result =
3278 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3282 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3279 result->AddStatement(variable_statement, zone()); 3283 result->AddStatement(variable_statement, zone());
3280 result->AddStatement(loop, zone()); 3284 result->AddStatement(loop, zone());
3281 scope_ = saved_scope; 3285 scope_ = saved_scope;
3282 for_scope->set_end_position(scanner()->location().end_pos); 3286 for_scope->set_end_position(scanner()->location().end_pos);
3283 for_scope = for_scope->FinalizeBlockScope(); 3287 for_scope = for_scope->FinalizeBlockScope();
3284 DCHECK(for_scope == NULL); 3288 DCHECK(for_scope == NULL);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3324 ForEachStatement* loop = 3328 ForEachStatement* loop =
3325 factory()->NewForEachStatement(mode, labels, stmt_pos); 3329 factory()->NewForEachStatement(mode, labels, stmt_pos);
3326 Target target(&this->target_stack_, loop); 3330 Target target(&this->target_stack_, loop);
3327 3331
3328 // The expression does not see the loop variable. 3332 // The expression does not see the loop variable.
3329 scope_ = saved_scope; 3333 scope_ = saved_scope;
3330 Expression* enumerable = ParseExpression(true, CHECK_OK); 3334 Expression* enumerable = ParseExpression(true, CHECK_OK);
3331 scope_ = for_scope; 3335 scope_ = for_scope;
3332 Expect(Token::RPAREN, CHECK_OK); 3336 Expect(Token::RPAREN, CHECK_OK);
3333 3337
3334 VariableProxy* each = scope_->NewUnresolved(factory(), name, each_pos); 3338 VariableProxy* each =
3339 scope_->NewUnresolved(factory(), name, Variable::NORMAL, each_pos);
3335 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3340 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3336 Block* body_block = 3341 Block* body_block =
3337 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); 3342 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3338 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; 3343 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
3339 Assignment* assignment = factory()->NewAssignment( 3344 Assignment* assignment = factory()->NewAssignment(
3340 init_op, each, temp_proxy, RelocInfo::kNoPosition); 3345 init_op, each, temp_proxy, RelocInfo::kNoPosition);
3341 Statement* assignment_statement = factory()->NewExpressionStatement( 3346 Statement* assignment_statement = factory()->NewExpressionStatement(
3342 assignment, RelocInfo::kNoPosition); 3347 assignment, RelocInfo::kNoPosition);
3343 body_block->AddStatement(variable_statement, zone()); 3348 body_block->AddStatement(variable_statement, zone());
3344 body_block->AddStatement(assignment_statement, zone()); 3349 body_block->AddStatement(assignment_statement, zone());
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
3765 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; 3770 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
3766 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { 3771 if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
3767 if (allow_harmony_scoping() && is_strict(language_mode())) { 3772 if (allow_harmony_scoping() && is_strict(language_mode())) {
3768 fvar_init_op = Token::INIT_CONST; 3773 fvar_init_op = Token::INIT_CONST;
3769 } 3774 }
3770 VariableMode fvar_mode = 3775 VariableMode fvar_mode =
3771 allow_harmony_scoping() && is_strict(language_mode()) ? CONST 3776 allow_harmony_scoping() && is_strict(language_mode()) ? CONST
3772 : CONST_LEGACY; 3777 : CONST_LEGACY;
3773 DCHECK(function_name != NULL); 3778 DCHECK(function_name != NULL);
3774 fvar = new (zone()) 3779 fvar = new (zone())
3775 Variable(scope_, function_name, fvar_mode, true /* is valid LHS */, 3780 Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
3776 Variable::NORMAL, kCreatedInitialized, kNotAssigned); 3781 kCreatedInitialized, kNotAssigned);
3777 VariableProxy* proxy = factory()->NewVariableProxy(fvar); 3782 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
3778 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( 3783 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
3779 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); 3784 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
3780 scope_->DeclareFunctionVar(fvar_declaration); 3785 scope_->DeclareFunctionVar(fvar_declaration);
3781 } 3786 }
3782 3787
3783 // Determine if the function can be parsed lazily. Lazy parsing is different 3788 // Determine if the function can be parsed lazily. Lazy parsing is different
3784 // from lazy compilation; we need to parse more eagerly than we compile. 3789 // from lazy compilation; we need to parse more eagerly than we compile.
3785 3790
3786 // We can only parse lazily if we also compile lazily. The heuristics for 3791 // We can only parse lazily if we also compile lazily. The heuristics for
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
3957 3962
3958 3963
3959 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3964 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3960 const AstRawString* function_name, int pos, Variable* fvar, 3965 const AstRawString* function_name, int pos, Variable* fvar,
3961 Token::Value fvar_init_op, FunctionKind kind, bool* ok) { 3966 Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
3962 // Everything inside an eagerly parsed function will be parsed eagerly 3967 // Everything inside an eagerly parsed function will be parsed eagerly
3963 // (see comment above). 3968 // (see comment above).
3964 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3969 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3965 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone()); 3970 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone());
3966 if (fvar != NULL) { 3971 if (fvar != NULL) {
3967 VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name); 3972 VariableProxy* fproxy =
3973 scope_->NewUnresolved(factory(), function_name, Variable::NORMAL);
3968 fproxy->BindTo(fvar); 3974 fproxy->BindTo(fvar);
3969 body->Add(factory()->NewExpressionStatement( 3975 body->Add(factory()->NewExpressionStatement(
3970 factory()->NewAssignment(fvar_init_op, 3976 factory()->NewAssignment(fvar_init_op,
3971 fproxy, 3977 fproxy,
3972 factory()->NewThisFunction(pos), 3978 factory()->NewThisFunction(pos),
3973 RelocInfo::kNoPosition), 3979 RelocInfo::kNoPosition),
3974 RelocInfo::kNoPosition), zone()); 3980 RelocInfo::kNoPosition), zone());
3975 } 3981 }
3976 3982
3977 3983
(...skipping 1507 matching lines...) Expand 10 before | Expand all | Expand 10 after
5485 } else { 5491 } else {
5486 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); 5492 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5487 running_hash = StringHasher::ComputeRunningHash(running_hash, data, 5493 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5488 raw_string->length()); 5494 raw_string->length());
5489 } 5495 }
5490 } 5496 }
5491 5497
5492 return running_hash; 5498 return running_hash;
5493 } 5499 }
5494 } } // namespace v8::internal 5500 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.cc ('k') | src/scopeinfo.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698