Skip to content

Commit 4be1b2d

Browse files
committed
f
Signed-off-by: sagudev <[email protected]>
1 parent 7f6380f commit 4be1b2d

26 files changed

+105
-84
lines changed

mozjs/benches/latin1_string_conversion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn bench_str_repetition(
6161
fn external_string(c: &mut Criterion) {
6262
let engine = JSEngine::init().unwrap();
6363
let mut runtime = Runtime::new(engine.handle());
64-
let context = *runtime.cx();
64+
let context = **runtime.cx();
6565
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
6666
let c_option = RealmOptions::default();
6767
rooted!(in(context) let global = unsafe { JS_NewGlobalObject(

mozjs/examples/eval.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use mozjs::rust::{JSEngine, RealmOptions, Runtime};
2323

2424
fn run(mut rt: Runtime) {
2525
let options = RealmOptions::default();
26-
rooted!(in(*rt.cx()) let global = unsafe {
27-
JS_NewGlobalObject(*rt.cx(), &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
26+
rooted!(in(**rt.cx()) let global = unsafe {
27+
JS_NewGlobalObject(**rt.cx(), &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
2828
OnNewGlobalHookOption::FireOnNewGlobalHook,
2929
&*options)
3030
});
@@ -37,7 +37,7 @@ fn run(mut rt: Runtime) {
3737
* The return value comes back here. If it could be a GC thing, you must add it to the
3838
* GC's "root set" with the rooted! macro.
3939
*/
40-
rooted!(in(*rt.cx()) let mut rval = UndefinedValue());
40+
rooted!(in(**rt.cx()) let mut rval = UndefinedValue());
4141

4242
/*
4343
* Some example source in a string. This is equivalent to JS_EvaluateScript in C++.

mozjs/examples/minimal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn main() {
3434
}
3535

3636
fn run(mut rt: Runtime) {
37-
let cx = *rt.cx();
37+
let cx = **rt.cx();
3838
// In addition to what the C++ interface requires, define a global scope for the code.
3939
//
4040
// This demonstrates the way Rust uses the C++ garbage collector: using the rooted! macro to

mozjs/examples/wasm.rs

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -49,34 +49,34 @@ unsafe extern "C" fn bar(_cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool
4949

5050
fn run(mut rt: Runtime) {
5151
let options = RealmOptions::default();
52-
rooted!(in(*rt.cx()) let global = unsafe {
53-
JS_NewGlobalObject(*rt.cx(), &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
52+
rooted!(in(**rt.cx()) let global = unsafe {
53+
JS_NewGlobalObject(**rt.cx(), &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
5454
OnNewGlobalHookOption::FireOnNewGlobalHook,
5555
&*options)
5656
});
57-
let _ac = JSAutoRealm::new(*rt.cx(), global.get());
57+
let _ac = JSAutoRealm::new(**rt.cx(), global.get());
5858

5959
// Get WebAssembly.Module and WebAssembly.Instance constructors.
60-
rooted!(in(*rt.cx()) let mut wasm = UndefinedValue());
61-
rooted!(in(*rt.cx()) let mut wasm_module = UndefinedValue());
62-
rooted!(in(*rt.cx()) let mut wasm_instance = UndefinedValue());
60+
rooted!(in(**rt.cx()) let mut wasm = UndefinedValue());
61+
rooted!(in(**rt.cx()) let mut wasm_module = UndefinedValue());
62+
rooted!(in(**rt.cx()) let mut wasm_instance = UndefinedValue());
6363

6464
unsafe {
6565
assert!(JS_GetProperty(
66-
*rt.cx(),
66+
**rt.cx(),
6767
global.handle(),
6868
c"WebAssembly".as_ptr(),
6969
wasm.handle_mut()
7070
));
71-
rooted!(in(*rt.cx()) let mut wasm_obj = wasm.to_object());
71+
rooted!(in(**rt.cx()) let mut wasm_obj = wasm.to_object());
7272
assert!(JS_GetProperty(
73-
*rt.cx(),
73+
**rt.cx(),
7474
wasm_obj.handle(),
7575
c"Module".as_ptr(),
7676
wasm_module.handle_mut()
7777
));
7878
assert!(JS_GetProperty(
79-
*rt.cx(),
79+
**rt.cx(),
8080
wasm_obj.handle(),
8181
c"Instance".as_ptr(),
8282
wasm_instance.handle_mut()
@@ -86,85 +86,85 @@ fn run(mut rt: Runtime) {
8686
assert!(HI_WASM.0.as_ptr() as usize % 8 == 0);
8787

8888
// Construct Wasm module from bytes.
89-
rooted!(in(*rt.cx()) let mut module = null_mut::<JSObject>());
89+
rooted!(in(**rt.cx()) let mut module = null_mut::<JSObject>());
9090
{
9191
let array_buffer = JS::NewArrayBufferWithUserOwnedContents(
92-
*rt.cx(),
92+
**rt.cx(),
9393
HI_WASM.0.len(),
9494
HI_WASM.0.as_ptr() as _,
9595
);
9696
assert!(!array_buffer.is_null());
9797

98-
rooted!(in(*rt.cx()) let val = ObjectValue(array_buffer));
98+
rooted!(in(**rt.cx()) let val = ObjectValue(array_buffer));
9999
let args = HandleValueArray::from(val.handle().into_handle());
100100

101101
assert!(Construct1(
102-
*rt.cx(),
102+
**rt.cx(),
103103
wasm_module.handle(),
104104
&args,
105105
module.handle_mut()
106106
))
107107
}
108108

109109
// Construct Wasm module instance with required imports.
110-
rooted!(in(*rt.cx()) let mut instance = null_mut::<JSObject>());
110+
rooted!(in(**rt.cx()) let mut instance = null_mut::<JSObject>());
111111
{
112112
// Build "env" imports object.
113-
rooted!(in(*rt.cx()) let mut env_import_obj = JS_NewPlainObject(*rt.cx()));
113+
rooted!(in(**rt.cx()) let mut env_import_obj = JS_NewPlainObject(**rt.cx()));
114114
assert!(!env_import_obj.is_null());
115115
let function = JS_DefineFunction(
116-
*rt.cx(),
116+
**rt.cx(),
117117
env_import_obj.handle().into(),
118118
c"bar".as_ptr(),
119119
Some(bar),
120120
1,
121121
0,
122122
);
123123
assert!(!function.is_null());
124-
rooted!(in(*rt.cx()) let mut env_import = ObjectValue(env_import_obj.get()));
124+
rooted!(in(**rt.cx()) let mut env_import = ObjectValue(env_import_obj.get()));
125125
// Build imports bag.
126-
rooted!(in(*rt.cx()) let mut imports = JS_NewPlainObject(*rt.cx()));
126+
rooted!(in(**rt.cx()) let mut imports = JS_NewPlainObject(**rt.cx()));
127127
assert!(!imports.is_null());
128128
assert!(JS_SetProperty(
129-
*rt.cx(),
129+
**rt.cx(),
130130
imports.handle(),
131131
c"env".as_ptr(),
132132
env_import.handle()
133133
));
134134

135-
rooted!(in(*rt.cx()) let mut args = ValueArray::new([ObjectValue(module.get()), ObjectValue(imports.get())]));
135+
rooted!(in(**rt.cx()) let mut args = ValueArray::new([ObjectValue(module.get()), ObjectValue(imports.get())]));
136136

137137
assert!(Construct1(
138-
*rt.cx(),
138+
**rt.cx(),
139139
wasm_instance.handle(),
140140
&HandleValueArray::from(&args),
141141
instance.handle_mut()
142142
));
143143
}
144144

145145
// Find `foo` method in exports.
146-
rooted!(in(*rt.cx()) let mut exports = UndefinedValue());
146+
rooted!(in(**rt.cx()) let mut exports = UndefinedValue());
147147

148148
assert!(JS_GetProperty(
149-
*rt.cx(),
149+
**rt.cx(),
150150
instance.handle(),
151151
c"exports".as_ptr(),
152152
exports.handle_mut()
153153
));
154154

155-
rooted!(in(*rt.cx()) let mut exports_obj = exports.to_object());
156-
rooted!(in(*rt.cx()) let mut foo = UndefinedValue());
155+
rooted!(in(**rt.cx()) let mut exports_obj = exports.to_object());
156+
rooted!(in(**rt.cx()) let mut foo = UndefinedValue());
157157
assert!(JS_GetProperty(
158-
*rt.cx(),
158+
**rt.cx(),
159159
exports_obj.handle(),
160160
c"foo".as_ptr(),
161161
foo.handle_mut()
162162
));
163163

164164
// call foo and get its result
165-
rooted!(in(*rt.cx()) let mut rval = UndefinedValue());
165+
rooted!(in(**rt.cx()) let mut rval = UndefinedValue());
166166
assert!(Call(
167-
*rt.cx(),
167+
**rt.cx(),
168168
JS::UndefinedHandleValue,
169169
foo.handle().into(),
170170
&HandleValueArray::empty(),

mozjs/src/context.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,27 +85,20 @@ pub use crate::jsapi::JSContext as RawJSContext;
8585
/// ### WIP
8686
///
8787
/// This model is still being incrementally introduced, so there are currently some escape hatches.
88-
#[derive(Copy, Clone)]
89-
pub struct JSContext<'rt> {
88+
pub struct JSContext {
9089
pub(crate) ptr: NonNull<RawJSContext>,
91-
pub(crate) runtime_anchor: PhantomData<&'rt ()>,
9290
}
9391

94-
impl<'rt> JSContext<'rt> {
92+
impl JSContext {
9593
/// Wrap an existing [RawJSContext] pointer.
9694
///
9795
/// SAFETY:
9896
/// - `cx` must be valid [RawJSContext] object.
99-
/// - the resulting lifetime `'rt` must not exceed the actual lifetime of the
100-
/// associated [Runtime].
101-
/// - only one [JSContext] can be alive.
97+
/// - only one [JSContext] can be alive and it should not outlive [Runtime].
10298
/// This in turn means that [JSContext] always needs to be passed down as an argument,
10399
/// but for the SpiderMonkey callbacks which provide [RawJSContext] it's safe to construct **one** from provided [RawJSContext].
104-
pub unsafe fn from_ptr(cx: NonNull<RawJSContext>) -> JSContext<'rt> {
105-
JSContext {
106-
ptr: cx,
107-
runtime_anchor: PhantomData,
108-
}
100+
pub unsafe fn from_ptr(cx: NonNull<RawJSContext>) -> JSContext {
101+
JSContext { ptr: cx }
109102
}
110103

111104
/// Returns [NoGC] token bounded to this [JSContext].
@@ -132,11 +125,33 @@ impl<'rt> JSContext<'rt> {
132125
/// fn SM_function_that_can_trigger_gc(_cx: *mut RawJSContext) {}
133126
///
134127
/// fn can_trigger_gc(cx: &mut JSContext) {
135-
/// unsafe { SM_function_that_can_trigger_gc(cx.raw()) } // returned pointer is immediately used
128+
/// unsafe { SM_function_that_can_trigger_gc(cx.raw_cx()) } // returned pointer is immediately used
136129
/// cx.no_gc(); // this is ok because no outstanding raw pointer is alive
137130
/// }
138131
/// ```
139-
pub unsafe fn raw(&mut self) -> *mut RawJSContext {
132+
pub unsafe fn raw_cx(&mut self) -> *mut RawJSContext {
133+
self.ptr.as_ptr()
134+
}
135+
136+
/// Obtain [RawJSContext] mutable pointer, that will not be used for GC.
137+
///
138+
/// # Safety
139+
///
140+
/// No &mut calls should be done on [JSContext] while returned pointer is available.
141+
/// In practices this means that one should use the result
142+
/// as direct argument to SpiderMonkey function and not store it in variable.
143+
///
144+
/// ```rust
145+
/// use mozjs::context::*;
146+
/// use mozjs::jsapi::JSContext as RawJSContext;
147+
///
148+
/// fn SM_function_that_cannot_trigger_gc(_cx: *mut RawJSContext) {}
149+
///
150+
/// fn f(cx: &mut JSContext) {
151+
/// unsafe { SM_function_that_cannot_trigger_gc(cx.raw_cx_no_gc()) } // returned pointer is immediately used
152+
/// }
153+
/// ```
154+
pub unsafe fn raw_cx_no_gc(&self) -> *mut RawJSContext {
140155
self.ptr.as_ptr()
141156
}
142157
}
@@ -149,13 +164,13 @@ impl<'rt> JSContext<'rt> {
149164
/// For more info and examples see [JSContext].
150165
pub struct NoGC<'cx>(PhantomData<&'cx ()>);
151166

152-
impl<'rt> Deref for JSContext<'rt> {
167+
impl Deref for JSContext {
153168
type Target = *mut RawJSContext;
154169

155170
/// This exists to make migration to [JSContext] easier,
156171
/// but it will be eventually removed as it is **unsafe**.
157172
///
158-
/// Use [JSContext::raw] instead.
173+
/// Use [JSContext::raw_cx] instead.
159174
fn deref(&'_ self) -> &'_ Self::Target {
160175
unsafe { std::mem::transmute::<&NonNull<RawJSContext>, &*mut RawJSContext>(&self.ptr) }
161176
}

mozjs/src/rust.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ unsafe impl Send for ParentRuntime {}
283283

284284
/// A wrapper for the `JSContext` structure in SpiderMonkey.
285285
pub struct Runtime {
286-
/// Raw pointer to the underlying SpiderMonkey context.
287-
cx: NonNull<JSContext>,
286+
/// Safe SpiderMonkey context.
287+
cx: crate::context::JSContext,
288288
/// The engine that this runtime is associated with.
289289
engine: JSEngineHandle,
290290
/// If this Runtime was created with a parent, this member exists to ensure
@@ -389,24 +389,30 @@ impl Runtime {
389389
Runtime {
390390
engine,
391391
_parent_child_count: parent.map(|p| p.children_of_parent),
392-
cx: js_context,
392+
cx: crate::context::JSContext::from_ptr(js_context),
393393
outstanding_children: Arc::new(()),
394394
thread_safe_handle: Arc::new(RwLock::new(Some(js_context))),
395395
}
396396
}
397397

398398
/// Returns the `JSRuntime` object.
399399
pub fn rt(&self) -> *mut JSRuntime {
400-
unsafe { JS_GetRuntime(self.cx.as_ptr()) }
400+
// SAFETY: JS_GetRuntime does not trigger GC
401+
unsafe { JS_GetRuntime(self.cx.raw_cx_no_gc()) }
401402
}
402403

403404
/// Returns the `JSContext` object.
404-
pub fn cx<'rt>(&'rt mut self) -> crate::context::JSContext<'rt> {
405-
unsafe { crate::context::JSContext::from_ptr(self.cx) }
405+
pub fn cx<'rt>(&'rt mut self) -> &'rt mut crate::context::JSContext {
406+
&mut self.cx
407+
}
408+
409+
/// Returns the `JSContext` object.
410+
pub fn cx_no_gc<'rt>(&'rt self) -> &'rt crate::context::JSContext {
411+
&self.cx
406412
}
407413

408414
pub fn evaluate_script(
409-
&self,
415+
&mut self,
410416
glob: HandleObject,
411417
script: &str,
412418
rval: MutableHandleValue,
@@ -418,11 +424,11 @@ impl Runtime {
418424
script
419425
);
420426

421-
let _ac = JSAutoRealm::new(self.cx.as_ptr(), glob.get());
427+
let _ac = JSAutoRealm::new(unsafe { self.cx().raw_cx() }, glob.get());
422428

423429
unsafe {
424430
let mut source = transform_str_to_source_text(&script);
425-
if !Evaluate2(self.cx.as_ptr(), options.ptr, &mut source, rval.into()) {
431+
if !Evaluate2(self.cx().raw_cx(), options.ptr, &mut source, rval.into()) {
426432
debug!("...err!");
427433
maybe_resume_unwind();
428434
Err(())
@@ -435,9 +441,9 @@ impl Runtime {
435441
}
436442
}
437443

438-
pub fn new_compile_options(&self, filename: &str, line: u32) -> CompileOptionsWrapper {
444+
pub fn new_compile_options(&mut self, filename: &str, line: u32) -> CompileOptionsWrapper {
439445
// SAFETY: `cx` argument points to a non-null, valid JSContext
440-
unsafe { CompileOptionsWrapper::new(self.cx.as_ptr(), filename, line) }
446+
unsafe { CompileOptionsWrapper::new(self.cx().raw_cx(), filename, line) }
441447
}
442448
}
443449

@@ -449,7 +455,7 @@ impl Drop for Runtime {
449455
"This runtime still has live children."
450456
);
451457
unsafe {
452-
JS_DestroyContext(self.cx.as_ptr());
458+
JS_DestroyContext(self.cx.raw_cx());
453459

454460
CONTEXT.with(|context| {
455461
assert!(context.take().is_some());

mozjs/tests/callback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use mozjs::rust::{JSEngine, RealmOptions, Runtime, SIMPLE_GLOBAL_CLASS};
1717
fn callback() {
1818
let engine = JSEngine::init().unwrap();
1919
let mut runtime = Runtime::new(engine.handle());
20-
let context = *runtime.cx();
20+
let context = **runtime.cx();
2121
#[cfg(feature = "debugmozjs")]
2222
unsafe {
2323
mozjs::jsapi::SetGCZeal(context, 2, 1);

mozjs/tests/capture_stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn capture_stack() {
3333

3434
let engine = JSEngine::init().unwrap();
3535
let mut runtime = Runtime::new(engine.handle());
36-
let context = *runtime.cx();
36+
let context = **runtime.cx();
3737
#[cfg(feature = "debugmozjs")]
3838
unsafe {
3939
mozjs::jsapi::SetGCZeal(context, 2, 1);

mozjs/tests/custom_auto_rooter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ unsafe impl CustomTrace for TraceCheck {
3232
fn virtual_trace_called() {
3333
let engine = JSEngine::init().unwrap();
3434
let mut runtime = Runtime::new(engine.handle());
35-
let context = *runtime.cx();
35+
let context = **runtime.cx();
3636

3737
let mut rooter = CustomAutoRooter::new(TraceCheck::new());
3838
let guard = rooter.root(context);

mozjs/tests/custom_auto_rooter_macro.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ unsafe impl CustomTrace for TraceCheck {
3030
fn custom_auto_rooter_macro() {
3131
let engine = JSEngine::init().unwrap();
3232
let mut runtime = Runtime::new(engine.handle());
33-
let context = *runtime.cx();
33+
let context = **runtime.cx();
3434

3535
auto_root!(in(context) let vec = vec![TraceCheck::new(), TraceCheck::new()]);
3636

0 commit comments

Comments
 (0)