Skip to content

Commit

Permalink
More Object and Value abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed May 29, 2020
1 parent 8745947 commit 896ba46
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 50 deletions.
2 changes: 1 addition & 1 deletion boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ impl Array {
let prototype = Value::new_object(None);
let length = Property::default().value(Value::from(0));

prototype.set_property_slice("length", length);
prototype.set_property("length", length);

make_builtin_fn(Self::concat, "concat", &prototype, 1);
make_builtin_fn(Self::push, "push", &prototype, 1);
Expand Down
4 changes: 2 additions & 2 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,14 +428,14 @@ pub fn make_constructor_fn(
.writable(false)
.configurable(false)
.enumerable(false);
constructor_val.set_property_slice("length", length);
constructor_val.set_property("length", length);

let name = Property::new()
.value(Value::from(name))
.writable(false)
.configurable(false)
.enumerable(false);
constructor_val.set_property_slice("name", name);
constructor_val.set_property("name", name);

constructor_val
}
Expand Down
18 changes: 15 additions & 3 deletions boa/src/builtins/object/internal_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl Object {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
#[inline]
pub fn is_extensible(&self) -> bool {
let val = self.get_internal_slot("extensible");
match *val.deref().borrow() {
Expand All @@ -59,6 +60,7 @@ impl Object {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
#[inline]
pub fn prevent_extensions(&mut self) -> bool {
self.set_internal_slot("extensible", Value::from(false));
true
Expand Down Expand Up @@ -375,30 +377,40 @@ impl Object {
}

/// Returns either the prototype or null
/// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof
#[inline]
pub fn get_prototype_of(&self) -> Value {
self.get_internal_slot(INSTANCE_PROTOTYPE)
}

/// Helper function to get an immutable internal slot or Null
/// Helper function to get an immutable internal slot or `Null`.
#[inline]
pub fn get_internal_slot(&self, name: &str) -> Value {
match self.internal_slots.get(name) {
Some(v) => v.clone(),
None => Value::null(),
}
}

/// Helper function to set an internal slot
/// Helper function to set an internal slot.
#[inline]
pub fn set_internal_slot(&mut self, name: &str, val: Value) {
self.internal_slots.insert(name.to_string(), val);
}

/// Helper function for property insertion.
#[inline]
pub fn insert_property(&mut self, name: String, p: Property) {
self.properties.insert(name, p);
}

/// Helper function for property removal.
#[inline]
pub fn remove_property(&mut self, name: &str) {
self.properties.remove(name);
}
Expand Down
12 changes: 11 additions & 1 deletion boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub struct Object {
/// Symbol Properties
symbol_properties: FxHashMap<i32, Property>,
/// Some rust object that stores internal state
pub state: Option<InternalStateCell>,
state: Option<InternalStateCell>,
}

/// Defines the different types of objects.
Expand Down Expand Up @@ -405,6 +405,16 @@ impl Object {
pub fn symbol_properties_mut(&mut self) -> &mut FxHashMap<i32, Property> {
&mut self.symbol_properties
}

#[inline]
pub fn state(&self) -> &Option<InternalStateCell> {
&self.state
}

#[inline]
pub fn state_mut(&mut self) -> &mut Option<InternalStateCell> {
&mut self.state
}
}

/// Create a new object.
Expand Down
13 changes: 5 additions & 8 deletions boa/src/builtins/regexp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,8 @@ impl RegExp {
}

let result = Value::from(result);
result
.set_property_slice("index", Property::default().value(Value::from(m.start())));
result.set_property_slice("input", Property::default().value(Value::from(arg_str)));
result.set_property("index", Property::default().value(Value::from(m.start())));
result.set_property("input", Property::default().value(Value::from(arg_str)));
result
} else {
if regex.use_last_index {
Expand Down Expand Up @@ -441,11 +440,9 @@ impl RegExp {

let match_val = Value::from(match_vec);

match_val.set_property_slice(
"index",
Property::default().value(Value::from(m.start())),
);
match_val.set_property_slice(
match_val
.set_property("index", Property::default().value(Value::from(m.start())));
match_val.set_property(
"input",
Property::default().value(Value::from(arg_str.clone())),
);
Expand Down
3 changes: 2 additions & 1 deletion boa/src/builtins/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,8 @@ impl String {
let prototype = Value::new_object(Some(global));
let length = Property::default().value(Value::from(0));

prototype.set_property_slice("length", length);
prototype.set_property("length", length);

make_builtin_fn(Self::char_at, "charAt", &prototype, 1);
make_builtin_fn(Self::char_code_at, "charCodeAt", &prototype, 1);
make_builtin_fn(Self::to_string, "toString", &prototype, 0);
Expand Down
7 changes: 2 additions & 5 deletions boa/src/builtins/symbol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ use super::function::{make_builtin_fn, make_constructor_fn};
use crate::{
builtins::{
object::{Object, ObjectData, INSTANCE_PROTOTYPE, PROTOTYPE},
value::{ResultValue, Value, ValueData},
value::{ResultValue, Value},
},
exec::Interpreter,
};
use gc::{Gc, GcCell};
use rand::random;

/// Creates Symbol instances.
Expand Down Expand Up @@ -64,9 +63,7 @@ pub fn call_symbol(_: &mut Value, args: &[Value], ctx: &mut Interpreter) -> Resu
.get_field(PROTOTYPE);
sym_instance.set_internal_slot(INSTANCE_PROTOTYPE, proto);

Ok(Value(Gc::new(ValueData::Symbol(Box::new(GcCell::new(
sym_instance,
))))))
Ok(Value::symbol(sym_instance))
}

/// `Symbol.prototype.toString()`
Expand Down
58 changes: 29 additions & 29 deletions boa/src/builtins/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub type ResultValue = Result<Value, Value>;

/// A Garbage-collected Javascript value as represented in the interpreter.
#[derive(Debug, Clone, Trace, Finalize, Default)]
pub struct Value(pub(crate) Gc<ValueData>);
pub struct Value(Gc<ValueData>);

impl Value {
/// Creates a new `undefined` value.
Expand Down Expand Up @@ -111,6 +111,12 @@ impl Value {
Self(Gc::new(ValueData::Object(Box::new(GcCell::new(object)))))
}

/// Creates a new symbol value.
#[inline]
pub fn symbol(object: Object) -> Self {
Self(Gc::new(ValueData::Symbol(Box::new(GcCell::new(object)))))
}

/// Gets the underlying `ValueData` structure.
#[inline]
pub fn data(&self) -> &ValueData {
Expand Down Expand Up @@ -549,19 +555,17 @@ impl ValueData {

/// Check whether an object has an internal state set.
pub fn has_internal_state(&self) -> bool {
if let Self::Object(ref obj) = *self {
obj.borrow().state.is_some()
} else {
false
match self.as_object() {
Some(object) => object.state().is_some(),
None => false,
}
}

/// Get the internal state of an object.
pub fn get_internal_state(&self) -> Option<InternalStateCell> {
if let Self::Object(ref obj) = *self {
obj.borrow().state.as_ref().cloned()
} else {
None
match self.as_object() {
Some(object) => object.state().clone(),
None => None,
}
}

Expand All @@ -575,10 +579,9 @@ impl ValueData {
&self,
f: F,
) -> R {
if let Self::Object(ref obj) = *self {
let o = obj.borrow();
let state = o
.state
if let Some(object) = self.as_object() {
let state = object
.state()
.as_ref()
.expect("no state")
.downcast_ref()
Expand All @@ -599,10 +602,9 @@ impl ValueData {
&self,
f: F,
) -> R {
if let Self::Object(ref obj) = *self {
let mut o = obj.borrow_mut();
let state = o
.state
if let Some(mut object) = self.as_object_mut() {
let state = object
.state_mut()
.as_mut()
.expect("no state")
.downcast_mut()
Expand Down Expand Up @@ -669,25 +671,23 @@ impl ValueData {
}
}

/// Set the property in the value
pub fn set_property(&self, field: String, property: Property) -> Property {
/// Set the property in the value.
pub fn set_property<S>(&self, field: S, property: Property) -> Property
where
S: Into<String>,
{
if let Some(mut object) = self.as_object_mut() {
object.properties_mut().insert(field, property.clone());
object
.properties_mut()
.insert(field.into(), property.clone());
}
property
}

/// Set the property in the value
pub fn set_property_slice(&self, field: &str, prop: Property) -> Property {
self.set_property(field.to_string(), prop)
}

/// Set internal state of an Object. Discards the previous state if it was set.
pub fn set_internal_state<T: Any + InternalState>(&self, state: T) {
if let Self::Object(ref obj) = *self {
obj.borrow_mut()
.state
.replace(InternalStateCell::new(state));
if let Some(mut object) = self.as_object_mut() {
object.state_mut().replace(InternalStateCell::new(state));
}
}

Expand Down

0 comments on commit 896ba46

Please sign in to comment.