2018-01-29 18:11:24 +00:00
|
|
|
// 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.
|
|
|
|
|
2019-04-30 18:47:05 +00:00
|
|
|
// Flags: --allow-natives-syntax
|
2018-01-29 18:11:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
"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));
|
|
|
|
|
2018-02-21 22:08:59 +00:00
|
|
|
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());
|
2018-01-29 18:11:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
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());
|
|
|
|
|
2018-02-21 22:08:59 +00:00
|
|
|
assertThrows(() => a.getA.call(b), TypeError);
|
|
|
|
assertThrows(() => b.getA.call(a), TypeError);
|
2018-01-29 18:11:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2018-02-21 22:08:59 +00:00
|
|
|
{
|
|
|
|
class C {
|
|
|
|
b = this.#a;
|
|
|
|
#a = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
assertThrows(() => new C, TypeError);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
class C {
|
|
|
|
#b = this.#a;
|
|
|
|
#a = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
assertThrows(() => new C, TypeError);
|
|
|
|
}
|
2018-01-29 18:11:24 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
let symbol = Symbol();
|
|
|
|
|
|
|
|
class C {
|
|
|
|
#a = 1;
|
|
|
|
[symbol] = 1;
|
|
|
|
getA() { return this.#a; }
|
2018-02-21 22:08:59 +00:00
|
|
|
setA(val) { this.#a = val; }
|
2018-01-29 18:11:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var p = new Proxy(new C, {
|
|
|
|
get: function(target, name) {
|
|
|
|
if (typeof(arg) === 'symbol') {
|
|
|
|
assertFalse(%SymbolIsPrivate(name));
|
|
|
|
}
|
|
|
|
return target[name];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-02-21 22:08:59 +00:00
|
|
|
assertThrows(() => p.getA(), TypeError);
|
|
|
|
assertThrows(() => p.setA(1), TypeError);
|
2018-01-29 18:11:24 +00:00
|
|
|
assertEquals(1, p[symbol]);
|
|
|
|
}
|
2018-02-20 21:08:39 +00:00
|
|
|
|
2018-02-21 22:08:59 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-02-20 21:08:39 +00:00
|
|
|
{
|
|
|
|
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));
|
|
|
|
}
|
2018-03-07 18:52:17 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2019-10-10 19:00:28 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
assertThrows(() => {
|
|
|
|
class A {
|
|
|
|
[this.#a] = 1;
|
|
|
|
#a = 2;
|
|
|
|
}
|
|
|
|
}, TypeError);
|
|
|
|
}
|