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 |