// Copyright 2018 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. // Flags: --harmony-private-fields --allow-natives-syntax "use strict"; { class C { static #a; static getA() { return this.#a; } } assertEquals(undefined, C.a); assertEquals(undefined, C.getA()); let c = new C; assertEquals(undefined, c.a); } { class C { static #a = 1; static getA() { return this.#a; } } assertEquals(undefined, C.a); assertEquals(1, C.getA()); let c = new C; assertEquals(undefined, c.a); } { class C { static #a = 1; static #b = this.#a; static getB() { return this.#b; } } assertEquals(1, C.getB()); let c = new C; assertEquals(undefined, c.getB); } { class C { static #a = 1; static getA() { return this.#a; } constructor() { assertThrows(() => this.#a, TypeError); C.#a = 2; } } assertEquals(1, C.getA()); let c = new C; assertThrows(() => C.prototype.getA.call(c)); assertEquals(2, C.getA()); } { class C { static #a = this; static #b = () => this; static getA() { return this.#a; } static getB() { return this.#b; } } assertSame(C, C.getA()); assertSame(C, C.getB()()); } { class C { static #a = this; static #b = function() { return this; }; static getA() { return this.#a; } static getB() { return this.#b; } } assertSame(C, C.getA()); assertSame(C, C.getB().call(C)); assertSame(undefined, C.getB()()); } { class C { static #a = function() { return 1 }; static getA() {return this.#a;} } assertEquals('#a', C.getA().name); } { let d = function() { return new.target; } class C { static #c = d; static getC() { return this.#c; } } assertEquals(undefined, C.getC()()); assertSame(new d, new (C.getC())); } { class C { static #a = 1; static getA(instance) { return instance.#a; } } class B { } assertEquals(undefined, C.a); assertEquals(1, C.getA(C)); assertThrows(() => C.getA(B), TypeError); } { class A { static #a = 1; static getA() { return this.#a; } } class B extends A {} assertThrows(() => B.getA(), TypeError); } { class A { static #a = 1; static getA() { return A.#a; } } class B extends A {} assertSame(1, B.getA()); } { let prototypeLookup = false; class A { static set a(val) { prototypeLookup = true; } static get a() { return undefined; } } class C extends A { static #a = 1; static getA() { return this.#a; } } assertEquals(1, C.getA()); assertEquals(false, prototypeLookup); } { class A { static a = 1; } class B extends A { static #b = this.a; static getB() { return this.#b; } } assertEquals(1, B.getB()); } { class A { static #a = 1; static getA() { return this.#a; } } class B extends A { static getA() { return super.getA(); } } assertThrows(() => B.getA(), TypeError); } { class A { static #a = 1; static getA() { return this.#a;} } class B extends A { static #a = 2; static get_A() { return this.#a;} } assertEquals(1, A.getA()); assertThrows(() => B.getA(), TypeError); assertEquals(2, B.get_A()); } { let foo = undefined; class A { static #a = (function() { foo = 1; })(); } assertEquals(1, foo); } { let foo = undefined; class A extends class {} { static #a = (function() { foo = 1; })(); } assertEquals(1, foo); } { function makeClass() { return class { static #a; static setA(val) { this.#a = val; } static getA() { return this.#a; } } } let classA = makeClass(); let classB = makeClass(); assertEquals(undefined, classA.getA()); assertEquals(undefined, classB.getA()); classA.setA(3); assertEquals(3, classA.getA()); assertEquals(undefined, classB.getA()); classB.setA(5); assertEquals(3, classA.getA()); assertEquals(5, classB.getA()); assertThrows(() => classA.getA.call(classB), TypeError); assertThrows(() => classB.getA.call(classA), TypeError); } { let value = undefined; new class { static #a = 1; static getA() { return this.#a; } constructor() { new class C { static #a = 2; constructor() { value = C.#a; } } } } assertEquals(2, value); } { class A { static #a = 1; static b = class { static getA() { return this.#a; } static get_A(val) { return val.#a; } } } assertEquals(1, A.b.getA.call(A)); assertEquals(1, A.b.get_A(A)); } { assertThrows(() => class { static b = this.#a; static #a = 1 }, TypeError); } { let symbol = Symbol(); class C { static #a = 1; static [symbol] = 1; static getA() { return this.#a; } static setA(val) { this.#a = val; } } var p = new Proxy(C, { get: function(target, name) { if (typeof(arg) === 'symbol') { assertFalse(%SymbolIsPrivate(name)); } return target[name]; } }); assertThrows(() => p.getA(), TypeError); assertThrows(() => p.setA(1), TypeError); assertEquals(1, p[symbol]); } { class C { static #b = Object.freeze(this); static getA() { return this.#a; } static #a = 1; } assertEquals(1, C.getA()); } { class C { static #a = 1; static getA() { return eval('this.#a'); } } assertEquals(1, C.getA()); } { var C; eval('C = class { static #a = 1; static getA() { return eval(\'this.#a\'); }}'); assertEquals(1, C.getA()); } { class C { static #a = 1; static getA() { return this.#a; } static setA() { eval('this.#a = 4'); } } assertEquals(1, C.getA()); C.setA(); assertEquals(4, C.getA()); } { class C { static getA() { return eval('this.#a'); } } assertThrows(() => C.getA(), SyntaxError); }