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