Skip to content

Commit

Permalink
Add static shape to Reflect
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Apr 27, 2023
1 parent f1bc7c4 commit db0c644
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 36 deletions.
17 changes: 17 additions & 0 deletions boa_builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,23 @@ fn main() -> io::Result<()> {
.property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
.build(file)?;

BuiltInBuilder::new("REFLECT_OBJECT")
.method(utf16!("apply"))
.method(utf16!("construct"))
.method(utf16!("defineProperty"))
.method(utf16!("deleteProperty"))
.method(utf16!("get"))
.method(utf16!("getOwnPropertyDescriptor"))
.method(utf16!("getPrototypeOf"))
.method(utf16!("has"))
.method(utf16!("isExtensible"))
.method(utf16!("ownKeys"))
.method(utf16!("preventExtensions"))
.method(utf16!("set"))
.method(utf16!("setPrototypeOf"))
.property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
.build(file)?;

BuiltInBuilderConstructor::new("OBJECT")
.accessor(utf16!("__proto__"), Attribute::CONFIGURABLE)
.method(utf16!("hasOwnProperty"))
Expand Down
47 changes: 19 additions & 28 deletions boa_engine/src/builtins/reflect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ use crate::{
context::intrinsics::Intrinsics,
error::JsNativeError,
object::JsObject,
property::Attribute,
realm::Realm,
symbol::JsSymbol,
Context, JsArgs, JsResult, JsValue,
};
use boa_profiler::Profiler;
Expand All @@ -34,32 +32,25 @@ impl IntrinsicObject for Reflect {
fn init(realm: &Realm) {
let _timer = Profiler::global().start_event(Self::NAME, "init");

let to_string_tag = JsSymbol::to_string_tag();

BuiltInBuilder::with_intrinsic::<Self>(realm)
.static_method(Self::apply, "apply", 3)
.static_method(Self::construct, "construct", 2)
.static_method(Self::define_property, "defineProperty", 3)
.static_method(Self::delete_property, "deleteProperty", 2)
.static_method(Self::get, "get", 2)
.static_method(
Self::get_own_property_descriptor,
"getOwnPropertyDescriptor",
2,
)
.static_method(Self::get_prototype_of, "getPrototypeOf", 1)
.static_method(Self::has, "has", 2)
.static_method(Self::is_extensible, "isExtensible", 1)
.static_method(Self::own_keys, "ownKeys", 1)
.static_method(Self::prevent_extensions, "preventExtensions", 1)
.static_method(Self::set, "set", 3)
.static_method(Self::set_prototype_of, "setPrototypeOf", 2)
.static_property(
to_string_tag,
Self::NAME,
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
)
.build();
BuiltInBuilder::with_intrinsic_static_shape::<Self>(
realm,
&boa_builtins::REFLECT_OBJECT_STATIC_SHAPE,
)
.static_method(Self::apply, 3)
.static_method(Self::construct, 2)
.static_method(Self::define_property, 3)
.static_method(Self::delete_property, 2)
.static_method(Self::get, 2)
.static_method(Self::get_own_property_descriptor, 2)
.static_method(Self::get_prototype_of, 1)
.static_method(Self::has, 2)
.static_method(Self::is_extensible, 1)
.static_method(Self::own_keys, 1)
.static_method(Self::prevent_extensions, 1)
.static_method(Self::set, 3)
.static_method(Self::set_prototype_of, 2)
.static_property(Self::NAME)
.build();
}

fn get(intrinsics: &Intrinsics) -> JsObject {
Expand Down
20 changes: 13 additions & 7 deletions boa_engine/src/context/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ impl StandardConstructor {
}
}

fn default_static_shape() -> Self {
Self {
constructor: JsFunction::empty_intrinsic_function_static_shape(true),
prototype: JsObject::default_with_static_shape(),
}
}

/// Return the prototype of the constructor object.
///
/// This is the same as `Object.prototype`, `Array.prototype`, etc
Expand Down Expand Up @@ -157,17 +164,16 @@ impl Default for StandardConstructors {
fn default() -> Self {
Self {
async_generator_function: StandardConstructor::default(),
object: StandardConstructor::default(),
object: StandardConstructor::default_static_shape(),
proxy: StandardConstructor::default(),
date: StandardConstructor::default(),
function: StandardConstructor {
constructor: JsFunction::empty_intrinsic_function(true),
prototype: JsFunction::empty_intrinsic_function(false).into(),
constructor: JsFunction::empty_intrinsic_function_static_shape(true),
prototype: JsFunction::empty_intrinsic_function_static_shape(false).into(),
},
async_function: StandardConstructor::default(),
generator_function: StandardConstructor::default(),
array: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
None,
array: StandardConstructor::with_prototype(JsObject::from_data_and_empty_static_shape(
ObjectData::array(),
)),
bigint: StandardConstructor::default(),
Expand Down Expand Up @@ -814,8 +820,8 @@ pub struct IntrinsicObjects {
impl Default for IntrinsicObjects {
fn default() -> Self {
Self {
reflect: JsObject::default(),
math: JsObject::default(),
reflect: JsObject::default_with_static_shape(),
math: JsObject::default_with_static_shape(),
json: JsObject::default_with_static_shape(),
throw_type_error: JsFunction::empty_intrinsic_function(false),
array_prototype_values: JsFunction::empty_intrinsic_function(false),
Expand Down
13 changes: 13 additions & 0 deletions boa_engine/src/object/builtins/jsfunction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ impl JsFunction {
}
}

pub(crate) fn empty_intrinsic_function_static_shape(constructor: bool) -> Self {
Self {
inner: JsObject::from_object_and_vtable(
Object::with_empty_shape(),
if constructor {
&CONSTRUCTOR_INTERNAL_METHODS
} else {
&FUNCTION_INTERNAL_METHODS
},
),
}
}

/// Creates a [`JsFunction`] from a [`JsObject`], or returns `None` if the object is not a function.
///
/// This does not clone the fields of the function, it only does a shallow clone of the object.
Expand Down
19 changes: 18 additions & 1 deletion boa_engine/src/object/jsobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use super::{
internal_methods::{InternalObjectMethods, ARRAY_EXOTIC_INTERNAL_METHODS},
shape::{shared_shape::SharedShape, Shape},
shape::{shared_shape::SharedShape, static_shape::StaticShape, Shape},
JsPrototype, NativeObject, Object, PropertyMap,
};
use crate::{
Expand Down Expand Up @@ -125,6 +125,23 @@ impl JsObject {
}
}

pub(crate) fn from_data_and_empty_static_shape(data: ObjectData) -> Self {
Self {
inner: Gc::new(VTableObject {
object: GcRefCell::new(Object {
kind: data.kind,
properties: PropertyMap::new(
Shape::r#static(StaticShape::new(&boa_builtins::EMPTY_OBJECT_STATIC_SHAPE)),
ThinVec::default(),
),
extensible: true,
private_elements: ThinVec::new(),
}),
vtable: data.internal_methods,
}),
}
}

/// Creates a new object with the provided prototype and object data.
///
/// This is equivalent to calling the specification's abstract operation [`OrdinaryObjectCreate`],
Expand Down

0 comments on commit db0c644

Please sign in to comment.