Skip to content

Commit f707d11

Browse files
authored
Implement proposal nonextensible-applies-to-private (#4511)
Implements the [`nonextensible-applies-to-private` proposal](https://github.com/tc39/proposal-nonextensible-applies-to-private). Since it's such a small change and it's already on stage 3, I decided to not gate this behind the experimental feature.
1 parent 31c7215 commit f707d11

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

core/engine/src/object/operations.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::internal_methods::InternalMethodPropertyContext;
2+
use crate::js_error;
23
use crate::value::JsVariant;
34
use crate::{
45
Context, JsResult, JsSymbol, JsValue,
@@ -888,22 +889,28 @@ impl JsObject {
888889
context: &mut Context,
889890
) -> JsResult<()> {
890891
// 1. If the host is a web browser, then
891-
// a. Perform ? HostEnsureCanAddPrivateElement(O).
892+
// a. Perform ? HostEnsureCanAddPrivateElement(O).
892893
context
893894
.host_hooks()
894895
.ensure_can_add_private_element(self, context)?;
895896

896-
// 2. Let entry be PrivateElementFind(O, P).
897+
// 2. If ? IsExtensible(O) is false, throw a TypeError exception.
898+
// NOTE: From <https://tc39.es/proposal-nonextensible-applies-to-private/#sec-privatefieldadd>
899+
if !self.is_extensible(context)? {
900+
return Err(js_error!(
901+
TypeError: "cannot add private field to non-extensible class instance"
902+
));
903+
}
904+
905+
// 3. Let entry be PrivateElementFind(O, P).
897906
let entry = self.private_element_find(name, false, false);
898907

899-
// 3. If entry is not empty, throw a TypeError exception.
908+
// 4. If entry is not empty, throw a TypeError exception.
900909
if entry.is_some() {
901-
return Err(JsNativeError::typ()
902-
.with_message("Private field already exists on prototype")
903-
.into());
910+
return Err(js_error!(TypeError: "private field already exists on prototype"));
904911
}
905912

906-
// 4. Append PrivateElement { [[Key]]: P, [[Kind]]: field, [[Value]]: value } to O.[[PrivateElements]].
913+
// 5. Append PrivateElement { [[Key]]: P, [[Kind]]: field, [[Value]]: value } to O.[[PrivateElements]].
907914
self.borrow_mut()
908915
.private_elements
909916
.push((name.clone(), PrivateElement::Field(value)));
@@ -931,26 +938,47 @@ impl JsObject {
931938
method,
932939
PrivateElement::Method(_) | PrivateElement::Accessor { .. }
933940
));
941+
934942
let (getter, setter) = if let PrivateElement::Accessor { getter, setter } = method {
935943
(getter.is_some(), setter.is_some())
936944
} else {
937945
(false, false)
938946
};
939947

940948
// 2. If the host is a web browser, then
941-
// a. Perform ? HostEnsureCanAddPrivateElement(O).
949+
// a. Perform ? HostEnsureCanAddPrivateElement(O).
942950
context
943951
.host_hooks()
944952
.ensure_can_add_private_element(self, context)?;
945953

954+
// 3. If ? IsExtensible(O) is false, throw a TypeError exception.
955+
// NOTE: From <https://tc39.es/proposal-nonextensible-applies-to-private/#sec-privatemethodoraccessoradd>
956+
if !self.is_extensible(context)? {
957+
return if getter || setter {
958+
Err(js_error!(
959+
TypeError: "cannot add private accessor to non-extensible class instance"
960+
))
961+
} else {
962+
Err(js_error!(
963+
TypeError: "cannot add private method to non-extensible class instance"
964+
))
965+
};
966+
}
967+
946968
// 3. Let entry be PrivateElementFind(O, method.[[Key]]).
947969
let entry = self.private_element_find(name, getter, setter);
948970

949971
// 4. If entry is not empty, throw a TypeError exception.
950972
if entry.is_some() {
951-
return Err(JsNativeError::typ()
952-
.with_message("Private method already exists on prototype")
953-
.into());
973+
return if getter || setter {
974+
Err(js_error!(
975+
TypeError: "private accessor already exists on class instance"
976+
))
977+
} else {
978+
Err(js_error!(
979+
TypeError: "private method already exists on class instance"
980+
))
981+
};
954982
}
955983

956984
// 5. Append method to O.[[PrivateElements]].

0 commit comments

Comments
 (0)