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 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 767 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); | 767 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); |
| 768 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); | 768 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); |
| 769 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); | 769 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); |
| 770 set_allow_harmony_destructuring_assignment( | 770 set_allow_harmony_destructuring_assignment( |
| 771 FLAG_harmony_destructuring_assignment); | 771 FLAG_harmony_destructuring_assignment); |
| 772 set_allow_strong_mode(FLAG_strong_mode); | 772 set_allow_strong_mode(FLAG_strong_mode); |
| 773 set_allow_legacy_const(FLAG_legacy_const); | 773 set_allow_legacy_const(FLAG_legacy_const); |
| 774 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); | 774 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); |
| 775 set_allow_harmony_function_name(FLAG_harmony_function_name); | 775 set_allow_harmony_function_name(FLAG_harmony_function_name); |
| 776 set_allow_harmony_function_sent(FLAG_harmony_function_sent); | 776 set_allow_harmony_function_sent(FLAG_harmony_function_sent); |
| 777 set_allow_harmony_restrictive_declarations( | |
| 778 FLAG_harmony_restrictive_declarations); | |
| 777 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | 779 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; |
| 778 ++feature) { | 780 ++feature) { |
| 779 use_counts_[feature] = 0; | 781 use_counts_[feature] = 0; |
| 780 } | 782 } |
| 781 if (info->ast_value_factory() == NULL) { | 783 if (info->ast_value_factory() == NULL) { |
| 782 // info takes ownership of AstValueFactory. | 784 // info takes ownership of AstValueFactory. |
| 783 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); | 785 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); |
| 784 info->set_ast_value_factory_owned(); | 786 info->set_ast_value_factory_owned(); |
| 785 ast_value_factory_ = info->ast_value_factory(); | 787 ast_value_factory_ = info->ast_value_factory(); |
| 786 } | 788 } |
| (...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1833 } | 1835 } |
| 1834 } | 1836 } |
| 1835 | 1837 |
| 1836 case Token::WITH: | 1838 case Token::WITH: |
| 1837 return ParseWithStatement(labels, ok); | 1839 return ParseWithStatement(labels, ok); |
| 1838 | 1840 |
| 1839 case Token::SWITCH: | 1841 case Token::SWITCH: |
| 1840 return ParseSwitchStatement(labels, ok); | 1842 return ParseSwitchStatement(labels, ok); |
| 1841 | 1843 |
| 1842 case Token::FUNCTION: { | 1844 case Token::FUNCTION: { |
| 1843 // FunctionDeclaration is only allowed in the context of SourceElements | 1845 // FunctionDeclaration only allowed as a StatementListItem, not in |
| 1844 // (Ecma 262 5th Edition, clause 14): | 1846 // an arbitrary Statement position. Exceptions such as |
| 1845 // SourceElement: | 1847 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses |
| 1846 // Statement | 1848 // are handled by calling ParseScopedStatement rather than |
| 1847 // FunctionDeclaration | 1849 // ParseSubStatement directly. |
| 1848 // Common language extension is to allow function declaration in place | 1850 ReportMessageAt(scanner()->peek_location(), |
| 1849 // of any statement. This language extension is disabled in strict mode. | 1851 is_strict(language_mode()) ? |
| 1850 // | 1852 MessageTemplate::kStrictFunction : |
| 1851 // In Harmony mode, this case also handles the extension: | 1853 MessageTemplate::kSloppyFunction); |
| 1852 // Statement: | 1854 *ok = false; |
| 1853 // GeneratorDeclaration | 1855 return nullptr; |
| 1854 if (is_strict(language_mode())) { | |
| 1855 ReportMessageAt(scanner()->peek_location(), | |
| 1856 MessageTemplate::kStrictFunction); | |
| 1857 *ok = false; | |
| 1858 return NULL; | |
| 1859 } | |
| 1860 return ParseFunctionDeclaration(NULL, ok); | |
| 1861 } | 1856 } |
| 1862 | 1857 |
| 1863 case Token::DEBUGGER: | 1858 case Token::DEBUGGER: |
| 1864 return ParseDebuggerStatement(ok); | 1859 return ParseDebuggerStatement(ok); |
| 1865 | 1860 |
| 1866 case Token::VAR: | 1861 case Token::VAR: |
| 1867 return ParseVariableStatement(kStatement, NULL, ok); | 1862 return ParseVariableStatement(kStatement, NULL, ok); |
| 1868 | 1863 |
| 1869 case Token::CONST: | 1864 case Token::CONST: |
| 1870 // In ES6 CONST is not allowed as a Statement, only as a | 1865 // In ES6 CONST is not allowed as a Statement, only as a |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2574 } | 2569 } |
| 2575 if (labels == NULL) { | 2570 if (labels == NULL) { |
| 2576 labels = new(zone()) ZoneList<const AstRawString*>(4, zone()); | 2571 labels = new(zone()) ZoneList<const AstRawString*>(4, zone()); |
| 2577 } | 2572 } |
| 2578 labels->Add(label, zone()); | 2573 labels->Add(label, zone()); |
| 2579 // Remove the "ghost" variable that turned out to be a label | 2574 // Remove the "ghost" variable that turned out to be a label |
| 2580 // from the top scope. This way, we don't try to resolve it | 2575 // from the top scope. This way, we don't try to resolve it |
| 2581 // during the scope processing. | 2576 // during the scope processing. |
| 2582 scope_->RemoveUnresolved(var); | 2577 scope_->RemoveUnresolved(var); |
| 2583 Expect(Token::COLON, CHECK_OK); | 2578 Expect(Token::COLON, CHECK_OK); |
| 2579 // ES#sec-labelled-function-declarations Labelled Function Declarations | |
|
adamk
2016/03/02 00:51:10
Can you add tests feature labels? It seems we curr
Dan Ehrenberg
2016/03/03 02:32:57
Done
| |
| 2580 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | |
| 2581 return ParseFunctionDeclaration(labels, ok); | |
| 2582 } | |
| 2584 return ParseStatement(labels, ok); | 2583 return ParseStatement(labels, ok); |
| 2585 } | 2584 } |
| 2586 | 2585 |
| 2587 // If we have an extension, we allow a native function declaration. | 2586 // If we have an extension, we allow a native function declaration. |
| 2588 // A native function declaration starts with "native function" with | 2587 // A native function declaration starts with "native function" with |
| 2589 // no line-terminator between the two words. | 2588 // no line-terminator between the two words. |
| 2590 if (extension_ != NULL && peek() == Token::FUNCTION && | 2589 if (extension_ != NULL && peek() == Token::FUNCTION && |
| 2591 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && | 2590 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && |
| 2592 expr->AsVariableProxy() != NULL && | 2591 expr->AsVariableProxy() != NULL && |
| 2593 expr->AsVariableProxy()->raw_name() == | 2592 expr->AsVariableProxy()->raw_name() == |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2614 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels, | 2613 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels, |
| 2615 bool* ok) { | 2614 bool* ok) { |
| 2616 // IfStatement :: | 2615 // IfStatement :: |
| 2617 // 'if' '(' Expression ')' Statement ('else' Statement)? | 2616 // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 2618 | 2617 |
| 2619 int pos = peek_position(); | 2618 int pos = peek_position(); |
| 2620 Expect(Token::IF, CHECK_OK); | 2619 Expect(Token::IF, CHECK_OK); |
| 2621 Expect(Token::LPAREN, CHECK_OK); | 2620 Expect(Token::LPAREN, CHECK_OK); |
| 2622 Expression* condition = ParseExpression(true, CHECK_OK); | 2621 Expression* condition = ParseExpression(true, CHECK_OK); |
| 2623 Expect(Token::RPAREN, CHECK_OK); | 2622 Expect(Token::RPAREN, CHECK_OK); |
| 2624 Statement* then_statement = ParseSubStatement(labels, CHECK_OK); | 2623 Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK); |
| 2625 Statement* else_statement = NULL; | 2624 Statement* else_statement = NULL; |
| 2626 if (peek() == Token::ELSE) { | 2625 if (peek() == Token::ELSE) { |
| 2627 Next(); | 2626 Next(); |
| 2628 else_statement = ParseSubStatement(labels, CHECK_OK); | 2627 else_statement = ParseScopedStatement(labels, false, CHECK_OK); |
| 2629 } else { | 2628 } else { |
| 2630 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 2629 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
| 2631 } | 2630 } |
| 2632 return factory()->NewIfStatement( | 2631 return factory()->NewIfStatement( |
| 2633 condition, then_statement, else_statement, pos); | 2632 condition, then_statement, else_statement, pos); |
| 2634 } | 2633 } |
| 2635 | 2634 |
| 2636 | 2635 |
| 2637 Statement* Parser::ParseContinueStatement(bool* ok) { | 2636 Statement* Parser::ParseContinueStatement(bool* ok) { |
| 2638 // ContinueStatement :: | 2637 // ContinueStatement :: |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2817 *ok = false; | 2816 *ok = false; |
| 2818 return NULL; | 2817 return NULL; |
| 2819 } | 2818 } |
| 2820 | 2819 |
| 2821 Expect(Token::LPAREN, CHECK_OK); | 2820 Expect(Token::LPAREN, CHECK_OK); |
| 2822 Expression* expr = ParseExpression(true, CHECK_OK); | 2821 Expression* expr = ParseExpression(true, CHECK_OK); |
| 2823 Expect(Token::RPAREN, CHECK_OK); | 2822 Expect(Token::RPAREN, CHECK_OK); |
| 2824 | 2823 |
| 2825 scope_->DeclarationScope()->RecordWithStatement(); | 2824 scope_->DeclarationScope()->RecordWithStatement(); |
| 2826 Scope* with_scope = NewScope(scope_, WITH_SCOPE); | 2825 Scope* with_scope = NewScope(scope_, WITH_SCOPE); |
| 2827 Block* body; | 2826 Statement* body; |
| 2828 { BlockState block_state(&scope_, with_scope); | 2827 { BlockState block_state(&scope_, with_scope); |
| 2829 with_scope->set_start_position(scanner()->peek_location().beg_pos); | 2828 with_scope->set_start_position(scanner()->peek_location().beg_pos); |
| 2830 | 2829 body = ParseScopedStatement(labels, true, CHECK_OK); |
| 2831 // The body of the with statement must be enclosed in an additional | |
| 2832 // lexical scope in case the body is a FunctionDeclaration. | |
| 2833 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); | |
| 2834 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | |
| 2835 block_scope->set_start_position(scanner()->location().beg_pos); | |
| 2836 { | |
| 2837 BlockState block_state(&scope_, block_scope); | |
| 2838 Target target(&this->target_stack_, body); | |
| 2839 Statement* stmt = ParseSubStatement(labels, CHECK_OK); | |
| 2840 body->statements()->Add(stmt, zone()); | |
| 2841 block_scope->set_end_position(scanner()->location().end_pos); | |
| 2842 block_scope = block_scope->FinalizeBlockScope(); | |
| 2843 body->set_scope(block_scope); | |
| 2844 } | |
| 2845 | |
| 2846 with_scope->set_end_position(scanner()->location().end_pos); | 2830 with_scope->set_end_position(scanner()->location().end_pos); |
| 2847 } | 2831 } |
| 2848 return factory()->NewWithStatement(with_scope, expr, body, pos); | 2832 return factory()->NewWithStatement(with_scope, expr, body, pos); |
| 2849 } | 2833 } |
| 2850 | 2834 |
| 2851 | 2835 |
| 2852 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | 2836 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| 2853 // CaseClause :: | 2837 // CaseClause :: |
| 2854 // 'case' Expression ':' StatementList | 2838 // 'case' Expression ':' StatementList |
| 2855 // 'default' ':' StatementList | 2839 // 'default' ':' StatementList |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3176 DoWhileStatement* Parser::ParseDoWhileStatement( | 3160 DoWhileStatement* Parser::ParseDoWhileStatement( |
| 3177 ZoneList<const AstRawString*>* labels, bool* ok) { | 3161 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 3178 // DoStatement :: | 3162 // DoStatement :: |
| 3179 // 'do' Statement 'while' '(' Expression ')' ';' | 3163 // 'do' Statement 'while' '(' Expression ')' ';' |
| 3180 | 3164 |
| 3181 DoWhileStatement* loop = | 3165 DoWhileStatement* loop = |
| 3182 factory()->NewDoWhileStatement(labels, peek_position()); | 3166 factory()->NewDoWhileStatement(labels, peek_position()); |
| 3183 Target target(&this->target_stack_, loop); | 3167 Target target(&this->target_stack_, loop); |
| 3184 | 3168 |
| 3185 Expect(Token::DO, CHECK_OK); | 3169 Expect(Token::DO, CHECK_OK); |
| 3186 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3170 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); |
| 3187 Expect(Token::WHILE, CHECK_OK); | 3171 Expect(Token::WHILE, CHECK_OK); |
| 3188 Expect(Token::LPAREN, CHECK_OK); | 3172 Expect(Token::LPAREN, CHECK_OK); |
| 3189 | 3173 |
| 3190 Expression* cond = ParseExpression(true, CHECK_OK); | 3174 Expression* cond = ParseExpression(true, CHECK_OK); |
| 3191 Expect(Token::RPAREN, CHECK_OK); | 3175 Expect(Token::RPAREN, CHECK_OK); |
| 3192 | 3176 |
| 3193 // Allow do-statements to be terminated with and without | 3177 // Allow do-statements to be terminated with and without |
| 3194 // semi-colons. This allows code such as 'do;while(0)return' to | 3178 // semi-colons. This allows code such as 'do;while(0)return' to |
| 3195 // parse, which would not be the case if we had used the | 3179 // parse, which would not be the case if we had used the |
| 3196 // ExpectSemicolon() functionality here. | 3180 // ExpectSemicolon() functionality here. |
| 3197 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); | 3181 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
| 3198 | 3182 |
| 3199 if (loop != NULL) loop->Initialize(cond, body); | 3183 if (loop != NULL) loop->Initialize(cond, body); |
| 3200 return loop; | 3184 return loop; |
| 3201 } | 3185 } |
| 3202 | 3186 |
| 3203 | 3187 |
| 3204 WhileStatement* Parser::ParseWhileStatement( | 3188 WhileStatement* Parser::ParseWhileStatement( |
| 3205 ZoneList<const AstRawString*>* labels, bool* ok) { | 3189 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 3206 // WhileStatement :: | 3190 // WhileStatement :: |
| 3207 // 'while' '(' Expression ')' Statement | 3191 // 'while' '(' Expression ')' Statement |
| 3208 | 3192 |
| 3209 WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position()); | 3193 WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position()); |
| 3210 Target target(&this->target_stack_, loop); | 3194 Target target(&this->target_stack_, loop); |
| 3211 | 3195 |
| 3212 Expect(Token::WHILE, CHECK_OK); | 3196 Expect(Token::WHILE, CHECK_OK); |
| 3213 Expect(Token::LPAREN, CHECK_OK); | 3197 Expect(Token::LPAREN, CHECK_OK); |
| 3214 Expression* cond = ParseExpression(true, CHECK_OK); | 3198 Expression* cond = ParseExpression(true, CHECK_OK); |
| 3215 Expect(Token::RPAREN, CHECK_OK); | 3199 Expect(Token::RPAREN, CHECK_OK); |
| 3216 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3200 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); |
| 3217 | 3201 |
| 3218 if (loop != NULL) loop->Initialize(cond, body); | 3202 if (loop != NULL) loop->Initialize(cond, body); |
| 3219 return loop; | 3203 return loop; |
| 3220 } | 3204 } |
| 3221 | 3205 |
| 3222 | 3206 |
| 3223 // !%_IsJSReceiver(result = iterator.next()) && | 3207 // !%_IsJSReceiver(result = iterator.next()) && |
| 3224 // %ThrowIteratorResultNotAnObject(result) | 3208 // %ThrowIteratorResultNotAnObject(result) |
| 3225 Expression* Parser::BuildIteratorNextResult(Expression* iterator, | 3209 Expression* Parser::BuildIteratorNextResult(Expression* iterator, |
| 3226 Variable* result, int pos) { | 3210 Variable* result, int pos) { |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3589 | 3573 |
| 3590 inner_scope->set_end_position(scanner()->location().end_pos); | 3574 inner_scope->set_end_position(scanner()->location().end_pos); |
| 3591 inner_block->set_scope(inner_scope); | 3575 inner_block->set_scope(inner_scope); |
| 3592 } | 3576 } |
| 3593 | 3577 |
| 3594 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 3578 outer_loop->Initialize(NULL, NULL, NULL, inner_block); |
| 3595 return outer_block; | 3579 return outer_block; |
| 3596 } | 3580 } |
| 3597 | 3581 |
| 3598 | 3582 |
| 3583 Statement* Parser::ParseScopedStatement( | |
| 3584 ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { | |
| 3585 if (is_strict(language_mode()) || peek() != Token::FUNCTION || | |
| 3586 (legacy && allow_harmony_restrictive_declarations())) { | |
| 3587 return ParseSubStatement(labels, ok); | |
| 3588 } else { | |
| 3589 if (legacy) { | |
| 3590 ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration]; | |
| 3591 } | |
| 3592 // Make a block around the statement for a lexical binding | |
| 3593 // is introduced by a FunctionDeclaration. | |
| 3594 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); | |
| 3595 BlockState block_state(&scope_, body_scope); | |
| 3596 Block* block = | |
| 3597 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | |
| 3598 Statement* body = ParseFunctionDeclaration(NULL, CHECK_OK); | |
| 3599 block->statements()->Add(body, zone()); | |
| 3600 body_scope->set_end_position(scanner()->location().end_pos); | |
| 3601 body_scope = body_scope->FinalizeBlockScope(); | |
| 3602 block->set_scope(body_scope); | |
| 3603 return block; | |
| 3604 } | |
| 3605 } | |
| 3606 | |
| 3607 | |
| 3599 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3608 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| 3600 bool* ok) { | 3609 bool* ok) { |
| 3601 int stmt_pos = peek_position(); | 3610 int stmt_pos = peek_position(); |
| 3602 Statement* init = NULL; | 3611 Statement* init = NULL; |
| 3603 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | 3612 ZoneList<const AstRawString*> lexical_bindings(1, zone()); |
| 3604 | 3613 |
| 3605 // Create an in-between scope for let-bound iteration variables. | 3614 // Create an in-between scope for let-bound iteration variables. |
| 3606 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3615 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
| 3607 | 3616 |
| 3608 BlockState block_state(&scope_, for_scope); | 3617 BlockState block_state(&scope_, for_scope); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3701 | 3710 |
| 3702 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); | 3711 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); |
| 3703 body_scope->set_start_position(scanner()->location().beg_pos); | 3712 body_scope->set_start_position(scanner()->location().beg_pos); |
| 3704 | 3713 |
| 3705 Block* body_block = | 3714 Block* body_block = |
| 3706 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3715 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
| 3707 | 3716 |
| 3708 { | 3717 { |
| 3709 BlockState block_state(&scope_, body_scope); | 3718 BlockState block_state(&scope_, body_scope); |
| 3710 | 3719 |
| 3711 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3720 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); |
| 3712 | 3721 |
| 3713 auto each_initialization_block = | 3722 auto each_initialization_block = |
| 3714 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); | 3723 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
| 3715 { | 3724 { |
| 3716 auto descriptor = parsing_result.descriptor; | 3725 auto descriptor = parsing_result.descriptor; |
| 3717 descriptor.declaration_pos = RelocInfo::kNoPosition; | 3726 descriptor.declaration_pos = RelocInfo::kNoPosition; |
| 3718 descriptor.initialization_pos = RelocInfo::kNoPosition; | 3727 descriptor.initialization_pos = RelocInfo::kNoPosition; |
| 3719 decl.initializer = factory()->NewVariableProxy(temp); | 3728 decl.initializer = factory()->NewVariableProxy(temp); |
| 3720 | 3729 |
| 3721 PatternRewriter::DeclareAndInitializeVariables( | 3730 PatternRewriter::DeclareAndInitializeVariables( |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3818 if (mode == ForEachStatement::ITERATE) { | 3827 if (mode == ForEachStatement::ITERATE) { |
| 3819 ExpressionClassifier classifier(this); | 3828 ExpressionClassifier classifier(this); |
| 3820 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK); | 3829 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK); |
| 3821 RewriteNonPattern(&classifier, CHECK_OK); | 3830 RewriteNonPattern(&classifier, CHECK_OK); |
| 3822 } else { | 3831 } else { |
| 3823 enumerable = ParseExpression(true, CHECK_OK); | 3832 enumerable = ParseExpression(true, CHECK_OK); |
| 3824 } | 3833 } |
| 3825 | 3834 |
| 3826 Expect(Token::RPAREN, CHECK_OK); | 3835 Expect(Token::RPAREN, CHECK_OK); |
| 3827 | 3836 |
| 3828 // Make a block around the statement in case a lexical binding | 3837 // For legacy compat reasons, give for loops similar treatment to |
| 3829 // is introduced, e.g. by a FunctionDeclaration. | 3838 // if statements in allowing a function declaration for a body |
| 3830 // This block must not use for_scope as its scope because if a | 3839 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); |
| 3831 // lexical binding is introduced which overlaps with the for-in/of, | 3840 InitializeForEachStatement(loop, expression, enumerable, body, |
| 3832 // expressions in head of the loop should actually have variables | 3841 is_destructuring); |
| 3833 // resolved in the outer scope. | |
| 3834 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); | |
| 3835 { | |
| 3836 BlockState block_state(&scope_, body_scope); | |
| 3837 Block* block = | |
| 3838 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | |
| 3839 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
| 3840 block->statements()->Add(body, zone()); | |
| 3841 InitializeForEachStatement(loop, expression, enumerable, block, | |
| 3842 is_destructuring); | |
| 3843 body_scope->set_end_position(scanner()->location().end_pos); | |
| 3844 body_scope = body_scope->FinalizeBlockScope(); | |
| 3845 block->set_scope(body_scope); | |
| 3846 } | |
| 3847 | 3842 |
| 3848 Statement* final_loop = loop->IsForOfStatement() | 3843 Statement* final_loop = loop->IsForOfStatement() |
| 3849 ? FinalizeForOfStatement( | 3844 ? FinalizeForOfStatement( |
| 3850 loop->AsForOfStatement(), RelocInfo::kNoPosition) | 3845 loop->AsForOfStatement(), RelocInfo::kNoPosition) |
| 3851 : loop; | 3846 : loop; |
| 3852 | 3847 |
| 3853 for_scope->set_end_position(scanner()->location().end_pos); | 3848 for_scope->set_end_position(scanner()->location().end_pos); |
| 3854 for_scope = for_scope->FinalizeBlockScope(); | 3849 for_scope = for_scope->FinalizeBlockScope(); |
| 3855 DCHECK(for_scope == nullptr); | 3850 DCHECK(for_scope == nullptr); |
| 3856 return final_loop; | 3851 return final_loop; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3893 cond = ParseExpression(true, CHECK_OK); | 3888 cond = ParseExpression(true, CHECK_OK); |
| 3894 } | 3889 } |
| 3895 Expect(Token::SEMICOLON, CHECK_OK); | 3890 Expect(Token::SEMICOLON, CHECK_OK); |
| 3896 | 3891 |
| 3897 if (peek() != Token::RPAREN) { | 3892 if (peek() != Token::RPAREN) { |
| 3898 Expression* exp = ParseExpression(true, CHECK_OK); | 3893 Expression* exp = ParseExpression(true, CHECK_OK); |
| 3899 next = factory()->NewExpressionStatement(exp, exp->position()); | 3894 next = factory()->NewExpressionStatement(exp, exp->position()); |
| 3900 } | 3895 } |
| 3901 Expect(Token::RPAREN, CHECK_OK); | 3896 Expect(Token::RPAREN, CHECK_OK); |
| 3902 | 3897 |
| 3903 body = ParseSubStatement(NULL, CHECK_OK); | 3898 body = ParseScopedStatement(NULL, true, CHECK_OK); |
| 3904 } | 3899 } |
| 3905 | 3900 |
| 3906 Statement* result = NULL; | 3901 Statement* result = NULL; |
| 3907 if (lexical_bindings.length() > 0) { | 3902 if (lexical_bindings.length() > 0) { |
| 3908 BlockState block_state(&scope_, for_scope); | 3903 BlockState block_state(&scope_, for_scope); |
| 3909 result = DesugarLexicalBindingsInForStatement( | 3904 result = DesugarLexicalBindingsInForStatement( |
| 3910 inner_scope, parsing_result.descriptor.mode, &lexical_bindings, loop, | 3905 inner_scope, parsing_result.descriptor.mode, &lexical_bindings, loop, |
| 3911 init, cond, next, body, CHECK_OK); | 3906 init, cond, next, body, CHECK_OK); |
| 3912 for_scope->set_end_position(scanner()->location().end_pos); | 3907 for_scope->set_end_position(scanner()->location().end_pos); |
| 3913 } else { | 3908 } else { |
| (...skipping 3026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6940 Expression* do_each = | 6935 Expression* do_each = |
| 6941 factory->NewDoExpression(new_assign_each, var_each, nopos); | 6936 factory->NewDoExpression(new_assign_each, var_each, nopos); |
| 6942 loop->set_assign_each(do_each); | 6937 loop->set_assign_each(do_each); |
| 6943 | 6938 |
| 6944 return final_loop; | 6939 return final_loop; |
| 6945 } | 6940 } |
| 6946 | 6941 |
| 6947 | 6942 |
| 6948 } // namespace internal | 6943 } // namespace internal |
| 6949 } // namespace v8 | 6944 } // namespace v8 |
| OLD | NEW |