Skip to content
Open
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
4 changes: 3 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v6
with:
python-version: '3.13'
python-version: "3.13"
- name: Install deps
run: |
brew install llvm yasm
Expand Down Expand Up @@ -90,9 +90,11 @@ jobs:
- name: Run sccache-cache
uses: mozilla-actions/[email protected]
- name: Build
# doc tests on mozjs_sys fail because they include stuff from SpiderMonkey
run: |
cargo +${{ steps.toolchain.outputs.name }} build --verbose --features ${{ matrix.features }}
cargo +${{ steps.toolchain.outputs.name }} test --tests --examples --verbose --features ${{ matrix.features }}
cargo +${{ steps.toolchain.outputs.name }} test --doc -p mozjs --verbose --features ${{ matrix.features }}
- name: Check wrappers integrity
# we generate wrappers only without debugmozjs
if: ${{ matrix.features != 'debugmozjs' }}
Expand Down
22 changes: 12 additions & 10 deletions mozjs/benches/latin1_string_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ use criterion::measurement::WallTime;
use criterion::{
criterion_group, criterion_main, BenchmarkGroup, BenchmarkId, Criterion, Throughput,
};
use mozjs::context::JSContext;
use mozjs::conversions::jsstr_to_string;
use mozjs::glue::{CreateJSExternalStringCallbacks, JSExternalStringCallbacksTraps};
use mozjs::jsapi::{
JSAutoRealm, JS_NewExternalStringLatin1, JS_NewGlobalObject, OnNewGlobalHookOption,
};
use mozjs::jsapi::{JSAutoRealm, OnNewGlobalHookOption};
use mozjs::rooted;
use mozjs::rust::wrappers2::{JS_NewExternalStringLatin1, JS_NewGlobalObject};
use mozjs::rust::{JSEngine, RealmOptions, Runtime, SIMPLE_GLOBAL_CLASS};
use mozjs_sys::jsapi::JSContext;
use std::ffi::c_void;
use std::ptr::NonNull;
use std::{iter, ptr};

// TODO: Create a trait for creating a latin1 string of a required length, so that we can
// try different kinds of content.
fn bench_str_repetition(
group: &mut BenchmarkGroup<WallTime>,
context: *mut JSContext,
context: &mut JSContext,
variant_name: &str,
latin1str_16_bytes: &[u8],
) {
Expand All @@ -39,7 +39,7 @@ fn bench_str_repetition(
str_len as *mut c_void,
)
};
rooted!(in(context) let latin1_jsstr = unsafe { JS_NewExternalStringLatin1(
rooted!(&in(context) let latin1_jsstr = unsafe { JS_NewExternalStringLatin1(
context,
latin1_chars,
str_len,
Expand All @@ -51,26 +51,28 @@ fn bench_str_repetition(
&latin1_jsstr,
|b, js_str| {
b.iter(|| {
unsafe { jsstr_to_string(context, js_str.get()) };
unsafe {
jsstr_to_string(context.raw_cx(), NonNull::new(js_str.get()).unwrap())
};
})
},
);
}
}
fn external_string(c: &mut Criterion) {
let engine = JSEngine::init().unwrap();
let runtime = Runtime::new(engine.handle());
let mut runtime = Runtime::new(engine.handle());
let context = runtime.cx();
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = RealmOptions::default();
rooted!(in(context) let global = unsafe { JS_NewGlobalObject(
rooted!(&in(context) let global = unsafe { JS_NewGlobalObject(
context,
&SIMPLE_GLOBAL_CLASS,
ptr::null_mut(),
h_option,
&*c_option,
)});
let _ac = JSAutoRealm::new(context, global.get());
let _ac = JSAutoRealm::new(unsafe { context.raw_cx() }, global.get());

let mut group = c.benchmark_group("Latin1 conversion");

Expand Down
10 changes: 5 additions & 5 deletions mozjs/examples/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@

use ::std::ptr;

use mozjs::jsapi::*;
use mozjs::jsapi::OnNewGlobalHookOption;
use mozjs::jsval::UndefinedValue;
use mozjs::rooted;
use mozjs::rust::wrappers2::*;
use mozjs::rust::SIMPLE_GLOBAL_CLASS;
use mozjs::rust::{JSEngine, RealmOptions, Runtime};

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

/*
* Some example source in a string. This is equivalent to JS_EvaluateScript in C++.
Expand All @@ -57,7 +58,6 @@ fn run(rt: Runtime) {
fn main() {
let engine = JSEngine::init().expect("failed to initalize JS engine");
let runtime = Runtime::new(engine.handle());
assert!(!runtime.cx().is_null(), "failed to create JSContext");
run(runtime);
}

Expand Down
6 changes: 3 additions & 3 deletions mozjs/examples/minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ::std::ptr;

use mozjs::rooted;
use mozjs::rust::wrappers2::JS_NewGlobalObject;
use mozjs::rust::SIMPLE_GLOBAL_CLASS;
use mozjs::{jsapi::*, rust::JSEngine, rust::RealmOptions, rust::Runtime};

Expand All @@ -25,22 +26,21 @@ fn main() {

// Create a Runtime -- wraps a JSContext in the C++ API.
let runtime = Runtime::new(engine.handle());
assert!(!runtime.cx().is_null(), "failed to create JSContext");

run(runtime);

// There is no need for the shut down block in the C++, because rust destructors and Arc
// reference counts will clean up everything.
}

fn run(rt: Runtime) {
fn run(mut rt: Runtime) {
let cx = rt.cx();
// In addition to what the C++ interface requires, define a global scope for the code.
//
// This demonstrates the way Rust uses the C++ garbage collector: using the rooted! macro to
// indicate when the GC can collect them.
let options = RealmOptions::default();
rooted!(in(cx) let _global = unsafe {
rooted!(&in(cx) let _global = unsafe {
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
OnNewGlobalHookOption::FireOnNewGlobalHook,
&*options)
Expand Down
76 changes: 38 additions & 38 deletions mozjs/examples/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ use mozjs::jsapi::*;
use mozjs::jsval::ObjectValue;
use mozjs::jsval::UndefinedValue;
use mozjs::rooted;
use mozjs::rust::wrappers::{Construct1, JS_GetProperty, JS_SetProperty};
use mozjs::rust::wrappers2::{
Call, Construct1, JS_DefineFunction, JS_GetProperty, JS_NewGlobalObject, JS_NewPlainObject,
JS_SetProperty, NewArrayBufferWithUserOwnedContents,
};
use mozjs::rust::SIMPLE_GLOBAL_CLASS;
use mozjs::rust::{IntoHandle, JSEngine, RealmOptions, Runtime};
use mozjs::rust::{HandleValue, IntoHandle, JSEngine, RealmOptions, Runtime};
use mozjs_sys::jsgc::ValueArray;

#[repr(align(8))]
Expand Down Expand Up @@ -47,36 +50,37 @@ unsafe extern "C" fn bar(_cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool
true
}

fn run(rt: Runtime) {
fn run(mut rt: Runtime) {
let options = RealmOptions::default();
rooted!(in(rt.cx()) let global = unsafe {
JS_NewGlobalObject(rt.cx(), &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
let cx = rt.cx();
rooted!(&in(cx) let global = unsafe {
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
OnNewGlobalHookOption::FireOnNewGlobalHook,
&*options)
});
let _ac = JSAutoRealm::new(rt.cx(), global.get());
let _ac = JSAutoRealm::new(unsafe { cx.raw_cx() }, global.get());

// Get WebAssembly.Module and WebAssembly.Instance constructors.
rooted!(in(rt.cx()) let mut wasm = UndefinedValue());
rooted!(in(rt.cx()) let mut wasm_module = UndefinedValue());
rooted!(in(rt.cx()) let mut wasm_instance = UndefinedValue());
rooted!(&in(cx) let mut wasm = UndefinedValue());
rooted!(&in(cx) let mut wasm_module = UndefinedValue());
rooted!(&in(cx) let mut wasm_instance = UndefinedValue());

unsafe {
assert!(JS_GetProperty(
rt.cx(),
cx,
global.handle(),
c"WebAssembly".as_ptr(),
wasm.handle_mut()
));
rooted!(in(rt.cx()) let mut wasm_obj = wasm.to_object());
rooted!(&in(cx) let mut wasm_obj = wasm.to_object());
assert!(JS_GetProperty(
rt.cx(),
cx,
wasm_obj.handle(),
c"Module".as_ptr(),
wasm_module.handle_mut()
));
assert!(JS_GetProperty(
rt.cx(),
cx,
wasm_obj.handle(),
c"Instance".as_ptr(),
wasm_instance.handle_mut()
Expand All @@ -86,86 +90,83 @@ fn run(rt: Runtime) {
assert!(HI_WASM.0.as_ptr() as usize % 8 == 0);

// Construct Wasm module from bytes.
rooted!(in(rt.cx()) let mut module = null_mut::<JSObject>());
rooted!(&in(cx) let mut module = null_mut::<JSObject>());
{
let array_buffer = JS::NewArrayBufferWithUserOwnedContents(
rt.cx(),
HI_WASM.0.len(),
HI_WASM.0.as_ptr() as _,
);
let array_buffer =
NewArrayBufferWithUserOwnedContents(cx, HI_WASM.0.len(), HI_WASM.0.as_ptr() as _);
assert!(!array_buffer.is_null());

rooted!(in(rt.cx()) let val = ObjectValue(array_buffer));
rooted!(&in(cx) let val = ObjectValue(array_buffer));
let args = HandleValueArray::from(val.handle().into_handle());

assert!(Construct1(
rt.cx(),
cx,
wasm_module.handle(),
&args,
module.handle_mut()
))
}

// Construct Wasm module instance with required imports.
rooted!(in(rt.cx()) let mut instance = null_mut::<JSObject>());
rooted!(&in(cx) let mut instance = null_mut::<JSObject>());
{
// Build "env" imports object.
rooted!(in(rt.cx()) let mut env_import_obj = JS_NewPlainObject(rt.cx()));
rooted!(&in(cx) let mut env_import_obj = JS_NewPlainObject(cx));
assert!(!env_import_obj.is_null());
let function = JS_DefineFunction(
rt.cx(),
cx,
env_import_obj.handle().into(),
c"bar".as_ptr(),
Some(bar),
1,
0,
);
assert!(!function.is_null());
rooted!(in(rt.cx()) let mut env_import = ObjectValue(env_import_obj.get()));
rooted!(&in(cx) let mut env_import = ObjectValue(env_import_obj.get()));
// Build imports bag.
rooted!(in(rt.cx()) let mut imports = JS_NewPlainObject(rt.cx()));
rooted!(&in(cx) let mut imports = JS_NewPlainObject(cx));
assert!(!imports.is_null());
assert!(JS_SetProperty(
rt.cx(),
cx,
imports.handle(),
c"env".as_ptr(),
env_import.handle()
));

rooted!(in(rt.cx()) let mut args = ValueArray::new([ObjectValue(module.get()), ObjectValue(imports.get())]));
rooted!(&in(cx) let mut args = ValueArray::new([ObjectValue(module.get()), ObjectValue(imports.get())]));

assert!(Construct1(
rt.cx(),
cx,
wasm_instance.handle(),
&HandleValueArray::from(&args),
instance.handle_mut()
));
}

// Find `foo` method in exports.
rooted!(in(rt.cx()) let mut exports = UndefinedValue());
rooted!(&in(cx) let mut exports = UndefinedValue());

assert!(JS_GetProperty(
rt.cx(),
cx,
instance.handle(),
c"exports".as_ptr(),
exports.handle_mut()
));

rooted!(in(rt.cx()) let mut exports_obj = exports.to_object());
rooted!(in(rt.cx()) let mut foo = UndefinedValue());
rooted!(&in(cx) let mut exports_obj = exports.to_object());
rooted!(&in(cx) let mut foo = UndefinedValue());
assert!(JS_GetProperty(
rt.cx(),
cx,
exports_obj.handle(),
c"foo".as_ptr(),
foo.handle_mut()
));

// call foo and get its result
rooted!(in(rt.cx()) let mut rval = UndefinedValue());
rooted!(&in(cx) let mut rval = UndefinedValue());
assert!(Call(
rt.cx(),
JS::UndefinedHandleValue,
cx,
HandleValue::undefined(),
foo.handle().into(),
&HandleValueArray::empty(),
rval.handle_mut().into()
Expand All @@ -180,7 +181,6 @@ fn run(rt: Runtime) {
fn main() {
let engine = JSEngine::init().expect("failed to initalize JS engine");
let runtime = Runtime::new(engine.handle());
assert!(!runtime.cx().is_null(), "failed to create JSContext");
run(runtime);
}

Expand Down
Loading
Loading