diff --git a/boa_engine/src/builtins/array/mod.rs b/boa_engine/src/builtins/array/mod.rs index c31fd8f8a5b..7404a876cfb 100644 --- a/boa_engine/src/builtins/array/mod.rs +++ b/boa_engine/src/builtins/array/mod.rs @@ -25,7 +25,7 @@ use crate::{ context::intrinsics::StandardConstructors, object::{ internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder, - JsObject, ObjectData, + JsFunction, JsObject, ObjectData, }, property::{Attribute, PropertyDescriptor, PropertyNameKind}, symbol::WellKnownSymbols, @@ -2857,7 +2857,7 @@ impl Array { } } - pub(crate) fn values_intrinsic(context: &mut Context) -> JsObject { + pub(crate) fn values_intrinsic(context: &mut Context) -> JsFunction { FunctionBuilder::native(context, Self::values) .name("values") .length(0) diff --git a/boa_engine/src/class.rs b/boa_engine/src/class.rs index e61123d615c..94f81452692 100644 --- a/boa_engine/src/class.rs +++ b/boa_engine/src/class.rs @@ -63,7 +63,7 @@ use crate::{ builtins::function::NativeFunctionSignature, - object::{ConstructorBuilder, JsObject, NativeObject, ObjectData, PROTOTYPE}, + object::{ConstructorBuilder, JsFunction, JsObject, NativeObject, ObjectData, PROTOTYPE}, property::{Attribute, PropertyDescriptor, PropertyKey}, Context, JsResult, JsValue, }; @@ -168,8 +168,8 @@ impl<'context> ClassBuilder<'context> { } #[inline] - pub(crate) fn build(mut self) -> JsObject { - self.builder.build() + pub(crate) fn build(mut self) -> JsFunction { + JsFunction::from_object_unchecked(self.builder.build().into()) } /// Add a method to the class. @@ -239,8 +239,8 @@ impl<'context> ClassBuilder<'context> { pub fn accessor( &mut self, key: K, - get: Option, - set: Option, + get: Option, + set: Option, attribute: Attribute, ) -> &mut Self where @@ -257,8 +257,8 @@ impl<'context> ClassBuilder<'context> { pub fn static_accessor( &mut self, key: K, - get: Option, - set: Option, + get: Option, + set: Option, attribute: Attribute, ) -> &mut Self where diff --git a/boa_engine/src/object/jsarray.rs b/boa_engine/src/object/jsarray.rs index 1f69efdc738..c3d75c949d3 100644 --- a/boa_engine/src/object/jsarray.rs +++ b/boa_engine/src/object/jsarray.rs @@ -1,6 +1,6 @@ use crate::{ builtins::Array, - object::{JsObject, JsObjectType}, + object::{JsFunction, JsObject, JsObjectType}, value::IntoOrUndefined, Context, JsResult, JsString, JsValue, }; @@ -207,7 +207,7 @@ impl JsArray { #[inline] pub fn find( &self, - predicate: JsObject, + predicate: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -221,7 +221,7 @@ impl JsArray { #[inline] pub fn filter( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -240,7 +240,7 @@ impl JsArray { #[inline] pub fn map( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -259,7 +259,7 @@ impl JsArray { #[inline] pub fn every( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -277,7 +277,7 @@ impl JsArray { #[inline] pub fn some( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -293,7 +293,7 @@ impl JsArray { } #[inline] - pub fn sort(&self, compare_fn: Option, context: &mut Context) -> JsResult { + pub fn sort(&self, compare_fn: Option, context: &mut Context) -> JsResult { Array::sort( &self.inner.clone().into(), &[compare_fn.into_or_undefined()], @@ -325,7 +325,7 @@ impl JsArray { #[inline] pub fn reduce( &self, - callback: JsObject, + callback: JsFunction, initial_value: Option, context: &mut Context, ) -> JsResult { @@ -339,7 +339,7 @@ impl JsArray { #[inline] pub fn reduce_right( &self, - callback: JsObject, + callback: JsFunction, initial_value: Option, context: &mut Context, ) -> JsResult { diff --git a/boa_engine/src/object/jsfunction.rs b/boa_engine/src/object/jsfunction.rs new file mode 100644 index 00000000000..dd6b90ae1d8 --- /dev/null +++ b/boa_engine/src/object/jsfunction.rs @@ -0,0 +1,53 @@ +use crate::{ + object::{JsObject, JsObjectType}, + Context, JsResult, JsValue, +}; +use boa_gc::{Finalize, Trace}; +use std::ops::Deref; + +/// JavaScript `Function` rust object. +#[derive(Debug, Clone, Trace, Finalize)] +pub struct JsFunction { + inner: JsObject, +} + +impl JsFunction { + #[inline] + pub(crate) fn from_object_unchecked(object: JsObject) -> Self { + Self { inner: object } + } + + #[inline] + pub fn from_object(object: JsObject, context: &mut Context) -> JsResult { + if object.borrow().is_function() { + Ok(Self::from_object_unchecked(object)) + } else { + context.throw_type_error("object is not an Function") + } + } +} + +impl From for JsObject { + #[inline] + fn from(o: JsFunction) -> Self { + o.inner.clone() + } +} + +impl From for JsValue { + #[inline] + fn from(o: JsFunction) -> Self { + o.inner.clone().into() + } +} + +impl Deref for JsFunction { + type Target = JsObject; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl JsObjectType for JsFunction {} diff --git a/boa_engine/src/object/jstypedarray.rs b/boa_engine/src/object/jstypedarray.rs index 02b28e30109..5824009b764 100644 --- a/boa_engine/src/object/jstypedarray.rs +++ b/boa_engine/src/object/jstypedarray.rs @@ -1,6 +1,6 @@ use crate::{ builtins::typed_array::TypedArray, - object::{JsArray, JsObject, JsObjectType}, + object::{JsArray, JsFunction, JsObject, JsObjectType}, value::IntoOrUndefined, Context, JsResult, JsString, JsValue, }; @@ -21,7 +21,7 @@ impl JsTypedArray { inner: object.into(), }) } else { - context.throw_type_error("object is not an TypedArray") + context.throw_type_error("object is not a TypedArray") } } @@ -91,7 +91,7 @@ impl JsTypedArray { pub fn every( &self, - predicate: JsObject, + predicate: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -109,7 +109,7 @@ impl JsTypedArray { #[inline] pub fn some( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -125,7 +125,7 @@ impl JsTypedArray { } #[inline] - pub fn sort(&self, compare_fn: Option, context: &mut Context) -> JsResult { + pub fn sort(&self, compare_fn: Option, context: &mut Context) -> JsResult { TypedArray::sort(&self.inner, &[compare_fn.into_or_undefined()], context)?; Ok(self.clone()) @@ -134,7 +134,7 @@ impl JsTypedArray { #[inline] pub fn filter( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -150,7 +150,7 @@ impl JsTypedArray { #[inline] pub fn map( &self, - callback: JsObject, + callback: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { @@ -166,7 +166,7 @@ impl JsTypedArray { #[inline] pub fn reduce( &self, - callback: JsObject, + callback: JsFunction, initial_value: Option, context: &mut Context, ) -> JsResult { @@ -180,7 +180,7 @@ impl JsTypedArray { #[inline] pub fn reduce_right( &self, - callback: JsObject, + callback: JsFunction, initial_value: Option, context: &mut Context, ) -> JsResult { @@ -216,7 +216,7 @@ impl JsTypedArray { #[inline] pub fn find( &self, - predicate: JsObject, + predicate: JsFunction, this_arg: Option, context: &mut Context, ) -> JsResult { diff --git a/boa_engine/src/object/mod.rs b/boa_engine/src/object/mod.rs index 9543a51b2e4..9b139a89404 100644 --- a/boa_engine/src/object/mod.rs +++ b/boa_engine/src/object/mod.rs @@ -58,12 +58,14 @@ mod tests; pub(crate) mod internal_methods; mod jsarray; +mod jsfunction; mod jsobject; mod jstypedarray; mod operations; mod property_map; pub use jsarray::*; +pub use jsfunction::*; pub use jstypedarray::*; pub(crate) trait JsObjectType: @@ -1505,7 +1507,7 @@ impl<'context> FunctionBuilder<'context> { /// Build the function object. #[inline] - pub fn build(self) -> JsObject { + pub fn build(self) -> JsFunction { let function = JsObject::from_proto_and_data( self.context .intrinsics() @@ -1521,7 +1523,7 @@ impl<'context> FunctionBuilder<'context> { function.insert_property("length", property.clone().value(self.length)); function.insert_property("name", property.value(self.name)); - function + JsFunction::from_object_unchecked(function) } /// Initializes the `Function.prototype` function object. @@ -1806,8 +1808,8 @@ impl<'context> ConstructorBuilder<'context> { pub fn accessor( &mut self, key: K, - get: Option, - set: Option, + get: Option, + set: Option, attribute: Attribute, ) -> &mut Self where @@ -1827,8 +1829,8 @@ impl<'context> ConstructorBuilder<'context> { pub fn static_accessor( &mut self, key: K, - get: Option, - set: Option, + get: Option, + set: Option, attribute: Attribute, ) -> &mut Self where @@ -1941,7 +1943,7 @@ impl<'context> ConstructorBuilder<'context> { } /// Build the constructor function object. - pub fn build(&mut self) -> JsObject { + pub fn build(&mut self) -> JsFunction { // Create the native function let function = Function::Native { function: self.function, @@ -2013,6 +2015,6 @@ impl<'context> ConstructorBuilder<'context> { } } - self.object.clone() + JsFunction::from_object_unchecked(self.object.clone()) } }