|
|
|
@ -5,7 +5,12 @@
|
|
|
|
|
//!
|
|
|
|
|
//! [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
|
|
|
|
|
|
|
|
|
|
use super::{JsPrototype, PROTOTYPE}; |
|
|
|
|
use std::ops::{Deref, DerefMut}; |
|
|
|
|
|
|
|
|
|
use super::{ |
|
|
|
|
shape::slot::{Slot, SlotAttributes}, |
|
|
|
|
JsPrototype, PROTOTYPE, |
|
|
|
|
}; |
|
|
|
|
use crate::{ |
|
|
|
|
context::intrinsics::{StandardConstructor, StandardConstructors}, |
|
|
|
|
object::JsObject, |
|
|
|
@ -28,6 +33,52 @@ pub(super) mod string;
|
|
|
|
|
pub(crate) use array::ARRAY_EXOTIC_INTERNAL_METHODS; |
|
|
|
|
pub(crate) use integer_indexed::integer_indexed_element_set; |
|
|
|
|
|
|
|
|
|
/// A lightweight wrapper around [`Context`] used in [`InternalObjectMethods`].
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub(crate) struct InternalMethodContext<'ctx> { |
|
|
|
|
context: &'ctx mut Context, |
|
|
|
|
slot: Slot, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'ctx> InternalMethodContext<'ctx> { |
|
|
|
|
/// Create a new [`InternalMethodContext`].
|
|
|
|
|
pub(crate) fn new(context: &'ctx mut Context) -> Self { |
|
|
|
|
Self { |
|
|
|
|
context, |
|
|
|
|
slot: Slot::new(), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Gets the [`Slot`] associated with this [`InternalMethodContext`].
|
|
|
|
|
#[inline] |
|
|
|
|
pub(crate) fn slot(&mut self) -> &mut Slot { |
|
|
|
|
&mut self.slot |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Deref for InternalMethodContext<'_> { |
|
|
|
|
type Target = Context; |
|
|
|
|
|
|
|
|
|
#[inline] |
|
|
|
|
fn deref(&self) -> &Self::Target { |
|
|
|
|
self.context |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl DerefMut for InternalMethodContext<'_> { |
|
|
|
|
#[inline] |
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target { |
|
|
|
|
self.context |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'context> From<&'context mut Context> for InternalMethodContext<'context> { |
|
|
|
|
#[inline] |
|
|
|
|
fn from(context: &'context mut Context) -> Self { |
|
|
|
|
Self::new(context) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl JsObject { |
|
|
|
|
/// Internal method `[[GetPrototypeOf]]`
|
|
|
|
|
///
|
|
|
|
@ -97,7 +148,7 @@ impl JsObject {
|
|
|
|
|
pub(crate) fn __get_own_property__( |
|
|
|
|
&self, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<Option<PropertyDescriptor>> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::__get_own_property__", "object"); |
|
|
|
|
(self.vtable().__get_own_property__)(self, key, context) |
|
|
|
@ -115,7 +166,7 @@ impl JsObject {
|
|
|
|
|
&self, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
desc: PropertyDescriptor, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::__define_own_property__", "object"); |
|
|
|
|
(self.vtable().__define_own_property__)(self, key, desc, context) |
|
|
|
@ -132,7 +183,7 @@ impl JsObject {
|
|
|
|
|
pub(crate) fn __has_property__( |
|
|
|
|
&self, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::__has_property__", "object"); |
|
|
|
|
(self.vtable().__has_property__)(self, key, context) |
|
|
|
@ -150,7 +201,7 @@ impl JsObject {
|
|
|
|
|
&self, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
receiver: JsValue, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<JsValue> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::__get__", "object"); |
|
|
|
|
(self.vtable().__get__)(self, key, receiver, context) |
|
|
|
@ -169,7 +220,7 @@ impl JsObject {
|
|
|
|
|
key: PropertyKey, |
|
|
|
|
value: JsValue, |
|
|
|
|
receiver: JsValue, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::__set__", "object"); |
|
|
|
|
(self.vtable().__set__)(self, key, value, receiver, context) |
|
|
|
@ -183,7 +234,11 @@ impl JsObject {
|
|
|
|
|
/// - [ECMAScript reference][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-delete-p
|
|
|
|
|
pub(crate) fn __delete__(&self, key: &PropertyKey, context: &mut Context) -> JsResult<bool> { |
|
|
|
|
pub(crate) fn __delete__( |
|
|
|
|
&self, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::__delete__", "object"); |
|
|
|
|
(self.vtable().__delete__)(self, key, context) |
|
|
|
|
} |
|
|
|
@ -215,6 +270,7 @@ impl JsObject {
|
|
|
|
|
/// - [ECMAScript reference][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
|
|
|
|
|
#[track_caller] |
|
|
|
|
pub(crate) fn __call__(&self, argument_count: usize) -> CallValue { |
|
|
|
|
CallValue::Pending { |
|
|
|
|
func: self.vtable().__call__, |
|
|
|
@ -233,6 +289,7 @@ impl JsObject {
|
|
|
|
|
/// - [ECMAScript reference][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
|
|
|
|
|
#[track_caller] |
|
|
|
|
pub(crate) fn __construct__(&self, argument_count: usize) -> CallValue { |
|
|
|
|
CallValue::Pending { |
|
|
|
|
func: self.vtable().__construct__, |
|
|
|
@ -283,19 +340,36 @@ pub(crate) struct InternalObjectMethods {
|
|
|
|
|
pub(crate) __set_prototype_of__: fn(&JsObject, JsPrototype, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __is_extensible__: fn(&JsObject, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __prevent_extensions__: fn(&JsObject, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __get_own_property__: |
|
|
|
|
fn(&JsObject, &PropertyKey, &mut Context) -> JsResult<Option<PropertyDescriptor>>, |
|
|
|
|
pub(crate) __define_own_property__: |
|
|
|
|
fn(&JsObject, &PropertyKey, PropertyDescriptor, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __has_property__: fn(&JsObject, &PropertyKey, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __get__: fn(&JsObject, &PropertyKey, JsValue, &mut Context) -> JsResult<JsValue>, |
|
|
|
|
pub(crate) __set__: |
|
|
|
|
fn(&JsObject, PropertyKey, JsValue, JsValue, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __delete__: fn(&JsObject, &PropertyKey, &mut Context) -> JsResult<bool>, |
|
|
|
|
pub(crate) __own_property_keys__: fn(&JsObject, &mut Context) -> JsResult<Vec<PropertyKey>>, |
|
|
|
|
pub(crate) __call__: fn(&JsObject, argument_count: usize, &mut Context) -> JsResult<CallValue>, |
|
|
|
|
pub(crate) __get_own_property__: fn( |
|
|
|
|
&JsObject, |
|
|
|
|
&PropertyKey, |
|
|
|
|
&mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<Option<PropertyDescriptor>>, |
|
|
|
|
pub(crate) __define_own_property__: fn( |
|
|
|
|
&JsObject, |
|
|
|
|
&PropertyKey, |
|
|
|
|
PropertyDescriptor, |
|
|
|
|
&mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool>, |
|
|
|
|
pub(crate) __has_property__: |
|
|
|
|
fn(&JsObject, &PropertyKey, &mut InternalMethodContext<'_>) -> JsResult<bool>, |
|
|
|
|
pub(crate) __get__: |
|
|
|
|
fn(&JsObject, &PropertyKey, JsValue, &mut InternalMethodContext<'_>) -> JsResult<JsValue>, |
|
|
|
|
pub(crate) __set__: fn( |
|
|
|
|
&JsObject, |
|
|
|
|
PropertyKey, |
|
|
|
|
JsValue, |
|
|
|
|
JsValue, |
|
|
|
|
&mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool>, |
|
|
|
|
pub(crate) __delete__: |
|
|
|
|
fn(&JsObject, &PropertyKey, &mut InternalMethodContext<'_>) -> JsResult<bool>, |
|
|
|
|
pub(crate) __own_property_keys__: |
|
|
|
|
fn(&JsObject, context: &mut Context) -> JsResult<Vec<PropertyKey>>, |
|
|
|
|
pub(crate) __call__: |
|
|
|
|
fn(&JsObject, argument_count: usize, context: &mut Context) -> JsResult<CallValue>, |
|
|
|
|
pub(crate) __construct__: |
|
|
|
|
fn(&JsObject, argument_count: usize, &mut Context) -> JsResult<CallValue>, |
|
|
|
|
fn(&JsObject, argument_count: usize, context: &mut Context) -> JsResult<CallValue>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The return value of an internal method (`[[Call]]` or `[[Construct]]`).
|
|
|
|
@ -447,7 +521,7 @@ pub(crate) fn ordinary_prevent_extensions(
|
|
|
|
|
pub(crate) fn ordinary_get_own_property( |
|
|
|
|
obj: &JsObject, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
_context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<Option<PropertyDescriptor>> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::ordinary_get_own_property", "object"); |
|
|
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
|
|
@ -464,7 +538,7 @@ pub(crate) fn ordinary_get_own_property(
|
|
|
|
|
// 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
|
|
|
|
|
// 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
|
|
|
|
|
// 9. Return D.
|
|
|
|
|
Ok(obj.borrow().properties.get(key)) |
|
|
|
|
Ok(obj.borrow().properties.get_with_slot(key, context.slot())) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Abstract operation `OrdinaryDefineOwnProperty`.
|
|
|
|
@ -477,9 +551,10 @@ pub(crate) fn ordinary_define_own_property(
|
|
|
|
|
obj: &JsObject, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
desc: PropertyDescriptor, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::ordinary_define_own_property", "object"); |
|
|
|
|
|
|
|
|
|
// 1. Let current be ? O.[[GetOwnProperty]](P).
|
|
|
|
|
let current = obj.__get_own_property__(key, context)?; |
|
|
|
|
|
|
|
|
@ -492,6 +567,7 @@ pub(crate) fn ordinary_define_own_property(
|
|
|
|
|
extensible, |
|
|
|
|
desc, |
|
|
|
|
current, |
|
|
|
|
context.slot(), |
|
|
|
|
)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -504,18 +580,23 @@ pub(crate) fn ordinary_define_own_property(
|
|
|
|
|
pub(crate) fn ordinary_has_property( |
|
|
|
|
obj: &JsObject, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::ordinary_has_property", "object"); |
|
|
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
|
|
|
// 2. Let hasOwn be ? O.[[GetOwnProperty]](P).
|
|
|
|
|
// 3. If hasOwn is not undefined, return true.
|
|
|
|
|
if obj.__get_own_property__(key, context)?.is_some() { |
|
|
|
|
context.slot().attributes |= SlotAttributes::FOUND; |
|
|
|
|
|
|
|
|
|
Ok(true) |
|
|
|
|
} else { |
|
|
|
|
// 4. Let parent be ? O.[[GetPrototypeOf]]().
|
|
|
|
|
let parent = obj.__get_prototype_of__(context)?; |
|
|
|
|
|
|
|
|
|
context.slot().set_not_cachable_if_already_prototype(); |
|
|
|
|
context.slot().attributes |= SlotAttributes::PROTOTYPE; |
|
|
|
|
|
|
|
|
|
parent |
|
|
|
|
// 5. If parent is not null, then
|
|
|
|
|
// a. Return ? parent.[[HasProperty]](P).
|
|
|
|
@ -534,7 +615,7 @@ pub(crate) fn ordinary_get(
|
|
|
|
|
obj: &JsObject, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
receiver: JsValue, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<JsValue> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::ordinary_get", "object"); |
|
|
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
|
|
@ -544,6 +625,9 @@ pub(crate) fn ordinary_get(
|
|
|
|
|
None => { |
|
|
|
|
// a. Let parent be ? O.[[GetPrototypeOf]]().
|
|
|
|
|
if let Some(parent) = obj.__get_prototype_of__(context)? { |
|
|
|
|
context.slot().set_not_cachable_if_already_prototype(); |
|
|
|
|
context.slot().attributes |= SlotAttributes::PROTOTYPE; |
|
|
|
|
|
|
|
|
|
// c. Return ? parent.[[Get]](P, Receiver).
|
|
|
|
|
parent.__get__(key, receiver, context) |
|
|
|
|
} |
|
|
|
@ -552,20 +636,24 @@ pub(crate) fn ordinary_get(
|
|
|
|
|
Ok(JsValue::undefined()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Some(ref desc) => match desc.kind() { |
|
|
|
|
// 4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
|
|
|
|
|
DescriptorKind::Data { |
|
|
|
|
value: Some(value), .. |
|
|
|
|
} => Ok(value.clone()), |
|
|
|
|
// 5. Assert: IsAccessorDescriptor(desc) is true.
|
|
|
|
|
// 6. Let getter be desc.[[Get]].
|
|
|
|
|
DescriptorKind::Accessor { get: Some(get), .. } if !get.is_undefined() => { |
|
|
|
|
// 8. Return ? Call(getter, Receiver).
|
|
|
|
|
get.call(&receiver, &[], context) |
|
|
|
|
Some(ref desc) => { |
|
|
|
|
context.slot().attributes |= SlotAttributes::FOUND; |
|
|
|
|
|
|
|
|
|
match desc.kind() { |
|
|
|
|
// 4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
|
|
|
|
|
DescriptorKind::Data { |
|
|
|
|
value: Some(value), .. |
|
|
|
|
} => Ok(value.clone()), |
|
|
|
|
// 5. Assert: IsAccessorDescriptor(desc) is true.
|
|
|
|
|
// 6. Let getter be desc.[[Get]].
|
|
|
|
|
DescriptorKind::Accessor { get: Some(get), .. } if !get.is_undefined() => { |
|
|
|
|
// 8. Return ? Call(getter, Receiver).
|
|
|
|
|
get.call(&receiver, &[], context) |
|
|
|
|
} |
|
|
|
|
// 7. If getter is undefined, return undefined.
|
|
|
|
|
_ => Ok(JsValue::undefined()), |
|
|
|
|
} |
|
|
|
|
// 7. If getter is undefined, return undefined.
|
|
|
|
|
_ => Ok(JsValue::undefined()), |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -580,7 +668,7 @@ pub(crate) fn ordinary_set(
|
|
|
|
|
key: PropertyKey, |
|
|
|
|
value: JsValue, |
|
|
|
|
receiver: JsValue, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::ordinary_set", "object"); |
|
|
|
|
|
|
|
|
@ -599,11 +687,20 @@ pub(crate) fn ordinary_set(
|
|
|
|
|
// a. Let parent be ? O.[[GetPrototypeOf]]().
|
|
|
|
|
// b. If parent is not null, then
|
|
|
|
|
else if let Some(parent) = obj.__get_prototype_of__(context)? { |
|
|
|
|
context.slot().set_not_cachable_if_already_prototype(); |
|
|
|
|
context.slot().attributes |= SlotAttributes::PROTOTYPE; |
|
|
|
|
|
|
|
|
|
// i. Return ? parent.[[Set]](P, V, Receiver).
|
|
|
|
|
return parent.__set__(key, value, receiver, context); |
|
|
|
|
} |
|
|
|
|
// c. Else,
|
|
|
|
|
else { |
|
|
|
|
// It's not on prototype chain.
|
|
|
|
|
context |
|
|
|
|
.slot() |
|
|
|
|
.attributes |
|
|
|
|
.remove(SlotAttributes::PROTOTYPE | SlotAttributes::NOT_CACHABLE); |
|
|
|
|
|
|
|
|
|
// i. Set ownDesc to the PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true,
|
|
|
|
|
// [[Enumerable]]: true, [[Configurable]]: true }.
|
|
|
|
|
PropertyDescriptor::builder() |
|
|
|
@ -626,6 +723,12 @@ pub(crate) fn ordinary_set(
|
|
|
|
|
return Ok(false); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// NOTE(HaledOdat): If the object and receiver are not the same then it's not inline cachable for now.
|
|
|
|
|
context.slot().attributes.set( |
|
|
|
|
SlotAttributes::NOT_CACHABLE, |
|
|
|
|
!JsObject::equals(obj, receiver), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
|
|
|
|
|
// d. If existingDescriptor is not undefined, then
|
|
|
|
|
if let Some(ref existing_desc) = receiver.__get_own_property__(&key, context)? { |
|
|
|
@ -647,12 +750,15 @@ pub(crate) fn ordinary_set(
|
|
|
|
|
context, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// e. Else
|
|
|
|
|
// i. Assert: Receiver does not currently have a property P.
|
|
|
|
|
// ii. Return ? CreateDataProperty(Receiver, P, V).
|
|
|
|
|
return receiver.create_data_property(key, value, context); |
|
|
|
|
return receiver.create_data_property_with_slot(key, value, context); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
context.slot().attributes |= SlotAttributes::FOUND; |
|
|
|
|
|
|
|
|
|
// 4. Assert: IsAccessorDescriptor(ownDesc) is true.
|
|
|
|
|
debug_assert!(own_desc.is_accessor_descriptor()); |
|
|
|
|
|
|
|
|
@ -679,7 +785,7 @@ pub(crate) fn ordinary_set(
|
|
|
|
|
pub(crate) fn ordinary_delete( |
|
|
|
|
obj: &JsObject, |
|
|
|
|
key: &PropertyKey, |
|
|
|
|
context: &mut Context, |
|
|
|
|
context: &mut InternalMethodContext<'_>, |
|
|
|
|
) -> JsResult<bool> { |
|
|
|
|
let _timer = Profiler::global().start_event("Object::ordinary_delete", "object"); |
|
|
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
|
|
@ -752,7 +858,7 @@ pub(crate) fn is_compatible_property_descriptor(
|
|
|
|
|
Profiler::global().start_event("Object::is_compatible_property_descriptor", "object"); |
|
|
|
|
|
|
|
|
|
// 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, Extensible, Desc, Current).
|
|
|
|
|
validate_and_apply_property_descriptor(None, extensible, desc, current) |
|
|
|
|
validate_and_apply_property_descriptor(None, extensible, desc, current, &mut Slot::new()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Abstract operation `ValidateAndApplyPropertyDescriptor`
|
|
|
|
@ -766,6 +872,7 @@ pub(crate) fn validate_and_apply_property_descriptor(
|
|
|
|
|
extensible: bool, |
|
|
|
|
desc: PropertyDescriptor, |
|
|
|
|
current: Option<PropertyDescriptor>, |
|
|
|
|
slot: &mut Slot, |
|
|
|
|
) -> bool { |
|
|
|
|
let _timer = |
|
|
|
|
Profiler::global().start_event("Object::validate_and_apply_property_descriptor", "object"); |
|
|
|
@ -781,7 +888,7 @@ pub(crate) fn validate_and_apply_property_descriptor(
|
|
|
|
|
// b. Assert: extensible is true.
|
|
|
|
|
|
|
|
|
|
if let Some((obj, key)) = obj_and_key { |
|
|
|
|
obj.borrow_mut().properties.insert( |
|
|
|
|
obj.borrow_mut().properties.insert_with_slot( |
|
|
|
|
key, |
|
|
|
|
// c. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then
|
|
|
|
|
if desc.is_generic_descriptor() || desc.is_data_descriptor() { |
|
|
|
@ -803,7 +910,9 @@ pub(crate) fn validate_and_apply_property_descriptor(
|
|
|
|
|
// its default value.
|
|
|
|
|
desc.into_accessor_defaulted() |
|
|
|
|
}, |
|
|
|
|
slot, |
|
|
|
|
); |
|
|
|
|
slot.attributes |= SlotAttributes::FOUND; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// e. Return true.
|
|
|
|
@ -899,7 +1008,10 @@ pub(crate) fn validate_and_apply_property_descriptor(
|
|
|
|
|
// a. For each field of Desc that is present, set the corresponding attribute of the
|
|
|
|
|
// property named P of object O to the value of the field.
|
|
|
|
|
current.fill_with(&desc); |
|
|
|
|
obj.borrow_mut().properties.insert(key, current); |
|
|
|
|
obj.borrow_mut() |
|
|
|
|
.properties |
|
|
|
|
.insert_with_slot(key, current, slot); |
|
|
|
|
slot.attributes |= SlotAttributes::FOUND; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 10. Return true.
|
|
|
|
|