test262/test/language/statements/class/elements/private-class-field-on-nonextensible-objects.js
Mark S. Miller 822589b1ef
[nonextensible-applies-to-private] Adding private field to non-extensible object throws (#4577)
* [nonextensible-applies-to-private] Adding private field to non-extensible object throws

* add feature nonextensible-applies-to-private

* extending tests in response to reviewer suggestions

* use const instead of let
2025-09-22 12:58:55 -07:00

118 lines
2.8 KiB
JavaScript

// Copyright (C) 2019 Caio Lima. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: It is not possible to add private fields on non-extensible objects
esid: sec-define-field
info: |
1.1 PrivateFieldAdd ( O, P, value )
1. If O.[[Extensible]] is false, throw a TypeError exception.
...
features:
- class
- class-fields-private
- class-fields-public
- nonextensible-applies-to-private
flags: [onlyStrict]
---*/
// Analogous to
// test/language/statements/class/subclass/private-class-field-on-nonextensible-return-override.js
class NonExtensibleBase {
constructor(seal) {
if (seal) Object.preventExtensions(this);
}
}
// extend superclass with private instance data field
class ClassWithPrivateField extends NonExtensibleBase {
#val;
constructor(seal) {
super(seal);
this.#val = 42;
}
val() {
return this.#val;
}
}
const t = new ClassWithPrivateField(false);
// extensible objects can be extended
assert.sameValue(t.val(), 42);
// where superclass prevented extensions & subclass extended
assert.throws(TypeError, function () {
new ClassWithPrivateField(true);
});
// extend superclass with private instance method
class ClassWithPrivateMethod extends NonExtensibleBase {
constructor(seal) {
super(seal);
}
// private methods are on the instance, so will fail
#privateMethod() {
return 42;
};
// public methods are on the prototype, so are ok.
publicMethod() {
return this.#privateMethod();
}
}
const m = new ClassWithPrivateMethod(false);
// extensible objects can be extended
assert.sameValue(m.publicMethod(), 42);
// where superclass prevented extensions & subclass extended
assert.throws(TypeError, function () {
new ClassWithPrivateMethod(true);
});
// extend superclass with private instance accessor
class ClassWithPrivateAccessor extends NonExtensibleBase {
constructor(seal) {
super(seal);
}
// private accessors are on the instance, so will fail
get #privateAccessor() {
return 42;
};
// public accessors are on the prototype, so are ok.
get publicAccessor() {
return this.#privateAccessor;
}
}
const a = new ClassWithPrivateAccessor(false);
// extensible objects can be extended
assert.sameValue(m.publicAccessor, 42);
// where superclass prevented extensions & subclass extended
assert.throws(TypeError, function () {
new ClassWithPrivateAccessor(true);
});
// base class private instance data field
class TestNonExtensibleData {
#g = (Object.preventExtensions(this), "Test262");
}
assert.throws(TypeError, function () {
new TestNonExtensibleData();
});
// base class with private static data field
assert.throws(TypeError, function () {
class TestNonExtensibleStaticData {
static #g = (Object.preventExtensions(TestNonExtensibleStaticData), "Test262");
}
});