diff --git a/core/engine/src/builtins/function/mod.rs b/core/engine/src/builtins/function/mod.rs index 79276f3cacd..04cd9a0064f 100644 --- a/core/engine/src/builtins/function/mod.rs +++ b/core/engine/src/builtins/function/mod.rs @@ -834,7 +834,7 @@ impl BuiltInFunctionObject { }; let object_borrow = object.borrow(); - if object_borrow.is::() { + if object_borrow.is::() || object_borrow.is::() { let name = { // Is there a case here where if there is no name field on a value // name should default to None? Do all functions have names set? @@ -850,13 +850,6 @@ impl BuiltInFunctionObject { ); } else if object_borrow.is::() || object_borrow.is::() { return Ok(js_string!("function () { [native code] }").into()); - } else if object_borrow.is::() { - let name = object_borrow - .downcast_ref::() - .map_or_else(|| js_string!(), |built_in| built_in.name.clone()); - return Ok( - js_string!(js_str!("function "), &name, js_str!("() { [native code] }")).into(), - ); } let function = object_borrow diff --git a/core/engine/src/context/intrinsics.rs b/core/engine/src/context/intrinsics.rs index d2292a8ba25..9ea9afab07c 100644 --- a/core/engine/src/context/intrinsics.rs +++ b/core/engine/src/context/intrinsics.rs @@ -2,12 +2,11 @@ use boa_gc::{Finalize, Trace, WeakGc}; use boa_macros::js_str; -use boa_string::JsString; use crate::{ builtins::{ - iterable::IteratorPrototypes, uri::UriFunctions, Array, BuiltInObject, Date, - IntrinsicObject, OrdinaryObject, + iterable::IteratorPrototypes, uri::UriFunctions, Array, Date, IntrinsicObject, + OrdinaryObject, }, js_string, object::{ @@ -101,9 +100,9 @@ impl StandardConstructor { } /// Similar to `with_prototype`, but the prototype is lazily initialized. - fn lazy(init: fn(&Realm) -> (), name: JsString, realm_inner: WeakGc) -> Self { + fn lazy(init: fn(&Realm) -> (), realm_inner: WeakGc) -> Self { Self { - constructor: JsFunction::lazy_intrinsic_function(true, init, name, realm_inner), + constructor: JsFunction::lazy_intrinsic_function(true, init, realm_inner), prototype: JsObject::default(), } } @@ -225,14 +224,14 @@ impl StandardConstructors { )), async_generator_function: StandardConstructor::default(), proxy: StandardConstructor::default(), - date: StandardConstructor::lazy(Date::init, Date::NAME, realm_inner.clone()), + date: StandardConstructor::lazy(Date::init, realm_inner.clone()), function: StandardConstructor { constructor: JsFunction::empty_intrinsic_function(true), prototype: JsFunction::empty_intrinsic_function(false).into(), }, async_function: StandardConstructor::default(), generator_function: StandardConstructor::default(), - array: StandardConstructor::lazy(Array::init, Array::NAME, realm_inner.clone()), + array: StandardConstructor::lazy(Array::init, realm_inner.clone()), bigint: StandardConstructor::default(), number: StandardConstructor::with_prototype(JsObject::from_proto_and_data(None, 0.0)), boolean: StandardConstructor::with_prototype(JsObject::from_proto_and_data( diff --git a/core/engine/src/object/builtins/jsfunction.rs b/core/engine/src/object/builtins/jsfunction.rs index b1005951f27..05b70f0cc41 100644 --- a/core/engine/src/object/builtins/jsfunction.rs +++ b/core/engine/src/object/builtins/jsfunction.rs @@ -5,8 +5,6 @@ use crate::{ value::TryFromJs, Context, JsNativeError, JsResult, JsValue, NativeFunction, TryIntoJsResult, }; use boa_gc::{Finalize, Trace, WeakGc}; -use boa_string::JsString; -use std::cell::Cell; use std::marker::PhantomData; use std::ops::Deref; @@ -109,7 +107,6 @@ impl JsFunction { pub(crate) fn lazy_intrinsic_function( constructor: bool, init: fn(&Realm), - name: JsString, realm_inner: WeakGc, ) -> Self { let kind = if constructor { @@ -122,11 +119,8 @@ impl JsFunction { inner: JsObject::from_proto_and_data( None, LazyBuiltIn { - init, - is_initialized: Cell::new(false), + init_and_realm: Some((init, realm_inner)), kind, - name, - realm_inner: Some(realm_inner), }, ), } diff --git a/core/engine/src/object/builtins/lazy_builtin.rs b/core/engine/src/object/builtins/lazy_builtin.rs index 8c67c4d196c..cceb38702f7 100644 --- a/core/engine/src/object/builtins/lazy_builtin.rs +++ b/core/engine/src/object/builtins/lazy_builtin.rs @@ -16,8 +16,6 @@ use crate::{ Context, JsData, JsNativeError, JsObject, JsResult, JsValue, }; use boa_gc::{Finalize, Trace, WeakGc}; -use boa_string::JsString; -use std::cell::Cell; #[derive(Debug, Clone, Trace, Finalize)] pub(crate) enum BuiltinKind { @@ -29,11 +27,8 @@ pub(crate) enum BuiltinKind { #[derive(Clone, Finalize)] pub struct LazyBuiltIn { - pub(crate) init: fn(&Realm), - pub(crate) is_initialized: Cell, + pub(crate) init_and_realm: Option<(fn(&Realm), WeakGc)>, pub(crate) kind: BuiltinKind, - pub(crate) realm_inner: Option>, - pub(crate) name: JsString, } // SAFETY: Temporary, TODO move back to derived Trace when possible @@ -82,21 +77,20 @@ pub(crate) fn lazy_get_prototype_of( context: &mut Context, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_get_prototype_of(obj, context) @@ -108,42 +102,40 @@ pub(crate) fn lazy_set_prototype_of( context: &mut Context, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_set_prototype_of(obj, prototype, context) } pub(crate) fn lazy_is_extensible(obj: &JsObject, context: &mut Context) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_is_extensible(obj, context) @@ -151,21 +143,20 @@ pub(crate) fn lazy_is_extensible(obj: &JsObject, context: &mut Context) -> JsRes pub(crate) fn lazy_prevent_extensions(obj: &JsObject, context: &mut Context) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_prevent_extensions(obj, context) @@ -177,21 +168,20 @@ pub(crate) fn lazy_get_own_property( context: &mut InternalMethodContext<'_>, ) -> JsResult> { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_get_own_property(obj, key, context) @@ -204,21 +194,20 @@ pub(crate) fn lazy_define_own_property( context: &mut InternalMethodContext<'_>, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_define_own_property(obj, key, desc, context) @@ -230,21 +219,20 @@ pub(crate) fn lazy_has_property( context: &mut InternalMethodContext<'_>, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_has_property(obj, key, context) @@ -257,21 +245,20 @@ pub(crate) fn lazy_try_get( context: &mut InternalMethodContext<'_>, ) -> JsResult> { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_try_get(obj, key, receiver, context) @@ -284,21 +271,20 @@ pub(crate) fn lazy_get( context: &mut InternalMethodContext<'_>, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_get(obj, key, receiver, context) @@ -312,21 +298,20 @@ pub(crate) fn lazy_set( context: &mut InternalMethodContext<'_>, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); - builtin_borrow.data.is_initialized.set(true); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_set(obj, key, value, receiver, context) @@ -338,21 +323,20 @@ pub(crate) fn lazy_delete( context: &mut InternalMethodContext<'_>, ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_delete(obj, key, context) @@ -363,21 +347,20 @@ pub(crate) fn lazy_own_property_keys( context: &mut Context, ) -> JsResult> { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } ordinary_own_property_keys(obj, context) @@ -390,21 +373,20 @@ pub(crate) fn lazy_construct( ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); let kind = &builtin.borrow().data.kind; - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } match kind { @@ -423,22 +405,20 @@ pub(crate) fn lazy_call( ) -> JsResult { let builtin: JsObject = obj.clone().downcast().expect("obj is not a Builtin"); let kind = &builtin.borrow().data.kind; - if !builtin.borrow().data.is_initialized.get() { - let builtin_borrow = builtin.borrow_mut(); + // If there is a value in here, we need to initialize the builtin + if builtin.borrow().data.init_and_realm.is_some() { + let mut builtin_borrow = builtin.borrow_mut(); + let (init, realm_inner) = builtin_borrow + .data + .init_and_realm + .take() + .expect("init_and_realm not set"); + let realm = &Realm { - inner: builtin_borrow - .data - .realm_inner - .as_ref() - .expect("realm_inner not set") - .upgrade() - .expect("realm_inner not set"), + inner: realm_inner.upgrade().expect("realm_inner not set"), }; - - builtin_borrow.data.is_initialized.set(true); - let init_fn = builtin_borrow.data.init; drop(builtin_borrow); - init_fn(realm); + init(realm); } match kind {