Skip to content

Commit

Permalink
Unify object creation with empty and from_proto_and_data methods
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Oct 4, 2021
1 parent 9f6245c commit 9290996
Show file tree
Hide file tree
Showing 40 changed files with 725 additions and 970 deletions.
25 changes: 13 additions & 12 deletions boa/src/builtins/array/array_iterator.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
builtins::{iterable::create_iter_result_object, Array, JsValue},
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, JsValue},
gc::{Finalize, Trace},
object::{function::make_builtin_fn, JsObject, ObjectData},
object::{JsObject, ObjectData},
property::{PropertyDescriptor, PropertyNameKind},
symbol::WellKnownSymbols,
BoaProfiler, Context, JsResult,
Expand Down Expand Up @@ -44,13 +44,11 @@ impl ArrayIterator {
kind: PropertyNameKind,
context: &Context,
) -> JsValue {
let array_iterator = JsValue::new_object(context);
array_iterator.set_data(ObjectData::array_iterator(Self::new(array, kind)));
array_iterator
.as_object()
.expect("array iterator object")
.set_prototype_instance(context.iterator_prototypes().array_iterator().into());
array_iterator
let array_iterator = JsObject::from_proto_and_data(
Some(context.iterator_prototypes().array_iterator()),
ObjectData::array_iterator(Self::new(array, kind)),
);
array_iterator.into()
}

/// %ArrayIteratorPrototype%.next( )
Expand Down Expand Up @@ -114,13 +112,16 @@ impl ArrayIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object
pub(crate) fn create_prototype(iterator_prototype: JsValue, context: &mut Context) -> JsObject {
pub(crate) fn create_prototype(
iterator_prototype: JsObject,
context: &mut Context,
) -> JsObject {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

// Create prototype
let array_iterator = context.construct_object();
let array_iterator =
JsObject::from_proto_and_data(Some(iterator_prototype), ObjectData::ordinary());
make_builtin_fn(Self::next, "next", &array_iterator, 0, context);
array_iterator.set_prototype_instance(iterator_prototype);

let to_string_tag = WellKnownSymbols::to_string_tag();
let to_string_tag_property = PropertyDescriptor::builder()
Expand Down
26 changes: 4 additions & 22 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,7 @@ impl Array {
Some(prototype) => prototype,
None => context.standard_objects().array_object().prototype(),
};
let array = context.construct_object();

array.set_prototype_instance(prototype.into());
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
array.borrow_mut().data = ObjectData::array();
let array = JsObject::from_proto_and_data(Some(prototype), ObjectData::array());

// 6. Perform ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
crate::object::internal_methods::ordinary_define_own_property(
Expand Down Expand Up @@ -275,22 +270,9 @@ impl Array {

/// Creates a new `Array` instance.
pub(crate) fn new_array(context: &mut Context) -> JsValue {
let array = JsValue::new_object(context);
array.set_data(ObjectData::array());
array
.as_object()
.expect("'array' should be an object")
.set_prototype_instance(context.standard_objects().array_object().prototype().into());
array.set_property(
"length",
PropertyDescriptor::builder()
.value(0)
.writable(true)
.enumerable(false)
.configurable(false)
.build(),
);
array
Self::array_create(0, None, context)
.expect("creating an empty array with the default prototype must not fail")
.into()
}

/// Utility function for concatenating array objects.
Expand Down
14 changes: 5 additions & 9 deletions boa/src/builtins/boolean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ mod tests;
use crate::{
builtins::BuiltIn,
context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
property::Attribute,
BoaProfiler, Context, JsResult, JsValue,
};
Expand Down Expand Up @@ -69,15 +71,9 @@ impl Boolean {
}
let prototype =
get_prototype_from_constructor(new_target, StandardObjects::boolean_object, context)?;
let boolean = JsValue::new_object(context);
let boolean = JsObject::from_proto_and_data(Some(prototype), ObjectData::boolean(data));

boolean
.as_object()
.expect("this should be an object")
.set_prototype_instance(prototype.into());
boolean.set_data(ObjectData::boolean(data));

Ok(boolean)
Ok(boolean.into())
}

/// An Utility function used to get the internal `[[BooleanData]]`.
Expand Down
51 changes: 26 additions & 25 deletions boa/src/builtins/date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use crate::{
builtins::BuiltIn,
context::StandardObjects,
gc::{empty_trace, Finalize, Trace},
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
property::Attribute,
symbol::WellKnownSymbols,
value::{JsValue, PreferredType},
Expand Down Expand Up @@ -346,16 +348,14 @@ impl Date {
StandardObjects::object_object,
context,
)?;
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = obj.into();
if args.is_empty() {
Ok(Self::make_date_now(&this))
Ok(if args.is_empty() {
Self::make_date_now(prototype)
} else if args.len() == 1 {
Self::make_date_single(&this, args, context)
Self::make_date_single(prototype, args, context)?
} else {
Self::make_date_multiple(&this, args, context)
Self::make_date_multiple(prototype, args, context)?
}
.into())
}
}

Expand Down Expand Up @@ -383,10 +383,8 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_now(this: &JsValue) -> JsValue {
let date = Date::default();
this.set_data(ObjectData::date(date));
this.clone()
pub(crate) fn make_date_now(prototype: JsObject) -> JsObject {
JsObject::from_proto_and_data(Some(prototype), ObjectData::date(Date::default()))
}

/// `Date(value)`
Expand All @@ -400,10 +398,10 @@ impl Date {
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_single(
this: &JsValue,
prototype: JsObject,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
) -> JsResult<JsObject> {
let value = &args[0];
let tv = match this_time_value(value, context) {
Ok(dt) => dt.0,
Expand All @@ -426,9 +424,10 @@ impl Date {
};

let tv = tv.filter(|time| Self::time_clip(time.timestamp_millis() as f64).is_some());
let date = Date(tv);
this.set_data(ObjectData::date(date));
Ok(this.clone())
Ok(JsObject::from_proto_and_data(
Some(prototype),
ObjectData::date(Date(tv)),
))
}

/// `Date(year, month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ])`
Expand All @@ -442,10 +441,10 @@ impl Date {
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_multiple(
this: &JsValue,
prototype: JsObject,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
) -> JsResult<JsObject> {
let mut year = args[0].to_number(context)?;
let month = args[1].to_number(context)?;
let day = args
Expand All @@ -466,9 +465,10 @@ impl Date {

// If any of the args are infinity or NaN, return an invalid date.
if !check_normal_opt!(year, month, day, hour, min, sec, milli) {
let date = Date(None);
this.set_data(ObjectData::date(date));
return Ok(this.clone());
return Ok(JsObject::from_proto_and_data(
Some(prototype),
ObjectData::date(Date(None)),
));
}

if (0.0..=99.0).contains(&year) {
Expand All @@ -493,9 +493,10 @@ impl Date {
Some(milli),
);

this.set_data(ObjectData::date(date));

Ok(this.clone())
Ok(JsObject::from_proto_and_data(
Some(prototype),
ObjectData::date(date),
))
}

/// `Date.prototype[@@toPrimitive]`
Expand Down
13 changes: 4 additions & 9 deletions boa/src/builtins/error/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use crate::context::StandardObjects;
use crate::object::internal_methods::get_prototype_from_constructor;
use crate::object::JsObject;

use crate::{
builtins::BuiltIn,
Expand Down Expand Up @@ -66,18 +67,12 @@ impl EvalError {
) -> JsResult<JsValue> {
let prototype =
get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj);
let obj = JsObject::from_proto_and_data(Some(prototype), ObjectData::error());
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;
obj.set("message", message.to_string(context)?, false, context)?;
}
}

// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::error());
Ok(this)
Ok(obj.into())
}
}
16 changes: 6 additions & 10 deletions boa/src/builtins/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
use crate::{
builtins::BuiltIn,
context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
profiler::BoaProfiler,
property::Attribute,
Context, JsResult, JsValue,
Expand Down Expand Up @@ -81,19 +83,13 @@ impl Error {
) -> JsResult<JsValue> {
let prototype =
get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj);
let obj = JsObject::from_proto_and_data(Some(prototype), ObjectData::error());
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;
obj.set("message", message.to_string(context)?, false, context)?;
}
}

// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::error());
Ok(this)
Ok(obj.into())
}

/// `Error.prototype.toString()`
Expand Down
16 changes: 6 additions & 10 deletions boa/src/builtins/error/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use crate::{
builtins::BuiltIn,
context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
profiler::BoaProfiler,
property::Attribute,
Context, JsResult, JsValue,
Expand Down Expand Up @@ -62,18 +64,12 @@ impl RangeError {
) -> JsResult<JsValue> {
let prototype =
get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj);
let obj = JsObject::from_proto_and_data(Some(prototype), ObjectData::error());
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;
obj.set("message", message.to_string(context)?, false, context)?;
}
}

// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::error());
Ok(this)
Ok(obj.into())
}
}
16 changes: 6 additions & 10 deletions boa/src/builtins/error/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use crate::{
builtins::BuiltIn,
context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
profiler::BoaProfiler,
property::Attribute,
Context, JsResult, JsValue,
Expand Down Expand Up @@ -61,18 +63,12 @@ impl ReferenceError {
) -> JsResult<JsValue> {
let prototype =
get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj);
let obj = JsObject::from_proto_and_data(Some(prototype), ObjectData::error());
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;
obj.set("message", message.to_string(context)?, false, context)?;
}
}

// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::error());
Ok(this)
Ok(obj.into())
}
}
16 changes: 6 additions & 10 deletions boa/src/builtins/error/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
use crate::{
builtins::BuiltIn,
context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
profiler::BoaProfiler,
property::Attribute,
Context, JsResult, JsValue,
Expand Down Expand Up @@ -64,18 +66,12 @@ impl SyntaxError {
) -> JsResult<JsValue> {
let prototype =
get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj);
let obj = JsObject::from_proto_and_data(Some(prototype), ObjectData::error());
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;
obj.set("message", message.to_string(context)?, false, context)?;
}
}

// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::error());
Ok(this)
Ok(obj.into())
}
}
Loading

0 comments on commit 9290996

Please sign in to comment.