Skip to content

Commit

Permalink
Merge a39c471 into 8036a49
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored Aug 2, 2020
2 parents 8036a49 + a39c471 commit 275f4ab
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 89 deletions.
176 changes: 97 additions & 79 deletions boa/src/builtins/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,66 +13,94 @@ use crate::builtins::{
use crate::BoaProfiler;

impl Object {
/// Check if object has property.
/// Check if the ordinary object is extensible.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
pub fn has_property(&self, property_key: &PropertyKey) -> bool {
let prop = self.get_own_property(property_key);
if prop.value.is_none() {
let parent: Value = self.get_prototype_of();
if !parent.is_null() {
// the parent value variant should be an object
// In the unlikely event it isn't return false
return match parent {
Value::Object(ref obj) => obj.borrow().has_property(property_key),
_ => false,
};
}
return false;
}

true
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
#[inline]
fn ordinary_is_extensible(&self) -> bool {
self.extensible
}

/// Check if it is extensible.
/// Determine whether it is permitted to add additional properties to this object.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
/// [spec]: https://tc39.es/ecma262/#table-5
#[inline]
pub fn is_extensible(&self) -> bool {
self.extensible
self.ordinary_is_extensible()
}

/// Disable extensibility.
/// Prevent further extensions to ordinary object.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
/// [spec]: https://tc39.es/ecma262/#sec-ordinaryisextensible
#[inline]
pub fn prevent_extensions(&mut self) -> bool {
fn ordinary_prevent_extensions(&mut self) -> bool {
self.extensible = false;
true
}

/// Delete property.
pub fn delete(&mut self, property_key: &PropertyKey) -> bool {
let desc = self.get_own_property(property_key);
if desc
.value
.clone()
.expect("unable to get value")
.is_undefined()
{
/// Control whether new properties may be added to this object.
/// Returns `true` if the operation was successful or `false`
/// if the operation was unsuccessful.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#table-5
#[inline]
pub fn prevent_extensions(&mut self) -> bool {
self.ordinary_prevent_extensions()
}

/// Return a bool value indicating whether this ordinay object already has either an own
/// or inherited property with the specified key.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#table-5
fn ordinary_has_property(&self, key: &PropertyKey) -> bool {
if self.get_own_property(key).is_some() {
return true;
}

if let Value::Object(ref object) = self.get_prototype_of() {
let object = object.borrow();
object.has_property(key)
} else {
false
}
}

/// Return a bool value indicating whether this ordinay object already has either an own
/// or inherited property with the specified key.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
pub fn has_property(&self, key: &PropertyKey) -> bool {
self.ordinary_has_property(key)
}

/// Delete property.
pub fn delete(&mut self, key: &PropertyKey) -> bool {
let desc = if let Some(desc) = self.get_own_property(key) {
desc
} else {
return true;
};

if desc.configurable_or(false) {
self.remove_property(&property_key.to_string());
self.remove_property(&key.to_string());
return true;
}

Expand All @@ -81,26 +109,17 @@ impl Object {

/// [[Get]]
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver
pub fn get(&self, property_key: &PropertyKey) -> Value {
let desc = self.get_own_property(property_key);
if desc.value.clone().is_none()
|| desc
.value
.clone()
.expect("Failed to get object")
.is_undefined()
{
// parent will either be null or an Object
let parent = self.get_prototype_of();
if parent.is_null() {
return Value::undefined();
}

let parent_obj = Object::from(&parent).expect("Failed to get object");

return parent_obj.get(property_key);
pub fn get(&self, key: &PropertyKey) -> Value {
let desc = self.get_own_property(key);
if desc.is_none() {
return if let Some(object) = self.get_prototype_of().as_object() {
object.get(key)
} else {
Value::undefined()
};
}

let desc = desc.unwrap();
if desc.is_data_descriptor() {
return desc.value.clone().expect("failed to extract value");
}
Expand All @@ -116,22 +135,22 @@ impl Object {

/// [[Set]]
/// <https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver>
pub fn set(&mut self, property_key: &PropertyKey, val: Value) -> bool {
pub fn set(&mut self, key: &PropertyKey, val: Value) -> bool {
let _timer = BoaProfiler::global().start_event("Object::set", "object");

// Fetch property key
let mut own_desc = self.get_own_property(property_key);
// [2]
if own_desc.is_none() {
let mut own_desc = if let Some(desc) = self.get_own_property(key) {
desc
} else {
let parent = self.get_prototype_of();
if !parent.is_null() {
// TODO: come back to this
}
own_desc = Property::data_descriptor(
Property::data_descriptor(
Value::undefined(),
Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE,
);
}
)
};
// [3]
if own_desc.is_data_descriptor() {
if !own_desc.writable() {
Expand All @@ -140,7 +159,7 @@ impl Object {

// Change value on the current descriptor
own_desc = own_desc.value(val);
return self.define_own_property(property_key, own_desc);
return self.define_own_property(key, own_desc);
}
// [4]
debug_assert!(own_desc.is_accessor_descriptor());
Expand All @@ -161,7 +180,9 @@ impl Object {
pub fn define_own_property(&mut self, property_key: &PropertyKey, desc: Property) -> bool {
let _timer = BoaProfiler::global().start_event("Object::define_own_property", "object");

let mut current = self.get_own_property(property_key);
let mut current = self
.get_own_property(property_key)
.unwrap_or_else(Property::empty);
let extensible = self.is_extensible();

// https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
Expand Down Expand Up @@ -261,13 +282,25 @@ impl Object {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p
pub fn get_own_property(&self, property_key: &PropertyKey) -> Property {
pub fn get_own_property(&self, property_key: &PropertyKey) -> Option<Property> {
let _timer = BoaProfiler::global().start_event("Object::get_own_property", "object");

// Prop could either be a String or Symbol
match property_key {
PropertyKey::String(ref st) => {
self.properties().get(st).map_or_else(Property::empty, |v| {
PropertyKey::String(ref st) => self.properties().get(st).map(|v| {
let mut d = Property::empty();
if v.is_data_descriptor() {
d.value = v.value.clone();
} else {
debug_assert!(v.is_accessor_descriptor());
d.get = v.get.clone();
d.set = v.set.clone();
}
d.attribute = v.attribute;
d
}),
PropertyKey::Symbol(ref symbol) => {
self.symbol_properties().get(&symbol.hash()).map(|v| {
let mut d = Property::empty();
if v.is_data_descriptor() {
d.value = v.value.clone();
Expand All @@ -280,21 +313,6 @@ impl Object {
d
})
}
PropertyKey::Symbol(ref symbol) => self
.symbol_properties()
.get(&symbol.hash())
.map_or_else(Property::empty, |v| {
let mut d = Property::empty();
if v.is_data_descriptor() {
d.value = v.value.clone();
} else {
debug_assert!(v.is_accessor_descriptor());
d.get = v.get.clone();
d.set = v.set.clone();
}
d.attribute = v.attribute;
d
}),
}
}

Expand Down
20 changes: 10 additions & 10 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,16 +561,16 @@ pub fn property_is_enumerable(this: &Value, args: &[Value], ctx: &mut Interprete
Some(key) => key,
};

let property_key = ctx.to_property_key(key)?;
let own_property = ctx.to_object(this).map(|obj| {
obj.as_object()
.expect("Unable to deref object")
.get_own_property(&property_key)
});

Ok(own_property.map_or(Value::from(false), |own_prop| {
Value::from(own_prop.enumerable_or(false))
}))
let key = ctx.to_property_key(key)?;
let property = ctx
.to_object(this)?
.as_object()
.expect("Unable to deref object")
.get_own_property(&key);

Ok(property
.map_or(false, |own_prop| own_prop.enumerable_or(false))
.into())
}

/// Initialise the `Object` object on the global object.
Expand Down

0 comments on commit 275f4ab

Please sign in to comment.