use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use crate::jsapi::JS::Realm;
use crate::jsapi::{JSAutoRealm, JSObject};
use crate::context::JSContext;
use crate::gc::Handle;
use crate::rust::wrappers2::{CurrentGlobal, GetCurrentRealmOrNull};
pub struct AutoRealm<'cx> {
cx: JSContext,
realm: JSAutoRealm,
phantom: PhantomData<&'cx mut ()>,
}
impl<'cx> AutoRealm<'cx> {
pub fn new(cx: &'cx mut JSContext, target: NonNull<JSObject>) -> AutoRealm<'cx> {
let realm = JSAutoRealm::new(unsafe { cx.raw_cx_no_gc() }, target.as_ptr());
AutoRealm {
cx: unsafe { JSContext::from_ptr(NonNull::new_unchecked(cx.raw_cx())) },
realm,
phantom: PhantomData,
}
}
pub fn new_from_handle(
cx: &'cx mut JSContext,
target: Handle<*mut JSObject>,
) -> AutoRealm<'cx> {
Self::new(cx, NonNull::new(target.get()).unwrap())
}
pub fn current_realm(&'_ mut self) -> CurrentRealm<'_> {
CurrentRealm::assert(self)
}
pub fn global(&'_ self) -> Handle<'_, *mut JSObject> {
unsafe { Handle::from_marked_location(CurrentGlobal(self)) }
}
pub fn global_and_reborrow(&'_ mut self) -> (Handle<'_, *mut JSObject>, &'_ mut Self) {
(unsafe { std::mem::transmute(self.global()) }, self)
}
pub unsafe fn erase_lifetime(self) -> AutoRealm<'static> {
std::mem::transmute(self)
}
pub fn realm(&self) -> &JSAutoRealm {
&self.realm
}
}
impl<'cx> Deref for AutoRealm<'cx> {
type Target = JSContext;
fn deref(&'_ self) -> &'_ Self::Target {
&self.cx
}
}
impl<'cx> DerefMut for AutoRealm<'cx> {
fn deref_mut(&'_ mut self) -> &'_ mut Self::Target {
&mut self.cx
}
}
impl<'cx> Drop for AutoRealm<'cx> {
fn drop(&mut self) {}
}
pub struct CurrentRealm<'cx> {
cx: &'cx mut JSContext,
realm: NonNull<Realm>,
}
impl<'cx> CurrentRealm<'cx> {
pub fn assert(cx: &'cx mut JSContext) -> CurrentRealm<'cx> {
let realm = unsafe { GetCurrentRealmOrNull(cx) };
CurrentRealm {
cx,
realm: NonNull::new(realm).unwrap(),
}
}
pub fn global(&'_ self) -> Handle<'_, *mut JSObject> {
unsafe { Handle::from_marked_location(CurrentGlobal(self)) }
}
pub fn global_and_reborrow(&'_ mut self) -> (Handle<'_, *mut JSObject>, &'_ mut Self) {
(unsafe { std::mem::transmute(self.global()) }, self)
}
pub fn realm(&self) -> &NonNull<Realm> {
&self.realm
}
}
impl<'cx> Deref for CurrentRealm<'cx> {
type Target = JSContext;
fn deref(&'_ self) -> &'_ Self::Target {
&self.cx
}
}
impl<'cx> DerefMut for CurrentRealm<'cx> {
fn deref_mut(&'_ mut self) -> &'_ mut Self::Target {
&mut self.cx
}
}