| 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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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_dynamic_import_(false) {} | 228 allow_harmony_dynamic_import_(false), |
| 229 allow_harmony_async_iteration_(false) {} |
| 229 | 230 |
| 230 #define ALLOW_ACCESSORS(name) \ | 231 #define ALLOW_ACCESSORS(name) \ |
| 231 bool allow_##name() const { return allow_##name##_; } \ | 232 bool allow_##name() const { return allow_##name##_; } \ |
| 232 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | 233 void set_allow_##name(bool allow) { allow_##name##_ = allow; } |
| 233 | 234 |
| 234 ALLOW_ACCESSORS(natives); | 235 ALLOW_ACCESSORS(natives); |
| 235 ALLOW_ACCESSORS(tailcalls); | 236 ALLOW_ACCESSORS(tailcalls); |
| 236 ALLOW_ACCESSORS(harmony_do_expressions); | 237 ALLOW_ACCESSORS(harmony_do_expressions); |
| 237 ALLOW_ACCESSORS(harmony_function_sent); | 238 ALLOW_ACCESSORS(harmony_function_sent); |
| 238 ALLOW_ACCESSORS(harmony_restrictive_generators); | 239 ALLOW_ACCESSORS(harmony_restrictive_generators); |
| 239 ALLOW_ACCESSORS(harmony_trailing_commas); | 240 ALLOW_ACCESSORS(harmony_trailing_commas); |
| 240 ALLOW_ACCESSORS(harmony_class_fields); | 241 ALLOW_ACCESSORS(harmony_class_fields); |
| 241 ALLOW_ACCESSORS(harmony_object_rest_spread); | 242 ALLOW_ACCESSORS(harmony_object_rest_spread); |
| 242 ALLOW_ACCESSORS(harmony_dynamic_import); | 243 ALLOW_ACCESSORS(harmony_dynamic_import); |
| 244 ALLOW_ACCESSORS(harmony_async_iteration); |
| 243 | 245 |
| 244 #undef ALLOW_ACCESSORS | 246 #undef ALLOW_ACCESSORS |
| 245 | 247 |
| 246 uintptr_t stack_limit() const { return stack_limit_; } | 248 uintptr_t stack_limit() const { return stack_limit_; } |
| 247 | 249 |
| 248 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } | 250 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } |
| 249 | 251 |
| 250 void set_default_eager_compile_hint( | 252 void set_default_eager_compile_hint( |
| 251 FunctionLiteral::EagerCompileHint eager_compile_hint) { | 253 FunctionLiteral::EagerCompileHint eager_compile_hint) { |
| 252 default_eager_compile_hint_ = eager_compile_hint; | 254 default_eager_compile_hint_ = eager_compile_hint; |
| (...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1285 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, | 1287 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, |
| 1286 ForInfo* for_info, BlockState* for_state, | 1288 ForInfo* for_info, BlockState* for_state, |
| 1287 ZoneList<const AstRawString*>* labels, bool* ok); | 1289 ZoneList<const AstRawString*>* labels, bool* ok); |
| 1288 | 1290 |
| 1289 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' | 1291 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' |
| 1290 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, | 1292 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, |
| 1291 bool bound_names_are_lexical, | 1293 bool bound_names_are_lexical, |
| 1292 ForInfo* for_info, BlockState* for_state, | 1294 ForInfo* for_info, BlockState* for_state, |
| 1293 ZoneList<const AstRawString*>* labels, | 1295 ZoneList<const AstRawString*>* labels, |
| 1294 bool* ok); | 1296 bool* ok); |
| 1297 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels, |
| 1298 bool* ok); |
| 1295 | 1299 |
| 1296 bool IsNextLetKeyword(); | 1300 bool IsNextLetKeyword(); |
| 1297 bool IsTrivialExpression(); | 1301 bool IsTrivialExpression(); |
| 1298 | 1302 |
| 1299 // Checks if the expression is a valid reference expression (e.g., on the | 1303 // Checks if the expression is a valid reference expression (e.g., on the |
| 1300 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1304 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 1301 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1305 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 1302 ExpressionT CheckAndRewriteReferenceExpression( | 1306 ExpressionT CheckAndRewriteReferenceExpression( |
| 1303 ExpressionT expression, int beg_pos, int end_pos, | 1307 ExpressionT expression, int beg_pos, int end_pos, |
| 1304 MessageTemplate::Template message, bool* ok); | 1308 MessageTemplate::Template message, bool* ok); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1481 | 1485 |
| 1482 bool allow_natives_; | 1486 bool allow_natives_; |
| 1483 bool allow_tailcalls_; | 1487 bool allow_tailcalls_; |
| 1484 bool allow_harmony_do_expressions_; | 1488 bool allow_harmony_do_expressions_; |
| 1485 bool allow_harmony_function_sent_; | 1489 bool allow_harmony_function_sent_; |
| 1486 bool allow_harmony_restrictive_generators_; | 1490 bool allow_harmony_restrictive_generators_; |
| 1487 bool allow_harmony_trailing_commas_; | 1491 bool allow_harmony_trailing_commas_; |
| 1488 bool allow_harmony_class_fields_; | 1492 bool allow_harmony_class_fields_; |
| 1489 bool allow_harmony_object_rest_spread_; | 1493 bool allow_harmony_object_rest_spread_; |
| 1490 bool allow_harmony_dynamic_import_; | 1494 bool allow_harmony_dynamic_import_; |
| 1495 bool allow_harmony_async_iteration_; |
| 1491 | 1496 |
| 1492 friend class DiscardableZoneScope; | 1497 friend class DiscardableZoneScope; |
| 1493 }; | 1498 }; |
| 1494 | 1499 |
| 1495 template <typename Impl> | 1500 template <typename Impl> |
| 1496 ParserBase<Impl>::FunctionState::FunctionState( | 1501 ParserBase<Impl>::FunctionState::FunctionState( |
| 1497 FunctionState** function_state_stack, ScopeState** scope_stack, | 1502 FunctionState** function_state_stack, ScopeState** scope_stack, |
| 1498 DeclarationScope* scope) | 1503 DeclarationScope* scope) |
| 1499 : ScopeState(scope_stack, scope), | 1504 : ScopeState(scope_stack, scope), |
| 1500 next_materialized_literal_index_(0), | 1505 next_materialized_literal_index_(0), |
| (...skipping 3287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4788 case Token::SEMICOLON: | 4793 case Token::SEMICOLON: |
| 4789 Next(); | 4794 Next(); |
| 4790 return factory()->NewEmptyStatement(kNoSourcePosition); | 4795 return factory()->NewEmptyStatement(kNoSourcePosition); |
| 4791 case Token::IF: | 4796 case Token::IF: |
| 4792 return ParseIfStatement(labels, ok); | 4797 return ParseIfStatement(labels, ok); |
| 4793 case Token::DO: | 4798 case Token::DO: |
| 4794 return ParseDoWhileStatement(labels, ok); | 4799 return ParseDoWhileStatement(labels, ok); |
| 4795 case Token::WHILE: | 4800 case Token::WHILE: |
| 4796 return ParseWhileStatement(labels, ok); | 4801 return ParseWhileStatement(labels, ok); |
| 4797 case Token::FOR: | 4802 case Token::FOR: |
| 4803 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() && |
| 4804 PeekAhead() == Token::AWAIT)) { |
| 4805 return ParseForAwaitStatement(labels, ok); |
| 4806 } |
| 4798 return ParseForStatement(labels, ok); | 4807 return ParseForStatement(labels, ok); |
| 4799 case Token::CONTINUE: | 4808 case Token::CONTINUE: |
| 4800 case Token::BREAK: | 4809 case Token::BREAK: |
| 4801 case Token::RETURN: | 4810 case Token::RETURN: |
| 4802 case Token::THROW: | 4811 case Token::THROW: |
| 4803 case Token::TRY: { | 4812 case Token::TRY: { |
| 4804 // These statements must have their labels preserved in an enclosing | 4813 // These statements must have their labels preserved in an enclosing |
| 4805 // block, as the corresponding AST nodes do not currently store their | 4814 // block, as the corresponding AST nodes do not currently store their |
| 4806 // labels. | 4815 // labels. |
| 4807 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4816 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5694 } | 5703 } |
| 5695 | 5704 |
| 5696 template <typename Impl> | 5705 template <typename Impl> |
| 5697 void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) { | 5706 void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) { |
| 5698 if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) { | 5707 if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) { |
| 5699 var->set_maybe_assigned(); | 5708 var->set_maybe_assigned(); |
| 5700 } | 5709 } |
| 5701 } | 5710 } |
| 5702 | 5711 |
| 5703 template <typename Impl> | 5712 template <typename Impl> |
| 5713 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( |
| 5714 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 5715 // for await '(' ForDeclaration of AssignmentExpression ')' |
| 5716 DCHECK(is_async_function()); |
| 5717 DCHECK(allow_harmony_async_iteration()); |
| 5718 |
| 5719 int stmt_pos = peek_position(); |
| 5720 |
| 5721 ForInfo for_info(this); |
| 5722 for_info.mode = ForEachStatement::ITERATE; |
| 5723 |
| 5724 // Create an in-between scope for let-bound iteration variables. |
| 5725 BlockState for_state(zone(), &scope_state_); |
| 5726 Expect(Token::FOR, CHECK_OK); |
| 5727 Expect(Token::AWAIT, CHECK_OK); |
| 5728 Expect(Token::LPAREN, CHECK_OK); |
| 5729 for_state.set_start_position(scanner()->location().beg_pos); |
| 5730 for_state.set_is_hidden(); |
| 5731 |
| 5732 auto loop = factory()->NewForOfStatement(labels, stmt_pos); |
| 5733 typename Types::Target target(this, loop); |
| 5734 |
| 5735 ExpressionT each_variable = impl()->EmptyExpression(); |
| 5736 |
| 5737 bool has_declarations = false; |
| 5738 |
| 5739 if (peek() == Token::VAR || peek() == Token::CONST || |
| 5740 (peek() == Token::LET && IsNextLetKeyword())) { |
| 5741 // The initializer contains declarations |
| 5742 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')' |
| 5743 // Statement |
| 5744 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')' |
| 5745 // Statement |
| 5746 has_declarations = true; |
| 5747 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, nullptr, |
| 5748 CHECK_OK); |
| 5749 for_info.position = scanner()->location().beg_pos; |
| 5750 |
| 5751 // Only a single declaration is allowed in for-await-of loops |
| 5752 if (for_info.parsing_result.declarations.length() != 1) { |
| 5753 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc, |
| 5754 MessageTemplate::kForInOfLoopMultiBindings, |
| 5755 "for-await-of"); |
| 5756 *ok = false; |
| 5757 return impl()->NullStatement(); |
| 5758 } |
| 5759 |
| 5760 // for-await-of's declarations do not permit initializers. |
| 5761 if (for_info.parsing_result.first_initializer_loc.IsValid()) { |
| 5762 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc, |
| 5763 MessageTemplate::kForInOfLoopInitializer, |
| 5764 "for-await-of"); |
| 5765 *ok = false; |
| 5766 return impl()->NullStatement(); |
| 5767 } |
| 5768 } else { |
| 5769 // The initializer does not contain declarations. |
| 5770 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')' |
| 5771 // Statement |
| 5772 int lhs_beg_pos = peek_position(); |
| 5773 ExpressionClassifier classifier(this); |
| 5774 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK); |
| 5775 int lhs_end_pos = scanner()->location().end_pos; |
| 5776 |
| 5777 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) { |
| 5778 ValidateAssignmentPattern(CHECK_OK); |
| 5779 } else { |
| 5780 impl()->RewriteNonPattern(CHECK_OK); |
| 5781 each_variable = impl()->CheckAndRewriteReferenceExpression( |
| 5782 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, |
| 5783 kSyntaxError, CHECK_OK); |
| 5784 } |
| 5785 } |
| 5786 |
| 5787 ExpectContextualKeyword(CStrVector("of"), CHECK_OK); |
| 5788 int each_keyword_pos = scanner()->location().beg_pos; |
| 5789 |
| 5790 const bool kAllowIn = true; |
| 5791 ExpressionT iterable = impl()->EmptyExpression(); |
| 5792 |
| 5793 { |
| 5794 ExpressionClassifier classifier(this); |
| 5795 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK); |
| 5796 impl()->RewriteNonPattern(CHECK_OK); |
| 5797 } |
| 5798 |
| 5799 Expect(Token::RPAREN, CHECK_OK); |
| 5800 |
| 5801 StatementT final_loop = impl()->NullStatement(); |
| 5802 { |
| 5803 ReturnExprScope no_tail_calls(function_state_, |
| 5804 ReturnExprContext::kInsideForInOfBody); |
| 5805 BlockState block_state(zone(), &scope_state_); |
| 5806 block_state.set_start_position(scanner()->location().beg_pos); |
| 5807 |
| 5808 const bool kDisallowLabelledFunctionStatement = true; |
| 5809 StatementT body = ParseScopedStatement( |
| 5810 nullptr, kDisallowLabelledFunctionStatement, CHECK_OK); |
| 5811 block_state.set_end_position(scanner()->location().end_pos); |
| 5812 |
| 5813 if (has_declarations) { |
| 5814 BlockT body_block = impl()->NullBlock(); |
| 5815 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, |
| 5816 &each_variable, CHECK_OK); |
| 5817 body_block->statements()->Add(body, zone()); |
| 5818 body_block->set_scope(block_state.FinalizedBlockScope()); |
| 5819 for_state.set_end_position(scanner()->location().end_pos); |
| 5820 |
| 5821 const bool finalize = true; |
| 5822 final_loop = impl()->InitializeForOfStatement( |
| 5823 loop, each_variable, iterable, body_block, finalize, |
| 5824 IteratorType::kAsync, each_keyword_pos); |
| 5825 } else { |
| 5826 const bool finalize = true; |
| 5827 final_loop = impl()->InitializeForOfStatement( |
| 5828 loop, each_variable, iterable, body, finalize, IteratorType::kAsync, |
| 5829 each_keyword_pos); |
| 5830 |
| 5831 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5832 DCHECK_NULL(for_scope); |
| 5833 USE(for_scope); |
| 5834 Scope* block_scope = block_state.FinalizedBlockScope(); |
| 5835 DCHECK_NULL(block_scope); |
| 5836 USE(block_scope); |
| 5837 return final_loop; |
| 5838 } |
| 5839 } |
| 5840 |
| 5841 DCHECK(has_declarations); |
| 5842 BlockT init_block = |
| 5843 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok); |
| 5844 |
| 5845 for_state.set_end_position(scanner()->location().end_pos); |
| 5846 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5847 // Parsed for-in loop w/ variable declarations. |
| 5848 if (!impl()->IsNullStatement(init_block)) { |
| 5849 init_block->statements()->Add(final_loop, zone()); |
| 5850 init_block->set_scope(for_scope); |
| 5851 return init_block; |
| 5852 } |
| 5853 DCHECK_NULL(for_scope); |
| 5854 return final_loop; |
| 5855 } |
| 5856 |
| 5857 template <typename Impl> |
| 5704 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5858 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
| 5705 Token::Value property) { | 5859 Token::Value property) { |
| 5706 if (property == Token::SMI || property == Token::NUMBER) return; | 5860 if (property == Token::SMI || property == Token::NUMBER) return; |
| 5707 | 5861 |
| 5708 if (IsProto()) { | 5862 if (IsProto()) { |
| 5709 if (has_seen_proto_) { | 5863 if (has_seen_proto_) { |
| 5710 this->parser()->classifier()->RecordExpressionError( | 5864 this->parser()->classifier()->RecordExpressionError( |
| 5711 this->scanner()->location(), MessageTemplate::kDuplicateProto); | 5865 this->scanner()->location(), MessageTemplate::kDuplicateProto); |
| 5712 return; | 5866 return; |
| 5713 } | 5867 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5751 } | 5905 } |
| 5752 | 5906 |
| 5753 #undef CHECK_OK | 5907 #undef CHECK_OK |
| 5754 #undef CHECK_OK_CUSTOM | 5908 #undef CHECK_OK_CUSTOM |
| 5755 #undef CHECK_OK_VOID | 5909 #undef CHECK_OK_VOID |
| 5756 | 5910 |
| 5757 } // namespace internal | 5911 } // namespace internal |
| 5758 } // namespace v8 | 5912 } // namespace v8 |
| 5759 | 5913 |
| 5760 #endif // V8_PARSING_PARSER_BASE_H | 5914 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |