mirror of
https://github.com/servo/servo
synced 2026-05-10 09:02:30 +02:00
Implement WindowOrWorkerGlobalScope::reportError (#40654)
This web API is alternative API to `throw e`, which is why we can reuse a lot of the existing machinery. The one testcase that isn't passing yet is because it reports an empty `TypeError`. The current logic in `ErrorInfo` only retrieves the message data, but doesn't include the type of the exception. For that, we need to use `(*report)._base.errorNumber` and map that back to the original type codes. However, deferring that to a follow-up as that requires some more work in mozjs. Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
This commit is contained in:
committed by
GitHub
parent
10796b8590
commit
8e0c2d5750
@@ -20,7 +20,7 @@ use js::jsapi::{
|
||||
};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::wrappers::{JS_ErrorFromException, JS_GetPendingException, JS_SetPendingException};
|
||||
use js::rust::{HandleObject, HandleValue, MutableHandleValue};
|
||||
use js::rust::{HandleObject, HandleValue, MutableHandleValue, describe_scripted_caller};
|
||||
use libc::c_uint;
|
||||
use script_bindings::conversions::SafeToJSValConvertible;
|
||||
pub(crate) use script_bindings::error::*;
|
||||
@@ -236,11 +236,12 @@ impl ErrorInfo {
|
||||
|
||||
fn from_dom_exception(object: HandleObject, cx: SafeJSContext) -> Option<ErrorInfo> {
|
||||
let exception = unsafe { root_from_object::<DOMException>(object.get(), *cx).ok()? };
|
||||
let scripted_caller = unsafe { describe_scripted_caller(*cx) }.unwrap_or_default();
|
||||
Some(ErrorInfo {
|
||||
filename: "".to_string(),
|
||||
message: exception.stringifier().into(),
|
||||
lineno: 0,
|
||||
column: 0,
|
||||
filename: scripted_caller.filename,
|
||||
lineno: scripted_caller.line,
|
||||
column: scripted_caller.col + 1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -254,6 +255,7 @@ impl ErrorInfo {
|
||||
None
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#extract-error>
|
||||
pub(crate) fn from_value(value: HandleValue, cx: SafeJSContext, can_gc: CanGc) -> ErrorInfo {
|
||||
if value.is_object() {
|
||||
rooted!(in(*cx) let object = value.to_object());
|
||||
@@ -263,11 +265,14 @@ impl ErrorInfo {
|
||||
}
|
||||
|
||||
match USVString::safe_from_jsval(cx, value, (), can_gc) {
|
||||
Ok(ConversionResult::Success(USVString(string))) => ErrorInfo {
|
||||
message: format!("uncaught exception: {}", string),
|
||||
filename: String::new(),
|
||||
lineno: 0,
|
||||
column: 0,
|
||||
Ok(ConversionResult::Success(USVString(string))) => {
|
||||
let scripted_caller = unsafe { describe_scripted_caller(*cx) }.unwrap_or_default();
|
||||
ErrorInfo {
|
||||
message: format!("uncaught exception: {}", string),
|
||||
filename: scripted_caller.filename,
|
||||
lineno: scripted_caller.line,
|
||||
column: scripted_caller.col + 1,
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
panic!("uncaught exception: failed to stringify primitive");
|
||||
|
||||
@@ -2725,7 +2725,28 @@ impl GlobalScope {
|
||||
})
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#report-the-error>
|
||||
/// <https://html.spec.whatwg.org/multipage/#report-an-exception>
|
||||
pub(crate) fn report_an_exception(&self, cx: SafeJSContext, error: HandleValue, can_gc: CanGc) {
|
||||
// Step 1. Let notHandled be true.
|
||||
//
|
||||
// Handled in `report_an_error`
|
||||
|
||||
// Step 2. Let errorInfo be the result of extracting error information from exception.
|
||||
// Step 3. Let script be a script found in an implementation-defined way, or null.
|
||||
// This should usually be the running script (most notably during run a classic script).
|
||||
// Step 4. If script is a classic script and script's muted errors is true, then set errorInfo[error] to null,
|
||||
// errorInfo[message] to "Script error.", errorInfo[filename] to the empty string,
|
||||
// errorInfo[lineno] to 0, and errorInfo[colno] to 0.
|
||||
let error_info = crate::dom::bindings::error::ErrorInfo::from_value(error, cx, can_gc);
|
||||
// Step 5. If omitError is true, then set errorInfo[error] to null.
|
||||
//
|
||||
// `omitError` defaults to `false`
|
||||
|
||||
// Steps 6-7
|
||||
self.report_an_error(error_info, error, can_gc);
|
||||
}
|
||||
|
||||
/// Steps 6-7 of <https://html.spec.whatwg.org/multipage/#report-an-exception>
|
||||
pub(crate) fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue, can_gc: CanGc) {
|
||||
// Step 6. Early return if global is in error reporting mode,
|
||||
if self.in_error_reporting_mode.get() {
|
||||
@@ -2760,12 +2781,17 @@ impl GlobalScope {
|
||||
// Step 6.3. Set global's in error reporting mode to false.
|
||||
self.in_error_reporting_mode.set(false);
|
||||
|
||||
// Step 7.
|
||||
// Step 7. If notHandled is true, then:
|
||||
if not_handled {
|
||||
// Step 7.2. If global implements DedicatedWorkerGlobalScope,
|
||||
// queue a global task on the DOM manipulation task source with the
|
||||
// global's associated Worker's relevant global object to run these steps:
|
||||
//
|
||||
// https://html.spec.whatwg.org/multipage/#runtime-script-errors-2
|
||||
if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() {
|
||||
dedicated.forward_error_to_worker_object(error_info);
|
||||
} else if self.is::<Window>() {
|
||||
// Step 7.3. Otherwise, the user agent may report exception to a developer console.
|
||||
if let Some(ref chan) = self.devtools_chan {
|
||||
let _ = chan.send(ScriptToDevtoolsControlMsg::ReportPageError(
|
||||
self.pipeline_id,
|
||||
|
||||
@@ -1329,6 +1329,12 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
||||
Some(DomRoot::from_ref(container))
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-reporterror>
|
||||
fn ReportError(&self, cx: JSContext, error: HandleValue, can_gc: CanGc) {
|
||||
self.as_global_scope()
|
||||
.report_an_exception(cx, error, can_gc);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-navigator>
|
||||
fn Navigator(&self) -> DomRoot<Navigator> {
|
||||
self.navigator
|
||||
|
||||
@@ -637,15 +637,17 @@ impl DedicatedWorkerGlobalScope {
|
||||
true
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#runtime-script-errors-2
|
||||
/// Step 7.2 of <https://html.spec.whatwg.org/multipage/#report-an-exception>
|
||||
pub(crate) fn forward_error_to_worker_object(&self, error_info: ErrorInfo) {
|
||||
// Step 7.2.1. Let workerObject be the Worker object associated with global.
|
||||
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
||||
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
|
||||
let task = Box::new(task!(forward_error_to_worker_object: move || {
|
||||
let worker = worker.root();
|
||||
let global = worker.global();
|
||||
|
||||
// Step 1.
|
||||
// Step 7.2.2. Set notHandled to the result of firing an event named error at workerObject, using ErrorEvent,
|
||||
// with the cancelable attribute initialized to true, and additional attributes initialized according to errorInfo.
|
||||
let event = ErrorEvent::new(
|
||||
&global,
|
||||
atom!("error"),
|
||||
@@ -659,7 +661,7 @@ impl DedicatedWorkerGlobalScope {
|
||||
CanGc::note(),
|
||||
);
|
||||
|
||||
// Step 2.
|
||||
// Step 7.2.3. If notHandled is true, then report exception for workerObject's relevant global object with omitError set to true.
|
||||
if event.upcast::<Event>().fire(worker.upcast::<EventTarget>(), CanGc::note()) {
|
||||
global.report_an_error(error_info, HandleValue::null(), CanGc::note());
|
||||
}
|
||||
|
||||
@@ -795,6 +795,12 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
|
||||
self.upcast::<GlobalScope>().crypto(CanGc::note())
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-reporterror>
|
||||
fn ReportError(&self, cx: JSContext, error: HandleValue, can_gc: CanGc) {
|
||||
self.upcast::<GlobalScope>()
|
||||
.report_an_exception(cx, error, can_gc);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-windowbase64-btoa>
|
||||
fn Btoa(&self, btoa: DOMString) -> Fallible<DOMString> {
|
||||
base64_btoa(btoa)
|
||||
|
||||
Reference in New Issue
Block a user