| 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 3232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3243 throw_arguments->Add(result_proxy_again, zone()); | 3243 throw_arguments->Add(result_proxy_again, zone()); |
| 3244 Expression* throw_call = factory()->NewCallRuntime( | 3244 Expression* throw_call = factory()->NewCallRuntime( |
| 3245 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | 3245 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); |
| 3246 | 3246 |
| 3247 return factory()->NewBinaryOperation( | 3247 return factory()->NewBinaryOperation( |
| 3248 Token::AND, | 3248 Token::AND, |
| 3249 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | 3249 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), |
| 3250 throw_call, pos); | 3250 throw_call, pos); |
| 3251 } | 3251 } |
| 3252 | 3252 |
| 3253 | |
| 3254 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | 3253 void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
| 3255 Expression* each, Expression* subject, | 3254 Expression* each, Expression* subject, |
| 3256 Statement* body, | 3255 Statement* body) { |
| 3257 bool is_destructuring) { | |
| 3258 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment()); | |
| 3259 ForOfStatement* for_of = stmt->AsForOfStatement(); | 3256 ForOfStatement* for_of = stmt->AsForOfStatement(); |
| 3260 | |
| 3261 if (for_of != NULL) { | 3257 if (for_of != NULL) { |
| 3262 Variable* iterator = scope_->NewTemporary( | 3258 InitializeForOfStatement(for_of, each, subject, body, |
| 3263 ast_value_factory()->dot_iterator_string()); | 3259 RelocInfo::kNoPosition); |
| 3264 Variable* result = scope_->NewTemporary( | |
| 3265 ast_value_factory()->dot_result_string()); | |
| 3266 | |
| 3267 Expression* assign_iterator; | |
| 3268 Expression* next_result; | |
| 3269 Expression* result_done; | |
| 3270 Expression* assign_each; | |
| 3271 | |
| 3272 // iterator = subject[Symbol.iterator]() | |
| 3273 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
| 3274 // TODO(verwaest): Come up with a better solution. | |
| 3275 assign_iterator = factory()->NewAssignment( | |
| 3276 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
| 3277 GetIterator(subject, factory(), subject->position() - 2), | |
| 3278 subject->position()); | |
| 3279 | |
| 3280 // !%_IsJSReceiver(result = iterator.next()) && | |
| 3281 // %ThrowIteratorResultNotAnObject(result) | |
| 3282 { | |
| 3283 // result = iterator.next() | |
| 3284 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
| 3285 // Hackily disambiguate o from o.next and o [Symbol.iterator](). | |
| 3286 // TODO(verwaest): Come up with a better solution. | |
| 3287 next_result = BuildIteratorNextResult(iterator_proxy, result, | |
| 3288 subject->position() - 1); | |
| 3289 } | |
| 3290 | |
| 3291 // result.done | |
| 3292 { | |
| 3293 Expression* done_literal = factory()->NewStringLiteral( | |
| 3294 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
| 3295 Expression* result_proxy = factory()->NewVariableProxy(result); | |
| 3296 result_done = factory()->NewProperty( | |
| 3297 result_proxy, done_literal, RelocInfo::kNoPosition); | |
| 3298 } | |
| 3299 | |
| 3300 // each = result.value | |
| 3301 { | |
| 3302 Expression* value_literal = factory()->NewStringLiteral( | |
| 3303 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
| 3304 Expression* result_proxy = factory()->NewVariableProxy(result); | |
| 3305 Expression* result_value = factory()->NewProperty( | |
| 3306 result_proxy, value_literal, RelocInfo::kNoPosition); | |
| 3307 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | |
| 3308 RelocInfo::kNoPosition); | |
| 3309 if (is_destructuring) { | |
| 3310 assign_each = PatternRewriter::RewriteDestructuringAssignment( | |
| 3311 this, assign_each->AsAssignment(), scope_); | |
| 3312 } | |
| 3313 } | |
| 3314 | |
| 3315 for_of->Initialize(each, subject, body, | |
| 3316 iterator, | |
| 3317 assign_iterator, | |
| 3318 next_result, | |
| 3319 result_done, | |
| 3320 assign_each); | |
| 3321 } else { | 3260 } else { |
| 3322 if (is_destructuring) { | 3261 if (each->IsArrayLiteral() || each->IsObjectLiteral()) { |
| 3262 DCHECK(allow_harmony_destructuring_assignment()); |
| 3323 Variable* temp = | 3263 Variable* temp = |
| 3324 scope_->NewTemporary(ast_value_factory()->empty_string()); | 3264 scope_->NewTemporary(ast_value_factory()->empty_string()); |
| 3325 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3265 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
| 3326 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( | 3266 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( |
| 3327 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, | 3267 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, |
| 3328 RelocInfo::kNoPosition), | 3268 RelocInfo::kNoPosition), |
| 3329 scope_); | 3269 scope_); |
| 3330 auto block = | 3270 auto block = |
| 3331 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); | 3271 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); |
| 3332 block->statements()->Add(factory()->NewExpressionStatement( | 3272 block->statements()->Add(factory()->NewExpressionStatement( |
| 3333 assign_each, RelocInfo::kNoPosition), | 3273 assign_each, RelocInfo::kNoPosition), |
| 3334 zone()); | 3274 zone()); |
| 3335 block->statements()->Add(body, zone()); | 3275 block->statements()->Add(body, zone()); |
| 3336 body = block; | 3276 body = block; |
| 3337 each = factory()->NewVariableProxy(temp); | 3277 each = factory()->NewVariableProxy(temp); |
| 3338 } | 3278 } |
| 3339 stmt->Initialize(each, subject, body); | 3279 stmt->Initialize(each, subject, body); |
| 3340 } | 3280 } |
| 3341 } | 3281 } |
| 3342 | 3282 |
| 3283 void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each, |
| 3284 Expression* iterable, Statement* body, |
| 3285 int iterable_pos) { |
| 3286 Variable* iterator = |
| 3287 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); |
| 3288 Variable* result = |
| 3289 scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
| 3290 |
| 3291 Expression* assign_iterator; |
| 3292 Expression* next_result; |
| 3293 Expression* result_done; |
| 3294 Expression* assign_each; |
| 3295 |
| 3296 // Hackily disambiguate o from o.next and o [Symbol.iterator](). |
| 3297 // TODO(verwaest): Come up with a better solution. |
| 3298 int get_iterator_pos = iterable_pos != RelocInfo::kNoPosition |
| 3299 ? iterable_pos |
| 3300 : iterable->position() - 2; |
| 3301 int next_result_pos = iterable_pos != RelocInfo::kNoPosition |
| 3302 ? iterable_pos |
| 3303 : iterable->position() - 1; |
| 3304 |
| 3305 // iterator = iterable[Symbol.iterator]() |
| 3306 assign_iterator = factory()->NewAssignment( |
| 3307 Token::ASSIGN, factory()->NewVariableProxy(iterator), |
| 3308 GetIterator(iterable, factory(), get_iterator_pos), iterable->position()); |
| 3309 |
| 3310 // !%_IsJSReceiver(result = iterator.next()) && |
| 3311 // %ThrowIteratorResultNotAnObject(result) |
| 3312 { |
| 3313 // result = iterator.next() |
| 3314 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
| 3315 next_result = |
| 3316 BuildIteratorNextResult(iterator_proxy, result, next_result_pos); |
| 3317 } |
| 3318 |
| 3319 // result.done |
| 3320 { |
| 3321 Expression* done_literal = factory()->NewStringLiteral( |
| 3322 ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
| 3323 Expression* result_proxy = factory()->NewVariableProxy(result); |
| 3324 result_done = factory()->NewProperty(result_proxy, done_literal, |
| 3325 RelocInfo::kNoPosition); |
| 3326 } |
| 3327 |
| 3328 // each = result.value |
| 3329 { |
| 3330 Expression* value_literal = factory()->NewStringLiteral( |
| 3331 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
| 3332 Expression* result_proxy = factory()->NewVariableProxy(result); |
| 3333 Expression* result_value = factory()->NewProperty( |
| 3334 result_proxy, value_literal, RelocInfo::kNoPosition); |
| 3335 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
| 3336 RelocInfo::kNoPosition); |
| 3337 if (each->IsArrayLiteral() || each->IsObjectLiteral()) { |
| 3338 DCHECK(allow_harmony_destructuring_assignment()); |
| 3339 assign_each = PatternRewriter::RewriteDestructuringAssignment( |
| 3340 this, assign_each->AsAssignment(), scope_); |
| 3341 } |
| 3342 } |
| 3343 |
| 3344 for_of->Initialize(each, iterable, body, iterator, assign_iterator, |
| 3345 next_result, result_done, assign_each); |
| 3346 } |
| 3347 |
| 3343 Statement* Parser::DesugarLexicalBindingsInForStatement( | 3348 Statement* Parser::DesugarLexicalBindingsInForStatement( |
| 3344 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, | 3349 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, |
| 3345 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3350 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
| 3346 Statement* body, bool* ok) { | 3351 Statement* body, bool* ok) { |
| 3347 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are | 3352 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are |
| 3348 // copied into a new environment. Moreover, the "next" statement must be | 3353 // copied into a new environment. Moreover, the "next" statement must be |
| 3349 // evaluated not in the environment of the just completed iteration but in | 3354 // evaluated not in the environment of the just completed iteration but in |
| 3350 // that of the upcoming one. We achieve this with the following desugaring. | 3355 // that of the upcoming one. We achieve this with the following desugaring. |
| 3351 // Extra care is needed to preserve the completion value of the original loop. | 3356 // Extra care is needed to preserve the completion value of the original loop. |
| 3352 // | 3357 // |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3737 each_initialization_block, &descriptor, &decl, | 3742 each_initialization_block, &descriptor, &decl, |
| 3738 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings | 3743 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
| 3739 : nullptr, | 3744 : nullptr, |
| 3740 CHECK_OK); | 3745 CHECK_OK); |
| 3741 } | 3746 } |
| 3742 | 3747 |
| 3743 body_block->statements()->Add(each_initialization_block, zone()); | 3748 body_block->statements()->Add(each_initialization_block, zone()); |
| 3744 body_block->statements()->Add(body, zone()); | 3749 body_block->statements()->Add(body, zone()); |
| 3745 VariableProxy* temp_proxy = | 3750 VariableProxy* temp_proxy = |
| 3746 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | 3751 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
| 3747 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, | 3752 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); |
| 3748 false); | |
| 3749 } | 3753 } |
| 3750 body_scope->set_end_position(scanner()->location().end_pos); | 3754 body_scope->set_end_position(scanner()->location().end_pos); |
| 3751 body_scope = body_scope->FinalizeBlockScope(); | 3755 body_scope = body_scope->FinalizeBlockScope(); |
| 3752 body_block->set_scope(body_scope); | 3756 body_block->set_scope(body_scope); |
| 3753 | 3757 |
| 3754 // Create a TDZ for any lexically-bound names. | 3758 // Create a TDZ for any lexically-bound names. |
| 3755 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | 3759 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { |
| 3756 DCHECK_NULL(init_block); | 3760 DCHECK_NULL(init_block); |
| 3757 | 3761 |
| 3758 init_block = | 3762 init_block = |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3836 RewriteNonPattern(&classifier, CHECK_OK); | 3840 RewriteNonPattern(&classifier, CHECK_OK); |
| 3837 } else { | 3841 } else { |
| 3838 enumerable = ParseExpression(true, CHECK_OK); | 3842 enumerable = ParseExpression(true, CHECK_OK); |
| 3839 } | 3843 } |
| 3840 | 3844 |
| 3841 Expect(Token::RPAREN, CHECK_OK); | 3845 Expect(Token::RPAREN, CHECK_OK); |
| 3842 | 3846 |
| 3843 // For legacy compat reasons, give for loops similar treatment to | 3847 // For legacy compat reasons, give for loops similar treatment to |
| 3844 // if statements in allowing a function declaration for a body | 3848 // if statements in allowing a function declaration for a body |
| 3845 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); | 3849 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); |
| 3846 InitializeForEachStatement(loop, expression, enumerable, body, | 3850 InitializeForEachStatement(loop, expression, enumerable, body); |
| 3847 is_destructuring); | |
| 3848 | 3851 |
| 3849 Statement* final_loop = loop->IsForOfStatement() | 3852 Statement* final_loop = loop->IsForOfStatement() |
| 3850 ? FinalizeForOfStatement( | 3853 ? FinalizeForOfStatement( |
| 3851 loop->AsForOfStatement(), RelocInfo::kNoPosition) | 3854 loop->AsForOfStatement(), RelocInfo::kNoPosition) |
| 3852 : loop; | 3855 : loop; |
| 3853 | 3856 |
| 3854 for_scope->set_end_position(scanner()->location().end_pos); | 3857 for_scope->set_end_position(scanner()->location().end_pos); |
| 3855 for_scope = for_scope->FinalizeBlockScope(); | 3858 for_scope = for_scope->FinalizeBlockScope(); |
| 3856 DCHECK(for_scope == nullptr); | 3859 DCHECK(for_scope == nullptr); |
| 3857 return final_loop; | 3860 return final_loop; |
| (...skipping 1794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5652 factory()->NewCallRuntime(Runtime::kAppendElement, | 5655 factory()->NewCallRuntime(Runtime::kAppendElement, |
| 5653 append_element_args, | 5656 append_element_args, |
| 5654 RelocInfo::kNoPosition), | 5657 RelocInfo::kNoPosition), |
| 5655 RelocInfo::kNoPosition), | 5658 RelocInfo::kNoPosition), |
| 5656 zone()); | 5659 zone()); |
| 5657 } else { | 5660 } else { |
| 5658 // If it's a spread, we're adding a for/of loop iterating through it. | 5661 // If it's a spread, we're adding a for/of loop iterating through it. |
| 5659 Variable* each = | 5662 Variable* each = |
| 5660 scope_->NewTemporary(ast_value_factory()->dot_for_string()); | 5663 scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
| 5661 Expression* subject = spread->expression(); | 5664 Expression* subject = spread->expression(); |
| 5662 Variable* iterator = | |
| 5663 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
| 5664 Variable* element = | |
| 5665 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
| 5666 // iterator = subject[Symbol.iterator]() | |
| 5667 Expression* assign_iterator = factory()->NewAssignment( | |
| 5668 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
| 5669 GetIterator(subject, factory(), spread->expression_position()), | |
| 5670 subject->position()); | |
| 5671 // !%_IsJSReceiver(element = iterator.next()) && | |
| 5672 // %ThrowIteratorResultNotAnObject(element) | |
| 5673 Expression* next_element; | |
| 5674 { | |
| 5675 // element = iterator.next() | |
| 5676 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
| 5677 next_element = BuildIteratorNextResult(iterator_proxy, element, | |
| 5678 spread->expression_position()); | |
| 5679 } | |
| 5680 // element.done | |
| 5681 Expression* element_done; | |
| 5682 { | |
| 5683 Expression* done_literal = factory()->NewStringLiteral( | |
| 5684 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
| 5685 Expression* element_proxy = factory()->NewVariableProxy(element); | |
| 5686 element_done = factory()->NewProperty(element_proxy, done_literal, | |
| 5687 RelocInfo::kNoPosition); | |
| 5688 } | |
| 5689 // each = element.value | |
| 5690 Expression* assign_each; | |
| 5691 { | |
| 5692 Expression* value_literal = factory()->NewStringLiteral( | |
| 5693 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
| 5694 Expression* element_proxy = factory()->NewVariableProxy(element); | |
| 5695 Expression* element_value = factory()->NewProperty( | |
| 5696 element_proxy, value_literal, RelocInfo::kNoPosition); | |
| 5697 assign_each = factory()->NewAssignment( | |
| 5698 Token::ASSIGN, factory()->NewVariableProxy(each), element_value, | |
| 5699 RelocInfo::kNoPosition); | |
| 5700 } | |
| 5701 // %AppendElement($R, each) | 5665 // %AppendElement($R, each) |
| 5702 Statement* append_body; | 5666 Statement* append_body; |
| 5703 { | 5667 { |
| 5704 ZoneList<Expression*>* append_element_args = | 5668 ZoneList<Expression*>* append_element_args = |
| 5705 NewExpressionList(2, zone()); | 5669 NewExpressionList(2, zone()); |
| 5706 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | 5670 append_element_args->Add(factory()->NewVariableProxy(result), zone()); |
| 5707 append_element_args->Add(factory()->NewVariableProxy(each), zone()); | 5671 append_element_args->Add(factory()->NewVariableProxy(each), zone()); |
| 5708 append_body = factory()->NewExpressionStatement( | 5672 append_body = factory()->NewExpressionStatement( |
| 5709 factory()->NewCallRuntime(Runtime::kAppendElement, | 5673 factory()->NewCallRuntime(Runtime::kAppendElement, |
| 5710 append_element_args, | 5674 append_element_args, |
| 5711 RelocInfo::kNoPosition), | 5675 RelocInfo::kNoPosition), |
| 5712 RelocInfo::kNoPosition); | 5676 RelocInfo::kNoPosition); |
| 5713 } | 5677 } |
| 5714 // for (each of spread) %AppendElement($R, each) | 5678 // for (each of spread) %AppendElement($R, each) |
| 5715 ForEachStatement* loop = factory()->NewForEachStatement( | 5679 ForEachStatement* loop = factory()->NewForEachStatement( |
| 5716 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); | 5680 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); |
| 5717 ForOfStatement* for_of = loop->AsForOfStatement(); | 5681 InitializeForOfStatement(loop->AsForOfStatement(), |
| 5718 for_of->Initialize(factory()->NewVariableProxy(each), subject, | 5682 factory()->NewVariableProxy(each), subject, |
| 5719 append_body, iterator, assign_iterator, next_element, | 5683 append_body, spread->expression_position()); |
| 5720 element_done, assign_each); | 5684 do_block->statements()->Add(loop, zone()); |
| 5721 do_block->statements()->Add(for_of, zone()); | |
| 5722 } | 5685 } |
| 5723 } | 5686 } |
| 5724 // Now, rewind the original array literal to truncate everything from the | 5687 // Now, rewind the original array literal to truncate everything from the |
| 5725 // first spread (included) until the end. This fixes $R's initialization. | 5688 // first spread (included) until the end. This fixes $R's initialization. |
| 5726 lit->RewindSpreads(); | 5689 lit->RewindSpreads(); |
| 5727 return factory()->NewDoExpression(do_block, result, lit->position()); | 5690 return factory()->NewDoExpression(do_block, result, lit->position()); |
| 5728 } | 5691 } |
| 5729 | 5692 |
| 5730 | 5693 |
| 5731 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 5694 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
| (...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6930 Expression* do_each = | 6893 Expression* do_each = |
| 6931 factory->NewDoExpression(new_assign_each, var_each, nopos); | 6894 factory->NewDoExpression(new_assign_each, var_each, nopos); |
| 6932 loop->set_assign_each(do_each); | 6895 loop->set_assign_each(do_each); |
| 6933 | 6896 |
| 6934 return final_loop; | 6897 return final_loop; |
| 6935 } | 6898 } |
| 6936 | 6899 |
| 6937 | 6900 |
| 6938 } // namespace internal | 6901 } // namespace internal |
| 6939 } // namespace v8 | 6902 } // namespace v8 |
| OLD | NEW |