Skip to content

Commit e010f53

Browse files
committed
Implement proposal nonextensible-applies-to-private
1 parent 0d0e174 commit e010f53

File tree

1 file changed

+40
-11
lines changed

1 file changed

+40
-11
lines changed

core/engine/src/object/operations.rs

Lines changed: 40 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,
@@ -887,23 +888,28 @@ impl JsObject {
887888
value: JsValue,
888889
context: &mut Context,
889890
) -> JsResult<()> {
890-
// 1. If the host is a web browser, then
891-
// a. Perform ? HostEnsureCanAddPrivateElement(O).
891+
if !self.extensible() {
892+
return Err(js_error!(
893+
TypeError: "cannot add private field to non-extensible class instance"
894+
)
895+
.into());
896+
}
897+
898+
// 2. If the host is a web browser, then
899+
// a. Perform ? HostEnsureCanAddPrivateElement(O).
892900
context
893901
.host_hooks()
894902
.ensure_can_add_private_element(self, context)?;
895903

896-
// 2. Let entry be PrivateElementFind(O, P).
904+
// 3. Let entry be PrivateElementFind(O, P).
897905
let entry = self.private_element_find(name, false, false);
898906

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

906-
// 4. Append PrivateElement { [[Key]]: P, [[Kind]]: field, [[Value]]: value } to O.[[PrivateElements]].
912+
// 5. Append PrivateElement { [[Key]]: P, [[Kind]]: field, [[Value]]: value } to O.[[PrivateElements]].
907913
self.borrow_mut()
908914
.private_elements
909915
.push((name.clone(), PrivateElement::Field(value)));
@@ -931,12 +937,27 @@ impl JsObject {
931937
method,
932938
PrivateElement::Method(_) | PrivateElement::Accessor { .. }
933939
));
940+
934941
let (getter, setter) = if let PrivateElement::Accessor { getter, setter } = method {
935942
(getter.is_some(), setter.is_some())
936943
} else {
937944
(false, false)
938945
};
939946

947+
if !self.extensible() {
948+
return if getter || setter {
949+
Err(js_error!(
950+
TypeError: "cannot add private accessor to non-extensible class instance"
951+
)
952+
.into())
953+
} else {
954+
Err(js_error!(
955+
TypeError: "cannot add private method to non-extensible class instance"
956+
)
957+
.into())
958+
};
959+
}
960+
940961
// 2. If the host is a web browser, then
941962
// a. Perform ? HostEnsureCanAddPrivateElement(O).
942963
context
@@ -948,9 +969,17 @@ impl JsObject {
948969

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

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

0 commit comments

Comments
 (0)