1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Flags: --allow-natives-syntax --harmony-do-expressions
6
7(function TestBasics() {
8  var C = class C {}
9  assertEquals(typeof C, 'function');
10  assertEquals(C.__proto__, Function.prototype);
11  assertEquals(Object.prototype, Object.getPrototypeOf(C.prototype));
12  assertEquals(Function.prototype, Object.getPrototypeOf(C));
13  assertEquals('C', C.name);
14
15  class D {}
16  assertEquals(typeof D, 'function');
17  assertEquals(D.__proto__, Function.prototype);
18  assertEquals(Object.prototype, Object.getPrototypeOf(D.prototype));
19  assertEquals(Function.prototype, Object.getPrototypeOf(D));
20  assertEquals('D', D.name);
21
22  class D2 { constructor() {} }
23  assertEquals('D2', D2.name);
24
25  var E = class {}
26  assertEquals('E', E.name);  // Should be 'E'.
27
28  var F = class { constructor() {} };
29  assertEquals('F', F.name);  // Should be 'F'.
30})();
31
32
33(function TestBasicsExtends() {
34  class C extends null {}
35  assertEquals(typeof C, 'function');
36  assertEquals(C.__proto__, Function.prototype);
37  assertEquals(null, Object.getPrototypeOf(C.prototype));
38
39  class D extends C {}
40  assertEquals(typeof D, 'function');
41  assertEquals(D.__proto__, C);
42  assertEquals(C.prototype, Object.getPrototypeOf(D.prototype));
43})();
44
45
46(function TestSideEffectInExtends() {
47  var calls = 0;
48  class C {}
49  class D extends (calls++, C) {}
50  assertEquals(1, calls);
51  assertEquals(typeof D, 'function');
52  assertEquals(D.__proto__, C);
53  assertEquals(C.prototype, Object.getPrototypeOf(D.prototype));
54})();
55
56
57(function TestInvalidExtends() {
58  assertThrows(function() {
59    class C extends 42 {}
60  }, TypeError);
61
62  assertThrows(function() {
63    // Function but its .prototype is not null or a function.
64    class C extends Math.abs {}
65  }, TypeError);
66
67  assertThrows(function() {
68    Math.abs.prototype = 42;
69    class C extends Math.abs {}
70  }, TypeError);
71  delete Math.abs.prototype;
72
73  assertThrows(function() {
74    function* g() {}
75    class C extends g {}
76  }, TypeError);
77})();
78
79
80(function TestConstructorProperty() {
81  class C {}
82  assertEquals(C, C.prototype.constructor);
83  var descr = Object.getOwnPropertyDescriptor(C.prototype, 'constructor');
84  assertTrue(descr.configurable);
85  assertFalse(descr.enumerable);
86  assertTrue(descr.writable);
87})();
88
89
90(function TestPrototypeProperty() {
91  class C {}
92  var descr = Object.getOwnPropertyDescriptor(C, 'prototype');
93  assertFalse(descr.configurable);
94  assertFalse(descr.enumerable);
95  assertFalse(descr.writable);
96})();
97
98
99(function TestConstructor() {
100  var count = 0;
101  class C {
102    constructor() {
103      assertEquals(Object.getPrototypeOf(this), C.prototype);
104      count++;
105    }
106  }
107  assertEquals(C, C.prototype.constructor);
108  var descr = Object.getOwnPropertyDescriptor(C.prototype, 'constructor');
109  assertTrue(descr.configurable);
110  assertFalse(descr.enumerable);
111  assertTrue(descr.writable);
112
113  var c = new C();
114  assertEquals(1, count);
115  assertEquals(Object.getPrototypeOf(c), C.prototype);
116})();
117
118
119(function TestImplicitConstructor() {
120  class C {}
121  var c = new C();
122  assertEquals(Object.getPrototypeOf(c), C.prototype);
123})();
124
125
126(function TestConstructorStrict() {
127  class C {
128    constructor() {
129      assertThrows(function() {
130        nonExistingBinding = 42;
131      }, ReferenceError);
132    }
133  }
134  new C();
135})();
136
137
138(function TestSuperInConstructor() {
139  var calls = 0;
140  class B {}
141  B.prototype.x = 42;
142
143  class C extends B {
144    constructor() {
145      super();
146      calls++;
147      assertEquals(42, super.x);
148    }
149  }
150
151  new C;
152  assertEquals(1, calls);
153})();
154
155
156(function TestStrictMode() {
157  class C {}
158
159  with ({a: 1}) {
160    assertEquals(1, a);
161  }
162
163  assertThrows('class C extends function B() { with ({}); return B; }() {}',
164               SyntaxError);
165
166  var D = class extends function() {
167    arguments.caller;
168  } {};
169  assertThrows(function() {
170    Object.getPrototypeOf(D).arguments;
171  }, TypeError);
172  assertThrows(function() {
173    new D;
174  }, TypeError);
175})();
176
177
178(function TestToString() {
179  class C {}
180  assertEquals('class C {}', C.toString());
181
182  class D { constructor() { 42; } }
183  assertEquals('class D { constructor() { 42; } }', D.toString());
184
185  class E { x() { 42; } }
186  assertEquals('class E { x() { 42; } }', E.toString());
187})();
188
189
190function assertMethodDescriptor(object, name) {
191  var descr = Object.getOwnPropertyDescriptor(object, name);
192  assertTrue(descr.configurable);
193  assertFalse(descr.enumerable);
194  assertTrue(descr.writable);
195  assertEquals('function', typeof descr.value);
196  assertFalse('prototype' in descr.value);
197}
198
199
200function assertGetterDescriptor(object, name) {
201  var descr = Object.getOwnPropertyDescriptor(object, name);
202  assertTrue(descr.configurable);
203  assertFalse(descr.enumerable);
204  assertEquals('function', typeof descr.get);
205  assertFalse('prototype' in descr.get);
206  assertEquals(undefined, descr.set);
207}
208
209
210function assertSetterDescriptor(object, name) {
211  var descr = Object.getOwnPropertyDescriptor(object, name);
212  assertTrue(descr.configurable);
213  assertFalse(descr.enumerable);
214  assertEquals(undefined, descr.get);
215  assertEquals('function', typeof descr.set);
216  assertFalse('prototype' in descr.set);
217}
218
219
220function assertAccessorDescriptor(object, name) {
221  var descr = Object.getOwnPropertyDescriptor(object, name);
222  assertTrue(descr.configurable);
223  assertFalse(descr.enumerable);
224  assertEquals('function', typeof descr.get);
225  assertEquals('function', typeof descr.set);
226  assertFalse('prototype' in descr.get);
227  assertFalse('prototype' in descr.set);
228}
229
230
231(function TestMethods() {
232  class C {
233    method() { return 1; }
234    static staticMethod() { return 2; }
235    method2() { return 3; }
236    static staticMethod2() { return 4; }
237  }
238
239  assertMethodDescriptor(C.prototype, 'method');
240  assertMethodDescriptor(C.prototype, 'method2');
241  assertMethodDescriptor(C, 'staticMethod');
242  assertMethodDescriptor(C, 'staticMethod2');
243
244  assertEquals(1, new C().method());
245  assertEquals(2, C.staticMethod());
246  assertEquals(3, new C().method2());
247  assertEquals(4, C.staticMethod2());
248})();
249
250
251(function TestGetters() {
252  class C {
253    get x() { return 1; }
254    static get staticX() { return 2; }
255    get y() { return 3; }
256    static get staticY() { return 4; }
257  }
258
259  assertGetterDescriptor(C.prototype, 'x');
260  assertGetterDescriptor(C.prototype, 'y');
261  assertGetterDescriptor(C, 'staticX');
262  assertGetterDescriptor(C, 'staticY');
263
264  assertEquals(1, new C().x);
265  assertEquals(2, C.staticX);
266  assertEquals(3, new C().y);
267  assertEquals(4, C.staticY);
268})();
269
270
271
272(function TestSetters() {
273  var x, staticX, y, staticY;
274  class C {
275    set x(v) { x = v; }
276    static set staticX(v) { staticX = v; }
277    set y(v) { y = v; }
278    static set staticY(v) { staticY = v; }
279  }
280
281  assertSetterDescriptor(C.prototype, 'x');
282  assertSetterDescriptor(C.prototype, 'y');
283  assertSetterDescriptor(C, 'staticX');
284  assertSetterDescriptor(C, 'staticY');
285
286  assertEquals(1, new C().x = 1);
287  assertEquals(1, x);
288  assertEquals(2, C.staticX = 2);
289  assertEquals(2, staticX);
290  assertEquals(3, new C().y = 3);
291  assertEquals(3, y);
292  assertEquals(4, C.staticY = 4);
293  assertEquals(4, staticY);
294})();
295
296
297(function TestSideEffectsInPropertyDefine() {
298  function B() {}
299  B.prototype = {
300    constructor: B,
301    set m(v) {
302      throw Error();
303    }
304  };
305
306  class C extends B {
307    m() { return 1; }
308  }
309
310  assertEquals(1, new C().m());
311})();
312
313
314(function TestAccessors() {
315  class C {
316    constructor(x) {
317      this._x = x;
318    }
319
320    get x() { return this._x; }
321    set x(v) { this._x = v; }
322
323    static get staticX() { return this._x; }
324    static set staticX(v) { this._x = v; }
325  }
326
327  assertAccessorDescriptor(C.prototype, 'x');
328  assertAccessorDescriptor(C, 'staticX');
329
330  var c = new C(1);
331  c._x = 1;
332  assertEquals(1, c.x);
333  c.x = 2;
334  assertEquals(2, c._x);
335
336  C._x = 3;
337  assertEquals(3, C.staticX);
338  C._x = 4;
339  assertEquals(4, C.staticX );
340})();
341
342
343(function TestProto() {
344  class C {
345    __proto__() { return 1; }
346  }
347  assertMethodDescriptor(C.prototype, '__proto__');
348  assertEquals(1, new C().__proto__());
349})();
350
351
352(function TestProtoStatic() {
353  class C {
354    static __proto__() { return 1; }
355  }
356  assertMethodDescriptor(C, '__proto__');
357  assertEquals(1, C.__proto__());
358})();
359
360
361(function TestProtoAccessor() {
362  class C {
363    get __proto__() { return this._p; }
364    set __proto__(v) { this._p = v; }
365  }
366  assertAccessorDescriptor(C.prototype, '__proto__');
367  var c = new C();
368  c._p = 1;
369  assertEquals(1, c.__proto__);
370  c.__proto__ = 2;
371  assertEquals(2, c.__proto__);
372})();
373
374
375(function TestStaticProtoAccessor() {
376  class C {
377    static get __proto__() { return this._p; }
378    static set __proto__(v) { this._p = v; }
379  }
380  assertAccessorDescriptor(C, '__proto__');
381  C._p = 1;
382  assertEquals(1, C.__proto__);
383  C.__proto__ = 2;
384  assertEquals(2, C.__proto__);
385})();
386
387
388(function TestSettersOnProto() {
389  function Base() {}
390  Base.prototype = {
391    set constructor(_) {
392      assertUnreachable();
393    },
394    set m(_) {
395      assertUnreachable();
396    }
397  };
398  Object.defineProperty(Base, 'staticM', {
399    set: function() {
400      assertUnreachable();
401    }
402  });
403
404  class C extends Base {
405    m() {
406      return 1;
407    }
408    static staticM() {
409      return 2;
410    }
411  }
412
413  assertEquals(1, new C().m());
414  assertEquals(2, C.staticM());
415})();
416
417
418(function TestConstructableButNoPrototype() {
419  var Base = function() {}.bind();
420  assertThrows(function() {
421    class C extends Base {}
422  }, TypeError);
423})();
424
425
426(function TestPrototypeGetter() {
427  var calls = 0;
428  var Base = function() {}.bind();
429  Object.defineProperty(Base, 'prototype', {
430    get: function() {
431      calls++;
432      return null;
433    },
434    configurable: true
435  });
436  class C extends Base {}
437  assertEquals(1, calls);
438
439  calls = 0;
440  Object.defineProperty(Base, 'prototype', {
441    get: function() {
442      calls++;
443      return 42;
444    },
445    configurable: true
446  });
447  assertThrows(function() {
448    class C extends Base {}
449  }, TypeError);
450  assertEquals(1, calls);
451})();
452
453
454(function TestPrototypeSetter() {
455  var Base = function() {}.bind();
456  Object.defineProperty(Base, 'prototype', {
457    set: function() {
458      assertUnreachable();
459    }
460  });
461  assertThrows(function() {
462    class C extends Base {}
463  }, TypeError);
464})();
465
466
467(function TestSuperInMethods() {
468  class B {
469    method() {
470      return 1;
471    }
472    get x() {
473      return 2;
474    }
475  }
476  class C extends B {
477    method() {
478      assertEquals(2, super.x);
479      return super.method();
480    }
481  }
482  assertEquals(1, new C().method());
483})();
484
485
486(function TestSuperInGetter() {
487  class B {
488    method() {
489      return 1;
490    }
491    get x() {
492      return 2;
493    }
494  }
495  class C extends B {
496    get y() {
497      assertEquals(2, super.x);
498      return super.method();
499    }
500  }
501  assertEquals(1, new C().y);
502})();
503
504
505(function TestSuperInSetter() {
506  class B {
507    method() {
508      return 1;
509    }
510    get x() {
511      return 2;
512    }
513  }
514  class C extends B {
515    set y(v) {
516      assertEquals(3, v);
517      assertEquals(2, super.x);
518      assertEquals(1, super.method());
519    }
520  }
521  assertEquals(3, new C().y = 3);
522})();
523
524
525(function TestSuperInStaticMethods() {
526  class B {
527    static method() {
528      return 1;
529    }
530    static get x() {
531      return 2;
532    }
533  }
534  class C extends B {
535    static method() {
536      assertEquals(2, super.x);
537      return super.method();
538    }
539  }
540  assertEquals(1, C.method());
541})();
542
543
544(function TestSuperInStaticGetter() {
545  class B {
546    static method() {
547      return 1;
548    }
549    static get x() {
550      return 2;
551    }
552  }
553  class C extends B {
554    static get x() {
555      assertEquals(2, super.x);
556      return super.method();
557    }
558  }
559  assertEquals(1, C.x);
560})();
561
562
563(function TestSuperInStaticSetter() {
564  class B {
565    static method() {
566      return 1;
567    }
568    static get x() {
569      return 2;
570    }
571  }
572  class C extends B {
573    static set x(v) {
574      assertEquals(3, v);
575      assertEquals(2, super.x);
576      assertEquals(1, super.method());
577    }
578  }
579  assertEquals(3, C.x = 3);
580})();
581
582
583(function TestNumericPropertyNames() {
584  class B {
585    1() { return 1; }
586    get 2() { return 2; }
587    set 3(_) {}
588
589    static 4() { return 4; }
590    static get 5() { return 5; }
591    static set 6(_) {}
592  }
593
594  assertMethodDescriptor(B.prototype, '1');
595  assertGetterDescriptor(B.prototype, '2');
596  assertSetterDescriptor(B.prototype, '3');
597
598  assertMethodDescriptor(B, '4');
599  assertGetterDescriptor(B, '5');
600  assertSetterDescriptor(B, '6');
601
602  class C extends B {
603    1() { return super[1](); }
604    get 2() { return super[2]; }
605
606    static 4() { return super[4](); }
607    static get 5() { return super[5]; }
608  }
609
610  assertEquals(1, new C()[1]());
611  assertEquals(2, new C()[2]);
612  assertEquals(4, C[4]());
613  assertEquals(5, C[5]);
614})();
615
616
617(function TestDefaultConstructorNoCrash() {
618  // Regression test for https://code.google.com/p/v8/issues/detail?id=3661
619  class C {}
620  assertThrows(function () {C();}, TypeError);
621  assertThrows(function () {C(1);}, TypeError);
622  assertTrue(new C() instanceof C);
623  assertTrue(new C(1) instanceof C);
624})();
625
626
627(function TestConstructorCall(){
628  var realmIndex = Realm.create();
629  var otherTypeError = Realm.eval(realmIndex, "TypeError");
630  var A = Realm.eval(realmIndex, '"use strict"; class A {}');
631  var instance = new A();
632  var constructor = instance.constructor;
633  var otherTypeError = Realm.eval(realmIndex, 'TypeError');
634  if (otherTypeError === TypeError) {
635    throw Error('Should not happen!');
636  }
637
638  // ES6 9.2.1[[Call]] throws a TypeError in the caller context/Realm when the
639  // called function is a classConstructor
640  assertThrows(function() { Realm.eval(realmIndex, "A()") }, otherTypeError);
641  assertThrows(function() { instance.constructor() }, TypeError);
642  assertThrows(function() { A() }, TypeError);
643
644  // ES6 9.3.1 call() first activates the callee context before invoking the
645  // method. The TypeError from the constructor is thus thrown in the other
646  // Realm.
647  assertThrows(function() { Realm.eval(realmIndex, "A.call()") },
648      otherTypeError);
649  assertThrows(function() { constructor.call() }, otherTypeError);
650  assertThrows(function() { A.call() }, otherTypeError);
651})();
652
653
654(function TestConstructorCallOptimized() {
655  class A { };
656
657  function invoke_constructor() { A() }
658  function call_constructor() { A.call() }
659  function apply_constructor() { A.apply() }
660
661  for (var i=0; i<3; i++) {
662    assertThrows(invoke_constructor);
663    assertThrows(call_constructor);
664    assertThrows(apply_constructor);
665  }
666  // Make sure we still check for class constructors when calling optimized
667  // code.
668  %OptimizeFunctionOnNextCall(invoke_constructor);
669  assertThrows(invoke_constructor);
670  %OptimizeFunctionOnNextCall(call_constructor);
671  assertThrows(call_constructor);
672  %OptimizeFunctionOnNextCall(apply_constructor);
673  assertThrows(apply_constructor);
674})();
675
676
677(function TestDefaultConstructor() {
678  var calls = 0;
679  class Base {
680    constructor() {
681      calls++;
682    }
683  }
684  class Derived extends Base {}
685  var object = new Derived;
686  assertEquals(1, calls);
687
688  calls = 0;
689  assertThrows(function() { Derived(); }, TypeError);
690  assertEquals(0, calls);
691})();
692
693
694(function TestDefaultConstructorArguments() {
695  var args, self;
696  class Base {
697    constructor() {
698      self = this;
699      args = arguments;
700    }
701  }
702  class Derived extends Base {}
703
704  new Derived;
705  assertEquals(0, args.length);
706
707  new Derived(0, 1, 2);
708  assertEquals(3, args.length);
709  assertTrue(self instanceof Derived);
710
711  var arr = new Array(100);
712  var obj = {};
713  assertThrows(function() {Derived.apply(obj, arr);}, TypeError);
714})();
715
716
717(function TestDefaultConstructorArguments2() {
718  var args;
719  class Base {
720    constructor(x, y) {
721      args = arguments;
722    }
723  }
724  class Derived extends Base {}
725
726  new Derived;
727  assertEquals(0, args.length);
728
729  new Derived(1);
730  assertEquals(1, args.length);
731  assertEquals(1, args[0]);
732
733  new Derived(1, 2, 3);
734  assertEquals(3, args.length);
735  assertEquals(1, args[0]);
736  assertEquals(2, args[1]);
737  assertEquals(3, args[2]);
738})();
739
740
741(function TestNameBindingConst() {
742  assertThrows('class C { constructor() { C = 42; } }; new C();', TypeError);
743  assertThrows('new (class C { constructor() { C = 42; } })', TypeError);
744  assertThrows('class C { m() { C = 42; } }; new C().m()', TypeError);
745  assertThrows('new (class C { m() { C = 42; } }).m()', TypeError);
746  assertThrows('class C { get x() { C = 42; } }; new C().x', TypeError);
747  assertThrows('(new (class C { get x() { C = 42; } })).x', TypeError);
748  assertThrows('class C { set x(_) { C = 42; } }; new C().x = 15;', TypeError);
749  assertThrows('(new (class C { set x(_) { C = 42; } })).x = 15;', TypeError);
750})();
751
752
753(function TestNameBinding() {
754  var C2;
755  class C {
756    constructor() {
757      C2 = C;
758    }
759    m() {
760      C2 = C;
761    }
762    get x() {
763      C2 = C;
764    }
765    set x(_) {
766      C2 = C;
767    }
768  }
769  new C();
770  assertEquals(C, C2);
771
772  C2 = undefined;
773  new C().m();
774  assertEquals(C, C2);
775
776  C2 = undefined;
777  new C().x;
778  assertEquals(C, C2);
779
780  C2 = undefined;
781  new C().x = 1;
782  assertEquals(C, C2);
783})();
784
785
786(function TestNameBindingExpression() {
787  var C3;
788  var C = class C2 {
789    constructor() {
790      assertEquals(C2, C);
791      C3 = C2;
792    }
793    m() {
794      assertEquals(C2, C);
795      C3 = C2;
796    }
797    get x() {
798      assertEquals(C2, C);
799      C3 = C2;
800    }
801    set x(_) {
802      assertEquals(C2, C);
803      C3 = C2;
804    }
805  }
806  new C();
807  assertEquals(C, C3);
808
809  C3 = undefined;
810  new C().m();
811  assertEquals(C, C3);
812
813  C3 = undefined;
814  new C().x;
815  assertEquals(C, C3);
816
817  C3 = undefined;
818  new C().x = 1;
819  assertEquals(C, C3);
820})();
821
822
823(function TestNameBindingInExtendsExpression() {
824  assertThrows(function() {
825    class x extends x {}
826  }, ReferenceError);
827
828  assertThrows(function() {
829    (class x extends x {});
830  }, ReferenceError);
831
832  assertThrows(function() {
833    var x = (class x extends x {});
834  }, ReferenceError);
835})();
836
837
838(function TestThisAccessRestriction() {
839  class Base {}
840  (function() {
841    class C extends Base {
842      constructor() {
843        var y;
844        super();
845      }
846    }; new C();
847  }());
848  assertThrows(function() {
849    class C extends Base {
850      constructor() {
851        super(this.x);
852      }
853    }; new C();
854  }, ReferenceError);
855  assertThrows(function() {
856    class C extends Base {
857      constructor() {
858        super(this);
859      }
860    }; new C();
861  }, ReferenceError);
862  assertThrows(function() {
863    class C extends Base {
864      constructor() {
865        super.method();
866        super(this);
867      }
868    }; new C();
869  }, ReferenceError);
870  assertThrows(function() {
871    class C extends Base {
872      constructor() {
873        super(super.method());
874      }
875    }; new C();
876  }, ReferenceError);
877  assertThrows(function() {
878    class C extends Base {
879      constructor() {
880        super(super());
881      }
882    }; new C();
883  }, ReferenceError);
884  assertThrows(function() {
885    class C extends Base {
886      constructor() {
887        super(1, 2, Object.getPrototypeOf(this));
888      }
889    }; new C();
890  }, ReferenceError);
891  (function() {
892    class C extends Base {
893      constructor() {
894        { super(1, 2); }
895      }
896    }; new C();
897  }());
898  (function() {
899    class C extends Base {
900      constructor() {
901        if (1) super();
902      }
903    }; new C();
904  }());
905
906  class C1 extends Object {
907    constructor() {
908      'use strict';
909      super();
910    }
911  };
912  new C1();
913
914  class C2 extends Object {
915    constructor() {
916      ; 'use strict';;;;;
917      super();
918    }
919  };
920  new C2();
921
922  class C3 extends Object {
923    constructor() {
924      ; 'use strict';;;;;
925      // This is a comment.
926      super();
927    }
928  };
929  new C3();
930}());
931
932
933function testClassRestrictedProperties(C) {
934  assertEquals(false, C.hasOwnProperty("arguments"));
935  assertThrows(function() { return C.arguments; }, TypeError);
936  assertThrows(function() { C.arguments = {}; }, TypeError);
937
938  assertEquals(false, C.hasOwnProperty("caller"));
939  assertThrows(function() { return C.caller; }, TypeError);
940  assertThrows(function() { C.caller = {}; }, TypeError);
941
942  assertEquals(false, (new C).method.hasOwnProperty("arguments"));
943  assertThrows(function() { return new C().method.arguments; }, TypeError);
944  assertThrows(function() { new C().method.arguments = {}; }, TypeError);
945
946  assertEquals(false, (new C).method.hasOwnProperty("caller"));
947  assertThrows(function() { return new C().method.caller; }, TypeError);
948  assertThrows(function() { new C().method.caller = {}; }, TypeError);
949}
950
951
952(function testRestrictedPropertiesStrict() {
953  "use strict";
954  class ClassWithDefaultConstructor {
955    method() {}
956  }
957  class Class {
958    constructor() {}
959    method() {}
960  }
961  class DerivedClassWithDefaultConstructor extends Class {}
962  class DerivedClass extends Class { constructor() { super(); } }
963
964  testClassRestrictedProperties(ClassWithDefaultConstructor);
965  testClassRestrictedProperties(Class);
966  testClassRestrictedProperties(DerivedClassWithDefaultConstructor);
967  testClassRestrictedProperties(DerivedClass);
968  testClassRestrictedProperties(class { method() {} });
969  testClassRestrictedProperties(class { constructor() {} method() {} });
970  testClassRestrictedProperties(class extends Class { });
971  testClassRestrictedProperties(
972      class extends Class { constructor() { super(); } });
973})();
974
975
976(function testRestrictedPropertiesSloppy() {
977  class ClassWithDefaultConstructor {
978    method() {}
979  }
980  class Class {
981    constructor() {}
982    method() {}
983  }
984  class DerivedClassWithDefaultConstructor extends Class {}
985  class DerivedClass extends Class { constructor() { super(); } }
986
987  testClassRestrictedProperties(ClassWithDefaultConstructor);
988  testClassRestrictedProperties(Class);
989  testClassRestrictedProperties(DerivedClassWithDefaultConstructor);
990  testClassRestrictedProperties(DerivedClass);
991  testClassRestrictedProperties(class { method() {} });
992  testClassRestrictedProperties(class { constructor() {} method() {} });
993  testClassRestrictedProperties(class extends Class { });
994  testClassRestrictedProperties(
995      class extends Class { constructor() { super(); } });
996})();
997
998
999(function testReturnFromClassLiteral() {
1000
1001  function usingDoExpressionInBody() {
1002    let x = 42;
1003    let dummy = function() {x};
1004    try {
1005      class C {
1006        dummy() {C}
1007        [do {return}]() {}
1008      };
1009    } finally {
1010      return x;
1011    }
1012  }
1013  assertEquals(42, usingDoExpressionInBody());
1014
1015  function usingDoExpressionInExtends() {
1016    let x = 42;
1017    let dummy = function() {x};
1018    try {
1019      class C extends (do {return}) { dummy() {C} };
1020    } finally {
1021      return x;
1022    }
1023  }
1024  assertEquals(42, usingDoExpressionInExtends());
1025
1026  function usingYieldInBody() {
1027    function* foo() {
1028      class C {
1029        [yield]() {}
1030      }
1031    }
1032    var g = foo();
1033    g.next();
1034    return g.return(42).value;
1035  }
1036  assertEquals(42, usingYieldInBody());
1037
1038  function usingYieldInExtends() {
1039    function* foo() {
1040      class C extends (yield) {};
1041    }
1042    var g = foo();
1043    g.next();
1044    return g.return(42).value;
1045  }
1046  assertEquals(42, usingYieldInExtends());
1047
1048})();
1049