| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 return &store_[PreparseDataConstants::kHeaderSize + position]; | 404 return &store_[PreparseDataConstants::kHeaderSize + position]; |
| 405 } | 405 } |
| 406 | 406 |
| 407 | 407 |
| 408 Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) { | 408 Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) { |
| 409 Scope* result = new(zone()) Scope(parent, type); | 409 Scope* result = new(zone()) Scope(parent, type); |
| 410 result->Initialize(inside_with); | 410 result->Initialize(inside_with); |
| 411 return result; | 411 return result; |
| 412 } | 412 } |
| 413 | 413 |
| 414 |
| 414 // ---------------------------------------------------------------------------- | 415 // ---------------------------------------------------------------------------- |
| 415 // Target is a support class to facilitate manipulation of the | 416 // Target is a support class to facilitate manipulation of the |
| 416 // Parser's target_stack_ (the stack of potential 'break' and | 417 // Parser's target_stack_ (the stack of potential 'break' and |
| 417 // 'continue' statement targets). Upon construction, a new target is | 418 // 'continue' statement targets). Upon construction, a new target is |
| 418 // added; it is removed upon destruction. | 419 // added; it is removed upon destruction. |
| 419 | 420 |
| 420 class Target BASE_EMBEDDED { | 421 class Target BASE_EMBEDDED { |
| 421 public: | 422 public: |
| 422 Target(Target** variable, AstNode* node) | 423 Target(Target** variable, AstNode* node) |
| 423 : variable_(variable), node_(node), previous_(*variable) { | 424 : variable_(variable), node_(node), previous_(*variable) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 previous_with_nesting_level_(parser->with_nesting_level_), | 530 previous_with_nesting_level_(parser->with_nesting_level_), |
| 530 previous_ast_node_id_(isolate->ast_node_id()) { | 531 previous_ast_node_id_(isolate->ast_node_id()) { |
| 531 parser->top_scope_ = scope; | 532 parser->top_scope_ = scope; |
| 532 parser->lexical_scope_ = this; | 533 parser->lexical_scope_ = this; |
| 533 parser->with_nesting_level_ = 0; | 534 parser->with_nesting_level_ = 0; |
| 534 isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1); | 535 isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1); |
| 535 } | 536 } |
| 536 | 537 |
| 537 | 538 |
| 538 LexicalScope::~LexicalScope() { | 539 LexicalScope::~LexicalScope() { |
| 539 parser_->top_scope_->Leave(); | |
| 540 parser_->top_scope_ = previous_scope_; | 540 parser_->top_scope_ = previous_scope_; |
| 541 parser_->lexical_scope_ = lexical_scope_parent_; | 541 parser_->lexical_scope_ = lexical_scope_parent_; |
| 542 parser_->with_nesting_level_ = previous_with_nesting_level_; | 542 parser_->with_nesting_level_ = previous_with_nesting_level_; |
| 543 parser_->isolate()->set_ast_node_id(previous_ast_node_id_); | 543 parser_->isolate()->set_ast_node_id(previous_ast_node_id_); |
| 544 } | 544 } |
| 545 | 545 |
| 546 | 546 |
| 547 // ---------------------------------------------------------------------------- | 547 // ---------------------------------------------------------------------------- |
| 548 // The CHECK_OK macro is a convenient macro to enforce error | 548 // The CHECK_OK macro is a convenient macro to enforce error |
| 549 // handling for functions that may fail (by returning !*ok). | 549 // handling for functions that may fail (by returning !*ok). |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 fni_(NULL), | 585 fni_(NULL), |
| 586 stack_overflow_(false), | 586 stack_overflow_(false), |
| 587 parenthesized_function_(false) { | 587 parenthesized_function_(false) { |
| 588 AstNode::ResetIds(); | 588 AstNode::ResetIds(); |
| 589 } | 589 } |
| 590 | 590 |
| 591 | 591 |
| 592 FunctionLiteral* Parser::ParseProgram(Handle<String> source, | 592 FunctionLiteral* Parser::ParseProgram(Handle<String> source, |
| 593 bool in_global_context, | 593 bool in_global_context, |
| 594 StrictModeFlag strict_mode) { | 594 StrictModeFlag strict_mode) { |
| 595 CompilationZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); | 595 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); |
| 596 | 596 |
| 597 HistogramTimerScope timer(isolate()->counters()->parse()); | 597 HistogramTimerScope timer(isolate()->counters()->parse()); |
| 598 isolate()->counters()->total_parse_size()->Increment(source->length()); | 598 isolate()->counters()->total_parse_size()->Increment(source->length()); |
| 599 fni_ = new(zone()) FuncNameInferrer(); | 599 fni_ = new(zone()) FuncNameInferrer(isolate()); |
| 600 | 600 |
| 601 // Initialize parser state. | 601 // Initialize parser state. |
| 602 source->TryFlatten(); | 602 source->TryFlatten(); |
| 603 if (source->IsExternalTwoByteString()) { | 603 if (source->IsExternalTwoByteString()) { |
| 604 // Notice that the stream is destroyed at the end of the branch block. | 604 // Notice that the stream is destroyed at the end of the branch block. |
| 605 // The last line of the blocks can't be moved outside, even though they're | 605 // The last line of the blocks can't be moved outside, even though they're |
| 606 // identical calls. | 606 // identical calls. |
| 607 ExternalTwoByteStringUC16CharacterStream stream( | 607 ExternalTwoByteStringUC16CharacterStream stream( |
| 608 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | 608 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
| 609 scanner_.Initialize(&stream); | 609 scanner_.Initialize(&stream); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 no_name, | 651 no_name, |
| 652 top_scope_, | 652 top_scope_, |
| 653 body, | 653 body, |
| 654 lexical_scope.materialized_literal_count(), | 654 lexical_scope.materialized_literal_count(), |
| 655 lexical_scope.expected_property_count(), | 655 lexical_scope.expected_property_count(), |
| 656 lexical_scope.only_simple_this_property_assignments(), | 656 lexical_scope.only_simple_this_property_assignments(), |
| 657 lexical_scope.this_property_assignments(), | 657 lexical_scope.this_property_assignments(), |
| 658 0, | 658 0, |
| 659 0, | 659 0, |
| 660 source->length(), | 660 source->length(), |
| 661 false, |
| 661 false); | 662 false); |
| 662 } else if (stack_overflow_) { | 663 } else if (stack_overflow_) { |
| 663 isolate()->StackOverflow(); | 664 isolate()->StackOverflow(); |
| 664 } | 665 } |
| 665 } | 666 } |
| 666 | 667 |
| 667 // Make sure the target stack is empty. | 668 // Make sure the target stack is empty. |
| 668 ASSERT(target_stack_ == NULL); | 669 ASSERT(target_stack_ == NULL); |
| 669 | 670 |
| 670 // If there was a syntax error we have to get rid of the AST | 671 // If there was a syntax error we have to get rid of the AST |
| 671 // and it is not safe to do so before the scope has been deleted. | 672 // and it is not safe to do so before the scope has been deleted. |
| 672 if (result == NULL) zone_scope->DeleteOnExit(); | 673 if (result == NULL) zone_scope->DeleteOnExit(); |
| 673 return result; | 674 return result; |
| 674 } | 675 } |
| 675 | 676 |
| 676 FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) { | 677 FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) { |
| 677 CompilationZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); | 678 ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); |
| 678 HistogramTimerScope timer(isolate()->counters()->parse_lazy()); | 679 HistogramTimerScope timer(isolate()->counters()->parse_lazy()); |
| 679 Handle<String> source(String::cast(script_->source())); | 680 Handle<String> source(String::cast(script_->source())); |
| 680 isolate()->counters()->total_parse_size()->Increment(source->length()); | 681 isolate()->counters()->total_parse_size()->Increment(source->length()); |
| 681 | 682 |
| 682 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 683 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 683 // Initialize parser state. | 684 // Initialize parser state. |
| 684 source->TryFlatten(); | 685 source->TryFlatten(); |
| 685 if (source->IsExternalTwoByteString()) { | 686 if (source->IsExternalTwoByteString()) { |
| 686 ExternalTwoByteStringUC16CharacterStream stream( | 687 ExternalTwoByteStringUC16CharacterStream stream( |
| 687 Handle<ExternalTwoByteString>::cast(source), | 688 Handle<ExternalTwoByteString>::cast(source), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 700 | 701 |
| 701 | 702 |
| 702 FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, | 703 FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, |
| 703 UC16CharacterStream* source, | 704 UC16CharacterStream* source, |
| 704 ZoneScope* zone_scope) { | 705 ZoneScope* zone_scope) { |
| 705 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 706 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 706 scanner_.Initialize(source); | 707 scanner_.Initialize(source); |
| 707 ASSERT(target_stack_ == NULL); | 708 ASSERT(target_stack_ == NULL); |
| 708 | 709 |
| 709 Handle<String> name(String::cast(shared_info->name())); | 710 Handle<String> name(String::cast(shared_info->name())); |
| 710 fni_ = new(zone()) FuncNameInferrer(); | 711 fni_ = new(zone()) FuncNameInferrer(isolate()); |
| 711 fni_->PushEnclosingName(name); | 712 fni_->PushEnclosingName(name); |
| 712 | 713 |
| 713 mode_ = PARSE_EAGERLY; | 714 mode_ = PARSE_EAGERLY; |
| 714 | 715 |
| 715 // Place holder for the result. | 716 // Place holder for the result. |
| 716 FunctionLiteral* result = NULL; | 717 FunctionLiteral* result = NULL; |
| 717 | 718 |
| 718 { | 719 { |
| 719 // Parse the function literal. | 720 // Parse the function literal. |
| 720 Handle<String> no_name = isolate()->factory()->empty_symbol(); | 721 Handle<String> no_name = isolate()->factory()->empty_symbol(); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 if (exp_stat == NULL) return NULL; | 816 if (exp_stat == NULL) return NULL; |
| 816 return exp_stat->expression()->AsAssignment(); | 817 return exp_stat->expression()->AsAssignment(); |
| 817 } | 818 } |
| 818 }; | 819 }; |
| 819 | 820 |
| 820 | 821 |
| 821 // An InitializationBlockFinder finds and marks sequences of statements of the | 822 // An InitializationBlockFinder finds and marks sequences of statements of the |
| 822 // form expr.a = ...; expr.b = ...; etc. | 823 // form expr.a = ...; expr.b = ...; etc. |
| 823 class InitializationBlockFinder : public ParserFinder { | 824 class InitializationBlockFinder : public ParserFinder { |
| 824 public: | 825 public: |
| 825 InitializationBlockFinder() | 826 // We find and mark the initialization blocks in top level |
| 826 : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {} | 827 // non-looping code only. This is because the optimization prevents |
| 828 // reuse of the map transitions, so it should be used only for code |
| 829 // that will only be run once. |
| 830 InitializationBlockFinder(Scope* top_scope, Target* target) |
| 831 : enabled_(top_scope->DeclarationScope()->is_global_scope() && |
| 832 !IsLoopTarget(target)), |
| 833 first_in_block_(NULL), |
| 834 last_in_block_(NULL), |
| 835 block_size_(0) {} |
| 827 | 836 |
| 828 ~InitializationBlockFinder() { | 837 ~InitializationBlockFinder() { |
| 838 if (!enabled_) return; |
| 829 if (InBlock()) EndBlock(); | 839 if (InBlock()) EndBlock(); |
| 830 } | 840 } |
| 831 | 841 |
| 832 void Update(Statement* stat) { | 842 void Update(Statement* stat) { |
| 843 if (!enabled_) return; |
| 833 Assignment* assignment = AsAssignment(stat); | 844 Assignment* assignment = AsAssignment(stat); |
| 834 if (InBlock()) { | 845 if (InBlock()) { |
| 835 if (BlockContinues(assignment)) { | 846 if (BlockContinues(assignment)) { |
| 836 UpdateBlock(assignment); | 847 UpdateBlock(assignment); |
| 837 } else { | 848 } else { |
| 838 EndBlock(); | 849 EndBlock(); |
| 839 } | 850 } |
| 840 } | 851 } |
| 841 if (!InBlock() && (assignment != NULL) && | 852 if (!InBlock() && (assignment != NULL) && |
| 842 (assignment->op() == Token::ASSIGN)) { | 853 (assignment->op() == Token::ASSIGN)) { |
| 843 StartBlock(assignment); | 854 StartBlock(assignment); |
| 844 } | 855 } |
| 845 } | 856 } |
| 846 | 857 |
| 847 private: | 858 private: |
| 848 // The minimum number of contiguous assignment that will | 859 // The minimum number of contiguous assignment that will |
| 849 // be treated as an initialization block. Benchmarks show that | 860 // be treated as an initialization block. Benchmarks show that |
| 850 // the overhead exceeds the savings below this limit. | 861 // the overhead exceeds the savings below this limit. |
| 851 static const int kMinInitializationBlock = 3; | 862 static const int kMinInitializationBlock = 3; |
| 852 | 863 |
| 864 static bool IsLoopTarget(Target* target) { |
| 865 while (target != NULL) { |
| 866 if (target->node()->AsIterationStatement() != NULL) return true; |
| 867 target = target->previous(); |
| 868 } |
| 869 return false; |
| 870 } |
| 871 |
| 853 // Returns true if the expressions appear to denote the same object. | 872 // Returns true if the expressions appear to denote the same object. |
| 854 // In the context of initialization blocks, we only consider expressions | 873 // In the context of initialization blocks, we only consider expressions |
| 855 // of the form 'expr.x' or expr["x"]. | 874 // of the form 'expr.x' or expr["x"]. |
| 856 static bool SameObject(Expression* e1, Expression* e2) { | 875 static bool SameObject(Expression* e1, Expression* e2) { |
| 857 VariableProxy* v1 = e1->AsVariableProxy(); | 876 VariableProxy* v1 = e1->AsVariableProxy(); |
| 858 VariableProxy* v2 = e2->AsVariableProxy(); | 877 VariableProxy* v2 = e2->AsVariableProxy(); |
| 859 if (v1 != NULL && v2 != NULL) { | 878 if (v1 != NULL && v2 != NULL) { |
| 860 return v1->name()->Equals(*v2->name()); | 879 return v1->name()->Equals(*v2->name()); |
| 861 } | 880 } |
| 862 Property* p1 = e1->AsProperty(); | 881 Property* p1 = e1->AsProperty(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 if (block_size_ >= kMinInitializationBlock) { | 924 if (block_size_ >= kMinInitializationBlock) { |
| 906 first_in_block_->mark_block_start(); | 925 first_in_block_->mark_block_start(); |
| 907 last_in_block_->mark_block_end(); | 926 last_in_block_->mark_block_end(); |
| 908 } | 927 } |
| 909 last_in_block_ = first_in_block_ = NULL; | 928 last_in_block_ = first_in_block_ = NULL; |
| 910 block_size_ = 0; | 929 block_size_ = 0; |
| 911 } | 930 } |
| 912 | 931 |
| 913 bool InBlock() { return first_in_block_ != NULL; } | 932 bool InBlock() { return first_in_block_ != NULL; } |
| 914 | 933 |
| 934 const bool enabled_; |
| 915 Assignment* first_in_block_; | 935 Assignment* first_in_block_; |
| 916 Assignment* last_in_block_; | 936 Assignment* last_in_block_; |
| 917 int block_size_; | 937 int block_size_; |
| 918 | 938 |
| 919 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder); | 939 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder); |
| 920 }; | 940 }; |
| 921 | 941 |
| 922 | 942 |
| 923 // A ThisNamedPropertyAssigmentFinder finds and marks statements of the form | 943 // A ThisNamedPropertyAssigmentFinder finds and marks statements of the form |
| 924 // this.x = ...;, where x is a named property. It also determines whether a | 944 // this.x = ...;, where x is a named property. It also determines whether a |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 // SourceElements :: | 1090 // SourceElements :: |
| 1071 // (Statement)* <end_token> | 1091 // (Statement)* <end_token> |
| 1072 | 1092 |
| 1073 // Allocate a target stack to use for this set of source | 1093 // Allocate a target stack to use for this set of source |
| 1074 // elements. This way, all scripts and functions get their own | 1094 // elements. This way, all scripts and functions get their own |
| 1075 // target stack thus avoiding illegal breaks and continues across | 1095 // target stack thus avoiding illegal breaks and continues across |
| 1076 // functions. | 1096 // functions. |
| 1077 TargetScope scope(&this->target_stack_); | 1097 TargetScope scope(&this->target_stack_); |
| 1078 | 1098 |
| 1079 ASSERT(processor != NULL); | 1099 ASSERT(processor != NULL); |
| 1080 InitializationBlockFinder block_finder; | 1100 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
| 1081 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); | 1101 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); |
| 1082 bool directive_prologue = true; // Parsing directive prologue. | 1102 bool directive_prologue = true; // Parsing directive prologue. |
| 1083 | 1103 |
| 1084 while (peek() != end_token) { | 1104 while (peek() != end_token) { |
| 1085 if (directive_prologue && peek() != Token::STRING) { | 1105 if (directive_prologue && peek() != Token::STRING) { |
| 1086 directive_prologue = false; | 1106 directive_prologue = false; |
| 1087 } | 1107 } |
| 1088 | 1108 |
| 1089 Scanner::Location token_loc = scanner().peek_location(); | 1109 Scanner::Location token_loc = scanner().peek_location(); |
| 1090 | 1110 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1125 top_scope_->EnableStrictMode(); | 1145 top_scope_->EnableStrictMode(); |
| 1126 // "use strict" is the only directive for now. | 1146 // "use strict" is the only directive for now. |
| 1127 directive_prologue = false; | 1147 directive_prologue = false; |
| 1128 } | 1148 } |
| 1129 } else { | 1149 } else { |
| 1130 // End of the directive prologue. | 1150 // End of the directive prologue. |
| 1131 directive_prologue = false; | 1151 directive_prologue = false; |
| 1132 } | 1152 } |
| 1133 } | 1153 } |
| 1134 | 1154 |
| 1135 // We find and mark the initialization blocks on top level code only. | 1155 block_finder.Update(stat); |
| 1136 // This is because the optimization prevents reuse of the map transitions, | |
| 1137 // so it should be used only for code that will only be run once. | |
| 1138 if (top_scope_->is_global_scope()) { | |
| 1139 block_finder.Update(stat); | |
| 1140 } | |
| 1141 // Find and mark all assignments to named properties in this (this.x =) | 1156 // Find and mark all assignments to named properties in this (this.x =) |
| 1142 if (top_scope_->is_function_scope()) { | 1157 if (top_scope_->is_function_scope()) { |
| 1143 this_property_assignment_finder.Update(top_scope_, stat); | 1158 this_property_assignment_finder.Update(top_scope_, stat); |
| 1144 } | 1159 } |
| 1145 processor->Add(stat); | 1160 processor->Add(stat); |
| 1146 } | 1161 } |
| 1147 | 1162 |
| 1148 // Propagate the collected information on this property assignments. | 1163 // Propagate the collected information on this property assignments. |
| 1149 if (top_scope_->is_function_scope()) { | 1164 if (top_scope_->is_function_scope()) { |
| 1150 bool only_simple_this_property_assignments = | 1165 bool only_simple_this_property_assignments = |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 // of SourceElements. | 1277 // of SourceElements. |
| 1263 if (top_scope_->is_strict_mode()) { | 1278 if (top_scope_->is_strict_mode()) { |
| 1264 ReportMessageAt(scanner().peek_location(), "strict_function", | 1279 ReportMessageAt(scanner().peek_location(), "strict_function", |
| 1265 Vector<const char*>::empty()); | 1280 Vector<const char*>::empty()); |
| 1266 *ok = false; | 1281 *ok = false; |
| 1267 return NULL; | 1282 return NULL; |
| 1268 } | 1283 } |
| 1269 return ParseFunctionDeclaration(ok); | 1284 return ParseFunctionDeclaration(ok); |
| 1270 } | 1285 } |
| 1271 | 1286 |
| 1272 case Token::NATIVE: | |
| 1273 return ParseNativeDeclaration(ok); | |
| 1274 | |
| 1275 case Token::DEBUGGER: | 1287 case Token::DEBUGGER: |
| 1276 stmt = ParseDebuggerStatement(ok); | 1288 stmt = ParseDebuggerStatement(ok); |
| 1277 break; | 1289 break; |
| 1278 | 1290 |
| 1279 default: | 1291 default: |
| 1280 stmt = ParseExpressionOrLabelledStatement(labels, ok); | 1292 stmt = ParseExpressionOrLabelledStatement(labels, ok); |
| 1281 } | 1293 } |
| 1282 | 1294 |
| 1283 // Store the source position of the statement | 1295 // Store the source position of the statement |
| 1284 if (stmt != NULL) stmt->set_statement_pos(statement_pos); | 1296 if (stmt != NULL) stmt->set_statement_pos(statement_pos); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1297 // is always the function scope. | 1309 // is always the function scope. |
| 1298 | 1310 |
| 1299 // If a function scope exists, then we can statically declare this | 1311 // If a function scope exists, then we can statically declare this |
| 1300 // variable and also set its mode. In any case, a Declaration node | 1312 // variable and also set its mode. In any case, a Declaration node |
| 1301 // will be added to the scope so that the declaration can be added | 1313 // will be added to the scope so that the declaration can be added |
| 1302 // to the corresponding activation frame at runtime if necessary. | 1314 // to the corresponding activation frame at runtime if necessary. |
| 1303 // For instance declarations inside an eval scope need to be added | 1315 // For instance declarations inside an eval scope need to be added |
| 1304 // to the calling function context. | 1316 // to the calling function context. |
| 1305 // Similarly, strict mode eval scope does not leak variable declarations to | 1317 // Similarly, strict mode eval scope does not leak variable declarations to |
| 1306 // the caller's scope so we declare all locals, too. | 1318 // the caller's scope so we declare all locals, too. |
| 1307 if (top_scope_->is_function_scope() || | 1319 Scope* declaration_scope = top_scope_->DeclarationScope(); |
| 1308 top_scope_->is_strict_mode_eval_scope()) { | 1320 if (declaration_scope->is_function_scope() || |
| 1321 declaration_scope->is_strict_mode_eval_scope()) { |
| 1309 // Declare the variable in the function scope. | 1322 // Declare the variable in the function scope. |
| 1310 var = top_scope_->LocalLookup(name); | 1323 var = declaration_scope->LocalLookup(name); |
| 1311 if (var == NULL) { | 1324 if (var == NULL) { |
| 1312 // Declare the name. | 1325 // Declare the name. |
| 1313 var = top_scope_->DeclareLocal(name, mode, Scope::VAR_OR_CONST); | 1326 var = declaration_scope->DeclareLocal(name, mode); |
| 1314 } else { | 1327 } else { |
| 1315 // The name was declared before; check for conflicting | 1328 // The name was declared before; check for conflicting |
| 1316 // re-declarations. If the previous declaration was a const or the | 1329 // re-declarations. If the previous declaration was a const or the |
| 1317 // current declaration is a const then we have a conflict. There is | 1330 // current declaration is a const then we have a conflict. There is |
| 1318 // similar code in runtime.cc in the Declare functions. | 1331 // similar code in runtime.cc in the Declare functions. |
| 1319 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) { | 1332 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) { |
| 1320 // We only have vars and consts in declarations. | 1333 // We only have vars and consts in declarations. |
| 1321 ASSERT(var->mode() == Variable::VAR || | 1334 ASSERT(var->mode() == Variable::VAR || |
| 1322 var->mode() == Variable::CONST); | 1335 var->mode() == Variable::CONST); |
| 1323 const char* type = (var->mode() == Variable::VAR) ? "var" : "const"; | 1336 const char* type = (var->mode() == Variable::VAR) ? "var" : "const"; |
| 1324 Handle<String> type_string = | 1337 Handle<String> type_string = |
| 1325 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); | 1338 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); |
| 1326 Expression* expression = | 1339 Expression* expression = |
| 1327 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), | 1340 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), |
| 1328 type_string, name); | 1341 type_string, name); |
| 1329 top_scope_->SetIllegalRedeclaration(expression); | 1342 declaration_scope->SetIllegalRedeclaration(expression); |
| 1330 } | 1343 } |
| 1331 } | 1344 } |
| 1332 } | 1345 } |
| 1333 | 1346 |
| 1334 // We add a declaration node for every declaration. The compiler | 1347 // We add a declaration node for every declaration. The compiler |
| 1335 // will only generate code if necessary. In particular, declarations | 1348 // will only generate code if necessary. In particular, declarations |
| 1336 // for inner local variables that do not represent functions won't | 1349 // for inner local variables that do not represent functions won't |
| 1337 // result in any generated code. | 1350 // result in any generated code. |
| 1338 // | 1351 // |
| 1339 // Note that we always add an unresolved proxy even if it's not | 1352 // Note that we always add an unresolved proxy even if it's not |
| 1340 // used, simply because we don't know in this method (w/o extra | 1353 // used, simply because we don't know in this method (w/o extra |
| 1341 // parameters) if the proxy is needed or not. The proxy will be | 1354 // parameters) if the proxy is needed or not. The proxy will be |
| 1342 // bound during variable resolution time unless it was pre-bound | 1355 // bound during variable resolution time unless it was pre-bound |
| 1343 // below. | 1356 // below. |
| 1344 // | 1357 // |
| 1345 // WARNING: This will lead to multiple declaration nodes for the | 1358 // WARNING: This will lead to multiple declaration nodes for the |
| 1346 // same variable if it is declared several times. This is not a | 1359 // same variable if it is declared several times. This is not a |
| 1347 // semantic issue as long as we keep the source order, but it may be | 1360 // semantic issue as long as we keep the source order, but it may be |
| 1348 // a performance issue since it may lead to repeated | 1361 // a performance issue since it may lead to repeated |
| 1349 // Runtime::DeclareContextSlot() calls. | 1362 // Runtime::DeclareContextSlot() calls. |
| 1350 VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with()); | 1363 VariableProxy* proxy = declaration_scope->NewUnresolved(name, false); |
| 1351 top_scope_->AddDeclaration(new(zone()) Declaration(proxy, mode, fun)); | 1364 declaration_scope->AddDeclaration(new(zone()) Declaration(proxy, mode, fun)); |
| 1352 | 1365 |
| 1353 // For global const variables we bind the proxy to a variable. | 1366 // For global const variables we bind the proxy to a variable. |
| 1354 if (mode == Variable::CONST && top_scope_->is_global_scope()) { | 1367 if (mode == Variable::CONST && declaration_scope->is_global_scope()) { |
| 1355 ASSERT(resolve); // should be set by all callers | 1368 ASSERT(resolve); // should be set by all callers |
| 1356 Variable::Kind kind = Variable::NORMAL; | 1369 Variable::Kind kind = Variable::NORMAL; |
| 1357 var = new(zone()) Variable(top_scope_, name, Variable::CONST, true, kind); | 1370 var = new(zone()) Variable(declaration_scope, |
| 1371 name, |
| 1372 Variable::CONST, |
| 1373 true, |
| 1374 kind); |
| 1358 } | 1375 } |
| 1359 | 1376 |
| 1360 // If requested and we have a local variable, bind the proxy to the variable | 1377 // If requested and we have a local variable, bind the proxy to the variable |
| 1361 // at parse-time. This is used for functions (and consts) declared inside | 1378 // at parse-time. This is used for functions (and consts) declared inside |
| 1362 // statements: the corresponding function (or const) variable must be in the | 1379 // statements: the corresponding function (or const) variable must be in the |
| 1363 // function scope and not a statement-local scope, e.g. as provided with a | 1380 // function scope and not a statement-local scope, e.g. as provided with a |
| 1364 // 'with' statement: | 1381 // 'with' statement: |
| 1365 // | 1382 // |
| 1366 // with (obj) { | 1383 // with (obj) { |
| 1367 // function f() {} | 1384 // function f() {} |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1385 | 1402 |
| 1386 return proxy; | 1403 return proxy; |
| 1387 } | 1404 } |
| 1388 | 1405 |
| 1389 | 1406 |
| 1390 // Language extension which is only enabled for source files loaded | 1407 // Language extension which is only enabled for source files loaded |
| 1391 // through the API's extension mechanism. A native function | 1408 // through the API's extension mechanism. A native function |
| 1392 // declaration is resolved by looking up the function through a | 1409 // declaration is resolved by looking up the function through a |
| 1393 // callback provided by the extension. | 1410 // callback provided by the extension. |
| 1394 Statement* Parser::ParseNativeDeclaration(bool* ok) { | 1411 Statement* Parser::ParseNativeDeclaration(bool* ok) { |
| 1395 if (extension_ == NULL) { | |
| 1396 ReportUnexpectedToken(Token::NATIVE); | |
| 1397 *ok = false; | |
| 1398 return NULL; | |
| 1399 } | |
| 1400 | |
| 1401 Expect(Token::NATIVE, CHECK_OK); | |
| 1402 Expect(Token::FUNCTION, CHECK_OK); | 1412 Expect(Token::FUNCTION, CHECK_OK); |
| 1403 Handle<String> name = ParseIdentifier(CHECK_OK); | 1413 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 1404 Expect(Token::LPAREN, CHECK_OK); | 1414 Expect(Token::LPAREN, CHECK_OK); |
| 1405 bool done = (peek() == Token::RPAREN); | 1415 bool done = (peek() == Token::RPAREN); |
| 1406 while (!done) { | 1416 while (!done) { |
| 1407 ParseIdentifier(CHECK_OK); | 1417 ParseIdentifier(CHECK_OK); |
| 1408 done = (peek() == Token::RPAREN); | 1418 done = (peek() == Token::RPAREN); |
| 1409 if (!done) { | 1419 if (!done) { |
| 1410 Expect(Token::COMMA, CHECK_OK); | 1420 Expect(Token::COMMA, CHECK_OK); |
| 1411 } | 1421 } |
| 1412 } | 1422 } |
| 1413 Expect(Token::RPAREN, CHECK_OK); | 1423 Expect(Token::RPAREN, CHECK_OK); |
| 1414 Expect(Token::SEMICOLON, CHECK_OK); | 1424 Expect(Token::SEMICOLON, CHECK_OK); |
| 1415 | 1425 |
| 1416 // Make sure that the function containing the native declaration | 1426 // Make sure that the function containing the native declaration |
| 1417 // isn't lazily compiled. The extension structures are only | 1427 // isn't lazily compiled. The extension structures are only |
| 1418 // accessible while parsing the first time not when reparsing | 1428 // accessible while parsing the first time not when reparsing |
| 1419 // because of lazy compilation. | 1429 // because of lazy compilation. |
| 1420 top_scope_->ForceEagerCompilation(); | 1430 top_scope_->DeclarationScope()->ForceEagerCompilation(); |
| 1421 | 1431 |
| 1422 // Compute the function template for the native function. | 1432 // Compute the function template for the native function. |
| 1423 v8::Handle<v8::FunctionTemplate> fun_template = | 1433 v8::Handle<v8::FunctionTemplate> fun_template = |
| 1424 extension_->GetNativeFunction(v8::Utils::ToLocal(name)); | 1434 extension_->GetNativeFunction(v8::Utils::ToLocal(name)); |
| 1425 ASSERT(!fun_template.IsEmpty()); | 1435 ASSERT(!fun_template.IsEmpty()); |
| 1426 | 1436 |
| 1427 // Instantiate the function and create a shared function info from it. | 1437 // Instantiate the function and create a shared function info from it. |
| 1428 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction()); | 1438 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction()); |
| 1429 const int literals = fun->NumberOfLiterals(); | 1439 const int literals = fun->NumberOfLiterals(); |
| 1430 Handle<Code> code = Handle<Code>(fun->shared()->code()); | 1440 Handle<Code> code = Handle<Code>(fun->shared()->code()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1448 return new(zone()) ExpressionStatement(new(zone()) Assignment( | 1458 return new(zone()) ExpressionStatement(new(zone()) Assignment( |
| 1449 Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)); | 1459 Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)); |
| 1450 } | 1460 } |
| 1451 | 1461 |
| 1452 | 1462 |
| 1453 Statement* Parser::ParseFunctionDeclaration(bool* ok) { | 1463 Statement* Parser::ParseFunctionDeclaration(bool* ok) { |
| 1454 // FunctionDeclaration :: | 1464 // FunctionDeclaration :: |
| 1455 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 1465 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 1456 Expect(Token::FUNCTION, CHECK_OK); | 1466 Expect(Token::FUNCTION, CHECK_OK); |
| 1457 int function_token_position = scanner().location().beg_pos; | 1467 int function_token_position = scanner().location().beg_pos; |
| 1458 bool is_reserved = false; | 1468 bool is_strict_reserved = false; |
| 1459 Handle<String> name = ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK); | 1469 Handle<String> name = ParseIdentifierOrStrictReservedWord( |
| 1470 &is_strict_reserved, CHECK_OK); |
| 1460 FunctionLiteral* fun = ParseFunctionLiteral(name, | 1471 FunctionLiteral* fun = ParseFunctionLiteral(name, |
| 1461 is_reserved, | 1472 is_strict_reserved, |
| 1462 function_token_position, | 1473 function_token_position, |
| 1463 DECLARATION, | 1474 DECLARATION, |
| 1464 CHECK_OK); | 1475 CHECK_OK); |
| 1465 // Even if we're not at the top-level of the global or a function | 1476 // Even if we're not at the top-level of the global or a function |
| 1466 // scope, we treat is as such and introduce the function with it's | 1477 // scope, we treat is as such and introduce the function with it's |
| 1467 // initial value upon entering the corresponding scope. | 1478 // initial value upon entering the corresponding scope. |
| 1468 Declare(name, Variable::VAR, fun, true, CHECK_OK); | 1479 Declare(name, Variable::VAR, fun, true, CHECK_OK); |
| 1469 return EmptyStatement(); | 1480 return EmptyStatement(); |
| 1470 } | 1481 } |
| 1471 | 1482 |
| 1472 | 1483 |
| 1473 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { | 1484 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
| 1474 // Block :: | 1485 // Block :: |
| 1475 // '{' Statement* '}' | 1486 // '{' Statement* '}' |
| 1476 | 1487 |
| 1477 // Note that a Block does not introduce a new execution scope! | 1488 // Note that a Block does not introduce a new execution scope! |
| 1478 // (ECMA-262, 3rd, 12.2) | 1489 // (ECMA-262, 3rd, 12.2) |
| 1479 // | 1490 // |
| 1480 // Construct block expecting 16 statements. | 1491 // Construct block expecting 16 statements. |
| 1481 Block* result = new(zone()) Block(labels, 16, false); | 1492 Block* result = new(zone()) Block(labels, 16, false); |
| 1482 Target target(&this->target_stack_, result); | 1493 Target target(&this->target_stack_, result); |
| 1483 Expect(Token::LBRACE, CHECK_OK); | 1494 Expect(Token::LBRACE, CHECK_OK); |
| 1495 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
| 1484 while (peek() != Token::RBRACE) { | 1496 while (peek() != Token::RBRACE) { |
| 1485 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1497 Statement* stat = ParseStatement(NULL, CHECK_OK); |
| 1486 if (stat && !stat->IsEmpty()) result->AddStatement(stat); | 1498 if (stat && !stat->IsEmpty()) { |
| 1499 result->AddStatement(stat); |
| 1500 block_finder.Update(stat); |
| 1501 } |
| 1487 } | 1502 } |
| 1488 Expect(Token::RBRACE, CHECK_OK); | 1503 Expect(Token::RBRACE, CHECK_OK); |
| 1489 return result; | 1504 return result; |
| 1490 } | 1505 } |
| 1491 | 1506 |
| 1492 | 1507 |
| 1493 Block* Parser::ParseVariableStatement(bool* ok) { | 1508 Block* Parser::ParseVariableStatement(bool* ok) { |
| 1494 // VariableStatement :: | 1509 // VariableStatement :: |
| 1495 // VariableDeclarations ';' | 1510 // VariableDeclarations ';' |
| 1496 | 1511 |
| 1497 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature | 1512 Handle<String> ignore; |
| 1498 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); | 1513 Block* result = ParseVariableDeclarations(true, &ignore, CHECK_OK); |
| 1499 ExpectSemicolon(CHECK_OK); | 1514 ExpectSemicolon(CHECK_OK); |
| 1500 return result; | 1515 return result; |
| 1501 } | 1516 } |
| 1502 | 1517 |
| 1503 | 1518 |
| 1504 bool Parser::IsEvalOrArguments(Handle<String> string) { | 1519 bool Parser::IsEvalOrArguments(Handle<String> string) { |
| 1505 return string.is_identical_to(isolate()->factory()->eval_symbol()) || | 1520 return string.is_identical_to(isolate()->factory()->eval_symbol()) || |
| 1506 string.is_identical_to(isolate()->factory()->arguments_symbol()); | 1521 string.is_identical_to(isolate()->factory()->arguments_symbol()); |
| 1507 } | 1522 } |
| 1508 | 1523 |
| 1509 | 1524 |
| 1510 // If the variable declaration declares exactly one non-const | 1525 // If the variable declaration declares exactly one non-const |
| 1511 // variable, then *var is set to that variable. In all other cases, | 1526 // variable, then *var is set to that variable. In all other cases, |
| 1512 // *var is untouched; in particular, it is the caller's responsibility | 1527 // *var is untouched; in particular, it is the caller's responsibility |
| 1513 // to initialize it properly. This mechanism is used for the parsing | 1528 // to initialize it properly. This mechanism is used for the parsing |
| 1514 // of 'for-in' loops. | 1529 // of 'for-in' loops. |
| 1515 Block* Parser::ParseVariableDeclarations(bool accept_IN, | 1530 Block* Parser::ParseVariableDeclarations(bool accept_IN, |
| 1516 Expression** var, | 1531 Handle<String>* out, |
| 1517 bool* ok) { | 1532 bool* ok) { |
| 1518 // VariableDeclarations :: | 1533 // VariableDeclarations :: |
| 1519 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 1534 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 1520 | 1535 |
| 1521 Variable::Mode mode = Variable::VAR; | 1536 Variable::Mode mode = Variable::VAR; |
| 1522 bool is_const = false; | 1537 bool is_const = false; |
| 1538 Scope* declaration_scope = top_scope_->DeclarationScope(); |
| 1523 if (peek() == Token::VAR) { | 1539 if (peek() == Token::VAR) { |
| 1524 Consume(Token::VAR); | 1540 Consume(Token::VAR); |
| 1525 } else if (peek() == Token::CONST) { | 1541 } else if (peek() == Token::CONST) { |
| 1526 Consume(Token::CONST); | 1542 Consume(Token::CONST); |
| 1527 if (top_scope_->is_strict_mode()) { | 1543 if (declaration_scope->is_strict_mode()) { |
| 1528 ReportMessage("strict_const", Vector<const char*>::empty()); | 1544 ReportMessage("strict_const", Vector<const char*>::empty()); |
| 1529 *ok = false; | 1545 *ok = false; |
| 1530 return NULL; | 1546 return NULL; |
| 1531 } | 1547 } |
| 1532 mode = Variable::CONST; | 1548 mode = Variable::CONST; |
| 1533 is_const = true; | 1549 is_const = true; |
| 1534 } else { | 1550 } else { |
| 1535 UNREACHABLE(); // by current callers | 1551 UNREACHABLE(); // by current callers |
| 1536 } | 1552 } |
| 1537 | 1553 |
| 1538 // The scope of a variable/const declared anywhere inside a function | 1554 // The scope of a variable/const declared anywhere inside a function |
| 1539 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 1555 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
| 1540 // transform a source-level variable/const declaration into a (Function) | 1556 // transform a source-level variable/const declaration into a (Function) |
| 1541 // Scope declaration, and rewrite the source-level initialization into an | 1557 // Scope declaration, and rewrite the source-level initialization into an |
| 1542 // assignment statement. We use a block to collect multiple assignments. | 1558 // assignment statement. We use a block to collect multiple assignments. |
| 1543 // | 1559 // |
| 1544 // We mark the block as initializer block because we don't want the | 1560 // We mark the block as initializer block because we don't want the |
| 1545 // rewriter to add a '.result' assignment to such a block (to get compliant | 1561 // rewriter to add a '.result' assignment to such a block (to get compliant |
| 1546 // behavior for code such as print(eval('var x = 7')), and for cosmetic | 1562 // behavior for code such as print(eval('var x = 7')), and for cosmetic |
| 1547 // reasons when pretty-printing. Also, unless an assignment (initialization) | 1563 // reasons when pretty-printing. Also, unless an assignment (initialization) |
| 1548 // is inside an initializer block, it is ignored. | 1564 // is inside an initializer block, it is ignored. |
| 1549 // | 1565 // |
| 1550 // Create new block with one expected declaration. | 1566 // Create new block with one expected declaration. |
| 1551 Block* block = new(zone()) Block(NULL, 1, true); | 1567 Block* block = new(zone()) Block(NULL, 1, true); |
| 1552 VariableProxy* last_var = NULL; // the last variable declared | |
| 1553 int nvars = 0; // the number of variables declared | 1568 int nvars = 0; // the number of variables declared |
| 1569 Handle<String> name; |
| 1554 do { | 1570 do { |
| 1555 if (fni_ != NULL) fni_->Enter(); | 1571 if (fni_ != NULL) fni_->Enter(); |
| 1556 | 1572 |
| 1557 // Parse variable name. | 1573 // Parse variable name. |
| 1558 if (nvars > 0) Consume(Token::COMMA); | 1574 if (nvars > 0) Consume(Token::COMMA); |
| 1559 Handle<String> name = ParseIdentifier(CHECK_OK); | 1575 name = ParseIdentifier(CHECK_OK); |
| 1560 if (fni_ != NULL) fni_->PushVariableName(name); | 1576 if (fni_ != NULL) fni_->PushVariableName(name); |
| 1561 | 1577 |
| 1562 // Strict mode variables may not be named eval or arguments | 1578 // Strict mode variables may not be named eval or arguments |
| 1563 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { | 1579 if (declaration_scope->is_strict_mode() && IsEvalOrArguments(name)) { |
| 1564 ReportMessage("strict_var_name", Vector<const char*>::empty()); | 1580 ReportMessage("strict_var_name", Vector<const char*>::empty()); |
| 1565 *ok = false; | 1581 *ok = false; |
| 1566 return NULL; | 1582 return NULL; |
| 1567 } | 1583 } |
| 1568 | 1584 |
| 1569 // Declare variable. | 1585 // Declare variable. |
| 1570 // Note that we *always* must treat the initial value via a separate init | 1586 // Note that we *always* must treat the initial value via a separate init |
| 1571 // assignment for variables and constants because the value must be assigned | 1587 // assignment for variables and constants because the value must be assigned |
| 1572 // when the variable is encountered in the source. But the variable/constant | 1588 // when the variable is encountered in the source. But the variable/constant |
| 1573 // is declared (and set to 'undefined') upon entering the function within | 1589 // is declared (and set to 'undefined') upon entering the function within |
| 1574 // which the variable or constant is declared. Only function variables have | 1590 // which the variable or constant is declared. Only function variables have |
| 1575 // an initial value in the declaration (because they are initialized upon | 1591 // an initial value in the declaration (because they are initialized upon |
| 1576 // entering the function). | 1592 // entering the function). |
| 1577 // | 1593 // |
| 1578 // If we have a const declaration, in an inner scope, the proxy is always | 1594 // If we have a const declaration, in an inner scope, the proxy is always |
| 1579 // bound to the declared variable (independent of possibly surrounding with | 1595 // bound to the declared variable (independent of possibly surrounding with |
| 1580 // statements). | 1596 // statements). |
| 1581 last_var = Declare(name, mode, NULL, | 1597 Declare(name, mode, NULL, is_const /* always bound for CONST! */, |
| 1582 is_const /* always bound for CONST! */, | 1598 CHECK_OK); |
| 1583 CHECK_OK); | |
| 1584 nvars++; | 1599 nvars++; |
| 1585 if (top_scope_->num_var_or_const() > kMaxNumFunctionLocals) { | 1600 if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) { |
| 1586 ReportMessageAt(scanner().location(), "too_many_variables", | 1601 ReportMessageAt(scanner().location(), "too_many_variables", |
| 1587 Vector<const char*>::empty()); | 1602 Vector<const char*>::empty()); |
| 1588 *ok = false; | 1603 *ok = false; |
| 1589 return NULL; | 1604 return NULL; |
| 1590 } | 1605 } |
| 1591 | 1606 |
| 1592 // Parse initialization expression if present and/or needed. A | 1607 // Parse initialization expression if present and/or needed. A |
| 1593 // declaration of the form: | 1608 // declaration of the form: |
| 1594 // | 1609 // |
| 1595 // var v = x; | 1610 // var v = x; |
| 1596 // | 1611 // |
| 1597 // is syntactic sugar for: | 1612 // is syntactic sugar for: |
| 1598 // | 1613 // |
| 1599 // var v; v = x; | 1614 // var v; v = x; |
| 1600 // | 1615 // |
| 1601 // In particular, we need to re-lookup 'v' as it may be a | 1616 // In particular, we need to re-lookup 'v' (in top_scope_, not |
| 1602 // different 'v' than the 'v' in the declaration (if we are inside | 1617 // declaration_scope) as it may be a different 'v' than the 'v' in the |
| 1603 // a 'with' statement that makes a object property with name 'v' | 1618 // declaration (e.g., if we are inside a 'with' statement or 'catch' |
| 1604 // visible). | 1619 // block). |
| 1605 // | 1620 // |
| 1606 // However, note that const declarations are different! A const | 1621 // However, note that const declarations are different! A const |
| 1607 // declaration of the form: | 1622 // declaration of the form: |
| 1608 // | 1623 // |
| 1609 // const c = x; | 1624 // const c = x; |
| 1610 // | 1625 // |
| 1611 // is *not* syntactic sugar for: | 1626 // is *not* syntactic sugar for: |
| 1612 // | 1627 // |
| 1613 // const c; c = x; | 1628 // const c; c = x; |
| 1614 // | 1629 // |
| 1615 // The "variable" c initialized to x is the same as the declared | 1630 // The "variable" c initialized to x is the same as the declared |
| 1616 // one - there is no re-lookup (see the last parameter of the | 1631 // one - there is no re-lookup (see the last parameter of the |
| 1617 // Declare() call above). | 1632 // Declare() call above). |
| 1618 | 1633 |
| 1634 Scope* initialization_scope = is_const ? declaration_scope : top_scope_; |
| 1619 Expression* value = NULL; | 1635 Expression* value = NULL; |
| 1620 int position = -1; | 1636 int position = -1; |
| 1621 if (peek() == Token::ASSIGN) { | 1637 if (peek() == Token::ASSIGN) { |
| 1622 Expect(Token::ASSIGN, CHECK_OK); | 1638 Expect(Token::ASSIGN, CHECK_OK); |
| 1623 position = scanner().location().beg_pos; | 1639 position = scanner().location().beg_pos; |
| 1624 value = ParseAssignmentExpression(accept_IN, CHECK_OK); | 1640 value = ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 1625 // Don't infer if it is "a = function(){...}();"-like expression. | 1641 // Don't infer if it is "a = function(){...}();"-like expression. |
| 1626 if (fni_ != NULL && value->AsCall() == NULL) fni_->Infer(); | 1642 if (fni_ != NULL && |
| 1643 value->AsCall() == NULL && |
| 1644 value->AsCallNew() == NULL) { |
| 1645 fni_->Infer(); |
| 1646 } |
| 1627 } | 1647 } |
| 1628 | 1648 |
| 1629 // Make sure that 'const c' actually initializes 'c' to undefined | 1649 // Make sure that 'const c' actually initializes 'c' to undefined |
| 1630 // even though it seems like a stupid thing to do. | 1650 // even though it seems like a stupid thing to do. |
| 1631 if (value == NULL && is_const) { | 1651 if (value == NULL && is_const) { |
| 1632 value = GetLiteralUndefined(); | 1652 value = GetLiteralUndefined(); |
| 1633 } | 1653 } |
| 1634 | 1654 |
| 1635 // Global variable declarations must be compiled in a specific | 1655 // Global variable declarations must be compiled in a specific |
| 1636 // way. When the script containing the global variable declaration | 1656 // way. When the script containing the global variable declaration |
| 1637 // is entered, the global variable must be declared, so that if it | 1657 // is entered, the global variable must be declared, so that if it |
| 1638 // doesn't exist (not even in a prototype of the global object) it | 1658 // doesn't exist (not even in a prototype of the global object) it |
| 1639 // gets created with an initial undefined value. This is handled | 1659 // gets created with an initial undefined value. This is handled |
| 1640 // by the declarations part of the function representing the | 1660 // by the declarations part of the function representing the |
| 1641 // top-level global code; see Runtime::DeclareGlobalVariable. If | 1661 // top-level global code; see Runtime::DeclareGlobalVariable. If |
| 1642 // it already exists (in the object or in a prototype), it is | 1662 // it already exists (in the object or in a prototype), it is |
| 1643 // *not* touched until the variable declaration statement is | 1663 // *not* touched until the variable declaration statement is |
| 1644 // executed. | 1664 // executed. |
| 1645 // | 1665 // |
| 1646 // Executing the variable declaration statement will always | 1666 // Executing the variable declaration statement will always |
| 1647 // guarantee to give the global object a "local" variable; a | 1667 // guarantee to give the global object a "local" variable; a |
| 1648 // variable defined in the global object and not in any | 1668 // variable defined in the global object and not in any |
| 1649 // prototype. This way, global variable declarations can shadow | 1669 // prototype. This way, global variable declarations can shadow |
| 1650 // properties in the prototype chain, but only after the variable | 1670 // properties in the prototype chain, but only after the variable |
| 1651 // declaration statement has been executed. This is important in | 1671 // declaration statement has been executed. This is important in |
| 1652 // browsers where the global object (window) has lots of | 1672 // browsers where the global object (window) has lots of |
| 1653 // properties defined in prototype objects. | 1673 // properties defined in prototype objects. |
| 1654 | 1674 |
| 1655 if (top_scope_->is_global_scope()) { | 1675 if (initialization_scope->is_global_scope()) { |
| 1656 // Compute the arguments for the runtime call. | 1676 // Compute the arguments for the runtime call. |
| 1657 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3); | 1677 ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3); |
| 1658 // We have at least 1 parameter. | 1678 // We have at least 1 parameter. |
| 1659 arguments->Add(new(zone()) Literal(name)); | 1679 arguments->Add(new(zone()) Literal(name)); |
| 1660 CallRuntime* initialize; | 1680 CallRuntime* initialize; |
| 1661 | 1681 |
| 1662 if (is_const) { | 1682 if (is_const) { |
| 1663 arguments->Add(value); | 1683 arguments->Add(value); |
| 1664 value = NULL; // zap the value to avoid the unnecessary assignment | 1684 value = NULL; // zap the value to avoid the unnecessary assignment |
| 1665 | 1685 |
| 1666 // Construct the call to Runtime_InitializeConstGlobal | 1686 // Construct the call to Runtime_InitializeConstGlobal |
| 1667 // and add it to the initialization statement block. | 1687 // and add it to the initialization statement block. |
| 1668 // Note that the function does different things depending on | 1688 // Note that the function does different things depending on |
| 1669 // the number of arguments (1 or 2). | 1689 // the number of arguments (1 or 2). |
| 1670 initialize = | 1690 initialize = |
| 1671 new(zone()) CallRuntime( | 1691 new(zone()) CallRuntime( |
| 1672 isolate()->factory()->InitializeConstGlobal_symbol(), | 1692 isolate()->factory()->InitializeConstGlobal_symbol(), |
| 1673 Runtime::FunctionForId(Runtime::kInitializeConstGlobal), | 1693 Runtime::FunctionForId(Runtime::kInitializeConstGlobal), |
| 1674 arguments); | 1694 arguments); |
| 1675 } else { | 1695 } else { |
| 1676 // Add strict mode. | 1696 // Add strict mode. |
| 1677 // We may want to pass singleton to avoid Literal allocations. | 1697 // We may want to pass singleton to avoid Literal allocations. |
| 1678 arguments->Add(NewNumberLiteral( | 1698 StrictModeFlag flag = initialization_scope->is_strict_mode() |
| 1679 top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode)); | 1699 ? kStrictMode |
| 1700 : kNonStrictMode; |
| 1701 arguments->Add(NewNumberLiteral(flag)); |
| 1680 | 1702 |
| 1681 // Be careful not to assign a value to the global variable if | 1703 // Be careful not to assign a value to the global variable if |
| 1682 // we're in a with. The initialization value should not | 1704 // we're in a with. The initialization value should not |
| 1683 // necessarily be stored in the global object in that case, | 1705 // necessarily be stored in the global object in that case, |
| 1684 // which is why we need to generate a separate assignment node. | 1706 // which is why we need to generate a separate assignment node. |
| 1685 if (value != NULL && !inside_with()) { | 1707 if (value != NULL && !inside_with()) { |
| 1686 arguments->Add(value); | 1708 arguments->Add(value); |
| 1687 value = NULL; // zap the value to avoid the unnecessary assignment | 1709 value = NULL; // zap the value to avoid the unnecessary assignment |
| 1688 } | 1710 } |
| 1689 | 1711 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1706 // between variables and constants: Variable initializations are simply | 1728 // between variables and constants: Variable initializations are simply |
| 1707 // assignments (with all the consequences if they are inside a 'with' | 1729 // assignments (with all the consequences if they are inside a 'with' |
| 1708 // statement - they may change a 'with' object property). Constant | 1730 // statement - they may change a 'with' object property). Constant |
| 1709 // initializations always assign to the declared constant which is | 1731 // initializations always assign to the declared constant which is |
| 1710 // always at the function scope level. This is only relevant for | 1732 // always at the function scope level. This is only relevant for |
| 1711 // dynamically looked-up variables and constants (the start context | 1733 // dynamically looked-up variables and constants (the start context |
| 1712 // for constant lookups is always the function context, while it is | 1734 // for constant lookups is always the function context, while it is |
| 1713 // the top context for variables). Sigh... | 1735 // the top context for variables). Sigh... |
| 1714 if (value != NULL) { | 1736 if (value != NULL) { |
| 1715 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR); | 1737 Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR); |
| 1738 bool in_with = is_const ? false : inside_with(); |
| 1739 VariableProxy* proxy = |
| 1740 initialization_scope->NewUnresolved(name, in_with); |
| 1716 Assignment* assignment = | 1741 Assignment* assignment = |
| 1717 new(zone()) Assignment(op, last_var, value, position); | 1742 new(zone()) Assignment(op, proxy, value, position); |
| 1718 if (block) { | 1743 if (block) { |
| 1719 block->AddStatement(new(zone()) ExpressionStatement(assignment)); | 1744 block->AddStatement(new(zone()) ExpressionStatement(assignment)); |
| 1720 } | 1745 } |
| 1721 } | 1746 } |
| 1722 | 1747 |
| 1723 if (fni_ != NULL) fni_->Leave(); | 1748 if (fni_ != NULL) fni_->Leave(); |
| 1724 } while (peek() == Token::COMMA); | 1749 } while (peek() == Token::COMMA); |
| 1725 | 1750 |
| 1726 if (!is_const && nvars == 1) { | 1751 // If there was a single non-const declaration, return it in the output |
| 1727 // We have a single, non-const variable. | 1752 // parameter for possible use by for/in. |
| 1728 ASSERT(last_var != NULL); | 1753 if (nvars == 1 && !is_const) { |
| 1729 *var = last_var; | 1754 *out = name; |
| 1730 } | 1755 } |
| 1731 | 1756 |
| 1732 return block; | 1757 return block; |
| 1733 } | 1758 } |
| 1734 | 1759 |
| 1735 | 1760 |
| 1736 static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) { | 1761 static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) { |
| 1737 ASSERT(!label.is_null()); | 1762 ASSERT(!label.is_null()); |
| 1738 if (labels != NULL) | 1763 if (labels != NULL) |
| 1739 for (int i = labels->length(); i-- > 0; ) | 1764 for (int i = labels->length(); i-- > 0; ) |
| 1740 if (labels->at(i).is_identical_to(label)) | 1765 if (labels->at(i).is_identical_to(label)) |
| 1741 return true; | 1766 return true; |
| 1742 | 1767 |
| 1743 return false; | 1768 return false; |
| 1744 } | 1769 } |
| 1745 | 1770 |
| 1746 | 1771 |
| 1747 Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, | 1772 Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, |
| 1748 bool* ok) { | 1773 bool* ok) { |
| 1749 // ExpressionStatement | LabelledStatement :: | 1774 // ExpressionStatement | LabelledStatement :: |
| 1750 // Expression ';' | 1775 // Expression ';' |
| 1751 // Identifier ':' Statement | 1776 // Identifier ':' Statement |
| 1752 bool starts_with_idenfifier = peek_any_identifier(); | 1777 bool starts_with_idenfifier = peek_any_identifier(); |
| 1753 Expression* expr = ParseExpression(true, CHECK_OK); | 1778 Expression* expr = ParseExpression(true, CHECK_OK); |
| 1754 if (peek() == Token::COLON && starts_with_idenfifier && expr && | 1779 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && |
| 1755 expr->AsVariableProxy() != NULL && | 1780 expr->AsVariableProxy() != NULL && |
| 1756 !expr->AsVariableProxy()->is_this()) { | 1781 !expr->AsVariableProxy()->is_this()) { |
| 1757 // Expression is a single identifier, and not, e.g., a parenthesized | 1782 // Expression is a single identifier, and not, e.g., a parenthesized |
| 1758 // identifier. | 1783 // identifier. |
| 1759 VariableProxy* var = expr->AsVariableProxy(); | 1784 VariableProxy* var = expr->AsVariableProxy(); |
| 1760 Handle<String> label = var->name(); | 1785 Handle<String> label = var->name(); |
| 1761 // TODO(1240780): We don't check for redeclaration of labels | 1786 // TODO(1240780): We don't check for redeclaration of labels |
| 1762 // during preparsing since keeping track of the set of active | 1787 // during preparsing since keeping track of the set of active |
| 1763 // labels requires nontrivial changes to the way scopes are | 1788 // labels requires nontrivial changes to the way scopes are |
| 1764 // structured. However, these are probably changes we want to | 1789 // structured. However, these are probably changes we want to |
| 1765 // make later anyway so we should go back and fix this then. | 1790 // make later anyway so we should go back and fix this then. |
| 1766 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | 1791 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
| 1767 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS); | 1792 SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS); |
| 1768 const char* elms[2] = { "Label", *c_string }; | 1793 const char* elms[2] = { "Label", *c_string }; |
| 1769 Vector<const char*> args(elms, 2); | 1794 Vector<const char*> args(elms, 2); |
| 1770 ReportMessage("redeclaration", args); | 1795 ReportMessage("redeclaration", args); |
| 1771 *ok = false; | 1796 *ok = false; |
| 1772 return NULL; | 1797 return NULL; |
| 1773 } | 1798 } |
| 1774 if (labels == NULL) labels = new(zone()) ZoneStringList(4); | 1799 if (labels == NULL) labels = new(zone()) ZoneStringList(4); |
| 1775 labels->Add(label); | 1800 labels->Add(label); |
| 1776 // Remove the "ghost" variable that turned out to be a label | 1801 // Remove the "ghost" variable that turned out to be a label |
| 1777 // from the top scope. This way, we don't try to resolve it | 1802 // from the top scope. This way, we don't try to resolve it |
| 1778 // during the scope processing. | 1803 // during the scope processing. |
| 1779 top_scope_->RemoveUnresolved(var); | 1804 top_scope_->RemoveUnresolved(var); |
| 1780 Expect(Token::COLON, CHECK_OK); | 1805 Expect(Token::COLON, CHECK_OK); |
| 1781 return ParseStatement(labels, ok); | 1806 return ParseStatement(labels, ok); |
| 1782 } | 1807 } |
| 1783 | 1808 |
| 1809 // If we have an extension, we allow a native function declaration. |
| 1810 // A native function declaration starts with "native function" with |
| 1811 // no line-terminator between the two words. |
| 1812 if (extension_ != NULL && |
| 1813 peek() == Token::FUNCTION && |
| 1814 !scanner().HasAnyLineTerminatorBeforeNext() && |
| 1815 expr != NULL && |
| 1816 expr->AsVariableProxy() != NULL && |
| 1817 expr->AsVariableProxy()->name()->Equals( |
| 1818 isolate()->heap()->native_symbol()) && |
| 1819 !scanner().literal_contains_escapes()) { |
| 1820 return ParseNativeDeclaration(ok); |
| 1821 } |
| 1822 |
| 1784 // Parsed expression statement. | 1823 // Parsed expression statement. |
| 1785 ExpectSemicolon(CHECK_OK); | 1824 ExpectSemicolon(CHECK_OK); |
| 1786 return new(zone()) ExpressionStatement(expr); | 1825 return new(zone()) ExpressionStatement(expr); |
| 1787 } | 1826 } |
| 1788 | 1827 |
| 1789 | 1828 |
| 1790 IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) { | 1829 IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) { |
| 1791 // IfStatement :: | 1830 // IfStatement :: |
| 1792 // 'if' '(' Expression ')' Statement ('else' Statement)? | 1831 // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 1793 | 1832 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1807 } | 1846 } |
| 1808 | 1847 |
| 1809 | 1848 |
| 1810 Statement* Parser::ParseContinueStatement(bool* ok) { | 1849 Statement* Parser::ParseContinueStatement(bool* ok) { |
| 1811 // ContinueStatement :: | 1850 // ContinueStatement :: |
| 1812 // 'continue' Identifier? ';' | 1851 // 'continue' Identifier? ';' |
| 1813 | 1852 |
| 1814 Expect(Token::CONTINUE, CHECK_OK); | 1853 Expect(Token::CONTINUE, CHECK_OK); |
| 1815 Handle<String> label = Handle<String>::null(); | 1854 Handle<String> label = Handle<String>::null(); |
| 1816 Token::Value tok = peek(); | 1855 Token::Value tok = peek(); |
| 1817 if (!scanner().has_line_terminator_before_next() && | 1856 if (!scanner().HasAnyLineTerminatorBeforeNext() && |
| 1818 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 1857 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| 1819 label = ParseIdentifier(CHECK_OK); | 1858 label = ParseIdentifier(CHECK_OK); |
| 1820 } | 1859 } |
| 1821 IterationStatement* target = NULL; | 1860 IterationStatement* target = NULL; |
| 1822 target = LookupContinueTarget(label, CHECK_OK); | 1861 target = LookupContinueTarget(label, CHECK_OK); |
| 1823 if (target == NULL) { | 1862 if (target == NULL) { |
| 1824 // Illegal continue statement. | 1863 // Illegal continue statement. |
| 1825 const char* message = "illegal_continue"; | 1864 const char* message = "illegal_continue"; |
| 1826 Vector<Handle<String> > args; | 1865 Vector<Handle<String> > args; |
| 1827 if (!label.is_null()) { | 1866 if (!label.is_null()) { |
| 1828 message = "unknown_label"; | 1867 message = "unknown_label"; |
| 1829 args = Vector<Handle<String> >(&label, 1); | 1868 args = Vector<Handle<String> >(&label, 1); |
| 1830 } | 1869 } |
| 1831 ReportMessageAt(scanner().location(), message, args); | 1870 ReportMessageAt(scanner().location(), message, args); |
| 1832 *ok = false; | 1871 *ok = false; |
| 1833 return NULL; | 1872 return NULL; |
| 1834 } | 1873 } |
| 1835 ExpectSemicolon(CHECK_OK); | 1874 ExpectSemicolon(CHECK_OK); |
| 1836 return new(zone()) ContinueStatement(target); | 1875 return new(zone()) ContinueStatement(target); |
| 1837 } | 1876 } |
| 1838 | 1877 |
| 1839 | 1878 |
| 1840 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { | 1879 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| 1841 // BreakStatement :: | 1880 // BreakStatement :: |
| 1842 // 'break' Identifier? ';' | 1881 // 'break' Identifier? ';' |
| 1843 | 1882 |
| 1844 Expect(Token::BREAK, CHECK_OK); | 1883 Expect(Token::BREAK, CHECK_OK); |
| 1845 Handle<String> label; | 1884 Handle<String> label; |
| 1846 Token::Value tok = peek(); | 1885 Token::Value tok = peek(); |
| 1847 if (!scanner().has_line_terminator_before_next() && | 1886 if (!scanner().HasAnyLineTerminatorBeforeNext() && |
| 1848 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 1887 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| 1849 label = ParseIdentifier(CHECK_OK); | 1888 label = ParseIdentifier(CHECK_OK); |
| 1850 } | 1889 } |
| 1851 // Parse labeled break statements that target themselves into | 1890 // Parse labeled break statements that target themselves into |
| 1852 // empty statements, e.g. 'l1: l2: l3: break l2;' | 1891 // empty statements, e.g. 'l1: l2: l3: break l2;' |
| 1853 if (!label.is_null() && ContainsLabel(labels, label)) { | 1892 if (!label.is_null() && ContainsLabel(labels, label)) { |
| 1854 return EmptyStatement(); | 1893 return EmptyStatement(); |
| 1855 } | 1894 } |
| 1856 BreakableStatement* target = NULL; | 1895 BreakableStatement* target = NULL; |
| 1857 target = LookupBreakTarget(label, CHECK_OK); | 1896 target = LookupBreakTarget(label, CHECK_OK); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1879 // Consume the return token. It is necessary to do the before | 1918 // Consume the return token. It is necessary to do the before |
| 1880 // reporting any errors on it, because of the way errors are | 1919 // reporting any errors on it, because of the way errors are |
| 1881 // reported (underlining). | 1920 // reported (underlining). |
| 1882 Expect(Token::RETURN, CHECK_OK); | 1921 Expect(Token::RETURN, CHECK_OK); |
| 1883 | 1922 |
| 1884 // An ECMAScript program is considered syntactically incorrect if it | 1923 // An ECMAScript program is considered syntactically incorrect if it |
| 1885 // contains a return statement that is not within the body of a | 1924 // contains a return statement that is not within the body of a |
| 1886 // function. See ECMA-262, section 12.9, page 67. | 1925 // function. See ECMA-262, section 12.9, page 67. |
| 1887 // | 1926 // |
| 1888 // To be consistent with KJS we report the syntax error at runtime. | 1927 // To be consistent with KJS we report the syntax error at runtime. |
| 1889 if (!top_scope_->is_function_scope()) { | 1928 Scope* declaration_scope = top_scope_->DeclarationScope(); |
| 1929 if (declaration_scope->is_global_scope() || |
| 1930 declaration_scope->is_eval_scope()) { |
| 1890 Handle<String> type = isolate()->factory()->illegal_return_symbol(); | 1931 Handle<String> type = isolate()->factory()->illegal_return_symbol(); |
| 1891 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null()); | 1932 Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null()); |
| 1892 return new(zone()) ExpressionStatement(throw_error); | 1933 return new(zone()) ExpressionStatement(throw_error); |
| 1893 } | 1934 } |
| 1894 | 1935 |
| 1895 Token::Value tok = peek(); | 1936 Token::Value tok = peek(); |
| 1896 if (scanner().has_line_terminator_before_next() || | 1937 if (scanner().HasAnyLineTerminatorBeforeNext() || |
| 1897 tok == Token::SEMICOLON || | 1938 tok == Token::SEMICOLON || |
| 1898 tok == Token::RBRACE || | 1939 tok == Token::RBRACE || |
| 1899 tok == Token::EOS) { | 1940 tok == Token::EOS) { |
| 1900 ExpectSemicolon(CHECK_OK); | 1941 ExpectSemicolon(CHECK_OK); |
| 1901 return new(zone()) ReturnStatement(GetLiteralUndefined()); | 1942 return new(zone()) ReturnStatement(GetLiteralUndefined()); |
| 1902 } | 1943 } |
| 1903 | 1944 |
| 1904 Expression* expr = ParseExpression(true, CHECK_OK); | 1945 Expression* expr = ParseExpression(true, CHECK_OK); |
| 1905 ExpectSemicolon(CHECK_OK); | 1946 ExpectSemicolon(CHECK_OK); |
| 1906 return new(zone()) ReturnStatement(expr); | 1947 return new(zone()) ReturnStatement(expr); |
| 1907 } | 1948 } |
| 1908 | 1949 |
| 1909 | 1950 |
| 1910 Block* Parser::WithHelper(Expression* obj, | 1951 Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) { |
| 1911 ZoneStringList* labels, | |
| 1912 bool is_catch_block, | |
| 1913 bool* ok) { | |
| 1914 // Parse the statement and collect escaping labels. | 1952 // Parse the statement and collect escaping labels. |
| 1915 ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0); | 1953 TargetCollector collector; |
| 1916 TargetCollector collector(target_list); | |
| 1917 Statement* stat; | 1954 Statement* stat; |
| 1918 { Target target(&this->target_stack_, &collector); | 1955 { Target target(&this->target_stack_, &collector); |
| 1919 with_nesting_level_++; | 1956 with_nesting_level_++; |
| 1920 top_scope_->RecordWithStatement(); | 1957 top_scope_->DeclarationScope()->RecordWithStatement(); |
| 1921 stat = ParseStatement(labels, CHECK_OK); | 1958 stat = ParseStatement(labels, CHECK_OK); |
| 1922 with_nesting_level_--; | 1959 with_nesting_level_--; |
| 1923 } | 1960 } |
| 1924 // Create resulting block with two statements. | 1961 // Create resulting block with two statements. |
| 1925 // 1: Evaluate the with expression. | 1962 // 1: Evaluate the with expression. |
| 1926 // 2: The try-finally block evaluating the body. | 1963 // 2: The try-finally block evaluating the body. |
| 1927 Block* result = new(zone()) Block(NULL, 2, false); | 1964 Block* result = new(zone()) Block(NULL, 2, false); |
| 1928 | 1965 |
| 1929 if (result != NULL) { | 1966 if (result != NULL) { |
| 1930 result->AddStatement(new(zone()) WithEnterStatement(obj, is_catch_block)); | 1967 result->AddStatement(new(zone()) EnterWithContextStatement(obj)); |
| 1931 | 1968 |
| 1932 // Create body block. | 1969 // Create body block. |
| 1933 Block* body = new(zone()) Block(NULL, 1, false); | 1970 Block* body = new(zone()) Block(NULL, 1, false); |
| 1934 body->AddStatement(stat); | 1971 body->AddStatement(stat); |
| 1935 | 1972 |
| 1936 // Create exit block. | 1973 // Create exit block. |
| 1937 Block* exit = new(zone()) Block(NULL, 1, false); | 1974 Block* exit = new(zone()) Block(NULL, 1, false); |
| 1938 exit->AddStatement(new(zone()) WithExitStatement()); | 1975 exit->AddStatement(new(zone()) ExitContextStatement()); |
| 1939 | 1976 |
| 1940 // Return a try-finally statement. | 1977 // Return a try-finally statement. |
| 1941 TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit); | 1978 TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit); |
| 1942 wrapper->set_escaping_targets(collector.targets()); | 1979 wrapper->set_escaping_targets(collector.targets()); |
| 1943 result->AddStatement(wrapper); | 1980 result->AddStatement(wrapper); |
| 1944 } | 1981 } |
| 1945 return result; | 1982 return result; |
| 1946 } | 1983 } |
| 1947 | 1984 |
| 1948 | 1985 |
| 1949 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { | 1986 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
| 1950 // WithStatement :: | 1987 // WithStatement :: |
| 1951 // 'with' '(' Expression ')' Statement | 1988 // 'with' '(' Expression ')' Statement |
| 1952 | 1989 |
| 1953 Expect(Token::WITH, CHECK_OK); | 1990 Expect(Token::WITH, CHECK_OK); |
| 1954 | 1991 |
| 1955 if (top_scope_->is_strict_mode()) { | 1992 if (top_scope_->is_strict_mode()) { |
| 1956 ReportMessage("strict_mode_with", Vector<const char*>::empty()); | 1993 ReportMessage("strict_mode_with", Vector<const char*>::empty()); |
| 1957 *ok = false; | 1994 *ok = false; |
| 1958 return NULL; | 1995 return NULL; |
| 1959 } | 1996 } |
| 1960 | 1997 |
| 1961 Expect(Token::LPAREN, CHECK_OK); | 1998 Expect(Token::LPAREN, CHECK_OK); |
| 1962 Expression* expr = ParseExpression(true, CHECK_OK); | 1999 Expression* expr = ParseExpression(true, CHECK_OK); |
| 1963 Expect(Token::RPAREN, CHECK_OK); | 2000 Expect(Token::RPAREN, CHECK_OK); |
| 1964 | 2001 |
| 1965 return WithHelper(expr, labels, false, CHECK_OK); | 2002 return WithHelper(expr, labels, CHECK_OK); |
| 1966 } | 2003 } |
| 1967 | 2004 |
| 1968 | 2005 |
| 1969 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | 2006 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| 1970 // CaseClause :: | 2007 // CaseClause :: |
| 1971 // 'case' Expression ':' Statement* | 2008 // 'case' Expression ':' Statement* |
| 1972 // 'default' ':' Statement* | 2009 // 'default' ':' Statement* |
| 1973 | 2010 |
| 1974 Expression* label = NULL; // NULL expression indicates default case | 2011 Expression* label = NULL; // NULL expression indicates default case |
| 1975 if (peek() == Token::CASE) { | 2012 if (peek() == Token::CASE) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2025 return statement; | 2062 return statement; |
| 2026 } | 2063 } |
| 2027 | 2064 |
| 2028 | 2065 |
| 2029 Statement* Parser::ParseThrowStatement(bool* ok) { | 2066 Statement* Parser::ParseThrowStatement(bool* ok) { |
| 2030 // ThrowStatement :: | 2067 // ThrowStatement :: |
| 2031 // 'throw' Expression ';' | 2068 // 'throw' Expression ';' |
| 2032 | 2069 |
| 2033 Expect(Token::THROW, CHECK_OK); | 2070 Expect(Token::THROW, CHECK_OK); |
| 2034 int pos = scanner().location().beg_pos; | 2071 int pos = scanner().location().beg_pos; |
| 2035 if (scanner().has_line_terminator_before_next()) { | 2072 if (scanner().HasAnyLineTerminatorBeforeNext()) { |
| 2036 ReportMessage("newline_after_throw", Vector<const char*>::empty()); | 2073 ReportMessage("newline_after_throw", Vector<const char*>::empty()); |
| 2037 *ok = false; | 2074 *ok = false; |
| 2038 return NULL; | 2075 return NULL; |
| 2039 } | 2076 } |
| 2040 Expression* exception = ParseExpression(true, CHECK_OK); | 2077 Expression* exception = ParseExpression(true, CHECK_OK); |
| 2041 ExpectSemicolon(CHECK_OK); | 2078 ExpectSemicolon(CHECK_OK); |
| 2042 | 2079 |
| 2043 return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos)); | 2080 return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos)); |
| 2044 } | 2081 } |
| 2045 | 2082 |
| 2046 | 2083 |
| 2047 TryStatement* Parser::ParseTryStatement(bool* ok) { | 2084 TryStatement* Parser::ParseTryStatement(bool* ok) { |
| 2048 // TryStatement :: | 2085 // TryStatement :: |
| 2049 // 'try' Block Catch | 2086 // 'try' Block Catch |
| 2050 // 'try' Block Finally | 2087 // 'try' Block Finally |
| 2051 // 'try' Block Catch Finally | 2088 // 'try' Block Catch Finally |
| 2052 // | 2089 // |
| 2053 // Catch :: | 2090 // Catch :: |
| 2054 // 'catch' '(' Identifier ')' Block | 2091 // 'catch' '(' Identifier ')' Block |
| 2055 // | 2092 // |
| 2056 // Finally :: | 2093 // Finally :: |
| 2057 // 'finally' Block | 2094 // 'finally' Block |
| 2058 | 2095 |
| 2059 Expect(Token::TRY, CHECK_OK); | 2096 Expect(Token::TRY, CHECK_OK); |
| 2060 | 2097 |
| 2061 ZoneList<Label*>* target_list = new(zone()) ZoneList<Label*>(0); | 2098 TargetCollector try_collector; |
| 2062 TargetCollector collector(target_list); | |
| 2063 Block* try_block; | 2099 Block* try_block; |
| 2064 | 2100 |
| 2065 { Target target(&this->target_stack_, &collector); | 2101 { Target target(&this->target_stack_, &try_collector); |
| 2066 try_block = ParseBlock(NULL, CHECK_OK); | 2102 try_block = ParseBlock(NULL, CHECK_OK); |
| 2067 } | 2103 } |
| 2068 | 2104 |
| 2069 Block* catch_block = NULL; | |
| 2070 Variable* catch_var = NULL; | |
| 2071 Block* finally_block = NULL; | |
| 2072 | |
| 2073 Token::Value tok = peek(); | 2105 Token::Value tok = peek(); |
| 2074 if (tok != Token::CATCH && tok != Token::FINALLY) { | 2106 if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 2075 ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); | 2107 ReportMessage("no_catch_or_finally", Vector<const char*>::empty()); |
| 2076 *ok = false; | 2108 *ok = false; |
| 2077 return NULL; | 2109 return NULL; |
| 2078 } | 2110 } |
| 2079 | 2111 |
| 2080 // If we can break out from the catch block and there is a finally block, | 2112 // If we can break out from the catch block and there is a finally block, |
| 2081 // then we will need to collect jump targets from the catch block. Since | 2113 // then we will need to collect escaping targets from the catch |
| 2082 // we don't know yet if there will be a finally block, we always collect | 2114 // block. Since we don't know yet if there will be a finally block, we |
| 2083 // the jump targets. | 2115 // always collect the targets. |
| 2084 ZoneList<Label*>* catch_target_list = new(zone()) ZoneList<Label*>(0); | 2116 TargetCollector catch_collector; |
| 2085 TargetCollector catch_collector(catch_target_list); | 2117 Scope* catch_scope = NULL; |
| 2086 bool has_catch = false; | 2118 Variable* catch_variable = NULL; |
| 2119 Block* catch_block = NULL; |
| 2120 Handle<String> name; |
| 2087 if (tok == Token::CATCH) { | 2121 if (tok == Token::CATCH) { |
| 2088 has_catch = true; | |
| 2089 Consume(Token::CATCH); | 2122 Consume(Token::CATCH); |
| 2090 | 2123 |
| 2091 Expect(Token::LPAREN, CHECK_OK); | 2124 Expect(Token::LPAREN, CHECK_OK); |
| 2092 Handle<String> name = ParseIdentifier(CHECK_OK); | 2125 name = ParseIdentifier(CHECK_OK); |
| 2093 | 2126 |
| 2094 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { | 2127 if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) { |
| 2095 ReportMessage("strict_catch_variable", Vector<const char*>::empty()); | 2128 ReportMessage("strict_catch_variable", Vector<const char*>::empty()); |
| 2096 *ok = false; | 2129 *ok = false; |
| 2097 return NULL; | 2130 return NULL; |
| 2098 } | 2131 } |
| 2099 | 2132 |
| 2100 Expect(Token::RPAREN, CHECK_OK); | 2133 Expect(Token::RPAREN, CHECK_OK); |
| 2101 | 2134 |
| 2102 if (peek() == Token::LBRACE) { | 2135 if (peek() == Token::LBRACE) { |
| 2103 // Allocate a temporary for holding the finally state while | 2136 // Rewrite the catch body B to a single statement block |
| 2104 // executing the finally block. | 2137 // { try B finally { PopContext }}. |
| 2105 catch_var = | 2138 Block* inner_body; |
| 2106 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol()); | 2139 // We need to collect escapes from the body for both the inner |
| 2107 Literal* name_literal = new(zone()) Literal(name); | 2140 // try/finally used to pop the catch context and any possible outer |
| 2108 VariableProxy* catch_var_use = new(zone()) VariableProxy(catch_var); | 2141 // try/finally. |
| 2109 Expression* obj = | 2142 TargetCollector inner_collector; |
| 2110 new(zone()) CatchExtensionObject(name_literal, catch_var_use); | |
| 2111 { Target target(&this->target_stack_, &catch_collector); | 2143 { Target target(&this->target_stack_, &catch_collector); |
| 2112 catch_block = WithHelper(obj, NULL, true, CHECK_OK); | 2144 { Target target(&this->target_stack_, &inner_collector); |
| 2145 catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with()); |
| 2146 if (top_scope_->is_strict_mode()) { |
| 2147 catch_scope->EnableStrictMode(); |
| 2148 } |
| 2149 catch_variable = catch_scope->DeclareLocal(name, Variable::VAR); |
| 2150 |
| 2151 Scope* saved_scope = top_scope_; |
| 2152 top_scope_ = catch_scope; |
| 2153 inner_body = ParseBlock(NULL, CHECK_OK); |
| 2154 top_scope_ = saved_scope; |
| 2155 } |
| 2113 } | 2156 } |
| 2157 |
| 2158 // Create exit block. |
| 2159 Block* inner_finally = new(zone()) Block(NULL, 1, false); |
| 2160 inner_finally->AddStatement(new(zone()) ExitContextStatement()); |
| 2161 |
| 2162 // Create a try/finally statement. |
| 2163 TryFinallyStatement* inner_try_finally = |
| 2164 new(zone()) TryFinallyStatement(inner_body, inner_finally); |
| 2165 inner_try_finally->set_escaping_targets(inner_collector.targets()); |
| 2166 |
| 2167 catch_block = new(zone()) Block(NULL, 1, false); |
| 2168 catch_block->AddStatement(inner_try_finally); |
| 2114 } else { | 2169 } else { |
| 2115 Expect(Token::LBRACE, CHECK_OK); | 2170 Expect(Token::LBRACE, CHECK_OK); |
| 2116 } | 2171 } |
| 2117 | 2172 |
| 2118 tok = peek(); | 2173 tok = peek(); |
| 2119 } | 2174 } |
| 2120 | 2175 |
| 2121 if (tok == Token::FINALLY || !has_catch) { | 2176 Block* finally_block = NULL; |
| 2177 if (tok == Token::FINALLY || catch_block == NULL) { |
| 2122 Consume(Token::FINALLY); | 2178 Consume(Token::FINALLY); |
| 2123 // Declare a variable for holding the finally state while | |
| 2124 // executing the finally block. | |
| 2125 finally_block = ParseBlock(NULL, CHECK_OK); | 2179 finally_block = ParseBlock(NULL, CHECK_OK); |
| 2126 } | 2180 } |
| 2127 | 2181 |
| 2128 // Simplify the AST nodes by converting: | 2182 // Simplify the AST nodes by converting: |
| 2129 // 'try { } catch { } finally { }' | 2183 // 'try B0 catch B1 finally B2' |
| 2130 // to: | 2184 // to: |
| 2131 // 'try { try { } catch { } } finally { }' | 2185 // 'try { try B0 catch B1 } finally B2' |
| 2132 | 2186 |
| 2133 if (catch_block != NULL && finally_block != NULL) { | 2187 if (catch_block != NULL && finally_block != NULL) { |
| 2134 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var); | 2188 // If we have both, create an inner try/catch. |
| 2189 ASSERT(catch_scope != NULL && catch_variable != NULL); |
| 2135 TryCatchStatement* statement = | 2190 TryCatchStatement* statement = |
| 2136 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block); | 2191 new(zone()) TryCatchStatement(try_block, |
| 2137 statement->set_escaping_targets(collector.targets()); | 2192 catch_scope, |
| 2193 catch_variable, |
| 2194 catch_block); |
| 2195 statement->set_escaping_targets(try_collector.targets()); |
| 2138 try_block = new(zone()) Block(NULL, 1, false); | 2196 try_block = new(zone()) Block(NULL, 1, false); |
| 2139 try_block->AddStatement(statement); | 2197 try_block->AddStatement(statement); |
| 2140 catch_block = NULL; | 2198 catch_block = NULL; // Clear to indicate it's been handled. |
| 2141 } | 2199 } |
| 2142 | 2200 |
| 2143 TryStatement* result = NULL; | 2201 TryStatement* result = NULL; |
| 2144 if (catch_block != NULL) { | 2202 if (catch_block != NULL) { |
| 2145 ASSERT(finally_block == NULL); | 2203 ASSERT(finally_block == NULL); |
| 2146 VariableProxy* catch_var_defn = new(zone()) VariableProxy(catch_var); | 2204 ASSERT(catch_scope != NULL && catch_variable != NULL); |
| 2147 result = | 2205 result = |
| 2148 new(zone()) TryCatchStatement(try_block, catch_var_defn, catch_block); | 2206 new(zone()) TryCatchStatement(try_block, |
| 2149 result->set_escaping_targets(collector.targets()); | 2207 catch_scope, |
| 2208 catch_variable, |
| 2209 catch_block); |
| 2150 } else { | 2210 } else { |
| 2151 ASSERT(finally_block != NULL); | 2211 ASSERT(finally_block != NULL); |
| 2152 result = new(zone()) TryFinallyStatement(try_block, finally_block); | 2212 result = new(zone()) TryFinallyStatement(try_block, finally_block); |
| 2153 // Add the jump targets of the try block and the catch block. | 2213 // Combine the jump targets of the try block and the possible catch block. |
| 2154 for (int i = 0; i < collector.targets()->length(); i++) { | 2214 try_collector.targets()->AddAll(*catch_collector.targets()); |
| 2155 catch_collector.AddTarget(collector.targets()->at(i)); | |
| 2156 } | |
| 2157 result->set_escaping_targets(catch_collector.targets()); | |
| 2158 } | 2215 } |
| 2159 | 2216 |
| 2217 result->set_escaping_targets(try_collector.targets()); |
| 2160 return result; | 2218 return result; |
| 2161 } | 2219 } |
| 2162 | 2220 |
| 2163 | 2221 |
| 2164 DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, | 2222 DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels, |
| 2165 bool* ok) { | 2223 bool* ok) { |
| 2166 // DoStatement :: | 2224 // DoStatement :: |
| 2167 // 'do' Statement 'while' '(' Expression ')' ';' | 2225 // 'do' Statement 'while' '(' Expression ')' ';' |
| 2168 | 2226 |
| 2169 DoWhileStatement* loop = new(zone()) DoWhileStatement(labels); | 2227 DoWhileStatement* loop = new(zone()) DoWhileStatement(labels); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 2272 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
| 2215 // ForStatement :: | 2273 // ForStatement :: |
| 2216 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 2274 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 2217 | 2275 |
| 2218 Statement* init = NULL; | 2276 Statement* init = NULL; |
| 2219 | 2277 |
| 2220 Expect(Token::FOR, CHECK_OK); | 2278 Expect(Token::FOR, CHECK_OK); |
| 2221 Expect(Token::LPAREN, CHECK_OK); | 2279 Expect(Token::LPAREN, CHECK_OK); |
| 2222 if (peek() != Token::SEMICOLON) { | 2280 if (peek() != Token::SEMICOLON) { |
| 2223 if (peek() == Token::VAR || peek() == Token::CONST) { | 2281 if (peek() == Token::VAR || peek() == Token::CONST) { |
| 2224 Expression* each = NULL; | 2282 Handle<String> name; |
| 2225 Block* variable_statement = | 2283 Block* variable_statement = |
| 2226 ParseVariableDeclarations(false, &each, CHECK_OK); | 2284 ParseVariableDeclarations(false, &name, CHECK_OK); |
| 2227 if (peek() == Token::IN && each != NULL) { | 2285 |
| 2286 if (peek() == Token::IN && !name.is_null()) { |
| 2287 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with()); |
| 2228 ForInStatement* loop = new(zone()) ForInStatement(labels); | 2288 ForInStatement* loop = new(zone()) ForInStatement(labels); |
| 2229 Target target(&this->target_stack_, loop); | 2289 Target target(&this->target_stack_, loop); |
| 2230 | 2290 |
| 2231 Expect(Token::IN, CHECK_OK); | 2291 Expect(Token::IN, CHECK_OK); |
| 2232 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2292 Expression* enumerable = ParseExpression(true, CHECK_OK); |
| 2233 Expect(Token::RPAREN, CHECK_OK); | 2293 Expect(Token::RPAREN, CHECK_OK); |
| 2234 | 2294 |
| 2235 Statement* body = ParseStatement(NULL, CHECK_OK); | 2295 Statement* body = ParseStatement(NULL, CHECK_OK); |
| 2236 loop->Initialize(each, enumerable, body); | 2296 loop->Initialize(each, enumerable, body); |
| 2237 Block* result = new(zone()) Block(NULL, 2, false); | 2297 Block* result = new(zone()) Block(NULL, 2, false); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2369 right->AsFunctionLiteral()->set_pretenure(true); | 2429 right->AsFunctionLiteral()->set_pretenure(true); |
| 2370 } | 2430 } |
| 2371 | 2431 |
| 2372 if (fni_ != NULL) { | 2432 if (fni_ != NULL) { |
| 2373 // Check if the right hand side is a call to avoid inferring a | 2433 // Check if the right hand side is a call to avoid inferring a |
| 2374 // name if we're dealing with "a = function(){...}();"-like | 2434 // name if we're dealing with "a = function(){...}();"-like |
| 2375 // expression. | 2435 // expression. |
| 2376 if ((op == Token::INIT_VAR | 2436 if ((op == Token::INIT_VAR |
| 2377 || op == Token::INIT_CONST | 2437 || op == Token::INIT_CONST |
| 2378 || op == Token::ASSIGN) | 2438 || op == Token::ASSIGN) |
| 2379 && (right->AsCall() == NULL)) { | 2439 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) { |
| 2380 fni_->Infer(); | 2440 fni_->Infer(); |
| 2381 } | 2441 } |
| 2382 fni_->Leave(); | 2442 fni_->Leave(); |
| 2383 } | 2443 } |
| 2384 | 2444 |
| 2385 return new(zone()) Assignment(op, expression, right, pos); | 2445 return new(zone()) Assignment(op, expression, right, pos); |
| 2386 } | 2446 } |
| 2387 | 2447 |
| 2388 | 2448 |
| 2389 // Precedence = 3 | 2449 // Precedence = 3 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2538 // '-' UnaryExpression | 2598 // '-' UnaryExpression |
| 2539 // '~' UnaryExpression | 2599 // '~' UnaryExpression |
| 2540 // '!' UnaryExpression | 2600 // '!' UnaryExpression |
| 2541 | 2601 |
| 2542 Token::Value op = peek(); | 2602 Token::Value op = peek(); |
| 2543 if (Token::IsUnaryOp(op)) { | 2603 if (Token::IsUnaryOp(op)) { |
| 2544 op = Next(); | 2604 op = Next(); |
| 2545 int position = scanner().location().beg_pos; | 2605 int position = scanner().location().beg_pos; |
| 2546 Expression* expression = ParseUnaryExpression(CHECK_OK); | 2606 Expression* expression = ParseUnaryExpression(CHECK_OK); |
| 2547 | 2607 |
| 2548 // Compute some expressions involving only number literals. | 2608 if (expression != NULL && (expression->AsLiteral() != NULL)) { |
| 2549 if (expression != NULL && expression->AsLiteral() && | 2609 Handle<Object> literal = expression->AsLiteral()->handle(); |
| 2550 expression->AsLiteral()->handle()->IsNumber()) { | 2610 if (op == Token::NOT) { |
| 2551 double value = expression->AsLiteral()->handle()->Number(); | 2611 // Convert the literal to a boolean condition and negate it. |
| 2552 switch (op) { | 2612 bool condition = literal->ToBoolean()->IsTrue(); |
| 2553 case Token::ADD: | 2613 Handle<Object> result(isolate()->heap()->ToBoolean(!condition)); |
| 2554 return expression; | 2614 return new(zone()) Literal(result); |
| 2555 case Token::SUB: | 2615 } else if (literal->IsNumber()) { |
| 2556 return NewNumberLiteral(-value); | 2616 // Compute some expressions involving only number literals. |
| 2557 case Token::BIT_NOT: | 2617 double value = literal->Number(); |
| 2558 return NewNumberLiteral(~DoubleToInt32(value)); | 2618 switch (op) { |
| 2559 default: break; | 2619 case Token::ADD: |
| 2620 return expression; |
| 2621 case Token::SUB: |
| 2622 return NewNumberLiteral(-value); |
| 2623 case Token::BIT_NOT: |
| 2624 return NewNumberLiteral(~DoubleToInt32(value)); |
| 2625 default: |
| 2626 break; |
| 2627 } |
| 2560 } | 2628 } |
| 2561 } | 2629 } |
| 2562 | 2630 |
| 2563 // "delete identifier" is a syntax error in strict mode. | 2631 // "delete identifier" is a syntax error in strict mode. |
| 2564 if (op == Token::DELETE && top_scope_->is_strict_mode()) { | 2632 if (op == Token::DELETE && top_scope_->is_strict_mode()) { |
| 2565 VariableProxy* operand = expression->AsVariableProxy(); | 2633 VariableProxy* operand = expression->AsVariableProxy(); |
| 2566 if (operand != NULL && !operand->is_this()) { | 2634 if (operand != NULL && !operand->is_this()) { |
| 2567 ReportMessage("strict_delete", Vector<const char*>::empty()); | 2635 ReportMessage("strict_delete", Vector<const char*>::empty()); |
| 2568 *ok = false; | 2636 *ok = false; |
| 2569 return NULL; | 2637 return NULL; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2600 return ParsePostfixExpression(ok); | 2668 return ParsePostfixExpression(ok); |
| 2601 } | 2669 } |
| 2602 } | 2670 } |
| 2603 | 2671 |
| 2604 | 2672 |
| 2605 Expression* Parser::ParsePostfixExpression(bool* ok) { | 2673 Expression* Parser::ParsePostfixExpression(bool* ok) { |
| 2606 // PostfixExpression :: | 2674 // PostfixExpression :: |
| 2607 // LeftHandSideExpression ('++' | '--')? | 2675 // LeftHandSideExpression ('++' | '--')? |
| 2608 | 2676 |
| 2609 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); | 2677 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); |
| 2610 if (!scanner().has_line_terminator_before_next() && | 2678 if (!scanner().HasAnyLineTerminatorBeforeNext() && |
| 2611 Token::IsCountOp(peek())) { | 2679 Token::IsCountOp(peek())) { |
| 2612 // Signal a reference error if the expression is an invalid | 2680 // Signal a reference error if the expression is an invalid |
| 2613 // left-hand side expression. We could report this as a syntax | 2681 // left-hand side expression. We could report this as a syntax |
| 2614 // error here but for compatibility with JSC we choose to report the | 2682 // error here but for compatibility with JSC we choose to report the |
| 2615 // error at runtime. | 2683 // error at runtime. |
| 2616 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2684 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
| 2617 Handle<String> type = | 2685 Handle<String> type = |
| 2618 isolate()->factory()->invalid_lhs_in_postfix_op_symbol(); | 2686 isolate()->factory()->invalid_lhs_in_postfix_op_symbol(); |
| 2619 expression = NewThrowReferenceError(type); | 2687 expression = NewThrowReferenceError(type); |
| 2620 } | 2688 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 // MemberExpression :: | 2819 // MemberExpression :: |
| 2752 // (PrimaryExpression | FunctionLiteral) | 2820 // (PrimaryExpression | FunctionLiteral) |
| 2753 // ('[' Expression ']' | '.' Identifier | Arguments)* | 2821 // ('[' Expression ']' | '.' Identifier | Arguments)* |
| 2754 | 2822 |
| 2755 // Parse the initial primary or function expression. | 2823 // Parse the initial primary or function expression. |
| 2756 Expression* result = NULL; | 2824 Expression* result = NULL; |
| 2757 if (peek() == Token::FUNCTION) { | 2825 if (peek() == Token::FUNCTION) { |
| 2758 Expect(Token::FUNCTION, CHECK_OK); | 2826 Expect(Token::FUNCTION, CHECK_OK); |
| 2759 int function_token_position = scanner().location().beg_pos; | 2827 int function_token_position = scanner().location().beg_pos; |
| 2760 Handle<String> name; | 2828 Handle<String> name; |
| 2761 bool is_reserved_name = false; | 2829 bool is_strict_reserved_name = false; |
| 2762 if (peek_any_identifier()) { | 2830 if (peek_any_identifier()) { |
| 2763 name = ParseIdentifierOrReservedWord(&is_reserved_name, CHECK_OK); | 2831 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, |
| 2832 CHECK_OK); |
| 2764 } | 2833 } |
| 2765 result = ParseFunctionLiteral(name, is_reserved_name, | 2834 result = ParseFunctionLiteral(name, is_strict_reserved_name, |
| 2766 function_token_position, NESTED, CHECK_OK); | 2835 function_token_position, NESTED, CHECK_OK); |
| 2767 } else { | 2836 } else { |
| 2768 result = ParsePrimaryExpression(CHECK_OK); | 2837 result = ParsePrimaryExpression(CHECK_OK); |
| 2769 } | 2838 } |
| 2770 | 2839 |
| 2771 while (true) { | 2840 while (true) { |
| 2772 switch (peek()) { | 2841 switch (peek()) { |
| 2773 case Token::LBRACK: { | 2842 case Token::LBRACK: { |
| 2774 Consume(Token::LBRACK); | 2843 Consume(Token::LBRACK); |
| 2775 int pos = scanner().location().beg_pos; | 2844 int pos = scanner().location().beg_pos; |
| 2776 Expression* index = ParseExpression(true, CHECK_OK); | 2845 Expression* index = ParseExpression(true, CHECK_OK); |
| 2777 result = new(zone()) Property(result, index, pos); | 2846 result = new(zone()) Property(result, index, pos); |
| 2847 if (fni_ != NULL) { |
| 2848 if (index->IsPropertyName()) { |
| 2849 fni_->PushLiteralName(index->AsLiteral()->AsPropertyName()); |
| 2850 } else { |
| 2851 fni_->PushLiteralName( |
| 2852 isolate()->factory()->anonymous_function_symbol()); |
| 2853 } |
| 2854 } |
| 2778 Expect(Token::RBRACK, CHECK_OK); | 2855 Expect(Token::RBRACK, CHECK_OK); |
| 2779 break; | 2856 break; |
| 2780 } | 2857 } |
| 2781 case Token::PERIOD: { | 2858 case Token::PERIOD: { |
| 2782 Consume(Token::PERIOD); | 2859 Consume(Token::PERIOD); |
| 2783 int pos = scanner().location().beg_pos; | 2860 int pos = scanner().location().beg_pos; |
| 2784 Handle<String> name = ParseIdentifierName(CHECK_OK); | 2861 Handle<String> name = ParseIdentifierName(CHECK_OK); |
| 2785 result = new(zone()) Property(result, new(zone()) Literal(name), pos); | 2862 result = new(zone()) Property(result, new(zone()) Literal(name), pos); |
| 2786 if (fni_ != NULL) fni_->PushLiteralName(name); | 2863 if (fni_ != NULL) fni_->PushLiteralName(name); |
| 2787 break; | 2864 break; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2826 case Token::NUMBER: | 2903 case Token::NUMBER: |
| 2827 return ReportMessage("unexpected_token_number", | 2904 return ReportMessage("unexpected_token_number", |
| 2828 Vector<const char*>::empty()); | 2905 Vector<const char*>::empty()); |
| 2829 case Token::STRING: | 2906 case Token::STRING: |
| 2830 return ReportMessage("unexpected_token_string", | 2907 return ReportMessage("unexpected_token_string", |
| 2831 Vector<const char*>::empty()); | 2908 Vector<const char*>::empty()); |
| 2832 case Token::IDENTIFIER: | 2909 case Token::IDENTIFIER: |
| 2833 return ReportMessage("unexpected_token_identifier", | 2910 return ReportMessage("unexpected_token_identifier", |
| 2834 Vector<const char*>::empty()); | 2911 Vector<const char*>::empty()); |
| 2835 case Token::FUTURE_RESERVED_WORD: | 2912 case Token::FUTURE_RESERVED_WORD: |
| 2913 return ReportMessage("unexpected_reserved", |
| 2914 Vector<const char*>::empty()); |
| 2915 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 2836 return ReportMessage(top_scope_->is_strict_mode() ? | 2916 return ReportMessage(top_scope_->is_strict_mode() ? |
| 2837 "unexpected_strict_reserved" : | 2917 "unexpected_strict_reserved" : |
| 2838 "unexpected_token_identifier", | 2918 "unexpected_token_identifier", |
| 2839 Vector<const char*>::empty()); | 2919 Vector<const char*>::empty()); |
| 2840 default: | 2920 default: |
| 2841 const char* name = Token::String(token); | 2921 const char* name = Token::String(token); |
| 2842 ASSERT(name != NULL); | 2922 ASSERT(name != NULL); |
| 2843 ReportMessage("unexpected_token", Vector<const char*>(&name, 1)); | 2923 ReportMessage("unexpected_token", Vector<const char*>(&name, 1)); |
| 2844 } | 2924 } |
| 2845 } | 2925 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2865 // String | 2945 // String |
| 2866 // ArrayLiteral | 2946 // ArrayLiteral |
| 2867 // ObjectLiteral | 2947 // ObjectLiteral |
| 2868 // RegExpLiteral | 2948 // RegExpLiteral |
| 2869 // '(' Expression ')' | 2949 // '(' Expression ')' |
| 2870 | 2950 |
| 2871 Expression* result = NULL; | 2951 Expression* result = NULL; |
| 2872 switch (peek()) { | 2952 switch (peek()) { |
| 2873 case Token::THIS: { | 2953 case Token::THIS: { |
| 2874 Consume(Token::THIS); | 2954 Consume(Token::THIS); |
| 2875 VariableProxy* recv = top_scope_->receiver(); | 2955 result = new(zone()) VariableProxy(top_scope_->receiver()); |
| 2876 result = recv; | |
| 2877 break; | 2956 break; |
| 2878 } | 2957 } |
| 2879 | 2958 |
| 2880 case Token::NULL_LITERAL: | 2959 case Token::NULL_LITERAL: |
| 2881 Consume(Token::NULL_LITERAL); | 2960 Consume(Token::NULL_LITERAL); |
| 2882 result = new(zone()) Literal(isolate()->factory()->null_value()); | 2961 result = new(zone()) Literal(isolate()->factory()->null_value()); |
| 2883 break; | 2962 break; |
| 2884 | 2963 |
| 2885 case Token::TRUE_LITERAL: | 2964 case Token::TRUE_LITERAL: |
| 2886 Consume(Token::TRUE_LITERAL); | 2965 Consume(Token::TRUE_LITERAL); |
| 2887 result = new(zone()) Literal(isolate()->factory()->true_value()); | 2966 result = new(zone()) Literal(isolate()->factory()->true_value()); |
| 2888 break; | 2967 break; |
| 2889 | 2968 |
| 2890 case Token::FALSE_LITERAL: | 2969 case Token::FALSE_LITERAL: |
| 2891 Consume(Token::FALSE_LITERAL); | 2970 Consume(Token::FALSE_LITERAL); |
| 2892 result = new(zone()) Literal(isolate()->factory()->false_value()); | 2971 result = new(zone()) Literal(isolate()->factory()->false_value()); |
| 2893 break; | 2972 break; |
| 2894 | 2973 |
| 2895 case Token::IDENTIFIER: | 2974 case Token::IDENTIFIER: |
| 2896 case Token::FUTURE_RESERVED_WORD: { | 2975 case Token::FUTURE_STRICT_RESERVED_WORD: { |
| 2897 Handle<String> name = ParseIdentifier(CHECK_OK); | 2976 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 2898 if (fni_ != NULL) fni_->PushVariableName(name); | 2977 if (fni_ != NULL) fni_->PushVariableName(name); |
| 2899 result = top_scope_->NewUnresolved(name, | 2978 result = top_scope_->NewUnresolved(name, |
| 2900 inside_with(), | 2979 inside_with(), |
| 2901 scanner().location().beg_pos); | 2980 scanner().location().beg_pos); |
| 2902 break; | 2981 break; |
| 2903 } | 2982 } |
| 2904 | 2983 |
| 2905 case Token::NUMBER: { | 2984 case Token::NUMBER: { |
| 2906 Consume(Token::NUMBER); | 2985 Consume(Token::NUMBER); |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3297 | 3376 |
| 3298 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, | 3377 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, |
| 3299 bool* ok) { | 3378 bool* ok) { |
| 3300 // Special handling of getter and setter syntax: | 3379 // Special handling of getter and setter syntax: |
| 3301 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | 3380 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
| 3302 // We have already read the "get" or "set" keyword. | 3381 // We have already read the "get" or "set" keyword. |
| 3303 Token::Value next = Next(); | 3382 Token::Value next = Next(); |
| 3304 bool is_keyword = Token::IsKeyword(next); | 3383 bool is_keyword = Token::IsKeyword(next); |
| 3305 if (next == Token::IDENTIFIER || next == Token::NUMBER || | 3384 if (next == Token::IDENTIFIER || next == Token::NUMBER || |
| 3306 next == Token::FUTURE_RESERVED_WORD || | 3385 next == Token::FUTURE_RESERVED_WORD || |
| 3386 next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 3307 next == Token::STRING || is_keyword) { | 3387 next == Token::STRING || is_keyword) { |
| 3308 Handle<String> name; | 3388 Handle<String> name; |
| 3309 if (is_keyword) { | 3389 if (is_keyword) { |
| 3310 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next)); | 3390 name = isolate_->factory()->LookupAsciiSymbol(Token::String(next)); |
| 3311 } else { | 3391 } else { |
| 3312 name = GetSymbol(CHECK_OK); | 3392 name = GetSymbol(CHECK_OK); |
| 3313 } | 3393 } |
| 3314 FunctionLiteral* value = | 3394 FunctionLiteral* value = |
| 3315 ParseFunctionLiteral(name, | 3395 ParseFunctionLiteral(name, |
| 3316 false, // reserved words are allowed here | 3396 false, // reserved words are allowed here |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3351 if (fni_ != NULL) fni_->Enter(); | 3431 if (fni_ != NULL) fni_->Enter(); |
| 3352 | 3432 |
| 3353 Literal* key = NULL; | 3433 Literal* key = NULL; |
| 3354 Token::Value next = peek(); | 3434 Token::Value next = peek(); |
| 3355 | 3435 |
| 3356 // Location of the property name token | 3436 // Location of the property name token |
| 3357 Scanner::Location loc = scanner().peek_location(); | 3437 Scanner::Location loc = scanner().peek_location(); |
| 3358 | 3438 |
| 3359 switch (next) { | 3439 switch (next) { |
| 3360 case Token::FUTURE_RESERVED_WORD: | 3440 case Token::FUTURE_RESERVED_WORD: |
| 3441 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 3361 case Token::IDENTIFIER: { | 3442 case Token::IDENTIFIER: { |
| 3362 bool is_getter = false; | 3443 bool is_getter = false; |
| 3363 bool is_setter = false; | 3444 bool is_setter = false; |
| 3364 Handle<String> id = | 3445 Handle<String> id = |
| 3365 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3446 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 3366 if (fni_ != NULL) fni_->PushLiteralName(id); | 3447 if (fni_ != NULL) fni_->PushLiteralName(id); |
| 3367 | 3448 |
| 3368 if ((is_getter || is_setter) && peek() != Token::COLON) { | 3449 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 3369 // Update loc to point to the identifier | 3450 // Update loc to point to the identifier |
| 3370 loc = scanner().peek_location(); | 3451 loc = scanner().peek_location(); |
| 3371 ObjectLiteral::Property* property = | 3452 ObjectLiteral::Property* property = |
| 3372 ParseObjectLiteralGetSet(is_getter, CHECK_OK); | 3453 ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
| 3373 if (IsBoilerplateProperty(property)) { | 3454 if (IsBoilerplateProperty(property)) { |
| 3374 number_of_boilerplate_properties++; | 3455 number_of_boilerplate_properties++; |
| 3375 } | 3456 } |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3499 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { | 3580 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { |
| 3500 // Arguments :: | 3581 // Arguments :: |
| 3501 // '(' (AssignmentExpression)*[','] ')' | 3582 // '(' (AssignmentExpression)*[','] ')' |
| 3502 | 3583 |
| 3503 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4); | 3584 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4); |
| 3504 Expect(Token::LPAREN, CHECK_OK); | 3585 Expect(Token::LPAREN, CHECK_OK); |
| 3505 bool done = (peek() == Token::RPAREN); | 3586 bool done = (peek() == Token::RPAREN); |
| 3506 while (!done) { | 3587 while (!done) { |
| 3507 Expression* argument = ParseAssignmentExpression(true, CHECK_OK); | 3588 Expression* argument = ParseAssignmentExpression(true, CHECK_OK); |
| 3508 result->Add(argument); | 3589 result->Add(argument); |
| 3590 if (result->length() > kMaxNumFunctionParameters) { |
| 3591 ReportMessageAt(scanner().location(), "too_many_arguments", |
| 3592 Vector<const char*>::empty()); |
| 3593 *ok = false; |
| 3594 return NULL; |
| 3595 } |
| 3509 done = (peek() == Token::RPAREN); | 3596 done = (peek() == Token::RPAREN); |
| 3510 if (!done) Expect(Token::COMMA, CHECK_OK); | 3597 if (!done) Expect(Token::COMMA, CHECK_OK); |
| 3511 } | 3598 } |
| 3512 Expect(Token::RPAREN, CHECK_OK); | 3599 Expect(Token::RPAREN, CHECK_OK); |
| 3513 return result; | 3600 return result; |
| 3514 } | 3601 } |
| 3515 | 3602 |
| 3516 | 3603 |
| 3517 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, | 3604 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, |
| 3518 bool name_is_reserved, | 3605 bool name_is_strict_reserved, |
| 3519 int function_token_position, | 3606 int function_token_position, |
| 3520 FunctionLiteralType type, | 3607 FunctionLiteralType type, |
| 3521 bool* ok) { | 3608 bool* ok) { |
| 3522 // Function :: | 3609 // Function :: |
| 3523 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 3610 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 3524 bool is_named = !var_name.is_null(); | 3611 bool is_named = !var_name.is_null(); |
| 3525 | 3612 |
| 3526 // The name associated with this function. If it's a function expression, | 3613 // The name associated with this function. If it's a function expression, |
| 3527 // this is the actual function name, otherwise this is the name of the | 3614 // this is the actual function name, otherwise this is the name of the |
| 3528 // variable declared and initialized with the function (expression). In | 3615 // variable declared and initialized with the function (expression). In |
| 3529 // that case, we don't have a function name (it's empty). | 3616 // that case, we don't have a function name (it's empty). |
| 3530 Handle<String> name = | 3617 Handle<String> name = |
| 3531 is_named ? var_name : isolate()->factory()->empty_symbol(); | 3618 is_named ? var_name : isolate()->factory()->empty_symbol(); |
| 3532 // The function name, if any. | 3619 // The function name, if any. |
| 3533 Handle<String> function_name = isolate()->factory()->empty_symbol(); | 3620 Handle<String> function_name = isolate()->factory()->empty_symbol(); |
| 3534 if (is_named && (type == EXPRESSION || type == NESTED)) { | 3621 if (is_named && (type == EXPRESSION || type == NESTED)) { |
| 3535 function_name = name; | 3622 function_name = name; |
| 3536 } | 3623 } |
| 3537 | 3624 |
| 3538 int num_parameters = 0; | 3625 int num_parameters = 0; |
| 3539 Scope* scope = NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); | 3626 Scope* scope = NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); |
| 3540 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); | 3627 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); |
| 3541 int materialized_literal_count; | 3628 int materialized_literal_count; |
| 3542 int expected_property_count; | 3629 int expected_property_count; |
| 3543 int start_pos; | 3630 int start_pos; |
| 3544 int end_pos; | 3631 int end_pos; |
| 3545 bool only_simple_this_property_assignments; | 3632 bool only_simple_this_property_assignments; |
| 3546 Handle<FixedArray> this_property_assignments; | 3633 Handle<FixedArray> this_property_assignments; |
| 3634 bool has_duplicate_parameters = false; |
| 3547 // Parse function body. | 3635 // Parse function body. |
| 3548 { LexicalScope lexical_scope(this, scope, isolate()); | 3636 { LexicalScope lexical_scope(this, scope, isolate()); |
| 3549 top_scope_->SetScopeName(name); | 3637 top_scope_->SetScopeName(name); |
| 3550 | 3638 |
| 3551 // FormalParameterList :: | 3639 // FormalParameterList :: |
| 3552 // '(' (Identifier)*[','] ')' | 3640 // '(' (Identifier)*[','] ')' |
| 3553 Expect(Token::LPAREN, CHECK_OK); | 3641 Expect(Token::LPAREN, CHECK_OK); |
| 3554 start_pos = scanner().location().beg_pos; | 3642 start_pos = scanner().location().beg_pos; |
| 3555 Scanner::Location name_loc = Scanner::Location::invalid(); | 3643 Scanner::Location name_loc = Scanner::Location::invalid(); |
| 3556 Scanner::Location dupe_loc = Scanner::Location::invalid(); | 3644 Scanner::Location dupe_loc = Scanner::Location::invalid(); |
| 3557 Scanner::Location reserved_loc = Scanner::Location::invalid(); | 3645 Scanner::Location reserved_loc = Scanner::Location::invalid(); |
| 3558 | 3646 |
| 3559 bool done = (peek() == Token::RPAREN); | 3647 bool done = (peek() == Token::RPAREN); |
| 3560 while (!done) { | 3648 while (!done) { |
| 3561 bool is_reserved = false; | 3649 bool is_strict_reserved = false; |
| 3562 Handle<String> param_name = | 3650 Handle<String> param_name = |
| 3563 ParseIdentifierOrReservedWord(&is_reserved, CHECK_OK); | 3651 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, |
| 3652 CHECK_OK); |
| 3564 | 3653 |
| 3565 // Store locations for possible future error reports. | 3654 // Store locations for possible future error reports. |
| 3566 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) { | 3655 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) { |
| 3567 name_loc = scanner().location(); | 3656 name_loc = scanner().location(); |
| 3568 } | 3657 } |
| 3569 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) { | 3658 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) { |
| 3659 has_duplicate_parameters = true; |
| 3570 dupe_loc = scanner().location(); | 3660 dupe_loc = scanner().location(); |
| 3571 } | 3661 } |
| 3572 if (!reserved_loc.IsValid() && is_reserved) { | 3662 if (!reserved_loc.IsValid() && is_strict_reserved) { |
| 3573 reserved_loc = scanner().location(); | 3663 reserved_loc = scanner().location(); |
| 3574 } | 3664 } |
| 3575 | 3665 |
| 3576 Variable* parameter = top_scope_->DeclareLocal(param_name, | 3666 top_scope_->DeclareParameter(param_name); |
| 3577 Variable::VAR, | |
| 3578 Scope::PARAMETER); | |
| 3579 top_scope_->AddParameter(parameter); | |
| 3580 num_parameters++; | 3667 num_parameters++; |
| 3581 if (num_parameters > kMaxNumFunctionParameters) { | 3668 if (num_parameters > kMaxNumFunctionParameters) { |
| 3582 ReportMessageAt(scanner().location(), "too_many_parameters", | 3669 ReportMessageAt(scanner().location(), "too_many_parameters", |
| 3583 Vector<const char*>::empty()); | 3670 Vector<const char*>::empty()); |
| 3584 *ok = false; | 3671 *ok = false; |
| 3585 return NULL; | 3672 return NULL; |
| 3586 } | 3673 } |
| 3587 done = (peek() == Token::RPAREN); | 3674 done = (peek() == Token::RPAREN); |
| 3588 if (!done) Expect(Token::COMMA, CHECK_OK); | 3675 if (!done) Expect(Token::COMMA, CHECK_OK); |
| 3589 } | 3676 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3626 if (end_pos <= function_block_pos) { | 3713 if (end_pos <= function_block_pos) { |
| 3627 // End position greater than end of stream is safe, and hard to check. | 3714 // End position greater than end of stream is safe, and hard to check. |
| 3628 ReportInvalidPreparseData(name, CHECK_OK); | 3715 ReportInvalidPreparseData(name, CHECK_OK); |
| 3629 } | 3716 } |
| 3630 isolate()->counters()->total_preparse_skipped()->Increment( | 3717 isolate()->counters()->total_preparse_skipped()->Increment( |
| 3631 end_pos - function_block_pos); | 3718 end_pos - function_block_pos); |
| 3632 // Seek to position just before terminal '}'. | 3719 // Seek to position just before terminal '}'. |
| 3633 scanner().SeekForward(end_pos - 1); | 3720 scanner().SeekForward(end_pos - 1); |
| 3634 materialized_literal_count = entry.literal_count(); | 3721 materialized_literal_count = entry.literal_count(); |
| 3635 expected_property_count = entry.property_count(); | 3722 expected_property_count = entry.property_count(); |
| 3723 if (entry.strict_mode()) top_scope_->EnableStrictMode(); |
| 3636 only_simple_this_property_assignments = false; | 3724 only_simple_this_property_assignments = false; |
| 3637 this_property_assignments = isolate()->factory()->empty_fixed_array(); | 3725 this_property_assignments = isolate()->factory()->empty_fixed_array(); |
| 3638 Expect(Token::RBRACE, CHECK_OK); | 3726 Expect(Token::RBRACE, CHECK_OK); |
| 3639 } else { | 3727 } else { |
| 3640 ParseSourceElements(body, Token::RBRACE, CHECK_OK); | 3728 ParseSourceElements(body, Token::RBRACE, CHECK_OK); |
| 3641 | 3729 |
| 3642 materialized_literal_count = lexical_scope.materialized_literal_count(); | 3730 materialized_literal_count = lexical_scope.materialized_literal_count(); |
| 3643 expected_property_count = lexical_scope.expected_property_count(); | 3731 expected_property_count = lexical_scope.expected_property_count(); |
| 3644 only_simple_this_property_assignments = | 3732 only_simple_this_property_assignments = |
| 3645 lexical_scope.only_simple_this_property_assignments(); | 3733 lexical_scope.only_simple_this_property_assignments(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3666 Vector<const char*>::empty()); | 3754 Vector<const char*>::empty()); |
| 3667 *ok = false; | 3755 *ok = false; |
| 3668 return NULL; | 3756 return NULL; |
| 3669 } | 3757 } |
| 3670 if (dupe_loc.IsValid()) { | 3758 if (dupe_loc.IsValid()) { |
| 3671 ReportMessageAt(dupe_loc, "strict_param_dupe", | 3759 ReportMessageAt(dupe_loc, "strict_param_dupe", |
| 3672 Vector<const char*>::empty()); | 3760 Vector<const char*>::empty()); |
| 3673 *ok = false; | 3761 *ok = false; |
| 3674 return NULL; | 3762 return NULL; |
| 3675 } | 3763 } |
| 3676 if (name_is_reserved) { | 3764 if (name_is_strict_reserved) { |
| 3677 int position = function_token_position != RelocInfo::kNoPosition | 3765 int position = function_token_position != RelocInfo::kNoPosition |
| 3678 ? function_token_position | 3766 ? function_token_position |
| 3679 : (start_pos > 0 ? start_pos - 1 : start_pos); | 3767 : (start_pos > 0 ? start_pos - 1 : start_pos); |
| 3680 Scanner::Location location = Scanner::Location(position, start_pos); | 3768 Scanner::Location location = Scanner::Location(position, start_pos); |
| 3681 ReportMessageAt(location, "strict_reserved_word", | 3769 ReportMessageAt(location, "strict_reserved_word", |
| 3682 Vector<const char*>::empty()); | 3770 Vector<const char*>::empty()); |
| 3683 *ok = false; | 3771 *ok = false; |
| 3684 return NULL; | 3772 return NULL; |
| 3685 } | 3773 } |
| 3686 if (reserved_loc.IsValid()) { | 3774 if (reserved_loc.IsValid()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3697 new(zone()) FunctionLiteral(name, | 3785 new(zone()) FunctionLiteral(name, |
| 3698 scope, | 3786 scope, |
| 3699 body, | 3787 body, |
| 3700 materialized_literal_count, | 3788 materialized_literal_count, |
| 3701 expected_property_count, | 3789 expected_property_count, |
| 3702 only_simple_this_property_assignments, | 3790 only_simple_this_property_assignments, |
| 3703 this_property_assignments, | 3791 this_property_assignments, |
| 3704 num_parameters, | 3792 num_parameters, |
| 3705 start_pos, | 3793 start_pos, |
| 3706 end_pos, | 3794 end_pos, |
| 3707 (function_name->length() > 0)); | 3795 (function_name->length() > 0), |
| 3796 has_duplicate_parameters); |
| 3708 function_literal->set_function_token_position(function_token_position); | 3797 function_literal->set_function_token_position(function_token_position); |
| 3709 | 3798 |
| 3710 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); | 3799 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); |
| 3711 return function_literal; | 3800 return function_literal; |
| 3712 } | 3801 } |
| 3713 | 3802 |
| 3714 | 3803 |
| 3715 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 3804 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| 3716 // CallRuntime :: | 3805 // CallRuntime :: |
| 3717 // '%' Identifier Arguments | 3806 // '%' Identifier Arguments |
| 3718 | 3807 |
| 3719 Expect(Token::MOD, CHECK_OK); | 3808 Expect(Token::MOD, CHECK_OK); |
| 3720 Handle<String> name = ParseIdentifier(CHECK_OK); | 3809 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 3721 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); | 3810 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
| 3722 | 3811 |
| 3723 if (extension_ != NULL) { | 3812 if (extension_ != NULL) { |
| 3724 // The extension structures are only accessible while parsing the | 3813 // The extension structures are only accessible while parsing the |
| 3725 // very first time not when reparsing because of lazy compilation. | 3814 // very first time not when reparsing because of lazy compilation. |
| 3726 top_scope_->ForceEagerCompilation(); | 3815 top_scope_->DeclarationScope()->ForceEagerCompilation(); |
| 3727 } | 3816 } |
| 3728 | 3817 |
| 3729 const Runtime::Function* function = Runtime::FunctionForSymbol(name); | 3818 const Runtime::Function* function = Runtime::FunctionForSymbol(name); |
| 3730 | 3819 |
| 3731 // Check for built-in IS_VAR macro. | 3820 // Check for built-in IS_VAR macro. |
| 3732 if (function != NULL && | 3821 if (function != NULL && |
| 3733 function->intrinsic_type == Runtime::RUNTIME && | 3822 function->intrinsic_type == Runtime::RUNTIME && |
| 3734 function->function_id == Runtime::kIS_VAR) { | 3823 function->function_id == Runtime::kIS_VAR) { |
| 3735 // %IS_VAR(x) evaluates to x if x is a variable, | 3824 // %IS_VAR(x) evaluates to x if x is a variable, |
| 3736 // leads to a parse error otherwise. Could be implemented as an | 3825 // leads to a parse error otherwise. Could be implemented as an |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3754 } | 3843 } |
| 3755 | 3844 |
| 3756 // We have a valid intrinsics call or a call to a builtin. | 3845 // We have a valid intrinsics call or a call to a builtin. |
| 3757 return new(zone()) CallRuntime(name, function, args); | 3846 return new(zone()) CallRuntime(name, function, args); |
| 3758 } | 3847 } |
| 3759 | 3848 |
| 3760 | 3849 |
| 3761 bool Parser::peek_any_identifier() { | 3850 bool Parser::peek_any_identifier() { |
| 3762 Token::Value next = peek(); | 3851 Token::Value next = peek(); |
| 3763 return next == Token::IDENTIFIER || | 3852 return next == Token::IDENTIFIER || |
| 3764 next == Token::FUTURE_RESERVED_WORD; | 3853 next == Token::FUTURE_RESERVED_WORD || |
| 3854 next == Token::FUTURE_STRICT_RESERVED_WORD; |
| 3765 } | 3855 } |
| 3766 | 3856 |
| 3767 | 3857 |
| 3768 void Parser::Consume(Token::Value token) { | 3858 void Parser::Consume(Token::Value token) { |
| 3769 Token::Value next = Next(); | 3859 Token::Value next = Next(); |
| 3770 USE(next); | 3860 USE(next); |
| 3771 USE(token); | 3861 USE(token); |
| 3772 ASSERT(next == token); | 3862 ASSERT(next == token); |
| 3773 } | 3863 } |
| 3774 | 3864 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3792 | 3882 |
| 3793 | 3883 |
| 3794 void Parser::ExpectSemicolon(bool* ok) { | 3884 void Parser::ExpectSemicolon(bool* ok) { |
| 3795 // Check for automatic semicolon insertion according to | 3885 // Check for automatic semicolon insertion according to |
| 3796 // the rules given in ECMA-262, section 7.9, page 21. | 3886 // the rules given in ECMA-262, section 7.9, page 21. |
| 3797 Token::Value tok = peek(); | 3887 Token::Value tok = peek(); |
| 3798 if (tok == Token::SEMICOLON) { | 3888 if (tok == Token::SEMICOLON) { |
| 3799 Next(); | 3889 Next(); |
| 3800 return; | 3890 return; |
| 3801 } | 3891 } |
| 3802 if (scanner().has_line_terminator_before_next() || | 3892 if (scanner().HasAnyLineTerminatorBeforeNext() || |
| 3803 tok == Token::RBRACE || | 3893 tok == Token::RBRACE || |
| 3804 tok == Token::EOS) { | 3894 tok == Token::EOS) { |
| 3805 return; | 3895 return; |
| 3806 } | 3896 } |
| 3807 Expect(Token::SEMICOLON, ok); | 3897 Expect(Token::SEMICOLON, ok); |
| 3808 } | 3898 } |
| 3809 | 3899 |
| 3810 | 3900 |
| 3811 Literal* Parser::GetLiteralUndefined() { | 3901 Literal* Parser::GetLiteralUndefined() { |
| 3812 return new(zone()) Literal(isolate()->factory()->undefined_value()); | 3902 return new(zone()) Literal(isolate()->factory()->undefined_value()); |
| 3813 } | 3903 } |
| 3814 | 3904 |
| 3815 | 3905 |
| 3816 Literal* Parser::GetLiteralTheHole() { | 3906 Literal* Parser::GetLiteralTheHole() { |
| 3817 return new(zone()) Literal(isolate()->factory()->the_hole_value()); | 3907 return new(zone()) Literal(isolate()->factory()->the_hole_value()); |
| 3818 } | 3908 } |
| 3819 | 3909 |
| 3820 | 3910 |
| 3821 Literal* Parser::GetLiteralNumber(double value) { | 3911 Literal* Parser::GetLiteralNumber(double value) { |
| 3822 return NewNumberLiteral(value); | 3912 return NewNumberLiteral(value); |
| 3823 } | 3913 } |
| 3824 | 3914 |
| 3825 | 3915 |
| 3916 // Parses and identifier that is valid for the current scope, in particular it |
| 3917 // fails on strict mode future reserved keywords in a strict scope. |
| 3826 Handle<String> Parser::ParseIdentifier(bool* ok) { | 3918 Handle<String> Parser::ParseIdentifier(bool* ok) { |
| 3827 bool is_reserved; | 3919 if (top_scope_->is_strict_mode()) { |
| 3828 return ParseIdentifierOrReservedWord(&is_reserved, ok); | 3920 Expect(Token::IDENTIFIER, ok); |
| 3921 } else if (!Check(Token::IDENTIFIER)) { |
| 3922 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); |
| 3923 } |
| 3924 if (!*ok) return Handle<String>(); |
| 3925 return GetSymbol(ok); |
| 3829 } | 3926 } |
| 3830 | 3927 |
| 3831 | 3928 |
| 3832 Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved, | 3929 // Parses and identifier or a strict mode future reserved word, and indicate |
| 3833 bool* ok) { | 3930 // whether it is strict mode future reserved. |
| 3834 *is_reserved = false; | 3931 Handle<String> Parser::ParseIdentifierOrStrictReservedWord( |
| 3835 if (top_scope_->is_strict_mode()) { | 3932 bool* is_strict_reserved, bool* ok) { |
| 3836 Expect(Token::IDENTIFIER, ok); | 3933 *is_strict_reserved = false; |
| 3837 } else { | 3934 if (!Check(Token::IDENTIFIER)) { |
| 3838 if (!Check(Token::IDENTIFIER)) { | 3935 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); |
| 3839 Expect(Token::FUTURE_RESERVED_WORD, ok); | 3936 *is_strict_reserved = true; |
| 3840 *is_reserved = true; | |
| 3841 } | |
| 3842 } | 3937 } |
| 3843 if (!*ok) return Handle<String>(); | 3938 if (!*ok) return Handle<String>(); |
| 3844 return GetSymbol(ok); | 3939 return GetSymbol(ok); |
| 3845 } | 3940 } |
| 3846 | 3941 |
| 3847 | 3942 |
| 3848 Handle<String> Parser::ParseIdentifierName(bool* ok) { | 3943 Handle<String> Parser::ParseIdentifierName(bool* ok) { |
| 3849 Token::Value next = Next(); | 3944 Token::Value next = Next(); |
| 3850 if (next != Token::IDENTIFIER && | 3945 if (next != Token::IDENTIFIER && |
| 3851 next != Token::FUTURE_RESERVED_WORD && | 3946 next != Token::FUTURE_RESERVED_WORD && |
| 3852 !Token::IsKeyword(next)) { | 3947 next != Token::FUTURE_STRICT_RESERVED_WORD && |
| 3948 !Token::IsKeyword(next)) { |
| 3853 ReportUnexpectedToken(next); | 3949 ReportUnexpectedToken(next); |
| 3854 *ok = false; | 3950 *ok = false; |
| 3855 return Handle<String>(); | 3951 return Handle<String>(); |
| 3856 } | 3952 } |
| 3857 return GetSymbol(ok); | 3953 return GetSymbol(ok); |
| 3858 } | 3954 } |
| 3859 | 3955 |
| 3860 | 3956 |
| 3861 // Checks LHS expression for assignment and prefix/postfix increment/decrement | 3957 // Checks LHS expression for assignment and prefix/postfix increment/decrement |
| 3862 // in strict mode. | 3958 // in strict mode. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3883 beg_pos <= octal.beg_pos && | 3979 beg_pos <= octal.beg_pos && |
| 3884 octal.end_pos <= end_pos) { | 3980 octal.end_pos <= end_pos) { |
| 3885 ReportMessageAt(octal, "strict_octal_literal", | 3981 ReportMessageAt(octal, "strict_octal_literal", |
| 3886 Vector<const char*>::empty()); | 3982 Vector<const char*>::empty()); |
| 3887 scanner().clear_octal_position(); | 3983 scanner().clear_octal_position(); |
| 3888 *ok = false; | 3984 *ok = false; |
| 3889 } | 3985 } |
| 3890 } | 3986 } |
| 3891 | 3987 |
| 3892 | 3988 |
| 3893 // This function reads an identifier and determines whether or not it | 3989 // This function reads an identifier name and determines whether or not it |
| 3894 // is 'get' or 'set'. | 3990 // is 'get' or 'set'. |
| 3895 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, | 3991 Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get, |
| 3896 bool* is_set, | 3992 bool* is_set, |
| 3897 bool* ok) { | 3993 bool* ok) { |
| 3898 Handle<String> result = ParseIdentifier(ok); | 3994 Handle<String> result = ParseIdentifierName(ok); |
| 3899 if (!*ok) return Handle<String>(); | 3995 if (!*ok) return Handle<String>(); |
| 3900 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { | 3996 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { |
| 3901 const char* token = scanner().literal_ascii_string().start(); | 3997 const char* token = scanner().literal_ascii_string().start(); |
| 3902 *is_get = strncmp(token, "get", 3) == 0; | 3998 *is_get = strncmp(token, "get", 3) == 0; |
| 3903 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 3999 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 3904 } | 4000 } |
| 3905 return result; | 4001 return result; |
| 3906 } | 4002 } |
| 3907 | 4003 |
| 3908 | 4004 |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4888 *source = data; | 4984 *source = data; |
| 4889 return result; | 4985 return result; |
| 4890 } | 4986 } |
| 4891 | 4987 |
| 4892 | 4988 |
| 4893 // Create a Scanner for the preparser to use as input, and preparse the source. | 4989 // Create a Scanner for the preparser to use as input, and preparse the source. |
| 4894 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, | 4990 static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, |
| 4895 bool allow_lazy, | 4991 bool allow_lazy, |
| 4896 ParserRecorder* recorder) { | 4992 ParserRecorder* recorder) { |
| 4897 Isolate* isolate = Isolate::Current(); | 4993 Isolate* isolate = Isolate::Current(); |
| 4898 V8JavaScriptScanner scanner(isolate->unicode_cache()); | 4994 JavaScriptScanner scanner(isolate->unicode_cache()); |
| 4899 scanner.Initialize(source); | 4995 scanner.Initialize(source); |
| 4900 intptr_t stack_limit = isolate->stack_guard()->real_climit(); | 4996 intptr_t stack_limit = isolate->stack_guard()->real_climit(); |
| 4901 if (!preparser::PreParser::PreParseProgram(&scanner, | 4997 if (!preparser::PreParser::PreParseProgram(&scanner, |
| 4902 recorder, | 4998 recorder, |
| 4903 allow_lazy, | 4999 allow_lazy, |
| 4904 stack_limit)) { | 5000 stack_limit)) { |
| 4905 isolate->StackOverflow(); | 5001 isolate->StackOverflow(); |
| 4906 return NULL; | 5002 return NULL; |
| 4907 } | 5003 } |
| 4908 | 5004 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4960 | 5056 |
| 4961 | 5057 |
| 4962 bool ParserApi::Parse(CompilationInfo* info) { | 5058 bool ParserApi::Parse(CompilationInfo* info) { |
| 4963 ASSERT(info->function() == NULL); | 5059 ASSERT(info->function() == NULL); |
| 4964 FunctionLiteral* result = NULL; | 5060 FunctionLiteral* result = NULL; |
| 4965 Handle<Script> script = info->script(); | 5061 Handle<Script> script = info->script(); |
| 4966 if (info->is_lazy()) { | 5062 if (info->is_lazy()) { |
| 4967 Parser parser(script, true, NULL, NULL); | 5063 Parser parser(script, true, NULL, NULL); |
| 4968 result = parser.ParseLazy(info); | 5064 result = parser.ParseLazy(info); |
| 4969 } else { | 5065 } else { |
| 5066 // Whether we allow %identifier(..) syntax. |
| 4970 bool allow_natives_syntax = | 5067 bool allow_natives_syntax = |
| 4971 info->allows_natives_syntax() || FLAG_allow_natives_syntax; | 5068 info->allows_natives_syntax() || FLAG_allow_natives_syntax; |
| 4972 ScriptDataImpl* pre_data = info->pre_parse_data(); | 5069 ScriptDataImpl* pre_data = info->pre_parse_data(); |
| 4973 Parser parser(script, allow_natives_syntax, info->extension(), pre_data); | 5070 Parser parser(script, allow_natives_syntax, info->extension(), pre_data); |
| 4974 if (pre_data != NULL && pre_data->has_error()) { | 5071 if (pre_data != NULL && pre_data->has_error()) { |
| 4975 Scanner::Location loc = pre_data->MessageLocation(); | 5072 Scanner::Location loc = pre_data->MessageLocation(); |
| 4976 const char* message = pre_data->BuildMessage(); | 5073 const char* message = pre_data->BuildMessage(); |
| 4977 Vector<const char*> args = pre_data->BuildArgs(); | 5074 Vector<const char*> args = pre_data->BuildArgs(); |
| 4978 parser.ReportMessageAt(loc, message, args); | 5075 parser.ReportMessageAt(loc, message, args); |
| 4979 DeleteArray(message); | 5076 DeleteArray(message); |
| 4980 for (int i = 0; i < args.length(); i++) { | 5077 for (int i = 0; i < args.length(); i++) { |
| 4981 DeleteArray(args[i]); | 5078 DeleteArray(args[i]); |
| 4982 } | 5079 } |
| 4983 DeleteArray(args.start()); | 5080 DeleteArray(args.start()); |
| 4984 ASSERT(info->isolate()->has_pending_exception()); | 5081 ASSERT(info->isolate()->has_pending_exception()); |
| 4985 } else { | 5082 } else { |
| 4986 Handle<String> source = Handle<String>(String::cast(script->source())); | 5083 Handle<String> source = Handle<String>(String::cast(script->source())); |
| 4987 result = parser.ParseProgram(source, | 5084 result = parser.ParseProgram(source, |
| 4988 info->is_global(), | 5085 info->is_global(), |
| 4989 info->StrictMode()); | 5086 info->StrictMode()); |
| 4990 } | 5087 } |
| 4991 } | 5088 } |
| 4992 | 5089 |
| 4993 info->SetFunction(result); | 5090 info->SetFunction(result); |
| 4994 return (result != NULL); | 5091 return (result != NULL); |
| 4995 } | 5092 } |
| 4996 | 5093 |
| 4997 } } // namespace v8::internal | 5094 } } // namespace v8::internal |
| OLD | NEW |