new classes: assert that constructors are not callable and rewrite 'return;'
authordslomov <dslomov@chromium.org>
Fri, 6 Feb 2015 10:34:50 +0000 (02:34 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 6 Feb 2015 10:35:13 +0000 (10:35 +0000)
R=arv@chromium.org
BUG=v8:3834
LOG=N

Review URL: https://codereview.chromium.org/885643004

Cr-Commit-Position: refs/heads/master@{#26483}

14 files changed:
src/ast-value-factory.h
src/ast.h
src/code-stubs.h
src/compiler/linkage.cc
src/globals.h
src/messages.js
src/objects.h
src/parser.cc
src/parser.h
src/preparser.cc
src/preparser.h
src/runtime/runtime-classes.cc
src/runtime/runtime.h
test/mjsunit/harmony/classes-experimental.js

index e88819c2fe581b712325986c7ac96be9f6f5f655..70a29f14e3d51c73f953a56c7bed2ef8c9598e07 100644 (file)
@@ -261,7 +261,8 @@ class AstValue : public ZoneObject {
   F(use_asm, "use asm")                                 \
   F(use_strong, "use strong")                           \
   F(use_strict, "use strict")                           \
-  F(value, "value")
+  F(value, "value")                                     \
+  F(is_construct_call, "_IsConstructCall")
 
 #define OTHER_CONSTANTS(F) \
   F(true_value)            \
index 4e1fb26c267496cbc4f3e4934fb017a589175b86..e457e66a215f1aed49d48e5c54ffed107b29cca9 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -2618,7 +2618,7 @@ class FunctionLiteral FINAL : public Expression {
   class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {};
   class IsFunction : public BitField<IsFunctionFlag, 4, 1> {};
   class IsParenthesized : public BitField<IsParenthesizedFlag, 5, 1> {};
-  class FunctionKindBits : public BitField<FunctionKind, 6, 6> {};
+  class FunctionKindBits : public BitField<FunctionKind, 6, 7> {};
 };
 
 
index f284a344c950cc88b7742b9bf527e77a3054612b..a60d9d3c2610a894bed8677d40c953d753172e6e 100644 (file)
@@ -591,7 +591,7 @@ class FastNewClosureStub : public HydrogenCodeStub {
  private:
   STATIC_ASSERT(LANGUAGE_END == 3);
   class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
-  class FunctionKindBits : public BitField<FunctionKind, 2, 6> {};
+  class FunctionKindBits : public BitField<FunctionKind, 2, 7> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
index 384cf1c09ac473c26dbb572e89ba2af361bdc415..4d3187506ace5dd7323bc8050255301ea2edfd4a 100644 (file)
@@ -213,6 +213,7 @@ bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
     case Runtime::kStringMatch:
     case Runtime::kStringReplaceGlobalRegExpWithString:
     case Runtime::kThrowConstAssignError:
+    case Runtime::kThrowConstructorNonCallableError:
     case Runtime::kThrowNonMethodError:
     case Runtime::kThrowNotDateError:
     case Runtime::kThrowReferenceError:
index 3f2c33593b012acabb7c9102cf269f51a26ee55d..0248bb1600d8e8487fa2d1ffae2f9fba33a04013 100644 (file)
@@ -820,7 +820,8 @@ enum FunctionKind {
   kConciseGeneratorMethod = kGeneratorFunction | kConciseMethod,
   kAccessorFunction = 1 << 3,
   kDefaultConstructor = 1 << 4,
-  kSubclassConstructor = 1 << 5
+  kSubclassConstructor = 1 << 5,
+  kBaseConstructor = 1 << 6,
 };
 
 
@@ -832,6 +833,7 @@ inline bool IsValidFunctionKind(FunctionKind kind) {
          kind == FunctionKind::kConciseGeneratorMethod ||
          kind == FunctionKind::kAccessorFunction ||
          kind == FunctionKind::kDefaultConstructor ||
+         kind == FunctionKind::kBaseConstructor ||
          kind == FunctionKind::kSubclassConstructor;
 }
 
@@ -866,10 +868,24 @@ inline bool IsDefaultConstructor(FunctionKind kind) {
 }
 
 
+inline bool IsBaseConstructor(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kBaseConstructor;
+}
+
+
 inline bool IsSubclassConstructor(FunctionKind kind) {
   DCHECK(IsValidFunctionKind(kind));
   return kind & FunctionKind::kSubclassConstructor;
 }
+
+
+inline bool IsConstructor(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind &
+         (FunctionKind::kBaseConstructor | FunctionKind::kSubclassConstructor |
+          FunctionKind::kDefaultConstructor);
+}
 } }  // namespace v8::internal
 
 namespace i = v8::internal;
index 3b61e1882db5bfa0a80dcd720c8b3670d584b817..3bfc1a83c143170d01b402a0fed7984b0bd74feb 100644 (file)
@@ -181,7 +181,8 @@ var kMessages = {
   sloppy_lexical:                ["Block-scoped declarations (let, const, function, class) not yet supported outside strict mode"],
   super_constructor_call:        ["A 'super' constructor call may only appear as the first statement of a function, and its arguments may not access 'this'. Other forms are not yet supported."],
   duplicate_proto:               ["Duplicate __proto__ fields are not allowed in object literals"],
-  param_after_rest:              ["Rest parameter must be last formal parameter"]
+  param_after_rest:              ["Rest parameter must be last formal parameter"],
+  constructor_noncallable:       ["Class constructors cannot be invoked without 'new'"]
 };
 
 
index 61daada4b9ae57c13bb34bd15d84d6fab5ff5025..d66f839bf75ad7d215ad4095eacf9dd49f3cc584 100644 (file)
@@ -7195,6 +7195,7 @@ class SharedFunctionInfo: public HeapObject {
     kIsConciseMethod,
     kIsAccessorFunction,
     kIsDefaultConstructor,
+    kIsBaseConstructor,
     kIsSubclassConstructor,
     kIsAsmFunction,
     kDeserialized,
@@ -7203,7 +7204,7 @@ class SharedFunctionInfo: public HeapObject {
   // Add hints for other modes when they're added.
   STATIC_ASSERT(LANGUAGE_END == 3);
 
-  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 6> {};
+  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 7> {};
 
   class DeoptCountBits : public BitField<int, 0, 4> {};
   class OptReenableTriesBits : public BitField<int, 4, 18> {};
index 3c72dd0f72c7b47b05c08da86de112bee65468eb..d3fde9ef8f8c11da510708a6b1aa59c88dbbe1ce 100644 (file)
@@ -298,7 +298,7 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
   {
     AstNodeFactory function_factory(ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, function_scope,
-                                 &function_factory);
+                                 kDefaultConstructor, &function_factory);
 
     body = new (zone()) ZoneList<Statement*>(1, zone());
     if (call_super) {
@@ -946,7 +946,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
     // Enters 'scope'.
     AstNodeFactory function_factory(ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, *scope,
-                                 &function_factory);
+                                 kNormalFunction, &function_factory);
 
     scope_->SetLanguageMode(info->language_mode());
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
@@ -1066,7 +1066,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
     original_scope_ = scope;
     AstNodeFactory function_factory(ast_value_factory());
     FunctionState function_state(&function_state_, &scope_, scope,
-                                 &function_factory);
+                                 shared_info->kind(), &function_factory);
     DCHECK(is_sloppy(scope->language_mode()) ||
            is_strict(info()->language_mode()));
     DCHECK(info()->language_mode() == shared_info->language_mode());
@@ -2650,11 +2650,17 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
       tok == Token::SEMICOLON ||
       tok == Token::RBRACE ||
       tok == Token::EOS) {
-    return_value = GetLiteralUndefined(position());
+    if (FLAG_experimental_classes &&
+        IsSubclassConstructor(function_state_->kind())) {
+      return_value = ThisExpression(scope_, factory(), loc.beg_pos);
+    } else {
+      return_value = GetLiteralUndefined(position());
+    }
   } else {
     return_value = ParseExpression(true, CHECK_OK);
   }
   ExpectSemicolon(CHECK_OK);
+
   if (is_generator()) {
     Expression* generator = factory()->NewVariableProxy(
         function_state_->generator_object_variable());
@@ -3671,7 +3677,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
   // Parse function body.
   {
     AstNodeFactory function_factory(ast_value_factory());
-    FunctionState function_state(&function_state_, &scope_, scope,
+    FunctionState function_state(&function_state_, &scope_, scope, kind,
                                  &function_factory);
     scope_->SetScopeName(function_name);
 
@@ -3825,7 +3831,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
                            &expected_property_count, CHECK_OK);
     } else {
       body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
-                                    is_generator, CHECK_OK);
+                                    kind, CHECK_OK);
       materialized_literal_count = function_state.materialized_literal_count();
       expected_property_count = function_state.expected_property_count();
       handler_count = function_state.handler_count();
@@ -3935,7 +3941,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
 
 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
     const AstRawString* function_name, int pos, Variable* fvar,
-    Token::Value fvar_init_op, bool is_generator, bool* ok) {
+    Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
   // Everything inside an eagerly parsed function will be parsed eagerly
   // (see comment above).
   ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
@@ -3952,8 +3958,29 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
         RelocInfo::kNoPosition), zone());
   }
 
+
+  // For concise constructors, check that they are constructed,
+  // not called.
+  if (FLAG_experimental_classes && i::IsConstructor(kind)) {
+    ZoneList<Expression*>* arguments =
+        new (zone()) ZoneList<Expression*>(0, zone());
+    CallRuntime* construct_check = factory()->NewCallRuntime(
+        ast_value_factory()->is_construct_call_string(),
+        Runtime::FunctionForId(Runtime::kInlineIsConstructCall), arguments,
+        pos);
+    CallRuntime* non_callable_error = factory()->NewCallRuntime(
+        ast_value_factory()->empty_string(),
+        Runtime::FunctionForId(Runtime::kThrowConstructorNonCallableError),
+        arguments, pos);
+    IfStatement* if_statement = factory()->NewIfStatement(
+        factory()->NewUnaryOperation(Token::NOT, construct_check, pos),
+        factory()->NewReturnStatement(non_callable_error, pos),
+        factory()->NewEmptyStatement(pos), pos);
+    body->Add(if_statement, zone());
+  }
+
   // For generators, allocate and yield an iterator on function entry.
-  if (is_generator) {
+  if (IsGeneratorFunction(kind)) {
     ZoneList<Expression*>* arguments =
         new(zone()) ZoneList<Expression*>(0, zone());
     CallRuntime* allocation = factory()->NewCallRuntime(
@@ -3974,7 +4001,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 
   ParseStatementList(body, Token::RBRACE, false, NULL, CHECK_OK);
 
-  if (is_generator) {
+  if (IsGeneratorFunction(kind)) {
     VariableProxy* get_proxy = factory()->NewVariableProxy(
         function_state_->generator_object_variable());
     Expression* undefined =
@@ -3985,6 +4012,14 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
         yield, RelocInfo::kNoPosition), zone());
   }
 
+  if (FLAG_experimental_classes && IsSubclassConstructor(kind)) {
+    body->Add(
+        factory()->NewReturnStatement(
+            this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
+            RelocInfo::kNoPosition),
+        zone());
+  }
+
   Expect(Token::RBRACE, CHECK_OK);
   scope_->set_end_position(scanner()->location().end_pos);
 
@@ -4025,7 +4060,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
     reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
   }
   PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
-      language_mode(), is_generator(), logger);
+      language_mode(), function_state_->kind(), logger);
   if (pre_parse_timer_ != NULL) {
     pre_parse_timer_->Stop();
   }
index ddb542de35cb5492d9afdf350bd504b772475bbb..d1d1d7c3c02fbdcbd5a04612c2ccf052c5876e67 100644 (file)
@@ -583,7 +583,7 @@ class ParserTraits {
                                       int* expected_property_count, bool* ok);
   V8_INLINE ZoneList<Statement*>* ParseEagerFunctionBody(
       const AstRawString* name, int pos, Variable* fvar,
-      Token::Value fvar_init_op, bool is_generator, bool* ok);
+      Token::Value fvar_init_op, FunctionKind kind, bool* ok);
 
   ClassLiteral* ParseClassLiteral(const AstRawString* name,
                                   Scanner::Location class_name_location,
@@ -871,7 +871,7 @@ class Parser : public ParserBase<ParserTraits> {
   // Consumes the ending }.
   ZoneList<Statement*>* ParseEagerFunctionBody(
       const AstRawString* function_name, int pos, Variable* fvar,
-      Token::Value fvar_init_op, bool is_generator, bool* ok);
+      Token::Value fvar_init_op, FunctionKind kind, bool* ok);
 
   void ThrowPendingError();
 
@@ -936,9 +936,9 @@ void ParserTraits::SkipLazyFunctionBody(const AstRawString* function_name,
 
 ZoneList<Statement*>* ParserTraits::ParseEagerFunctionBody(
     const AstRawString* name, int pos, Variable* fvar,
-    Token::Value fvar_init_op, bool is_generator, bool* ok) {
-  return parser_->ParseEagerFunctionBody(name, pos, fvar, fvar_init_op,
-                                         is_generator, ok);
+    Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
+  return parser_->ParseEagerFunctionBody(name, pos, fvar, fvar_init_op, kind,
+                                         ok);
 }
 
 void ParserTraits::CheckConflictingVarDeclarations(v8::internal::Scope* scope,
index 170c9e725135818e3ff81a9914b16429b387dfa1..4c96ffb52f4573b13150f4a8c6583d89fe4ff18d 100644 (file)
@@ -104,18 +104,18 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral(
 
 
 PreParser::PreParseResult PreParser::PreParseLazyFunction(
-    LanguageMode language_mode, bool is_generator, ParserRecorder* log) {
+    LanguageMode language_mode, FunctionKind kind, ParserRecorder* log) {
   log_ = log;
   // Lazy functions always have trivial outer scopes (no with/catch scopes).
   PreParserScope top_scope(scope_, SCRIPT_SCOPE);
   PreParserFactory top_factory(NULL);
-  FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory);
+  FunctionState top_state(&function_state_, &scope_, &top_scope,
+                          kNormalFunction, &top_factory);
   scope_->SetLanguageMode(language_mode);
   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
   PreParserFactory function_factory(NULL);
-  FunctionState function_state(&function_state_, &scope_, &function_scope,
+  FunctionState function_state(&function_state_, &scope_, &function_scope, kind,
                                &function_factory);
-  function_state.set_is_generator(is_generator);
   DCHECK_EQ(Token::LBRACE, scanner()->current_token());
   bool ok = true;
   int start_position = peek_position();
@@ -869,9 +869,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
   ScopeType outer_scope_type = scope_->type();
   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
   PreParserFactory factory(NULL);
-  FunctionState function_state(&function_state_, &scope_, &function_scope,
+  FunctionState function_state(&function_state_, &scope_, &function_scope, kind,
                                &factory);
-  function_state.set_is_generator(IsGeneratorFunction(kind));
   //  FormalParameterList ::
   //    '(' (Identifier)*[','] ')'
   Expect(Token::LPAREN, CHECK_OK);
index 29a2b55e83e89719ee6472c35f9826765adb5be6..e6ef4ecf1a66d178613d1135d238e5ed2d79d8ff 100644 (file)
@@ -200,7 +200,7 @@ class ParserBase : public Traits {
    public:
     FunctionState(FunctionState** function_state_stack,
                   typename Traits::Type::Scope** scope_stack,
-                  typename Traits::Type::Scope* scope,
+                  typename Traits::Type::Scope* scope, FunctionKind kind,
                   typename Traits::Type::Factory* factory);
     ~FunctionState();
 
@@ -217,15 +217,15 @@ class ParserBase : public Traits {
     void AddProperty() { expected_property_count_++; }
     int expected_property_count() { return expected_property_count_; }
 
-    void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
-    bool is_generator() const { return is_generator_; }
+    bool is_generator() const { return IsGeneratorFunction(kind_); }
+
+    FunctionKind kind() const { return kind_; }
 
     void set_generator_object_variable(
         typename Traits::Type::GeneratorVariable* variable) {
       DCHECK(variable != NULL);
-      DCHECK(!is_generator());
+      DCHECK(is_generator());
       generator_object_variable_ = variable;
-      is_generator_ = true;
     }
     typename Traits::Type::GeneratorVariable* generator_object_variable()
         const {
@@ -246,13 +246,13 @@ class ParserBase : public Traits {
     // Properties count estimation.
     int expected_property_count_;
 
-    // Whether the function is a generator.
-    bool is_generator_;
+    FunctionKind kind_;
     // For generators, this variable may hold the generator object. It variable
     // is used by yield expressions and return statements. It is not necessary
     // for generator functions to have this variable set.
     Variable* generator_object_variable_;
 
+
     FunctionState** function_state_stack_;
     FunctionState* outer_function_state_;
     typename Traits::Type::Scope** scope_stack_;
@@ -1451,9 +1451,9 @@ class PreParserTraits {
   }
 
   V8_INLINE PreParserStatementList
-      ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
-                             Variable* fvar, Token::Value fvar_init_op,
-                             bool is_generator, bool* ok);
+  ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
+                         Variable* fvar, Token::Value fvar_init_op,
+                         FunctionKind kind, bool* ok);
 
   // Utility functions
   int DeclareArrowParametersFromExpression(PreParserExpression expression,
@@ -1545,7 +1545,8 @@ class PreParser : public ParserBase<PreParserTraits> {
   PreParseResult PreParseProgram(int* materialized_literals = 0) {
     PreParserScope scope(scope_, SCRIPT_SCOPE);
     PreParserFactory factory(NULL);
-    FunctionState top_scope(&function_state_, &scope_, &scope, &factory);
+    FunctionState top_scope(&function_state_, &scope_, &scope, kNormalFunction,
+                            &factory);
     bool ok = true;
     int start_position = scanner()->peek_location().beg_pos;
     ParseSourceElements(Token::EOS, &ok);
@@ -1571,7 +1572,7 @@ class PreParser : public ParserBase<PreParserTraits> {
   // At return, unless an error occurred, the scanner is positioned before the
   // the final '}'.
   PreParseResult PreParseLazyFunction(LanguageMode language_mode,
-                                      bool is_generator, ParserRecorder* log);
+                                      FunctionKind kind, ParserRecorder* log);
 
  private:
   friend class PreParserTraits;
@@ -1635,9 +1636,9 @@ class PreParser : public ParserBase<PreParserTraits> {
                                       int* materialized_literal_count,
                                       int* expected_property_count, bool* ok);
   V8_INLINE PreParserStatementList
-      ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
-                             Variable* fvar, Token::Value fvar_init_op,
-                             bool is_generator, bool* ok);
+  ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
+                         Variable* fvar, Token::Value fvar_init_op,
+                         FunctionKind kind, bool* ok);
 
   Expression ParseFunctionLiteral(
       Identifier name, Scanner::Location function_name_location,
@@ -1663,7 +1664,7 @@ void PreParserTraits::MaterializeTemplateCallsiteLiterals() {
 
 PreParserStatementList PreParser::ParseEagerFunctionBody(
     PreParserIdentifier function_name, int pos, Variable* fvar,
-    Token::Value fvar_init_op, bool is_generator, bool* ok) {
+    Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
   ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
 
   ParseSourceElements(Token::RBRACE, ok);
@@ -1676,9 +1677,9 @@ PreParserStatementList PreParser::ParseEagerFunctionBody(
 
 PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
     PreParserIdentifier function_name, int pos, Variable* fvar,
-    Token::Value fvar_init_op, bool is_generator, bool* ok) {
+    Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
   return pre_parser_->ParseEagerFunctionBody(function_name, pos, fvar,
-                                             fvar_init_op, is_generator, ok);
+                                             fvar_init_op, kind, ok);
 }
 
 
@@ -1686,12 +1687,12 @@ template <class Traits>
 ParserBase<Traits>::FunctionState::FunctionState(
     FunctionState** function_state_stack,
     typename Traits::Type::Scope** scope_stack,
-    typename Traits::Type::Scope* scope,
+    typename Traits::Type::Scope* scope, FunctionKind kind,
     typename Traits::Type::Factory* factory)
     : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
       next_handler_index_(0),
       expected_property_count_(0),
-      is_generator_(false),
+      kind_(kind),
       generator_object_variable_(NULL),
       function_state_stack_(function_state_stack),
       outer_function_state_(*function_state_stack),
@@ -2157,7 +2158,7 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
     if (in_class && !is_static && this->IsConstructor(name)) {
       *has_seen_constructor = true;
       kind = has_extends ? FunctionKind::kSubclassConstructor
-                         : FunctionKind::kNormalFunction;
+                         : FunctionKind::kBaseConstructor;
     }
 
     value = this->ParseFunctionLiteral(
@@ -2838,7 +2839,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos,
     typename Traits::Type::Factory function_factory(this->ast_value_factory());
     FunctionState function_state(&function_state_, &scope_,
                                  Traits::Type::ptr_to_scope(scope),
-                                 &function_factory);
+                                 kArrowFunction, &function_factory);
     Scanner::Location dupe_error_loc = Scanner::Location::invalid();
     num_parameters = Traits::DeclareArrowParametersFromExpression(
         params_ast, scope_, &dupe_error_loc, ok);
@@ -2871,8 +2872,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos,
       } else {
         body = this->ParseEagerFunctionBody(
             this->EmptyIdentifier(), RelocInfo::kNoPosition, NULL,
-            Token::INIT_VAR, false,  // Not a generator.
-            CHECK_OK);
+            Token::INIT_VAR, kArrowFunction, CHECK_OK);
         materialized_literal_count =
             function_state.materialized_literal_count();
         expected_property_count = function_state.expected_property_count();
index 8a207a8eabcea60d5b12d844e1f97199495af936..ffd121e612ef4d3dd6572ce7dff205cf02139153 100644 (file)
@@ -38,6 +38,15 @@ RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
 }
 
 
+RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 0);
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate,
+      NewTypeError("constructor_noncallable", HandleVector<Object>(NULL, 0)));
+}
+
+
 RUNTIME_FUNCTION(Runtime_ToMethod) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
index e8f8295bfb94e5736edd53169d3c3d32c70b6d8d..3f8aa2101a6c21e076c9b550a523e5f60a619008 100644 (file)
@@ -186,18 +186,19 @@ namespace internal {
   /* Classes support */                                    \
   F(ToMethod, 2, 1)                                        \
   F(HomeObjectSymbol, 0, 1)                                \
+  F(DefaultConstructorSuperCall, 0, 1)                     \
   F(DefineClass, 6, 1)                                     \
   F(DefineClassMethod, 3, 1)                               \
   F(ClassGetSourceCode, 1, 1)                              \
-  F(ThrowNonMethodError, 0, 1)                             \
-  F(ThrowUnsupportedSuperError, 0, 1)                      \
   F(LoadFromSuper, 3, 1)                                   \
   F(LoadKeyedFromSuper, 3, 1)                              \
+  F(ThrowConstructorNonCallableError, 0, 1)                \
+  F(ThrowNonMethodError, 0, 1)                             \
+  F(ThrowUnsupportedSuperError, 0, 1)                      \
   F(StoreToSuper_Strict, 4, 1)                             \
   F(StoreToSuper_Sloppy, 4, 1)                             \
   F(StoreKeyedToSuper_Strict, 4, 1)                        \
-  F(StoreKeyedToSuper_Sloppy, 4, 1)                        \
-  F(DefaultConstructorSuperCall, 0, 1)
+  F(StoreKeyedToSuper_Sloppy, 4, 1)
 
 
 #define RUNTIME_FUNCTION_LIST_ALWAYS_2(F)              \
index 5a3c3e5558319941e0098dabdc712ebfd1be0e93..ed720d97b6275462e397d3f55e81746a450839f1 100644 (file)
@@ -34,15 +34,18 @@ class Subclass extends Base {
 let b = new Base(1, 2);
 assertSame(3, b.prp);
 
+
 let s = new Subclass(2, -1);
 assertSame(1, s.prp);
 assertSame(undefined, s.prp1);
 assertFalse(s.hasOwnProperty("prp1"));
 
 class Subclass2 extends Base {
-  constructor() {
+  constructor(x) {
     super(1,2);
 
+    if (x < 0) return;
+
     let called = false;
     function tmp() { called = true; return 3; }
     var exn = null;
@@ -54,4 +57,11 @@ class Subclass2 extends Base {
   }
 }
 
-new Subclass2();
+var s2 = new Subclass2(1);
+assertSame(3, s2.prp);
+
+var s3 = new Subclass2(-1);
+assertSame(3, s3.prp);
+
+assertThrows(function() { Subclass.call(new Object(), 1, 2); }, TypeError);
+assertThrows(function() { Base.call(new Object(), 1, 2); }, TypeError);