Make super() a syntax error in base class constructor
authorErik Arvidsson <arv@chromium.org>
Thu, 12 Feb 2015 23:04:40 +0000 (18:04 -0500)
committerErik Arvidsson <arv@chromium.org>
Thu, 12 Feb 2015 23:04:54 +0000 (23:04 +0000)
BUG=v8:3330
LOG=N
R=dslomov@chromium.org

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

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

src/preparser.h
test/cctest/test-parsing.cc
test/message/super-constructor-extra-statement.out
test/message/super-constructor.out
test/mjsunit/harmony/classes-experimental.js

index 141761d..fa72794 100644 (file)
@@ -2752,8 +2752,8 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new, bool* ok) {
       return this->SuperReference(scope_, factory());
     }
     // new super() is never allowed.
-    // super() is only allowed in constructor
-    if (!is_new && peek() == Token::LPAREN && i::IsConstructor(kind)) {
+    // super() is only allowed in derived constructor
+    if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) {
       scope_->RecordSuperConstructorCallUsage();
       return this->SuperReference(scope_, factory());
     }
index 9c2f24d..aabeb0a 100644 (file)
@@ -960,12 +960,10 @@ TEST(ScopeUsesArgumentsSuperThis) {
     NONE = 0,
     ARGUMENTS = 1,
     SUPER_PROPERTY = 1 << 1,
-    SUPER_CONSTRUCTOR_CALL = 1 << 2,
-    THIS = 1 << 3,
-    INNER_ARGUMENTS = 1 << 4,
-    INNER_SUPER_PROPERTY = 1 << 5,
-    INNER_SUPER_CONSTRUCTOR_CALL = 1 << 6,
-    INNER_THIS = 1 << 7
+    THIS = 1 << 2,
+    INNER_ARGUMENTS = 1 << 3,
+    INNER_SUPER_PROPERTY = 1 << 4,
+    INNER_THIS = 1 << 5
   };
 
   static const struct {
@@ -975,14 +973,13 @@ TEST(ScopeUsesArgumentsSuperThis) {
     {"", NONE},
     {"return this", THIS},
     {"return arguments", ARGUMENTS},
-    {"return super()", SUPER_CONSTRUCTOR_CALL},
     {"return super.x", SUPER_PROPERTY},
     {"return arguments[0]", ARGUMENTS},
     {"return this + arguments[0]", ARGUMENTS | THIS},
     {"return this + arguments[0] + super.x",
      ARGUMENTS | SUPER_PROPERTY | THIS},
     {"return x => this + x", INNER_THIS},
-    {"return x => super() + x", INNER_SUPER_CONSTRUCTOR_CALL},
+    {"return x => super.f() + x", INNER_SUPER_PROPERTY},
     {"this.foo = 42;", THIS},
     {"this.foo();", THIS},
     {"if (foo()) { this.f() }", THIS},
@@ -993,8 +990,8 @@ TEST(ScopeUsesArgumentsSuperThis) {
     {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
     // Multiple nesting levels must work as well.
     {"while (true) { while (true) { while (true) return this } }", THIS},
-    {"while (true) { while (true) { while (true) return super() } }",
-     SUPER_CONSTRUCTOR_CALL},
+    {"while (true) { while (true) { while (true) return super.f() } }",
+     SUPER_PROPERTY},
     {"if (1) { return () => { while (true) new this() } }", INNER_THIS},
     // Note that propagation of the inner_uses_this() value does not
     // cross boundaries of normal functions onto parent scopes.
@@ -1009,8 +1006,8 @@ TEST(ScopeUsesArgumentsSuperThis) {
     // Flags must be correctly set when using block scoping.
     {"\"use strict\"; while (true) { let x; this, arguments; }",
      INNER_ARGUMENTS | INNER_THIS},
-    {"\"use strict\"; while (true) { let x; this, super(), arguments; }",
-     INNER_ARGUMENTS | INNER_SUPER_CONSTRUCTOR_CALL | INNER_THIS},
+    {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
+     INNER_ARGUMENTS | INNER_SUPER_PROPERTY | INNER_THIS},
     {"\"use strict\"; if (foo()) { let x; this.f() }", INNER_THIS},
     {"\"use strict\"; if (foo()) { let x; super.f() }",
      INNER_SUPER_PROPERTY},
@@ -1032,11 +1029,8 @@ TEST(ScopeUsesArgumentsSuperThis) {
 
   for (unsigned j = 0; j < arraysize(surroundings); ++j) {
     for (unsigned i = 0; i < arraysize(source_data); ++i) {
-      // Super constructor call is only allowed in constructor.
       // Super property is only allowed in constructor and method.
-      if (((source_data[i].expected & SUPER_CONSTRUCTOR_CALL) ||
-           (source_data[i].expected & SUPER_PROPERTY) ||
-           (source_data[i].expected & INNER_SUPER_CONSTRUCTOR_CALL) ||
+      if (((source_data[i].expected & SUPER_PROPERTY) ||
            (source_data[i].expected & INNER_SUPER_PROPERTY) ||
            (source_data[i].expected == NONE)) && j != 2) {
         continue;
@@ -1079,15 +1073,11 @@ TEST(ScopeUsesArgumentsSuperThis) {
                scope->uses_arguments());
       CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
                scope->uses_super_property());
-      CHECK_EQ((source_data[i].expected & SUPER_CONSTRUCTOR_CALL) != 0,
-               scope->uses_super_constructor_call());
       CHECK_EQ((source_data[i].expected & THIS) != 0, scope->uses_this());
       CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0,
                scope->inner_uses_arguments());
       CHECK_EQ((source_data[i].expected & INNER_SUPER_PROPERTY) != 0,
                scope->inner_uses_super_property());
-      CHECK_EQ((source_data[i].expected & INNER_SUPER_CONSTRUCTOR_CALL) != 0,
-               scope->inner_uses_super_constructor_call());
       CHECK_EQ((source_data[i].expected & INNER_THIS) != 0,
                scope->inner_uses_this());
     }
@@ -3713,7 +3703,6 @@ TEST(SuperCall) {
                                    {NULL, NULL}};
 
   const char* success_data[] = {
-    "class C { constructor() { super(); } }",
     "class C extends B { constructor() { super(); } }",
     "class C extends B { constructor() { () => super(); } }",
     NULL
@@ -3729,6 +3718,7 @@ TEST(SuperCall) {
                     always_flags, arraysize(always_flags));
 
   const char* error_data[] = {
+    "class C { constructor() { super(); } }",
     "class C { method() { super(); } }",
     "class C { method() { () => super(); } }",
     "class C { *method() { super(); } }",
index a4156d0..0faa3be 100644 (file)
@@ -2,9 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-*%(basename)s:11: ReferenceError: Unsupported reference to 'super'
+*%(basename)s:11: SyntaxError: 'super' keyword unexpected here
     super(x);
-    ^
-ReferenceError: Unsupported reference to 'super'
-    at new C (*%(basename)s:11:5)
-    at *%(basename)s:15:9
+    ^^^^^
+SyntaxError: 'super' keyword unexpected here
index 63fb9c9..3fa546b 100644 (file)
@@ -1,9 +1,7 @@
 # Copyright 2014 the V8 project authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-*%(basename)s:10: ReferenceError: Unsupported reference to 'super'
+*%(basename)s:10: SyntaxError: 'super' keyword unexpected here
     super(this.x);
-    ^
-ReferenceError: Unsupported reference to 'super'
-    at new C (*%(basename)s:10:5)
-    at *%(basename)s:14:9
+    ^^^^^
+SyntaxError: 'super' keyword unexpected here
index 657c3b6..e7ebbda 100644 (file)
 }());
 
 
-(function TestSuperInBaseConstructors() {
-  class Base {
-    constructor() {
-      let exn = null;
-      try {
-        super();
-      } catch (e) {
-        exn = e;
-      }
-      assertTrue(exn instanceof ReferenceError);
-    }
-  }
-
-  new Base();
-}());
-
-
 (function TestPrototypeWiring() {
   class Base {
     constructor(x) {