Skip to content

Commit

Permalink
Split object internal methods and operations in modules
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Aug 24, 2021
1 parent 6fa16d9 commit 6b3e634
Show file tree
Hide file tree
Showing 9 changed files with 652 additions and 621 deletions.
4 changes: 1 addition & 3 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
BoaProfiler, Context, JsResult, JsValue,
};
use bitflags::bitflags;

use std::fmt::{self, Debug};
use std::rc::Rc;

Expand Down Expand Up @@ -348,9 +349,6 @@ impl BuiltInFunctionObject {
// TODO?: 3.a. PrepareForTailCall
return context.call(this, &this_arg, &[]);
}
let arg_array = arg_array.as_object().ok_or_else(|| {
context.construct_type_error("argList must be null, undefined or an object")
})?;
let arg_list = arg_array.create_list_from_array_like(&[], context)?;
// TODO?: 5. PrepareForTailCall
context.call(this, &this_arg, &arg_list)
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/object/for_in_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl ForInIterator {
let mut object = iterator.object.to_object(context)?;
loop {
if !iterator.object_was_visited {
let keys = object.own_property_keys();
let keys = object.__own_property_keys__(context)?;
for k in keys {
match k {
PropertyKey::String(ref k) => {
Expand Down
48 changes: 39 additions & 9 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
use crate::{
builtins::BuiltIn,
object::{
ConstructorBuilder, Object as BuiltinObject, ObjectData, ObjectInitializer, ObjectKind,
PROTOTYPE,
ConstructorBuilder, GcObject, Object as BuiltinObject, ObjectData, ObjectInitializer,
ObjectKind, PROTOTYPE,
},
property::{Attribute, DescriptorKind, PropertyDescriptor, PropertyNameKind},
property::{Attribute, DescriptorKind, PropertyDescriptor, PropertyKey, PropertyNameKind},
symbol::WellKnownSymbols,
value::{JsValue, Type},
BoaProfiler, Context, JsResult,
Expand Down Expand Up @@ -132,7 +132,7 @@ impl Object {
let properties = args.get(1).cloned().unwrap_or_else(JsValue::undefined);

let obj = match prototype {
JsValue::Object(_) | JsValue::Null => JsValue::new(BuiltinObject::with_prototype(
JsValue::Object(_) | JsValue::Null => GcObject::new(BuiltinObject::with_prototype(
prototype,
ObjectData::ordinary(),
)),
Expand All @@ -145,10 +145,11 @@ impl Object {
};

if !properties.is_undefined() {
return Object::define_properties(&JsValue::undefined(), &[obj, properties], context);
define_properties(&obj, properties, context)?;
return Ok(obj.into());
}

Ok(obj)
Ok(obj.into())
}

/// `Object.getOwnPropertyDescriptor( object, property )`
Expand Down Expand Up @@ -413,9 +414,9 @@ impl Object {
) -> JsResult<JsValue> {
let arg = args.get(0).cloned().unwrap_or_default();
let arg_obj = arg.as_object();
if let Some(mut obj) = arg_obj {
if let Some(obj) = arg_obj {
let props = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
obj.define_properties(props, context)?;
define_properties(&obj, props, context)?;
Ok(arg)
} else {
context.throw_type_error("Expected an object")
Expand Down Expand Up @@ -568,7 +569,7 @@ impl Object {
// 3.a.i. Let from be ! ToObject(nextSource).
let from = source.to_object(context).unwrap();
// 3.a.ii. Let keys be ? from.[[OwnPropertyKeys]]().
let keys = from.own_property_keys();
let keys = from.__own_property_keys__(context)?;
// 3.a.iii. For each element nextKey of keys, do
for key in keys {
// 3.a.iii.1. Let desc be ? from.[[GetOwnProperty]](nextKey).
Expand Down Expand Up @@ -672,3 +673,32 @@ impl Object {
Ok(result.into())
}
}

/// The abstract operation ObjectDefineProperties
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.defineproperties
#[inline]
fn define_properties(object: &GcObject, props: JsValue, context: &mut Context) -> JsResult<()> {
let props = &props.to_object(context)?;
let keys = props.__own_property_keys__(context)?;
let mut descriptors: Vec<(PropertyKey, PropertyDescriptor)> = Vec::new();

for next_key in keys {
if let Some(prop_desc) = props.__get_own_property__(&next_key, context)? {
if prop_desc.expect_enumerable() {
let desc_obj = props.get(next_key.clone(), context)?;
let desc = desc_obj.to_property_descriptor(context)?;
descriptors.push((next_key, desc));
}
}
}

for (p, d) in descriptors {
object.define_property_or_throw(p, d, context)?;
}

Ok(())
}
17 changes: 5 additions & 12 deletions boa/src/builtins/reflect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,18 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.apply
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply
pub(crate) fn apply(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let undefined = JsValue::undefined();
let target = args
.get(0)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("target must be a function"))?;
let this_arg = args.get(1).unwrap_or(&undefined);
let args_list = args
.get(2)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("args list must be an object"))?;
let this_arg = args.get(1).cloned().unwrap_or_default();
let args_list = args.get(2).cloned().unwrap_or_default();

if !target.is_callable() {
return context.throw_type_error("target must be a function");
}
let args = args_list.create_list_from_array_like(&[], context)?;
target.call(this_arg, &args, context)
target.call(&this_arg, &args, context)
}

/// Calls a target function as a constructor with arguments.
Expand All @@ -112,10 +108,7 @@ impl Reflect {
.get(0)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("target must be a function"))?;
let args_list = args
.get(1)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("args list must be an object"))?;
let args_list = args.get(1).cloned().unwrap_or_default();

if !target.is_constructable() {
return context.throw_type_error("target must be a constructor");
Expand Down Expand Up @@ -316,7 +309,7 @@ impl Reflect {
.ok_or_else(|| context.construct_type_error("target must be an object"))?;

let keys: Vec<JsValue> = target
.own_property_keys()
.__own_property_keys__(context)?
.into_iter()
.map(|key| key.into())
.collect();
Expand Down
Loading

0 comments on commit 6b3e634

Please sign in to comment.