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 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
7 | 7 |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 stack_overflow_(false), | 217 stack_overflow_(false), |
218 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), | 218 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), |
219 function_literal_id_(0), | 219 function_literal_id_(0), |
220 allow_natives_(false), | 220 allow_natives_(false), |
221 allow_tailcalls_(false), | 221 allow_tailcalls_(false), |
222 allow_harmony_do_expressions_(false), | 222 allow_harmony_do_expressions_(false), |
223 allow_harmony_function_sent_(false), | 223 allow_harmony_function_sent_(false), |
224 allow_harmony_restrictive_generators_(false), | 224 allow_harmony_restrictive_generators_(false), |
225 allow_harmony_trailing_commas_(false), | 225 allow_harmony_trailing_commas_(false), |
226 allow_harmony_class_fields_(false), | 226 allow_harmony_class_fields_(false), |
227 allow_harmony_object_rest_spread_(false) {} | 227 allow_harmony_object_rest_spread_(false), |
| 228 allow_harmony_async_iteration_(false) {} |
228 | 229 |
229 #define ALLOW_ACCESSORS(name) \ | 230 #define ALLOW_ACCESSORS(name) \ |
230 bool allow_##name() const { return allow_##name##_; } \ | 231 bool allow_##name() const { return allow_##name##_; } \ |
231 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | 232 void set_allow_##name(bool allow) { allow_##name##_ = allow; } |
232 | 233 |
233 ALLOW_ACCESSORS(natives); | 234 ALLOW_ACCESSORS(natives); |
234 ALLOW_ACCESSORS(tailcalls); | 235 ALLOW_ACCESSORS(tailcalls); |
235 ALLOW_ACCESSORS(harmony_do_expressions); | 236 ALLOW_ACCESSORS(harmony_do_expressions); |
236 ALLOW_ACCESSORS(harmony_function_sent); | 237 ALLOW_ACCESSORS(harmony_function_sent); |
237 ALLOW_ACCESSORS(harmony_restrictive_generators); | 238 ALLOW_ACCESSORS(harmony_restrictive_generators); |
238 ALLOW_ACCESSORS(harmony_trailing_commas); | 239 ALLOW_ACCESSORS(harmony_trailing_commas); |
239 ALLOW_ACCESSORS(harmony_class_fields); | 240 ALLOW_ACCESSORS(harmony_class_fields); |
240 ALLOW_ACCESSORS(harmony_object_rest_spread); | 241 ALLOW_ACCESSORS(harmony_object_rest_spread); |
| 242 ALLOW_ACCESSORS(harmony_async_iteration); |
241 | 243 |
242 #undef ALLOW_ACCESSORS | 244 #undef ALLOW_ACCESSORS |
243 | 245 |
244 uintptr_t stack_limit() const { return stack_limit_; } | 246 uintptr_t stack_limit() const { return stack_limit_; } |
245 | 247 |
246 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } | 248 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } |
247 | 249 |
248 void set_default_eager_compile_hint( | 250 void set_default_eager_compile_hint( |
249 FunctionLiteral::EagerCompileHint eager_compile_hint) { | 251 FunctionLiteral::EagerCompileHint eager_compile_hint) { |
250 default_eager_compile_hint_ = eager_compile_hint; | 252 default_eager_compile_hint_ = eager_compile_hint; |
(...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, | 1311 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, |
1310 ForInfo* for_info, BlockState* for_state, | 1312 ForInfo* for_info, BlockState* for_state, |
1311 ZoneList<const AstRawString*>* labels, bool* ok); | 1313 ZoneList<const AstRawString*>* labels, bool* ok); |
1312 | 1314 |
1313 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' | 1315 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' |
1314 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, | 1316 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, |
1315 bool bound_names_are_lexical, | 1317 bool bound_names_are_lexical, |
1316 ForInfo* for_info, BlockState* for_state, | 1318 ForInfo* for_info, BlockState* for_state, |
1317 ZoneList<const AstRawString*>* labels, | 1319 ZoneList<const AstRawString*>* labels, |
1318 bool* ok); | 1320 bool* ok); |
| 1321 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels, |
| 1322 bool* ok); |
1319 | 1323 |
1320 bool IsNextLetKeyword(); | 1324 bool IsNextLetKeyword(); |
1321 bool IsTrivialExpression(); | 1325 bool IsTrivialExpression(); |
1322 | 1326 |
1323 // Checks if the expression is a valid reference expression (e.g., on the | 1327 // Checks if the expression is a valid reference expression (e.g., on the |
1324 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1328 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1325 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1329 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1326 ExpressionT CheckAndRewriteReferenceExpression( | 1330 ExpressionT CheckAndRewriteReferenceExpression( |
1327 ExpressionT expression, int beg_pos, int end_pos, | 1331 ExpressionT expression, int beg_pos, int end_pos, |
1328 MessageTemplate::Template message, bool* ok); | 1332 MessageTemplate::Template message, bool* ok); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1477 int function_literal_id_; | 1481 int function_literal_id_; |
1478 | 1482 |
1479 bool allow_natives_; | 1483 bool allow_natives_; |
1480 bool allow_tailcalls_; | 1484 bool allow_tailcalls_; |
1481 bool allow_harmony_do_expressions_; | 1485 bool allow_harmony_do_expressions_; |
1482 bool allow_harmony_function_sent_; | 1486 bool allow_harmony_function_sent_; |
1483 bool allow_harmony_restrictive_generators_; | 1487 bool allow_harmony_restrictive_generators_; |
1484 bool allow_harmony_trailing_commas_; | 1488 bool allow_harmony_trailing_commas_; |
1485 bool allow_harmony_class_fields_; | 1489 bool allow_harmony_class_fields_; |
1486 bool allow_harmony_object_rest_spread_; | 1490 bool allow_harmony_object_rest_spread_; |
| 1491 bool allow_harmony_async_iteration_; |
1487 | 1492 |
1488 friend class DiscardableZoneScope; | 1493 friend class DiscardableZoneScope; |
1489 }; | 1494 }; |
1490 | 1495 |
1491 template <typename Impl> | 1496 template <typename Impl> |
1492 ParserBase<Impl>::FunctionState::FunctionState( | 1497 ParserBase<Impl>::FunctionState::FunctionState( |
1493 FunctionState** function_state_stack, ScopeState** scope_stack, | 1498 FunctionState** function_state_stack, ScopeState** scope_stack, |
1494 DeclarationScope* scope) | 1499 DeclarationScope* scope) |
1495 : ScopeState(scope_stack, scope), | 1500 : ScopeState(scope_stack, scope), |
1496 next_materialized_literal_index_(0), | 1501 next_materialized_literal_index_(0), |
(...skipping 3273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4770 case Token::SEMICOLON: | 4775 case Token::SEMICOLON: |
4771 Next(); | 4776 Next(); |
4772 return factory()->NewEmptyStatement(kNoSourcePosition); | 4777 return factory()->NewEmptyStatement(kNoSourcePosition); |
4773 case Token::IF: | 4778 case Token::IF: |
4774 return ParseIfStatement(labels, ok); | 4779 return ParseIfStatement(labels, ok); |
4775 case Token::DO: | 4780 case Token::DO: |
4776 return ParseDoWhileStatement(labels, ok); | 4781 return ParseDoWhileStatement(labels, ok); |
4777 case Token::WHILE: | 4782 case Token::WHILE: |
4778 return ParseWhileStatement(labels, ok); | 4783 return ParseWhileStatement(labels, ok); |
4779 case Token::FOR: | 4784 case Token::FOR: |
| 4785 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() && |
| 4786 PeekAhead() == Token::AWAIT)) { |
| 4787 return ParseForAwaitStatement(labels, ok); |
| 4788 } |
4780 return ParseForStatement(labels, ok); | 4789 return ParseForStatement(labels, ok); |
4781 case Token::CONTINUE: | 4790 case Token::CONTINUE: |
4782 case Token::BREAK: | 4791 case Token::BREAK: |
4783 case Token::RETURN: | 4792 case Token::RETURN: |
4784 case Token::THROW: | 4793 case Token::THROW: |
4785 case Token::TRY: { | 4794 case Token::TRY: { |
4786 // These statements must have their labels preserved in an enclosing | 4795 // These statements must have their labels preserved in an enclosing |
4787 // block, as the corresponding AST nodes do not currently store their | 4796 // block, as the corresponding AST nodes do not currently store their |
4788 // labels. | 4797 // labels. |
4789 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4798 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5667 block->statements()->Add(loop, zone()); | 5676 block->statements()->Add(loop, zone()); |
5668 block->set_scope(for_scope); | 5677 block->set_scope(for_scope); |
5669 loop->Initialize(init, cond, next, body); | 5678 loop->Initialize(init, cond, next, body); |
5670 return block; | 5679 return block; |
5671 } | 5680 } |
5672 | 5681 |
5673 loop->Initialize(init, cond, next, body); | 5682 loop->Initialize(init, cond, next, body); |
5674 return loop; | 5683 return loop; |
5675 } | 5684 } |
5676 | 5685 |
| 5686 template <typename Impl> |
| 5687 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( |
| 5688 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 5689 // for await '(' ForDeclaration of AssignmentExpression ')' |
| 5690 DCHECK(is_async_function()); |
| 5691 DCHECK(allow_harmony_async_iteration()); |
| 5692 |
| 5693 int stmt_pos = peek_position(); |
| 5694 |
| 5695 ForInfo for_info(this); |
| 5696 for_info.mode = ForEachStatement::ITERATE; |
| 5697 |
| 5698 // Create an in-between scope for let-bound iteration variables. |
| 5699 BlockState for_state(zone(), &scope_state_); |
| 5700 Expect(Token::FOR, CHECK_OK); |
| 5701 Expect(Token::AWAIT, CHECK_OK); |
| 5702 Expect(Token::LPAREN, CHECK_OK); |
| 5703 for_state.set_start_position(scanner()->location().beg_pos); |
| 5704 for_state.set_is_hidden(); |
| 5705 |
| 5706 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); |
| 5707 typename Types::Target target(this, loop); |
| 5708 |
| 5709 ExpressionT each_variable = impl()->EmptyExpression(); |
| 5710 |
| 5711 bool has_declarations = false; |
| 5712 |
| 5713 switch (peek()) { |
| 5714 case Token::LET: |
| 5715 if (!IsNextLetKeyword()) goto parse_lhs; |
| 5716 /* falls through */ |
| 5717 case Token::VAR: |
| 5718 case Token::CONST: { |
| 5719 // The initializer contains declarations |
| 5720 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')' |
| 5721 // Statement |
| 5722 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')' |
| 5723 // Statement |
| 5724 has_declarations = true; |
| 5725 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, |
| 5726 nullptr, CHECK_OK); |
| 5727 for_info.position = scanner()->location().beg_pos; |
| 5728 |
| 5729 // Only a single declaration is allowed in for-await-of loops |
| 5730 if (for_info.parsing_result.declarations.length() != 1) { |
| 5731 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc, |
| 5732 MessageTemplate::kForInOfLoopMultiBindings, |
| 5733 "for-await-of"); |
| 5734 *ok = false; |
| 5735 return impl()->NullStatement(); |
| 5736 } |
| 5737 |
| 5738 // for-await-of's declarations do not permit initializers. |
| 5739 if (for_info.parsing_result.first_initializer_loc.IsValid()) { |
| 5740 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc, |
| 5741 MessageTemplate::kForInOfLoopInitializer, |
| 5742 "for-await-of"); |
| 5743 *ok = false; |
| 5744 return impl()->NullStatement(); |
| 5745 } |
| 5746 break; |
| 5747 } |
| 5748 |
| 5749 default: |
| 5750 parse_lhs : { |
| 5751 // The initializer does not contain declarations. |
| 5752 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')' |
| 5753 // Statement |
| 5754 int lhs_beg_pos = peek_position(); |
| 5755 ExpressionClassifier classifier(this); |
| 5756 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK); |
| 5757 int lhs_end_pos = scanner()->location().end_pos; |
| 5758 |
| 5759 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) { |
| 5760 ValidateAssignmentPattern(CHECK_OK); |
| 5761 } else { |
| 5762 impl()->RewriteNonPattern(CHECK_OK); |
| 5763 each_variable = impl()->CheckAndRewriteReferenceExpression( |
| 5764 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, |
| 5765 kSyntaxError, CHECK_OK); |
| 5766 } |
| 5767 } break; |
| 5768 } |
| 5769 |
| 5770 ExpectContextualKeyword(CStrVector("of"), CHECK_OK); |
| 5771 int each_keyword_pos = scanner()->location().beg_pos; |
| 5772 |
| 5773 const bool kAllowIn = true; |
| 5774 ExpressionT iterable = impl()->EmptyExpression(); |
| 5775 |
| 5776 { |
| 5777 ExpressionClassifier classifier(this); |
| 5778 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK); |
| 5779 impl()->RewriteNonPattern(CHECK_OK); |
| 5780 } |
| 5781 |
| 5782 Expect(Token::RPAREN, CHECK_OK); |
| 5783 |
| 5784 StatementT final_loop = impl()->NullStatement(); |
| 5785 { |
| 5786 ReturnExprScope no_tail_calls(function_state_, |
| 5787 ReturnExprContext::kInsideForInOfBody); |
| 5788 BlockState block_state(zone(), &scope_state_); |
| 5789 block_state.set_start_position(scanner()->location().beg_pos); |
| 5790 |
| 5791 // For legacy compat reasons, give for loops similar treatment to |
| 5792 // if statements in allowing a function declaration for a body |
| 5793 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
| 5794 block_state.set_end_position(scanner()->location().end_pos); |
| 5795 |
| 5796 if (has_declarations) { |
| 5797 BlockT body_block = impl()->NullBlock(); |
| 5798 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, |
| 5799 &each_variable, CHECK_OK); |
| 5800 body_block->statements()->Add(body, zone()); |
| 5801 body_block->set_scope(block_state.FinalizedBlockScope()); |
| 5802 for_state.set_end_position(scanner()->location().end_pos); |
| 5803 |
| 5804 const bool finalize = true; |
| 5805 final_loop = impl()->InitializeForOfStatement( |
| 5806 loop, each_variable, iterable, body_block, finalize, |
| 5807 IteratorType::kAsync, each_keyword_pos); |
| 5808 } else { |
| 5809 const bool finalize = true; |
| 5810 final_loop = impl()->InitializeForOfStatement( |
| 5811 loop, each_variable, iterable, body, finalize, IteratorType::kAsync, |
| 5812 each_keyword_pos); |
| 5813 |
| 5814 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5815 DCHECK_NULL(for_scope); |
| 5816 USE(for_scope); |
| 5817 Scope* block_scope = block_state.FinalizedBlockScope(); |
| 5818 DCHECK_NULL(block_scope); |
| 5819 USE(block_scope); |
| 5820 return final_loop; |
| 5821 } |
| 5822 } |
| 5823 |
| 5824 DCHECK(has_declarations); |
| 5825 BlockT init_block = |
| 5826 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok); |
| 5827 |
| 5828 for_state.set_end_position(scanner()->location().end_pos); |
| 5829 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5830 // Parsed for-in loop w/ variable declarations. |
| 5831 if (!impl()->IsNullStatement(init_block)) { |
| 5832 init_block->statements()->Add(final_loop, zone()); |
| 5833 init_block->set_scope(for_scope); |
| 5834 return init_block; |
| 5835 } |
| 5836 DCHECK_NULL(for_scope); |
| 5837 return final_loop; |
| 5838 } |
| 5839 |
5677 #undef CHECK_OK | 5840 #undef CHECK_OK |
5678 #undef CHECK_OK_CUSTOM | 5841 #undef CHECK_OK_CUSTOM |
5679 | 5842 |
5680 template <typename Impl> | 5843 template <typename Impl> |
5681 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5844 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
5682 Token::Value property) { | 5845 Token::Value property) { |
5683 if (property == Token::SMI || property == Token::NUMBER) return; | 5846 if (property == Token::SMI || property == Token::NUMBER) return; |
5684 | 5847 |
5685 if (IsProto()) { | 5848 if (IsProto()) { |
5686 if (has_seen_proto_) { | 5849 if (has_seen_proto_) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5726 return; | 5889 return; |
5727 } | 5890 } |
5728 } | 5891 } |
5729 | 5892 |
5730 #undef CHECK_OK_VOID | 5893 #undef CHECK_OK_VOID |
5731 | 5894 |
5732 } // namespace internal | 5895 } // namespace internal |
5733 } // namespace v8 | 5896 } // namespace v8 |
5734 | 5897 |
5735 #endif // V8_PARSING_PARSER_BASE_H | 5898 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |