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 |