Skip to content

Commit

Permalink
Refactor built-in constructor and function initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwilliams committed Oct 6, 2024
1 parent d697af1 commit 5ceedff
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 13 deletions.
21 changes: 20 additions & 1 deletion core/engine/src/builtins/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
native_function::{NativeFunctionObject, NativeFunctionPointer},
object::{
shape::{property_table::PropertyTableInner, slot::SlotAttributes},
FunctionBinding, JsFunction, JsPrototype, CONSTRUCTOR, PROTOTYPE,
FunctionBinding, JsFunction, JsPrototype, LazyBuiltIn, CONSTRUCTOR, PROTOTYPE,
},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
Expand Down Expand Up @@ -391,6 +391,25 @@ impl BuiltInConstructorWithPrototype<'_> {
}

let mut object = self.object.borrow_mut();
if object.is::<NativeFunctionObject>() {
let function = object
.downcast_mut::<NativeFunctionObject>()
.expect("Builtin must be a function object");
function.f = NativeFunction::from_fn_ptr(self.function);
function.constructor = Some(ConstructorKind::Base);
function.realm = Some(self.realm.clone());
} else if object.is::<LazyBuiltIn>() {
let lazy = object
.downcast_mut::<LazyBuiltIn>()
.expect("Builtin must be a lazy object");
lazy.set_constructor(
NativeFunction::from_fn_ptr(self.function),
self.realm.clone(),
);
} else {
unreachable!("The object must be a function or a lazy object");
}

object
.properties_mut()
.shape
Expand Down
12 changes: 5 additions & 7 deletions core/engine/src/object/builtins/jsfunction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,16 @@ impl JsFunction {
init: fn(&Realm),
realm_inner: WeakGc<RealmInner>,
) -> Self {
let kind = if constructor {
BuiltinKind::Function(Self::empty_intrinsic_function(constructor))
} else {
BuiltinKind::Ordinary
};

Self {
inner: JsObject::from_proto_and_data(
None,
LazyBuiltIn {
init_and_realm: Some((init, realm_inner)),
kind,
kind: BuiltinKind::Function(NativeFunctionObject {
f: NativeFunction::from_fn_ptr(|_, _, _| Ok(JsValue::undefined())),
constructor: constructor.then_some(ConstructorKind::Base),
realm: None,
}),
},
),
}
Expand Down
31 changes: 26 additions & 5 deletions core/engine/src/object/builtins/lazy_builtin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::JsFunction;
use crate::{
builtins::function::ConstructorKind,
gc::custom_trace,
native_function::NativeFunctionObject,
object::{
internal_methods::{
non_existant_call, non_existant_construct, ordinary_define_own_property,
Expand All @@ -13,13 +14,13 @@ use crate::{
},
property::{PropertyDescriptor, PropertyKey},
realm::{Realm, RealmInner},
Context, JsData, JsNativeError, JsObject, JsResult, JsValue,
Context, JsData, JsNativeError, JsObject, JsResult, JsValue, NativeFunction,
};
use boa_gc::{Finalize, Trace, WeakGc};

#[derive(Debug, Clone, Trace, Finalize)]
pub(crate) enum BuiltinKind {
Function(JsFunction),
Function(NativeFunctionObject),
Ordinary,
}

Expand All @@ -32,6 +33,18 @@ pub struct LazyBuiltIn {
pub(crate) kind: BuiltinKind,
}

impl LazyBuiltIn {
pub(crate) fn set_constructor(&mut self, function: NativeFunction, realm: Realm) {
if let BuiltinKind::Function(ref mut native_function) = self.kind {
native_function.f = function;
native_function.constructor = Some(ConstructorKind::Base);
native_function.realm = Some(realm);
} else {
panic!("Expected BuiltinKind::Function");
}
}
}

// SAFETY: Temporary, TODO move back to derived Trace when possible
unsafe impl Trace for LazyBuiltIn {
custom_trace!(this, mark, {
Expand Down Expand Up @@ -395,7 +408,11 @@ pub(crate) fn lazy_construct(
.with_message("not a constructor")
.with_realm(context.realm().clone())
.into()),
BuiltinKind::Function(constructor) => Ok(constructor.__construct__(argument_count)),
BuiltinKind::Function(constructor) => Ok((constructor.internal_methods().__construct__)(
obj,
argument_count,
context,
)?),
}
}

Expand Down Expand Up @@ -427,6 +444,10 @@ pub(crate) fn lazy_call(
.with_message("not a constructor")
.with_realm(context.realm().clone())
.into()),
BuiltinKind::Function(function) => Ok(function.__call__(argument_count)),
BuiltinKind::Function(function) => Ok((function.internal_methods().__call__)(
obj,
argument_count,
context,
)?),
}
}

0 comments on commit 5ceedff

Please sign in to comment.