Skip to content

Commit

Permalink
Move Object internal object methods to GcObject (#835)
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored Oct 16, 2020
1 parent dc1628a commit 2cb2442
Show file tree
Hide file tree
Showing 22 changed files with 431 additions and 205 deletions.
4 changes: 2 additions & 2 deletions boa/src/builtins/array/array_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl ArrayIterator {
let array_iterator = Value::new_object(Some(ctx.global_object()));
array_iterator.set_data(ObjectData::ArrayIterator(Self::new(array, kind)));
array_iterator
.as_object_mut()
.as_object()
.expect("array iterator object")
.set_prototype_instance(ctx.iterator_prototypes().array_iterator().into());
Ok(array_iterator)
Expand Down Expand Up @@ -126,7 +126,7 @@ impl ArrayIterator {
let array_iterator = Value::new_object(Some(global));
make_builtin_fn(Self::next, "next", &array_iterator, 0, ctx);
array_iterator
.as_object_mut()
.as_object()
.expect("array iterator prototype object")
.set_prototype_instance(iterator_prototype);

Expand Down
6 changes: 3 additions & 3 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl Array {
None => context.standard_objects().array_object().prototype(),
};

this.as_object_mut()
this.as_object()
.expect("this should be an array object")
.set_prototype_instance(prototype.into());
// This value is used by console.log and other routines to match Object type
Expand All @@ -213,7 +213,7 @@ impl Array {
));
array.set_data(ObjectData::Array);
array
.as_object_mut()
.as_object()
.expect("array object")
.set_prototype_instance(context.standard_objects().array_object().prototype().into());
array.set_field("length", Value::from(0));
Expand Down Expand Up @@ -281,7 +281,7 @@ impl Array {
_interpreter: &mut Context,
) -> Result<Value> {
match args.get(0).and_then(|x| x.as_object()) {
Some(object) => Ok(Value::from(object.is_array())),
Some(object) => Ok(Value::from(object.borrow().is_array())),
None => Ok(Value::from(false)),
}
}
Expand Down
6 changes: 1 addition & 5 deletions boa/src/builtins/boolean/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,7 @@ fn instances_have_correct_proto_set() {
let bool_prototype = forward_val(&mut engine, "boolProto").expect("value expected");

assert!(same_value(
&bool_instance
.as_object()
.unwrap()
.prototype_instance()
.clone(),
&bool_instance.as_object().unwrap().prototype_instance(),
&bool_prototype
));
}
61 changes: 3 additions & 58 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use crate::{
builtins::{Array, BuiltIn},
environment::lexical_environment::Environment,
object::{ConstructorBuilder, FunctionBuilder, Object, ObjectData, PROTOTYPE},
object::{ConstructorBuilder, FunctionBuilder, GcObject, Object, ObjectData},
property::{Attribute, DataDescriptor},
syntax::ast::node::{FormalParameter, RcStatementList},
BoaProfiler, Context, Result, Value,
Expand Down Expand Up @@ -172,7 +172,7 @@ impl Function {
/// <https://tc39.es/ecma262/#sec-createunmappedargumentsobject>
pub fn create_unmapped_arguments_object(arguments_list: &[Value]) -> Value {
let len = arguments_list.len();
let mut obj = Object::default();
let mut obj = GcObject::new(Object::default());
// Set length
let length = DataDescriptor::new(
len,
Expand All @@ -195,61 +195,6 @@ pub fn create_unmapped_arguments_object(arguments_list: &[Value]) -> Value {
Value::from(obj)
}

/// Creates a new constructor function
///
/// This utility function handling linking the new Constructor to the prototype.
/// So far this is only used by internal functions
pub fn make_constructor_fn(
name: &str,
length: usize,
body: NativeFunction,
global: &Value,
prototype: Value,
constructable: bool,
callable: bool,
) -> Value {
let _timer =
BoaProfiler::global().start_event(&format!("make_constructor_fn: {}", name), "init");

// Create the native function
let function = Function::BuiltIn(
body.into(),
FunctionFlags::from_parameters(callable, constructable),
);

// Get reference to Function.prototype
// Create the function object and point its instance prototype to Function.prototype
let mut constructor =
Object::function(function, global.get_field("Function").get_field(PROTOTYPE));

let length = DataDescriptor::new(
length,
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
);
constructor.insert("length", length);

let name = DataDescriptor::new(
name,
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
);
constructor.insert("name", name);

let constructor = Value::from(constructor);

prototype.as_object_mut().unwrap().insert_property(
"constructor",
constructor.clone(),
Attribute::all(),
);

constructor
.as_object_mut()
.expect("constructor object")
.insert_property(PROTOTYPE, prototype, Attribute::all());

constructor
}

/// Creates a new member function of a `Object` or `prototype`.
///
/// A function registered using this macro can then be called from Javascript using:
Expand Down Expand Up @@ -290,7 +235,7 @@ pub fn make_builtin_fn<N>(
function.insert_property("length", length, Attribute::all());

parent
.as_object_mut()
.as_object()
.unwrap()
.insert_property(name, function, Attribute::all());
}
Expand Down
8 changes: 4 additions & 4 deletions boa/src/builtins/iterable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ impl IteratorPrototypes {
let iterator_prototype = create_iterator_prototype(ctx);
Self {
iterator_prototype: iterator_prototype
.as_gc_object()
.as_object()
.expect("Iterator prototype is not an object"),
array_iterator: ArrayIterator::create_prototype(ctx, iterator_prototype.clone())
.as_gc_object()
.as_object()
.expect("Array Iterator Prototype is not an object"),
string_iterator: StringIterator::create_prototype(ctx, iterator_prototype.clone())
.as_gc_object()
.as_object()
.expect("String Iterator Prototype is not an object"),
map_iterator: MapIterator::create_prototype(ctx, iterator_prototype)
.as_gc_object()
.as_object()
.expect("Map Iterator Prototype is not an object"),
}
}
Expand Down
2 changes: 2 additions & 0 deletions boa/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ impl Json {
.map(|obj| {
let object_to_return = Value::new_object(None);
for (key, val) in obj
.borrow()
.iter()
// FIXME: handle accessor descriptors
.map(|(k, v)| (k, v.as_data_descriptor().unwrap().value()))
Expand All @@ -176,6 +177,7 @@ impl Json {
.ok_or_else(Value::undefined)?
} 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| {
if key == "length" {
None
Expand Down
6 changes: 2 additions & 4 deletions boa/src/builtins/json/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,12 @@ fn json_parse_sets_prototypes() {
.unwrap()
.as_object()
.unwrap()
.prototype_instance()
.clone();
.prototype_instance();
let array_prototype = forward_val(&mut engine, r#"jsonObj.arr"#)
.unwrap()
.as_object()
.unwrap()
.prototype_instance()
.clone();
.prototype_instance();
let global_object_prototype = engine
.global_object()
.get_field("Object")
Expand Down
4 changes: 2 additions & 2 deletions boa/src/builtins/map/map_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl MapIterator {
let map_iterator = Value::new_object(Some(ctx.global_object()));
map_iterator.set_data(ObjectData::MapIterator(Self::new(map, kind)));
map_iterator
.as_object_mut()
.as_object()
.expect("map iterator object")
.set_prototype_instance(ctx.iterator_prototypes().map_iterator().into());
Ok(map_iterator)
Expand Down Expand Up @@ -143,7 +143,7 @@ impl MapIterator {
let map_iterator = Value::new_object(Some(global));
make_builtin_fn(Self::next, "next", &map_iterator, 0, ctx);
map_iterator
.as_object_mut()
.as_object()
.expect("map iterator prototype object")
.set_prototype_instance(iterator_prototype);

Expand Down
4 changes: 2 additions & 2 deletions boa/src/builtins/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Map {
// Set Prototype
let prototype = ctx.global_object().get_field("Map").get_field(PROTOTYPE);

this.as_object_mut()
this.as_object()
.expect("this is map object")
.set_prototype_instance(prototype);
// This value is used by console.log and other routines to match Object type
Expand Down Expand Up @@ -354,7 +354,7 @@ impl Map {
/// Helper function to get a key-value pair from an array.
fn get_key_value(value: &Value) -> Option<(Value, Value)> {
if let Value::Object(object) = value {
if object.borrow().is_array() {
if object.is_array() {
let (key, value) = match value.get_field("length").as_number().unwrap() as i32 {
0 => (Value::Undefined, Value::Undefined),
1 => (value.get_field("0"), Value::Undefined),
Expand Down
46 changes: 23 additions & 23 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl Object {
if let Some(key) = args.get(1) {
let key = key.to_property_key(ctx)?;

if let Some(desc) = object.borrow().get_own_property(&key) {
if let Some(desc) = object.get_own_property(&key) {
return Ok(Self::from_property_descriptor(desc, ctx)?);
}
}
Expand Down Expand Up @@ -169,7 +169,6 @@ impl Object {
for key in object.borrow().keys() {
let descriptor = {
let desc = object
.borrow()
.get_own_property(&key)
.expect("Expected property to be on object.");
Self::from_property_descriptor(desc, ctx)?
Expand Down Expand Up @@ -239,16 +238,16 @@ impl Object {
/// Get the `prototype` of an object.
pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object");
Ok(obj.as_object().map_or_else(Value::undefined, |object| {
object.prototype_instance().clone()
}))
Ok(obj
.as_object()
.map_or_else(Value::undefined, |object| object.prototype_instance()))
}

/// Set the `prototype` of an object.
pub fn set_prototype_of(_: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object").clone();
let proto = args.get(1).expect("Cannot get object").clone();
obj.as_object_mut().unwrap().set_prototype_instance(proto);
obj.as_object().unwrap().set_prototype_instance(proto);
Ok(obj)
}

Expand Down Expand Up @@ -281,11 +280,11 @@ impl Object {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties
pub fn define_properties(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
let arg = args.get(0).cloned().unwrap_or_default();
let arg_obj = arg.as_object_mut();
let arg_obj = arg.as_object();
if let Some(mut obj) = arg_obj {
let props = args.get(1).cloned().unwrap_or_else(Value::undefined);
obj.define_properties(props, ctx)?;
Ok(arg.clone())
Ok(arg)
} else {
ctx.throw_type_error("Expected an object")
}
Expand All @@ -307,19 +306,21 @@ impl Object {
} else if this.is_null() {
Ok("[object Null]".into())
} else {
let gc_o = this.to_object(ctx)?;
let o = gc_o.borrow();
let builtin_tag = match &o.data {
ObjectData::Array => "Array",
// TODO: Arguments Exotic Objects are currently not supported
ObjectData::Function(_) => "Function",
ObjectData::Error => "Error",
ObjectData::Boolean(_) => "Boolean",
ObjectData::Number(_) => "Number",
ObjectData::String(_) => "String",
ObjectData::Date(_) => "Date",
ObjectData::RegExp(_) => "RegExp",
_ => "Object",
let o = this.to_object(ctx)?;
let builtin_tag = {
let o = o.borrow();
match &o.data {
ObjectData::Array => "Array",
// TODO: Arguments Exotic Objects are currently not supported
ObjectData::Function(_) => "Function",
ObjectData::Error => "Error",
ObjectData::Boolean(_) => "Boolean",
ObjectData::Number(_) => "Number",
ObjectData::String(_) => "String",
ObjectData::Date(_) => "Date",
ObjectData::RegExp(_) => "RegExp",
_ => "Object",
}
};

let tag = o.get(&ctx.well_known_symbols().to_string_tag_symbol().into());
Expand Down Expand Up @@ -349,7 +350,6 @@ impl Object {
};
let own_property = this
.as_object()
.as_deref()
.expect("Cannot get THIS object")
.get_own_property(&prop.expect("cannot get prop").into());
if own_property.is_none() {
Expand All @@ -370,7 +370,7 @@ impl Object {
};

let key = key.to_property_key(ctx)?;
let own_property = this.to_object(ctx)?.borrow().get_own_property(&key);
let own_property = this.to_object(ctx)?.get_own_property(&key);

Ok(own_property.map_or(Value::from(false), |own_prop| {
Value::from(own_prop.enumerable())
Expand Down
5 changes: 5 additions & 0 deletions boa/src/builtins/regexp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ impl RegExp {
.to_string(ctx)?;
let mut last_index = this.get_field("lastIndex").to_index(ctx)?;
let result = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
let result =
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
Expand Down Expand Up @@ -349,6 +350,7 @@ impl RegExp {
.to_string(ctx)?;
let mut last_index = this.get_field("lastIndex").to_index(ctx)?;
let result = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
let result = {
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
Expand Down Expand Up @@ -401,6 +403,7 @@ impl RegExp {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match
pub(crate) fn r#match(this: &Value, arg: RcString, ctx: &mut Context) -> Result<Value> {
let (matcher, flags) = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
(regex.matcher.clone(), regex.flags.clone())
} else {
Expand Down Expand Up @@ -433,6 +436,7 @@ impl RegExp {
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
let (body, flags) = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
(regex.original_source.clone(), regex.flags.clone())
} else {
Expand All @@ -457,6 +461,7 @@ impl RegExp {
// TODO: it's returning an array, it should return an iterator
pub(crate) fn match_all(this: &Value, arg_str: String) -> Result<Value> {
let matches = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().unwrap();
let mut matches = Vec::new();

Expand Down
4 changes: 2 additions & 2 deletions boa/src/builtins/string/string_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl StringIterator {
let string_iterator = Value::new_object(Some(ctx.global_object()));
string_iterator.set_data(ObjectData::StringIterator(Self::new(string)));
string_iterator
.as_object_mut()
.as_object()
.expect("array iterator object")
.set_prototype_instance(ctx.iterator_prototypes().string_iterator().into());
Ok(string_iterator)
Expand Down Expand Up @@ -76,7 +76,7 @@ impl StringIterator {
let array_iterator = Value::new_object(Some(global));
make_builtin_fn(Self::next, "next", &array_iterator, 0, ctx);
array_iterator
.as_object_mut()
.as_object()
.expect("array iterator prototype object")
.set_prototype_instance(iterator_prototype);

Expand Down
Loading

0 comments on commit 2cb2442

Please sign in to comment.