| 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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 stack_overflow_(false), | 211 stack_overflow_(false), |
| 212 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), | 212 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), |
| 213 function_literal_id_(0), | 213 function_literal_id_(0), |
| 214 allow_natives_(false), | 214 allow_natives_(false), |
| 215 allow_tailcalls_(false), | 215 allow_tailcalls_(false), |
| 216 allow_harmony_do_expressions_(false), | 216 allow_harmony_do_expressions_(false), |
| 217 allow_harmony_function_sent_(false), | 217 allow_harmony_function_sent_(false), |
| 218 allow_harmony_restrictive_generators_(false), | 218 allow_harmony_restrictive_generators_(false), |
| 219 allow_harmony_trailing_commas_(false), | 219 allow_harmony_trailing_commas_(false), |
| 220 allow_harmony_class_fields_(false), | 220 allow_harmony_class_fields_(false), |
| 221 allow_harmony_object_rest_spread_(false) {} | 221 allow_harmony_object_rest_spread_(false), |
| 222 allow_harmony_async_iteration_(false) {} |
| 222 | 223 |
| 223 #define ALLOW_ACCESSORS(name) \ | 224 #define ALLOW_ACCESSORS(name) \ |
| 224 bool allow_##name() const { return allow_##name##_; } \ | 225 bool allow_##name() const { return allow_##name##_; } \ |
| 225 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | 226 void set_allow_##name(bool allow) { allow_##name##_ = allow; } |
| 226 | 227 |
| 227 ALLOW_ACCESSORS(natives); | 228 ALLOW_ACCESSORS(natives); |
| 228 ALLOW_ACCESSORS(tailcalls); | 229 ALLOW_ACCESSORS(tailcalls); |
| 229 ALLOW_ACCESSORS(harmony_do_expressions); | 230 ALLOW_ACCESSORS(harmony_do_expressions); |
| 230 ALLOW_ACCESSORS(harmony_function_sent); | 231 ALLOW_ACCESSORS(harmony_function_sent); |
| 231 ALLOW_ACCESSORS(harmony_restrictive_generators); | 232 ALLOW_ACCESSORS(harmony_restrictive_generators); |
| 232 ALLOW_ACCESSORS(harmony_trailing_commas); | 233 ALLOW_ACCESSORS(harmony_trailing_commas); |
| 233 ALLOW_ACCESSORS(harmony_class_fields); | 234 ALLOW_ACCESSORS(harmony_class_fields); |
| 234 ALLOW_ACCESSORS(harmony_object_rest_spread); | 235 ALLOW_ACCESSORS(harmony_object_rest_spread); |
| 236 ALLOW_ACCESSORS(harmony_async_iteration); |
| 235 | 237 |
| 236 #undef ALLOW_ACCESSORS | 238 #undef ALLOW_ACCESSORS |
| 237 | 239 |
| 238 uintptr_t stack_limit() const { return stack_limit_; } | 240 uintptr_t stack_limit() const { return stack_limit_; } |
| 239 | 241 |
| 240 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } | 242 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } |
| 241 | 243 |
| 242 void set_default_eager_compile_hint( | 244 void set_default_eager_compile_hint( |
| 243 FunctionLiteral::EagerCompileHint eager_compile_hint) { | 245 FunctionLiteral::EagerCompileHint eager_compile_hint) { |
| 244 default_eager_compile_hint_ = eager_compile_hint; | 246 default_eager_compile_hint_ = eager_compile_hint; |
| (...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 bool* ok); | 1285 bool* ok); |
| 1284 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, | 1286 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, |
| 1285 bool* ok); | 1287 bool* ok); |
| 1286 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, | 1288 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, |
| 1287 bool* ok); | 1289 bool* ok); |
| 1288 StatementT ParseThrowStatement(bool* ok); | 1290 StatementT ParseThrowStatement(bool* ok); |
| 1289 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, | 1291 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, |
| 1290 bool* ok); | 1292 bool* ok); |
| 1291 StatementT ParseTryStatement(bool* ok); | 1293 StatementT ParseTryStatement(bool* ok); |
| 1292 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); | 1294 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); |
| 1295 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels, |
| 1296 bool* ok); |
| 1293 | 1297 |
| 1294 bool IsNextLetKeyword(); | 1298 bool IsNextLetKeyword(); |
| 1295 bool IsTrivialExpression(); | 1299 bool IsTrivialExpression(); |
| 1296 | 1300 |
| 1297 // Checks if the expression is a valid reference expression (e.g., on the | 1301 // Checks if the expression is a valid reference expression (e.g., on the |
| 1298 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1302 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 1299 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1303 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 1300 ExpressionT CheckAndRewriteReferenceExpression( | 1304 ExpressionT CheckAndRewriteReferenceExpression( |
| 1301 ExpressionT expression, int beg_pos, int end_pos, | 1305 ExpressionT expression, int beg_pos, int end_pos, |
| 1302 MessageTemplate::Template message, bool* ok); | 1306 MessageTemplate::Template message, bool* ok); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 int function_literal_id_; | 1455 int function_literal_id_; |
| 1452 | 1456 |
| 1453 bool allow_natives_; | 1457 bool allow_natives_; |
| 1454 bool allow_tailcalls_; | 1458 bool allow_tailcalls_; |
| 1455 bool allow_harmony_do_expressions_; | 1459 bool allow_harmony_do_expressions_; |
| 1456 bool allow_harmony_function_sent_; | 1460 bool allow_harmony_function_sent_; |
| 1457 bool allow_harmony_restrictive_generators_; | 1461 bool allow_harmony_restrictive_generators_; |
| 1458 bool allow_harmony_trailing_commas_; | 1462 bool allow_harmony_trailing_commas_; |
| 1459 bool allow_harmony_class_fields_; | 1463 bool allow_harmony_class_fields_; |
| 1460 bool allow_harmony_object_rest_spread_; | 1464 bool allow_harmony_object_rest_spread_; |
| 1465 bool allow_harmony_async_iteration_; |
| 1461 | 1466 |
| 1462 friend class DiscardableZoneScope; | 1467 friend class DiscardableZoneScope; |
| 1463 }; | 1468 }; |
| 1464 | 1469 |
| 1465 template <typename Impl> | 1470 template <typename Impl> |
| 1466 ParserBase<Impl>::FunctionState::FunctionState( | 1471 ParserBase<Impl>::FunctionState::FunctionState( |
| 1467 FunctionState** function_state_stack, ScopeState** scope_stack, | 1472 FunctionState** function_state_stack, ScopeState** scope_stack, |
| 1468 DeclarationScope* scope) | 1473 DeclarationScope* scope) |
| 1469 : ScopeState(scope_stack, scope), | 1474 : ScopeState(scope_stack, scope), |
| 1470 next_materialized_literal_index_(0), | 1475 next_materialized_literal_index_(0), |
| (...skipping 3155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4626 case Token::SEMICOLON: | 4631 case Token::SEMICOLON: |
| 4627 Next(); | 4632 Next(); |
| 4628 return factory()->NewEmptyStatement(kNoSourcePosition); | 4633 return factory()->NewEmptyStatement(kNoSourcePosition); |
| 4629 case Token::IF: | 4634 case Token::IF: |
| 4630 return ParseIfStatement(labels, ok); | 4635 return ParseIfStatement(labels, ok); |
| 4631 case Token::DO: | 4636 case Token::DO: |
| 4632 return ParseDoWhileStatement(labels, ok); | 4637 return ParseDoWhileStatement(labels, ok); |
| 4633 case Token::WHILE: | 4638 case Token::WHILE: |
| 4634 return ParseWhileStatement(labels, ok); | 4639 return ParseWhileStatement(labels, ok); |
| 4635 case Token::FOR: | 4640 case Token::FOR: |
| 4641 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() && |
| 4642 PeekAhead() == Token::AWAIT)) { |
| 4643 return ParseForAwaitStatement(labels, ok); |
| 4644 } |
| 4636 return ParseForStatement(labels, ok); | 4645 return ParseForStatement(labels, ok); |
| 4637 case Token::CONTINUE: | 4646 case Token::CONTINUE: |
| 4638 case Token::BREAK: | 4647 case Token::BREAK: |
| 4639 case Token::RETURN: | 4648 case Token::RETURN: |
| 4640 case Token::THROW: | 4649 case Token::THROW: |
| 4641 case Token::TRY: { | 4650 case Token::TRY: { |
| 4642 // These statements must have their labels preserved in an enclosing | 4651 // These statements must have their labels preserved in an enclosing |
| 4643 // block, as the corresponding AST nodes do not currently store their | 4652 // block, as the corresponding AST nodes do not currently store their |
| 4644 // labels. | 4653 // labels. |
| 4645 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4654 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
| (...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5503 block->set_scope(for_scope); | 5512 block->set_scope(for_scope); |
| 5504 loop->Initialize(init, cond, next, body); | 5513 loop->Initialize(init, cond, next, body); |
| 5505 return block; | 5514 return block; |
| 5506 } else { | 5515 } else { |
| 5507 loop->Initialize(init, cond, next, body); | 5516 loop->Initialize(init, cond, next, body); |
| 5508 return loop; | 5517 return loop; |
| 5509 } | 5518 } |
| 5510 } | 5519 } |
| 5511 } | 5520 } |
| 5512 | 5521 |
| 5522 template <typename Impl> |
| 5523 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( |
| 5524 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 5525 // for await '(' ForDeclaration of AssignmentExpression ')' |
| 5526 DCHECK(is_async_function()); |
| 5527 DCHECK(allow_harmony_async_iteration()); |
| 5528 |
| 5529 int stmt_pos = peek_position(); |
| 5530 bool bound_names_are_lexical = false; |
| 5531 |
| 5532 ForInfo for_info(this); |
| 5533 for_info.mode = ForEachStatement::ITERATE; |
| 5534 |
| 5535 // Create an in-between scope for let-bound iteration variables. |
| 5536 BlockState for_state(zone(), &scope_state_); |
| 5537 Expect(Token::FOR, CHECK_OK); |
| 5538 Expect(Token::AWAIT, CHECK_OK); |
| 5539 Expect(Token::LPAREN, CHECK_OK); |
| 5540 for_state.set_start_position(scanner()->location().beg_pos); |
| 5541 for_state.set_is_hidden(); |
| 5542 |
| 5543 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); |
| 5544 typename Types::Target target(this, loop); |
| 5545 |
| 5546 ExpressionT each_variable = impl()->EmptyExpression(); |
| 5547 |
| 5548 bool has_declarations = false; |
| 5549 |
| 5550 switch (peek()) { |
| 5551 case Token::LET: |
| 5552 if (!IsNextLetKeyword()) goto parse_lhs; |
| 5553 /* falls through */ |
| 5554 case Token::VAR: |
| 5555 case Token::CONST: { |
| 5556 // The initializer contains declarations |
| 5557 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')' |
| 5558 // Statement |
| 5559 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')' |
| 5560 // Statement |
| 5561 has_declarations = true; |
| 5562 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, |
| 5563 nullptr, CHECK_OK); |
| 5564 bound_names_are_lexical = |
| 5565 IsLexicalVariableMode(for_info.parsing_result.descriptor.mode); |
| 5566 |
| 5567 for_info.position = scanner()->location().beg_pos; |
| 5568 |
| 5569 // Only a single declaration is allowed in for-await-of loops |
| 5570 if (for_info.parsing_result.declarations.length() != 1) { |
| 5571 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc, |
| 5572 MessageTemplate::kForInOfLoopMultiBindings, |
| 5573 "for-await-of"); |
| 5574 *ok = false; |
| 5575 return impl()->NullStatement(); |
| 5576 } |
| 5577 |
| 5578 // for-await-of's declarations do not permit initializers. |
| 5579 if (for_info.parsing_result.first_initializer_loc.IsValid()) { |
| 5580 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc, |
| 5581 MessageTemplate::kForInOfLoopInitializer, |
| 5582 "for-await-of"); |
| 5583 *ok = false; |
| 5584 return impl()->NullStatement(); |
| 5585 } |
| 5586 break; |
| 5587 } |
| 5588 |
| 5589 default: |
| 5590 parse_lhs : { |
| 5591 // The initializer does not contain declarations. |
| 5592 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')' |
| 5593 // Statement |
| 5594 int lhs_beg_pos = peek_position(); |
| 5595 ExpressionClassifier classifier(this); |
| 5596 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK); |
| 5597 int lhs_end_pos = scanner()->location().end_pos; |
| 5598 |
| 5599 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) { |
| 5600 ValidateAssignmentPattern(CHECK_OK); |
| 5601 } else { |
| 5602 impl()->RewriteNonPattern(CHECK_OK); |
| 5603 each_variable = impl()->CheckAndRewriteReferenceExpression( |
| 5604 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, |
| 5605 kSyntaxError, CHECK_OK); |
| 5606 } |
| 5607 } break; |
| 5608 } |
| 5609 |
| 5610 ExpectContextualKeyword(CStrVector("of"), CHECK_OK); |
| 5611 int each_keyword_pos = scanner()->location().beg_pos; |
| 5612 |
| 5613 const bool kAllowIn = true; |
| 5614 ExpressionT iterable = impl()->EmptyExpression(); |
| 5615 |
| 5616 { |
| 5617 ExpressionClassifier classifier(this); |
| 5618 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK); |
| 5619 impl()->RewriteNonPattern(CHECK_OK); |
| 5620 } |
| 5621 |
| 5622 Expect(Token::RPAREN, CHECK_OK); |
| 5623 |
| 5624 { |
| 5625 ReturnExprScope no_tail_calls(function_state_, |
| 5626 ReturnExprContext::kInsideForInOfBody); |
| 5627 BlockState block_state(zone(), &scope_state_); |
| 5628 block_state.set_start_position(scanner()->location().beg_pos); |
| 5629 |
| 5630 // For legacy compat reasons, give for loops similar treatment to |
| 5631 // if statements in allowing a function declaration for a body |
| 5632 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
| 5633 block_state.set_end_position(scanner()->location().end_pos); |
| 5634 |
| 5635 if (has_declarations) { |
| 5636 BlockT body_block = impl()->NullBlock(); |
| 5637 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, |
| 5638 &each_variable, CHECK_OK); |
| 5639 body_block->statements()->Add(body, zone()); |
| 5640 body_block->set_scope(block_state.FinalizedBlockScope()); |
| 5641 for_state.set_end_position(scanner()->location().end_pos); |
| 5642 |
| 5643 StatementT final_loop = impl()->InitializeForAwaitOfStatement( |
| 5644 loop, each_variable, iterable, body_block, each_keyword_pos); |
| 5645 |
| 5646 BlockT init_block = |
| 5647 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok); |
| 5648 |
| 5649 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5650 // Parsed for-in loop w/ variable declarations. |
| 5651 if (!impl()->IsNullStatement(init_block)) { |
| 5652 init_block->statements()->Add(final_loop, zone()); |
| 5653 init_block->set_scope(for_scope); |
| 5654 return init_block; |
| 5655 } else { |
| 5656 DCHECK_NULL(for_scope); |
| 5657 return final_loop; |
| 5658 } |
| 5659 } else { |
| 5660 StatementT final_loop = impl()->InitializeForAwaitOfStatement( |
| 5661 loop, each_variable, iterable, body, each_keyword_pos); |
| 5662 |
| 5663 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5664 DCHECK_NULL(for_scope); |
| 5665 USE(for_scope); |
| 5666 Scope* block_scope = block_state.FinalizedBlockScope(); |
| 5667 DCHECK_NULL(block_scope); |
| 5668 USE(block_scope); |
| 5669 return final_loop; |
| 5670 } |
| 5671 |
| 5672 UNREACHABLE(); |
| 5673 return impl()->NullStatement(); |
| 5674 } |
| 5675 } |
| 5676 |
| 5513 #undef CHECK_OK | 5677 #undef CHECK_OK |
| 5514 #undef CHECK_OK_CUSTOM | 5678 #undef CHECK_OK_CUSTOM |
| 5515 | 5679 |
| 5516 template <typename Impl> | 5680 template <typename Impl> |
| 5517 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5681 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
| 5518 Token::Value property) { | 5682 Token::Value property) { |
| 5519 if (property == Token::SMI || property == Token::NUMBER) return; | 5683 if (property == Token::SMI || property == Token::NUMBER) return; |
| 5520 | 5684 |
| 5521 if (IsProto()) { | 5685 if (IsProto()) { |
| 5522 if (has_seen_proto_) { | 5686 if (has_seen_proto_) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5561 has_seen_constructor_ = true; | 5725 has_seen_constructor_ = true; |
| 5562 return; | 5726 return; |
| 5563 } | 5727 } |
| 5564 } | 5728 } |
| 5565 | 5729 |
| 5566 | 5730 |
| 5567 } // namespace internal | 5731 } // namespace internal |
| 5568 } // namespace v8 | 5732 } // namespace v8 |
| 5569 | 5733 |
| 5570 #endif // V8_PARSING_PARSER_BASE_H | 5734 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |