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 "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 Loading... | |
| 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, false, &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 Loading... | |
| 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 Loading... | |
| 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(inner_scope, true, CHECK_OK); | |
| 4809 } | |
| 4810 | |
| 4810 if (IsAsyncFunction(kind)) { | 4811 if (IsAsyncFunction(kind)) { |
| 4811 init_block = BuildRejectPromiseOnException(init_block); | 4812 init_block = BuildRejectPromiseOnException(init_block); |
| 4812 } | 4813 } |
| 4813 | 4814 |
| 4814 DCHECK_NOT_NULL(init_block); | 4815 DCHECK_NOT_NULL(init_block); |
| 4815 | 4816 |
| 4816 inner_scope->set_end_position(scanner()->location().end_pos); | 4817 inner_scope->set_end_position(scanner()->location().end_pos); |
| 4817 inner_scope = inner_scope->FinalizeBlockScope(); | 4818 inner_scope = inner_scope->FinalizeBlockScope(); |
| 4818 if (inner_scope != nullptr) { | 4819 if (inner_scope != nullptr) { |
| 4819 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4820 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
| 4820 InsertShadowingVarBindingInitializers(inner_block); | 4821 InsertShadowingVarBindingInitializers(inner_block); |
| 4821 } | 4822 } |
| 4822 | 4823 |
| 4823 result->Add(init_block, zone()); | 4824 result->Add(init_block, zone()); |
| 4824 result->Add(inner_block, zone()); | 4825 result->Add(inner_block, zone()); |
| 4826 } else { | |
| 4827 if (is_sloppy(inner_scope->language_mode())) { | |
| 4828 InsertSloppyBlockFunctionVarBindings(inner_scope, false, CHECK_OK); | |
| 4829 } | |
| 4825 } | 4830 } |
| 4826 | 4831 |
| 4827 if (function_type == FunctionLiteral::kNamedExpression) { | 4832 if (function_type == FunctionLiteral::kNamedExpression) { |
| 4828 // Now that we know the language mode, we can create the const assignment | 4833 // Now that we know the language mode, we can create the const assignment |
| 4829 // in the previously reserved spot. | 4834 // in the previously reserved spot. |
| 4830 // NOTE: We create a proxy and resolve it here so that in the | 4835 // 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 | 4836 // future we can change the AST to only refer to VariableProxies |
| 4832 // instead of Variables and Proxies as is the case now. | 4837 // instead of Variables and Proxies as is the case now. |
| 4833 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; | 4838 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; |
| 4834 Variable* fvar = new (zone()) | 4839 Variable* fvar = new (zone()) |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5101 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); | 5106 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); |
| 5102 VariableProxy* from = factory()->NewVariableProxy(parameter); | 5107 VariableProxy* from = factory()->NewVariableProxy(parameter); |
| 5103 Expression* assignment = factory()->NewAssignment( | 5108 Expression* assignment = factory()->NewAssignment( |
| 5104 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | 5109 Token::ASSIGN, to, from, RelocInfo::kNoPosition); |
| 5105 Statement* statement = factory()->NewExpressionStatement( | 5110 Statement* statement = factory()->NewExpressionStatement( |
| 5106 assignment, RelocInfo::kNoPosition); | 5111 assignment, RelocInfo::kNoPosition); |
| 5107 inner_block->statements()->InsertAt(0, statement, zone()); | 5112 inner_block->statements()->InsertAt(0, statement, zone()); |
| 5108 } | 5113 } |
| 5109 } | 5114 } |
| 5110 | 5115 |
| 5111 | 5116 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, |
| 5112 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { | 5117 bool outer_is_param_scope, |
| 5118 bool* ok) { | |
| 5113 // For each variable which is used as a function declaration in a sloppy | 5119 // For each variable which is used as a function declaration in a sloppy |
| 5114 // block, | 5120 // block, |
| 5115 DCHECK(scope->is_declaration_scope()); | 5121 DCHECK(scope->is_declaration_scope()); |
| 5116 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 5122 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); |
| 5117 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | 5123 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { |
| 5118 AstRawString* name = static_cast<AstRawString*>(p->key); | 5124 AstRawString* name = static_cast<AstRawString*>(p->key); |
| 5119 // If the variable wouldn't conflict with a lexical declaration, | 5125 |
| 5120 Variable* var = scope->LookupLocal(name); | 5126 bool var_created = false; |
| 5121 if (var == nullptr || !IsLexicalVariableMode(var->mode())) { | 5127 |
| 5128 // Write in assignments to var for each block-scoped function declaration | |
| 5129 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); | |
| 5130 for (SloppyBlockFunctionStatement* delegate : *delegates) { | |
| 5131 // If the variable wouldn't conflict with a lexical declaration | |
| 5132 // or parameter, | |
| 5133 | |
| 5134 // Check if there's a conflict with a simple parameter | |
| 5135 if (scope->IsDeclaredParameter(name)) continue; | |
| 5136 | |
| 5137 Scope* outer_scope = scope->outer_scope(); | |
| 5138 | |
| 5139 /* Check if there's a conflict with a complex parameter. | |
|
adamk
2016/06/28 20:55:11
Style nit: please use '//' style comments for cons
bakkot
2016/06/29 00:25:02
Done.
| |
| 5140 * This depends on the fact that functions always create a new scope to | |
|
adamk
2016/06/28 20:55:11
This comment seems a bit backwards, and it confuse
bakkot
2016/06/29 00:25:02
Amended the comment slightly, and now we have a co
| |
| 5141 * hold complex parameters, and the names local to that scope are | |
| 5142 * precisely the names of the parameters. IsDeclaredParameter(name) does | |
|
adamk
2016/06/28 20:55:10
Does IsDeclaredParameter ever hold in this case? I
bakkot
2016/06/29 00:25:02
You're correct; refactored that out. (I thought it
| |
| 5143 * not necessarily hold for names declared by complex parameters, nor | |
| 5144 * are those bindings necessarily declared lexically, so we have to | |
| 5145 * check for them explicitly. outer_is_param_scope holds iff we are in a | |
| 5146 * function with complex parameters. | |
| 5147 */ | |
| 5148 if (outer_is_param_scope && outer_scope->LookupLocal(name) != nullptr) { | |
| 5149 continue; | |
| 5150 } | |
| 5151 | |
| 5152 // Check if there's a conflict with a lexical declaration | |
| 5153 Scope* query_scope = delegate->scope()->outer_scope(); | |
|
adamk
2016/06/28 20:55:10
Can't everything above here live outside the deleg
bakkot
2016/06/29 00:25:02
Done.
| |
| 5154 Variable* var = nullptr; | |
| 5155 bool should_hoist = true; | |
| 5156 do { | |
|
adamk
2016/06/28 20:55:10
Even this loop seems like it should be hoistable w
bakkot
2016/06/29 00:25:02
Not exactly, but I added a note.
| |
| 5157 var = query_scope->LookupLocal(name); | |
| 5158 if (var != nullptr && IsLexicalVariableMode(var->mode())) { | |
| 5159 should_hoist = false; | |
| 5160 break; | |
| 5161 } | |
| 5162 query_scope = query_scope->outer_scope(); | |
| 5163 } while (query_scope != outer_scope); | |
| 5164 | |
| 5165 if (!should_hoist) continue; | |
| 5166 | |
| 5122 // Declare a var-style binding for the function in the outer scope | 5167 // Declare a var-style binding for the function in the outer scope |
| 5123 VariableProxy* proxy = scope->NewUnresolved(factory(), name); | 5168 if (!var_created) { |
| 5124 Declaration* declaration = factory()->NewVariableDeclaration( | 5169 var_created = true; |
| 5125 proxy, VAR, scope, RelocInfo::kNoPosition); | 5170 VariableProxy* proxy = scope->NewUnresolved(factory(), name); |
| 5126 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); | 5171 Declaration* declaration = factory()->NewVariableDeclaration( |
| 5127 DCHECK(ok); // Based on the preceding check, this should not fail | 5172 proxy, VAR, scope, RelocInfo::kNoPosition); |
| 5128 if (!ok) return; | 5173 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); |
| 5174 DCHECK(ok); // Based on the preceding check, this should not fail | |
| 5175 if (!ok) return; | |
| 5176 } | |
| 5129 | 5177 |
| 5130 // Write in assignments to var for each block-scoped function declaration | 5178 // Read from the local lexical scope and write to the function scope |
| 5131 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); | 5179 VariableProxy* to = scope->NewUnresolved(factory(), name); |
| 5132 for (SloppyBlockFunctionStatement* delegate : *delegates) { | 5180 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); |
| 5133 // Read from the local lexical scope and write to the function scope | 5181 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, to, from, |
| 5134 VariableProxy* to = scope->NewUnresolved(factory(), name); | 5182 RelocInfo::kNoPosition); |
| 5135 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); | 5183 Statement* statement = |
| 5136 Expression* assignment = factory()->NewAssignment( | 5184 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 5137 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | 5185 delegate->set_statement(statement); |
| 5138 Statement* statement = factory()->NewExpressionStatement( | |
| 5139 assignment, RelocInfo::kNoPosition); | |
| 5140 delegate->set_statement(statement); | |
| 5141 } | |
| 5142 } | 5186 } |
| 5143 } | 5187 } |
| 5144 } | 5188 } |
| 5145 | 5189 |
| 5146 | 5190 |
| 5147 // ---------------------------------------------------------------------------- | 5191 // ---------------------------------------------------------------------------- |
| 5148 // Parser support | 5192 // Parser support |
| 5149 | 5193 |
| 5150 bool Parser::TargetStackContainsLabel(const AstRawString* label) { | 5194 bool Parser::TargetStackContainsLabel(const AstRawString* label) { |
| 5151 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | 5195 for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| (...skipping 1824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6976 try_block, target); | 7020 try_block, target); |
| 6977 final_loop = target; | 7021 final_loop = target; |
| 6978 } | 7022 } |
| 6979 | 7023 |
| 6980 return final_loop; | 7024 return final_loop; |
| 6981 } | 7025 } |
| 6982 | 7026 |
| 6983 | 7027 |
| 6984 } // namespace internal | 7028 } // namespace internal |
| 6985 } // namespace v8 | 7029 } // namespace v8 |
| OLD | NEW |