pub struct AutoRealm<'cx> {
cx: JSContext,
realm: JSAutoRealm,
phantom: PhantomData<&'cx mut ()>,
}Expand description
Safe wrapper around JSAutoRealm.
On creation it enters the realm of the target object, realm becomes current (it’s on top of the realm stack). Drop exits realm.
While creating AutoRealm will not trigger GC,
it still takes &mut JSContext, because it can be used in place of JSContext (by Deref/DerefMut).
with additional information of entered/current realm:
use mozjs::context::JSContext;
use mozjs::jsapi::JSObject;
use mozjs::realm::AutoRealm;
use std::ptr::NonNull;
fn f(cx: &mut JSContext, target: NonNull<JSObject>) {
let realm = AutoRealm::new(cx, target);
f(cx, target); // one cannot use JSContext here,
// because that could allow out of order realm drops.
}instead do this:
use mozjs::context::JSContext;
use mozjs::jsapi::JSObject;
use mozjs::realm::AutoRealm;
use std::ptr::NonNull;
fn f(cx: &mut JSContext, target: NonNull<JSObject>) {
let mut realm = AutoRealm::new(cx, target);
let cx = &mut realm; // this JSContext is bounded to AutoRealm
// which in turn is bounded to original JSContext
f(cx, target);
}This also enforces LIFO entering/exiting realms, which is not enforced by JSAutoRealm:
use mozjs::context::JSContext;
use mozjs::jsapi::JSObject;
use mozjs::realm::AutoRealm;
use std::ptr::NonNull;
fn f(cx: &mut JSContext, t1: NonNull<JSObject>, t2: NonNull<JSObject>) {
let mut realm1 = AutoRealm::new(cx, t1);
let cx = &mut realm1;
let realm2 = AutoRealm::new(cx, t2);
drop(realm1); // it's not possible to drop realm1 before realm2
}Fields§
§cx: JSContext§realm: JSAutoRealm§phantom: PhantomData<&'cx mut ()>Implementations§
Source§impl<'cx> AutoRealm<'cx>
impl<'cx> AutoRealm<'cx>
Sourcepub fn new(cx: &'cx mut JSContext, target: NonNull<JSObject>) -> AutoRealm<'cx>
pub fn new(cx: &'cx mut JSContext, target: NonNull<JSObject>) -> AutoRealm<'cx>
Enters the realm of the given target object. The realm becomes the current realm (it’s on top of the realm stack). The realm is exited when the AutoRealm is dropped.
While this function will not trigger GC (it will in fact root the object)
but because AutoRealm can act as a JSContext we need to take &mut JSContext.
Sourcepub fn new_from_handle(
cx: &'cx mut JSContext,
target: Handle<'_, *mut JSObject>,
) -> AutoRealm<'cx>
pub fn new_from_handle( cx: &'cx mut JSContext, target: Handle<'_, *mut JSObject>, ) -> AutoRealm<'cx>
Enters the realm of the given target object. The realm becomes the current realm (it’s on top of the realm stack). The realm is exited when the AutoRealm is dropped.
While this function will not trigger GC (it will in fact root the object)
but because AutoRealm can act as a JSContext we need to take &mut JSContext.
Sourcepub fn current_realm(&mut self) -> CurrentRealm<'_>
pub fn current_realm(&mut self) -> CurrentRealm<'_>
If we can get &mut AutoRealm then we are current realm, because if there existed other current realm, we couldn’t get &mut AutoRealm.
use mozjs::context::JSContext;
use mozjs::jsapi::JSObject;
use mozjs::realm::AutoRealm;
use std::ptr::NonNull;
fn f(cx: &mut JSContext, t: NonNull<JSObject>) {
let mut realm = AutoRealm::new(cx, t);
let mut current_realm = realm.current_realm();
}Sourcepub fn global(&self) -> Handle<'_, *mut JSObject>
pub fn global(&self) -> Handle<'_, *mut JSObject>
Obtain the handle to the global object of the this realm. Because the handle is bounded with lifetime to realm, you cannot do this:
use mozjs::context::JSContext;
use mozjs::jsapi::JSObject;
use mozjs::realm::AutoRealm;
use std::ptr::NonNull;
use mozjs::rust::Handle;
fn g(realm: &'_ mut AutoRealm, global: Handle<'_, *mut JSObject>) {
}
fn f(realm: &mut AutoRealm) {
let global = realm.global();
g(realm, global);
}instead use AutoRealm::global_and_reborrow.
Sourcepub fn global_and_reborrow(&mut self) -> (Handle<'_, *mut JSObject>, &mut Self)
pub fn global_and_reborrow(&mut self) -> (Handle<'_, *mut JSObject>, &mut Self)
Obtain the handle to the global object of the this realm and reborrow the realm.
use mozjs::context::JSContext;
use mozjs::jsapi::JSObject;
use mozjs::realm::AutoRealm;
use std::ptr::NonNull;
use mozjs::rust::Handle;
fn g(realm: &'_ mut AutoRealm, global: Handle<'_, *mut JSObject>) {
}
fn f(realm: &mut AutoRealm) {
let (global, realm) = realm.global_and_reborrow();
g(realm, global);
}Sourcepub unsafe fn erase_lifetime(self) -> AutoRealm<'static>
pub unsafe fn erase_lifetime(self) -> AutoRealm<'static>
pub fn realm(&self) -> &JSAutoRealm
Methods from Deref<Target = JSContext>§
Sourcepub unsafe fn raw_cx(&mut self) -> *mut RawJSContext
pub unsafe fn raw_cx(&mut self) -> *mut RawJSContext
Obtain RawJSContext mutable pointer.
§Safety
No NoGC tokens should be constructed while returned pointer is available to user. In practices this means that one should use the result as direct argument to SpiderMonkey function and not store it in variable.
use mozjs::context::*;
use mozjs::jsapi::JSContext as RawJSContext;
fn SM_function_that_can_trigger_gc(_cx: *mut RawJSContext) {}
fn can_trigger_gc(cx: &mut JSContext) {
unsafe { SM_function_that_can_trigger_gc(cx.raw_cx()) } // returned pointer is immediately used
cx.no_gc(); // this is ok because no outstanding raw pointer is alive
}Sourcepub unsafe fn raw_cx_no_gc(&self) -> *mut RawJSContext
pub unsafe fn raw_cx_no_gc(&self) -> *mut RawJSContext
Obtain RawJSContext mutable pointer, that will not be used for GC.
§Safety
No &mut calls should be done on JSContext while returned pointer is available. In practices this means that one should use the result as direct argument to SpiderMonkey function and not store it in variable.
use mozjs::context::*;
use mozjs::jsapi::JSContext as RawJSContext;
fn SM_function_that_cannot_trigger_gc(_cx: *mut RawJSContext) {}
fn f(cx: &mut JSContext) {
unsafe { SM_function_that_cannot_trigger_gc(cx.raw_cx_no_gc()) } // returned pointer is immediately used
}