use std::default::Default;
use js::jsapi::{Heap, JSObject};
use js::rust::HandleObject;
use crate::dom::bindings::conversions::DerivedFrom;
use crate::dom::bindings::iterable::{Iterable, IterableIterator};
use crate::dom::bindings::root::{Dom, DomRoot, Root};
use crate::dom::bindings::trace::JSTraceable;
use crate::dom::globalscope::GlobalScope;
use crate::realms::AlreadyInRealm;
use crate::script_runtime::{CanGc, JSContext};
pub fn reflect_dom_object<T, U>(obj: Box<T>, global: &U) -> DomRoot<T>
where
T: DomObject + DomObjectWrap,
U: DerivedFrom<GlobalScope>,
{
let global_scope = global.upcast();
unsafe {
T::WRAP(
GlobalScope::get_cx(),
global_scope,
None,
obj,
CanGc::note(),
)
}
}
pub fn reflect_dom_object_with_proto<T, U>(
obj: Box<T>,
global: &U,
proto: Option<HandleObject>,
can_gc: CanGc,
) -> DomRoot<T>
where
T: DomObject + DomObjectWrap,
U: DerivedFrom<GlobalScope>,
{
let global_scope = global.upcast();
unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, proto, obj, can_gc) }
}
#[allow(crown::unrooted_must_root)]
#[derive(MallocSizeOf)]
#[crown::unrooted_must_root_lint::must_root]
pub struct Reflector {
#[ignore_malloc_size_of = "defined and measured in rust-mozjs"]
object: Heap<*mut JSObject>,
}
#[allow(crown::unrooted_must_root)]
impl PartialEq for Reflector {
fn eq(&self, other: &Reflector) -> bool {
self.object.get() == other.object.get()
}
}
impl Reflector {
#[inline]
pub fn get_jsobject(&self) -> HandleObject {
unsafe { HandleObject::from_raw(self.object.handle()) }
}
pub unsafe fn set_jsobject(&self, object: *mut JSObject) {
assert!(self.object.get().is_null());
assert!(!object.is_null());
self.object.set(object);
}
pub fn rootable(&self) -> &Heap<*mut JSObject> {
&self.object
}
#[allow(clippy::new_without_default)]
pub fn new() -> Reflector {
Reflector {
object: Heap::default(),
}
}
}
pub trait DomObject: JSTraceable + 'static {
fn reflector(&self) -> &Reflector;
fn global(&self) -> DomRoot<GlobalScope>
where
Self: Sized,
{
let realm = AlreadyInRealm::assert_for_cx(GlobalScope::get_cx());
GlobalScope::from_reflector(self, &realm)
}
}
impl DomObject for Reflector {
fn reflector(&self) -> &Self {
self
}
}
pub trait MutDomObject: DomObject {
unsafe fn init_reflector(&self, obj: *mut JSObject);
}
impl MutDomObject for Reflector {
unsafe fn init_reflector(&self, obj: *mut JSObject) {
self.set_jsobject(obj)
}
}
pub trait DomObjectWrap: Sized + DomObject {
#[allow(clippy::type_complexity)]
const WRAP: unsafe fn(
JSContext,
&GlobalScope,
Option<HandleObject>,
Box<Self>,
CanGc,
) -> Root<Dom<Self>>;
}
pub trait DomObjectIteratorWrap: DomObjectWrap + JSTraceable + Iterable {
#[allow(clippy::type_complexity)]
const ITER_WRAP: unsafe fn(
JSContext,
&GlobalScope,
Option<HandleObject>,
Box<IterableIterator<Self>>,
CanGc,
) -> Root<Dom<IterableIterator<Self>>>;
}