There are 3 JSContext types:
js::jsapi::JSContextwhich is usually used as*mut RawContextscript_bindings::script_runtime::JSContextwhich is just wrapper for above pointer, typically namedSafeJSContextjs::context::JSContextnewJSContext, usually passed as&mut JSContext(GC can happen) or&JSContext(no GC can happen)
Function need to accept &mut JSContext (or something even more powerful, see Realms) if they get any of these arguments: SafeJSContext, RawJSContext, CanGc:
- fn f(cx: SafeJSContext, can_gc: CanGc) {
+ fn f(cx: &mut js::context::JSContext) {
- another_fn_that_still_uses_old(cx.into(), CanGc::from_cx(cx));
+ another_fn_that_uses_raw_cx(unsafe { cx.raw_cx() });prefer doing this inline instead of let can_gc = CanGc::from_cx(cx) as this makes further changes/inspection easier.
The task! macro supports passing &mut JSContext into closures, by naming first parameter cx:
- task!(PostConnectionSteps: |static_node_list: SmallVec<[DomRoot<Node>; 4]>| {
+ task!(PostConnectionSteps: |cx, static_node_list: SmallVec<[DomRoot<Node>; 4]>| {
- vtable_for(&node).post_connection_steps(CanGc::note());
+ vtable_for(&node).post_connection_steps(CanGc::from_cx(cx));
})There are also two special JSContext variants which represents JSContext with entered realm:
js::realm::AutoRealm(to be used insteadJSAutoRealm)js::realm::CurrentRealm(analogue toInRealm)
- let _realm = JSAutoRealm::new(cx_ptr, target_obj);
+ let mut realm = AutoRealm::new(cx, NonNull::new(target).unwrap());- let _realm = enter_realm(object);
+ let mut realm: AutoRealm = enter_auto_realm(cx, object);
+ let mut realm = realm.current_realm(); // if you need current realm- let in_realm_proof = AlreadyInRealm::assert_for_cx(cx_ptr);
+ let mut realm = CurrentRealm::assert(cx);
+ let in_realm_proof = (&mut realm).into();+ let in_realm_proof = (&mut realm).into();
+ InRealm::Already(&in_realm_proof)
- InRealm::AlreadyInRealm(&AlreadyInRealm)- let global = GlobalScope::from_context(cx_ptr, InRealm::Already(&in_realm_proof));
+ let global = GlobalScope::from_current_realm(realm);There are two types of handles in mozjs:
// raw handles
use js::jsapi::{Handle as RawHandle, MutableHandle as RawMutableHandle};
// safe handles with lifetimes
use js::rust::{Handle, MutableHandle};unfortunetly the deref methods of handles are unsound, so one should insted prefer using .as_ref(&cx) or .as_mut_ref(&cx) which will prevent any GC while reference to inner content is alive.
Same methods also exists for RootedGuard (the type that gets created in rooted! macro).
conversion traits implements both safe and unsafe methods, prefer using safe methods:
to_jsval -> safe_to_jsval
from_jsval -> safe_from_jsval
In bindings.conf one can specify one of these options (ordered by their power, prefer using the least powerful one as possible):
cx_no_gcprepends argument&JSContext, which allows creating NoGC tokens and using functions that do not trigger GC.cxprepends argument&mut JSContext, which allows everything that previous one allows, but it also allows calling GC triggering functions.realmprepends argument&mut CurrentRealm, which can be deref_mut to&mut JSContext(so it can do everything that previous can), but it also ensures that there is current entered realm, which can be used for creation of InRealm.