Skip to content

Commit

Permalink
try to use same object in both lazyPrototype and constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwilliams committed Nov 4, 2024
1 parent cf4d917 commit 56fa816
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 128 deletions.
24 changes: 18 additions & 6 deletions core/engine/src/context/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ use boa_macros::js_str;

use crate::{
builtins::{
iterable::IteratorPrototypes, uri::UriFunctions, Array, Date, IntrinsicObject, Math,
OrdinaryObject,
function::ConstructorKind, iterable::IteratorPrototypes, uri::UriFunctions, Array, Date,
IntrinsicObject, Math, OrdinaryObject,
},
js_string,
native_function::NativeFunctionObject,
object::{
internal_methods::immutable_prototype::IMMUTABLE_PROTOTYPE_EXOTIC_INTERNAL_METHODS,
shape::{shared_shape::template::ObjectTemplate, RootShape},
JsFunction, JsObject, LazyBuiltIn, Object, CONSTRUCTOR, PROTOTYPE,
BuiltinKind, JsFunction, JsObject, LazyBuiltIn, Object, CONSTRUCTOR, PROTOTYPE,
},
property::{Attribute, PropertyKey},
realm::{Realm, RealmInner},
JsSymbol,
JsSymbol, JsValue, NativeFunction,
};

#[cfg(feature = "intl")]
Expand Down Expand Up @@ -101,11 +102,22 @@ impl StandardConstructor {

/// Similar to `with_prototype`, but the prototype is lazily initialized.
fn lazy(init: fn(&Realm) -> (), realm_inner: &WeakGc<RealmInner>) -> Self {
let constructor = JsFunction::lazy_intrinsic_function(true, init, realm_inner.clone());
let obj = JsObject::from_proto_and_data(
None,
LazyBuiltIn {
init_and_realm: Some((init, realm_inner.clone())),
kind: BuiltinKind::Function(NativeFunctionObject {
f: NativeFunction::from_fn_ptr(|_, _, _| Ok(JsValue::undefined())),
constructor: Some(ConstructorKind::Base),
realm: None,
}),
},
);
let constructor = JsFunction::from_object_unchecked(obj);

Self {
constructor: constructor.clone(),
prototype: JsObject::lazy_prototype(constructor.clone()),
prototype: JsObject::lazy_prototype(obj.clone()),
}
}

Expand Down
182 changes: 61 additions & 121 deletions core/engine/src/object/builtins/lazy_prototype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{JsFunction, LazyBuiltIn};
#[derive(Clone, Trace, Finalize, Debug)]
#[allow(clippy::type_complexity)]
pub struct LazyPrototype {
pub(crate) constructor: JsFunction,
pub(crate) constructor: JsObject<LazyBuiltIn>,
}

// // SAFETY: Temporary, TODO move back to derived Trace when possible
Expand Down Expand Up @@ -59,16 +59,11 @@ pub(crate) fn lazy_get_prototype_of(
obj: &JsObject,
context: &mut Context,
) -> JsResult<JsPrototype> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_get_prototype_of(obj, context)
}

Expand All @@ -77,43 +72,28 @@ pub(crate) fn lazy_set_prototype_of(
prototype: JsPrototype,
context: &mut Context,
) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_set_prototype_of(obj, prototype, context)
}
pub(crate) fn lazy_is_extensible(obj: &JsObject, context: &mut Context) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_is_extensible(obj, context)
}

pub(crate) fn lazy_prevent_extensions(obj: &JsObject, context: &mut Context) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_prevent_extensions(obj, context)
}

Expand All @@ -122,16 +102,11 @@ pub(crate) fn lazy_get_own_property(
key: &PropertyKey,
context: &mut InternalMethodContext<'_>,
) -> JsResult<Option<PropertyDescriptor>> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_get_own_property(obj, key, context)
}

Expand All @@ -141,16 +116,11 @@ pub(crate) fn lazy_define_own_property(
desc: PropertyDescriptor,
context: &mut InternalMethodContext<'_>,
) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());

ordinary_define_own_property(obj, key, desc, context)
}
Expand All @@ -160,16 +130,11 @@ pub(crate) fn lazy_has_property(
key: &PropertyKey,
context: &mut InternalMethodContext<'_>,
) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_has_property(obj, key, context)
}

Expand All @@ -179,16 +144,11 @@ pub(crate) fn lazy_try_get(
receiver: JsValue,
context: &mut InternalMethodContext<'_>,
) -> JsResult<Option<JsValue>> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());

ordinary_try_get(obj, key, receiver, context)
}
Expand All @@ -199,16 +159,11 @@ pub(crate) fn lazy_get(
receiver: JsValue,
context: &mut InternalMethodContext<'_>,
) -> JsResult<JsValue> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_get(obj, key, receiver, context)
}

Expand All @@ -219,16 +174,11 @@ pub(crate) fn lazy_set(
receiver: JsValue,
context: &mut InternalMethodContext<'_>,
) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_set(obj, key, value, receiver, context)
}

Expand All @@ -237,33 +187,23 @@ pub(crate) fn lazy_delete(
key: &PropertyKey,
context: &mut InternalMethodContext<'_>,
) -> JsResult<bool> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());
ordinary_delete(obj, key, context)
}

pub(crate) fn lazy_own_property_keys(
obj: &JsObject,
context: &mut Context,
) -> JsResult<Vec<PropertyKey>> {
let lazy_prototype: JsObject<LazyPrototype> =
obj.clone().downcast().expect("obj is not a Builtin");
let lazy_builtin = lazy_prototype
.borrow_mut()
.data
.constructor
.downcast_ref::<LazyBuiltIn>()
.expect("constructor is not a LazyBuiltIn")
.clone();
LazyBuiltIn::ensure_init(lazy_builtin);
let lazy_built_in: JsObject<LazyBuiltIn> = obj
.clone()
.downcast::<LazyBuiltIn>()
.expect("obj is not a Builtin");
LazyBuiltIn::ensure_init(lazy_built_in.borrow_mut().data.clone());

ordinary_own_property_keys(obj, context)
}
3 changes: 2 additions & 1 deletion core/engine/src/object/jsobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::{
};
use boa_gc::{self, Finalize, Gc, GcBox, GcRefCell, Trace, WeakGc};
use boa_macros::js_str;
use once_cell::sync::Lazy;
use std::{
cell::RefCell,
collections::HashMap,
Expand Down Expand Up @@ -96,7 +97,7 @@ impl JsObject {
}
/// Creates a new lazy `JsObject` from its inner object and its vtable.
/// This is used for built-in objects that are lazily initialized.
pub(crate) fn lazy_prototype(constructor: JsFunction) -> Self {
pub(crate) fn lazy_prototype(constructor: JsObject<LazyBuiltIn>) -> Self {
Self::from_proto_and_data(None, LazyPrototype { constructor })
}

Expand Down

0 comments on commit 56fa816

Please sign in to comment.