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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 Expression* prop = | 499 Expression* prop = |
500 factory()->NewProperty(iterable, iterator_symbol_literal, pos); | 500 factory()->NewProperty(iterable, iterator_symbol_literal, pos); |
501 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone()); | 501 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone()); |
502 return factory()->NewCall(prop, args, pos); | 502 return factory()->NewCall(prop, args, pos); |
503 } | 503 } |
504 | 504 |
505 void Parser::MarkTailPosition(Expression* expression) { | 505 void Parser::MarkTailPosition(Expression* expression) { |
506 expression->MarkTail(); | 506 expression->MarkTail(); |
507 } | 507 } |
508 | 508 |
| 509 Expression* Parser::NewV8Intrinsic(const AstRawString* name, |
| 510 ZoneList<Expression*>* args, int pos, |
| 511 bool* ok) { |
| 512 if (extension_ != nullptr) { |
| 513 // The extension structures are only accessible while parsing the |
| 514 // very first time, not when reparsing because of lazy compilation. |
| 515 GetClosureScope()->ForceEagerCompilation(); |
| 516 } |
| 517 |
| 518 const Runtime::Function* function = Runtime::FunctionForName(name->string()); |
| 519 |
| 520 if (function != nullptr) { |
| 521 // Check for possible name clash. |
| 522 DCHECK_EQ(Context::kNotFound, |
| 523 Context::IntrinsicIndexForName(name->string())); |
| 524 // Check for built-in IS_VAR macro. |
| 525 if (function->function_id == Runtime::kIS_VAR) { |
| 526 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type); |
| 527 // %IS_VAR(x) evaluates to x if x is a variable, |
| 528 // leads to a parse error otherwise. Could be implemented as an |
| 529 // inline function %_IS_VAR(x) to eliminate this special case. |
| 530 if (args->length() == 1 && args->at(0)->AsVariableProxy() != nullptr) { |
| 531 return args->at(0); |
| 532 } else { |
| 533 ReportMessage(MessageTemplate::kNotIsvar); |
| 534 *ok = false; |
| 535 return nullptr; |
| 536 } |
| 537 } |
| 538 |
| 539 // Check that the expected number of arguments are being passed. |
| 540 if (function->nargs != -1 && function->nargs != args->length()) { |
| 541 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs); |
| 542 *ok = false; |
| 543 return nullptr; |
| 544 } |
| 545 |
| 546 return factory()->NewCallRuntime(function, args, pos); |
| 547 } |
| 548 |
| 549 int context_index = Context::IntrinsicIndexForName(name->string()); |
| 550 |
| 551 // Check that the function is defined. |
| 552 if (context_index == Context::kNotFound) { |
| 553 ReportMessage(MessageTemplate::kNotDefined, name); |
| 554 *ok = false; |
| 555 return nullptr; |
| 556 } |
| 557 |
| 558 return factory()->NewCallRuntime(context_index, args, pos); |
| 559 } |
| 560 |
509 Parser::Parser(ParseInfo* info) | 561 Parser::Parser(ParseInfo* info) |
510 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), | 562 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), |
511 info->extension(), info->ast_value_factory(), NULL), | 563 info->extension(), info->ast_value_factory(), NULL), |
512 scanner_(info->unicode_cache()), | 564 scanner_(info->unicode_cache()), |
513 reusable_preparser_(NULL), | 565 reusable_preparser_(NULL), |
514 original_scope_(NULL), | 566 original_scope_(NULL), |
515 target_stack_(NULL), | 567 target_stack_(NULL), |
516 compile_options_(info->compile_options()), | 568 compile_options_(info->compile_options()), |
517 cached_parse_data_(NULL), | 569 cached_parse_data_(NULL), |
518 total_preparse_skipped_(0), | 570 total_preparse_skipped_(0), |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 this->scope()->SetLanguageMode(info->language_mode()); | 752 this->scope()->SetLanguageMode(info->language_mode()); |
701 ParseStatementList(body, Token::EOS, &ok); | 753 ParseStatementList(body, Token::EOS, &ok); |
702 } | 754 } |
703 | 755 |
704 // The parser will peek but not consume EOS. Our scope logically goes all | 756 // The parser will peek but not consume EOS. Our scope logically goes all |
705 // the way to the EOS, though. | 757 // the way to the EOS, though. |
706 scope->set_end_position(scanner()->peek_location().beg_pos); | 758 scope->set_end_position(scanner()->peek_location().beg_pos); |
707 | 759 |
708 if (ok && is_strict(language_mode())) { | 760 if (ok && is_strict(language_mode())) { |
709 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 761 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
710 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, | 762 CheckDecimalLiteralWithLeadingZero(beg_pos, |
711 scanner()->location().end_pos); | 763 scanner()->location().end_pos); |
712 } | 764 } |
713 if (ok && is_sloppy(language_mode())) { | 765 if (ok && is_sloppy(language_mode())) { |
714 // TODO(littledan): Function bindings on the global object that modify | 766 // TODO(littledan): Function bindings on the global object that modify |
715 // pre-existing bindings should be made writable, enumerable and | 767 // pre-existing bindings should be made writable, enumerable and |
716 // nonconfigurable if possible, whereas this code will leave attributes | 768 // nonconfigurable if possible, whereas this code will leave attributes |
717 // unchanged if the property already exists. | 769 // unchanged if the property already exists. |
718 InsertSloppyBlockFunctionVarBindings(scope, &ok); | 770 InsertSloppyBlockFunctionVarBindings(scope, &ok); |
719 } | 771 } |
720 if (ok) { | 772 if (ok) { |
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1610 | 1662 |
1611 void Parser::DeclareAndInitializeVariables( | 1663 void Parser::DeclareAndInitializeVariables( |
1612 Block* block, const DeclarationDescriptor* declaration_descriptor, | 1664 Block* block, const DeclarationDescriptor* declaration_descriptor, |
1613 const DeclarationParsingResult::Declaration* declaration, | 1665 const DeclarationParsingResult::Declaration* declaration, |
1614 ZoneList<const AstRawString*>* names, bool* ok) { | 1666 ZoneList<const AstRawString*>* names, bool* ok) { |
1615 DCHECK_NOT_NULL(block); | 1667 DCHECK_NOT_NULL(block); |
1616 PatternRewriter::DeclareAndInitializeVariables( | 1668 PatternRewriter::DeclareAndInitializeVariables( |
1617 this, block, declaration_descriptor, declaration, names, ok); | 1669 this, block, declaration_descriptor, declaration, names, ok); |
1618 } | 1670 } |
1619 | 1671 |
1620 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | |
1621 ZoneList<const AstRawString*>* names, | |
1622 bool* ok) { | |
1623 // VariableStatement :: | |
1624 // VariableDeclarations ';' | |
1625 | |
1626 // The scope of a var declared variable anywhere inside a function | |
1627 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | |
1628 // transform a source-level var declaration into a (Function) Scope | |
1629 // declaration, and rewrite the source-level initialization into an assignment | |
1630 // statement. We use a block to collect multiple assignments. | |
1631 // | |
1632 // We mark the block as initializer block because we don't want the | |
1633 // rewriter to add a '.result' assignment to such a block (to get compliant | |
1634 // behavior for code such as print(eval('var x = 7')), and for cosmetic | |
1635 // reasons when pretty-printing. Also, unless an assignment (initialization) | |
1636 // is inside an initializer block, it is ignored. | |
1637 | |
1638 DeclarationParsingResult parsing_result; | |
1639 Block* result = | |
1640 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK); | |
1641 ExpectSemicolon(CHECK_OK); | |
1642 return result; | |
1643 } | |
1644 | |
1645 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | 1672 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, |
1646 const AstRawString* label) { | 1673 const AstRawString* label) { |
1647 DCHECK(label != NULL); | 1674 DCHECK(label != NULL); |
1648 if (labels != NULL) { | 1675 if (labels != NULL) { |
1649 for (int i = labels->length(); i-- > 0; ) { | 1676 for (int i = labels->length(); i-- > 0; ) { |
1650 if (labels->at(i) == label) { | 1677 if (labels->at(i) == label) { |
1651 return true; | 1678 return true; |
1652 } | 1679 } |
1653 } | 1680 } |
1654 } | 1681 } |
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2760 } | 2787 } |
2761 | 2788 |
2762 inner_scope->set_end_position(scanner()->location().end_pos); | 2789 inner_scope->set_end_position(scanner()->location().end_pos); |
2763 inner_block->set_scope(inner_scope); | 2790 inner_block->set_scope(inner_scope); |
2764 } | 2791 } |
2765 | 2792 |
2766 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 2793 outer_loop->Initialize(NULL, NULL, NULL, inner_block); |
2767 return outer_block; | 2794 return outer_block; |
2768 } | 2795 } |
2769 | 2796 |
2770 Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels, | |
2771 bool legacy, bool* ok) { | |
2772 if (is_strict(language_mode()) || peek() != Token::FUNCTION || | |
2773 (legacy && allow_harmony_restrictive_declarations())) { | |
2774 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); | |
2775 } else { | |
2776 if (legacy) { | |
2777 ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration]; | |
2778 } | |
2779 // Make a block around the statement for a lexical binding | |
2780 // is introduced by a FunctionDeclaration. | |
2781 BlockState block_state(&scope_state_); | |
2782 block_state.set_start_position(scanner()->location().beg_pos); | |
2783 Block* block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | |
2784 Statement* body = ParseFunctionDeclaration(CHECK_OK); | |
2785 block->statements()->Add(body, zone()); | |
2786 block_state.set_end_position(scanner()->location().end_pos); | |
2787 block->set_scope(block_state.FinalizedBlockScope()); | |
2788 return block; | |
2789 } | |
2790 } | |
2791 | |
2792 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 2797 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
2793 bool* ok) { | 2798 bool* ok) { |
2794 int stmt_pos = peek_position(); | 2799 int stmt_pos = peek_position(); |
2795 Statement* init = NULL; | 2800 Statement* init = NULL; |
2796 ZoneList<const AstRawString*> bound_names(1, zone()); | 2801 ZoneList<const AstRawString*> bound_names(1, zone()); |
2797 bool bound_names_are_lexical = false; | 2802 bool bound_names_are_lexical = false; |
2798 | 2803 |
2799 // Create an in-between scope for let-bound iteration variables. | 2804 // Create an in-between scope for let-bound iteration variables. |
2800 BlockState for_state(&scope_state_); | 2805 BlockState for_state(&scope_state_); |
2801 Expect(Token::FOR, CHECK_OK); | 2806 Expect(Token::FOR, CHECK_OK); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3129 loop->Initialize(NULL, cond, next, body); | 3134 loop->Initialize(NULL, cond, next, body); |
3130 result = block; | 3135 result = block; |
3131 } else { | 3136 } else { |
3132 loop->Initialize(init, cond, next, body); | 3137 loop->Initialize(init, cond, next, body); |
3133 result = loop; | 3138 result = loop; |
3134 } | 3139 } |
3135 } | 3140 } |
3136 return result; | 3141 return result; |
3137 } | 3142 } |
3138 | 3143 |
3139 | |
3140 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { | |
3141 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | |
3142 // contexts this is used as a statement which invokes the debugger as i a | |
3143 // break point is present. | |
3144 // DebuggerStatement :: | |
3145 // 'debugger' ';' | |
3146 | |
3147 int pos = peek_position(); | |
3148 Expect(Token::DEBUGGER, CHECK_OK); | |
3149 ExpectSemicolon(CHECK_OK); | |
3150 return factory()->NewDebuggerStatement(pos); | |
3151 } | |
3152 | |
3153 | |
3154 void Parser::ParseArrowFunctionFormalParameters( | 3144 void Parser::ParseArrowFunctionFormalParameters( |
3155 ParserFormalParameters* parameters, Expression* expr, int end_pos, | 3145 ParserFormalParameters* parameters, Expression* expr, int end_pos, |
3156 bool* ok) { | 3146 bool* ok) { |
3157 // ArrowFunctionFormals :: | 3147 // ArrowFunctionFormals :: |
3158 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail) | 3148 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail) |
3159 // Tail | 3149 // Tail |
3160 // NonTailArrowFunctionFormals :: | 3150 // NonTailArrowFunctionFormals :: |
3161 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy) | 3151 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy) |
3162 // VariableProxy | 3152 // VariableProxy |
3163 // Tail :: | 3153 // Tail :: |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3530 CheckFunctionName(language_mode, function_name, function_name_validity, | 3520 CheckFunctionName(language_mode, function_name, function_name_validity, |
3531 function_name_location, CHECK_OK); | 3521 function_name_location, CHECK_OK); |
3532 const bool allow_duplicate_parameters = | 3522 const bool allow_duplicate_parameters = |
3533 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); | 3523 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); |
3534 ValidateFormalParameters(language_mode, allow_duplicate_parameters, | 3524 ValidateFormalParameters(language_mode, allow_duplicate_parameters, |
3535 CHECK_OK); | 3525 CHECK_OK); |
3536 | 3526 |
3537 if (is_strict(language_mode)) { | 3527 if (is_strict(language_mode)) { |
3538 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | 3528 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
3539 CHECK_OK); | 3529 CHECK_OK); |
3540 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(), | 3530 CheckDecimalLiteralWithLeadingZero(scope->start_position(), |
3541 scope->end_position()); | 3531 scope->end_position()); |
3542 } | 3532 } |
3543 CheckConflictingVarDeclarations(scope, CHECK_OK); | 3533 CheckConflictingVarDeclarations(scope, CHECK_OK); |
3544 | 3534 |
3545 if (body) { | 3535 if (body) { |
3546 // If body can be inspected, rewrite queued destructuring assignments | 3536 // If body can be inspected, rewrite queued destructuring assignments |
3547 RewriteDestructuringAssignments(); | 3537 RewriteDestructuringAssignments(); |
3548 } | 3538 } |
3549 has_duplicate_parameters = | 3539 has_duplicate_parameters = |
3550 !classifier()->is_valid_formal_parameter_list_without_duplicates(); | 3540 !classifier()->is_valid_formal_parameter_list_without_duplicates(); |
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4262 | 4252 |
4263 do_block->statements()->Add( | 4253 do_block->statements()->Add( |
4264 factory()->NewExpressionStatement(class_literal, pos), zone()); | 4254 factory()->NewExpressionStatement(class_literal, pos), zone()); |
4265 do_expr->set_represented_function(constructor); | 4255 do_expr->set_represented_function(constructor); |
4266 Rewriter::Rewrite(this, GetClosureScope(), do_expr, ast_value_factory()); | 4256 Rewriter::Rewrite(this, GetClosureScope(), do_expr, ast_value_factory()); |
4267 | 4257 |
4268 return do_expr; | 4258 return do_expr; |
4269 } | 4259 } |
4270 | 4260 |
4271 | 4261 |
4272 Expression* Parser::ParseV8Intrinsic(bool* ok) { | |
4273 // CallRuntime :: | |
4274 // '%' Identifier Arguments | |
4275 | |
4276 int pos = peek_position(); | |
4277 Expect(Token::MOD, CHECK_OK); | |
4278 // Allow "eval" or "arguments" for backward compatibility. | |
4279 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers, | |
4280 CHECK_OK); | |
4281 Scanner::Location spread_pos; | |
4282 ExpressionClassifier classifier(this); | |
4283 ZoneList<Expression*>* args = ParseArguments(&spread_pos, CHECK_OK); | |
4284 | |
4285 DCHECK(!spread_pos.IsValid()); | |
4286 | |
4287 if (extension_ != NULL) { | |
4288 // The extension structures are only accessible while parsing the | |
4289 // very first time not when reparsing because of lazy compilation. | |
4290 GetClosureScope()->ForceEagerCompilation(); | |
4291 } | |
4292 | |
4293 const Runtime::Function* function = Runtime::FunctionForName(name->string()); | |
4294 | |
4295 if (function != NULL) { | |
4296 // Check for possible name clash. | |
4297 DCHECK_EQ(Context::kNotFound, | |
4298 Context::IntrinsicIndexForName(name->string())); | |
4299 // Check for built-in IS_VAR macro. | |
4300 if (function->function_id == Runtime::kIS_VAR) { | |
4301 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type); | |
4302 // %IS_VAR(x) evaluates to x if x is a variable, | |
4303 // leads to a parse error otherwise. Could be implemented as an | |
4304 // inline function %_IS_VAR(x) to eliminate this special case. | |
4305 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) { | |
4306 return args->at(0); | |
4307 } else { | |
4308 ReportMessage(MessageTemplate::kNotIsvar); | |
4309 *ok = false; | |
4310 return NULL; | |
4311 } | |
4312 } | |
4313 | |
4314 // Check that the expected number of arguments are being passed. | |
4315 if (function->nargs != -1 && function->nargs != args->length()) { | |
4316 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs); | |
4317 *ok = false; | |
4318 return NULL; | |
4319 } | |
4320 | |
4321 return factory()->NewCallRuntime(function, args, pos); | |
4322 } | |
4323 | |
4324 int context_index = Context::IntrinsicIndexForName(name->string()); | |
4325 | |
4326 // Check that the function is defined. | |
4327 if (context_index == Context::kNotFound) { | |
4328 ReportMessage(MessageTemplate::kNotDefined, name); | |
4329 *ok = false; | |
4330 return NULL; | |
4331 } | |
4332 | |
4333 return factory()->NewCallRuntime(context_index, args, pos); | |
4334 } | |
4335 | |
4336 | |
4337 Literal* Parser::GetLiteralUndefined(int position) { | 4262 Literal* Parser::GetLiteralUndefined(int position) { |
4338 return factory()->NewUndefinedLiteral(position); | 4263 return factory()->NewUndefinedLiteral(position); |
4339 } | 4264 } |
4340 | 4265 |
4341 | 4266 |
4342 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | 4267 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
4343 Declaration* decl = scope->CheckConflictingVarDeclarations(); | 4268 Declaration* decl = scope->CheckConflictingVarDeclarations(); |
4344 if (decl != NULL) { | 4269 if (decl != NULL) { |
4345 // In ES6, conflicting variable bindings are early errors. | 4270 // In ES6, conflicting variable bindings are early errors. |
4346 const AstRawString* name = decl->proxy()->raw_name(); | 4271 const AstRawString* name = decl->proxy()->raw_name(); |
(...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6082 node->Print(Isolate::Current()); | 6007 node->Print(Isolate::Current()); |
6083 } | 6008 } |
6084 #endif // DEBUG | 6009 #endif // DEBUG |
6085 | 6010 |
6086 #undef CHECK_OK | 6011 #undef CHECK_OK |
6087 #undef CHECK_OK_VOID | 6012 #undef CHECK_OK_VOID |
6088 #undef CHECK_FAILED | 6013 #undef CHECK_FAILED |
6089 | 6014 |
6090 } // namespace internal | 6015 } // namespace internal |
6091 } // namespace v8 | 6016 } // namespace v8 |
OLD | NEW |