| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 Handle<FixedArray> this_property_assignments() { | 276 Handle<FixedArray> this_property_assignments() { |
| 277 return this_property_assignments_; | 277 return this_property_assignments_; |
| 278 } | 278 } |
| 279 | 279 |
| 280 void AddProperty() { expected_property_count_++; } | 280 void AddProperty() { expected_property_count_++; } |
| 281 int expected_property_count() { return expected_property_count_; } | 281 int expected_property_count() { return expected_property_count_; } |
| 282 | 282 |
| 283 void AddLoop() { loop_count_++; } | 283 void AddLoop() { loop_count_++; } |
| 284 bool ContainsLoops() const { return loop_count_ > 0; } | 284 bool ContainsLoops() const { return loop_count_ > 0; } |
| 285 | 285 |
| 286 bool StrictMode() { return strict_mode_; } |
| 287 void EnableStrictMode() { |
| 288 strict_mode_ = FLAG_strict_mode; |
| 289 } |
| 290 |
| 286 private: | 291 private: |
| 287 // Captures the number of literals that need materialization in the | 292 // Captures the number of literals that need materialization in the |
| 288 // function. Includes regexp literals, and boilerplate for object | 293 // function. Includes regexp literals, and boilerplate for object |
| 289 // and array literals. | 294 // and array literals. |
| 290 int materialized_literal_count_; | 295 int materialized_literal_count_; |
| 291 | 296 |
| 292 // Properties count estimation. | 297 // Properties count estimation. |
| 293 int expected_property_count_; | 298 int expected_property_count_; |
| 294 | 299 |
| 295 // Keeps track of assignments to properties of this. Used for | 300 // Keeps track of assignments to properties of this. Used for |
| 296 // optimizing constructors. | 301 // optimizing constructors. |
| 297 bool only_simple_this_property_assignments_; | 302 bool only_simple_this_property_assignments_; |
| 298 Handle<FixedArray> this_property_assignments_; | 303 Handle<FixedArray> this_property_assignments_; |
| 299 | 304 |
| 300 // Captures the number of loops inside the scope. | 305 // Captures the number of loops inside the scope. |
| 301 int loop_count_; | 306 int loop_count_; |
| 302 | 307 |
| 308 // Parsing strict mode code. |
| 309 bool strict_mode_; |
| 310 |
| 303 // Bookkeeping | 311 // Bookkeeping |
| 304 TemporaryScope** variable_; | 312 TemporaryScope** variable_; |
| 305 TemporaryScope* parent_; | 313 TemporaryScope* parent_; |
| 306 }; | 314 }; |
| 307 | 315 |
| 308 | 316 |
| 309 TemporaryScope::TemporaryScope(TemporaryScope** variable) | 317 TemporaryScope::TemporaryScope(TemporaryScope** variable) |
| 310 : materialized_literal_count_(0), | 318 : materialized_literal_count_(0), |
| 311 expected_property_count_(0), | 319 expected_property_count_(0), |
| 312 only_simple_this_property_assignments_(false), | 320 only_simple_this_property_assignments_(false), |
| 313 this_property_assignments_(Factory::empty_fixed_array()), | 321 this_property_assignments_(Factory::empty_fixed_array()), |
| 314 loop_count_(0), | 322 loop_count_(0), |
| 315 variable_(variable), | 323 variable_(variable), |
| 316 parent_(*variable) { | 324 parent_(*variable) { |
| 325 // Inherit the strict mode from the parent scope. |
| 326 strict_mode_ = (parent_ != NULL) && parent_->strict_mode_; |
| 317 *variable = this; | 327 *variable = this; |
| 318 } | 328 } |
| 319 | 329 |
| 320 | 330 |
| 321 TemporaryScope::~TemporaryScope() { | 331 TemporaryScope::~TemporaryScope() { |
| 322 *variable_ = parent_; | 332 *variable_ = parent_; |
| 323 } | 333 } |
| 324 | 334 |
| 325 | 335 |
| 326 Handle<String> Parser::LookupSymbol(int symbol_id) { | 336 Handle<String> Parser::LookupSymbol(int symbol_id) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 *with_nesting_level_variable_ = prev_level_; | 564 *with_nesting_level_variable_ = prev_level_; |
| 555 } | 565 } |
| 556 | 566 |
| 557 private: | 567 private: |
| 558 Scope** scope_variable_; | 568 Scope** scope_variable_; |
| 559 int* with_nesting_level_variable_; | 569 int* with_nesting_level_variable_; |
| 560 Scope* prev_scope_; | 570 Scope* prev_scope_; |
| 561 int prev_level_; | 571 int prev_level_; |
| 562 }; | 572 }; |
| 563 | 573 |
| 564 | |
| 565 // ---------------------------------------------------------------------------- | 574 // ---------------------------------------------------------------------------- |
| 566 // The CHECK_OK macro is a convenient macro to enforce error | 575 // The CHECK_OK macro is a convenient macro to enforce error |
| 567 // handling for functions that may fail (by returning !*ok). | 576 // handling for functions that may fail (by returning !*ok). |
| 568 // | 577 // |
| 569 // CAUTION: This macro appends extra statements after a call, | 578 // CAUTION: This macro appends extra statements after a call, |
| 570 // thus it must never be used where only a single statement | 579 // thus it must never be used where only a single statement |
| 571 // is correct (e.g. an if statement branch w/o braces)! | 580 // is correct (e.g. an if statement branch w/o braces)! |
| 572 | 581 |
| 573 #define CHECK_OK ok); \ | 582 #define CHECK_OK ok); \ |
| 574 if (!*ok) return NULL; \ | 583 if (!*ok) return NULL; \ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 593 script_(script), | 602 script_(script), |
| 594 scanner_(), | 603 scanner_(), |
| 595 top_scope_(NULL), | 604 top_scope_(NULL), |
| 596 with_nesting_level_(0), | 605 with_nesting_level_(0), |
| 597 temp_scope_(NULL), | 606 temp_scope_(NULL), |
| 598 target_stack_(NULL), | 607 target_stack_(NULL), |
| 599 allow_natives_syntax_(allow_natives_syntax), | 608 allow_natives_syntax_(allow_natives_syntax), |
| 600 extension_(extension), | 609 extension_(extension), |
| 601 pre_data_(pre_data), | 610 pre_data_(pre_data), |
| 602 fni_(NULL), | 611 fni_(NULL), |
| 603 stack_overflow_(false) { | 612 stack_overflow_(false), |
| 613 parenthesized_function_(false) { |
| 604 AstNode::ResetIds(); | 614 AstNode::ResetIds(); |
| 605 } | 615 } |
| 606 | 616 |
| 607 | 617 |
| 608 FunctionLiteral* Parser::ParseProgram(Handle<String> source, | 618 FunctionLiteral* Parser::ParseProgram(Handle<String> source, |
| 609 bool in_global_context) { | 619 bool in_global_context, |
| 620 StrictModeFlag strict_mode) { |
| 610 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); | 621 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); |
| 611 | 622 |
| 612 HistogramTimerScope timer(&Counters::parse); | 623 HistogramTimerScope timer(&Counters::parse); |
| 613 Counters::total_parse_size.Increment(source->length()); | 624 Counters::total_parse_size.Increment(source->length()); |
| 614 fni_ = new FuncNameInferrer(); | 625 fni_ = new FuncNameInferrer(); |
| 615 | 626 |
| 616 // Initialize parser state. | 627 // Initialize parser state. |
| 617 source->TryFlatten(); | 628 source->TryFlatten(); |
| 618 if (source->IsExternalTwoByteString()) { | 629 if (source->IsExternalTwoByteString()) { |
| 619 // Notice that the stream is destroyed at the end of the branch block. | 630 // Notice that the stream is destroyed at the end of the branch block. |
| 620 // The last line of the blocks can't be moved outside, even though they're | 631 // The last line of the blocks can't be moved outside, even though they're |
| 621 // identical calls. | 632 // identical calls. |
| 622 ExternalTwoByteStringUC16CharacterStream stream( | 633 ExternalTwoByteStringUC16CharacterStream stream( |
| 623 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | 634 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
| 624 scanner_.Initialize(&stream); | 635 scanner_.Initialize(&stream); |
| 625 return DoParseProgram(source, in_global_context, &zone_scope); | 636 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); |
| 626 } else { | 637 } else { |
| 627 GenericStringUC16CharacterStream stream(source, 0, source->length()); | 638 GenericStringUC16CharacterStream stream(source, 0, source->length()); |
| 628 scanner_.Initialize(&stream); | 639 scanner_.Initialize(&stream); |
| 629 return DoParseProgram(source, in_global_context, &zone_scope); | 640 return DoParseProgram(source, in_global_context, strict_mode, &zone_scope); |
| 630 } | 641 } |
| 631 } | 642 } |
| 632 | 643 |
| 633 | 644 |
| 634 FunctionLiteral* Parser::DoParseProgram(Handle<String> source, | 645 FunctionLiteral* Parser::DoParseProgram(Handle<String> source, |
| 635 bool in_global_context, | 646 bool in_global_context, |
| 647 StrictModeFlag strict_mode, |
| 636 ZoneScope* zone_scope) { | 648 ZoneScope* zone_scope) { |
| 637 ASSERT(target_stack_ == NULL); | 649 ASSERT(target_stack_ == NULL); |
| 638 if (pre_data_ != NULL) pre_data_->Initialize(); | 650 if (pre_data_ != NULL) pre_data_->Initialize(); |
| 639 | 651 |
| 640 // Compute the parsing mode. | 652 // Compute the parsing mode. |
| 641 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY; | 653 mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY; |
| 642 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY; | 654 if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY; |
| 643 | 655 |
| 644 Scope::Type type = | 656 Scope::Type type = |
| 645 in_global_context | 657 in_global_context |
| 646 ? Scope::GLOBAL_SCOPE | 658 ? Scope::GLOBAL_SCOPE |
| 647 : Scope::EVAL_SCOPE; | 659 : Scope::EVAL_SCOPE; |
| 648 Handle<String> no_name = Factory::empty_symbol(); | 660 Handle<String> no_name = Factory::empty_symbol(); |
| 649 | 661 |
| 650 FunctionLiteral* result = NULL; | 662 FunctionLiteral* result = NULL; |
| 651 { Scope* scope = NewScope(top_scope_, type, inside_with()); | 663 { Scope* scope = NewScope(top_scope_, type, inside_with()); |
| 652 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, | 664 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, |
| 653 scope); | 665 scope); |
| 654 TemporaryScope temp_scope(&this->temp_scope_); | 666 TemporaryScope temp_scope(&this->temp_scope_); |
| 667 if (strict_mode == kStrictMode) { |
| 668 temp_scope.EnableStrictMode(); |
| 669 } |
| 655 ZoneList<Statement*>* body = new ZoneList<Statement*>(16); | 670 ZoneList<Statement*>* body = new ZoneList<Statement*>(16); |
| 656 bool ok = true; | 671 bool ok = true; |
| 672 int beg_loc = scanner().location().beg_pos; |
| 657 ParseSourceElements(body, Token::EOS, &ok); | 673 ParseSourceElements(body, Token::EOS, &ok); |
| 674 if (ok && temp_scope_->StrictMode()) { |
| 675 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); |
| 676 } |
| 658 if (ok) { | 677 if (ok) { |
| 659 result = new FunctionLiteral( | 678 result = new FunctionLiteral( |
| 660 no_name, | 679 no_name, |
| 661 top_scope_, | 680 top_scope_, |
| 662 body, | 681 body, |
| 663 temp_scope.materialized_literal_count(), | 682 temp_scope.materialized_literal_count(), |
| 664 temp_scope.expected_property_count(), | 683 temp_scope.expected_property_count(), |
| 665 temp_scope.only_simple_this_property_assignments(), | 684 temp_scope.only_simple_this_property_assignments(), |
| 666 temp_scope.this_property_assignments(), | 685 temp_scope.this_property_assignments(), |
| 667 0, | 686 0, |
| 668 0, | 687 0, |
| 669 source->length(), | 688 source->length(), |
| 670 false, | 689 false, |
| 671 temp_scope.ContainsLoops()); | 690 temp_scope.ContainsLoops(), |
| 691 temp_scope.StrictMode()); |
| 672 } else if (stack_overflow_) { | 692 } else if (stack_overflow_) { |
| 673 Top::StackOverflow(); | 693 Top::StackOverflow(); |
| 674 } | 694 } |
| 675 } | 695 } |
| 676 | 696 |
| 677 // Make sure the target stack is empty. | 697 // Make sure the target stack is empty. |
| 678 ASSERT(target_stack_ == NULL); | 698 ASSERT(target_stack_ == NULL); |
| 679 | 699 |
| 680 // If there was a syntax error we have to get rid of the AST | 700 // If there was a syntax error we have to get rid of the AST |
| 681 // and it is not safe to do so before the scope has been deleted. | 701 // and it is not safe to do so before the scope has been deleted. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 | 745 |
| 726 { | 746 { |
| 727 // Parse the function literal. | 747 // Parse the function literal. |
| 728 Handle<String> no_name = Factory::empty_symbol(); | 748 Handle<String> no_name = Factory::empty_symbol(); |
| 729 Scope* scope = | 749 Scope* scope = |
| 730 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with()); | 750 NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with()); |
| 731 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, | 751 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, |
| 732 scope); | 752 scope); |
| 733 TemporaryScope temp_scope(&this->temp_scope_); | 753 TemporaryScope temp_scope(&this->temp_scope_); |
| 734 | 754 |
| 755 if (info->strict_mode()) { |
| 756 temp_scope.EnableStrictMode(); |
| 757 } |
| 758 |
| 735 FunctionLiteralType type = | 759 FunctionLiteralType type = |
| 736 info->is_expression() ? EXPRESSION : DECLARATION; | 760 info->is_expression() ? EXPRESSION : DECLARATION; |
| 737 bool ok = true; | 761 bool ok = true; |
| 738 result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok); | 762 result = ParseFunctionLiteral(name, |
| 763 false, // Strict mode name already checked. |
| 764 RelocInfo::kNoPosition, type, &ok); |
| 739 // Make sure the results agree. | 765 // Make sure the results agree. |
| 740 ASSERT(ok == (result != NULL)); | 766 ASSERT(ok == (result != NULL)); |
| 741 // The only errors should be stack overflows. | |
| 742 ASSERT(ok || stack_overflow_); | |
| 743 } | 767 } |
| 744 | 768 |
| 745 // Make sure the target stack is empty. | 769 // Make sure the target stack is empty. |
| 746 ASSERT(target_stack_ == NULL); | 770 ASSERT(target_stack_ == NULL); |
| 747 | 771 |
| 748 // If there was a stack overflow we have to get rid of AST and it is | 772 // If there was a stack overflow we have to get rid of AST and it is |
| 749 // not safe to do before scope has been deleted. | 773 // not safe to do before scope has been deleted. |
| 750 if (result == NULL) { | 774 if (result == NULL) { |
| 751 Top::StackOverflow(); | |
| 752 zone_scope->DeleteOnExit(); | 775 zone_scope->DeleteOnExit(); |
| 776 if (stack_overflow_) Top::StackOverflow(); |
| 753 } else { | 777 } else { |
| 754 Handle<String> inferred_name(info->inferred_name()); | 778 Handle<String> inferred_name(info->inferred_name()); |
| 755 result->set_inferred_name(inferred_name); | 779 result->set_inferred_name(inferred_name); |
| 756 } | 780 } |
| 757 return result; | 781 return result; |
| 758 } | 782 } |
| 759 | 783 |
| 760 | 784 |
| 761 Handle<String> Parser::GetSymbol(bool* ok) { | 785 Handle<String> Parser::GetSymbol(bool* ok) { |
| 762 int symbol_id = -1; | 786 int symbol_id = -1; |
| 763 if (pre_data() != NULL) { | 787 if (pre_data() != NULL) { |
| 764 symbol_id = pre_data()->GetSymbolIdentifier(); | 788 symbol_id = pre_data()->GetSymbolIdentifier(); |
| 765 } | 789 } |
| 766 return LookupSymbol(symbol_id); | 790 return LookupSymbol(symbol_id); |
| 767 } | 791 } |
| 768 | 792 |
| 769 | 793 |
| 770 void Parser::ReportMessage(const char* type, Vector<const char*> args) { | 794 void Parser::ReportMessage(const char* type, Vector<const char*> args) { |
| 771 Scanner::Location source_location = scanner().location(); | 795 Scanner::Location source_location = scanner().location(); |
| 772 ReportMessageAt(source_location, type, args); | 796 ReportMessageAt(source_location, type, args); |
| 773 } | 797 } |
| 774 | 798 |
| 775 | 799 |
| 776 void Parser::ReportMessageAt(Scanner::Location source_location, | 800 void Parser::ReportMessageAt(Scanner::Location source_location, |
| 777 const char* type, | 801 const char* type, |
| 778 Vector<const char*> args) { | 802 Vector<const char*> args) { |
| 779 MessageLocation location(script_, | 803 MessageLocation location(script_, |
| 780 source_location.beg_pos, source_location.end_pos); | 804 source_location.beg_pos, |
| 805 source_location.end_pos); |
| 781 Handle<JSArray> array = Factory::NewJSArray(args.length()); | 806 Handle<JSArray> array = Factory::NewJSArray(args.length()); |
| 782 for (int i = 0; i < args.length(); i++) { | 807 for (int i = 0; i < args.length(); i++) { |
| 783 SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i]))); | 808 SetElement(array, i, Factory::NewStringFromUtf8(CStrVector(args[i]))); |
| 784 } | 809 } |
| 785 Handle<Object> result = Factory::NewSyntaxError(type, array); | 810 Handle<Object> result = Factory::NewSyntaxError(type, array); |
| 786 Top::Throw(*result, &location); | 811 Top::Throw(*result, &location); |
| 787 } | 812 } |
| 788 | 813 |
| 789 | 814 |
| 815 void Parser::ReportMessageAt(Scanner::Location source_location, |
| 816 const char* type, |
| 817 Vector<Handle<String> > args) { |
| 818 MessageLocation location(script_, |
| 819 source_location.beg_pos, |
| 820 source_location.end_pos); |
| 821 Handle<JSArray> array = Factory::NewJSArray(args.length()); |
| 822 for (int i = 0; i < args.length(); i++) { |
| 823 SetElement(array, i, args[i]); |
| 824 } |
| 825 Handle<Object> result = Factory::NewSyntaxError(type, array); |
| 826 Top::Throw(*result, &location); |
| 827 } |
| 828 |
| 829 |
| 790 // Base class containing common code for the different finder classes used by | 830 // Base class containing common code for the different finder classes used by |
| 791 // the parser. | 831 // the parser. |
| 792 class ParserFinder { | 832 class ParserFinder { |
| 793 protected: | 833 protected: |
| 794 ParserFinder() {} | 834 ParserFinder() {} |
| 795 static Assignment* AsAssignment(Statement* stat) { | 835 static Assignment* AsAssignment(Statement* stat) { |
| 796 if (stat == NULL) return NULL; | 836 if (stat == NULL) return NULL; |
| 797 ExpressionStatement* exp_stat = stat->AsExpressionStatement(); | 837 ExpressionStatement* exp_stat = stat->AsExpressionStatement(); |
| 798 if (exp_stat == NULL) return NULL; | 838 if (exp_stat == NULL) return NULL; |
| 799 return exp_stat->expression()->AsAssignment(); | 839 return exp_stat->expression()->AsAssignment(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 | 1091 |
| 1052 // Allocate a target stack to use for this set of source | 1092 // Allocate a target stack to use for this set of source |
| 1053 // elements. This way, all scripts and functions get their own | 1093 // elements. This way, all scripts and functions get their own |
| 1054 // target stack thus avoiding illegal breaks and continues across | 1094 // target stack thus avoiding illegal breaks and continues across |
| 1055 // functions. | 1095 // functions. |
| 1056 TargetScope scope(&this->target_stack_); | 1096 TargetScope scope(&this->target_stack_); |
| 1057 | 1097 |
| 1058 ASSERT(processor != NULL); | 1098 ASSERT(processor != NULL); |
| 1059 InitializationBlockFinder block_finder; | 1099 InitializationBlockFinder block_finder; |
| 1060 ThisNamedPropertyAssigmentFinder this_property_assignment_finder; | 1100 ThisNamedPropertyAssigmentFinder this_property_assignment_finder; |
| 1101 bool directive_prologue = true; // Parsing directive prologue. |
| 1102 |
| 1061 while (peek() != end_token) { | 1103 while (peek() != end_token) { |
| 1104 if (directive_prologue && peek() != Token::STRING) { |
| 1105 directive_prologue = false; |
| 1106 } |
| 1107 |
| 1108 Scanner::Location token_loc = scanner().peek_location(); |
| 1062 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1109 Statement* stat = ParseStatement(NULL, CHECK_OK); |
| 1063 if (stat == NULL || stat->IsEmpty()) continue; | 1110 |
| 1111 if (stat == NULL || stat->IsEmpty()) { |
| 1112 directive_prologue = false; // End of directive prologue. |
| 1113 continue; |
| 1114 } |
| 1115 |
| 1116 if (directive_prologue) { |
| 1117 // A shot at a directive. |
| 1118 ExpressionStatement *e_stat; |
| 1119 Literal *literal; |
| 1120 // Still processing directive prologue? |
| 1121 if ((e_stat = stat->AsExpressionStatement()) != NULL && |
| 1122 (literal = e_stat->expression()->AsLiteral()) != NULL && |
| 1123 literal->handle()->IsString()) { |
| 1124 Handle<String> directive = Handle<String>::cast(literal->handle()); |
| 1125 |
| 1126 // Check "use strict" directive (ES5 14.1). |
| 1127 if (!temp_scope_->StrictMode() && |
| 1128 directive->Equals(Heap::use_strict()) && |
| 1129 token_loc.end_pos - token_loc.beg_pos == |
| 1130 Heap::use_strict()->length() + 2) { |
| 1131 temp_scope_->EnableStrictMode(); |
| 1132 // "use strict" is the only directive for now. |
| 1133 directive_prologue = false; |
| 1134 } |
| 1135 } else { |
| 1136 // End of the directive prologue. |
| 1137 directive_prologue = false; |
| 1138 } |
| 1139 } |
| 1140 |
| 1064 // We find and mark the initialization blocks on top level code only. | 1141 // We find and mark the initialization blocks on top level code only. |
| 1065 // This is because the optimization prevents reuse of the map transitions, | 1142 // This is because the optimization prevents reuse of the map transitions, |
| 1066 // so it should be used only for code that will only be run once. | 1143 // so it should be used only for code that will only be run once. |
| 1067 if (top_scope_->is_global_scope()) { | 1144 if (top_scope_->is_global_scope()) { |
| 1068 block_finder.Update(stat); | 1145 block_finder.Update(stat); |
| 1069 } | 1146 } |
| 1070 // Find and mark all assignments to named properties in this (this.x =) | 1147 // Find and mark all assignments to named properties in this (this.x =) |
| 1071 if (top_scope_->is_function_scope()) { | 1148 if (top_scope_->is_function_scope()) { |
| 1072 this_property_assignment_finder.Update(top_scope_, stat); | 1149 this_property_assignment_finder.Update(top_scope_, stat); |
| 1073 } | 1150 } |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 return new ExpressionStatement( | 1441 return new ExpressionStatement( |
| 1365 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)); | 1442 new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)); |
| 1366 } | 1443 } |
| 1367 | 1444 |
| 1368 | 1445 |
| 1369 Statement* Parser::ParseFunctionDeclaration(bool* ok) { | 1446 Statement* Parser::ParseFunctionDeclaration(bool* ok) { |
| 1370 // FunctionDeclaration :: | 1447 // FunctionDeclaration :: |
| 1371 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 1448 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 1372 Expect(Token::FUNCTION, CHECK_OK); | 1449 Expect(Token::FUNCTION, CHECK_OK); |
| 1373 int function_token_position = scanner().location().beg_pos; | 1450 int function_token_position = scanner().location().beg_pos; |
| 1374 Handle<String> name = ParseIdentifier(CHECK_OK); | 1451 bool is_reserved = false; |
| 1452 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK); |
| 1375 FunctionLiteral* fun = ParseFunctionLiteral(name, | 1453 FunctionLiteral* fun = ParseFunctionLiteral(name, |
| 1454 is_reserved, |
| 1376 function_token_position, | 1455 function_token_position, |
| 1377 DECLARATION, | 1456 DECLARATION, |
| 1378 CHECK_OK); | 1457 CHECK_OK); |
| 1379 // Even if we're not at the top-level of the global or a function | 1458 // Even if we're not at the top-level of the global or a function |
| 1380 // scope, we treat is as such and introduce the function with it's | 1459 // scope, we treat is as such and introduce the function with it's |
| 1381 // initial value upon entering the corresponding scope. | 1460 // initial value upon entering the corresponding scope. |
| 1382 Declare(name, Variable::VAR, fun, true, CHECK_OK); | 1461 Declare(name, Variable::VAR, fun, true, CHECK_OK); |
| 1383 return EmptyStatement(); | 1462 return EmptyStatement(); |
| 1384 } | 1463 } |
| 1385 | 1464 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1407 Block* Parser::ParseVariableStatement(bool* ok) { | 1486 Block* Parser::ParseVariableStatement(bool* ok) { |
| 1408 // VariableStatement :: | 1487 // VariableStatement :: |
| 1409 // VariableDeclarations ';' | 1488 // VariableDeclarations ';' |
| 1410 | 1489 |
| 1411 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature | 1490 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature |
| 1412 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); | 1491 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); |
| 1413 ExpectSemicolon(CHECK_OK); | 1492 ExpectSemicolon(CHECK_OK); |
| 1414 return result; | 1493 return result; |
| 1415 } | 1494 } |
| 1416 | 1495 |
| 1496 static bool IsEvalOrArguments(Handle<String> string) { |
| 1497 return string.is_identical_to(Factory::eval_symbol()) || |
| 1498 string.is_identical_to(Factory::arguments_symbol()); |
| 1499 } |
| 1417 | 1500 |
| 1418 // If the variable declaration declares exactly one non-const | 1501 // If the variable declaration declares exactly one non-const |
| 1419 // variable, then *var is set to that variable. In all other cases, | 1502 // variable, then *var is set to that variable. In all other cases, |
| 1420 // *var is untouched; in particular, it is the caller's responsibility | 1503 // *var is untouched; in particular, it is the caller's responsibility |
| 1421 // to initialize it properly. This mechanism is used for the parsing | 1504 // to initialize it properly. This mechanism is used for the parsing |
| 1422 // of 'for-in' loops. | 1505 // of 'for-in' loops. |
| 1423 Block* Parser::ParseVariableDeclarations(bool accept_IN, | 1506 Block* Parser::ParseVariableDeclarations(bool accept_IN, |
| 1424 Expression** var, | 1507 Expression** var, |
| 1425 bool* ok) { | 1508 bool* ok) { |
| 1426 // VariableDeclarations :: | 1509 // VariableDeclarations :: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1455 VariableProxy* last_var = NULL; // the last variable declared | 1538 VariableProxy* last_var = NULL; // the last variable declared |
| 1456 int nvars = 0; // the number of variables declared | 1539 int nvars = 0; // the number of variables declared |
| 1457 do { | 1540 do { |
| 1458 if (fni_ != NULL) fni_->Enter(); | 1541 if (fni_ != NULL) fni_->Enter(); |
| 1459 | 1542 |
| 1460 // Parse variable name. | 1543 // Parse variable name. |
| 1461 if (nvars > 0) Consume(Token::COMMA); | 1544 if (nvars > 0) Consume(Token::COMMA); |
| 1462 Handle<String> name = ParseIdentifier(CHECK_OK); | 1545 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 1463 if (fni_ != NULL) fni_->PushVariableName(name); | 1546 if (fni_ != NULL) fni_->PushVariableName(name); |
| 1464 | 1547 |
| 1548 // Strict mode variables may not be named eval or arguments |
| 1549 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { |
| 1550 ReportMessage("strict_var_name", Vector<const char*>::empty()); |
| 1551 *ok = false; |
| 1552 return NULL; |
| 1553 } |
| 1554 |
| 1465 // Declare variable. | 1555 // Declare variable. |
| 1466 // Note that we *always* must treat the initial value via a separate init | 1556 // Note that we *always* must treat the initial value via a separate init |
| 1467 // assignment for variables and constants because the value must be assigned | 1557 // assignment for variables and constants because the value must be assigned |
| 1468 // when the variable is encountered in the source. But the variable/constant | 1558 // when the variable is encountered in the source. But the variable/constant |
| 1469 // is declared (and set to 'undefined') upon entering the function within | 1559 // is declared (and set to 'undefined') upon entering the function within |
| 1470 // which the variable or constant is declared. Only function variables have | 1560 // which the variable or constant is declared. Only function variables have |
| 1471 // an initial value in the declaration (because they are initialized upon | 1561 // an initial value in the declaration (because they are initialized upon |
| 1472 // entering the function). | 1562 // entering the function). |
| 1473 // | 1563 // |
| 1474 // If we have a const declaration, in an inner scope, the proxy is always | 1564 // If we have a const declaration, in an inner scope, the proxy is always |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1613 | 1703 |
| 1614 return false; | 1704 return false; |
| 1615 } | 1705 } |
| 1616 | 1706 |
| 1617 | 1707 |
| 1618 Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, | 1708 Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| 1619 bool* ok) { | 1709 bool* ok) { |
| 1620 // ExpressionStatement | LabelledStatement :: | 1710 // ExpressionStatement | LabelledStatement :: |
| 1621 // Expression ';' | 1711 // Expression ';' |
| 1622 // Identifier ':' Statement | 1712 // Identifier ':' Statement |
| 1623 bool starts_with_idenfifier = (peek() == Token::IDENTIFIER); | 1713 bool starts_with_idenfifier = peek_any_identifier(); |
| 1624 Expression* expr = ParseExpression(true, CHECK_OK); | 1714 Expression* expr = ParseExpression(true, CHECK_OK); |
| 1625 if (peek() == Token::COLON && starts_with_idenfifier && expr && | 1715 if (peek() == Token::COLON && starts_with_idenfifier && expr && |
| 1626 expr->AsVariableProxy() != NULL && | 1716 expr->AsVariableProxy() != NULL && |
| 1627 !expr->AsVariableProxy()->is_this()) { | 1717 !expr->AsVariableProxy()->is_this()) { |
| 1628 // Expression is a single identifier, and not, e.g., a parenthesized | 1718 // Expression is a single identifier, and not, e.g., a parenthesized |
| 1629 // identifier. | 1719 // identifier. |
| 1630 VariableProxy* var = expr->AsVariableProxy(); | 1720 VariableProxy* var = expr->AsVariableProxy(); |
| 1631 Handle<String> label = var->name(); | 1721 Handle<String> label = var->name(); |
| 1632 // TODO(1240780): We don't check for redeclaration of labels | 1722 // TODO(1240780): We don't check for redeclaration of labels |
| 1633 // during preparsing since keeping track of the set of active | 1723 // during preparsing since keeping track of the set of active |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1685 Expect(Token::CONTINUE, CHECK_OK); | 1775 Expect(Token::CONTINUE, CHECK_OK); |
| 1686 Handle<String> label = Handle<String>::null(); | 1776 Handle<String> label = Handle<String>::null(); |
| 1687 Token::Value tok = peek(); | 1777 Token::Value tok = peek(); |
| 1688 if (!scanner().has_line_terminator_before_next() && | 1778 if (!scanner().has_line_terminator_before_next() && |
| 1689 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 1779 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| 1690 label = ParseIdentifier(CHECK_OK); | 1780 label = ParseIdentifier(CHECK_OK); |
| 1691 } | 1781 } |
| 1692 IterationStatement* target = NULL; | 1782 IterationStatement* target = NULL; |
| 1693 target = LookupContinueTarget(label, CHECK_OK); | 1783 target = LookupContinueTarget(label, CHECK_OK); |
| 1694 if (target == NULL) { | 1784 if (target == NULL) { |
| 1695 // Illegal continue statement. To be consistent with KJS we delay | 1785 // Illegal continue statement. |
| 1696 // reporting of the syntax error until runtime. | 1786 const char* message = "illegal_continue"; |
| 1697 Handle<String> error_type = Factory::illegal_continue_symbol(); | 1787 Vector<Handle<String> > args; |
| 1698 if (!label.is_null()) error_type = Factory::unknown_label_symbol(); | 1788 if (!label.is_null()) { |
| 1699 Expression* throw_error = NewThrowSyntaxError(error_type, label); | 1789 message = "unknown_label"; |
| 1700 return new ExpressionStatement(throw_error); | 1790 args = Vector<Handle<String> >(&label, 1); |
| 1791 } |
| 1792 ReportMessageAt(scanner().location(), message, args); |
| 1793 *ok = false; |
| 1794 return NULL; |
| 1701 } | 1795 } |
| 1702 ExpectSemicolon(CHECK_OK); | 1796 ExpectSemicolon(CHECK_OK); |
| 1703 return new ContinueStatement(target); | 1797 return new ContinueStatement(target); |
| 1704 } | 1798 } |
| 1705 | 1799 |
| 1706 | 1800 |
| 1707 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { | 1801 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| 1708 // BreakStatement :: | 1802 // BreakStatement :: |
| 1709 // 'break' Identifier? ';' | 1803 // 'break' Identifier? ';' |
| 1710 | 1804 |
| 1711 Expect(Token::BREAK, CHECK_OK); | 1805 Expect(Token::BREAK, CHECK_OK); |
| 1712 Handle<String> label; | 1806 Handle<String> label; |
| 1713 Token::Value tok = peek(); | 1807 Token::Value tok = peek(); |
| 1714 if (!scanner().has_line_terminator_before_next() && | 1808 if (!scanner().has_line_terminator_before_next() && |
| 1715 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 1809 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| 1716 label = ParseIdentifier(CHECK_OK); | 1810 label = ParseIdentifier(CHECK_OK); |
| 1717 } | 1811 } |
| 1718 // Parse labeled break statements that target themselves into | 1812 // Parse labeled break statements that target themselves into |
| 1719 // empty statements, e.g. 'l1: l2: l3: break l2;' | 1813 // empty statements, e.g. 'l1: l2: l3: break l2;' |
| 1720 if (!label.is_null() && ContainsLabel(labels, label)) { | 1814 if (!label.is_null() && ContainsLabel(labels, label)) { |
| 1721 return EmptyStatement(); | 1815 return EmptyStatement(); |
| 1722 } | 1816 } |
| 1723 BreakableStatement* target = NULL; | 1817 BreakableStatement* target = NULL; |
| 1724 target = LookupBreakTarget(label, CHECK_OK); | 1818 target = LookupBreakTarget(label, CHECK_OK); |
| 1725 if (target == NULL) { | 1819 if (target == NULL) { |
| 1726 // Illegal break statement. To be consistent with KJS we delay | 1820 // Illegal break statement. |
| 1727 // reporting of the syntax error until runtime. | 1821 const char* message = "illegal_break"; |
| 1728 Handle<String> error_type = Factory::illegal_break_symbol(); | 1822 Vector<Handle<String> > args; |
| 1729 if (!label.is_null()) error_type = Factory::unknown_label_symbol(); | 1823 if (!label.is_null()) { |
| 1730 Expression* throw_error = NewThrowSyntaxError(error_type, label); | 1824 message = "unknown_label"; |
| 1731 return new ExpressionStatement(throw_error); | 1825 args = Vector<Handle<String> >(&label, 1); |
| 1826 } |
| 1827 ReportMessageAt(scanner().location(), message, args); |
| 1828 *ok = false; |
| 1829 return NULL; |
| 1732 } | 1830 } |
| 1733 ExpectSemicolon(CHECK_OK); | 1831 ExpectSemicolon(CHECK_OK); |
| 1734 return new BreakStatement(target); | 1832 return new BreakStatement(target); |
| 1735 } | 1833 } |
| 1736 | 1834 |
| 1737 | 1835 |
| 1738 Statement* Parser::ParseReturnStatement(bool* ok) { | 1836 Statement* Parser::ParseReturnStatement(bool* ok) { |
| 1739 // ReturnStatement :: | 1837 // ReturnStatement :: |
| 1740 // 'return' Expression? ';' | 1838 // 'return' Expression? ';' |
| 1741 | 1839 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1807 } | 1905 } |
| 1808 return result; | 1906 return result; |
| 1809 } | 1907 } |
| 1810 | 1908 |
| 1811 | 1909 |
| 1812 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { | 1910 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
| 1813 // WithStatement :: | 1911 // WithStatement :: |
| 1814 // 'with' '(' Expression ')' Statement | 1912 // 'with' '(' Expression ')' Statement |
| 1815 | 1913 |
| 1816 Expect(Token::WITH, CHECK_OK); | 1914 Expect(Token::WITH, CHECK_OK); |
| 1915 |
| 1916 if (temp_scope_->StrictMode()) { |
| 1917 ReportMessage("strict_mode_with", Vector<const char*>::empty()); |
| 1918 *ok = false; |
| 1919 return NULL; |
| 1920 } |
| 1921 |
| 1817 Expect(Token::LPAREN, CHECK_OK); | 1922 Expect(Token::LPAREN, CHECK_OK); |
| 1818 Expression* expr = ParseExpression(true, CHECK_OK); | 1923 Expression* expr = ParseExpression(true, CHECK_OK); |
| 1819 Expect(Token::RPAREN, CHECK_OK); | 1924 Expect(Token::RPAREN, CHECK_OK); |
| 1820 | 1925 |
| 1821 return WithHelper(expr, labels, false, CHECK_OK); | 1926 return WithHelper(expr, labels, false, CHECK_OK); |
| 1822 } | 1927 } |
| 1823 | 1928 |
| 1824 | 1929 |
| 1825 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | 1930 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| 1826 // CaseClause :: | 1931 // CaseClause :: |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 // the jump targets. | 2044 // the jump targets. |
| 1940 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); | 2045 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); |
| 1941 TargetCollector catch_collector(catch_target_list); | 2046 TargetCollector catch_collector(catch_target_list); |
| 1942 bool has_catch = false; | 2047 bool has_catch = false; |
| 1943 if (tok == Token::CATCH) { | 2048 if (tok == Token::CATCH) { |
| 1944 has_catch = true; | 2049 has_catch = true; |
| 1945 Consume(Token::CATCH); | 2050 Consume(Token::CATCH); |
| 1946 | 2051 |
| 1947 Expect(Token::LPAREN, CHECK_OK); | 2052 Expect(Token::LPAREN, CHECK_OK); |
| 1948 Handle<String> name = ParseIdentifier(CHECK_OK); | 2053 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 2054 |
| 2055 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { |
| 2056 ReportMessage("strict_catch_variable", Vector<const char*>::empty()); |
| 2057 *ok = false; |
| 2058 return NULL; |
| 2059 } |
| 2060 |
| 1949 Expect(Token::RPAREN, CHECK_OK); | 2061 Expect(Token::RPAREN, CHECK_OK); |
| 1950 | 2062 |
| 1951 if (peek() == Token::LBRACE) { | 2063 if (peek() == Token::LBRACE) { |
| 1952 // Allocate a temporary for holding the finally state while | 2064 // Allocate a temporary for holding the finally state while |
| 1953 // executing the finally block. | 2065 // executing the finally block. |
| 1954 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); | 2066 catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol()); |
| 1955 Literal* name_literal = new Literal(name); | 2067 Literal* name_literal = new Literal(name); |
| 1956 VariableProxy* catch_var_use = new VariableProxy(catch_var); | 2068 VariableProxy* catch_var_use = new VariableProxy(catch_var); |
| 1957 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); | 2069 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); |
| 1958 { Target target(&this->target_stack_, &catch_collector); | 2070 { Target target(&this->target_stack_, &catch_collector); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2184 | 2296 |
| 2185 // Signal a reference error if the expression is an invalid left-hand | 2297 // Signal a reference error if the expression is an invalid left-hand |
| 2186 // side expression. We could report this as a syntax error here but | 2298 // side expression. We could report this as a syntax error here but |
| 2187 // for compatibility with JSC we choose to report the error at | 2299 // for compatibility with JSC we choose to report the error at |
| 2188 // runtime. | 2300 // runtime. |
| 2189 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2301 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
| 2190 Handle<String> type = Factory::invalid_lhs_in_assignment_symbol(); | 2302 Handle<String> type = Factory::invalid_lhs_in_assignment_symbol(); |
| 2191 expression = NewThrowReferenceError(type); | 2303 expression = NewThrowReferenceError(type); |
| 2192 } | 2304 } |
| 2193 | 2305 |
| 2306 if (temp_scope_->StrictMode()) { |
| 2307 // Assignment to eval or arguments is disallowed in strict mode. |
| 2308 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK); |
| 2309 } |
| 2310 |
| 2194 Token::Value op = Next(); // Get assignment operator. | 2311 Token::Value op = Next(); // Get assignment operator. |
| 2195 int pos = scanner().location().beg_pos; | 2312 int pos = scanner().location().beg_pos; |
| 2196 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK); | 2313 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 2197 | 2314 |
| 2198 // TODO(1231235): We try to estimate the set of properties set by | 2315 // TODO(1231235): We try to estimate the set of properties set by |
| 2199 // constructors. We define a new property whenever there is an | 2316 // constructors. We define a new property whenever there is an |
| 2200 // assignment to a property of 'this'. We should probably only add | 2317 // assignment to a property of 'this'. We should probably only add |
| 2201 // properties if we haven't seen them before. Otherwise we'll | 2318 // properties if we haven't seen them before. Otherwise we'll |
| 2202 // probably overestimate the number of properties. | 2319 // probably overestimate the number of properties. |
| 2203 Property* property = expression ? expression->AsProperty() : NULL; | 2320 Property* property = expression ? expression->AsProperty() : NULL; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2316 uint32_t shift = DoubleToInt32(y_val) & 0x1f; | 2433 uint32_t shift = DoubleToInt32(y_val) & 0x1f; |
| 2317 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); | 2434 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); |
| 2318 x = NewNumberLiteral(value); | 2435 x = NewNumberLiteral(value); |
| 2319 continue; | 2436 continue; |
| 2320 } | 2437 } |
| 2321 default: | 2438 default: |
| 2322 break; | 2439 break; |
| 2323 } | 2440 } |
| 2324 } | 2441 } |
| 2325 | 2442 |
| 2326 // Convert constant divisions to multiplications for speed. | |
| 2327 if (op == Token::DIV && | |
| 2328 y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) { | |
| 2329 double y_val = y->AsLiteral()->handle()->Number(); | |
| 2330 int64_t y_int = static_cast<int64_t>(y_val); | |
| 2331 // There are rounding issues with this optimization, but they don't | |
| 2332 // apply if the number to be divided with has a reciprocal that can be | |
| 2333 // precisely represented as a floating point number. This is the case | |
| 2334 // if the number is an integer power of 2. Negative integer powers of | |
| 2335 // 2 work too, but for -2, -1, 1 and 2 we don't do the strength | |
| 2336 // reduction because the inlined optimistic idiv has a reasonable | |
| 2337 // chance of succeeding by producing a Smi answer with no remainder. | |
| 2338 if (static_cast<double>(y_int) == y_val && | |
| 2339 (IsPowerOf2(y_int) || IsPowerOf2(-y_int)) && | |
| 2340 (y_int > 2 || y_int < -2)) { | |
| 2341 y = NewNumberLiteral(1 / y_val); | |
| 2342 op = Token::MUL; | |
| 2343 } | |
| 2344 } | |
| 2345 | |
| 2346 // For now we distinguish between comparisons and other binary | 2443 // For now we distinguish between comparisons and other binary |
| 2347 // operations. (We could combine the two and get rid of this | 2444 // operations. (We could combine the two and get rid of this |
| 2348 // code and AST node eventually.) | 2445 // code and AST node eventually.) |
| 2349 if (Token::IsCompareOp(op)) { | 2446 if (Token::IsCompareOp(op)) { |
| 2350 // We have a comparison. | 2447 // We have a comparison. |
| 2351 Token::Value cmp = op; | 2448 Token::Value cmp = op; |
| 2352 switch (op) { | 2449 switch (op) { |
| 2353 case Token::NE: cmp = Token::EQ; break; | 2450 case Token::NE: cmp = Token::EQ; break; |
| 2354 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; | 2451 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; |
| 2355 default: break; | 2452 default: break; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2417 case Token::ADD: | 2514 case Token::ADD: |
| 2418 return expression; | 2515 return expression; |
| 2419 case Token::SUB: | 2516 case Token::SUB: |
| 2420 return NewNumberLiteral(-value); | 2517 return NewNumberLiteral(-value); |
| 2421 case Token::BIT_NOT: | 2518 case Token::BIT_NOT: |
| 2422 return NewNumberLiteral(~DoubleToInt32(value)); | 2519 return NewNumberLiteral(~DoubleToInt32(value)); |
| 2423 default: break; | 2520 default: break; |
| 2424 } | 2521 } |
| 2425 } | 2522 } |
| 2426 | 2523 |
| 2524 // "delete identifier" is a syntax error in strict mode. |
| 2525 if (op == Token::DELETE && temp_scope_->StrictMode()) { |
| 2526 VariableProxy* operand = expression->AsVariableProxy(); |
| 2527 if (operand != NULL && !operand->is_this()) { |
| 2528 ReportMessage("strict_delete", Vector<const char*>::empty()); |
| 2529 *ok = false; |
| 2530 return NULL; |
| 2531 } |
| 2532 } |
| 2533 |
| 2427 return new UnaryOperation(op, expression); | 2534 return new UnaryOperation(op, expression); |
| 2428 | 2535 |
| 2429 } else if (Token::IsCountOp(op)) { | 2536 } else if (Token::IsCountOp(op)) { |
| 2430 op = Next(); | 2537 op = Next(); |
| 2431 Expression* expression = ParseUnaryExpression(CHECK_OK); | 2538 Expression* expression = ParseUnaryExpression(CHECK_OK); |
| 2432 // Signal a reference error if the expression is an invalid | 2539 // Signal a reference error if the expression is an invalid |
| 2433 // left-hand side expression. We could report this as a syntax | 2540 // left-hand side expression. We could report this as a syntax |
| 2434 // error here but for compatibility with JSC we choose to report the | 2541 // error here but for compatibility with JSC we choose to report the |
| 2435 // error at runtime. | 2542 // error at runtime. |
| 2436 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2543 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
| 2437 Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol(); | 2544 Handle<String> type = Factory::invalid_lhs_in_prefix_op_symbol(); |
| 2438 expression = NewThrowReferenceError(type); | 2545 expression = NewThrowReferenceError(type); |
| 2439 } | 2546 } |
| 2547 |
| 2548 if (temp_scope_->StrictMode()) { |
| 2549 // Prefix expression operand in strict mode may not be eval or arguments. |
| 2550 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); |
| 2551 } |
| 2552 |
| 2440 int position = scanner().location().beg_pos; | 2553 int position = scanner().location().beg_pos; |
| 2441 IncrementOperation* increment = new IncrementOperation(op, expression); | 2554 IncrementOperation* increment = new IncrementOperation(op, expression); |
| 2442 return new CountOperation(true /* prefix */, increment, position); | 2555 return new CountOperation(true /* prefix */, increment, position); |
| 2443 | 2556 |
| 2444 } else { | 2557 } else { |
| 2445 return ParsePostfixExpression(ok); | 2558 return ParsePostfixExpression(ok); |
| 2446 } | 2559 } |
| 2447 } | 2560 } |
| 2448 | 2561 |
| 2449 | 2562 |
| 2450 Expression* Parser::ParsePostfixExpression(bool* ok) { | 2563 Expression* Parser::ParsePostfixExpression(bool* ok) { |
| 2451 // PostfixExpression :: | 2564 // PostfixExpression :: |
| 2452 // LeftHandSideExpression ('++' | '--')? | 2565 // LeftHandSideExpression ('++' | '--')? |
| 2453 | 2566 |
| 2454 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); | 2567 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); |
| 2455 if (!scanner().has_line_terminator_before_next() && | 2568 if (!scanner().has_line_terminator_before_next() && |
| 2456 Token::IsCountOp(peek())) { | 2569 Token::IsCountOp(peek())) { |
| 2457 // Signal a reference error if the expression is an invalid | 2570 // Signal a reference error if the expression is an invalid |
| 2458 // left-hand side expression. We could report this as a syntax | 2571 // left-hand side expression. We could report this as a syntax |
| 2459 // error here but for compatibility with JSC we choose to report the | 2572 // error here but for compatibility with JSC we choose to report the |
| 2460 // error at runtime. | 2573 // error at runtime. |
| 2461 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2574 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
| 2462 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol(); | 2575 Handle<String> type = Factory::invalid_lhs_in_postfix_op_symbol(); |
| 2463 expression = NewThrowReferenceError(type); | 2576 expression = NewThrowReferenceError(type); |
| 2464 } | 2577 } |
| 2578 |
| 2579 if (temp_scope_->StrictMode()) { |
| 2580 // Postfix expression operand in strict mode may not be eval or arguments. |
| 2581 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); |
| 2582 } |
| 2583 |
| 2465 Token::Value next = Next(); | 2584 Token::Value next = Next(); |
| 2466 int position = scanner().location().beg_pos; | 2585 int position = scanner().location().beg_pos; |
| 2467 IncrementOperation* increment = new IncrementOperation(next, expression); | 2586 IncrementOperation* increment = new IncrementOperation(next, expression); |
| 2468 expression = new CountOperation(false /* postfix */, increment, position); | 2587 expression = new CountOperation(false /* postfix */, increment, position); |
| 2469 } | 2588 } |
| 2470 return expression; | 2589 return expression; |
| 2471 } | 2590 } |
| 2472 | 2591 |
| 2473 | 2592 |
| 2474 Expression* Parser::ParseLeftHandSideExpression(bool* ok) { | 2593 Expression* Parser::ParseLeftHandSideExpression(bool* ok) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2495 | 2614 |
| 2496 case Token::LPAREN: { | 2615 case Token::LPAREN: { |
| 2497 int pos = scanner().location().beg_pos; | 2616 int pos = scanner().location().beg_pos; |
| 2498 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); | 2617 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
| 2499 | 2618 |
| 2500 // Keep track of eval() calls since they disable all local variable | 2619 // Keep track of eval() calls since they disable all local variable |
| 2501 // optimizations. | 2620 // optimizations. |
| 2502 // The calls that need special treatment are the | 2621 // The calls that need special treatment are the |
| 2503 // direct (i.e. not aliased) eval calls. These calls are all of the | 2622 // direct (i.e. not aliased) eval calls. These calls are all of the |
| 2504 // form eval(...) with no explicit receiver object where eval is not | 2623 // form eval(...) with no explicit receiver object where eval is not |
| 2505 // declared in the current scope chain. These calls are marked as | 2624 // declared in the current scope chain. |
| 2506 // potentially direct eval calls. Whether they are actually direct calls | 2625 // These calls are marked as potentially direct eval calls. Whether |
| 2507 // to eval is determined at run time. | 2626 // they are actually direct calls to eval is determined at run time. |
| 2627 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared |
| 2628 // in the local scope chain. It only matters that it's called "eval", |
| 2629 // is called without a receiver and it refers to the original eval |
| 2630 // function. |
| 2508 VariableProxy* callee = result->AsVariableProxy(); | 2631 VariableProxy* callee = result->AsVariableProxy(); |
| 2509 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { | 2632 if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { |
| 2510 Handle<String> name = callee->name(); | 2633 Handle<String> name = callee->name(); |
| 2511 Variable* var = top_scope_->Lookup(name); | 2634 Variable* var = top_scope_->Lookup(name); |
| 2512 if (var == NULL) { | 2635 if (var == NULL) { |
| 2513 top_scope_->RecordEvalCall(); | 2636 top_scope_->RecordEvalCall(); |
| 2514 } | 2637 } |
| 2515 } | 2638 } |
| 2516 result = NewCall(result, args, pos); | 2639 result = NewCall(result, args, pos); |
| 2517 break; | 2640 break; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2579 // MemberExpression :: | 2702 // MemberExpression :: |
| 2580 // (PrimaryExpression | FunctionLiteral) | 2703 // (PrimaryExpression | FunctionLiteral) |
| 2581 // ('[' Expression ']' | '.' Identifier | Arguments)* | 2704 // ('[' Expression ']' | '.' Identifier | Arguments)* |
| 2582 | 2705 |
| 2583 // Parse the initial primary or function expression. | 2706 // Parse the initial primary or function expression. |
| 2584 Expression* result = NULL; | 2707 Expression* result = NULL; |
| 2585 if (peek() == Token::FUNCTION) { | 2708 if (peek() == Token::FUNCTION) { |
| 2586 Expect(Token::FUNCTION, CHECK_OK); | 2709 Expect(Token::FUNCTION, CHECK_OK); |
| 2587 int function_token_position = scanner().location().beg_pos; | 2710 int function_token_position = scanner().location().beg_pos; |
| 2588 Handle<String> name; | 2711 Handle<String> name; |
| 2589 if (peek() == Token::IDENTIFIER) name = ParseIdentifier(CHECK_OK); | 2712 bool is_reserved_name = false; |
| 2590 result = ParseFunctionLiteral(name, function_token_position, | 2713 if (peek_any_identifier()) { |
| 2591 NESTED, CHECK_OK); | 2714 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK); |
| 2715 } |
| 2716 result = ParseFunctionLiteral(name, is_reserved_name, |
| 2717 function_token_position, NESTED, CHECK_OK); |
| 2592 } else { | 2718 } else { |
| 2593 result = ParsePrimaryExpression(CHECK_OK); | 2719 result = ParsePrimaryExpression(CHECK_OK); |
| 2594 } | 2720 } |
| 2595 | 2721 |
| 2596 while (true) { | 2722 while (true) { |
| 2597 switch (peek()) { | 2723 switch (peek()) { |
| 2598 case Token::LBRACK: { | 2724 case Token::LBRACK: { |
| 2599 Consume(Token::LBRACK); | 2725 Consume(Token::LBRACK); |
| 2600 int pos = scanner().location().beg_pos; | 2726 int pos = scanner().location().beg_pos; |
| 2601 Expression* index = ParseExpression(true, CHECK_OK); | 2727 Expression* index = ParseExpression(true, CHECK_OK); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 return ReportMessage("unexpected_eos", Vector<const char*>::empty()); | 2776 return ReportMessage("unexpected_eos", Vector<const char*>::empty()); |
| 2651 case Token::NUMBER: | 2777 case Token::NUMBER: |
| 2652 return ReportMessage("unexpected_token_number", | 2778 return ReportMessage("unexpected_token_number", |
| 2653 Vector<const char*>::empty()); | 2779 Vector<const char*>::empty()); |
| 2654 case Token::STRING: | 2780 case Token::STRING: |
| 2655 return ReportMessage("unexpected_token_string", | 2781 return ReportMessage("unexpected_token_string", |
| 2656 Vector<const char*>::empty()); | 2782 Vector<const char*>::empty()); |
| 2657 case Token::IDENTIFIER: | 2783 case Token::IDENTIFIER: |
| 2658 return ReportMessage("unexpected_token_identifier", | 2784 return ReportMessage("unexpected_token_identifier", |
| 2659 Vector<const char*>::empty()); | 2785 Vector<const char*>::empty()); |
| 2786 case Token::FUTURE_RESERVED_WORD: |
| 2787 return ReportMessage(temp_scope_->StrictMode() ? |
| 2788 "unexpected_strict_reserved" : |
| 2789 "unexpected_token_identifier", |
| 2790 Vector<const char*>::empty()); |
| 2660 default: | 2791 default: |
| 2661 const char* name = Token::String(token); | 2792 const char* name = Token::String(token); |
| 2662 ASSERT(name != NULL); | 2793 ASSERT(name != NULL); |
| 2663 ReportMessage("unexpected_token", Vector<const char*>(&name, 1)); | 2794 ReportMessage("unexpected_token", Vector<const char*>(&name, 1)); |
| 2664 } | 2795 } |
| 2665 } | 2796 } |
| 2666 | 2797 |
| 2667 | 2798 |
| 2668 void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) { | 2799 void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) { |
| 2669 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS); | 2800 SmartPointer<char> name_string = name->ToCString(DISALLOW_NULLS); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2705 case Token::TRUE_LITERAL: | 2836 case Token::TRUE_LITERAL: |
| 2706 Consume(Token::TRUE_LITERAL); | 2837 Consume(Token::TRUE_LITERAL); |
| 2707 result = new Literal(Factory::true_value()); | 2838 result = new Literal(Factory::true_value()); |
| 2708 break; | 2839 break; |
| 2709 | 2840 |
| 2710 case Token::FALSE_LITERAL: | 2841 case Token::FALSE_LITERAL: |
| 2711 Consume(Token::FALSE_LITERAL); | 2842 Consume(Token::FALSE_LITERAL); |
| 2712 result = new Literal(Factory::false_value()); | 2843 result = new Literal(Factory::false_value()); |
| 2713 break; | 2844 break; |
| 2714 | 2845 |
| 2715 case Token::IDENTIFIER: { | 2846 case Token::IDENTIFIER: |
| 2847 case Token::FUTURE_RESERVED_WORD: { |
| 2716 Handle<String> name = ParseIdentifier(CHECK_OK); | 2848 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 2717 if (fni_ != NULL) fni_->PushVariableName(name); | 2849 if (fni_ != NULL) fni_->PushVariableName(name); |
| 2718 result = top_scope_->NewUnresolved(name, inside_with()); | 2850 result = top_scope_->NewUnresolved(name, inside_with()); |
| 2719 break; | 2851 break; |
| 2720 } | 2852 } |
| 2721 | 2853 |
| 2722 case Token::NUMBER: { | 2854 case Token::NUMBER: { |
| 2723 Consume(Token::NUMBER); | 2855 Consume(Token::NUMBER); |
| 2724 ASSERT(scanner().is_literal_ascii()); | 2856 ASSERT(scanner().is_literal_ascii()); |
| 2725 double value = StringToDouble(scanner().literal_ascii_string(), | 2857 double value = StringToDouble(scanner().literal_ascii_string(), |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2747 case Token::LBRACK: | 2879 case Token::LBRACK: |
| 2748 result = ParseArrayLiteral(CHECK_OK); | 2880 result = ParseArrayLiteral(CHECK_OK); |
| 2749 break; | 2881 break; |
| 2750 | 2882 |
| 2751 case Token::LBRACE: | 2883 case Token::LBRACE: |
| 2752 result = ParseObjectLiteral(CHECK_OK); | 2884 result = ParseObjectLiteral(CHECK_OK); |
| 2753 break; | 2885 break; |
| 2754 | 2886 |
| 2755 case Token::LPAREN: | 2887 case Token::LPAREN: |
| 2756 Consume(Token::LPAREN); | 2888 Consume(Token::LPAREN); |
| 2889 // Heuristically try to detect immediately called functions before |
| 2890 // seeing the call parentheses. |
| 2891 parenthesized_function_ = (peek() == Token::FUNCTION); |
| 2757 result = ParseExpression(true, CHECK_OK); | 2892 result = ParseExpression(true, CHECK_OK); |
| 2758 Expect(Token::RPAREN, CHECK_OK); | 2893 Expect(Token::RPAREN, CHECK_OK); |
| 2759 break; | 2894 break; |
| 2760 | 2895 |
| 2761 case Token::MOD: | 2896 case Token::MOD: |
| 2762 if (allow_natives_syntax_ || extension_ != NULL) { | 2897 if (allow_natives_syntax_ || extension_ != NULL) { |
| 2763 result = ParseV8Intrinsic(CHECK_OK); | 2898 result = ParseV8Intrinsic(CHECK_OK); |
| 2764 break; | 2899 break; |
| 2765 } | 2900 } |
| 2766 // If we're not allowing special syntax we fall-through to the | 2901 // If we're not allowing special syntax we fall-through to the |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2921 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { | 3056 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { |
| 2922 if (expression->AsLiteral() != NULL) { | 3057 if (expression->AsLiteral() != NULL) { |
| 2923 return expression->AsLiteral()->handle(); | 3058 return expression->AsLiteral()->handle(); |
| 2924 } | 3059 } |
| 2925 if (CompileTimeValue::IsCompileTimeValue(expression)) { | 3060 if (CompileTimeValue::IsCompileTimeValue(expression)) { |
| 2926 return CompileTimeValue::GetValue(expression); | 3061 return CompileTimeValue::GetValue(expression); |
| 2927 } | 3062 } |
| 2928 return Factory::undefined_value(); | 3063 return Factory::undefined_value(); |
| 2929 } | 3064 } |
| 2930 | 3065 |
| 3066 // Defined in ast.cc |
| 3067 bool IsEqualString(void* first, void* second); |
| 3068 bool IsEqualNumber(void* first, void* second); |
| 3069 |
| 3070 |
| 3071 // Validation per 11.1.5 Object Initialiser |
| 3072 class ObjectLiteralPropertyChecker { |
| 3073 public: |
| 3074 ObjectLiteralPropertyChecker(Parser* parser, bool strict) : |
| 3075 props(&IsEqualString), |
| 3076 elems(&IsEqualNumber), |
| 3077 parser_(parser), |
| 3078 strict_(strict) { |
| 3079 } |
| 3080 |
| 3081 void CheckProperty( |
| 3082 ObjectLiteral::Property* property, |
| 3083 Scanner::Location loc, |
| 3084 bool* ok); |
| 3085 |
| 3086 private: |
| 3087 enum PropertyKind { |
| 3088 kGetAccessor = 0x01, |
| 3089 kSetAccessor = 0x02, |
| 3090 kAccessor = kGetAccessor | kSetAccessor, |
| 3091 kData = 0x04 |
| 3092 }; |
| 3093 |
| 3094 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) { |
| 3095 switch (property->kind()) { |
| 3096 case ObjectLiteral::Property::GETTER: |
| 3097 return kGetAccessor; |
| 3098 case ObjectLiteral::Property::SETTER: |
| 3099 return kSetAccessor; |
| 3100 default: |
| 3101 return kData; |
| 3102 } |
| 3103 } |
| 3104 |
| 3105 HashMap props; |
| 3106 HashMap elems; |
| 3107 Parser* parser_; |
| 3108 bool strict_; |
| 3109 }; |
| 3110 |
| 3111 |
| 3112 void ObjectLiteralPropertyChecker::CheckProperty( |
| 3113 ObjectLiteral::Property* property, |
| 3114 Scanner::Location loc, |
| 3115 bool* ok) { |
| 3116 |
| 3117 ASSERT(property != NULL); |
| 3118 |
| 3119 Literal *lit = property->key(); |
| 3120 Handle<Object> handle = lit->handle(); |
| 3121 |
| 3122 uint32_t hash; |
| 3123 HashMap* map; |
| 3124 void* key; |
| 3125 |
| 3126 if (handle->IsSymbol()) { |
| 3127 Handle<String> name(String::cast(*handle)); |
| 3128 if (name->AsArrayIndex(&hash)) { |
| 3129 Handle<Object> key_handle = Factory::NewNumberFromUint(hash); |
| 3130 key = key_handle.location(); |
| 3131 map = &elems; |
| 3132 } else { |
| 3133 key = handle.location(); |
| 3134 hash = name->Hash(); |
| 3135 map = &props; |
| 3136 } |
| 3137 } else if (handle->ToArrayIndex(&hash)) { |
| 3138 key = handle.location(); |
| 3139 map = &elems; |
| 3140 } else { |
| 3141 ASSERT(handle->IsNumber()); |
| 3142 double num = handle->Number(); |
| 3143 char arr[100]; |
| 3144 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 3145 const char* str = DoubleToCString(num, buffer); |
| 3146 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); |
| 3147 key = name.location(); |
| 3148 hash = name->Hash(); |
| 3149 map = &props; |
| 3150 } |
| 3151 |
| 3152 // Lookup property previously defined, if any. |
| 3153 HashMap::Entry* entry = map->Lookup(key, hash, true); |
| 3154 intptr_t prev = reinterpret_cast<intptr_t> (entry->value); |
| 3155 intptr_t curr = GetPropertyKind(property); |
| 3156 |
| 3157 // Duplicate data properties are illegal in strict mode. |
| 3158 if (strict_ && (curr & prev & kData) != 0) { |
| 3159 parser_->ReportMessageAt(loc, "strict_duplicate_property", |
| 3160 Vector<const char*>::empty()); |
| 3161 *ok = false; |
| 3162 return; |
| 3163 } |
| 3164 // Data property conflicting with an accessor. |
| 3165 if (((curr & kData) && (prev & kAccessor)) || |
| 3166 ((prev & kData) && (curr & kAccessor))) { |
| 3167 parser_->ReportMessageAt(loc, "accessor_data_property", |
| 3168 Vector<const char*>::empty()); |
| 3169 *ok = false; |
| 3170 return; |
| 3171 } |
| 3172 // Two accessors of the same type conflicting |
| 3173 if ((curr & prev & kAccessor) != 0) { |
| 3174 parser_->ReportMessageAt(loc, "accessor_get_set", |
| 3175 Vector<const char*>::empty()); |
| 3176 *ok = false; |
| 3177 return; |
| 3178 } |
| 3179 |
| 3180 // Update map |
| 3181 entry->value = reinterpret_cast<void*> (prev | curr); |
| 3182 *ok = true; |
| 3183 } |
| 3184 |
| 2931 | 3185 |
| 2932 void Parser::BuildObjectLiteralConstantProperties( | 3186 void Parser::BuildObjectLiteralConstantProperties( |
| 2933 ZoneList<ObjectLiteral::Property*>* properties, | 3187 ZoneList<ObjectLiteral::Property*>* properties, |
| 2934 Handle<FixedArray> constant_properties, | 3188 Handle<FixedArray> constant_properties, |
| 2935 bool* is_simple, | 3189 bool* is_simple, |
| 2936 bool* fast_elements, | 3190 bool* fast_elements, |
| 2937 int* depth) { | 3191 int* depth) { |
| 2938 int position = 0; | 3192 int position = 0; |
| 2939 // Accumulate the value in local variables and store it at the end. | 3193 // Accumulate the value in local variables and store it at the end. |
| 2940 bool is_simple_acc = true; | 3194 bool is_simple_acc = true; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2990 | 3244 |
| 2991 | 3245 |
| 2992 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, | 3246 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, |
| 2993 bool* ok) { | 3247 bool* ok) { |
| 2994 // Special handling of getter and setter syntax: | 3248 // Special handling of getter and setter syntax: |
| 2995 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | 3249 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
| 2996 // We have already read the "get" or "set" keyword. | 3250 // We have already read the "get" or "set" keyword. |
| 2997 Token::Value next = Next(); | 3251 Token::Value next = Next(); |
| 2998 bool is_keyword = Token::IsKeyword(next); | 3252 bool is_keyword = Token::IsKeyword(next); |
| 2999 if (next == Token::IDENTIFIER || next == Token::NUMBER || | 3253 if (next == Token::IDENTIFIER || next == Token::NUMBER || |
| 3254 next == Token::FUTURE_RESERVED_WORD || |
| 3000 next == Token::STRING || is_keyword) { | 3255 next == Token::STRING || is_keyword) { |
| 3001 Handle<String> name; | 3256 Handle<String> name; |
| 3002 if (is_keyword) { | 3257 if (is_keyword) { |
| 3003 name = Factory::LookupAsciiSymbol(Token::String(next)); | 3258 name = Factory::LookupAsciiSymbol(Token::String(next)); |
| 3004 } else { | 3259 } else { |
| 3005 name = GetSymbol(CHECK_OK); | 3260 name = GetSymbol(CHECK_OK); |
| 3006 } | 3261 } |
| 3007 FunctionLiteral* value = | 3262 FunctionLiteral* value = |
| 3008 ParseFunctionLiteral(name, | 3263 ParseFunctionLiteral(name, |
| 3264 false, // reserved words are allowed here |
| 3009 RelocInfo::kNoPosition, | 3265 RelocInfo::kNoPosition, |
| 3010 DECLARATION, | 3266 DECLARATION, |
| 3011 CHECK_OK); | 3267 CHECK_OK); |
| 3012 // Allow any number of parameters for compatiabilty with JSC. | 3268 // Allow any number of parameters for compatiabilty with JSC. |
| 3013 // Specification only allows zero parameters for get and one for set. | 3269 // Specification only allows zero parameters for get and one for set. |
| 3014 ObjectLiteral::Property* property = | 3270 ObjectLiteral::Property* property = |
| 3015 new ObjectLiteral::Property(is_getter, value); | 3271 new ObjectLiteral::Property(is_getter, value); |
| 3016 return property; | 3272 return property; |
| 3017 } else { | 3273 } else { |
| 3018 ReportUnexpectedToken(next); | 3274 ReportUnexpectedToken(next); |
| 3019 *ok = false; | 3275 *ok = false; |
| 3020 return NULL; | 3276 return NULL; |
| 3021 } | 3277 } |
| 3022 } | 3278 } |
| 3023 | 3279 |
| 3024 | 3280 |
| 3025 Expression* Parser::ParseObjectLiteral(bool* ok) { | 3281 Expression* Parser::ParseObjectLiteral(bool* ok) { |
| 3026 // ObjectLiteral :: | 3282 // ObjectLiteral :: |
| 3027 // '{' ( | 3283 // '{' ( |
| 3028 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 3284 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 3029 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 3285 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 3030 // )*[','] '}' | 3286 // )*[','] '}' |
| 3031 | 3287 |
| 3032 ZoneList<ObjectLiteral::Property*>* properties = | 3288 ZoneList<ObjectLiteral::Property*>* properties = |
| 3033 new ZoneList<ObjectLiteral::Property*>(4); | 3289 new ZoneList<ObjectLiteral::Property*>(4); |
| 3034 int number_of_boilerplate_properties = 0; | 3290 int number_of_boilerplate_properties = 0; |
| 3035 | 3291 |
| 3292 ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode()); |
| 3293 |
| 3036 Expect(Token::LBRACE, CHECK_OK); | 3294 Expect(Token::LBRACE, CHECK_OK); |
| 3295 Scanner::Location loc = scanner().location(); |
| 3296 |
| 3037 while (peek() != Token::RBRACE) { | 3297 while (peek() != Token::RBRACE) { |
| 3038 if (fni_ != NULL) fni_->Enter(); | 3298 if (fni_ != NULL) fni_->Enter(); |
| 3039 | 3299 |
| 3040 Literal* key = NULL; | 3300 Literal* key = NULL; |
| 3041 Token::Value next = peek(); | 3301 Token::Value next = peek(); |
| 3302 |
| 3303 // Location of the property name token |
| 3304 Scanner::Location loc = scanner().peek_location(); |
| 3305 |
| 3042 switch (next) { | 3306 switch (next) { |
| 3307 case Token::FUTURE_RESERVED_WORD: |
| 3043 case Token::IDENTIFIER: { | 3308 case Token::IDENTIFIER: { |
| 3044 bool is_getter = false; | 3309 bool is_getter = false; |
| 3045 bool is_setter = false; | 3310 bool is_setter = false; |
| 3046 Handle<String> id = | 3311 Handle<String> id = |
| 3047 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3312 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 3048 if (fni_ != NULL) fni_->PushLiteralName(id); | 3313 if (fni_ != NULL) fni_->PushLiteralName(id); |
| 3049 | 3314 |
| 3050 if ((is_getter || is_setter) && peek() != Token::COLON) { | 3315 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 3316 // Update loc to point to the identifier |
| 3317 loc = scanner().peek_location(); |
| 3051 ObjectLiteral::Property* property = | 3318 ObjectLiteral::Property* property = |
| 3052 ParseObjectLiteralGetSet(is_getter, CHECK_OK); | 3319 ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
| 3053 if (IsBoilerplateProperty(property)) { | 3320 if (IsBoilerplateProperty(property)) { |
| 3054 number_of_boilerplate_properties++; | 3321 number_of_boilerplate_properties++; |
| 3055 } | 3322 } |
| 3323 // Validate the property. |
| 3324 checker.CheckProperty(property, loc, CHECK_OK); |
| 3056 properties->Add(property); | 3325 properties->Add(property); |
| 3057 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3326 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3058 | 3327 |
| 3059 if (fni_ != NULL) { | 3328 if (fni_ != NULL) { |
| 3060 fni_->Infer(); | 3329 fni_->Infer(); |
| 3061 fni_->Leave(); | 3330 fni_->Leave(); |
| 3062 } | 3331 } |
| 3063 continue; // restart the while | 3332 continue; // restart the while |
| 3064 } | 3333 } |
| 3065 // Failed to parse as get/set property, so it's just a property | 3334 // Failed to parse as get/set property, so it's just a property |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3102 } | 3371 } |
| 3103 | 3372 |
| 3104 Expect(Token::COLON, CHECK_OK); | 3373 Expect(Token::COLON, CHECK_OK); |
| 3105 Expression* value = ParseAssignmentExpression(true, CHECK_OK); | 3374 Expression* value = ParseAssignmentExpression(true, CHECK_OK); |
| 3106 | 3375 |
| 3107 ObjectLiteral::Property* property = | 3376 ObjectLiteral::Property* property = |
| 3108 new ObjectLiteral::Property(key, value); | 3377 new ObjectLiteral::Property(key, value); |
| 3109 | 3378 |
| 3110 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 3379 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| 3111 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; | 3380 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; |
| 3381 // Validate the property |
| 3382 checker.CheckProperty(property, loc, CHECK_OK); |
| 3112 properties->Add(property); | 3383 properties->Add(property); |
| 3113 | 3384 |
| 3114 // TODO(1240767): Consider allowing trailing comma. | 3385 // TODO(1240767): Consider allowing trailing comma. |
| 3115 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3386 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3116 | 3387 |
| 3117 if (fni_ != NULL) { | 3388 if (fni_ != NULL) { |
| 3118 fni_->Infer(); | 3389 fni_->Infer(); |
| 3119 fni_->Leave(); | 3390 fni_->Leave(); |
| 3120 } | 3391 } |
| 3121 } | 3392 } |
| 3122 Expect(Token::RBRACE, CHECK_OK); | 3393 Expect(Token::RBRACE, CHECK_OK); |
| 3394 |
| 3123 // Computation of literal_index must happen before pre parse bailout. | 3395 // Computation of literal_index must happen before pre parse bailout. |
| 3124 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3396 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
| 3125 | 3397 |
| 3126 Handle<FixedArray> constant_properties = | 3398 Handle<FixedArray> constant_properties = |
| 3127 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); | 3399 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); |
| 3128 | 3400 |
| 3129 bool is_simple = true; | 3401 bool is_simple = true; |
| 3130 bool fast_elements = true; | 3402 bool fast_elements = true; |
| 3131 int depth = 1; | 3403 int depth = 1; |
| 3132 BuildObjectLiteralConstantProperties(properties, | 3404 BuildObjectLiteralConstantProperties(properties, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3174 result->Add(argument); | 3446 result->Add(argument); |
| 3175 done = (peek() == Token::RPAREN); | 3447 done = (peek() == Token::RPAREN); |
| 3176 if (!done) Expect(Token::COMMA, CHECK_OK); | 3448 if (!done) Expect(Token::COMMA, CHECK_OK); |
| 3177 } | 3449 } |
| 3178 Expect(Token::RPAREN, CHECK_OK); | 3450 Expect(Token::RPAREN, CHECK_OK); |
| 3179 return result; | 3451 return result; |
| 3180 } | 3452 } |
| 3181 | 3453 |
| 3182 | 3454 |
| 3183 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, | 3455 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, |
| 3456 bool name_is_reserved, |
| 3184 int function_token_position, | 3457 int function_token_position, |
| 3185 FunctionLiteralType type, | 3458 FunctionLiteralType type, |
| 3186 bool* ok) { | 3459 bool* ok) { |
| 3187 // Function :: | 3460 // Function :: |
| 3188 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 3461 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 3189 bool is_named = !var_name.is_null(); | 3462 bool is_named = !var_name.is_null(); |
| 3190 | 3463 |
| 3191 // The name associated with this function. If it's a function expression, | 3464 // The name associated with this function. If it's a function expression, |
| 3192 // this is the actual function name, otherwise this is the name of the | 3465 // this is the actual function name, otherwise this is the name of the |
| 3193 // variable declared and initialized with the function (expression). In | 3466 // variable declared and initialized with the function (expression). In |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3205 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); | 3478 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); |
| 3206 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, | 3479 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, |
| 3207 scope); | 3480 scope); |
| 3208 TemporaryScope temp_scope(&this->temp_scope_); | 3481 TemporaryScope temp_scope(&this->temp_scope_); |
| 3209 top_scope_->SetScopeName(name); | 3482 top_scope_->SetScopeName(name); |
| 3210 | 3483 |
| 3211 // FormalParameterList :: | 3484 // FormalParameterList :: |
| 3212 // '(' (Identifier)*[','] ')' | 3485 // '(' (Identifier)*[','] ')' |
| 3213 Expect(Token::LPAREN, CHECK_OK); | 3486 Expect(Token::LPAREN, CHECK_OK); |
| 3214 int start_pos = scanner().location().beg_pos; | 3487 int start_pos = scanner().location().beg_pos; |
| 3488 Scanner::Location name_loc = Scanner::NoLocation(); |
| 3489 Scanner::Location dupe_loc = Scanner::NoLocation(); |
| 3490 Scanner::Location reserved_loc = Scanner::NoLocation(); |
| 3491 |
| 3215 bool done = (peek() == Token::RPAREN); | 3492 bool done = (peek() == Token::RPAREN); |
| 3216 while (!done) { | 3493 while (!done) { |
| 3217 Handle<String> param_name = ParseIdentifier(CHECK_OK); | 3494 bool is_reserved = false; |
| 3218 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name, | 3495 Handle<String> param_name = |
| 3219 Variable::VAR)); | 3496 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK); |
| 3497 |
| 3498 // Store locations for possible future error reports. |
| 3499 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) { |
| 3500 name_loc = scanner().location(); |
| 3501 } |
| 3502 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) { |
| 3503 dupe_loc = scanner().location(); |
| 3504 } |
| 3505 if (!reserved_loc.IsValid() && is_reserved) { |
| 3506 reserved_loc = scanner().location(); |
| 3507 } |
| 3508 |
| 3509 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR); |
| 3510 top_scope_->AddParameter(parameter); |
| 3220 num_parameters++; | 3511 num_parameters++; |
| 3512 if (num_parameters > kMaxNumFunctionParameters) { |
| 3513 ReportMessageAt(scanner().location(), "too_many_parameters", |
| 3514 Vector<const char*>::empty()); |
| 3515 *ok = false; |
| 3516 return NULL; |
| 3517 } |
| 3221 done = (peek() == Token::RPAREN); | 3518 done = (peek() == Token::RPAREN); |
| 3222 if (!done) Expect(Token::COMMA, CHECK_OK); | 3519 if (!done) Expect(Token::COMMA, CHECK_OK); |
| 3223 } | 3520 } |
| 3224 Expect(Token::RPAREN, CHECK_OK); | 3521 Expect(Token::RPAREN, CHECK_OK); |
| 3225 | 3522 |
| 3226 Expect(Token::LBRACE, CHECK_OK); | 3523 Expect(Token::LBRACE, CHECK_OK); |
| 3227 ZoneList<Statement*>* body = new ZoneList<Statement*>(8); | 3524 ZoneList<Statement*>* body = new ZoneList<Statement*>(8); |
| 3228 | 3525 |
| 3229 // If we have a named function expression, we add a local variable | 3526 // If we have a named function expression, we add a local variable |
| 3230 // declaration to the body of the function with the name of the | 3527 // declaration to the body of the function with the name of the |
| 3231 // function and let it refer to the function itself (closure). | 3528 // function and let it refer to the function itself (closure). |
| 3232 // NOTE: We create a proxy and resolve it here so that in the | 3529 // NOTE: We create a proxy and resolve it here so that in the |
| 3233 // future we can change the AST to only refer to VariableProxies | 3530 // future we can change the AST to only refer to VariableProxies |
| 3234 // instead of Variables and Proxis as is the case now. | 3531 // instead of Variables and Proxis as is the case now. |
| 3235 if (!function_name.is_null() && function_name->length() > 0) { | 3532 if (!function_name.is_null() && function_name->length() > 0) { |
| 3236 Variable* fvar = top_scope_->DeclareFunctionVar(function_name); | 3533 Variable* fvar = top_scope_->DeclareFunctionVar(function_name); |
| 3237 VariableProxy* fproxy = | 3534 VariableProxy* fproxy = |
| 3238 top_scope_->NewUnresolved(function_name, inside_with()); | 3535 top_scope_->NewUnresolved(function_name, inside_with()); |
| 3239 fproxy->BindTo(fvar); | 3536 fproxy->BindTo(fvar); |
| 3240 body->Add(new ExpressionStatement( | 3537 body->Add(new ExpressionStatement( |
| 3241 new Assignment(Token::INIT_CONST, fproxy, | 3538 new Assignment(Token::INIT_CONST, fproxy, |
| 3242 new ThisFunction(), | 3539 new ThisFunction(), |
| 3243 RelocInfo::kNoPosition))); | 3540 RelocInfo::kNoPosition))); |
| 3244 } | 3541 } |
| 3245 | 3542 |
| 3246 // Determine if the function will be lazily compiled. The mode can | 3543 // Determine if the function will be lazily compiled. The mode can |
| 3247 // only be PARSE_LAZILY if the --lazy flag is true. | 3544 // only be PARSE_LAZILY if the --lazy flag is true. |
| 3248 bool is_lazily_compiled = | 3545 bool is_lazily_compiled = (mode() == PARSE_LAZILY && |
| 3249 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); | 3546 top_scope_->outer_scope()->is_global_scope() && |
| 3547 top_scope_->HasTrivialOuterContext() && |
| 3548 !parenthesized_function_); |
| 3549 parenthesized_function_ = false; // The bit was set for this function only. |
| 3250 | 3550 |
| 3251 int function_block_pos = scanner().location().beg_pos; | 3551 int function_block_pos = scanner().location().beg_pos; |
| 3252 int materialized_literal_count; | 3552 int materialized_literal_count; |
| 3253 int expected_property_count; | 3553 int expected_property_count; |
| 3254 int end_pos; | 3554 int end_pos; |
| 3255 bool only_simple_this_property_assignments; | 3555 bool only_simple_this_property_assignments; |
| 3256 Handle<FixedArray> this_property_assignments; | 3556 Handle<FixedArray> this_property_assignments; |
| 3257 if (is_lazily_compiled && pre_data() != NULL) { | 3557 if (is_lazily_compiled && pre_data() != NULL) { |
| 3258 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); | 3558 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); |
| 3259 if (!entry.is_valid()) { | 3559 if (!entry.is_valid()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3278 materialized_literal_count = temp_scope.materialized_literal_count(); | 3578 materialized_literal_count = temp_scope.materialized_literal_count(); |
| 3279 expected_property_count = temp_scope.expected_property_count(); | 3579 expected_property_count = temp_scope.expected_property_count(); |
| 3280 only_simple_this_property_assignments = | 3580 only_simple_this_property_assignments = |
| 3281 temp_scope.only_simple_this_property_assignments(); | 3581 temp_scope.only_simple_this_property_assignments(); |
| 3282 this_property_assignments = temp_scope.this_property_assignments(); | 3582 this_property_assignments = temp_scope.this_property_assignments(); |
| 3283 | 3583 |
| 3284 Expect(Token::RBRACE, CHECK_OK); | 3584 Expect(Token::RBRACE, CHECK_OK); |
| 3285 end_pos = scanner().location().end_pos; | 3585 end_pos = scanner().location().end_pos; |
| 3286 } | 3586 } |
| 3287 | 3587 |
| 3588 // Validate strict mode. |
| 3589 if (temp_scope_->StrictMode()) { |
| 3590 if (IsEvalOrArguments(name)) { |
| 3591 int position = function_token_position != RelocInfo::kNoPosition |
| 3592 ? function_token_position |
| 3593 : (start_pos > 0 ? start_pos - 1 : start_pos); |
| 3594 Scanner::Location location = Scanner::Location(position, start_pos); |
| 3595 ReportMessageAt(location, |
| 3596 "strict_function_name", Vector<const char*>::empty()); |
| 3597 *ok = false; |
| 3598 return NULL; |
| 3599 } |
| 3600 if (name_loc.IsValid()) { |
| 3601 ReportMessageAt(name_loc, "strict_param_name", |
| 3602 Vector<const char*>::empty()); |
| 3603 *ok = false; |
| 3604 return NULL; |
| 3605 } |
| 3606 if (dupe_loc.IsValid()) { |
| 3607 ReportMessageAt(dupe_loc, "strict_param_dupe", |
| 3608 Vector<const char*>::empty()); |
| 3609 *ok = false; |
| 3610 return NULL; |
| 3611 } |
| 3612 if (name_is_reserved) { |
| 3613 int position = function_token_position != RelocInfo::kNoPosition |
| 3614 ? function_token_position |
| 3615 : (start_pos > 0 ? start_pos - 1 : start_pos); |
| 3616 Scanner::Location location = Scanner::Location(position, start_pos); |
| 3617 ReportMessageAt(location, "strict_reserved_word", |
| 3618 Vector<const char*>::empty()); |
| 3619 *ok = false; |
| 3620 return NULL; |
| 3621 } |
| 3622 if (reserved_loc.IsValid()) { |
| 3623 ReportMessageAt(reserved_loc, "strict_reserved_word", |
| 3624 Vector<const char*>::empty()); |
| 3625 *ok = false; |
| 3626 return NULL; |
| 3627 } |
| 3628 CheckOctalLiteral(start_pos, end_pos, CHECK_OK); |
| 3629 } |
| 3630 |
| 3288 FunctionLiteral* function_literal = | 3631 FunctionLiteral* function_literal = |
| 3289 new FunctionLiteral(name, | 3632 new FunctionLiteral(name, |
| 3290 top_scope_, | 3633 top_scope_, |
| 3291 body, | 3634 body, |
| 3292 materialized_literal_count, | 3635 materialized_literal_count, |
| 3293 expected_property_count, | 3636 expected_property_count, |
| 3294 only_simple_this_property_assignments, | 3637 only_simple_this_property_assignments, |
| 3295 this_property_assignments, | 3638 this_property_assignments, |
| 3296 num_parameters, | 3639 num_parameters, |
| 3297 start_pos, | 3640 start_pos, |
| 3298 end_pos, | 3641 end_pos, |
| 3299 function_name->length() > 0, | 3642 function_name->length() > 0, |
| 3300 temp_scope.ContainsLoops()); | 3643 temp_scope.ContainsLoops(), |
| 3644 temp_scope.StrictMode()); |
| 3301 function_literal->set_function_token_position(function_token_position); | 3645 function_literal->set_function_token_position(function_token_position); |
| 3302 | 3646 |
| 3303 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); | 3647 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); |
| 3304 return function_literal; | 3648 return function_literal; |
| 3305 } | 3649 } |
| 3306 } | 3650 } |
| 3307 | 3651 |
| 3308 | 3652 |
| 3309 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 3653 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| 3310 // CallRuntime :: | 3654 // CallRuntime :: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3345 ReportMessage("illegal_access", Vector<const char*>::empty()); | 3689 ReportMessage("illegal_access", Vector<const char*>::empty()); |
| 3346 *ok = false; | 3690 *ok = false; |
| 3347 return NULL; | 3691 return NULL; |
| 3348 } | 3692 } |
| 3349 | 3693 |
| 3350 // We have a valid intrinsics call or a call to a builtin. | 3694 // We have a valid intrinsics call or a call to a builtin. |
| 3351 return new CallRuntime(name, function, args); | 3695 return new CallRuntime(name, function, args); |
| 3352 } | 3696 } |
| 3353 | 3697 |
| 3354 | 3698 |
| 3699 bool Parser::peek_any_identifier() { |
| 3700 Token::Value next = peek(); |
| 3701 return next == Token::IDENTIFIER || |
| 3702 next == Token::FUTURE_RESERVED_WORD; |
| 3703 } |
| 3704 |
| 3705 |
| 3355 void Parser::Consume(Token::Value token) { | 3706 void Parser::Consume(Token::Value token) { |
| 3356 Token::Value next = Next(); | 3707 Token::Value next = Next(); |
| 3357 USE(next); | 3708 USE(next); |
| 3358 USE(token); | 3709 USE(token); |
| 3359 ASSERT(next == token); | 3710 ASSERT(next == token); |
| 3360 } | 3711 } |
| 3361 | 3712 |
| 3362 | 3713 |
| 3363 void Parser::Expect(Token::Value token, bool* ok) { | 3714 void Parser::Expect(Token::Value token, bool* ok) { |
| 3364 Token::Value next = Next(); | 3715 Token::Value next = Next(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3404 return new Literal(Factory::the_hole_value()); | 3755 return new Literal(Factory::the_hole_value()); |
| 3405 } | 3756 } |
| 3406 | 3757 |
| 3407 | 3758 |
| 3408 Literal* Parser::GetLiteralNumber(double value) { | 3759 Literal* Parser::GetLiteralNumber(double value) { |
| 3409 return NewNumberLiteral(value); | 3760 return NewNumberLiteral(value); |
| 3410 } | 3761 } |
| 3411 | 3762 |
| 3412 | 3763 |
| 3413 Handle<String> Parser::ParseIdentifier(bool* ok) { | 3764 Handle<String> Parser::ParseIdentifier(bool* ok) { |
| 3414 Expect(Token::IDENTIFIER, ok); | 3765 bool is_reserved; |
| 3766 return ParseIdentifierOrReservedWord(&is_reserved, ok); |
| 3767 } |
| 3768 |
| 3769 |
| 3770 Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved, |
| 3771 bool* ok) { |
| 3772 *is_reserved = false; |
| 3773 if (temp_scope_->StrictMode()) { |
| 3774 Expect(Token::IDENTIFIER, ok); |
| 3775 } else { |
| 3776 if (!Check(Token::IDENTIFIER)) { |
| 3777 Expect(Token::FUTURE_RESERVED_WORD, ok); |
| 3778 *is_reserved = true; |
| 3779 } |
| 3780 } |
| 3415 if (!*ok) return Handle<String>(); | 3781 if (!*ok) return Handle<String>(); |
| 3416 return GetSymbol(ok); | 3782 return GetSymbol(ok); |
| 3417 } | 3783 } |
| 3418 | 3784 |
| 3419 | 3785 |
| 3420 Handle<String> Parser::ParseIdentifierName(bool* ok) { | 3786 Handle<String> Parser::ParseIdentifierName(bool* ok) { |
| 3421 Token::Value next = Next(); | 3787 Token::Value next = Next(); |
| 3422 if (next != Token::IDENTIFIER && !Token::IsKeyword(next)) { | 3788 if (next != Token::IDENTIFIER && |
| 3789 next != Token::FUTURE_RESERVED_WORD && |
| 3790 !Token::IsKeyword(next)) { |
| 3423 ReportUnexpectedToken(next); | 3791 ReportUnexpectedToken(next); |
| 3424 *ok = false; | 3792 *ok = false; |
| 3425 return Handle<String>(); | 3793 return Handle<String>(); |
| 3426 } | 3794 } |
| 3427 return GetSymbol(ok); | 3795 return GetSymbol(ok); |
| 3428 } | 3796 } |
| 3429 | 3797 |
| 3430 | 3798 |
| 3799 // Checks LHS expression for assignment and prefix/postfix increment/decrement |
| 3800 // in strict mode. |
| 3801 void Parser::CheckStrictModeLValue(Expression* expression, |
| 3802 const char* error, |
| 3803 bool* ok) { |
| 3804 ASSERT(temp_scope_->StrictMode()); |
| 3805 VariableProxy* lhs = expression != NULL |
| 3806 ? expression->AsVariableProxy() |
| 3807 : NULL; |
| 3808 |
| 3809 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) { |
| 3810 ReportMessage(error, Vector<const char*>::empty()); |
| 3811 *ok = false; |
| 3812 } |
| 3813 } |
| 3814 |
| 3815 |
| 3816 // Checks whether octal literal last seen is between beg_pos and end_pos. |
| 3817 // If so, reports an error. |
| 3818 void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
| 3819 int octal = scanner().octal_position(); |
| 3820 if (beg_pos <= octal && octal <= end_pos) { |
| 3821 ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal", |
| 3822 Vector<const char*>::empty()); |
| 3823 scanner().clear_octal_position(); |
| 3824 *ok = false; |
| 3825 } |
| 3826 } |
| 3827 |
| 3828 |
| 3431 // This function reads an identifier and determines whether or not it | 3829 // This function reads an identifier and determines whether or not it |
| 3432 // is 'get' or 'set'. The reason for not using ParseIdentifier and | 3830 // is 'get' or 'set'. |
| 3433 // checking on the output is that this involves heap allocation which | |
| 3434 // we can't do during preparsing. | |
| 3435 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, | 3831 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, |
| 3436 bool* is_set, | 3832 bool* is_set, |
| 3437 bool* ok) { | 3833 bool* ok) { |
| 3438 Expect(Token::IDENTIFIER, ok); | 3834 Handle<String> result = ParseIdentifier(ok); |
| 3439 if (!*ok) return Handle<String>(); | 3835 if (!*ok) return Handle<String>(); |
| 3440 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { | 3836 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { |
| 3441 const char* token = scanner().literal_ascii_string().start(); | 3837 const char* token = scanner().literal_ascii_string().start(); |
| 3442 *is_get = strncmp(token, "get", 3) == 0; | 3838 *is_get = strncmp(token, "get", 3) == 0; |
| 3443 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 3839 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 3444 } | 3840 } |
| 3445 return GetSymbol(ok); | 3841 return result; |
| 3446 } | 3842 } |
| 3447 | 3843 |
| 3448 | 3844 |
| 3449 // ---------------------------------------------------------------------------- | 3845 // ---------------------------------------------------------------------------- |
| 3450 // Parser support | 3846 // Parser support |
| 3451 | 3847 |
| 3452 | 3848 |
| 3453 bool Parser::TargetStackContainsLabel(Handle<String> label) { | 3849 bool Parser::TargetStackContainsLabel(Handle<String> label) { |
| 3454 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | 3850 for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| 3455 BreakableStatement* stat = t->node()->AsBreakableStatement(); | 3851 BreakableStatement* stat = t->node()->AsBreakableStatement(); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3530 Vector< Handle<Object> > arguments = | 3926 Vector< Handle<Object> > arguments = |
| 3531 HandleVector<Object>(elements, ARRAY_SIZE(elements)); | 3927 HandleVector<Object>(elements, ARRAY_SIZE(elements)); |
| 3532 return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments); | 3928 return NewThrowError(Factory::MakeTypeError_symbol(), type, arguments); |
| 3533 } | 3929 } |
| 3534 | 3930 |
| 3535 | 3931 |
| 3536 Expression* Parser::NewThrowError(Handle<String> constructor, | 3932 Expression* Parser::NewThrowError(Handle<String> constructor, |
| 3537 Handle<String> type, | 3933 Handle<String> type, |
| 3538 Vector< Handle<Object> > arguments) { | 3934 Vector< Handle<Object> > arguments) { |
| 3539 int argc = arguments.length(); | 3935 int argc = arguments.length(); |
| 3540 Handle<JSArray> array = Factory::NewJSArray(argc, TENURED); | 3936 Handle<FixedArray> elements = Factory::NewFixedArray(argc, TENURED); |
| 3541 ASSERT(array->IsJSArray() && array->HasFastElements()); | |
| 3542 for (int i = 0; i < argc; i++) { | 3937 for (int i = 0; i < argc; i++) { |
| 3543 Handle<Object> element = arguments[i]; | 3938 Handle<Object> element = arguments[i]; |
| 3544 if (!element.is_null()) { | 3939 if (!element.is_null()) { |
| 3545 // We know this doesn't cause a GC here because we allocated the JSArray | 3940 elements->set(i, *element); |
| 3546 // large enough. | |
| 3547 array->SetFastElement(i, *element)->ToObjectUnchecked(); | |
| 3548 } | 3941 } |
| 3549 } | 3942 } |
| 3943 Handle<JSArray> array = Factory::NewJSArrayWithElements(elements, TENURED); |
| 3944 |
| 3550 ZoneList<Expression*>* args = new ZoneList<Expression*>(2); | 3945 ZoneList<Expression*>* args = new ZoneList<Expression*>(2); |
| 3551 args->Add(new Literal(type)); | 3946 args->Add(new Literal(type)); |
| 3552 args->Add(new Literal(array)); | 3947 args->Add(new Literal(array)); |
| 3553 return new Throw(new CallRuntime(constructor, NULL, args), | 3948 return new Throw(new CallRuntime(constructor, NULL, args), |
| 3554 scanner().location().beg_pos); | 3949 scanner().location().beg_pos); |
| 3555 } | 3950 } |
| 3556 | 3951 |
| 3557 // ---------------------------------------------------------------------------- | 3952 // ---------------------------------------------------------------------------- |
| 3558 // JSON | 3953 // JSON |
| 3559 | 3954 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3577 case Token::EOS: | 3972 case Token::EOS: |
| 3578 message = "unexpected_eos"; | 3973 message = "unexpected_eos"; |
| 3579 break; | 3974 break; |
| 3580 case Token::NUMBER: | 3975 case Token::NUMBER: |
| 3581 message = "unexpected_token_number"; | 3976 message = "unexpected_token_number"; |
| 3582 break; | 3977 break; |
| 3583 case Token::STRING: | 3978 case Token::STRING: |
| 3584 message = "unexpected_token_string"; | 3979 message = "unexpected_token_string"; |
| 3585 break; | 3980 break; |
| 3586 case Token::IDENTIFIER: | 3981 case Token::IDENTIFIER: |
| 3982 case Token::FUTURE_RESERVED_WORD: |
| 3587 message = "unexpected_token_identifier"; | 3983 message = "unexpected_token_identifier"; |
| 3588 break; | 3984 break; |
| 3589 default: | 3985 default: |
| 3590 message = "unexpected_token"; | 3986 message = "unexpected_token"; |
| 3591 name_opt = Token::String(token); | 3987 name_opt = Token::String(token); |
| 3592 ASSERT(name_opt != NULL); | 3988 ASSERT(name_opt != NULL); |
| 3593 break; | 3989 break; |
| 3594 } | 3990 } |
| 3595 | 3991 |
| 3596 Scanner::Location source_location = scanner_.location(); | 3992 Scanner::Location source_location = scanner_.location(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3623 } else { | 4019 } else { |
| 3624 return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string()); | 4020 return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string()); |
| 3625 } | 4021 } |
| 3626 } | 4022 } |
| 3627 | 4023 |
| 3628 | 4024 |
| 3629 // Parse any JSON value. | 4025 // Parse any JSON value. |
| 3630 Handle<Object> JsonParser::ParseJsonValue() { | 4026 Handle<Object> JsonParser::ParseJsonValue() { |
| 3631 Token::Value token = scanner_.Next(); | 4027 Token::Value token = scanner_.Next(); |
| 3632 switch (token) { | 4028 switch (token) { |
| 3633 case Token::STRING: { | 4029 case Token::STRING: |
| 3634 return GetString(); | 4030 return GetString(); |
| 3635 } | 4031 case Token::NUMBER: |
| 3636 case Token::NUMBER: { | 4032 return Factory::NewNumber(scanner_.number()); |
| 3637 ASSERT(scanner_.is_literal_ascii()); | |
| 3638 double value = StringToDouble(scanner_.literal_ascii_string(), | |
| 3639 NO_FLAGS, // Hex, octal or trailing junk. | |
| 3640 OS::nan_value()); | |
| 3641 return Factory::NewNumber(value); | |
| 3642 } | |
| 3643 case Token::FALSE_LITERAL: | 4033 case Token::FALSE_LITERAL: |
| 3644 return Factory::false_value(); | 4034 return Factory::false_value(); |
| 3645 case Token::TRUE_LITERAL: | 4035 case Token::TRUE_LITERAL: |
| 3646 return Factory::true_value(); | 4036 return Factory::true_value(); |
| 3647 case Token::NULL_LITERAL: | 4037 case Token::NULL_LITERAL: |
| 3648 return Factory::null_value(); | 4038 return Factory::null_value(); |
| 3649 case Token::LBRACE: | 4039 case Token::LBRACE: |
| 3650 return ParseJsonObject(); | 4040 return ParseJsonObject(); |
| 3651 case Token::LBRACK: | 4041 case Token::LBRACK: |
| 3652 return ParseJsonArray(); | 4042 return ParseJsonArray(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3673 return ReportUnexpectedToken(); | 4063 return ReportUnexpectedToken(); |
| 3674 } | 4064 } |
| 3675 Handle<String> key = GetString(); | 4065 Handle<String> key = GetString(); |
| 3676 if (scanner_.Next() != Token::COLON) { | 4066 if (scanner_.Next() != Token::COLON) { |
| 3677 return ReportUnexpectedToken(); | 4067 return ReportUnexpectedToken(); |
| 3678 } | 4068 } |
| 3679 Handle<Object> value = ParseJsonValue(); | 4069 Handle<Object> value = ParseJsonValue(); |
| 3680 if (value.is_null()) return Handle<Object>::null(); | 4070 if (value.is_null()) return Handle<Object>::null(); |
| 3681 uint32_t index; | 4071 uint32_t index; |
| 3682 if (key->AsArrayIndex(&index)) { | 4072 if (key->AsArrayIndex(&index)) { |
| 3683 CALL_HEAP_FUNCTION_INLINE( | 4073 SetOwnElement(json_object, index, value); |
| 3684 (*json_object)->SetElement(index, *value, true)); | 4074 } else if (key->Equals(Heap::Proto_symbol())) { |
| 4075 // We can't remove the __proto__ accessor since it's hardcoded |
| 4076 // in several places. Instead go along and add the value as |
| 4077 // the prototype of the created object if possible. |
| 4078 SetPrototype(json_object, value); |
| 3685 } else { | 4079 } else { |
| 3686 CALL_HEAP_FUNCTION_INLINE( | 4080 SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE); |
| 3687 (*json_object)->SetPropertyPostInterceptor(*key, *value, NONE)); | |
| 3688 } | 4081 } |
| 3689 } while (scanner_.Next() == Token::COMMA); | 4082 } while (scanner_.Next() == Token::COMMA); |
| 3690 if (scanner_.current_token() != Token::RBRACE) { | 4083 if (scanner_.current_token() != Token::RBRACE) { |
| 3691 return ReportUnexpectedToken(); | 4084 return ReportUnexpectedToken(); |
| 3692 } | 4085 } |
| 3693 } | 4086 } |
| 3694 return json_object; | 4087 return json_object; |
| 3695 } | 4088 } |
| 3696 | 4089 |
| 3697 | 4090 |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4037 break; | 4430 break; |
| 4038 case 't': | 4431 case 't': |
| 4039 Advance(2); | 4432 Advance(2); |
| 4040 builder->AddCharacter('\t'); | 4433 builder->AddCharacter('\t'); |
| 4041 break; | 4434 break; |
| 4042 case 'v': | 4435 case 'v': |
| 4043 Advance(2); | 4436 Advance(2); |
| 4044 builder->AddCharacter('\v'); | 4437 builder->AddCharacter('\v'); |
| 4045 break; | 4438 break; |
| 4046 case 'c': { | 4439 case 'c': { |
| 4047 Advance(2); | 4440 Advance(); |
| 4048 uc32 control = ParseControlLetterEscape(); | 4441 uc32 controlLetter = Next(); |
| 4049 builder->AddCharacter(control); | 4442 // Special case if it is an ASCII letter. |
| 4443 // Convert lower case letters to uppercase. |
| 4444 uc32 letter = controlLetter & ~('a' ^ 'A'); |
| 4445 if (letter < 'A' || 'Z' < letter) { |
| 4446 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
| 4447 // This is outside the specification. We match JSC in |
| 4448 // reading the backslash as a literal character instead |
| 4449 // of as starting an escape. |
| 4450 builder->AddCharacter('\\'); |
| 4451 } else { |
| 4452 Advance(2); |
| 4453 builder->AddCharacter(controlLetter & 0x1f); |
| 4454 } |
| 4050 break; | 4455 break; |
| 4051 } | 4456 } |
| 4052 case 'x': { | 4457 case 'x': { |
| 4053 Advance(2); | 4458 Advance(2); |
| 4054 uc32 value; | 4459 uc32 value; |
| 4055 if (ParseHexEscape(2, &value)) { | 4460 if (ParseHexEscape(2, &value)) { |
| 4056 builder->AddCharacter(value); | 4461 builder->AddCharacter(value); |
| 4057 } else { | 4462 } else { |
| 4058 builder->AddCharacter('x'); | 4463 builder->AddCharacter('x'); |
| 4059 } | 4464 } |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4314 } else { | 4719 } else { |
| 4315 Reset(start); | 4720 Reset(start); |
| 4316 return false; | 4721 return false; |
| 4317 } | 4722 } |
| 4318 *min_out = min; | 4723 *min_out = min; |
| 4319 *max_out = max; | 4724 *max_out = max; |
| 4320 return true; | 4725 return true; |
| 4321 } | 4726 } |
| 4322 | 4727 |
| 4323 | 4728 |
| 4324 // Upper and lower case letters differ by one bit. | |
| 4325 STATIC_CHECK(('a' ^ 'A') == 0x20); | |
| 4326 | |
| 4327 uc32 RegExpParser::ParseControlLetterEscape() { | |
| 4328 if (!has_more()) | |
| 4329 return 'c'; | |
| 4330 uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters. | |
| 4331 if (letter < 'A' || 'Z' < letter) { | |
| 4332 // Non-spec error-correction: "\c" followed by non-control letter is | |
| 4333 // interpreted as an IdentityEscape of 'c'. | |
| 4334 return 'c'; | |
| 4335 } | |
| 4336 Advance(); | |
| 4337 return letter & 0x1f; // Remainder modulo 32, per specification. | |
| 4338 } | |
| 4339 | |
| 4340 | |
| 4341 uc32 RegExpParser::ParseOctalLiteral() { | 4729 uc32 RegExpParser::ParseOctalLiteral() { |
| 4342 ASSERT('0' <= current() && current() <= '7'); | 4730 ASSERT('0' <= current() && current() <= '7'); |
| 4343 // For compatibility with some other browsers (not all), we parse | 4731 // For compatibility with some other browsers (not all), we parse |
| 4344 // up to three octal digits with a value below 256. | 4732 // up to three octal digits with a value below 256. |
| 4345 uc32 value = current() - '0'; | 4733 uc32 value = current() - '0'; |
| 4346 Advance(); | 4734 Advance(); |
| 4347 if ('0' <= current() && current() <= '7') { | 4735 if ('0' <= current() && current() <= '7') { |
| 4348 value = value * 8 + current() - '0'; | 4736 value = value * 8 + current() - '0'; |
| 4349 Advance(); | 4737 Advance(); |
| 4350 if (value < 32 && '0' <= current() && current() <= '7') { | 4738 if (value < 32 && '0' <= current() && current() <= '7') { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4396 return '\n'; | 4784 return '\n'; |
| 4397 case 'r': | 4785 case 'r': |
| 4398 Advance(); | 4786 Advance(); |
| 4399 return '\r'; | 4787 return '\r'; |
| 4400 case 't': | 4788 case 't': |
| 4401 Advance(); | 4789 Advance(); |
| 4402 return '\t'; | 4790 return '\t'; |
| 4403 case 'v': | 4791 case 'v': |
| 4404 Advance(); | 4792 Advance(); |
| 4405 return '\v'; | 4793 return '\v'; |
| 4406 case 'c': | 4794 case 'c': { |
| 4407 Advance(); | 4795 uc32 controlLetter = Next(); |
| 4408 return ParseControlLetterEscape(); | 4796 uc32 letter = controlLetter & ~('A' ^ 'a'); |
| 4797 // For compatibility with JSC, inside a character class |
| 4798 // we also accept digits and underscore as control characters. |
| 4799 if ((controlLetter >= '0' && controlLetter <= '9') || |
| 4800 controlLetter == '_' || |
| 4801 (letter >= 'A' && letter <= 'Z')) { |
| 4802 Advance(2); |
| 4803 // Control letters mapped to ASCII control characters in the range |
| 4804 // 0x00-0x1f. |
| 4805 return controlLetter & 0x1f; |
| 4806 } |
| 4807 // We match JSC in reading the backslash as a literal |
| 4808 // character instead of as starting an escape. |
| 4809 return '\\'; |
| 4810 } |
| 4409 case '0': case '1': case '2': case '3': case '4': case '5': | 4811 case '0': case '1': case '2': case '3': case '4': case '5': |
| 4410 case '6': case '7': | 4812 case '6': case '7': |
| 4411 // For compatibility, we interpret a decimal escape that isn't | 4813 // For compatibility, we interpret a decimal escape that isn't |
| 4412 // a back reference (and therefore either \0 or not valid according | 4814 // a back reference (and therefore either \0 or not valid according |
| 4413 // to the specification) as a 1..3 digit octal character code. | 4815 // to the specification) as a 1..3 digit octal character code. |
| 4414 return ParseOctalLiteral(); | 4816 return ParseOctalLiteral(); |
| 4415 case 'x': { | 4817 case 'x': { |
| 4416 Advance(); | 4818 Advance(); |
| 4417 uc32 value; | 4819 uc32 value; |
| 4418 if (ParseHexEscape(2, &value)) { | 4820 if (ParseHexEscape(2, &value)) { |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4699 Vector<const char*> args = pre_data->BuildArgs(); | 5101 Vector<const char*> args = pre_data->BuildArgs(); |
| 4700 parser.ReportMessageAt(loc, message, args); | 5102 parser.ReportMessageAt(loc, message, args); |
| 4701 DeleteArray(message); | 5103 DeleteArray(message); |
| 4702 for (int i = 0; i < args.length(); i++) { | 5104 for (int i = 0; i < args.length(); i++) { |
| 4703 DeleteArray(args[i]); | 5105 DeleteArray(args[i]); |
| 4704 } | 5106 } |
| 4705 DeleteArray(args.start()); | 5107 DeleteArray(args.start()); |
| 4706 ASSERT(Top::has_pending_exception()); | 5108 ASSERT(Top::has_pending_exception()); |
| 4707 } else { | 5109 } else { |
| 4708 Handle<String> source = Handle<String>(String::cast(script->source())); | 5110 Handle<String> source = Handle<String>(String::cast(script->source())); |
| 4709 result = parser.ParseProgram(source, info->is_global()); | 5111 result = parser.ParseProgram(source, |
| 5112 info->is_global(), |
| 5113 info->StrictMode()); |
| 4710 } | 5114 } |
| 4711 } | 5115 } |
| 4712 | 5116 |
| 4713 info->SetFunction(result); | 5117 info->SetFunction(result); |
| 4714 return (result != NULL); | 5118 return (result != NULL); |
| 4715 } | 5119 } |
| 4716 | 5120 |
| 4717 } } // namespace v8::internal | 5121 } } // namespace v8::internal |
| OLD | NEW |