diff options
author | Martin Robinson <mrobinson@igalia.com> | 2023-01-12 17:10:34 +0100 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-01-12 19:57:51 +0100 |
commit | e68ebd26179e4fcecab973a973c49fc8642937a3 (patch) | |
tree | 3a32c3f3c566679455803f9677402f28c4f781fc /components/script/dom/bindings/error.rs | |
parent | 633f14df119b021a108d379cdcce058383e372e6 (diff) | |
download | servo-e68ebd26179e4fcecab973a973c49fc8642937a3.tar.gz servo-e68ebd26179e4fcecab973a973c49fc8642937a3.zip |
Stringify unknown JavaScript objects in global exception handlers
When turning DOM exceptions into `ErrorInfo` always try to stringify
the JavaScript value, even if it's an object that isn't a `DOMException`
or native exception. This means that exceptions that extend the `Error`
prototype are now stringified. The result is that test output for WPT
global assertion failures is more useful. For instance for the test
include-frames-from-child-same-origin-grandchild.sub.html:
Before:
```
uncaught exception: unknown (can't convert to string)
```
After:
```
uncaught exception: Error: assert_equals: expected 4 but got 3
```
Diffstat (limited to 'components/script/dom/bindings/error.rs')
-rw-r--r-- | components/script/dom/bindings/error.rs | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs index 79cc8fbd869..9356918ccc1 100644 --- a/components/script/dom/bindings/error.rs +++ b/components/script/dom/bindings/error.rs @@ -29,8 +29,7 @@ use js::jsval::UndefinedValue; use js::rust::wrappers::JS_ErrorFromException; use js::rust::wrappers::JS_GetPendingException; use js::rust::wrappers::JS_SetPendingException; -use js::rust::HandleObject; -use js::rust::MutableHandleValue; +use js::rust::{HandleObject, HandleValue, MutableHandleValue}; use libc::c_uint; use std::slice::from_raw_parts; @@ -181,7 +180,7 @@ pub struct ErrorInfo { } impl ErrorInfo { - unsafe fn from_native_error(cx: *mut JSContext, object: HandleObject) -> Option<ErrorInfo> { + unsafe fn from_native_error(object: HandleObject, cx: *mut JSContext) -> Option<ErrorInfo> { let report = JS_ErrorFromException(cx, object); if report.is_null() { return None; @@ -209,10 +208,10 @@ impl ErrorInfo { }; Some(ErrorInfo { - filename: filename, - message: message, - lineno: lineno, - column: column, + filename, + message, + lineno, + column, }) } @@ -229,6 +228,37 @@ impl ErrorInfo { column: 0, }) } + + unsafe fn from_object(object: HandleObject, cx: *mut JSContext) -> Option<ErrorInfo> { + if let Some(info) = ErrorInfo::from_native_error(object, cx) { + return Some(info); + } + if let Some(info) = ErrorInfo::from_dom_exception(object, cx) { + return Some(info); + } + return None; + } + + unsafe fn from_value(value: HandleValue, cx: *mut JSContext) -> ErrorInfo { + if value.is_object() { + rooted!(in(cx) let object = value.to_object()); + if let Some(info) = ErrorInfo::from_object(object.handle(), cx) { + return info; + } + } + + match USVString::from_jsval(cx, value, ()) { + Ok(ConversionResult::Success(USVString(string))) => ErrorInfo { + message: format!("uncaught exception: {}", string), + filename: String::new(), + lineno: 0, + column: 0, + }, + _ => { + panic!("uncaught exception: failed to stringify primitive"); + }, + } + } } /// Report a pending exception, thereby clearing it. @@ -248,29 +278,7 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool, } JS_ClearPendingException(cx); - let error_info = if value.is_object() { - rooted!(in(cx) let object = value.to_object()); - ErrorInfo::from_native_error(cx, object.handle()) - .or_else(|| ErrorInfo::from_dom_exception(object.handle(), cx)) - .unwrap_or_else(|| ErrorInfo { - message: format!("uncaught exception: unknown (can't convert to string)"), - filename: String::new(), - lineno: 0, - column: 0, - }) - } else { - match USVString::from_jsval(cx, value.handle(), ()) { - Ok(ConversionResult::Success(USVString(string))) => ErrorInfo { - message: format!("uncaught exception: {}", string), - filename: String::new(), - lineno: 0, - column: 0, - }, - _ => { - panic!("Uncaught exception: failed to stringify primitive"); - }, - } - }; + let error_info = ErrorInfo::from_value(value.handle(), cx); error!( "Error at {}:{}:{} {}", |