Skip to content

Commit

Permalink
Extract PropertyMap struct from Object
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Jul 22, 2021
1 parent f6d5733 commit c572930
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 59 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 @@ -221,7 +221,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 @@ -194,7 +194,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 @@ -424,7 +424,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 @@ -440,7 +445,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
26 changes: 5 additions & 21 deletions boa/src/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ impl GcObject {
let keys_to_delete = {
let obj = self.borrow();
let mut keys = obj
.properties
.index_property_keys()
.filter(|&&k| k >= new_len)
.cloned()
Expand Down Expand Up @@ -684,11 +685,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 @@ -702,7 +699,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 @@ -923,26 +920,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::{AccessorDescriptor, Attribute, DataDescriptor, PropertyDescriptor, PropertyKey},
BoaProfiler, Context, JsBigInt, JsString, JsSymbol, Value,
};
use rustc_hash::FxHashMap;
use std::{
any::Any,
fmt::{self, Debug, Display},
Expand All @@ -29,11 +28,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 @@ -66,11 +65,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 @@ -141,9 +136,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 @@ -163,9 +156,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 @@ -190,9 +181,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 @@ -203,9 +192,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 @@ -219,9 +206,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 @@ -232,9 +217,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 @@ -248,9 +231,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 @@ -609,6 +590,11 @@ impl Object {
_ => None,
}
}

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

/// The functions binding.
Expand Down
50 changes: 47 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
1 change: 1 addition & 0 deletions boa/src/value/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,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 c572930

Please sign in to comment.