// 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 x = 'c'; class C { static [x] = 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'); let r = { ["z"]: class { static y = this.name; static name = "zz" } } let r_z_name_desc = Object.getOwnPropertyDescriptor(r.z, "name"); assertEquals(r.z.y, 'z'); assertEquals(r_z_name_desc, { value: 'zz', enumerable: true, writable: true, configurable: true }); let s = { ["z"]: class Y { static y = this.name } } assertEquals(s.z.y, 'Y'); const C = class { static x = this.name; } assertEquals(C.x, 'C'); } { let p = class { static z = class { static y = this.name } } assertEquals(p.z.y, 'z'); let q = class { static ["z"] = class { static y = this.name } } assertEquals(q.z.y, 'z'); let r = class { static ["z"] = class { static y = this.name; static name = "zz" } } let r_z_name_desc = Object.getOwnPropertyDescriptor(r.z, "name"); assertEquals(r.z.y, 'z'); assertEquals(r_z_name_desc, { value: 'zz', enumerable: true, writable: true, configurable: true }); let s = class { static ["z"] = class Y { static y = this.name } } assertEquals(s.z.y, 'Y'); }