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

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

Issue 2099623003: Annex B.3.3 semantics (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: typos Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | test/mjsunit/es6/block-sloppy-function.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/ast-expression-rewriter.h" 9 #include "src/ast/ast-expression-rewriter.h"
10 #include "src/ast/ast-expression-visitor.h" 10 #include "src/ast/ast-expression-visitor.h"
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 if (ok && is_strict(language_mode())) { 962 if (ok && is_strict(language_mode())) {
963 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); 963 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
964 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, 964 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos,
965 scanner()->location().end_pos); 965 scanner()->location().end_pos);
966 } 966 }
967 if (ok && is_sloppy(language_mode())) { 967 if (ok && is_sloppy(language_mode())) {
968 // TODO(littledan): Function bindings on the global object that modify 968 // TODO(littledan): Function bindings on the global object that modify
969 // pre-existing bindings should be made writable, enumerable and 969 // pre-existing bindings should be made writable, enumerable and
970 // nonconfigurable if possible, whereas this code will leave attributes 970 // nonconfigurable if possible, whereas this code will leave attributes
971 // unchanged if the property already exists. 971 // unchanged if the property already exists.
972 InsertSloppyBlockFunctionVarBindings(scope, &ok); 972 InsertSloppyBlockFunctionVarBindings(scope, nullptr, &ok);
973 } 973 }
974 if (ok) { 974 if (ok) {
975 CheckConflictingVarDeclarations(scope_, &ok); 975 CheckConflictingVarDeclarations(scope_, &ok);
976 } 976 }
977 977
978 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { 978 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
979 if (body->length() != 1 || 979 if (body->length() != 1 ||
980 !body->at(0)->IsExpressionStatement() || 980 !body->at(0)->IsExpressionStatement() ||
981 !body->at(0)->AsExpressionStatement()-> 981 !body->at(0)->AsExpressionStatement()->
982 expression()->IsFunctionLiteral()) { 982 expression()->IsFunctionLiteral()) {
(...skipping 3366 matching lines...) Expand 10 before | Expand all | Expand 10 after
4349 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); 4349 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
4350 ValidateFormalParameters(&formals_classifier, language_mode, 4350 ValidateFormalParameters(&formals_classifier, language_mode,
4351 allow_duplicate_parameters, CHECK_OK); 4351 allow_duplicate_parameters, CHECK_OK);
4352 4352
4353 if (is_strict(language_mode)) { 4353 if (is_strict(language_mode)) {
4354 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), 4354 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
4355 CHECK_OK); 4355 CHECK_OK);
4356 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(), 4356 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(),
4357 scope->end_position()); 4357 scope->end_position());
4358 } 4358 }
4359 if (is_sloppy(language_mode)) {
4360 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
4361 }
4362 CheckConflictingVarDeclarations(scope, CHECK_OK); 4359 CheckConflictingVarDeclarations(scope, CHECK_OK);
4363 4360
4364 if (body) { 4361 if (body) {
4365 // If body can be inspected, rewrite queued destructuring assignments 4362 // If body can be inspected, rewrite queued destructuring assignments
4366 ParserTraits::RewriteDestructuringAssignments(); 4363 ParserTraits::RewriteDestructuringAssignments();
4367 } 4364 }
4368 has_duplicate_parameters = 4365 has_duplicate_parameters =
4369 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); 4366 !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
4370 } 4367 }
4371 4368
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
4800 4797
4801 Expect(Token::RBRACE, CHECK_OK); 4798 Expect(Token::RBRACE, CHECK_OK);
4802 scope_->set_end_position(scanner()->location().end_pos); 4799 scope_->set_end_position(scanner()->location().end_pos);
4803 4800
4804 if (!parameters.is_simple) { 4801 if (!parameters.is_simple) {
4805 DCHECK_NOT_NULL(inner_scope); 4802 DCHECK_NOT_NULL(inner_scope);
4806 DCHECK_EQ(body, inner_block->statements()); 4803 DCHECK_EQ(body, inner_block->statements());
4807 SetLanguageMode(scope_, inner_scope->language_mode()); 4804 SetLanguageMode(scope_, inner_scope->language_mode());
4808 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); 4805 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
4809 4806
4807 if (is_sloppy(inner_scope->language_mode())) {
4808 InsertSloppyBlockFunctionVarBindings(
4809 inner_scope, inner_scope->outer_scope(), CHECK_OK);
4810 }
4811
4810 if (IsAsyncFunction(kind)) { 4812 if (IsAsyncFunction(kind)) {
4811 init_block = BuildRejectPromiseOnException(init_block); 4813 init_block = BuildRejectPromiseOnException(init_block);
4812 } 4814 }
4813 4815
4814 DCHECK_NOT_NULL(init_block); 4816 DCHECK_NOT_NULL(init_block);
4815 4817
4816 inner_scope->set_end_position(scanner()->location().end_pos); 4818 inner_scope->set_end_position(scanner()->location().end_pos);
4817 inner_scope = inner_scope->FinalizeBlockScope(); 4819 inner_scope = inner_scope->FinalizeBlockScope();
4818 if (inner_scope != nullptr) { 4820 if (inner_scope != nullptr) {
4819 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); 4821 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4820 InsertShadowingVarBindingInitializers(inner_block); 4822 InsertShadowingVarBindingInitializers(inner_block);
4821 } 4823 }
4822 4824
4823 result->Add(init_block, zone()); 4825 result->Add(init_block, zone());
4824 result->Add(inner_block, zone()); 4826 result->Add(inner_block, zone());
4827 } else {
4828 if (is_sloppy(inner_scope->language_mode())) {
4829 InsertSloppyBlockFunctionVarBindings(inner_scope, nullptr, CHECK_OK);
4830 }
4825 } 4831 }
4826 4832
4827 if (function_type == FunctionLiteral::kNamedExpression) { 4833 if (function_type == FunctionLiteral::kNamedExpression) {
4828 // Now that we know the language mode, we can create the const assignment 4834 // Now that we know the language mode, we can create the const assignment
4829 // in the previously reserved spot. 4835 // in the previously reserved spot.
4830 // NOTE: We create a proxy and resolve it here so that in the 4836 // NOTE: We create a proxy and resolve it here so that in the
4831 // future we can change the AST to only refer to VariableProxies 4837 // future we can change the AST to only refer to VariableProxies
4832 // instead of Variables and Proxies as is the case now. 4838 // instead of Variables and Proxies as is the case now.
4833 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; 4839 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY;
4834 Variable* fvar = new (zone()) 4840 Variable* fvar = new (zone())
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
5101 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); 5107 VariableProxy* to = inner_scope->NewUnresolved(factory(), name);
5102 VariableProxy* from = factory()->NewVariableProxy(parameter); 5108 VariableProxy* from = factory()->NewVariableProxy(parameter);
5103 Expression* assignment = factory()->NewAssignment( 5109 Expression* assignment = factory()->NewAssignment(
5104 Token::ASSIGN, to, from, RelocInfo::kNoPosition); 5110 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
5105 Statement* statement = factory()->NewExpressionStatement( 5111 Statement* statement = factory()->NewExpressionStatement(
5106 assignment, RelocInfo::kNoPosition); 5112 assignment, RelocInfo::kNoPosition);
5107 inner_block->statements()->InsertAt(0, statement, zone()); 5113 inner_block->statements()->InsertAt(0, statement, zone());
5108 } 5114 }
5109 } 5115 }
5110 5116
5111 5117 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope,
5112 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { 5118 Scope* complex_params_scope,
5119 bool* ok) {
5113 // For each variable which is used as a function declaration in a sloppy 5120 // For each variable which is used as a function declaration in a sloppy
5114 // block, 5121 // block,
5115 DCHECK(scope->is_declaration_scope()); 5122 DCHECK(scope->is_declaration_scope());
5116 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); 5123 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
5117 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { 5124 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
5118 AstRawString* name = static_cast<AstRawString*>(p->key); 5125 AstRawString* name = static_cast<AstRawString*>(p->key);
5119 // If the variable wouldn't conflict with a lexical declaration, 5126
5120 Variable* var = scope->LookupLocal(name); 5127 // If the variable wouldn't conflict with a lexical declaration
5121 if (var == nullptr || !IsLexicalVariableMode(var->mode())) { 5128 // or parameter,
5129
5130 // Check if there's a conflict with a parameter.
5131 // This depends on the fact that functions always have a scope solely to
5132 // hold complex parameters, and the names local to that scope are
5133 // precisely the names of the parameters. IsDeclaredParameter(name) does
5134 // not hold for names declared by complex parameters, nor are those
5135 // bindings necessarily declared lexically, so we have to check for them
5136 // explicitly. On the other hand, if there are not complex parameters,
5137 // it is sufficient to just check IsDeclaredParameter.
5138 if (complex_params_scope != nullptr) {
5139 if (complex_params_scope->LookupLocal(name) != nullptr) {
5140 continue;
5141 }
5142 } else {
5143 if (scope->IsDeclaredParameter(name)) {
5144 continue;
5145 }
5146 }
5147
5148 bool var_created = false;
5149
5150 // Write in assignments to var for each block-scoped function declaration
5151 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value);
5152 for (SloppyBlockFunctionStatement* delegate : *delegates) {
5153 // Check if there's a conflict with a lexical declaration
5154 Scope* outer_scope = scope->outer_scope();
5155 Scope* query_scope = delegate->scope()->outer_scope();
5156 Variable* var = nullptr;
5157 bool should_hoist = true;
5158
5159 // Note that we perform this loop for each delegate named 'name',
5160 // which may duplicate work if those delegates share scopes.
5161 // It is not sufficient to just do a Lookup on query_scope: for
5162 // example, that does not prevent hoisting of the function in
5163 // `{ let e; try {} catch (e) { function e(){} } }`
5164 do {
5165 var = query_scope->LookupLocal(name);
5166 if (var != nullptr && IsLexicalVariableMode(var->mode())) {
5167 should_hoist = false;
5168 break;
5169 }
5170 query_scope = query_scope->outer_scope();
5171 } while (query_scope != outer_scope);
5172
5173 if (!should_hoist) continue;
5174
5122 // Declare a var-style binding for the function in the outer scope 5175 // Declare a var-style binding for the function in the outer scope
5123 VariableProxy* proxy = scope->NewUnresolved(factory(), name); 5176 if (!var_created) {
5124 Declaration* declaration = factory()->NewVariableDeclaration( 5177 var_created = true;
5125 proxy, VAR, scope, RelocInfo::kNoPosition); 5178 VariableProxy* proxy = scope->NewUnresolved(factory(), name);
5126 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); 5179 Declaration* declaration = factory()->NewVariableDeclaration(
5127 DCHECK(ok); // Based on the preceding check, this should not fail 5180 proxy, VAR, scope, RelocInfo::kNoPosition);
5128 if (!ok) return; 5181 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
5182 DCHECK(ok); // Based on the preceding check, this should not fail
5183 if (!ok) return;
5184 }
5129 5185
5130 // Write in assignments to var for each block-scoped function declaration 5186 // Read from the local lexical scope and write to the function scope
5131 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); 5187 VariableProxy* to = scope->NewUnresolved(factory(), name);
5132 for (SloppyBlockFunctionStatement* delegate : *delegates) { 5188 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
5133 // Read from the local lexical scope and write to the function scope 5189 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, to, from,
5134 VariableProxy* to = scope->NewUnresolved(factory(), name); 5190 RelocInfo::kNoPosition);
5135 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); 5191 Statement* statement =
5136 Expression* assignment = factory()->NewAssignment( 5192 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
5137 Token::ASSIGN, to, from, RelocInfo::kNoPosition); 5193 delegate->set_statement(statement);
5138 Statement* statement = factory()->NewExpressionStatement(
5139 assignment, RelocInfo::kNoPosition);
5140 delegate->set_statement(statement);
5141 }
5142 } 5194 }
5143 } 5195 }
5144 } 5196 }
5145 5197
5146 5198
5147 // ---------------------------------------------------------------------------- 5199 // ----------------------------------------------------------------------------
5148 // Parser support 5200 // Parser support
5149 5201
5150 bool Parser::TargetStackContainsLabel(const AstRawString* label) { 5202 bool Parser::TargetStackContainsLabel(const AstRawString* label) {
5151 for (Target* t = target_stack_; t != NULL; t = t->previous()) { 5203 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
(...skipping 1824 matching lines...) Expand 10 before | Expand all | Expand 10 after
6976 try_block, target); 7028 try_block, target);
6977 final_loop = target; 7029 final_loop = target;
6978 } 7030 }
6979 7031
6980 return final_loop; 7032 return final_loop;
6981 } 7033 }
6982 7034
6983 7035
6984 } // namespace internal 7036 } // namespace internal
6985 } // namespace v8 7037 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | test/mjsunit/es6/block-sloppy-function.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698