| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 10 matching lines...) Expand all Loading... |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_PREPARSER_H | 28 #ifndef V8_PREPARSER_H |
| 29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
| 30 | 30 |
| 31 #include "func-name-inferrer.h" |
| 31 #include "hashmap.h" | 32 #include "hashmap.h" |
| 32 #include "scopes.h" | 33 #include "scopes.h" |
| 33 #include "token.h" | 34 #include "token.h" |
| 34 #include "scanner.h" | 35 #include "scanner.h" |
| 35 #include "v8.h" | 36 #include "v8.h" |
| 36 | 37 |
| 37 namespace v8 { | 38 namespace v8 { |
| 38 namespace internal { | 39 namespace internal { |
| 39 | 40 |
| 40 // Common base class shared between parser and pre-parser. | 41 // Common base class shared between parser and pre-parser. |
| 41 template <typename Traits> | 42 template <typename Traits> |
| 42 class ParserBase : public Traits { | 43 class ParserBase : public Traits { |
| 43 public: | 44 public: |
| 44 ParserBase(Scanner* scanner, uintptr_t stack_limit, | 45 ParserBase(Scanner* scanner, uintptr_t stack_limit, |
| 45 v8::Extension* extension, | 46 v8::Extension* extension, |
| 46 typename Traits::Type::Zone* zone, | 47 typename Traits::Type::Zone* zone, |
| 47 typename Traits::Type::Parser this_object) | 48 typename Traits::Type::Parser this_object) |
| 48 : Traits(this_object), | 49 : Traits(this_object), |
| 49 parenthesized_function_(false), | 50 parenthesized_function_(false), |
| 50 scope_(NULL), | 51 scope_(NULL), |
| 51 function_state_(NULL), | 52 function_state_(NULL), |
| 52 extension_(extension), | 53 extension_(extension), |
| 54 fni_(NULL), |
| 53 scanner_(scanner), | 55 scanner_(scanner), |
| 54 stack_limit_(stack_limit), | 56 stack_limit_(stack_limit), |
| 55 stack_overflow_(false), | 57 stack_overflow_(false), |
| 56 allow_lazy_(false), | 58 allow_lazy_(false), |
| 57 allow_natives_syntax_(false), | 59 allow_natives_syntax_(false), |
| 58 allow_generators_(false), | 60 allow_generators_(false), |
| 59 allow_for_of_(false), | 61 allow_for_of_(false), |
| 60 zone_(zone) { } | 62 zone_(zone) { } |
| 61 | 63 |
| 62 // Getters that indicate whether certain syntactical constructs are | 64 // Getters that indicate whether certain syntactical constructs are |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 AllowEvalOrArgumentsAsIdentifier, | 325 AllowEvalOrArgumentsAsIdentifier, |
| 324 bool* ok); | 326 bool* ok); |
| 325 // Parses an identifier or a strict mode future reserved word, and indicate | 327 // Parses an identifier or a strict mode future reserved word, and indicate |
| 326 // whether it is strict mode future reserved. | 328 // whether it is strict mode future reserved. |
| 327 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord( | 329 typename Traits::Type::Identifier ParseIdentifierOrStrictReservedWord( |
| 328 bool* is_strict_reserved, | 330 bool* is_strict_reserved, |
| 329 bool* ok); | 331 bool* ok); |
| 330 typename Traits::Type::Identifier ParseIdentifierName(bool* ok); | 332 typename Traits::Type::Identifier ParseIdentifierName(bool* ok); |
| 331 // Parses an identifier and determines whether or not it is 'get' or 'set'. | 333 // Parses an identifier and determines whether or not it is 'get' or 'set'. |
| 332 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, | 334 typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, |
| 333 bool* is_set, | 335 bool* is_set, |
| 334 bool* ok); | 336 bool* ok); |
| 335 | 337 |
| 336 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal, | 338 typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal, |
| 337 bool* ok); | 339 bool* ok); |
| 338 | 340 |
| 339 typename Traits::Type::Expression ParsePrimaryExpression(bool* ok); | 341 typename Traits::Type::Expression ParsePrimaryExpression(bool* ok); |
| 340 typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok); | 342 typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok); |
| 341 typename Traits::Type::Expression ParseArrayLiteral(bool* ok); | 343 typename Traits::Type::Expression ParseArrayLiteral(bool* ok); |
| 344 typename Traits::Type::Expression ParseObjectLiteral(bool* ok); |
| 342 | 345 |
| 343 // Used to detect duplicates in object literals. Each of the values | 346 // Used to detect duplicates in object literals. Each of the values |
| 344 // kGetterProperty, kSetterProperty and kValueProperty represents | 347 // kGetterProperty, kSetterProperty and kValueProperty represents |
| 345 // a type of object literal property. When parsing a property, its | 348 // a type of object literal property. When parsing a property, its |
| 346 // type value is stored in the DuplicateFinder for the property name. | 349 // type value is stored in the DuplicateFinder for the property name. |
| 347 // Values are chosen so that having intersection bits means the there is | 350 // Values are chosen so that having intersection bits means the there is |
| 348 // an incompatibility. | 351 // an incompatibility. |
| 349 // I.e., you can add a getter to a property that already has a setter, since | 352 // I.e., you can add a getter to a property that already has a setter, since |
| 350 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | 353 // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
| 351 // already has a getter or a value. Adding the getter to an existing | 354 // already has a getter or a value. Adding the getter to an existing |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 | 399 |
| 397 // If true, the next (and immediately following) function literal is | 400 // If true, the next (and immediately following) function literal is |
| 398 // preceded by a parenthesis. | 401 // preceded by a parenthesis. |
| 399 // Heuristically that means that the function will be called immediately, | 402 // Heuristically that means that the function will be called immediately, |
| 400 // so never lazily compile it. | 403 // so never lazily compile it. |
| 401 bool parenthesized_function_; | 404 bool parenthesized_function_; |
| 402 | 405 |
| 403 typename Traits::Type::Scope* scope_; // Scope stack. | 406 typename Traits::Type::Scope* scope_; // Scope stack. |
| 404 FunctionState* function_state_; // Function state stack. | 407 FunctionState* function_state_; // Function state stack. |
| 405 v8::Extension* extension_; | 408 v8::Extension* extension_; |
| 409 FuncNameInferrer* fni_; |
| 406 | 410 |
| 407 private: | 411 private: |
| 408 Scanner* scanner_; | 412 Scanner* scanner_; |
| 409 uintptr_t stack_limit_; | 413 uintptr_t stack_limit_; |
| 410 bool stack_overflow_; | 414 bool stack_overflow_; |
| 411 | 415 |
| 412 bool allow_lazy_; | 416 bool allow_lazy_; |
| 413 bool allow_natives_syntax_; | 417 bool allow_natives_syntax_; |
| 414 bool allow_generators_; | 418 bool allow_generators_; |
| 415 bool allow_for_of_; | 419 bool allow_for_of_; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 PreParserExpression NewBinaryOperation(Token::Value op, | 603 PreParserExpression NewBinaryOperation(Token::Value op, |
| 600 PreParserExpression left, | 604 PreParserExpression left, |
| 601 PreParserExpression right, int pos) { | 605 PreParserExpression right, int pos) { |
| 602 return PreParserExpression::Default(); | 606 return PreParserExpression::Default(); |
| 603 } | 607 } |
| 604 PreParserExpression NewArrayLiteral(PreParserExpressionList values, | 608 PreParserExpression NewArrayLiteral(PreParserExpressionList values, |
| 605 int literal_index, | 609 int literal_index, |
| 606 int pos) { | 610 int pos) { |
| 607 return PreParserExpression::Default(); | 611 return PreParserExpression::Default(); |
| 608 } | 612 } |
| 613 |
| 614 PreParserExpression NewObjectLiteralProperty(bool is_getter, |
| 615 PreParserExpression value, |
| 616 int pos) { |
| 617 return PreParserExpression::Default(); |
| 618 } |
| 619 |
| 620 PreParserExpression NewObjectLiteralProperty(PreParserExpression key, |
| 621 PreParserExpression value) { |
| 622 return PreParserExpression::Default(); |
| 623 } |
| 624 |
| 625 PreParserExpression NewObjectLiteral(PreParserExpressionList properties, |
| 626 int literal_index, |
| 627 int boilerplate_properties, |
| 628 bool has_function, |
| 629 int pos) { |
| 630 return PreParserExpression::Default(); |
| 631 } |
| 632 |
| 633 PreParserExpression NewLiteral(PreParserIdentifier identifier, |
| 634 int pos) { |
| 635 return PreParserExpression::Default(); |
| 636 } |
| 637 |
| 638 PreParserExpression NewNumberLiteral(double number, |
| 639 int pos) { |
| 640 return PreParserExpression::Default(); |
| 641 } |
| 609 }; | 642 }; |
| 610 | 643 |
| 611 | 644 |
| 612 class PreParser; | 645 class PreParser; |
| 613 | 646 |
| 614 class PreParserTraits { | 647 class PreParserTraits { |
| 615 public: | 648 public: |
| 616 struct Type { | 649 struct Type { |
| 617 typedef PreParser* Parser; | 650 typedef PreParser* Parser; |
| 618 | 651 |
| 619 // Types used by FunctionState and BlockState. | 652 // Types used by FunctionState and BlockState. |
| 620 typedef PreParserScope Scope; | 653 typedef PreParserScope Scope; |
| 621 typedef PreParserFactory Factory; | 654 typedef PreParserFactory Factory; |
| 622 // PreParser doesn't need to store generator variables. | 655 // PreParser doesn't need to store generator variables. |
| 623 typedef void GeneratorVariable; | 656 typedef void GeneratorVariable; |
| 624 // No interaction with Zones. | 657 // No interaction with Zones. |
| 625 typedef void Zone; | 658 typedef void Zone; |
| 626 | 659 |
| 627 // Return types for traversing functions. | 660 // Return types for traversing functions. |
| 628 typedef PreParserIdentifier Identifier; | 661 typedef PreParserIdentifier Identifier; |
| 629 typedef PreParserExpression Expression; | 662 typedef PreParserExpression Expression; |
| 663 typedef PreParserExpression FunctionLiteral; |
| 664 typedef PreParserExpression ObjectLiteralProperty; |
| 665 typedef PreParserExpression Literal; |
| 630 typedef PreParserExpressionList ExpressionList; | 666 typedef PreParserExpressionList ExpressionList; |
| 667 typedef PreParserExpressionList PropertyList; |
| 631 }; | 668 }; |
| 632 | 669 |
| 633 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} | 670 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} |
| 634 | 671 |
| 635 // Custom operations executed when FunctionStates are created and | 672 // Custom operations executed when FunctionStates are created and |
| 636 // destructed. (The PreParser doesn't need to do anything.) | 673 // destructed. (The PreParser doesn't need to do anything.) |
| 637 template<typename FunctionState> | 674 template<typename FunctionState> |
| 638 static void SetUpFunctionState(FunctionState* function_state, void*) {} | 675 static void SetUpFunctionState(FunctionState* function_state, void*) {} |
| 639 template<typename FunctionState> | 676 template<typename FunctionState> |
| 640 static void TearDownFunctionState(FunctionState* function_state) {} | 677 static void TearDownFunctionState(FunctionState* function_state) {} |
| 641 | 678 |
| 642 // Helper functions for recursive descent. | 679 // Helper functions for recursive descent. |
| 643 static bool IsEvalOrArguments(PreParserIdentifier identifier) { | 680 static bool IsEvalOrArguments(PreParserIdentifier identifier) { |
| 644 return identifier.IsEvalOrArguments(); | 681 return identifier.IsEvalOrArguments(); |
| 645 } | 682 } |
| 646 | 683 |
| 684 static bool IsBoilerplateProperty(PreParserExpression property) { |
| 685 // PreParser doesn't count boilerplate properties. |
| 686 return false; |
| 687 } |
| 688 |
| 689 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) { |
| 690 return false; |
| 691 } |
| 692 |
| 693 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) { |
| 694 // PreParser should not use FuncNameInferrer. |
| 695 ASSERT(false); |
| 696 } |
| 697 |
| 698 static void CheckFunctionLiteralInsideTopLevelObjectLiteral( |
| 699 PreParserScope* scope, PreParserExpression value, bool* has_function) {} |
| 700 |
| 647 // Reporting errors. | 701 // Reporting errors. |
| 648 void ReportMessageAt(Scanner::Location location, | 702 void ReportMessageAt(Scanner::Location location, |
| 649 const char* message, | 703 const char* message, |
| 650 Vector<const char*> args); | 704 Vector<const char*> args); |
| 651 void ReportMessageAt(Scanner::Location location, | 705 void ReportMessageAt(Scanner::Location location, |
| 652 const char* type, | 706 const char* type, |
| 653 const char* name_opt); | 707 const char* name_opt); |
| 654 void ReportMessageAt(int start_pos, | 708 void ReportMessageAt(int start_pos, |
| 655 int end_pos, | 709 int end_pos, |
| 656 const char* type, | 710 const char* type, |
| 657 const char* name_opt); | 711 const char* name_opt); |
| 658 | 712 |
| 659 // "null" return type creators. | 713 // "null" return type creators. |
| 660 static PreParserIdentifier EmptyIdentifier() { | 714 static PreParserIdentifier EmptyIdentifier() { |
| 661 return PreParserIdentifier::Default(); | 715 return PreParserIdentifier::Default(); |
| 662 } | 716 } |
| 663 static PreParserExpression EmptyExpression() { | 717 static PreParserExpression EmptyExpression() { |
| 664 return PreParserExpression::Default(); | 718 return PreParserExpression::Default(); |
| 665 } | 719 } |
| 720 static PreParserExpression EmptyLiteral() { |
| 721 return PreParserExpression::Default(); |
| 722 } |
| 666 | 723 |
| 667 // Odd-ball literal creators. | 724 // Odd-ball literal creators. |
| 668 static PreParserExpression GetLiteralTheHole(int position, | 725 static PreParserExpression GetLiteralTheHole(int position, |
| 669 PreParserFactory* factory) { | 726 PreParserFactory* factory) { |
| 670 return PreParserExpression::Default(); | 727 return PreParserExpression::Default(); |
| 671 } | 728 } |
| 672 | 729 |
| 673 // Producing data during the recursive descent. | 730 // Producing data during the recursive descent. |
| 674 PreParserIdentifier GetSymbol(Scanner* scanner); | 731 PreParserIdentifier GetSymbol(Scanner* scanner); |
| 675 static PreParserIdentifier NextLiteralString(Scanner* scanner, | 732 static PreParserIdentifier NextLiteralString(Scanner* scanner, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 695 } | 752 } |
| 696 | 753 |
| 697 PreParserExpression ExpressionFromString(int pos, | 754 PreParserExpression ExpressionFromString(int pos, |
| 698 Scanner* scanner, | 755 Scanner* scanner, |
| 699 PreParserFactory* factory = NULL); | 756 PreParserFactory* factory = NULL); |
| 700 | 757 |
| 701 static PreParserExpressionList NewExpressionList(int size, void* zone) { | 758 static PreParserExpressionList NewExpressionList(int size, void* zone) { |
| 702 return PreParserExpressionList(); | 759 return PreParserExpressionList(); |
| 703 } | 760 } |
| 704 | 761 |
| 762 static PreParserExpressionList NewPropertyList(int size, void* zone) { |
| 763 return PreParserExpressionList(); |
| 764 } |
| 765 |
| 705 // Temporary glue; these functions will move to ParserBase. | 766 // Temporary glue; these functions will move to ParserBase. |
| 706 PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok); | 767 PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok); |
| 707 PreParserExpression ParseObjectLiteral(bool* ok); | |
| 708 PreParserExpression ParseV8Intrinsic(bool* ok); | 768 PreParserExpression ParseV8Intrinsic(bool* ok); |
| 769 PreParserExpression ParseFunctionLiteral( |
| 770 PreParserIdentifier name, |
| 771 Scanner::Location function_name_location, |
| 772 bool name_is_strict_reserved, |
| 773 bool is_generator, |
| 774 int function_token_position, |
| 775 FunctionLiteral::FunctionType type, |
| 776 bool* ok); |
| 709 | 777 |
| 710 private: | 778 private: |
| 711 PreParser* pre_parser_; | 779 PreParser* pre_parser_; |
| 712 }; | 780 }; |
| 713 | 781 |
| 714 | 782 |
| 715 // Preparsing checks a JavaScript program and emits preparse-data that helps | 783 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 716 // a later parsing to be faster. | 784 // a later parsing to be faster. |
| 717 // See preparse-data-format.h for the data format. | 785 // See preparse-data-format.h for the data format. |
| 718 | 786 |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 } | 1291 } |
| 1224 } | 1292 } |
| 1225 Expect(Token::RBRACK, CHECK_OK); | 1293 Expect(Token::RBRACK, CHECK_OK); |
| 1226 | 1294 |
| 1227 // Update the scope information before the pre-parsing bailout. | 1295 // Update the scope information before the pre-parsing bailout. |
| 1228 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 1296 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
| 1229 | 1297 |
| 1230 return factory()->NewArrayLiteral(values, literal_index, pos); | 1298 return factory()->NewArrayLiteral(values, literal_index, pos); |
| 1231 } | 1299 } |
| 1232 | 1300 |
| 1301 |
| 1302 template <class Traits> |
| 1303 typename Traits::Type::Expression ParserBase<Traits>::ParseObjectLiteral( |
| 1304 bool* ok) { |
| 1305 // ObjectLiteral :: |
| 1306 // '{' (( |
| 1307 // ((IdentifierName | String | Number) ':' AssignmentExpression) | |
| 1308 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 1309 // ) ',')* '}' |
| 1310 // (Except that trailing comma is not required and not allowed.) |
| 1311 |
| 1312 int pos = peek_position(); |
| 1313 typename Traits::Type::PropertyList properties = |
| 1314 this->NewPropertyList(4, zone_); |
| 1315 int number_of_boilerplate_properties = 0; |
| 1316 bool has_function = false; |
| 1317 |
| 1318 ObjectLiteralChecker checker(this, strict_mode()); |
| 1319 |
| 1320 Expect(Token::LBRACE, CHECK_OK); |
| 1321 |
| 1322 while (peek() != Token::RBRACE) { |
| 1323 if (fni_ != NULL) fni_->Enter(); |
| 1324 |
| 1325 typename Traits::Type::Literal key = this->EmptyLiteral(); |
| 1326 Token::Value next = peek(); |
| 1327 int next_pos = peek_position(); |
| 1328 |
| 1329 switch (next) { |
| 1330 case Token::FUTURE_RESERVED_WORD: |
| 1331 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 1332 case Token::IDENTIFIER: { |
| 1333 bool is_getter = false; |
| 1334 bool is_setter = false; |
| 1335 typename Traits::Type::Identifier id = |
| 1336 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 1337 if (fni_ != NULL) this->PushLiteralName(fni_, id); |
| 1338 |
| 1339 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 1340 // Special handling of getter and setter syntax: |
| 1341 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
| 1342 // We have already read the "get" or "set" keyword. |
| 1343 Token::Value next = Next(); |
| 1344 if (next != i::Token::IDENTIFIER && |
| 1345 next != i::Token::FUTURE_RESERVED_WORD && |
| 1346 next != i::Token::FUTURE_STRICT_RESERVED_WORD && |
| 1347 next != i::Token::NUMBER && |
| 1348 next != i::Token::STRING && |
| 1349 !Token::IsKeyword(next)) { |
| 1350 ReportUnexpectedToken(next); |
| 1351 *ok = false; |
| 1352 return this->EmptyLiteral(); |
| 1353 } |
| 1354 // Validate the property. |
| 1355 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; |
| 1356 checker.CheckProperty(next, type, CHECK_OK); |
| 1357 typename Traits::Type::Identifier name = this->GetSymbol(scanner_); |
| 1358 typename Traits::Type::FunctionLiteral value = |
| 1359 this->ParseFunctionLiteral( |
| 1360 name, scanner()->location(), |
| 1361 false, // reserved words are allowed here |
| 1362 false, // not a generator |
| 1363 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
| 1364 CHECK_OK); |
| 1365 // Allow any number of parameters for compatibilty with JSC. |
| 1366 // Specification only allows zero parameters for get and one for set. |
| 1367 typename Traits::Type::ObjectLiteralProperty property = |
| 1368 factory()->NewObjectLiteralProperty(is_getter, value, next_pos); |
| 1369 if (this->IsBoilerplateProperty(property)) { |
| 1370 number_of_boilerplate_properties++; |
| 1371 } |
| 1372 properties->Add(property, zone()); |
| 1373 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 1374 |
| 1375 if (fni_ != NULL) { |
| 1376 fni_->Infer(); |
| 1377 fni_->Leave(); |
| 1378 } |
| 1379 continue; // restart the while |
| 1380 } |
| 1381 // Failed to parse as get/set property, so it's just a normal property |
| 1382 // (which might be called "get" or "set" or something else). |
| 1383 key = factory()->NewLiteral(id, next_pos); |
| 1384 break; |
| 1385 } |
| 1386 case Token::STRING: { |
| 1387 Consume(Token::STRING); |
| 1388 typename Traits::Type::Identifier string = this->GetSymbol(scanner_); |
| 1389 if (fni_ != NULL) this->PushLiteralName(fni_, string); |
| 1390 uint32_t index; |
| 1391 if (this->IsArrayIndex(string, &index)) { |
| 1392 key = factory()->NewNumberLiteral(index, next_pos); |
| 1393 break; |
| 1394 } |
| 1395 key = factory()->NewLiteral(string, next_pos); |
| 1396 break; |
| 1397 } |
| 1398 case Token::NUMBER: { |
| 1399 Consume(Token::NUMBER); |
| 1400 key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_, |
| 1401 factory()); |
| 1402 break; |
| 1403 } |
| 1404 default: |
| 1405 if (Token::IsKeyword(next)) { |
| 1406 Consume(next); |
| 1407 typename Traits::Type::Identifier string = this->GetSymbol(scanner_); |
| 1408 key = factory()->NewLiteral(string, next_pos); |
| 1409 } else { |
| 1410 Token::Value next = Next(); |
| 1411 ReportUnexpectedToken(next); |
| 1412 *ok = false; |
| 1413 return this->EmptyLiteral(); |
| 1414 } |
| 1415 } |
| 1416 |
| 1417 // Validate the property |
| 1418 checker.CheckProperty(next, kValueProperty, CHECK_OK); |
| 1419 |
| 1420 Expect(Token::COLON, CHECK_OK); |
| 1421 typename Traits::Type::Expression value = |
| 1422 this->ParseAssignmentExpression(true, CHECK_OK); |
| 1423 |
| 1424 typename Traits::Type::ObjectLiteralProperty property = |
| 1425 factory()->NewObjectLiteralProperty(key, value); |
| 1426 |
| 1427 // Mark top-level object literals that contain function literals and |
| 1428 // pretenure the literal so it can be added as a constant function |
| 1429 // property. (Parser only.) |
| 1430 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, |
| 1431 &has_function); |
| 1432 |
| 1433 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| 1434 if (this->IsBoilerplateProperty(property)) { |
| 1435 number_of_boilerplate_properties++; |
| 1436 } |
| 1437 properties->Add(property, zone()); |
| 1438 |
| 1439 // TODO(1240767): Consider allowing trailing comma. |
| 1440 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 1441 |
| 1442 if (fni_ != NULL) { |
| 1443 fni_->Infer(); |
| 1444 fni_->Leave(); |
| 1445 } |
| 1446 } |
| 1447 Expect(Token::RBRACE, CHECK_OK); |
| 1448 |
| 1449 // Computation of literal_index must happen before pre parse bailout. |
| 1450 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
| 1451 |
| 1452 return factory()->NewObjectLiteral(properties, |
| 1453 literal_index, |
| 1454 number_of_boilerplate_properties, |
| 1455 has_function, |
| 1456 pos); |
| 1457 } |
| 1458 |
| 1459 |
| 1460 |
| 1233 #undef CHECK_OK | 1461 #undef CHECK_OK |
| 1234 | 1462 |
| 1235 | 1463 |
| 1236 template <typename Traits> | 1464 template <typename Traits> |
| 1237 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | 1465 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( |
| 1238 Token::Value property, | 1466 Token::Value property, |
| 1239 PropertyKind type, | 1467 PropertyKind type, |
| 1240 bool* ok) { | 1468 bool* ok) { |
| 1241 int old; | 1469 int old; |
| 1242 if (property == Token::NUMBER) { | 1470 if (property == Token::NUMBER) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1264 "accessor_get_set"); | 1492 "accessor_get_set"); |
| 1265 } | 1493 } |
| 1266 *ok = false; | 1494 *ok = false; |
| 1267 } | 1495 } |
| 1268 } | 1496 } |
| 1269 | 1497 |
| 1270 | 1498 |
| 1271 } } // v8::internal | 1499 } } // v8::internal |
| 1272 | 1500 |
| 1273 #endif // V8_PREPARSER_H | 1501 #endif // V8_PREPARSER_H |
| OLD | NEW |