| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 Handle<FixedArray> this_property_assignments() { | 276 Handle<FixedArray> this_property_assignments() { |
| 277 return this_property_assignments_; | 277 return this_property_assignments_; |
| 278 } | 278 } |
| 279 | 279 |
| 280 void AddProperty() { expected_property_count_++; } | 280 void AddProperty() { expected_property_count_++; } |
| 281 int expected_property_count() { return expected_property_count_; } | 281 int expected_property_count() { return expected_property_count_; } |
| 282 | 282 |
| 283 void AddLoop() { loop_count_++; } | 283 void AddLoop() { loop_count_++; } |
| 284 bool ContainsLoops() const { return loop_count_ > 0; } | 284 bool ContainsLoops() const { return loop_count_ > 0; } |
| 285 | 285 |
| 286 bool StrictMode() { return strict_mode_; } |
| 287 void EnableStrictMode() { |
| 288 strict_mode_ = FLAG_strict_mode; |
| 289 } |
| 290 |
| 286 private: | 291 private: |
| 287 // Captures the number of literals that need materialization in the | 292 // Captures the number of literals that need materialization in the |
| 288 // function. Includes regexp literals, and boilerplate for object | 293 // function. Includes regexp literals, and boilerplate for object |
| 289 // and array literals. | 294 // and array literals. |
| 290 int materialized_literal_count_; | 295 int materialized_literal_count_; |
| 291 | 296 |
| 292 // Properties count estimation. | 297 // Properties count estimation. |
| 293 int expected_property_count_; | 298 int expected_property_count_; |
| 294 | 299 |
| 295 // Keeps track of assignments to properties of this. Used for | 300 // Keeps track of assignments to properties of this. Used for |
| 296 // optimizing constructors. | 301 // optimizing constructors. |
| 297 bool only_simple_this_property_assignments_; | 302 bool only_simple_this_property_assignments_; |
| 298 Handle<FixedArray> this_property_assignments_; | 303 Handle<FixedArray> this_property_assignments_; |
| 299 | 304 |
| 300 // Captures the number of loops inside the scope. | 305 // Captures the number of loops inside the scope. |
| 301 int loop_count_; | 306 int loop_count_; |
| 302 | 307 |
| 308 // Parsing strict mode code. |
| 309 bool strict_mode_; |
| 310 |
| 303 // Bookkeeping | 311 // Bookkeeping |
| 304 TemporaryScope** variable_; | 312 TemporaryScope** variable_; |
| 305 TemporaryScope* parent_; | 313 TemporaryScope* parent_; |
| 306 }; | 314 }; |
| 307 | 315 |
| 308 | 316 |
| 309 TemporaryScope::TemporaryScope(TemporaryScope** variable) | 317 TemporaryScope::TemporaryScope(TemporaryScope** variable) |
| 310 : materialized_literal_count_(0), | 318 : materialized_literal_count_(0), |
| 311 expected_property_count_(0), | 319 expected_property_count_(0), |
| 312 only_simple_this_property_assignments_(false), | 320 only_simple_this_property_assignments_(false), |
| 313 this_property_assignments_( | 321 this_property_assignments_( |
| 314 Isolate::Current()->factory()->empty_fixed_array()), | 322 Isolate::Current()->factory()->empty_fixed_array()), |
| 315 loop_count_(0), | 323 loop_count_(0), |
| 316 variable_(variable), | 324 variable_(variable), |
| 317 parent_(*variable) { | 325 parent_(*variable) { |
| 326 // Inherit the strict mode from the parent scope. |
| 327 strict_mode_ = (parent_ != NULL) && parent_->strict_mode_; |
| 318 *variable = this; | 328 *variable = this; |
| 319 } | 329 } |
| 320 | 330 |
| 321 | 331 |
| 322 TemporaryScope::~TemporaryScope() { | 332 TemporaryScope::~TemporaryScope() { |
| 323 *variable_ = parent_; | 333 *variable_ = parent_; |
| 324 } | 334 } |
| 325 | 335 |
| 326 | 336 |
| 327 Handle<String> Parser::LookupSymbol(int symbol_id) { | 337 Handle<String> Parser::LookupSymbol(int symbol_id) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 *with_nesting_level_variable_ = prev_level_; | 569 *with_nesting_level_variable_ = prev_level_; |
| 560 } | 570 } |
| 561 | 571 |
| 562 private: | 572 private: |
| 563 Scope** scope_variable_; | 573 Scope** scope_variable_; |
| 564 int* with_nesting_level_variable_; | 574 int* with_nesting_level_variable_; |
| 565 Scope* prev_scope_; | 575 Scope* prev_scope_; |
| 566 int prev_level_; | 576 int prev_level_; |
| 567 }; | 577 }; |
| 568 | 578 |
| 569 | |
| 570 // ---------------------------------------------------------------------------- | 579 // ---------------------------------------------------------------------------- |
| 571 // The CHECK_OK macro is a convenient macro to enforce error | 580 // The CHECK_OK macro is a convenient macro to enforce error |
| 572 // handling for functions that may fail (by returning !*ok). | 581 // handling for functions that may fail (by returning !*ok). |
| 573 // | 582 // |
| 574 // CAUTION: This macro appends extra statements after a call, | 583 // CAUTION: This macro appends extra statements after a call, |
| 575 // thus it must never be used where only a single statement | 584 // thus it must never be used where only a single statement |
| 576 // is correct (e.g. an if statement branch w/o braces)! | 585 // is correct (e.g. an if statement branch w/o braces)! |
| 577 | 586 |
| 578 #define CHECK_OK ok); \ | 587 #define CHECK_OK ok); \ |
| 579 if (!*ok) return NULL; \ | 588 if (!*ok) return NULL; \ |
| (...skipping 19 matching lines...) Expand all Loading... |
| 599 script_(script), | 608 script_(script), |
| 600 scanner_(isolate_), | 609 scanner_(isolate_), |
| 601 top_scope_(NULL), | 610 top_scope_(NULL), |
| 602 with_nesting_level_(0), | 611 with_nesting_level_(0), |
| 603 temp_scope_(NULL), | 612 temp_scope_(NULL), |
| 604 target_stack_(NULL), | 613 target_stack_(NULL), |
| 605 allow_natives_syntax_(allow_natives_syntax), | 614 allow_natives_syntax_(allow_natives_syntax), |
| 606 extension_(extension), | 615 extension_(extension), |
| 607 pre_data_(pre_data), | 616 pre_data_(pre_data), |
| 608 fni_(NULL), | 617 fni_(NULL), |
| 609 stack_overflow_(false) { | 618 stack_overflow_(false), |
| 619 parenthesized_function_(false) { |
| 610 AstNode::ResetIds(); | 620 AstNode::ResetIds(); |
| 611 } | 621 } |
| 612 | 622 |
| 613 | 623 |
| 614 FunctionLiteral* Parser::ParseProgram(Handle<String> source, | 624 FunctionLiteral* Parser::ParseProgram(Handle<String> source, |
| 615 bool in_global_context) { | 625 bool in_global_context) { |
| 616 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); | 626 CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); |
| 617 | 627 |
| 618 HistogramTimerScope timer(COUNTERS->parse()); | 628 HistogramTimerScope timer(COUNTERS->parse()); |
| 619 COUNTERS->total_parse_size()->Increment(source->length()); | 629 COUNTERS->total_parse_size()->Increment(source->length()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 : Scope::EVAL_SCOPE; | 663 : Scope::EVAL_SCOPE; |
| 654 Handle<String> no_name = isolate()->factory()->empty_symbol(); | 664 Handle<String> no_name = isolate()->factory()->empty_symbol(); |
| 655 | 665 |
| 656 FunctionLiteral* result = NULL; | 666 FunctionLiteral* result = NULL; |
| 657 { Scope* scope = NewScope(top_scope_, type, inside_with()); | 667 { Scope* scope = NewScope(top_scope_, type, inside_with()); |
| 658 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, | 668 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, |
| 659 scope); | 669 scope); |
| 660 TemporaryScope temp_scope(&this->temp_scope_); | 670 TemporaryScope temp_scope(&this->temp_scope_); |
| 661 ZoneList<Statement*>* body = new ZoneList<Statement*>(16); | 671 ZoneList<Statement*>* body = new ZoneList<Statement*>(16); |
| 662 bool ok = true; | 672 bool ok = true; |
| 673 int beg_loc = scanner().location().beg_pos; |
| 663 ParseSourceElements(body, Token::EOS, &ok); | 674 ParseSourceElements(body, Token::EOS, &ok); |
| 675 if (ok && temp_scope_->StrictMode()) { |
| 676 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); |
| 677 } |
| 664 if (ok) { | 678 if (ok) { |
| 665 result = new FunctionLiteral( | 679 result = new FunctionLiteral( |
| 666 no_name, | 680 no_name, |
| 667 top_scope_, | 681 top_scope_, |
| 668 body, | 682 body, |
| 669 temp_scope.materialized_literal_count(), | 683 temp_scope.materialized_literal_count(), |
| 670 temp_scope.expected_property_count(), | 684 temp_scope.expected_property_count(), |
| 671 temp_scope.only_simple_this_property_assignments(), | 685 temp_scope.only_simple_this_property_assignments(), |
| 672 temp_scope.this_property_assignments(), | 686 temp_scope.this_property_assignments(), |
| 673 0, | 687 0, |
| 674 0, | 688 0, |
| 675 source->length(), | 689 source->length(), |
| 676 false, | 690 false, |
| 677 temp_scope.ContainsLoops()); | 691 temp_scope.ContainsLoops(), |
| 692 temp_scope.StrictMode()); |
| 678 } else if (stack_overflow_) { | 693 } else if (stack_overflow_) { |
| 679 isolate()->StackOverflow(); | 694 isolate()->StackOverflow(); |
| 680 } | 695 } |
| 681 } | 696 } |
| 682 | 697 |
| 683 // Make sure the target stack is empty. | 698 // Make sure the target stack is empty. |
| 684 ASSERT(target_stack_ == NULL); | 699 ASSERT(target_stack_ == NULL); |
| 685 | 700 |
| 686 // If there was a syntax error we have to get rid of the AST | 701 // If there was a syntax error we have to get rid of the AST |
| 687 // and it is not safe to do so before the scope has been deleted. | 702 // and it is not safe to do so before the scope has been deleted. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 void Parser::ReportMessage(const char* type, Vector<const char*> args) { | 791 void Parser::ReportMessage(const char* type, Vector<const char*> args) { |
| 777 Scanner::Location source_location = scanner().location(); | 792 Scanner::Location source_location = scanner().location(); |
| 778 ReportMessageAt(source_location, type, args); | 793 ReportMessageAt(source_location, type, args); |
| 779 } | 794 } |
| 780 | 795 |
| 781 | 796 |
| 782 void Parser::ReportMessageAt(Scanner::Location source_location, | 797 void Parser::ReportMessageAt(Scanner::Location source_location, |
| 783 const char* type, | 798 const char* type, |
| 784 Vector<const char*> args) { | 799 Vector<const char*> args) { |
| 785 MessageLocation location(script_, | 800 MessageLocation location(script_, |
| 786 source_location.beg_pos, source_location.end_pos); | 801 source_location.beg_pos, |
| 802 source_location.end_pos); |
| 787 Handle<JSArray> array = isolate()->factory()->NewJSArray(args.length()); | 803 Handle<JSArray> array = isolate()->factory()->NewJSArray(args.length()); |
| 788 for (int i = 0; i < args.length(); i++) { | 804 for (int i = 0; i < args.length(); i++) { |
| 789 SetElement(array, i, | 805 SetElement(array, i, |
| 790 isolate()->factory()->NewStringFromUtf8(CStrVector(args[i]))); | 806 isolate()->factory()->NewStringFromUtf8(CStrVector(args[i]))); |
| 791 } | 807 } |
| 792 Handle<Object> result = isolate()->factory()->NewSyntaxError(type, array); | 808 Handle<Object> result = isolate()->factory()->NewSyntaxError(type, array); |
| 793 isolate()->Throw(*result, &location); | 809 isolate()->Throw(*result, &location); |
| 794 } | 810 } |
| 795 | 811 |
| 796 | 812 |
| 813 void Parser::ReportMessageAt(Scanner::Location source_location, |
| 814 const char* type, |
| 815 Vector<Handle<String> > args) { |
| 816 MessageLocation location(script_, |
| 817 source_location.beg_pos, |
| 818 source_location.end_pos); |
| 819 Handle<JSArray> array = FACTORY->NewJSArray(args.length()); |
| 820 for (int i = 0; i < args.length(); i++) { |
| 821 SetElement(array, i, args[i]); |
| 822 } |
| 823 Handle<Object> result = FACTORY->NewSyntaxError(type, array); |
| 824 isolate()->Throw(*result, &location); |
| 825 } |
| 826 |
| 827 |
| 797 // Base class containing common code for the different finder classes used by | 828 // Base class containing common code for the different finder classes used by |
| 798 // the parser. | 829 // the parser. |
| 799 class ParserFinder { | 830 class ParserFinder { |
| 800 protected: | 831 protected: |
| 801 ParserFinder() {} | 832 ParserFinder() {} |
| 802 static Assignment* AsAssignment(Statement* stat) { | 833 static Assignment* AsAssignment(Statement* stat) { |
| 803 if (stat == NULL) return NULL; | 834 if (stat == NULL) return NULL; |
| 804 ExpressionStatement* exp_stat = stat->AsExpressionStatement(); | 835 ExpressionStatement* exp_stat = stat->AsExpressionStatement(); |
| 805 if (exp_stat == NULL) return NULL; | 836 if (exp_stat == NULL) return NULL; |
| 806 return exp_stat->expression()->AsAssignment(); | 837 return exp_stat->expression()->AsAssignment(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 | 1089 |
| 1059 // Allocate a target stack to use for this set of source | 1090 // Allocate a target stack to use for this set of source |
| 1060 // elements. This way, all scripts and functions get their own | 1091 // elements. This way, all scripts and functions get their own |
| 1061 // target stack thus avoiding illegal breaks and continues across | 1092 // target stack thus avoiding illegal breaks and continues across |
| 1062 // functions. | 1093 // functions. |
| 1063 TargetScope scope(&this->target_stack_); | 1094 TargetScope scope(&this->target_stack_); |
| 1064 | 1095 |
| 1065 ASSERT(processor != NULL); | 1096 ASSERT(processor != NULL); |
| 1066 InitializationBlockFinder block_finder; | 1097 InitializationBlockFinder block_finder; |
| 1067 ThisNamedPropertyAssigmentFinder this_property_assignment_finder; | 1098 ThisNamedPropertyAssigmentFinder this_property_assignment_finder; |
| 1099 bool directive_prologue = true; // Parsing directive prologue. |
| 1100 |
| 1068 while (peek() != end_token) { | 1101 while (peek() != end_token) { |
| 1102 if (directive_prologue && peek() != Token::STRING) { |
| 1103 directive_prologue = false; |
| 1104 } |
| 1105 |
| 1106 Scanner::Location token_loc = scanner().peek_location(); |
| 1069 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1107 Statement* stat = ParseStatement(NULL, CHECK_OK); |
| 1070 if (stat == NULL || stat->IsEmpty()) continue; | 1108 |
| 1109 if (stat == NULL || stat->IsEmpty()) { |
| 1110 directive_prologue = false; // End of directive prologue. |
| 1111 continue; |
| 1112 } |
| 1113 |
| 1114 if (directive_prologue) { |
| 1115 // A shot at a directive. |
| 1116 ExpressionStatement *e_stat; |
| 1117 Literal *literal; |
| 1118 // Still processing directive prologue? |
| 1119 if ((e_stat = stat->AsExpressionStatement()) != NULL && |
| 1120 (literal = e_stat->expression()->AsLiteral()) != NULL && |
| 1121 literal->handle()->IsString()) { |
| 1122 Handle<String> directive = Handle<String>::cast(literal->handle()); |
| 1123 |
| 1124 // Check "use strict" directive (ES5 14.1). |
| 1125 if (!temp_scope_->StrictMode() && |
| 1126 directive->Equals(isolate()->heap()->use_strict()) && |
| 1127 token_loc.end_pos - token_loc.beg_pos == |
| 1128 isolate()->heap()->use_strict()->length() + 2) { |
| 1129 temp_scope_->EnableStrictMode(); |
| 1130 // "use strict" is the only directive for now. |
| 1131 directive_prologue = false; |
| 1132 } |
| 1133 } else { |
| 1134 // End of the directive prologue. |
| 1135 directive_prologue = false; |
| 1136 } |
| 1137 } |
| 1138 |
| 1071 // We find and mark the initialization blocks on top level code only. | 1139 // We find and mark the initialization blocks on top level code only. |
| 1072 // This is because the optimization prevents reuse of the map transitions, | 1140 // This is because the optimization prevents reuse of the map transitions, |
| 1073 // so it should be used only for code that will only be run once. | 1141 // so it should be used only for code that will only be run once. |
| 1074 if (top_scope_->is_global_scope()) { | 1142 if (top_scope_->is_global_scope()) { |
| 1075 block_finder.Update(stat); | 1143 block_finder.Update(stat); |
| 1076 } | 1144 } |
| 1077 // Find and mark all assignments to named properties in this (this.x =) | 1145 // Find and mark all assignments to named properties in this (this.x =) |
| 1078 if (top_scope_->is_function_scope()) { | 1146 if (top_scope_->is_function_scope()) { |
| 1079 this_property_assignment_finder.Update(top_scope_, stat); | 1147 this_property_assignment_finder.Update(top_scope_, stat); |
| 1080 } | 1148 } |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 Block* Parser::ParseVariableStatement(bool* ok) { | 1482 Block* Parser::ParseVariableStatement(bool* ok) { |
| 1415 // VariableStatement :: | 1483 // VariableStatement :: |
| 1416 // VariableDeclarations ';' | 1484 // VariableDeclarations ';' |
| 1417 | 1485 |
| 1418 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature | 1486 Expression* dummy; // to satisfy the ParseVariableDeclarations() signature |
| 1419 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); | 1487 Block* result = ParseVariableDeclarations(true, &dummy, CHECK_OK); |
| 1420 ExpectSemicolon(CHECK_OK); | 1488 ExpectSemicolon(CHECK_OK); |
| 1421 return result; | 1489 return result; |
| 1422 } | 1490 } |
| 1423 | 1491 |
| 1492 static bool IsEvalOrArguments(Handle<String> string) { |
| 1493 return string.is_identical_to(FACTORY->eval_symbol()) || |
| 1494 string.is_identical_to(FACTORY->arguments_symbol()); |
| 1495 } |
| 1424 | 1496 |
| 1425 // If the variable declaration declares exactly one non-const | 1497 // If the variable declaration declares exactly one non-const |
| 1426 // variable, then *var is set to that variable. In all other cases, | 1498 // variable, then *var is set to that variable. In all other cases, |
| 1427 // *var is untouched; in particular, it is the caller's responsibility | 1499 // *var is untouched; in particular, it is the caller's responsibility |
| 1428 // to initialize it properly. This mechanism is used for the parsing | 1500 // to initialize it properly. This mechanism is used for the parsing |
| 1429 // of 'for-in' loops. | 1501 // of 'for-in' loops. |
| 1430 Block* Parser::ParseVariableDeclarations(bool accept_IN, | 1502 Block* Parser::ParseVariableDeclarations(bool accept_IN, |
| 1431 Expression** var, | 1503 Expression** var, |
| 1432 bool* ok) { | 1504 bool* ok) { |
| 1433 // VariableDeclarations :: | 1505 // VariableDeclarations :: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1462 VariableProxy* last_var = NULL; // the last variable declared | 1534 VariableProxy* last_var = NULL; // the last variable declared |
| 1463 int nvars = 0; // the number of variables declared | 1535 int nvars = 0; // the number of variables declared |
| 1464 do { | 1536 do { |
| 1465 if (fni_ != NULL) fni_->Enter(); | 1537 if (fni_ != NULL) fni_->Enter(); |
| 1466 | 1538 |
| 1467 // Parse variable name. | 1539 // Parse variable name. |
| 1468 if (nvars > 0) Consume(Token::COMMA); | 1540 if (nvars > 0) Consume(Token::COMMA); |
| 1469 Handle<String> name = ParseIdentifier(CHECK_OK); | 1541 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 1470 if (fni_ != NULL) fni_->PushVariableName(name); | 1542 if (fni_ != NULL) fni_->PushVariableName(name); |
| 1471 | 1543 |
| 1544 // Strict mode variables may not be named eval or arguments |
| 1545 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { |
| 1546 ReportMessage("strict_var_name", Vector<const char*>::empty()); |
| 1547 *ok = false; |
| 1548 return NULL; |
| 1549 } |
| 1550 |
| 1472 // Declare variable. | 1551 // Declare variable. |
| 1473 // Note that we *always* must treat the initial value via a separate init | 1552 // Note that we *always* must treat the initial value via a separate init |
| 1474 // assignment for variables and constants because the value must be assigned | 1553 // assignment for variables and constants because the value must be assigned |
| 1475 // when the variable is encountered in the source. But the variable/constant | 1554 // when the variable is encountered in the source. But the variable/constant |
| 1476 // is declared (and set to 'undefined') upon entering the function within | 1555 // is declared (and set to 'undefined') upon entering the function within |
| 1477 // which the variable or constant is declared. Only function variables have | 1556 // which the variable or constant is declared. Only function variables have |
| 1478 // an initial value in the declaration (because they are initialized upon | 1557 // an initial value in the declaration (because they are initialized upon |
| 1479 // entering the function). | 1558 // entering the function). |
| 1480 // | 1559 // |
| 1481 // If we have a const declaration, in an inner scope, the proxy is always | 1560 // If we have a const declaration, in an inner scope, the proxy is always |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1692 Expect(Token::CONTINUE, CHECK_OK); | 1771 Expect(Token::CONTINUE, CHECK_OK); |
| 1693 Handle<String> label = Handle<String>::null(); | 1772 Handle<String> label = Handle<String>::null(); |
| 1694 Token::Value tok = peek(); | 1773 Token::Value tok = peek(); |
| 1695 if (!scanner().has_line_terminator_before_next() && | 1774 if (!scanner().has_line_terminator_before_next() && |
| 1696 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 1775 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| 1697 label = ParseIdentifier(CHECK_OK); | 1776 label = ParseIdentifier(CHECK_OK); |
| 1698 } | 1777 } |
| 1699 IterationStatement* target = NULL; | 1778 IterationStatement* target = NULL; |
| 1700 target = LookupContinueTarget(label, CHECK_OK); | 1779 target = LookupContinueTarget(label, CHECK_OK); |
| 1701 if (target == NULL) { | 1780 if (target == NULL) { |
| 1702 // Illegal continue statement. To be consistent with KJS we delay | 1781 // Illegal continue statement. |
| 1703 // reporting of the syntax error until runtime. | 1782 const char* message = "illegal_continue"; |
| 1704 Handle<String> error_type = isolate()->factory()->illegal_continue_symbol(); | 1783 Vector<Handle<String> > args; |
| 1705 if (!label.is_null()) { | 1784 if (!label.is_null()) { |
| 1706 error_type = isolate()->factory()->unknown_label_symbol(); | 1785 message = "unknown_label"; |
| 1786 args = Vector<Handle<String> >(&label, 1); |
| 1707 } | 1787 } |
| 1708 Expression* throw_error = NewThrowSyntaxError(error_type, label); | 1788 ReportMessageAt(scanner().location(), message, args); |
| 1709 return new ExpressionStatement(throw_error); | 1789 *ok = false; |
| 1790 return NULL; |
| 1710 } | 1791 } |
| 1711 ExpectSemicolon(CHECK_OK); | 1792 ExpectSemicolon(CHECK_OK); |
| 1712 return new ContinueStatement(target); | 1793 return new ContinueStatement(target); |
| 1713 } | 1794 } |
| 1714 | 1795 |
| 1715 | 1796 |
| 1716 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { | 1797 Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| 1717 // BreakStatement :: | 1798 // BreakStatement :: |
| 1718 // 'break' Identifier? ';' | 1799 // 'break' Identifier? ';' |
| 1719 | 1800 |
| 1720 Expect(Token::BREAK, CHECK_OK); | 1801 Expect(Token::BREAK, CHECK_OK); |
| 1721 Handle<String> label; | 1802 Handle<String> label; |
| 1722 Token::Value tok = peek(); | 1803 Token::Value tok = peek(); |
| 1723 if (!scanner().has_line_terminator_before_next() && | 1804 if (!scanner().has_line_terminator_before_next() && |
| 1724 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 1805 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
| 1725 label = ParseIdentifier(CHECK_OK); | 1806 label = ParseIdentifier(CHECK_OK); |
| 1726 } | 1807 } |
| 1727 // Parse labeled break statements that target themselves into | 1808 // Parse labeled break statements that target themselves into |
| 1728 // empty statements, e.g. 'l1: l2: l3: break l2;' | 1809 // empty statements, e.g. 'l1: l2: l3: break l2;' |
| 1729 if (!label.is_null() && ContainsLabel(labels, label)) { | 1810 if (!label.is_null() && ContainsLabel(labels, label)) { |
| 1730 return EmptyStatement(); | 1811 return EmptyStatement(); |
| 1731 } | 1812 } |
| 1732 BreakableStatement* target = NULL; | 1813 BreakableStatement* target = NULL; |
| 1733 target = LookupBreakTarget(label, CHECK_OK); | 1814 target = LookupBreakTarget(label, CHECK_OK); |
| 1734 if (target == NULL) { | 1815 if (target == NULL) { |
| 1735 // Illegal break statement. To be consistent with KJS we delay | 1816 // Illegal break statement. |
| 1736 // reporting of the syntax error until runtime. | 1817 const char* message = "illegal_break"; |
| 1737 Handle<String> error_type = isolate()->factory()->illegal_break_symbol(); | 1818 Vector<Handle<String> > args; |
| 1738 if (!label.is_null()) { | 1819 if (!label.is_null()) { |
| 1739 error_type = isolate()->factory()->unknown_label_symbol(); | 1820 message = "unknown_label"; |
| 1821 args = Vector<Handle<String> >(&label, 1); |
| 1740 } | 1822 } |
| 1741 Expression* throw_error = NewThrowSyntaxError(error_type, label); | 1823 ReportMessageAt(scanner().location(), message, args); |
| 1742 return new ExpressionStatement(throw_error); | 1824 *ok = false; |
| 1825 return NULL; |
| 1743 } | 1826 } |
| 1744 ExpectSemicolon(CHECK_OK); | 1827 ExpectSemicolon(CHECK_OK); |
| 1745 return new BreakStatement(target); | 1828 return new BreakStatement(target); |
| 1746 } | 1829 } |
| 1747 | 1830 |
| 1748 | 1831 |
| 1749 Statement* Parser::ParseReturnStatement(bool* ok) { | 1832 Statement* Parser::ParseReturnStatement(bool* ok) { |
| 1750 // ReturnStatement :: | 1833 // ReturnStatement :: |
| 1751 // 'return' Expression? ';' | 1834 // 'return' Expression? ';' |
| 1752 | 1835 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1818 } | 1901 } |
| 1819 return result; | 1902 return result; |
| 1820 } | 1903 } |
| 1821 | 1904 |
| 1822 | 1905 |
| 1823 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { | 1906 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { |
| 1824 // WithStatement :: | 1907 // WithStatement :: |
| 1825 // 'with' '(' Expression ')' Statement | 1908 // 'with' '(' Expression ')' Statement |
| 1826 | 1909 |
| 1827 Expect(Token::WITH, CHECK_OK); | 1910 Expect(Token::WITH, CHECK_OK); |
| 1911 |
| 1912 if (temp_scope_->StrictMode()) { |
| 1913 ReportMessage("strict_mode_with", Vector<const char*>::empty()); |
| 1914 *ok = false; |
| 1915 return NULL; |
| 1916 } |
| 1917 |
| 1828 Expect(Token::LPAREN, CHECK_OK); | 1918 Expect(Token::LPAREN, CHECK_OK); |
| 1829 Expression* expr = ParseExpression(true, CHECK_OK); | 1919 Expression* expr = ParseExpression(true, CHECK_OK); |
| 1830 Expect(Token::RPAREN, CHECK_OK); | 1920 Expect(Token::RPAREN, CHECK_OK); |
| 1831 | 1921 |
| 1832 return WithHelper(expr, labels, false, CHECK_OK); | 1922 return WithHelper(expr, labels, false, CHECK_OK); |
| 1833 } | 1923 } |
| 1834 | 1924 |
| 1835 | 1925 |
| 1836 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | 1926 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| 1837 // CaseClause :: | 1927 // CaseClause :: |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1950 // the jump targets. | 2040 // the jump targets. |
| 1951 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); | 2041 ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0); |
| 1952 TargetCollector catch_collector(catch_target_list); | 2042 TargetCollector catch_collector(catch_target_list); |
| 1953 bool has_catch = false; | 2043 bool has_catch = false; |
| 1954 if (tok == Token::CATCH) { | 2044 if (tok == Token::CATCH) { |
| 1955 has_catch = true; | 2045 has_catch = true; |
| 1956 Consume(Token::CATCH); | 2046 Consume(Token::CATCH); |
| 1957 | 2047 |
| 1958 Expect(Token::LPAREN, CHECK_OK); | 2048 Expect(Token::LPAREN, CHECK_OK); |
| 1959 Handle<String> name = ParseIdentifier(CHECK_OK); | 2049 Handle<String> name = ParseIdentifier(CHECK_OK); |
| 2050 |
| 2051 if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) { |
| 2052 ReportMessage("strict_catch_variable", Vector<const char*>::empty()); |
| 2053 *ok = false; |
| 2054 return NULL; |
| 2055 } |
| 2056 |
| 1960 Expect(Token::RPAREN, CHECK_OK); | 2057 Expect(Token::RPAREN, CHECK_OK); |
| 1961 | 2058 |
| 1962 if (peek() == Token::LBRACE) { | 2059 if (peek() == Token::LBRACE) { |
| 1963 // Allocate a temporary for holding the finally state while | 2060 // Allocate a temporary for holding the finally state while |
| 1964 // executing the finally block. | 2061 // executing the finally block. |
| 1965 catch_var = | 2062 catch_var = |
| 1966 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol()); | 2063 top_scope_->NewTemporary(isolate()->factory()->catch_var_symbol()); |
| 1967 Literal* name_literal = new Literal(name); | 2064 Literal* name_literal = new Literal(name); |
| 1968 VariableProxy* catch_var_use = new VariableProxy(catch_var); | 2065 VariableProxy* catch_var_use = new VariableProxy(catch_var); |
| 1969 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); | 2066 Expression* obj = new CatchExtensionObject(name_literal, catch_var_use); |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2491 | 2588 |
| 2492 case Token::LPAREN: { | 2589 case Token::LPAREN: { |
| 2493 int pos = scanner().location().beg_pos; | 2590 int pos = scanner().location().beg_pos; |
| 2494 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); | 2591 ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
| 2495 | 2592 |
| 2496 // Keep track of eval() calls since they disable all local variable | 2593 // Keep track of eval() calls since they disable all local variable |
| 2497 // optimizations. | 2594 // optimizations. |
| 2498 // The calls that need special treatment are the | 2595 // The calls that need special treatment are the |
| 2499 // direct (i.e. not aliased) eval calls. These calls are all of the | 2596 // direct (i.e. not aliased) eval calls. These calls are all of the |
| 2500 // form eval(...) with no explicit receiver object where eval is not | 2597 // form eval(...) with no explicit receiver object where eval is not |
| 2501 // declared in the current scope chain. These calls are marked as | 2598 // declared in the current scope chain. |
| 2502 // potentially direct eval calls. Whether they are actually direct calls | 2599 // These calls are marked as potentially direct eval calls. Whether |
| 2503 // to eval is determined at run time. | 2600 // they are actually direct calls to eval is determined at run time. |
| 2601 // TODO(994): In ES5, it doesn't matter if the "eval" var is declared |
| 2602 // in the local scope chain. It only matters that it's called "eval", |
| 2603 // is called without a receiver and it refers to the original eval |
| 2604 // function. |
| 2504 VariableProxy* callee = result->AsVariableProxy(); | 2605 VariableProxy* callee = result->AsVariableProxy(); |
| 2505 if (callee != NULL && | 2606 if (callee != NULL && |
| 2506 callee->IsVariable(isolate()->factory()->eval_symbol())) { | 2607 callee->IsVariable(isolate()->factory()->eval_symbol())) { |
| 2507 Handle<String> name = callee->name(); | 2608 Handle<String> name = callee->name(); |
| 2508 Variable* var = top_scope_->Lookup(name); | 2609 Variable* var = top_scope_->Lookup(name); |
| 2509 if (var == NULL) { | 2610 if (var == NULL) { |
| 2510 top_scope_->RecordEvalCall(); | 2611 top_scope_->RecordEvalCall(); |
| 2511 } | 2612 } |
| 2512 } | 2613 } |
| 2513 result = NewCall(result, args, pos); | 2614 result = NewCall(result, args, pos); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2744 case Token::LBRACK: | 2845 case Token::LBRACK: |
| 2745 result = ParseArrayLiteral(CHECK_OK); | 2846 result = ParseArrayLiteral(CHECK_OK); |
| 2746 break; | 2847 break; |
| 2747 | 2848 |
| 2748 case Token::LBRACE: | 2849 case Token::LBRACE: |
| 2749 result = ParseObjectLiteral(CHECK_OK); | 2850 result = ParseObjectLiteral(CHECK_OK); |
| 2750 break; | 2851 break; |
| 2751 | 2852 |
| 2752 case Token::LPAREN: | 2853 case Token::LPAREN: |
| 2753 Consume(Token::LPAREN); | 2854 Consume(Token::LPAREN); |
| 2855 // Heuristically try to detect immediately called functions before |
| 2856 // seeing the call parentheses. |
| 2857 parenthesized_function_ = (peek() == Token::FUNCTION); |
| 2754 result = ParseExpression(true, CHECK_OK); | 2858 result = ParseExpression(true, CHECK_OK); |
| 2755 Expect(Token::RPAREN, CHECK_OK); | 2859 Expect(Token::RPAREN, CHECK_OK); |
| 2756 break; | 2860 break; |
| 2757 | 2861 |
| 2758 case Token::MOD: | 2862 case Token::MOD: |
| 2759 if (allow_natives_syntax_ || extension_ != NULL) { | 2863 if (allow_natives_syntax_ || extension_ != NULL) { |
| 2760 result = ParseV8Intrinsic(CHECK_OK); | 2864 result = ParseV8Intrinsic(CHECK_OK); |
| 2761 break; | 2865 break; |
| 2762 } | 2866 } |
| 2763 // If we're not allowing special syntax we fall-through to the | 2867 // If we're not allowing special syntax we fall-through to the |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2918 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { | 3022 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { |
| 2919 if (expression->AsLiteral() != NULL) { | 3023 if (expression->AsLiteral() != NULL) { |
| 2920 return expression->AsLiteral()->handle(); | 3024 return expression->AsLiteral()->handle(); |
| 2921 } | 3025 } |
| 2922 if (CompileTimeValue::IsCompileTimeValue(expression)) { | 3026 if (CompileTimeValue::IsCompileTimeValue(expression)) { |
| 2923 return CompileTimeValue::GetValue(expression); | 3027 return CompileTimeValue::GetValue(expression); |
| 2924 } | 3028 } |
| 2925 return isolate()->factory()->undefined_value(); | 3029 return isolate()->factory()->undefined_value(); |
| 2926 } | 3030 } |
| 2927 | 3031 |
| 3032 // Defined in ast.cc |
| 3033 bool IsEqualString(void* first, void* second); |
| 3034 bool IsEqualSmi(void* first, void* second); |
| 3035 |
| 3036 |
| 3037 // Validation per 11.1.5 Object Initialiser |
| 3038 class ObjectLiteralPropertyChecker { |
| 3039 public: |
| 3040 ObjectLiteralPropertyChecker(Parser* parser, bool strict) : |
| 3041 props(&IsEqualString), |
| 3042 elems(&IsEqualSmi), |
| 3043 parser_(parser), |
| 3044 strict_(strict) { |
| 3045 } |
| 3046 |
| 3047 void CheckProperty( |
| 3048 ObjectLiteral::Property* property, |
| 3049 Scanner::Location loc, |
| 3050 bool* ok); |
| 3051 |
| 3052 private: |
| 3053 enum PropertyKind { |
| 3054 kGetAccessor = 0x01, |
| 3055 kSetAccessor = 0x02, |
| 3056 kAccessor = kGetAccessor | kSetAccessor, |
| 3057 kData = 0x04 |
| 3058 }; |
| 3059 |
| 3060 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) { |
| 3061 switch (property->kind()) { |
| 3062 case ObjectLiteral::Property::GETTER: |
| 3063 return kGetAccessor; |
| 3064 case ObjectLiteral::Property::SETTER: |
| 3065 return kSetAccessor; |
| 3066 default: |
| 3067 return kData; |
| 3068 } |
| 3069 } |
| 3070 |
| 3071 HashMap props; |
| 3072 HashMap elems; |
| 3073 Parser* parser_; |
| 3074 bool strict_; |
| 3075 }; |
| 3076 |
| 3077 |
| 3078 void ObjectLiteralPropertyChecker::CheckProperty( |
| 3079 ObjectLiteral::Property* property, |
| 3080 Scanner::Location loc, |
| 3081 bool* ok) { |
| 3082 |
| 3083 ASSERT(property != NULL); |
| 3084 |
| 3085 Literal *lit = property->key(); |
| 3086 Handle<Object> handle = lit->handle(); |
| 3087 |
| 3088 uint32_t hash; |
| 3089 HashMap* map; |
| 3090 void* key; |
| 3091 Smi* smi_key_location; |
| 3092 |
| 3093 if (handle->IsSymbol()) { |
| 3094 Handle<String> name(String::cast(*handle)); |
| 3095 if (name->AsArrayIndex(&hash)) { |
| 3096 smi_key_location = Smi::FromInt(hash); |
| 3097 key = &smi_key_location; |
| 3098 map = &elems; |
| 3099 } else { |
| 3100 key = handle.location(); |
| 3101 hash = name->Hash(); |
| 3102 map = &props; |
| 3103 } |
| 3104 } else if (handle->ToArrayIndex(&hash)) { |
| 3105 key = handle.location(); |
| 3106 map = &elems; |
| 3107 } else { |
| 3108 ASSERT(handle->IsNumber()); |
| 3109 double num = handle->Number(); |
| 3110 char arr[100]; |
| 3111 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 3112 const char* str = DoubleToCString(num, buffer); |
| 3113 Handle<String> name = FACTORY->NewStringFromAscii(CStrVector(str)); |
| 3114 key = name.location(); |
| 3115 hash = name->Hash(); |
| 3116 map = &props; |
| 3117 } |
| 3118 |
| 3119 // Lookup property previously defined, if any. |
| 3120 HashMap::Entry* entry = map->Lookup(key, hash, true); |
| 3121 intptr_t prev = reinterpret_cast<intptr_t> (entry->value); |
| 3122 intptr_t curr = GetPropertyKind(property); |
| 3123 |
| 3124 // Duplicate data properties are illegal in strict mode. |
| 3125 if (strict_ && (curr & prev & kData) != 0) { |
| 3126 parser_->ReportMessageAt(loc, "strict_duplicate_property", |
| 3127 Vector<const char*>::empty()); |
| 3128 *ok = false; |
| 3129 return; |
| 3130 } |
| 3131 // Data property conflicting with an accessor. |
| 3132 if (((curr & kData) && (prev & kAccessor)) || |
| 3133 ((prev & kData) && (curr & kAccessor))) { |
| 3134 parser_->ReportMessageAt(loc, "accessor_data_property", |
| 3135 Vector<const char*>::empty()); |
| 3136 *ok = false; |
| 3137 return; |
| 3138 } |
| 3139 // Two accessors of the same type conflicting |
| 3140 if ((curr & prev & kAccessor) != 0) { |
| 3141 parser_->ReportMessageAt(loc, "accessor_get_set", |
| 3142 Vector<const char*>::empty()); |
| 3143 *ok = false; |
| 3144 return; |
| 3145 } |
| 3146 |
| 3147 // Update map |
| 3148 entry->value = reinterpret_cast<void*> (prev | curr); |
| 3149 *ok = true; |
| 3150 } |
| 3151 |
| 2928 | 3152 |
| 2929 void Parser::BuildObjectLiteralConstantProperties( | 3153 void Parser::BuildObjectLiteralConstantProperties( |
| 2930 ZoneList<ObjectLiteral::Property*>* properties, | 3154 ZoneList<ObjectLiteral::Property*>* properties, |
| 2931 Handle<FixedArray> constant_properties, | 3155 Handle<FixedArray> constant_properties, |
| 2932 bool* is_simple, | 3156 bool* is_simple, |
| 2933 bool* fast_elements, | 3157 bool* fast_elements, |
| 2934 int* depth) { | 3158 int* depth) { |
| 2935 int position = 0; | 3159 int position = 0; |
| 2936 // Accumulate the value in local variables and store it at the end. | 3160 // Accumulate the value in local variables and store it at the end. |
| 2937 bool is_simple_acc = true; | 3161 bool is_simple_acc = true; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3023 // ObjectLiteral :: | 3247 // ObjectLiteral :: |
| 3024 // '{' ( | 3248 // '{' ( |
| 3025 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 3249 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 3026 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 3250 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 3027 // )*[','] '}' | 3251 // )*[','] '}' |
| 3028 | 3252 |
| 3029 ZoneList<ObjectLiteral::Property*>* properties = | 3253 ZoneList<ObjectLiteral::Property*>* properties = |
| 3030 new ZoneList<ObjectLiteral::Property*>(4); | 3254 new ZoneList<ObjectLiteral::Property*>(4); |
| 3031 int number_of_boilerplate_properties = 0; | 3255 int number_of_boilerplate_properties = 0; |
| 3032 | 3256 |
| 3257 ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode()); |
| 3258 |
| 3033 Expect(Token::LBRACE, CHECK_OK); | 3259 Expect(Token::LBRACE, CHECK_OK); |
| 3260 Scanner::Location loc = scanner().location(); |
| 3261 |
| 3034 while (peek() != Token::RBRACE) { | 3262 while (peek() != Token::RBRACE) { |
| 3035 if (fni_ != NULL) fni_->Enter(); | 3263 if (fni_ != NULL) fni_->Enter(); |
| 3036 | 3264 |
| 3037 Literal* key = NULL; | 3265 Literal* key = NULL; |
| 3038 Token::Value next = peek(); | 3266 Token::Value next = peek(); |
| 3267 |
| 3268 // Location of the property name token |
| 3269 Scanner::Location loc = scanner().peek_location(); |
| 3270 |
| 3039 switch (next) { | 3271 switch (next) { |
| 3040 case Token::IDENTIFIER: { | 3272 case Token::IDENTIFIER: { |
| 3041 bool is_getter = false; | 3273 bool is_getter = false; |
| 3042 bool is_setter = false; | 3274 bool is_setter = false; |
| 3043 Handle<String> id = | 3275 Handle<String> id = |
| 3044 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3276 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 3045 if (fni_ != NULL) fni_->PushLiteralName(id); | 3277 if (fni_ != NULL) fni_->PushLiteralName(id); |
| 3046 | 3278 |
| 3047 if ((is_getter || is_setter) && peek() != Token::COLON) { | 3279 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 3280 // Update loc to point to the identifier |
| 3281 loc = scanner().peek_location(); |
| 3048 ObjectLiteral::Property* property = | 3282 ObjectLiteral::Property* property = |
| 3049 ParseObjectLiteralGetSet(is_getter, CHECK_OK); | 3283 ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
| 3050 if (IsBoilerplateProperty(property)) { | 3284 if (IsBoilerplateProperty(property)) { |
| 3051 number_of_boilerplate_properties++; | 3285 number_of_boilerplate_properties++; |
| 3052 } | 3286 } |
| 3287 // Validate the property. |
| 3288 checker.CheckProperty(property, loc, CHECK_OK); |
| 3053 properties->Add(property); | 3289 properties->Add(property); |
| 3054 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3290 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3055 | 3291 |
| 3056 if (fni_ != NULL) { | 3292 if (fni_ != NULL) { |
| 3057 fni_->Infer(); | 3293 fni_->Infer(); |
| 3058 fni_->Leave(); | 3294 fni_->Leave(); |
| 3059 } | 3295 } |
| 3060 continue; // restart the while | 3296 continue; // restart the while |
| 3061 } | 3297 } |
| 3062 // Failed to parse as get/set property, so it's just a property | 3298 // Failed to parse as get/set property, so it's just a property |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3099 } | 3335 } |
| 3100 | 3336 |
| 3101 Expect(Token::COLON, CHECK_OK); | 3337 Expect(Token::COLON, CHECK_OK); |
| 3102 Expression* value = ParseAssignmentExpression(true, CHECK_OK); | 3338 Expression* value = ParseAssignmentExpression(true, CHECK_OK); |
| 3103 | 3339 |
| 3104 ObjectLiteral::Property* property = | 3340 ObjectLiteral::Property* property = |
| 3105 new ObjectLiteral::Property(key, value); | 3341 new ObjectLiteral::Property(key, value); |
| 3106 | 3342 |
| 3107 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 3343 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| 3108 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; | 3344 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; |
| 3345 // Validate the property |
| 3346 checker.CheckProperty(property, loc, CHECK_OK); |
| 3109 properties->Add(property); | 3347 properties->Add(property); |
| 3110 | 3348 |
| 3111 // TODO(1240767): Consider allowing trailing comma. | 3349 // TODO(1240767): Consider allowing trailing comma. |
| 3112 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3350 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3113 | 3351 |
| 3114 if (fni_ != NULL) { | 3352 if (fni_ != NULL) { |
| 3115 fni_->Infer(); | 3353 fni_->Infer(); |
| 3116 fni_->Leave(); | 3354 fni_->Leave(); |
| 3117 } | 3355 } |
| 3118 } | 3356 } |
| 3119 Expect(Token::RBRACE, CHECK_OK); | 3357 Expect(Token::RBRACE, CHECK_OK); |
| 3358 |
| 3120 // Computation of literal_index must happen before pre parse bailout. | 3359 // Computation of literal_index must happen before pre parse bailout. |
| 3121 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3360 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
| 3122 | 3361 |
| 3123 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray( | 3362 Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray( |
| 3124 number_of_boilerplate_properties * 2, TENURED); | 3363 number_of_boilerplate_properties * 2, TENURED); |
| 3125 | 3364 |
| 3126 bool is_simple = true; | 3365 bool is_simple = true; |
| 3127 bool fast_elements = true; | 3366 bool fast_elements = true; |
| 3128 int depth = 1; | 3367 int depth = 1; |
| 3129 BuildObjectLiteralConstantProperties(properties, | 3368 BuildObjectLiteralConstantProperties(properties, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3203 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); | 3442 NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); |
| 3204 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, | 3443 LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_, |
| 3205 scope); | 3444 scope); |
| 3206 TemporaryScope temp_scope(&this->temp_scope_); | 3445 TemporaryScope temp_scope(&this->temp_scope_); |
| 3207 top_scope_->SetScopeName(name); | 3446 top_scope_->SetScopeName(name); |
| 3208 | 3447 |
| 3209 // FormalParameterList :: | 3448 // FormalParameterList :: |
| 3210 // '(' (Identifier)*[','] ')' | 3449 // '(' (Identifier)*[','] ')' |
| 3211 Expect(Token::LPAREN, CHECK_OK); | 3450 Expect(Token::LPAREN, CHECK_OK); |
| 3212 int start_pos = scanner().location().beg_pos; | 3451 int start_pos = scanner().location().beg_pos; |
| 3452 Scanner::Location name_loc = Scanner::NoLocation(); |
| 3453 Scanner::Location dupe_loc = Scanner::NoLocation(); |
| 3454 |
| 3213 bool done = (peek() == Token::RPAREN); | 3455 bool done = (peek() == Token::RPAREN); |
| 3214 while (!done) { | 3456 while (!done) { |
| 3215 Handle<String> param_name = ParseIdentifier(CHECK_OK); | 3457 Handle<String> param_name = ParseIdentifier(CHECK_OK); |
| 3216 top_scope_->AddParameter(top_scope_->DeclareLocal(param_name, | 3458 |
| 3217 Variable::VAR)); | 3459 // Store locations for possible future error reports. |
| 3460 if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) { |
| 3461 name_loc = scanner().location(); |
| 3462 } |
| 3463 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) { |
| 3464 dupe_loc = scanner().location(); |
| 3465 } |
| 3466 |
| 3467 Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR); |
| 3468 top_scope_->AddParameter(parameter); |
| 3218 num_parameters++; | 3469 num_parameters++; |
| 3219 done = (peek() == Token::RPAREN); | 3470 done = (peek() == Token::RPAREN); |
| 3220 if (!done) Expect(Token::COMMA, CHECK_OK); | 3471 if (!done) Expect(Token::COMMA, CHECK_OK); |
| 3221 } | 3472 } |
| 3222 Expect(Token::RPAREN, CHECK_OK); | 3473 Expect(Token::RPAREN, CHECK_OK); |
| 3223 | 3474 |
| 3224 Expect(Token::LBRACE, CHECK_OK); | 3475 Expect(Token::LBRACE, CHECK_OK); |
| 3225 ZoneList<Statement*>* body = new ZoneList<Statement*>(8); | 3476 ZoneList<Statement*>* body = new ZoneList<Statement*>(8); |
| 3226 | 3477 |
| 3227 // If we have a named function expression, we add a local variable | 3478 // If we have a named function expression, we add a local variable |
| 3228 // declaration to the body of the function with the name of the | 3479 // declaration to the body of the function with the name of the |
| 3229 // function and let it refer to the function itself (closure). | 3480 // function and let it refer to the function itself (closure). |
| 3230 // NOTE: We create a proxy and resolve it here so that in the | 3481 // NOTE: We create a proxy and resolve it here so that in the |
| 3231 // future we can change the AST to only refer to VariableProxies | 3482 // future we can change the AST to only refer to VariableProxies |
| 3232 // instead of Variables and Proxis as is the case now. | 3483 // instead of Variables and Proxis as is the case now. |
| 3233 if (!function_name.is_null() && function_name->length() > 0) { | 3484 if (!function_name.is_null() && function_name->length() > 0) { |
| 3234 Variable* fvar = top_scope_->DeclareFunctionVar(function_name); | 3485 Variable* fvar = top_scope_->DeclareFunctionVar(function_name); |
| 3235 VariableProxy* fproxy = | 3486 VariableProxy* fproxy = |
| 3236 top_scope_->NewUnresolved(function_name, inside_with()); | 3487 top_scope_->NewUnresolved(function_name, inside_with()); |
| 3237 fproxy->BindTo(fvar); | 3488 fproxy->BindTo(fvar); |
| 3238 body->Add(new ExpressionStatement( | 3489 body->Add(new ExpressionStatement( |
| 3239 new Assignment(Token::INIT_CONST, fproxy, | 3490 new Assignment(Token::INIT_CONST, fproxy, |
| 3240 new ThisFunction(), | 3491 new ThisFunction(), |
| 3241 RelocInfo::kNoPosition))); | 3492 RelocInfo::kNoPosition))); |
| 3242 } | 3493 } |
| 3243 | 3494 |
| 3244 // Determine if the function will be lazily compiled. The mode can | 3495 // Determine if the function will be lazily compiled. The mode can |
| 3245 // only be PARSE_LAZILY if the --lazy flag is true. | 3496 // only be PARSE_LAZILY if the --lazy flag is true. |
| 3246 bool is_lazily_compiled = | 3497 bool is_lazily_compiled = (mode() == PARSE_LAZILY && |
| 3247 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); | 3498 top_scope_->outer_scope()->is_global_scope() && |
| 3499 top_scope_->HasTrivialOuterContext() && |
| 3500 !parenthesized_function_); |
| 3501 parenthesized_function_ = false; // The bit was set for this function only. |
| 3248 | 3502 |
| 3249 int function_block_pos = scanner().location().beg_pos; | 3503 int function_block_pos = scanner().location().beg_pos; |
| 3250 int materialized_literal_count; | 3504 int materialized_literal_count; |
| 3251 int expected_property_count; | 3505 int expected_property_count; |
| 3252 int end_pos; | 3506 int end_pos; |
| 3253 bool only_simple_this_property_assignments; | 3507 bool only_simple_this_property_assignments; |
| 3254 Handle<FixedArray> this_property_assignments; | 3508 Handle<FixedArray> this_property_assignments; |
| 3255 if (is_lazily_compiled && pre_data() != NULL) { | 3509 if (is_lazily_compiled && pre_data() != NULL) { |
| 3256 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); | 3510 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); |
| 3257 if (!entry.is_valid()) { | 3511 if (!entry.is_valid()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3277 materialized_literal_count = temp_scope.materialized_literal_count(); | 3531 materialized_literal_count = temp_scope.materialized_literal_count(); |
| 3278 expected_property_count = temp_scope.expected_property_count(); | 3532 expected_property_count = temp_scope.expected_property_count(); |
| 3279 only_simple_this_property_assignments = | 3533 only_simple_this_property_assignments = |
| 3280 temp_scope.only_simple_this_property_assignments(); | 3534 temp_scope.only_simple_this_property_assignments(); |
| 3281 this_property_assignments = temp_scope.this_property_assignments(); | 3535 this_property_assignments = temp_scope.this_property_assignments(); |
| 3282 | 3536 |
| 3283 Expect(Token::RBRACE, CHECK_OK); | 3537 Expect(Token::RBRACE, CHECK_OK); |
| 3284 end_pos = scanner().location().end_pos; | 3538 end_pos = scanner().location().end_pos; |
| 3285 } | 3539 } |
| 3286 | 3540 |
| 3541 // Validate strict mode. |
| 3542 if (temp_scope_->StrictMode()) { |
| 3543 if (IsEvalOrArguments(name)) { |
| 3544 int position = function_token_position != RelocInfo::kNoPosition |
| 3545 ? function_token_position |
| 3546 : (start_pos > 0 ? start_pos - 1 : start_pos); |
| 3547 ReportMessageAt(Scanner::Location(position, start_pos), |
| 3548 "strict_function_name", Vector<const char*>::empty()); |
| 3549 *ok = false; |
| 3550 return NULL; |
| 3551 } |
| 3552 if (name_loc.IsValid()) { |
| 3553 ReportMessageAt(name_loc, "strict_param_name", |
| 3554 Vector<const char*>::empty()); |
| 3555 *ok = false; |
| 3556 return NULL; |
| 3557 } |
| 3558 if (dupe_loc.IsValid()) { |
| 3559 ReportMessageAt(dupe_loc, "strict_param_dupe", |
| 3560 Vector<const char*>::empty()); |
| 3561 *ok = false; |
| 3562 return NULL; |
| 3563 } |
| 3564 CheckOctalLiteral(start_pos, end_pos, CHECK_OK); |
| 3565 } |
| 3566 |
| 3287 FunctionLiteral* function_literal = | 3567 FunctionLiteral* function_literal = |
| 3288 new FunctionLiteral(name, | 3568 new FunctionLiteral(name, |
| 3289 top_scope_, | 3569 top_scope_, |
| 3290 body, | 3570 body, |
| 3291 materialized_literal_count, | 3571 materialized_literal_count, |
| 3292 expected_property_count, | 3572 expected_property_count, |
| 3293 only_simple_this_property_assignments, | 3573 only_simple_this_property_assignments, |
| 3294 this_property_assignments, | 3574 this_property_assignments, |
| 3295 num_parameters, | 3575 num_parameters, |
| 3296 start_pos, | 3576 start_pos, |
| 3297 end_pos, | 3577 end_pos, |
| 3298 function_name->length() > 0, | 3578 function_name->length() > 0, |
| 3299 temp_scope.ContainsLoops()); | 3579 temp_scope.ContainsLoops(), |
| 3580 temp_scope.StrictMode()); |
| 3300 function_literal->set_function_token_position(function_token_position); | 3581 function_literal->set_function_token_position(function_token_position); |
| 3301 | 3582 |
| 3302 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); | 3583 if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal); |
| 3303 return function_literal; | 3584 return function_literal; |
| 3304 } | 3585 } |
| 3305 } | 3586 } |
| 3306 | 3587 |
| 3307 | 3588 |
| 3308 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 3589 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
| 3309 // CallRuntime :: | 3590 // CallRuntime :: |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3419 Handle<String> Parser::ParseIdentifierName(bool* ok) { | 3700 Handle<String> Parser::ParseIdentifierName(bool* ok) { |
| 3420 Token::Value next = Next(); | 3701 Token::Value next = Next(); |
| 3421 if (next != Token::IDENTIFIER && !Token::IsKeyword(next)) { | 3702 if (next != Token::IDENTIFIER && !Token::IsKeyword(next)) { |
| 3422 ReportUnexpectedToken(next); | 3703 ReportUnexpectedToken(next); |
| 3423 *ok = false; | 3704 *ok = false; |
| 3424 return Handle<String>(); | 3705 return Handle<String>(); |
| 3425 } | 3706 } |
| 3426 return GetSymbol(ok); | 3707 return GetSymbol(ok); |
| 3427 } | 3708 } |
| 3428 | 3709 |
| 3710 // Checks whether octal literal last seen is between beg_pos and end_pos. |
| 3711 // If so, reports an error. |
| 3712 void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
| 3713 int octal = scanner().octal_position(); |
| 3714 if (beg_pos <= octal && octal <= end_pos) { |
| 3715 ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal", |
| 3716 Vector<const char*>::empty()); |
| 3717 scanner().clear_octal_position(); |
| 3718 *ok = false; |
| 3719 } |
| 3720 } |
| 3721 |
| 3429 | 3722 |
| 3430 // This function reads an identifier and determines whether or not it | 3723 // This function reads an identifier and determines whether or not it |
| 3431 // is 'get' or 'set'. The reason for not using ParseIdentifier and | 3724 // is 'get' or 'set'. The reason for not using ParseIdentifier and |
| 3432 // checking on the output is that this involves heap allocation which | 3725 // checking on the output is that this involves heap allocation which |
| 3433 // we can't do during preparsing. | 3726 // we can't do during preparsing. |
| 3434 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, | 3727 Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, |
| 3435 bool* is_set, | 3728 bool* is_set, |
| 3436 bool* ok) { | 3729 bool* ok) { |
| 3437 Expect(Token::IDENTIFIER, ok); | 3730 Expect(Token::IDENTIFIER, ok); |
| 3438 if (!*ok) return Handle<String>(); | 3731 if (!*ok) return Handle<String>(); |
| (...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4700 Handle<String> source = Handle<String>(String::cast(script->source())); | 4993 Handle<String> source = Handle<String>(String::cast(script->source())); |
| 4701 result = parser.ParseProgram(source, info->is_global()); | 4994 result = parser.ParseProgram(source, info->is_global()); |
| 4702 } | 4995 } |
| 4703 } | 4996 } |
| 4704 | 4997 |
| 4705 info->SetFunction(result); | 4998 info->SetFunction(result); |
| 4706 return (result != NULL); | 4999 return (result != NULL); |
| 4707 } | 5000 } |
| 4708 | 5001 |
| 4709 } } // namespace v8::internal | 5002 } } // namespace v8::internal |
| OLD | NEW |