| // Copyright 2017 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. | 
 |  | 
 | "use strict"; | 
 |  | 
 | { | 
 |   class C { | 
 |     static a; | 
 |   } | 
 |  | 
 |   assertEquals(undefined, C.a); | 
 |   let descriptor = Object.getOwnPropertyDescriptor(C, 'a'); | 
 |   assertTrue(C.hasOwnProperty('a')); | 
 |   assertTrue(descriptor.writable); | 
 |   assertTrue(descriptor.enumerable); | 
 |   assertTrue(descriptor.configurable); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.a); | 
 | } | 
 |  | 
 | { | 
 |   let x = 'a'; | 
 |   class C { | 
 |     static a; | 
 |     static hasOwnProperty = function() { return 1; } | 
 |     static b = x; | 
 |     static c = 1; | 
 |   } | 
 |  | 
 |   assertEquals(undefined, C.a); | 
 |   assertEquals('a', C.b); | 
 |   assertEquals(1, C.c); | 
 |   assertEquals(1, C.hasOwnProperty()); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.a); | 
 |   assertEquals(undefined, c.b); | 
 |   assertEquals(undefined, c.c); | 
 | } | 
 |  | 
 | { | 
 |   assertThrows(() => { | 
 |     class C { | 
 |       static x = Object.freeze(this); | 
 |       static c = 42; | 
 |     } | 
 |   }, TypeError); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static c = this; | 
 |     static d = () => this; | 
 |   } | 
 |  | 
 |   assertEquals(C, C.c); | 
 |   assertEquals(C, C.d()); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.c); | 
 |   assertEquals(undefined, c.d); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static c = 1; | 
 |     static d = this.c; | 
 |   } | 
 |  | 
 |   assertEquals(1, C.c); | 
 |   assertEquals(1, C.d); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.c); | 
 |   assertEquals(undefined, c.d); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static b = 1; | 
 |     static c = () => this.b; | 
 |   } | 
 |  | 
 |   assertEquals(1, C.b); | 
 |   assertEquals(1, C.c()); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.c); | 
 | } | 
 |  | 
 | { | 
 |   let x = 'a'; | 
 |   class C { | 
 |     static b = 1; | 
 |     static c = () => this.b; | 
 |     static e = () => x; | 
 |   } | 
 |  | 
 |   assertEquals(1, C.b); | 
 |   assertEquals('a', C.e()); | 
 |  | 
 |   let a = {b : 2 }; | 
 |   assertEquals(1, C.c.call(a)); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.b); | 
 |   assertEquals(undefined, c.c); | 
 | } | 
 |  | 
 | { | 
 |   let x = 'a'; | 
 |   class C { | 
 |     static c = 1; | 
 |     static d = function() { return this.c; }; | 
 |     static e = function() { return x; }; | 
 |   } | 
 |  | 
 |   assertEquals(1, C.c); | 
 |   assertEquals(1, C.d()); | 
 |   assertEquals('a', C.e()); | 
 |  | 
 |   C.c = 2; | 
 |   assertEquals(2, C.d()); | 
 |  | 
 |   let a = {c : 3 }; | 
 |   assertEquals(3, C.d.call(a)); | 
 |  | 
 |   assertThrows(C.d.bind(undefined)); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.c); | 
 |   assertEquals(undefined, c.d); | 
 |   assertEquals(undefined, c.e); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static c = function() { return 1 }; | 
 |   } | 
 |  | 
 |   assertEquals('c', C.c.name); | 
 | } | 
 |  | 
 | { | 
 |   let d = function() { return new.target; } | 
 |   class C { | 
 |     static c = d; | 
 |   } | 
 |  | 
 |   assertEquals(undefined, C.c()); | 
 |   assertEquals(new d, new C.c()); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static c = () => new.target; | 
 |   } | 
 |  | 
 |   assertEquals(undefined, C.c()); | 
 | } | 
 |  | 
 | { | 
 |    class C { | 
 |      static c = () => { | 
 |        let b; | 
 |        class A { | 
 |          constructor() { | 
 |            b = new.target; | 
 |          } | 
 |        }; | 
 |        new A; | 
 |        assertEquals(A, b); | 
 |      } | 
 |   } | 
 |  | 
 |   C.c(); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static c = new.target; | 
 |   } | 
 |  | 
 |   assertEquals(undefined, C.c); | 
 | } | 
 |  | 
 | { | 
 |   class B { | 
 |     static d = 1; | 
 |     static b = () => this.d; | 
 |   } | 
 |  | 
 |   class C extends B { | 
 |     static c = super.d; | 
 |     static d = () => super.d; | 
 |     static e = () => super.b(); | 
 |   } | 
 |  | 
 |   assertEquals(1, C.c); | 
 |   assertEquals(1, C.d()); | 
 |   assertEquals(1, C.e()); | 
 | } | 
 |  | 
 | { | 
 |   let foo = undefined; | 
 |   class B { | 
 |     static set d(x) { | 
 |       foo = x; | 
 |     } | 
 |   } | 
 |  | 
 |   class C extends B { | 
 |     static d = 2; | 
 |   } | 
 |  | 
 |   assertEquals(undefined, foo); | 
 |   assertEquals(2, C.d); | 
 | } | 
 |  | 
 |  | 
 | { | 
 |   let C  = class { | 
 |     static c; | 
 |   }; | 
 |  | 
 |   assertEquals("C", C.name); | 
 | } | 
 |  | 
 | { | 
 |   class C { | 
 |     static c = new C; | 
 |   } | 
 |  | 
 |   assertTrue(C.c instanceof C); | 
 | } | 
 |  | 
 | (function test() { | 
 |   function makeC() { | 
 |     var x = 1; | 
 |  | 
 |     return class { | 
 |       static a = () => () => x; | 
 |     } | 
 |   } | 
 |  | 
 |   let C = makeC(); | 
 |   let f = C.a(); | 
 |   assertEquals(1, f()); | 
 | })() | 
 |  | 
 | { | 
 |   let c = "c"; | 
 |   class C { | 
 |     static ["a"] = 1; | 
 |     static ["b"]; | 
 |     static [c]; | 
 |   } | 
 |  | 
 |   assertEquals(1, C.a); | 
 |   assertEquals(undefined, C.b); | 
 |   assertEquals(undefined, C[c]); | 
 | } | 
 |  | 
 | { | 
 |   let log = []; | 
 |   function run(i) { | 
 |     log.push(i); | 
 |     return i; | 
 |   } | 
 |  | 
 |   class C { | 
 |     static [run(1)] = run(6); | 
 |     static [run(2)] = run(7); | 
 |     [run(3)]() { run(9);} | 
 |     static [run(4)] = run(8); | 
 |     static [run(5)]() { throw new Error('should not execute');}; | 
 |   } | 
 |  | 
 |   let c = new C; | 
 |   c[3](); | 
 |   assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], log); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | function x() { | 
 |  | 
 |   // This tests lazy parsing. | 
 |   return function() { | 
 |     let log = []; | 
 |     function run(i) { | 
 |       log.push(i); | 
 |       return i; | 
 |     } | 
 |  | 
 |     class C { | 
 |       static [run(1)] = run(6); | 
 |       static [run(2)] = run(7); | 
 |       [run(3)]() { run(9);} | 
 |       static [run(4)] = run(8); | 
 |       static [run(5)]() { throw new Error('should not execute');}; | 
 |     } | 
 |  | 
 |     let c = new C; | 
 |     c[3](); | 
 |     assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], log); | 
 |   } | 
 | } | 
 | x()(); | 
 |  | 
 | { | 
 |   let log = []; | 
 |   function run(i) { | 
 |     log.push(i); | 
 |     return i; | 
 |   } | 
 |  | 
 |   class C { | 
 |     [run(1)] = run(7); | 
 |     [run(2)] = run(8); | 
 |     [run(3)]() { run(9);} | 
 |     static [run(4)] = run(6); | 
 |     [run(5)]() { throw new Error('should not execute');}; | 
 |   } | 
 |  | 
 |   let c = new C; | 
 |   c[3](); | 
 |   assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], log); | 
 | } | 
 |  | 
 | function y() { | 
 |   // This tests lazy parsing. | 
 |   return function() { | 
 |     let log = []; | 
 |     function run(i) { | 
 |       log.push(i); | 
 |       return i; | 
 |     } | 
 |  | 
 |     class C { | 
 |       [run(1)] = run(7); | 
 |       [run(2)] = run(8); | 
 |       [run(3)]() { run(9);} | 
 |       static [run(4)] = run(6); | 
 |       [run(5)]() { throw new Error('should not execute');}; | 
 |     } | 
 |  | 
 |     let c = new C; | 
 |     c[3](); | 
 |     assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], log); | 
 |   } | 
 | } | 
 | y()(); | 
 |  | 
 | { | 
 |   class C {} | 
 |   class D { | 
 |     static [C]; | 
 |   } | 
 |  | 
 |   assertThrows(() => { class X { static [X] } }); | 
 |   assertEquals(undefined, D[C]); | 
 | } | 
 |  | 
 | { | 
 |   function t() { | 
 |     return class { | 
 |       static ['x'] = 2; | 
 |     } | 
 |   } | 
 |  | 
 |   let klass = t(); | 
 |   let obj = new klass; | 
 |   assertEquals(2, klass.x); | 
 | } | 
 |  | 
 | { | 
 |   let x = 'a'; | 
 |   class C { | 
 |     a; | 
 |     b = x; | 
 |     c = 1; | 
 |     hasOwnProperty() { return 1;} | 
 |     static [x] = 2; | 
 |     static b = 3; | 
 |     static d; | 
 |   } | 
 |  | 
 |   assertEquals(2, C.a); | 
 |   assertEquals(3, C.b); | 
 |   assertEquals(undefined, C.d); | 
 |   assertEquals(undefined, C.c); | 
 |  | 
 |   let c = new C; | 
 |   assertEquals(undefined, c.a); | 
 |   assertEquals('a', c.b); | 
 |   assertEquals(1, c.c); | 
 |   assertEquals(undefined, c.d); | 
 |   assertEquals(1, c.hasOwnProperty()); | 
 | } | 
 |  | 
 | { | 
 |   function t() { | 
 |     return class { | 
 |       ['x'] = 1; | 
 |       static ['x'] = 2; | 
 |     } | 
 |   } | 
 |  | 
 |   let klass = t(); | 
 |   let obj = new klass; | 
 |   assertEquals(1, obj.x); | 
 |   assertEquals(2, klass.x); | 
 | } | 
 |  | 
 |  | 
 | { | 
 |   class X { | 
 |     static p = function() { return arguments[0]; } | 
 |   } | 
 |  | 
 |   assertEquals(1, X.p(1)); | 
 | } | 
 |  | 
 | { | 
 |   class X { | 
 |     static t = () => { | 
 |       function p() { return arguments[0]; }; | 
 |       return p; | 
 |     } | 
 |   } | 
 |  | 
 |   let p = X.t(); | 
 |   assertEquals(1, p(1)); | 
 | } | 
 |  | 
 | { | 
 |   class X { | 
 |     static t = () => { | 
 |       function p() { return eval("arguments[0]"); }; | 
 |       return p; | 
 |     } | 
 |   } | 
 |  | 
 |   let p = X.t(); | 
 |   assertEquals(1, p(1)); | 
 | } | 
 |  | 
 | { | 
 |   class X { | 
 |     static p = eval("(function() { return arguments[0]; })(1)"); | 
 |   } | 
 |  | 
 |   assertEquals(1, X.p); | 
 | } | 
 |  | 
 | { | 
 |   let p = { z: class { static y = this.name } } | 
 |   assertEquals(p.z.y, 'z'); | 
 |  | 
 |   let q = { ["z"]: class { static y = this.name } } | 
 |   assertEquals(q.z.y, 'z'); | 
 |  | 
 |   const C = class { | 
 |     static x = this.name; | 
 |   } | 
 |   assertEquals(C.x, 'C'); | 
 | } |