Skip to content

Commit

Permalink
Extract PropertyMap struct from Object (#1425)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 authored Aug 6, 2021
1 parent fe665db commit f331694
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 61 deletions.
6 changes: 3 additions & 3 deletions boa/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl Json {
let value = holder.get_field(key.clone(), context)?;

if let Value::Object(ref object) = value {
let keys: Vec<_> = object.borrow().keys().collect();
let keys: Vec<_> = object.borrow().properties().keys().collect();

for key in keys {
let v = Self::walk(reviver, context, &mut value.clone(), &key);
Expand Down Expand Up @@ -196,7 +196,7 @@ impl Json {
.as_object()
.map(|obj| {
let object_to_return = Value::object(Object::default());
for key in obj.borrow().keys() {
for key in obj.borrow().properties().keys() {
let val = obj.__get__(&key, obj.clone().into(), context)?;
let this_arg = object.clone();
object_to_return.set_property(
Expand All @@ -222,7 +222,7 @@ impl Json {
} else if replacer_as_object.is_array() {
let mut obj_to_return = serde_json::Map::new();
let replacer_as_object = replacer_as_object.borrow();
let fields = replacer_as_object.keys().filter_map(|key| {
let fields = replacer_as_object.properties().keys().filter_map(|key| {
if key == "length" {
None
} else {
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ impl Object {
.to_object(context)?;
let descriptors = context.construct_object();

for key in object.borrow().keys() {
for key in object.borrow().properties().keys() {
let descriptor = {
let desc = object
.__get_own_property__(&key)
Expand Down
9 changes: 7 additions & 2 deletions boa/src/object/gcobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,12 @@ impl GcObject {
if rec_limiter.live {
Err(context.construct_type_error("cyclic object value"))
} else if self.is_array() {
let mut keys: Vec<u32> = self.borrow().index_property_keys().cloned().collect();
let mut keys: Vec<u32> = self
.borrow()
.properties
.index_property_keys()
.cloned()
.collect();
keys.sort_unstable();
let mut arr: Vec<JSONValue> = Vec::with_capacity(keys.len());
let this = Value::from(self.clone());
Expand All @@ -444,7 +449,7 @@ impl GcObject {
} else {
let mut new_obj = Map::new();
let this = Value::from(self.clone());
let keys: Vec<PropertyKey> = self.borrow().keys().collect();
let keys: Vec<PropertyKey> = self.borrow().properties.keys().collect();
for k in keys {
let key = k.clone();
let value = this.get_field(k.to_string(), context)?;
Expand Down
34 changes: 11 additions & 23 deletions boa/src/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,11 +526,16 @@ impl GcObject {
return Ok(false);
}

let max_value = self.borrow().index_property_keys().max().copied();
let max_value = self
.borrow()
.properties
.index_property_keys()
.max()
.copied();

if let Some(mut index) = max_value {
while index >= new_len {
let contains_index = self.borrow().indexed_properties.contains_key(&index);
let contains_index = self.borrow().properties.contains_key(&index.into());
if contains_index && !self.__delete__(&index.into()) {
new_len_desc = new_len_desc.value(index + 1);
if !new_writable {
Expand Down Expand Up @@ -661,11 +666,7 @@ impl GcObject {
#[inline]
pub fn ordinary_get_own_property(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
let object = self.borrow();
let property = match key {
PropertyKey::Index(index) => object.indexed_properties.get(index),
PropertyKey::String(ref st) => object.string_properties.get(st),
PropertyKey::Symbol(ref symbol) => object.symbol_properties.get(symbol),
};
let property = object.properties.get(key);

property.cloned()
}
Expand All @@ -679,7 +680,7 @@ impl GcObject {
#[inline]
#[track_caller]
pub fn own_property_keys(&self) -> Vec<PropertyKey> {
self.borrow().keys().collect()
self.borrow().properties.keys().collect()
}

/// The abstract operation ObjectDefineProperties
Expand Down Expand Up @@ -895,26 +896,13 @@ impl Object {
K: Into<PropertyKey>,
P: Into<PropertyDescriptor>,
{
let property = property.into();
match key.into() {
PropertyKey::Index(index) => self.indexed_properties.insert(index, property),
PropertyKey::String(ref string) => {
self.string_properties.insert(string.clone(), property)
}
PropertyKey::Symbol(ref symbol) => {
self.symbol_properties.insert(symbol.clone(), property)
}
}
self.properties.insert(key.into(), property.into())
}

/// Helper function for property removal.
#[inline]
pub(crate) fn remove(&mut self, key: &PropertyKey) -> Option<PropertyDescriptor> {
match key {
PropertyKey::Index(index) => self.indexed_properties.remove(index),
PropertyKey::String(ref string) => self.string_properties.remove(string),
PropertyKey::Symbol(ref symbol) => self.symbol_properties.remove(symbol),
}
self.properties.remove(key)
}

/// Inserts a field in the object `properties` without checking if it's writable.
Expand Down
44 changes: 15 additions & 29 deletions boa/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::{
property::{Attribute, PropertyDescriptor, PropertyKey},
BoaProfiler, Context, JsBigInt, JsString, JsSymbol, Value,
};
use rustc_hash::FxHashMap;
use std::{
any::Any,
fmt::{self, Debug, Display},
Expand All @@ -30,11 +29,11 @@ mod tests;

mod gcobject;
mod internal_methods;
mod iter;
mod property_map;

use crate::builtins::object::for_in_iterator::ForInIterator;
pub use gcobject::{GcObject, RecursionLimiter, Ref, RefMut};
pub use iter::*;
pub use property_map::*;

/// Static `prototype`, usually set on constructors as a key to point to their respective prototype object.
pub static PROTOTYPE: &str = "prototype";
Expand Down Expand Up @@ -67,11 +66,7 @@ impl<T: Any + Debug + Trace> NativeObject for T {
pub struct Object {
/// The type of the object.
pub data: ObjectData,
indexed_properties: FxHashMap<u32, PropertyDescriptor>,
/// Properties
string_properties: FxHashMap<JsString, PropertyDescriptor>,
/// Symbol Properties
symbol_properties: FxHashMap<JsSymbol, PropertyDescriptor>,
properties: PropertyMap,
/// Instance prototype `__proto__`.
prototype: Value,
/// Whether it can have new properties added to it.
Expand Down Expand Up @@ -142,9 +137,7 @@ impl Default for Object {
fn default() -> Self {
Self {
data: ObjectData::Ordinary,
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype: Value::null(),
extensible: true,
}
Expand All @@ -164,9 +157,7 @@ impl Object {

Self {
data: ObjectData::Function(function),
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype,
extensible: true,
}
Expand All @@ -191,9 +182,7 @@ impl Object {
pub fn boolean(value: bool) -> Self {
Self {
data: ObjectData::Boolean(value),
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype: Value::null(),
extensible: true,
}
Expand All @@ -204,9 +193,7 @@ impl Object {
pub fn number(value: f64) -> Self {
Self {
data: ObjectData::Number(value),
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype: Value::null(),
extensible: true,
}
Expand All @@ -220,9 +207,7 @@ impl Object {
{
Self {
data: ObjectData::String(value.into()),
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype: Value::null(),
extensible: true,
}
Expand All @@ -233,9 +218,7 @@ impl Object {
pub fn bigint(value: JsBigInt) -> Self {
Self {
data: ObjectData::BigInt(value),
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype: Value::null(),
extensible: true,
}
Expand All @@ -249,9 +232,7 @@ impl Object {
{
Self {
data: ObjectData::NativeObject(Box::new(value)),
indexed_properties: FxHashMap::default(),
string_properties: FxHashMap::default(),
symbol_properties: FxHashMap::default(),
properties: PropertyMap::default(),
prototype: Value::null(),
extensible: true,
}
Expand Down Expand Up @@ -610,6 +591,11 @@ impl Object {
_ => None,
}
}

#[inline]
pub fn properties(&self) -> &PropertyMap {
&self.properties
}
}

/// The functions binding.
Expand Down
59 changes: 56 additions & 3 deletions boa/src/object/iter.rs → boa/src/object/property_map.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,52 @@
use super::{Object, PropertyDescriptor, PropertyKey};
use crate::{JsString, JsSymbol};
use super::{PropertyDescriptor, PropertyKey};
use crate::{
gc::{Finalize, Trace},
JsString, JsSymbol,
};
use rustc_hash::FxHashMap;
use std::{collections::hash_map, iter::FusedIterator};

impl Object {
#[derive(Default, Debug, Trace, Finalize)]
pub struct PropertyMap {
indexed_properties: FxHashMap<u32, PropertyDescriptor>,
/// Properties
string_properties: FxHashMap<JsString, PropertyDescriptor>,
/// Symbol Properties
symbol_properties: FxHashMap<JsSymbol, PropertyDescriptor>,
}

impl PropertyMap {
pub fn new() -> Self {
Self::default()
}
pub fn get(&self, key: &PropertyKey) -> Option<&PropertyDescriptor> {
match key {
PropertyKey::Index(index) => self.indexed_properties.get(index),
PropertyKey::String(string) => self.string_properties.get(string),
PropertyKey::Symbol(symbol) => self.symbol_properties.get(symbol),
}
}

pub fn insert(
&mut self,
key: PropertyKey,
property: PropertyDescriptor,
) -> Option<PropertyDescriptor> {
match &key {
PropertyKey::Index(index) => self.indexed_properties.insert(*index, property),
PropertyKey::String(string) => self.string_properties.insert(string.clone(), property),
PropertyKey::Symbol(symbol) => self.symbol_properties.insert(symbol.clone(), property),
}
}

pub fn remove(&mut self, key: &PropertyKey) -> Option<PropertyDescriptor> {
match key {
PropertyKey::Index(index) => self.indexed_properties.remove(index),
PropertyKey::String(string) => self.string_properties.remove(string),
PropertyKey::Symbol(symbol) => self.symbol_properties.remove(symbol),
}
}

/// An iterator visiting all key-value pairs in arbitrary order. The iterator element type is `(PropertyKey, &'a Property)`.
///
/// This iterator does not recurse down the prototype chain.
Expand Down Expand Up @@ -103,6 +147,15 @@ impl Object {
pub fn string_property_values(&self) -> StringPropertyValues<'_> {
StringPropertyValues(self.string_properties.values())
}

#[inline]
pub fn contains_key(&self, key: &PropertyKey) -> bool {
match key {
PropertyKey::Index(index) => self.indexed_properties.contains_key(index),
PropertyKey::String(string) => self.string_properties.contains_key(string),
PropertyKey::Symbol(symbol) => self.symbol_properties.contains_key(symbol),
}
}
}

/// An iterator over the property entries of an `Object`
Expand Down
1 change: 1 addition & 0 deletions boa/src/value/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ macro_rules! print_obj_value {
(impl $v:expr, $f:expr) => {
$v
.borrow()
.properties()
.iter()
.map($f)
.collect::<Vec<String>>()
Expand Down

0 comments on commit f331694

Please sign in to comment.