Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mozjs-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "mozjs_sys"
description = "System crate for the Mozilla SpiderMonkey JavaScript engine."
repository.workspace = true
version = "0.140.5-1"
version = "0.140.5-2"
authors = ["Mozilla", "The Servo Project Developers"]
links = "mozjs"
license.workspace = true
Expand Down
35 changes: 35 additions & 0 deletions mozjs-sys/etc/patches/0044-CurrentGlobalHandle.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
diff --git a/js/public/GlobalObject.h b/js/public/GlobalObject.h
index 22da1fc28..2d5562d33 100644
--- a/js/public/GlobalObject.h
+++ b/js/public/GlobalObject.h
@@ -29,6 +29,12 @@ class JS_PUBLIC_API RealmOptions;
*/
extern JS_PUBLIC_API JSObject* CurrentGlobalOrNull(JSContext* cx);

+/**
+ * Get the current realm's global. Returns nullptr if no realm has been
+ * entered.
+ */
+extern JS_PUBLIC_API JSObject *const * CurrentGlobal(JSContext* cx);
+
/**
* Get the global object associated with an object's realm. The object must not
* be a cross-compartment wrapper (because CCWs are shared by all realms in the
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 5a884a2a6..2d49fc416 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1187,6 +1187,13 @@ JS_PUBLIC_API JSObject* JS::CurrentGlobalOrNull(JSContext* cx) {
return cx->global();
}

+JS_PUBLIC_API JSObject *const * JS::CurrentGlobal(JSContext* cx) {
+ AssertHeapIsIdleOrIterating();
+ CHECK_THREAD(cx);
+ MOZ_ASSERT(cx->realm());
+ return reinterpret_cast<JSObject *const *>(cx->global().address());
+}
+
JS_PUBLIC_API JSObject* JS::GetNonCCWObjectGlobal(JSObject* obj) {
AssertHeapIsIdleOrIterating();
MOZ_DIAGNOSTIC_ASSERT(!IsCrossCompartmentWrapper(obj));
6 changes: 6 additions & 0 deletions mozjs-sys/mozjs/js/public/GlobalObject.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions mozjs-sys/mozjs/js/src/jsapi.cpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mozjs/src/generate_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def replace_in_line(fn: tuple[str, str | None]) -> str:
.replace("*mut JSContext", "&mut JSContext")
.replace("*const JSContext", "&JSContext")
)
if link_name in no_gc or "NewCompileOptions" in sig:
if link_name in no_gc or "NewCompileOptions" in sig or "CurrentGlobal" in sig:
sig = sig.replace("&mut JSContext", "&JSContext")
return sig

Expand Down
1 change: 1 addition & 0 deletions mozjs/src/jsapi2_wrappers.in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ wrap!(jsapi: pub fn StealPendingExceptionStack(cx: &mut JSContext, exceptionStac
wrap!(jsapi: pub fn SetPendingExceptionStack(cx: &JSContext, exceptionStack: *const ExceptionStack));
wrap!(jsapi: pub fn ExceptionStackOrNull(obj: HandleObject) -> *mut JSObject);
wrap!(jsapi: pub fn CurrentGlobalOrNull(cx: &JSContext) -> *mut JSObject);
wrap!(jsapi: pub fn CurrentGlobal(cx: &JSContext) -> *const *mut JSObject);
wrap!(jsapi: pub fn NewMapObject(cx: &mut JSContext) -> *mut JSObject);
wrap!(jsapi: pub fn MapSize(cx: &JSContext, obj: HandleObject) -> u32);
wrap!(jsapi: pub fn MapGet(cx: &mut JSContext, obj: HandleObject, key: HandleValue, rval: MutableHandleValue) -> bool);
Expand Down
92 changes: 87 additions & 5 deletions mozjs/src/realm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::jsapi::{JSAutoRealm, JSObject};

use crate::context::JSContext;
use crate::gc::Handle;
use crate::rust::wrappers2::{CurrentGlobalOrNull, GetCurrentRealmOrNull};
use crate::rust::wrappers2::{CurrentGlobal, GetCurrentRealmOrNull};

/// Safe wrapper around [JSAutoRealm].
///
Expand Down Expand Up @@ -100,10 +100,51 @@ impl<'cx> AutoRealm<'cx> {
CurrentRealm::assert(self)
}

/// Obtain the handle to the global object of the current realm.
/// Obtain the handle to the global object of the this realm.
/// Because the handle is bounded with lifetime to realm, you cannot do this:
///
/// ```compile_fail
/// 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].
pub fn global(&'_ self) -> Handle<'_, *mut JSObject> {
// SAFETY: object is rooted by realm
unsafe { Handle::from_marked_location(CurrentGlobalOrNull(&*self) as _) }
unsafe { Handle::from_marked_location(CurrentGlobal(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);
/// }
/// ```
pub fn global_and_reborrow(&'_ mut self) -> (Handle<'_, *mut JSObject>, &'_ mut Self) {
// SAFETY: This is ok because the handle will still be bound to original lifetime.
(unsafe { std::mem::transmute(self.global()) }, self)
}

/// Erase the lifetime of this [AutoRealm].
Expand Down Expand Up @@ -170,10 +211,51 @@ impl<'cx> CurrentRealm<'cx> {
}
}

/// Obtain the handle to the global object of the current realm.
/// Obtain the handle to the global object of the this realm.
/// Because the handle is bounded with lifetime to realm, you cannot do this:
///
/// ```compile_fail
/// use mozjs::context::JSContext;
/// use mozjs::jsapi::JSObject;
/// use mozjs::realm::CurrentRealm;
/// use std::ptr::NonNull;
/// use mozjs::rust::Handle;
///
/// fn g(realm: &'_ mut CurrentRealm, global: Handle<'_, *mut JSObject>) {
/// }
///
/// fn f(realm: &mut CurrentRealm) {
/// let global = realm.global();
/// g(realm, global);
/// }
/// ```
///
/// instead use [CurrentRealm::global_and_reborrow].
pub fn global(&'_ self) -> Handle<'_, *mut JSObject> {
// SAFETY: object is rooted by realm
unsafe { Handle::from_marked_location(CurrentGlobalOrNull(&*self) as _) }
unsafe { Handle::from_marked_location(CurrentGlobal(self)) }
}

/// Obtain the handle to the global object of this realm and reborrow the realm.
///
/// ```
/// use mozjs::context::JSContext;
/// use mozjs::jsapi::JSObject;
/// use mozjs::realm::CurrentRealm;
/// use std::ptr::NonNull;
/// use mozjs::rust::Handle;
///
/// fn g(realm: &'_ mut CurrentRealm, global: Handle<'_, *mut JSObject>) {
/// }
///
/// fn f(realm: &mut CurrentRealm) {
/// let (global, realm) = realm.global_and_reborrow();
/// g(realm, global);
/// }
/// ```
pub fn global_and_reborrow(&'_ mut self) -> (Handle<'_, *mut JSObject>, &'_ mut Self) {
// SAFETY: This is ok because the handle will still be bound to original lifetime.
(unsafe { std::mem::transmute(self.global()) }, self)
}

pub fn realm(&self) -> &NonNull<Realm> {
Expand Down
15 changes: 5 additions & 10 deletions mozjs/tests/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,19 @@ fn callback() {
&*c_option,
));
let mut realm = AutoRealm::new_from_handle(context, global.handle());
let context = &mut realm;
let (global_handle, realm) = realm.global_and_reborrow();
let context = realm;

let function = JS_DefineFunction(
context,
global.handle().into(),
c"puts".as_ptr(),
Some(puts),
1,
0,
);
let function =
JS_DefineFunction(context, global_handle, c"puts".as_ptr(), Some(puts), 1, 0);
assert!(!function.is_null());

let javascript = "puts('Test Iñtërnâtiônàlizætiøn ┬─┬ノ( º _ ºノ) ');";
rooted!(&in(context) let mut rval = UndefinedValue());
let options = CompileOptionsWrapper::new(&context, "test.js", 0);
assert!(evaluate_script(
context,
global.handle(),
global_handle,
javascript,
rval.handle_mut(),
options
Expand Down
Loading