| Index: src/preparser.h
 | 
| diff --git a/src/preparser.h b/src/preparser.h
 | 
| index b24c0728477a9a9bff8cabfb7c0d6a2d1188605d..0147caf5d134e312bc5fd49754d7c57c8d19f866 100644
 | 
| --- a/src/preparser.h
 | 
| +++ b/src/preparser.h
 | 
| @@ -46,6 +46,7 @@ namespace internal {
 | 
|  //     typedef Identifier;
 | 
|  //     typedef Expression;
 | 
|  //     typedef FunctionLiteral;
 | 
| +//     typedef ClassLiteral;
 | 
|  //     typedef ObjectLiteralProperty;
 | 
|  //     typedef Literal;
 | 
|  //     typedef ExpressionList;
 | 
| @@ -63,6 +64,7 @@ class ParserBase : public Traits {
 | 
|    typedef typename Traits::Type::Expression ExpressionT;
 | 
|    typedef typename Traits::Type::Identifier IdentifierT;
 | 
|    typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
 | 
| +  typedef typename Traits::Type::ClassLiteral ClassLiteralT;
 | 
|    typedef typename Traits::Type::Literal LiteralT;
 | 
|    typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
 | 
|  
 | 
| @@ -480,10 +482,12 @@ class ParserBase : public Traits {
 | 
|    ExpressionT ParsePrimaryExpression(bool* ok);
 | 
|    ExpressionT ParseExpression(bool accept_IN, bool* ok);
 | 
|    ExpressionT ParseArrayLiteral(bool* ok);
 | 
| +  IdentifierT ParsePropertyName(bool* is_get, bool* is_set, bool* is_static,
 | 
| +                                bool* ok);
 | 
|    ExpressionT ParseObjectLiteral(bool* ok);
 | 
|    ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
 | 
| +                                                 bool in_class, bool is_static,
 | 
|                                                   bool* ok);
 | 
| -  IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok);
 | 
|    typename Traits::Type::ExpressionList ParseArguments(bool* ok);
 | 
|    ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
 | 
|    ExpressionT ParseYieldExpression(bool* ok);
 | 
| @@ -498,6 +502,10 @@ class ParserBase : public Traits {
 | 
|                                                  bool* ok);
 | 
|    ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast,
 | 
|                                          bool* ok);
 | 
| +  ClassLiteralT ParseClassLiteral(IdentifierT name,
 | 
| +                                  Scanner::Location function_name_location,
 | 
| +                                  bool name_is_strict_reserved, int pos,
 | 
| +                                  bool* ok);
 | 
|  
 | 
|    // Checks if the expression is a valid reference expression (e.g., on the
 | 
|    // left-hand side of assignments). Although ruled out by ECMA as early errors,
 | 
| @@ -612,10 +620,20 @@ class PreParserIdentifier {
 | 
|    static PreParserIdentifier Yield() {
 | 
|      return PreParserIdentifier(kYieldIdentifier);
 | 
|    }
 | 
| +  static PreParserIdentifier Prototype() {
 | 
| +    return PreParserIdentifier(kPrototypeIdentifier);
 | 
| +  }
 | 
| +  static PreParserIdentifier Constructor() {
 | 
| +    return PreParserIdentifier(kConstructorIdentifier);
 | 
| +  }
 | 
|    bool IsEval() const { return type_ == kEvalIdentifier; }
 | 
|    bool IsArguments() const { return type_ == kArgumentsIdentifier; }
 | 
| -  bool IsEvalOrArguments() const { return type_ >= kEvalIdentifier; }
 | 
|    bool IsYield() const { return type_ == kYieldIdentifier; }
 | 
| +  bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
 | 
| +  bool IsConstructor() const { return type_ == kConstructorIdentifier; }
 | 
| +  bool IsEvalOrArguments() const {
 | 
| +    return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier;
 | 
| +  }
 | 
|    bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; }
 | 
|    bool IsFutureStrictReserved() const {
 | 
|      return type_ == kFutureStrictReservedIdentifier;
 | 
| @@ -638,7 +656,9 @@ class PreParserIdentifier {
 | 
|      kLetIdentifier,
 | 
|      kYieldIdentifier,
 | 
|      kEvalIdentifier,
 | 
| -    kArgumentsIdentifier
 | 
| +    kArgumentsIdentifier,
 | 
| +    kPrototypeIdentifier,
 | 
| +    kConstructorIdentifier
 | 
|    };
 | 
|    explicit PreParserIdentifier(Type type) : type_(type) {}
 | 
|    Type type_;
 | 
| @@ -927,6 +947,7 @@ class PreParserScope {
 | 
|    ScopeType type() { return scope_type_; }
 | 
|    StrictMode strict_mode() const { return strict_mode_; }
 | 
|    void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
 | 
| +  void SetScopeName(PreParserIdentifier name) {}
 | 
|  
 | 
|    // When PreParser is in use, lazy compilation is already being done,
 | 
|    // things cannot get lazier than that.
 | 
| @@ -971,11 +992,12 @@ class PreParserFactory {
 | 
|    }
 | 
|    PreParserExpression NewObjectLiteralProperty(bool is_getter,
 | 
|                                                 PreParserExpression value,
 | 
| -                                               int pos) {
 | 
| +                                               int pos, bool is_static) {
 | 
|      return PreParserExpression::Default();
 | 
|    }
 | 
|    PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
 | 
| -                                               PreParserExpression value) {
 | 
| +                                               PreParserExpression value,
 | 
| +                                               bool is_static) {
 | 
|      return PreParserExpression::Default();
 | 
|    }
 | 
|    PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
 | 
| @@ -985,7 +1007,7 @@ class PreParserFactory {
 | 
|                                         int pos) {
 | 
|      return PreParserExpression::Default();
 | 
|    }
 | 
| -  PreParserExpression NewVariableProxy(void* generator_variable) {
 | 
| +  PreParserExpression NewVariableProxy(void* variable) {
 | 
|      return PreParserExpression::Default();
 | 
|    }
 | 
|    PreParserExpression NewProperty(PreParserExpression obj,
 | 
| @@ -1061,6 +1083,14 @@ class PreParserFactory {
 | 
|        int position) {
 | 
|      return PreParserExpression::Default();
 | 
|    }
 | 
| +  PreParserExpression NewClassLiteral(PreParserIdentifier name,
 | 
| +                                      PreParserExpression extends,
 | 
| +                                      PreParserExpression constructor,
 | 
| +                                      PreParserExpressionList properties,
 | 
| +                                      AstValueFactory* ast_value_factory,
 | 
| +                                      int position) {
 | 
| +    return PreParserExpression::Default();
 | 
| +  }
 | 
|  
 | 
|    // Return the object itself as AstVisitor and implement the needed
 | 
|    // dummy method right in this class.
 | 
| @@ -1099,6 +1129,7 @@ class PreParserTraits {
 | 
|      typedef PreParserExpression Expression;
 | 
|      typedef PreParserExpression YieldExpression;
 | 
|      typedef PreParserExpression FunctionLiteral;
 | 
| +    typedef PreParserExpression ClassLiteral;
 | 
|      typedef PreParserExpression ObjectLiteralProperty;
 | 
|      typedef PreParserExpression Literal;
 | 
|      typedef PreParserExpressionList ExpressionList;
 | 
| @@ -1125,6 +1156,14 @@ class PreParserTraits {
 | 
|      return identifier.IsEvalOrArguments();
 | 
|    }
 | 
|  
 | 
| +  static bool IsPrototype(PreParserIdentifier identifier) {
 | 
| +    return identifier.IsPrototype();
 | 
| +  }
 | 
| +
 | 
| +  static bool IsConstructor(PreParserIdentifier identifier) {
 | 
| +    return identifier.IsConstructor();
 | 
| +  }
 | 
| +
 | 
|    // Returns true if the expression is of type "this.foo".
 | 
|    static bool IsThisProperty(PreParserExpression expression) {
 | 
|      return expression.IsThisProperty();
 | 
| @@ -1245,6 +1284,12 @@ class PreParserTraits {
 | 
|    static PreParserExpression EmptyObjectLiteralProperty() {
 | 
|      return PreParserExpression::Default();
 | 
|    }
 | 
| +  static PreParserExpression EmptyFunctionLiteral() {
 | 
| +    return PreParserExpression::Default();
 | 
| +  }
 | 
| +  static PreParserExpression EmptyClassLiteral() {
 | 
| +    return PreParserExpression::Default();
 | 
| +  }
 | 
|    static PreParserExpressionList NullExpressionList() {
 | 
|      return PreParserExpressionList();
 | 
|    }
 | 
| @@ -1435,6 +1480,7 @@ class PreParser : public ParserBase<PreParserTraits> {
 | 
|    SourceElements ParseSourceElements(int end_token, bool* ok);
 | 
|    Statement ParseStatement(bool* ok);
 | 
|    Statement ParseFunctionDeclaration(bool* ok);
 | 
| +  Statement ParseClassDeclaration(bool* ok);
 | 
|    Statement ParseBlock(bool* ok);
 | 
|    Statement ParseVariableStatement(VariableDeclarationContext var_context,
 | 
|                                     bool* ok);
 | 
| @@ -1708,6 +1754,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
 | 
|    //   ArrayLiteral
 | 
|    //   ObjectLiteral
 | 
|    //   RegExpLiteral
 | 
| +  //   ClassLiteral
 | 
|    //   '(' Expression ')'
 | 
|  
 | 
|    int pos = peek_position();
 | 
| @@ -1778,6 +1825,23 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
 | 
|        }
 | 
|        break;
 | 
|  
 | 
| +    case Token::CLASS: {
 | 
| +      Consume(Token::CLASS);
 | 
| +      int class_token_position = position();
 | 
| +      IdentifierT name = this->EmptyIdentifier();
 | 
| +      bool is_strict_reserved_name = false;
 | 
| +      Scanner::Location class_name_location = Scanner::Location::invalid();
 | 
| +      if (peek_any_identifier()) {
 | 
| +        name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
 | 
| +                                                   CHECK_OK);
 | 
| +        class_name_location = scanner()->location();
 | 
| +      }
 | 
| +      result = this->ParseClassLiteral(name, class_name_location,
 | 
| +                                       is_strict_reserved_name,
 | 
| +                                       class_token_position, CHECK_OK);
 | 
| +      break;
 | 
| +    }
 | 
| +
 | 
|      case Token::MOD:
 | 
|        if (allow_natives_syntax() || extension_ != NULL) {
 | 
|          result = this->ParseV8Intrinsic(CHECK_OK);
 | 
| @@ -1848,7 +1912,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
 | 
|  
 | 
|  template <class Traits>
 | 
|  typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
 | 
| -    bool* is_getter, bool* is_setter, bool* ok) {
 | 
| +    bool* is_get, bool* is_set, bool* is_static, bool* ok) {
 | 
|    Token::Value next = peek();
 | 
|    switch (next) {
 | 
|      case Token::STRING:
 | 
| @@ -1857,27 +1921,35 @@ typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
 | 
|      case Token::NUMBER:
 | 
|        Consume(Token::NUMBER);
 | 
|        return this->GetNumberAsSymbol(scanner_);
 | 
| +    case Token::STATIC:
 | 
| +      *is_static = true;
 | 
| +      // Fall through.
 | 
|      default:
 | 
| -      return ParseIdentifierNameOrGetOrSet(is_getter, is_setter,
 | 
| -                                           CHECK_OK_CUSTOM(EmptyIdentifier));
 | 
| +      return ParseIdentifierNameOrGetOrSet(is_get, is_set, ok);
 | 
|    }
 | 
| +  UNREACHABLE();
 | 
| +  return this->EmptyIdentifier();
 | 
|  }
 | 
|  
 | 
|  
 | 
|  template <class Traits>
 | 
|  typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
 | 
| -    Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
 | 
| +    Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
 | 
| +                                     bool in_class, bool is_static, bool* ok) {
 | 
|    // TODO(arv): Add support for concise generator methods.
 | 
|    ExpressionT value = this->EmptyExpression();
 | 
| -  bool is_getter = false;
 | 
| -  bool is_setter = false;
 | 
| +  bool is_get = false;
 | 
| +  bool is_set = false;
 | 
| +  bool name_is_static = false;
 | 
|    Token::Value name_token = peek();
 | 
|    int next_pos = peek_position();
 | 
| -  IdentifierT name = ParsePropertyName(
 | 
| -      &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
| +  IdentifierT name =
 | 
| +      ParsePropertyName(&is_get, &is_set, &name_is_static,
 | 
| +                        CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
| +
 | 
|    if (fni_ != NULL) this->PushLiteralName(fni_, name);
 | 
|  
 | 
| -  if (peek() == Token::COLON) {
 | 
| +  if (!in_class && peek() == Token::COLON) {
 | 
|      // PropertyDefinition : PropertyName ':' AssignmentExpression
 | 
|      checker->CheckProperty(name_token, kValueProperty,
 | 
|                             CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
| @@ -1887,6 +1959,13 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
 | 
|  
 | 
|    } else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
 | 
|      // Concise Method
 | 
| +
 | 
| +    if (is_static && this->IsPrototype(name)) {
 | 
| +      ReportMessageAt(scanner()->location(), "static_prototype");
 | 
| +      *ok = false;
 | 
| +      return this->EmptyObjectLiteralProperty();
 | 
| +    }
 | 
| +
 | 
|      checker->CheckProperty(name_token, kValueProperty,
 | 
|                             CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
|      value = this->ParseFunctionLiteral(
 | 
| @@ -1896,25 +1975,43 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
 | 
|          FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
 | 
|          CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
|  
 | 
| -  } else if (is_getter || is_setter) {
 | 
| +  } else if (in_class && name_is_static && !is_static) {
 | 
| +    // static MethodDefinition
 | 
| +    return ParsePropertyDefinition(checker, true, true, ok);
 | 
| +
 | 
| +  } else if (is_get || is_set) {
 | 
|      // Accessor
 | 
|      bool dont_care = false;
 | 
|      name_token = peek();
 | 
| -    name = ParsePropertyName(&dont_care, &dont_care,
 | 
| +    name = ParsePropertyName(&dont_care, &dont_care, &dont_care,
 | 
|                               CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
| +
 | 
|      // Validate the property.
 | 
| +    if (is_static && this->IsPrototype(name)) {
 | 
| +      ReportMessageAt(scanner()->location(), "static_prototype");
 | 
| +      *ok = false;
 | 
| +      return this->EmptyObjectLiteralProperty();
 | 
| +    } else if (in_class && !is_static && this->IsConstructor(name)) {
 | 
| +      // ES6, spec draft rev 27, treats static get constructor as an error too.
 | 
| +      // https://bugs.ecmascript.org/show_bug.cgi?id=3223
 | 
| +      // TODO(arv): Update when bug is resolved.
 | 
| +      ReportMessageAt(scanner()->location(), "constructor_special_method");
 | 
| +      *ok = false;
 | 
| +      return this->EmptyObjectLiteralProperty();
 | 
| +    }
 | 
|      checker->CheckProperty(name_token,
 | 
| -                           is_getter ? kGetterProperty : kSetterProperty,
 | 
| +                           is_get ? kGetterProperty : kSetterProperty,
 | 
|                             CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
| +
 | 
|      typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
 | 
|          name, scanner()->location(),
 | 
|          false,  // reserved words are allowed here
 | 
|          FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
 | 
|          FunctionLiteral::ANONYMOUS_EXPRESSION,
 | 
| -        is_getter ? FunctionLiteral::GETTER_ARITY
 | 
| -                  : FunctionLiteral::SETTER_ARITY,
 | 
| +        is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
 | 
|          CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 | 
| -    return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
 | 
| +    return factory()->NewObjectLiteralProperty(is_get, value, next_pos,
 | 
| +                                               is_static);
 | 
|    } else {
 | 
|      Token::Value next = Next();
 | 
|      ReportUnexpectedToken(next);
 | 
| @@ -1927,7 +2024,7 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
 | 
|                       ? factory()->NewNumberLiteral(index, next_pos)
 | 
|                       : factory()->NewStringLiteral(name, next_pos);
 | 
|  
 | 
| -  return factory()->NewObjectLiteralProperty(key, value);
 | 
| +  return factory()->NewObjectLiteralProperty(key, value, is_static);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1950,8 +2047,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
 | 
|    while (peek() != Token::RBRACE) {
 | 
|      if (fni_ != NULL) fni_->Enter();
 | 
|  
 | 
| +    const bool in_class = false;
 | 
| +    const bool is_static = false;
 | 
|      ObjectLiteralPropertyT property =
 | 
| -        this->ParsePropertyDefinition(&checker, CHECK_OK);
 | 
| +        this->ParsePropertyDefinition(&checker, in_class, is_static, CHECK_OK);
 | 
|  
 | 
|      // Mark top-level object literals that contain function literals and
 | 
|      // pretenure the literal so it can be added as a constant function
 | 
| @@ -2400,7 +2499,7 @@ template <class Traits>
 | 
|  typename ParserBase<Traits>::ExpressionT
 | 
|  ParserBase<Traits>::ParseMemberExpression(bool* ok) {
 | 
|    // MemberExpression ::
 | 
| -  //   (PrimaryExpression | FunctionLiteral)
 | 
| +  //   (PrimaryExpression | FunctionLiteral | ClassLiteral)
 | 
|    //     ('[' Expression ']' | '.' Identifier | Arguments)*
 | 
|  
 | 
|    // The '[' Expression ']' and '.' Identifier parts are parsed by
 | 
| @@ -2603,6 +2702,69 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
 | 
|  }
 | 
|  
 | 
|  
 | 
| +template <class Traits>
 | 
| +typename ParserBase<Traits>::ClassLiteralT
 | 
| +ParserBase<Traits>::ParseClassLiteral(IdentifierT name,
 | 
| +                                      Scanner::Location class_name_location,
 | 
| +                                      bool name_is_strict_reserved, int pos,
 | 
| +                                      bool* ok) {
 | 
| +  // All parts of a ClassDeclaration or a ClassExpression are strict code.
 | 
| +  if (name_is_strict_reserved) {
 | 
| +    ReportMessageAt(class_name_location, "unexpected_strict_reserved");
 | 
| +    *ok = false;
 | 
| +    return this->EmptyClassLiteral();
 | 
| +  }
 | 
| +  if (this->IsEvalOrArguments(name)) {
 | 
| +    ReportMessageAt(class_name_location, "strict_eval_arguments");
 | 
| +    *ok = false;
 | 
| +    return this->EmptyClassLiteral();
 | 
| +  }
 | 
| +
 | 
| +  // TODO(arv): Implement scopes and name binding in class body only.
 | 
| +  // TODO(arv): Maybe add CLASS_SCOPE?
 | 
| +  typename Traits::Type::ScopePtr extends_scope =
 | 
| +      this->NewScope(scope_, BLOCK_SCOPE);
 | 
| +  FunctionState extends_function_state(
 | 
| +      &function_state_, &scope_, &extends_scope, zone(),
 | 
| +      this->ast_value_factory(), ast_node_id_gen_);
 | 
| +  scope_->SetStrictMode(STRICT);
 | 
| +  scope_->SetScopeName(name);
 | 
| +
 | 
| +  ExpressionT extends = this->EmptyExpression();
 | 
| +  if (Check(Token::EXTENDS)) {
 | 
| +    extends =
 | 
| +        this->ParseLeftHandSideExpression(CHECK_OK_CUSTOM(EmptyClassLiteral));
 | 
| +  }
 | 
| +
 | 
| +  ObjectLiteralChecker checker(this, STRICT);
 | 
| +  typename Traits::Type::PropertyList properties =
 | 
| +      this->NewPropertyList(4, zone_);
 | 
| +  FunctionLiteralT constructor = this->EmptyFunctionLiteral();
 | 
| +
 | 
| +  Expect(Token::LBRACE, CHECK_OK_CUSTOM(EmptyClassLiteral));
 | 
| +  while (peek() != Token::RBRACE) {
 | 
| +    if (Check(Token::SEMICOLON)) continue;
 | 
| +    if (fni_ != NULL) fni_->Enter();
 | 
| +
 | 
| +    const bool in_class = true;
 | 
| +    const bool is_static = false;
 | 
| +    ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
 | 
| +        &checker, in_class, is_static, CHECK_OK_CUSTOM(EmptyClassLiteral));
 | 
| +
 | 
| +    properties->Add(property, zone());
 | 
| +
 | 
| +    if (fni_ != NULL) {
 | 
| +      fni_->Infer();
 | 
| +      fni_->Leave();
 | 
| +    }
 | 
| +  }
 | 
| +  Expect(Token::RBRACE, CHECK_OK_CUSTOM(EmptyClassLiteral));
 | 
| +
 | 
| +  return factory()->NewClassLiteral(name, extends, constructor, properties,
 | 
| +                                    this->ast_value_factory(), pos);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  template <typename Traits>
 | 
|  typename ParserBase<Traits>::ExpressionT
 | 
|  ParserBase<Traits>::CheckAndRewriteReferenceExpression(
 | 
| 
 |