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
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.8-3"
version = "0.140.8-4"
authors = ["Mozilla", "The Servo Project Developers"]
links = "mozjs"
license.workspace = true
Expand Down
38 changes: 38 additions & 0 deletions mozjs-sys/src/jsglue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,44 @@ bool ShouldMeasureObject(JSObject* obj, nsISupports** iface) {
return false;
}

bool PendingExceptionStackInfo(JSContext* cx, char* message_buffer,
size_t* message_len, char* filename_buffer,
size_t* filename_len, uint32_t* line,
uint32_t* col, JS::MutableHandleValue dest) {
JS::ExceptionStack stack(cx);
JS::ErrorReportBuilder builder(cx);
if (JS::StealPendingExceptionStack(cx, &stack) &&
builder.init(cx, stack, JS::ErrorReportBuilder::WithSideEffects)) {
JSErrorReport* aReport = builder.report();

if (!aReport || aReport->isWarning()) {
return false;
}

const char* message = aReport->message().c_str();
const char* filename = aReport->filename.c_str();

if (!message) {
message = builder.toStringResult().c_str();
}
*message_len = std::min<size_t>(1024, strlen(message));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might reasonable strategy for filename, but not for message. Also we are doing two copies, one to message_buffer and one with to_string. Maybe we should impl this with callbacks, that receive len and char* and create rust string from it.

We might also skip utf8 validation if I understand https://searchfox.org/firefox-main/source/js/public/CharacterEncoding.h#135 correctly.

Copy link
Copy Markdown
Contributor Author

@Gae24 Gae24 Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry could you expand on it? Is the issue that the selected length could be insufficient?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and the fact that implementation is not optimal we copy it twice, firstly into rust array then into rust String.

strncpy(message_buffer, message, *message_len);

if (filename) {
*filename_len = std::min<size_t>(1024, strlen(filename));
strncpy(filename_buffer, filename, *filename_len);
}

*line = aReport->lineno;
*col = aReport->column.oneOriginValue();
dest.set(stack.exception());

return true;
}

return false;
}

extern "C" {

JSPrincipals* CreateRustJSPrincipals(const JSPrincipalsCallbacks& callbacks,
Expand Down
4 changes: 2 additions & 2 deletions mozjs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "mozjs"
description = "Rust bindings to the Mozilla SpiderMonkey JavaScript engine."
repository.workspace = true
version = "0.15.8"
version = "0.15.9"
authors = ["The Servo Project Developers"]
license.workspace = true
edition.workspace = true
Expand All @@ -27,7 +27,7 @@ encoding_rs = "0.8.35"
libc.workspace = true
log = "0.4"
# When doing non-version changes also update ../mozjs-sys/etc/sm-security-bump.py
mozjs_sys = { version = "=0.140.8-3", path = "../mozjs-sys" }
mozjs_sys = { version = "=0.140.8-4", path = "../mozjs-sys" }
num-traits = "0.2"

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
Expand Down
1 change: 1 addition & 0 deletions mozjs/src/glue2_wrappers.in.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
wrap!(glue: pub fn RegisterScriptEnvironmentPreparer(cx: &mut JSContext, hook: InvokeScriptPreparerHook));
wrap!(glue: pub fn RunScriptEnvironmentPreparerClosure(cx: &mut JSContext, closure: *mut ScriptEnvironmentPreparer_Closure) -> bool);
wrap!(glue: pub fn PendingExceptionStackInfo(cx: &mut JSContext, message_buffer: *mut ::std::os::raw::c_char, message_len: *mut usize, filename_buffer: *mut ::std::os::raw::c_char, filename_len: *mut usize, line: *mut u32, col: *mut u32, dest: MutableHandleValue) -> bool);
wrap!(glue: pub fn InvokeGetOwnPropertyDescriptor(handler: *const ::std::os::raw::c_void, cx: &mut JSContext, proxy: HandleObject, id: HandleId, desc: MutableHandle<PropertyDescriptor>, isNone: *mut bool) -> bool);
wrap!(glue: pub fn InvokeHasOwn(handler: *const ::std::os::raw::c_void, cx: &mut JSContext, proxy: HandleObject, id: HandleId, bp: *mut bool) -> bool);
wrap!(glue: pub fn CallJitGetterOp(info: *const JSJitInfo, cx: &mut JSContext, thisObj: HandleObject, specializedThis: *mut ::std::os::raw::c_void, argc: ::std::os::raw::c_uint, vp: *mut Value) -> bool);
Expand Down
1 change: 1 addition & 0 deletions mozjs/src/glue_wrappers.in.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
wrap!(glue: pub fn PendingExceptionStackInfo(cx: *mut JSContext, message_buffer: *mut ::std::os::raw::c_char, message_len: *mut usize, filename_buffer: *mut ::std::os::raw::c_char, filename_len: *mut usize, line: *mut u32, col: *mut u32, dest: MutableHandleValue) -> bool);
wrap!(glue: pub fn InvokeGetOwnPropertyDescriptor(handler: *const ::std::os::raw::c_void, cx: *mut JSContext, proxy: HandleObject, id: HandleId, desc: MutableHandle<PropertyDescriptor>, isNone: *mut bool) -> bool);
wrap!(glue: pub fn InvokeHasOwn(handler: *const ::std::os::raw::c_void, cx: *mut JSContext, proxy: HandleObject, id: HandleId, bp: *mut bool) -> bool);
wrap!(glue: pub fn CallJitGetterOp(info: *const JSJitInfo, cx: *mut JSContext, thisObj: HandleObject, specializedThis: *mut ::std::os::raw::c_void, argc: ::std::os::raw::c_uint, vp: *mut Value) -> bool);
Expand Down
48 changes: 48 additions & 0 deletions mozjs/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::glue::AppendToRootedObjectVector;
use crate::glue::{CreateRootedIdVector, CreateRootedObjectVector};
use crate::glue::{
DeleteCompileOptions, DeleteRootedObjectVector, DescribeScriptedCaller, DestroyRootedIdVector,
PendingExceptionStackInfo,
};
use crate::glue::{DeleteJSAutoStructuredCloneBuffer, NewJSAutoStructuredCloneBuffer};
use crate::glue::{
Expand All @@ -45,6 +46,7 @@ use crate::jsapi::HandleObjectVector as RawHandleObjectVector;
use crate::jsapi::HandleValue as RawHandleValue;
use crate::jsapi::JS_AddExtraGCRootsTracer;
use crate::jsapi::MutableHandleIdVector as RawMutableHandleIdVector;
use crate::jsapi::MutableHandleValue as RawMutableHandleValue;
use crate::jsapi::{already_AddRefed, jsid};
use crate::jsapi::{BuildStackString, CaptureCurrentStack, StackFormat};
use crate::jsapi::{HandleValueArray, StencilRelease};
Expand Down Expand Up @@ -1056,6 +1058,52 @@ pub unsafe fn describe_scripted_caller(cx: *mut JSContext) -> Result<ScriptedCal
})
}

pub struct ErrorInfo {
pub message: String,
pub filename: String,
pub line: u32,
pub col: u32,
}

/// Retrieve error info from the pending exception stack, by clearing it.
/// Return None if there isn't one or if it is a warning.
pub unsafe fn error_info_from_exception_stack(
cx: *mut JSContext,
rval: RawMutableHandleValue,
) -> Option<ErrorInfo> {
let mut message_buf = [0; 1024];
let mut message_len = 0;

let mut filename_buf = [0; 1024];
let mut filename_len = 0;

let mut line = 0;
let mut col = 0;

if !PendingExceptionStackInfo(
cx,
message_buf.as_mut_ptr() as *mut std::ffi::c_char,
&mut message_len,
filename_buf.as_mut_ptr() as *mut std::ffi::c_char,
&mut filename_len,
&mut line,
&mut col,
rval,
) {
return None;
}

let message = str::from_utf8(&message_buf[..message_len]).ok()?;
let filename = str::from_utf8(&filename_buf[..filename_len]).ok()?;

Some(ErrorInfo {
message: message.to_string(),
filename: filename.to_string(),
line,
col,
})
}

pub struct CapturedJSStack<'a> {
cx: *mut JSContext,
stack: RootedGuard<'a, *mut JSObject>,
Expand Down
Loading