Revision: 19805
Author:   [email protected]
Date:     Tue Mar 11 15:40:41 2014 UTC
Log:      Move ParseObjectLiteral to ParserBase.

BUG=v8:3126
LOG=N
[email protected]

Review URL: https://codereview.chromium.org/192993002
http://code.google.com/p/v8/source/detail?r=19805

Modified:
 /branches/bleeding_edge/src/func-name-inferrer.h
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/src/preparser.cc
 /branches/bleeding_edge/src/preparser.h

=======================================
--- /branches/bleeding_edge/src/func-name-inferrer.h Mon Jun 11 12:42:31 2012 UTC +++ /branches/bleeding_edge/src/func-name-inferrer.h Tue Mar 11 15:40:41 2014 UTC
@@ -28,9 +28,13 @@
 #ifndef V8_FUNC_NAME_INFERRER_H_
 #define V8_FUNC_NAME_INFERRER_H_

+#include "handles.h"
+#include "zone.h"
+
 namespace v8 {
 namespace internal {

+class FunctionLiteral;
 class Isolate;

 // FuncNameInferrer is a stateful class that is used to perform name
=======================================
--- /branches/bleeding_edge/src/parser.cc       Tue Mar 11 14:41:22 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc       Tue Mar 11 15:40:41 2014 UTC
@@ -33,7 +33,6 @@
 #include "char-predicates-inl.h"
 #include "codegen.h"
 #include "compiler.h"
-#include "func-name-inferrer.h"
 #include "messages.h"
 #include "parser.h"
 #include "platform.h"
@@ -520,7 +519,7 @@
 }


-Expression* ParserTraits::ExpressionFromLiteral(
+Literal* ParserTraits::ExpressionFromLiteral(
     Token::Value token, int pos,
     Scanner* scanner,
     AstNodeFactory<AstConstructionVisitor>* factory) {
@@ -575,11 +574,6 @@
return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
                              RelocInfo::kNoPosition);
 }
-
-
-Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
-  return parser_->ParseObjectLiteral(ok);
-}


Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
@@ -590,6 +584,20 @@
 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
   return parser_->ParseV8Intrinsic(ok);
 }
+
+
+FunctionLiteral* ParserTraits::ParseFunctionLiteral(
+    Handle<String> name,
+    Scanner::Location function_name_location,
+    bool name_is_strict_reserved,
+    bool is_generator,
+    int function_token_position,
+    FunctionLiteral::FunctionType type,
+    bool* ok) {
+  return parser_->ParseFunctionLiteral(name, function_name_location,
+ name_is_strict_reserved, is_generator,
+                                       function_token_position, type, ok);
+}


 Parser::Parser(CompilationInfo* info)
@@ -606,7 +614,6 @@
       original_scope_(NULL),
       target_stack_(NULL),
       pre_parse_data_(NULL),
-      fni_(NULL),
       info_(info) {
   ASSERT(!script_.is_null());
   isolate_->set_ast_node_id(0);
@@ -3492,169 +3499,6 @@
Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
   return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
 }
-
-
-Expression* Parser::ParseObjectLiteral(bool* ok) {
-  // ObjectLiteral ::
-  // '{' ((
-  //       ((IdentifierName | String | Number) ':' AssignmentExpression) |
- // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
-  //      ) ',')* '}'
-  // (Except that trailing comma is not required and not allowed.)
-
-  int pos = peek_position();
-  ZoneList<ObjectLiteral::Property*>* properties =
-      new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
-  int number_of_boilerplate_properties = 0;
-  bool has_function = false;
-
-  ObjectLiteralChecker checker(this, strict_mode());
-
-  Expect(Token::LBRACE, CHECK_OK);
-
-  while (peek() != Token::RBRACE) {
-    if (fni_ != NULL) fni_->Enter();
-
-    Literal* key = NULL;
-    Token::Value next = peek();
-    int next_pos = peek_position();
-
-    switch (next) {
-      case Token::FUTURE_RESERVED_WORD:
-      case Token::FUTURE_STRICT_RESERVED_WORD:
-      case Token::IDENTIFIER: {
-        bool is_getter = false;
-        bool is_setter = false;
-        Handle<String> id =
- ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
-        if (fni_ != NULL) fni_->PushLiteralName(id);
-
-        if ((is_getter || is_setter) && peek() != Token::COLON) {
-          // Special handling of getter and setter syntax:
- // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
-          // We have already read the "get" or "set" keyword.
-          Token::Value next = Next();
-          if (next != i::Token::IDENTIFIER &&
-              next != i::Token::FUTURE_RESERVED_WORD &&
-              next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
-              next != i::Token::NUMBER &&
-              next != i::Token::STRING &&
-              !Token::IsKeyword(next)) {
-            ReportUnexpectedToken(next);
-            *ok = false;
-            return NULL;
-          }
-          // Validate the property.
- PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
-          checker.CheckProperty(next, type, CHECK_OK);
-          Handle<String> name = GetSymbol();
-          FunctionLiteral* value =
-              ParseFunctionLiteral(name,
-                                   scanner()->location(),
- false, // reserved words are allowed here
-                                   false,   // not a generator
-                                   RelocInfo::kNoPosition,
-                                   FunctionLiteral::ANONYMOUS_EXPRESSION,
-                                   CHECK_OK);
-          // Allow any number of parameters for compatibilty with JSC.
- // Specification only allows zero parameters for get and one for set.
-          ObjectLiteral::Property* property =
- factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
-          if (ObjectLiteral::IsBoilerplateProperty(property)) {
-            number_of_boilerplate_properties++;
-          }
-          properties->Add(property, zone());
-          if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
-          if (fni_ != NULL) {
-            fni_->Infer();
-            fni_->Leave();
-          }
-          continue;  // restart the while
-        }
- // Failed to parse as get/set property, so it's just a normal property
-        // (which might be called "get" or "set" or something else).
-        key = factory()->NewLiteral(id, next_pos);
-        break;
-      }
-      case Token::STRING: {
-        Consume(Token::STRING);
-        Handle<String> string = GetSymbol();
-        if (fni_ != NULL) fni_->PushLiteralName(string);
-        uint32_t index;
-        if (!string.is_null() && string->AsArrayIndex(&index)) {
-          key = factory()->NewNumberLiteral(index, next_pos);
-          break;
-        }
-        key = factory()->NewLiteral(string, next_pos);
-        break;
-      }
-      case Token::NUMBER: {
-        Consume(Token::NUMBER);
-        ASSERT(scanner()->is_literal_ascii());
-        double value = StringToDouble(isolate()->unicode_cache(),
-                                      scanner()->literal_ascii_string(),
-                                      ALLOW_HEX | ALLOW_OCTAL |
- ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
-        key = factory()->NewNumberLiteral(value, next_pos);
-        break;
-      }
-      default:
-        if (Token::IsKeyword(next)) {
-          Consume(next);
-          Handle<String> string = GetSymbol();
-          key = factory()->NewLiteral(string, next_pos);
-        } else {
-          Token::Value next = Next();
-          ReportUnexpectedToken(next);
-          *ok = false;
-          return NULL;
-        }
-    }
-
-    // Validate the property
-    checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
-    Expect(Token::COLON, CHECK_OK);
-    Expression* value = ParseAssignmentExpression(true, CHECK_OK);
-
-    ObjectLiteral::Property* property =
-        factory()->NewObjectLiteralProperty(key, value);
-
-    // Mark top-level object literals that contain function literals and
-    // pretenure the literal so it can be added as a constant function
-    // property.
-    if (scope_->DeclarationScope()->is_global_scope() &&
-        value->AsFunctionLiteral() != NULL) {
-      has_function = true;
-      value->AsFunctionLiteral()->set_pretenure();
-    }
-
- // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
-    if (ObjectLiteral::IsBoilerplateProperty(property)) {
-      number_of_boilerplate_properties++;
-    }
-    properties->Add(property, zone());
-
-    // TODO(1240767): Consider allowing trailing comma.
-    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
-    if (fni_ != NULL) {
-      fni_->Infer();
-      fni_->Leave();
-    }
-  }
-  Expect(Token::RBRACE, CHECK_OK);
-
-  // Computation of literal_index must happen before pre parse bailout.
-  int literal_index = function_state_->NextMaterializedLiteralIndex();
-
-  return factory()->NewObjectLiteral(properties,
-                                     literal_index,
-                                     number_of_boilerplate_properties,
-                                     has_function,
-                                     pos);
-}


 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
=======================================
--- /branches/bleeding_edge/src/parser.h        Tue Mar 11 14:41:22 2014 UTC
+++ /branches/bleeding_edge/src/parser.h        Tue Mar 11 15:40:41 2014 UTC
@@ -39,7 +39,6 @@
 namespace internal {

 class CompilationInfo;
-class FuncNameInferrer;
 class ParserLog;
 class PositionStack;
 class Target;
@@ -420,7 +419,11 @@
     // Return types for traversing functions.
     typedef Handle<String> Identifier;
     typedef v8::internal::Expression* Expression;
+    typedef v8::internal::FunctionLiteral* FunctionLiteral;
+    typedef v8::internal::Literal* Literal;
+    typedef ObjectLiteral::Property* ObjectLiteralProperty;
     typedef ZoneList<v8::internal::Expression*>* ExpressionList;
+    typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
   };

   explicit ParserTraits(Parser* parser) : parser_(parser) {}
@@ -445,6 +448,27 @@
   // Helper functions for recursive descent.
   bool IsEvalOrArguments(Handle<String> identifier) const;

+  static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
+    return ObjectLiteral::IsBoilerplateProperty(property);
+  }
+
+  static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
+    return !string.is_null() && string->AsArrayIndex(index);
+  }
+
+  static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+    fni->PushLiteralName(id);
+  }
+
+  static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+      Scope* scope, Expression* value, bool* has_function) {
+    if (scope->DeclarationScope()->is_global_scope() &&
+        value->AsFunctionLiteral() != NULL) {
+      *has_function = true;
+      value->AsFunctionLiteral()->set_pretenure();
+    }
+  }
+
   // Reporting errors.
   void ReportMessageAt(Scanner::Location source_location,
                        const char* message,
@@ -461,6 +485,9 @@
   static Expression* EmptyExpression() {
     return NULL;
   }
+  static Literal* EmptyLiteral() {
+    return NULL;
+  }

   // Odd-ball literal creators.
   Literal* GetLiteralTheHole(int position,
@@ -472,7 +499,7 @@
                                    PretenureFlag tenured);
   Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
-  Expression* ExpressionFromLiteral(
+  Literal* ExpressionFromLiteral(
       Token::Value token, int pos, Scanner* scanner,
       AstNodeFactory<AstConstructionVisitor>* factory);
   Expression* ExpressionFromIdentifier(
@@ -484,11 +511,21 @@
ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
     return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
   }
+ ZoneList<ObjectLiteral::Property*>* NewPropertyList(int size, Zone* zone) {
+    return new(zone) ZoneList<ObjectLiteral::Property*>(size, zone);
+  }

   // Temporary glue; these functions will move to ParserBase.
-  Expression* ParseObjectLiteral(bool* ok);
   Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
   Expression* ParseV8Intrinsic(bool* ok);
+  FunctionLiteral* ParseFunctionLiteral(
+      Handle<String> name,
+      Scanner::Location function_name_location,
+      bool name_is_strict_reserved,
+      bool is_generator,
+      int function_token_position,
+      FunctionLiteral::FunctionType type,
+      bool* ok);

  private:
   Parser* parser_;
@@ -749,7 +786,6 @@
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   Target* target_stack_;  // for break, continue statements
   ScriptDataImpl* pre_parse_data_;
-  FuncNameInferrer* fni_;

   Mode mode_;

=======================================
--- /branches/bleeding_edge/src/preparser.cc    Tue Mar 11 14:41:22 2014 UTC
+++ /branches/bleeding_edge/src/preparser.cc    Tue Mar 11 15:40:41 2014 UTC
@@ -120,11 +120,6 @@
   }
   return PreParserExpression::StringLiteral();
 }
-
-
-PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
-  return pre_parser_->ParseObjectLiteral(ok);
-}


PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN,
@@ -136,6 +131,20 @@
 PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
   return pre_parser_->ParseV8Intrinsic(ok);
 }
+
+
+PreParserExpression PreParserTraits::ParseFunctionLiteral(
+    PreParserIdentifier name,
+    Scanner::Location function_name_location,
+    bool name_is_strict_reserved,
+    bool is_generator,
+    int function_token_position,
+    FunctionLiteral::FunctionType type,
+    bool* ok) {
+  return pre_parser_->ParseFunctionLiteral(
+      name, function_name_location, name_is_strict_reserved, is_generator,
+      function_token_position, type, ok);
+}


 PreParser::PreParseResult PreParser::PreParseLazyFunction(
@@ -1124,91 +1133,6 @@
   ASSERT(false);
   return PreParserExpression::Default();
 }
-
-
-PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
-  // ObjectLiteral ::
-  // '{' ((
-  //       ((IdentifierName | String | Number) ':' AssignmentExpression) |
- // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
-  //      ) ',')* '}'
-  // (Except that trailing comma is not required and not allowed.)
-
-  ObjectLiteralChecker checker(this, strict_mode());
-
-  Expect(Token::LBRACE, CHECK_OK);
-  while (peek() != Token::RBRACE) {
-    Token::Value next = peek();
-    switch (next) {
-      case Token::IDENTIFIER:
-      case Token::FUTURE_RESERVED_WORD:
-      case Token::FUTURE_STRICT_RESERVED_WORD: {
-        bool is_getter = false;
-        bool is_setter = false;
-        ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
-        if ((is_getter || is_setter) && peek() != Token::COLON) {
-            Token::Value next = Next();
-            if (next != Token::IDENTIFIER &&
-                next != Token::FUTURE_RESERVED_WORD &&
-                next != Token::FUTURE_STRICT_RESERVED_WORD &&
-                next != Token::NUMBER &&
-                next != Token::STRING &&
-                !Token::IsKeyword(next)) {
-              ReportUnexpectedToken(next);
-              *ok = false;
-              return Expression::Default();
-            }
-            // Validate the property
- PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
-            checker.CheckProperty(next, type, CHECK_OK);
-            PreParserIdentifier name = GetSymbol(scanner());
-            ParseFunctionLiteral(name,
-                                 scanner()->location(),
-                                 false,  // reserved words are allowed here
-                                 false,  // not a generator
-                                 RelocInfo::kNoPosition,
-                                 FunctionLiteral::ANONYMOUS_EXPRESSION,
-                                 CHECK_OK);
-            if (peek() != Token::RBRACE) {
-              Expect(Token::COMMA, CHECK_OK);
-            }
-            continue;  // restart the while
-        }
-        break;
-      }
-      case Token::STRING:
-        Consume(next);
-        LogSymbol();
-        break;
-      case Token::NUMBER:
-        Consume(next);
-        break;
-      default:
-        if (Token::IsKeyword(next)) {
-          Consume(next);
-          LogSymbol();
-        } else {
-          Token::Value next = Next();
-          ReportUnexpectedToken(next);
-          *ok = false;
-          return Expression::Default();
-        }
-    }
-
-    // Validate the property
-    checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
-    Expect(Token::COLON, CHECK_OK);
-    ParseAssignmentExpression(true, CHECK_OK);
-
-    // TODO(1240767): Consider allowing trailing comma.
-    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-  }
-  Expect(Token::RBRACE, CHECK_OK);
-
-  function_state_->NextMaterializedLiteralIndex();
-  return Expression::Default();
-}


 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
=======================================
--- /branches/bleeding_edge/src/preparser.h     Tue Mar 11 14:41:22 2014 UTC
+++ /branches/bleeding_edge/src/preparser.h     Tue Mar 11 15:40:41 2014 UTC
@@ -28,6 +28,7 @@
 #ifndef V8_PREPARSER_H
 #define V8_PREPARSER_H

+#include "func-name-inferrer.h"
 #include "hashmap.h"
 #include "scopes.h"
 #include "token.h"
@@ -50,6 +51,7 @@
         scope_(NULL),
         function_state_(NULL),
         extension_(extension),
+        fni_(NULL),
         scanner_(scanner),
         stack_limit_(stack_limit),
         stack_overflow_(false),
@@ -330,8 +332,8 @@
   typename Traits::Type::Identifier ParseIdentifierName(bool* ok);
// Parses an identifier and determines whether or not it is 'get' or 'set'. typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, - bool* is_set,
-                                                                bool* ok);
+ bool* is_set, + bool* ok);

   typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
                                                        bool* ok);
@@ -339,6 +341,7 @@
   typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok);
   typename Traits::Type::Expression ParseArrayLiteral(bool* ok);
+  typename Traits::Type::Expression ParseObjectLiteral(bool* ok);

   // Used to detect duplicates in object literals. Each of the values
   // kGetterProperty, kSetterProperty and kValueProperty represents
@@ -403,6 +406,7 @@
   typename Traits::Type::Scope* scope_;  // Scope stack.
   FunctionState* function_state_;  // Function state stack.
   v8::Extension* extension_;
+  FuncNameInferrer* fni_;

  private:
   Scanner* scanner_;
@@ -606,6 +610,35 @@
                                       int pos) {
     return PreParserExpression::Default();
   }
+
+  PreParserExpression NewObjectLiteralProperty(bool is_getter,
+                                               PreParserExpression value,
+                                               int pos) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
+                                               PreParserExpression value) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
+                                       int literal_index,
+                                       int boilerplate_properties,
+                                       bool has_function,
+                                       int pos) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewLiteral(PreParserIdentifier identifier,
+                                 int pos) {
+    return PreParserExpression::Default();
+  }
+
+  PreParserExpression NewNumberLiteral(double number,
+                                       int pos) {
+    return PreParserExpression::Default();
+  }
 };


@@ -627,7 +660,11 @@
     // Return types for traversing functions.
     typedef PreParserIdentifier Identifier;
     typedef PreParserExpression Expression;
+    typedef PreParserExpression FunctionLiteral;
+    typedef PreParserExpression ObjectLiteralProperty;
+    typedef PreParserExpression Literal;
     typedef PreParserExpressionList ExpressionList;
+    typedef PreParserExpressionList PropertyList;
   };

explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
@@ -643,6 +680,23 @@
   static bool IsEvalOrArguments(PreParserIdentifier identifier) {
     return identifier.IsEvalOrArguments();
   }
+
+  static bool IsBoilerplateProperty(PreParserExpression property) {
+    // PreParser doesn't count boilerplate properties.
+    return false;
+  }
+
+  static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
+    return false;
+  }
+
+ static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
+    // PreParser should not use FuncNameInferrer.
+    ASSERT(false);
+  }
+
+  static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+ PreParserScope* scope, PreParserExpression value, bool* has_function) {}

   // Reporting errors.
   void ReportMessageAt(Scanner::Location location,
@@ -663,6 +717,9 @@
   static PreParserExpression EmptyExpression() {
     return PreParserExpression::Default();
   }
+  static PreParserExpression EmptyLiteral() {
+    return PreParserExpression::Default();
+  }

   // Odd-ball literal creators.
   static PreParserExpression GetLiteralTheHole(int position,
@@ -701,11 +758,22 @@
   static PreParserExpressionList NewExpressionList(int size, void* zone) {
     return PreParserExpressionList();
   }
+
+  static PreParserExpressionList NewPropertyList(int size, void* zone) {
+    return PreParserExpressionList();
+  }

   // Temporary glue; these functions will move to ParserBase.
   PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok);
-  PreParserExpression ParseObjectLiteral(bool* ok);
   PreParserExpression ParseV8Intrinsic(bool* ok);
+  PreParserExpression ParseFunctionLiteral(
+      PreParserIdentifier name,
+      Scanner::Location function_name_location,
+      bool name_is_strict_reserved,
+      bool is_generator,
+      int function_token_position,
+      FunctionLiteral::FunctionType type,
+      bool* ok);

  private:
   PreParser* pre_parser_;
@@ -1229,6 +1297,166 @@

   return factory()->NewArrayLiteral(values, literal_index, pos);
 }
+
+
+template <class Traits>
+typename Traits::Type::Expression ParserBase<Traits>::ParseObjectLiteral(
+    bool* ok) {
+  // ObjectLiteral ::
+  // '{' ((
+  //       ((IdentifierName | String | Number) ':' AssignmentExpression) |
+ // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
+  //      ) ',')* '}'
+  // (Except that trailing comma is not required and not allowed.)
+
+  int pos = peek_position();
+  typename Traits::Type::PropertyList properties =
+      this->NewPropertyList(4, zone_);
+  int number_of_boilerplate_properties = 0;
+  bool has_function = false;
+
+  ObjectLiteralChecker checker(this, strict_mode());
+
+  Expect(Token::LBRACE, CHECK_OK);
+
+  while (peek() != Token::RBRACE) {
+    if (fni_ != NULL) fni_->Enter();
+
+    typename Traits::Type::Literal key = this->EmptyLiteral();
+    Token::Value next = peek();
+    int next_pos = peek_position();
+
+    switch (next) {
+      case Token::FUTURE_RESERVED_WORD:
+      case Token::FUTURE_STRICT_RESERVED_WORD:
+      case Token::IDENTIFIER: {
+        bool is_getter = false;
+        bool is_setter = false;
+        typename Traits::Type::Identifier id =
+ ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
+        if (fni_ != NULL) this->PushLiteralName(fni_, id);
+
+        if ((is_getter || is_setter) && peek() != Token::COLON) {
+          // Special handling of getter and setter syntax:
+ // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
+          // We have already read the "get" or "set" keyword.
+          Token::Value next = Next();
+          if (next != i::Token::IDENTIFIER &&
+              next != i::Token::FUTURE_RESERVED_WORD &&
+              next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
+              next != i::Token::NUMBER &&
+              next != i::Token::STRING &&
+              !Token::IsKeyword(next)) {
+            ReportUnexpectedToken(next);
+            *ok = false;
+            return this->EmptyLiteral();
+          }
+          // Validate the property.
+ PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
+          checker.CheckProperty(next, type, CHECK_OK);
+ typename Traits::Type::Identifier name = this->GetSymbol(scanner_);
+          typename Traits::Type::FunctionLiteral value =
+              this->ParseFunctionLiteral(
+                  name, scanner()->location(),
+                  false,  // reserved words are allowed here
+                  false,  // not a generator
+ RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
+                  CHECK_OK);
+          // Allow any number of parameters for compatibilty with JSC.
+ // Specification only allows zero parameters for get and one for set.
+          typename Traits::Type::ObjectLiteralProperty property =
+ factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+          if (this->IsBoilerplateProperty(property)) {
+            number_of_boilerplate_properties++;
+          }
+          properties->Add(property, zone());
+          if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+
+          if (fni_ != NULL) {
+            fni_->Infer();
+            fni_->Leave();
+          }
+          continue;  // restart the while
+        }
+ // Failed to parse as get/set property, so it's just a normal property
+        // (which might be called "get" or "set" or something else).
+        key = factory()->NewLiteral(id, next_pos);
+        break;
+      }
+      case Token::STRING: {
+        Consume(Token::STRING);
+ typename Traits::Type::Identifier string = this->GetSymbol(scanner_);
+        if (fni_ != NULL) this->PushLiteralName(fni_, string);
+        uint32_t index;
+        if (this->IsArrayIndex(string, &index)) {
+          key = factory()->NewNumberLiteral(index, next_pos);
+          break;
+        }
+        key = factory()->NewLiteral(string, next_pos);
+        break;
+      }
+      case Token::NUMBER: {
+        Consume(Token::NUMBER);
+ key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
+                                          factory());
+        break;
+      }
+      default:
+        if (Token::IsKeyword(next)) {
+          Consume(next);
+ typename Traits::Type::Identifier string = this->GetSymbol(scanner_);
+          key = factory()->NewLiteral(string, next_pos);
+        } else {
+          Token::Value next = Next();
+          ReportUnexpectedToken(next);
+          *ok = false;
+          return this->EmptyLiteral();
+        }
+    }
+
+    // Validate the property
+    checker.CheckProperty(next, kValueProperty, CHECK_OK);
+
+    Expect(Token::COLON, CHECK_OK);
+    typename Traits::Type::Expression value =
+        this->ParseAssignmentExpression(true, CHECK_OK);
+
+    typename Traits::Type::ObjectLiteralProperty property =
+        factory()->NewObjectLiteralProperty(key, value);
+
+    // Mark top-level object literals that contain function literals and
+    // pretenure the literal so it can be added as a constant function
+    // property. (Parser only.)
+    this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value,
+                                                          &has_function);
+
+ // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
+    if (this->IsBoilerplateProperty(property)) {
+      number_of_boilerplate_properties++;
+    }
+    properties->Add(property, zone());
+
+    // TODO(1240767): Consider allowing trailing comma.
+    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
+
+    if (fni_ != NULL) {
+      fni_->Infer();
+      fni_->Leave();
+    }
+  }
+  Expect(Token::RBRACE, CHECK_OK);
+
+  // Computation of literal_index must happen before pre parse bailout.
+  int literal_index = function_state_->NextMaterializedLiteralIndex();
+
+  return factory()->NewObjectLiteral(properties,
+                                     literal_index,
+                                     number_of_boilerplate_properties,
+                                     has_function,
+                                     pos);
+}
+
+

 #undef CHECK_OK

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to