aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/error.rs
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2023-01-12 17:10:34 +0100
committerMartin Robinson <mrobinson@igalia.com>2023-01-12 19:57:51 +0100
commite68ebd26179e4fcecab973a973c49fc8642937a3 (patch)
tree3a32c3f3c566679455803f9677402f28c4f781fc /components/script/dom/bindings/error.rs
parent633f14df119b021a108d379cdcce058383e372e6 (diff)
downloadservo-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.rs68
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 {}:{}:{} {}",