node/deps/v8/test/mjsunit/harmony/private-accessors.js
Michaël Zasso 974ab4060f
deps: update V8 to 9.8.177.9
PR-URL: https://github.com/nodejs/node/pull/41610
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
2022-02-02 17:23:18 +01:00

219 lines
4.5 KiB
JavaScript

// Copyright 2019 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";
// Complementary private accessors.
{
let store = 1;
class C {
get #a() { return store; }
set #a(val) { store = val; }
incA() { this.#a++; } // CountOperation
setA(val) { this.#a = val; }
getA() { return this.#a; }
}
const c = new C;
assertEquals(store, c.getA());
assertEquals(1, c.getA());
c.setA(2);
assertEquals(store, c.getA());
assertEquals(2, c.getA());
c.incA();
assertEquals(store, c.getA());
assertEquals(3, c.getA());
}
// Compound assignment.
{
let store;
class A {
get #a() { return store; }
set #a(val) { store = val; }
getA() { return this.#a; }
constructor(val) {
({ y: this.#a } = val);
}
}
const a = new A({y: 'test'});
assertEquals('test', a.getA());
}
// Accessing super in private accessors.
{
class A { foo(val) {} }
class C extends A {
set #a(val) { super.foo(val); }
}
new C();
class D extends A {
get #a() { return super.foo; }
}
new D();
class E extends A {
set #a(val) { super.foo(val); }
get #a() { return super.foo; }
}
new E();
}
// Nested private accessors.
{
class C {
get #a() {
let storeD = 'd';
class D {
// Shadows outer #a
get #a() { return storeD; }
getD() { return this.#a; }
}
return new D;
}
getA() {
return this.#a;
}
}
assertEquals('d', new C().getA().getD());
}
{
assertThrows(() => {
class A {
[this.#a] = 1;
get #a() {}
}
}, TypeError);
assertThrows(() => {
class A {
[this.#a] = 1;
set #a(val) {}
}
}, TypeError);
assertThrows(() => {
class A {
[this.#a] = 1;
set #a(val) {}
get #a() {}
}
}, TypeError);
}
// Duplicate private accessors.
// https://tc39.es/proposal-private-methods/#sec-static-semantics-early-errors
{
assertThrows('class C { get #a() {} get #a() {} }', SyntaxError);
assertThrows('class C { set #a(val) {} set #a(val) {} }', SyntaxError);
}
// Test that the lhs don't get re-evaluated in the assignment, and it always
// gets evaluated before the rhs.
{
let objectCount = 0;
let operations = [];
let lhsObject = {
get property() {
operations.push('lhsEvaluation');
return new Foo();
}
};
let rhs = () => {operations.push('rhsEvaluation'); return 1; };
class Foo {
id = objectCount++;
get #foo() {
operations.push('get', this.id);
return 0;
}
set #foo(x) {
operations.push('set', this.id);
}
static compound() {
lhsObject.property.#foo += rhs();
}
static assign() {
lhsObject.property.#foo = lhsObject.property.#foo + rhs();
}
}
objectCount = 0;
operations = [];
Foo.compound();
assertEquals(1, objectCount);
assertEquals(
['lhsEvaluation', 'get', 0, 'rhsEvaluation', 'set', 0],
operations);
objectCount = 0;
operations = [];
Foo.assign();
assertEquals(2, objectCount);
assertEquals(
['lhsEvaluation', 'lhsEvaluation', 'get', 1, 'rhsEvaluation', 'set', 0],
operations);
}
// Test that the brand checks are done on the lhs evaluated before the rhs.
{
let objectCount = 0;
let operations = [];
let maximumObjects = 1;
let lhsObject = {
get property() {
operations.push('lhsEvaluation');
return (objectCount >= maximumObjects) ? {id: -1} : new Foo();
}
};
let rhs = () => {operations.push('rhsEvaluation'); return 1; };
class Foo {
id = objectCount++;
set #foo(val) {
operations.push('set', this.id);
}
get #foo() {
operations.push('get', this.id);
return 0;
}
static compound() {
lhsObject.property.#foo += rhs();
}
static assign() {
lhsObject.property.#foo = lhsObject.property.#foo + rhs();
}
}
objectCount = 0;
operations = [];
maximumObjects = 1;
Foo.compound();
assertEquals(1, objectCount);
assertEquals(
['lhsEvaluation', 'get', 0, 'rhsEvaluation', 'set', 0],
operations);
objectCount = 0;
operations = [];
maximumObjects = 2;
Foo.assign();
assertEquals(2, objectCount);
assertEquals(
['lhsEvaluation', 'lhsEvaluation', 'get', 1, 'rhsEvaluation', 'set', 0],
operations);
objectCount = 0;
operations = [];
maximumObjects = 1;
assertThrows(() => Foo.assign(), TypeError, /Receiver must be an instance of class Foo/);
assertEquals(1, objectCount);
assertEquals(['lhsEvaluation', 'lhsEvaluation'], operations);
}