Skip to content

Commit 16e1e3a

Browse files
sagudevjdm
andauthored
Fixup global method on realm and add reborrow variant (#657)
* currentglobal Signed-off-by: sagudev <[email protected]> * wrappers2 Signed-off-by: sagudev <[email protected]> * fmt Signed-off-by: sagudev <[email protected]> * Apply suggestions from code review Co-authored-by: Josh Matthews <[email protected]> Signed-off-by: Sam <[email protected]> --------- Signed-off-by: sagudev <[email protected]> Signed-off-by: Sam <[email protected]> Co-authored-by: Josh Matthews <[email protected]>
1 parent 8bf5bf8 commit 16e1e3a

File tree

8 files changed

+143
-17
lines changed

8 files changed

+143
-17
lines changed

mozjs-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "mozjs_sys"
33
description = "System crate for the Mozilla SpiderMonkey JavaScript engine."
44
repository.workspace = true
5-
version = "0.140.5-1"
5+
version = "0.140.5-2"
66
authors = ["Mozilla", "The Servo Project Developers"]
77
links = "mozjs"
88
license.workspace = true
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
diff --git a/js/public/GlobalObject.h b/js/public/GlobalObject.h
2+
index 22da1fc28..2d5562d33 100644
3+
--- a/js/public/GlobalObject.h
4+
+++ b/js/public/GlobalObject.h
5+
@@ -29,6 +29,12 @@ class JS_PUBLIC_API RealmOptions;
6+
*/
7+
extern JS_PUBLIC_API JSObject* CurrentGlobalOrNull(JSContext* cx);
8+
9+
+/**
10+
+ * Get the current realm's global. Returns nullptr if no realm has been
11+
+ * entered.
12+
+ */
13+
+extern JS_PUBLIC_API JSObject *const * CurrentGlobal(JSContext* cx);
14+
+
15+
/**
16+
* Get the global object associated with an object's realm. The object must not
17+
* be a cross-compartment wrapper (because CCWs are shared by all realms in the
18+
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
19+
index 5a884a2a6..2d49fc416 100644
20+
--- a/js/src/jsapi.cpp
21+
+++ b/js/src/jsapi.cpp
22+
@@ -1187,6 +1187,13 @@ JS_PUBLIC_API JSObject* JS::CurrentGlobalOrNull(JSContext* cx) {
23+
return cx->global();
24+
}
25+
26+
+JS_PUBLIC_API JSObject *const * JS::CurrentGlobal(JSContext* cx) {
27+
+ AssertHeapIsIdleOrIterating();
28+
+ CHECK_THREAD(cx);
29+
+ MOZ_ASSERT(cx->realm());
30+
+ return reinterpret_cast<JSObject *const *>(cx->global().address());
31+
+}
32+
+
33+
JS_PUBLIC_API JSObject* JS::GetNonCCWObjectGlobal(JSObject* obj) {
34+
AssertHeapIsIdleOrIterating();
35+
MOZ_DIAGNOSTIC_ASSERT(!IsCrossCompartmentWrapper(obj));

mozjs-sys/mozjs/js/public/GlobalObject.h

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mozjs-sys/mozjs/js/src/jsapi.cpp

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mozjs/src/generate_wrappers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def replace_in_line(fn: tuple[str, str | None]) -> str:
124124
.replace("*mut JSContext", "&mut JSContext")
125125
.replace("*const JSContext", "&JSContext")
126126
)
127-
if link_name in no_gc or "NewCompileOptions" in sig:
127+
if link_name in no_gc or "NewCompileOptions" in sig or "CurrentGlobal" in sig:
128128
sig = sig.replace("&mut JSContext", "&JSContext")
129129
return sig
130130

mozjs/src/jsapi2_wrappers.in.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ wrap!(jsapi: pub fn StealPendingExceptionStack(cx: &mut JSContext, exceptionStac
136136
wrap!(jsapi: pub fn SetPendingExceptionStack(cx: &JSContext, exceptionStack: *const ExceptionStack));
137137
wrap!(jsapi: pub fn ExceptionStackOrNull(obj: HandleObject) -> *mut JSObject);
138138
wrap!(jsapi: pub fn CurrentGlobalOrNull(cx: &JSContext) -> *mut JSObject);
139+
wrap!(jsapi: pub fn CurrentGlobal(cx: &JSContext) -> *const *mut JSObject);
139140
wrap!(jsapi: pub fn NewMapObject(cx: &mut JSContext) -> *mut JSObject);
140141
wrap!(jsapi: pub fn MapSize(cx: &JSContext, obj: HandleObject) -> u32);
141142
wrap!(jsapi: pub fn MapGet(cx: &mut JSContext, obj: HandleObject, key: HandleValue, rval: MutableHandleValue) -> bool);

mozjs/src/realm.rs

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::jsapi::{JSAutoRealm, JSObject};
77

88
use crate::context::JSContext;
99
use crate::gc::Handle;
10-
use crate::rust::wrappers2::{CurrentGlobalOrNull, GetCurrentRealmOrNull};
10+
use crate::rust::wrappers2::{CurrentGlobal, GetCurrentRealmOrNull};
1111

1212
/// Safe wrapper around [JSAutoRealm].
1313
///
@@ -100,10 +100,51 @@ impl<'cx> AutoRealm<'cx> {
100100
CurrentRealm::assert(self)
101101
}
102102

103-
/// Obtain the handle to the global object of the current realm.
103+
/// Obtain the handle to the global object of the this realm.
104+
/// Because the handle is bounded with lifetime to realm, you cannot do this:
105+
///
106+
/// ```compile_fail
107+
/// use mozjs::context::JSContext;
108+
/// use mozjs::jsapi::JSObject;
109+
/// use mozjs::realm::AutoRealm;
110+
/// use std::ptr::NonNull;
111+
/// use mozjs::rust::Handle;
112+
///
113+
/// fn g(realm: &'_ mut AutoRealm, global: Handle<'_, *mut JSObject>) {
114+
/// }
115+
///
116+
/// fn f(realm: &mut AutoRealm) {
117+
/// let global = realm.global();
118+
/// g(realm, global);
119+
/// }
120+
/// ```
121+
///
122+
/// instead use [AutoRealm::global_and_reborrow].
104123
pub fn global(&'_ self) -> Handle<'_, *mut JSObject> {
105124
// SAFETY: object is rooted by realm
106-
unsafe { Handle::from_marked_location(CurrentGlobalOrNull(&*self) as _) }
125+
unsafe { Handle::from_marked_location(CurrentGlobal(self)) }
126+
}
127+
128+
/// Obtain the handle to the global object of the this realm and reborrow the realm.
129+
///
130+
/// ```
131+
/// use mozjs::context::JSContext;
132+
/// use mozjs::jsapi::JSObject;
133+
/// use mozjs::realm::AutoRealm;
134+
/// use std::ptr::NonNull;
135+
/// use mozjs::rust::Handle;
136+
///
137+
/// fn g(realm: &'_ mut AutoRealm, global: Handle<'_, *mut JSObject>) {
138+
/// }
139+
///
140+
/// fn f(realm: &mut AutoRealm) {
141+
/// let (global, realm) = realm.global_and_reborrow();
142+
/// g(realm, global);
143+
/// }
144+
/// ```
145+
pub fn global_and_reborrow(&'_ mut self) -> (Handle<'_, *mut JSObject>, &'_ mut Self) {
146+
// SAFETY: This is ok because the handle will still be bound to original lifetime.
147+
(unsafe { std::mem::transmute(self.global()) }, self)
107148
}
108149

109150
/// Erase the lifetime of this [AutoRealm].
@@ -170,10 +211,51 @@ impl<'cx> CurrentRealm<'cx> {
170211
}
171212
}
172213

173-
/// Obtain the handle to the global object of the current realm.
214+
/// Obtain the handle to the global object of the this realm.
215+
/// Because the handle is bounded with lifetime to realm, you cannot do this:
216+
///
217+
/// ```compile_fail
218+
/// use mozjs::context::JSContext;
219+
/// use mozjs::jsapi::JSObject;
220+
/// use mozjs::realm::CurrentRealm;
221+
/// use std::ptr::NonNull;
222+
/// use mozjs::rust::Handle;
223+
///
224+
/// fn g(realm: &'_ mut CurrentRealm, global: Handle<'_, *mut JSObject>) {
225+
/// }
226+
///
227+
/// fn f(realm: &mut CurrentRealm) {
228+
/// let global = realm.global();
229+
/// g(realm, global);
230+
/// }
231+
/// ```
232+
///
233+
/// instead use [CurrentRealm::global_and_reborrow].
174234
pub fn global(&'_ self) -> Handle<'_, *mut JSObject> {
175235
// SAFETY: object is rooted by realm
176-
unsafe { Handle::from_marked_location(CurrentGlobalOrNull(&*self) as _) }
236+
unsafe { Handle::from_marked_location(CurrentGlobal(self)) }
237+
}
238+
239+
/// Obtain the handle to the global object of this realm and reborrow the realm.
240+
///
241+
/// ```
242+
/// use mozjs::context::JSContext;
243+
/// use mozjs::jsapi::JSObject;
244+
/// use mozjs::realm::CurrentRealm;
245+
/// use std::ptr::NonNull;
246+
/// use mozjs::rust::Handle;
247+
///
248+
/// fn g(realm: &'_ mut CurrentRealm, global: Handle<'_, *mut JSObject>) {
249+
/// }
250+
///
251+
/// fn f(realm: &mut CurrentRealm) {
252+
/// let (global, realm) = realm.global_and_reborrow();
253+
/// g(realm, global);
254+
/// }
255+
/// ```
256+
pub fn global_and_reborrow(&'_ mut self) -> (Handle<'_, *mut JSObject>, &'_ mut Self) {
257+
// SAFETY: This is ok because the handle will still be bound to original lifetime.
258+
(unsafe { std::mem::transmute(self.global()) }, self)
177259
}
178260

179261
pub fn realm(&self) -> &NonNull<Realm> {

mozjs/tests/callback.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,19 @@ fn callback() {
3838
&*c_option,
3939
));
4040
let mut realm = AutoRealm::new_from_handle(context, global.handle());
41-
let context = &mut realm;
41+
let (global_handle, realm) = realm.global_and_reborrow();
42+
let context = realm;
4243

43-
let function = JS_DefineFunction(
44-
context,
45-
global.handle().into(),
46-
c"puts".as_ptr(),
47-
Some(puts),
48-
1,
49-
0,
50-
);
44+
let function =
45+
JS_DefineFunction(context, global_handle, c"puts".as_ptr(), Some(puts), 1, 0);
5146
assert!(!function.is_null());
5247

5348
let javascript = "puts('Test Iñtërnâtiônàlizætiøn ┬─┬ノ( º _ ºノ) ');";
5449
rooted!(&in(context) let mut rval = UndefinedValue());
5550
let options = CompileOptionsWrapper::new(&context, "test.js", 0);
5651
assert!(evaluate_script(
5752
context,
58-
global.handle(),
53+
global_handle,
5954
javascript,
6055
rval.handle_mut(),
6156
options

0 commit comments

Comments
 (0)