mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
script: Extract ErrorInfo from pending exception stack (#43632)
When reporting an exception attempt to extract `ErrorInfo` from the stack of the exception. Testing: Covered by existing tests, expectations updated. Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -5068,9 +5068,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mozjs"
|
||||
version = "0.15.9"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "475b6fbb284d1229f4108c5cf3842da47ee319b45c9a6c24358f41a0640a64f5"
|
||||
checksum = "2231fbdbc1ee3eaae2d2859792f5f1a6ca065fdebecccfe9447e531292883126"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
@@ -5083,9 +5083,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mozjs_sys"
|
||||
version = "0.140.8-4"
|
||||
version = "0.140.10-1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59e4cb2d3bf4a10d2f0005331419fb12b21ff260711ded47b9590ed432fad41e"
|
||||
checksum = "4d2a078fe5215b5afe55502b2a5c40b2119d81492eafc246373dc9cfda332129"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
|
||||
@@ -111,7 +111,7 @@ indexmap = { version = "2.14.0", features = ["std"] }
|
||||
inventory = { version = "0.3.24" }
|
||||
ipc-channel = "0.21"
|
||||
itertools = "0.14"
|
||||
js = { package = "mozjs", version = "=0.15.9", default-features = false, features = ["libz-sys", "intl"] }
|
||||
js = { package = "mozjs", version = "=0.15.11", default-features = false, features = ["libz-sys", "intl"] }
|
||||
keyboard-types = { version = "0.8.3", features = ["serde", "webdriver"] }
|
||||
kurbo = { version = "0.12", features = ["euclid"] }
|
||||
libc = "0.2"
|
||||
|
||||
@@ -14,6 +14,7 @@ use embedder_traits::JavaScriptErrorInfo;
|
||||
use js::context::JSContext;
|
||||
use js::conversions::jsstr_to_string;
|
||||
use js::error::{throw_range_error, throw_type_error};
|
||||
use js::gc::{HandleObject, HandleValue, MutableHandleValue};
|
||||
#[cfg(feature = "js_backtrace")]
|
||||
use js::jsapi::StackFormat as JSStackFormat;
|
||||
use js::jsapi::{ExceptionStackBehavior, JS_ClearPendingException, JS_IsExceptionPending};
|
||||
@@ -21,7 +22,7 @@ use js::jsval::UndefinedValue;
|
||||
use js::realm::CurrentRealm;
|
||||
use js::rust::wrappers::{JS_ErrorFromException, JS_GetPendingException, JS_SetPendingException};
|
||||
use js::rust::wrappers2::JS_GetProperty;
|
||||
use js::rust::{HandleObject, HandleValue, MutableHandleValue, describe_scripted_caller};
|
||||
use js::rust::{describe_scripted_caller, error_info_from_exception_stack};
|
||||
use libc::c_uint;
|
||||
use script_bindings::conversions::SafeToJSValConvertible;
|
||||
pub(crate) use script_bindings::error::*;
|
||||
@@ -348,28 +349,34 @@ impl ErrorInfo {
|
||||
/// Report a pending exception, thereby clearing it.
|
||||
pub(crate) fn report_pending_exception(cx: SafeJSContext, realm: InRealm, can_gc: CanGc) {
|
||||
rooted!(in(*cx) let mut value = UndefinedValue());
|
||||
if take_pending_exception(cx, value.handle_mut()) {
|
||||
GlobalScope::from_safe_context(cx, realm).report_an_exception(cx, value.handle(), can_gc);
|
||||
if let Some(error_info) = error_info_from_pending_exception(cx, value.handle_mut(), can_gc) {
|
||||
GlobalScope::from_safe_context(cx, realm).report_an_error(
|
||||
error_info,
|
||||
value.handle(),
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn take_pending_exception(cx: SafeJSContext, value: MutableHandleValue) -> bool {
|
||||
fn error_info_from_pending_exception(
|
||||
cx: SafeJSContext,
|
||||
value: MutableHandleValue,
|
||||
_can_gc: CanGc,
|
||||
) -> Option<ErrorInfo> {
|
||||
unsafe {
|
||||
if !JS_IsExceptionPending(*cx) {
|
||||
return false;
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
if !JS_GetPendingException(*cx, value) {
|
||||
JS_ClearPendingException(*cx);
|
||||
error!("Uncaught exception: JS_GetPendingException failed");
|
||||
return false;
|
||||
}
|
||||
let error_info = error_info_from_exception_stack(*cx, value.into())?;
|
||||
|
||||
JS_ClearPendingException(*cx);
|
||||
Some(ErrorInfo {
|
||||
message: error_info.message,
|
||||
filename: error_info.filename,
|
||||
lineno: error_info.line,
|
||||
column: error_info.col,
|
||||
})
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn javascript_error_info_from_error_info(
|
||||
@@ -417,11 +424,9 @@ pub(crate) fn take_and_report_pending_exception_for_api(
|
||||
let in_realm = InRealm::Already(&in_realm_proof);
|
||||
|
||||
rooted!(&in(cx) let mut value = UndefinedValue());
|
||||
if !take_pending_exception(cx.into(), value.handle_mut()) {
|
||||
return None;
|
||||
}
|
||||
let error_info =
|
||||
error_info_from_pending_exception(cx.into(), value.handle_mut(), CanGc::from_cx(cx))?;
|
||||
|
||||
let error_info = ErrorInfo::from_value(value.handle(), cx.into(), CanGc::from_cx(cx));
|
||||
let return_value = javascript_error_info_from_error_info(cx, &error_info, value.handle());
|
||||
GlobalScope::from_safe_context(cx.into(), in_realm).report_an_error(
|
||||
error_info,
|
||||
|
||||
@@ -13,8 +13,8 @@ use js::jsapi::{ExceptionStackBehavior, Heap, JSScript, SetScriptPrivate};
|
||||
use js::jsval::{PrivateValue, UndefinedValue};
|
||||
use js::panic::maybe_resume_unwind;
|
||||
use js::rust::wrappers2::{
|
||||
Compile1, JS_ClearPendingException, JS_ExecuteScript, JS_GetPendingException,
|
||||
JS_GetScriptPrivate, JS_SetPendingException,
|
||||
Compile1, JS_ClearPendingException, JS_ExecuteScript, JS_GetScriptPrivate,
|
||||
JS_IsExceptionPending, JS_SetPendingException,
|
||||
};
|
||||
use js::rust::{CompileOptionsWrapper, MutableHandleValue, transform_str_to_source_text};
|
||||
use script_bindings::cformat;
|
||||
@@ -24,11 +24,12 @@ use servo_url::ServoUrl;
|
||||
|
||||
use crate::DomTypeHolder;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::error::{Error, ErrorResult};
|
||||
use crate::dom::bindings::error::{Error, ErrorResult, report_pending_exception};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::window::Window;
|
||||
use crate::realms::{InRealm, enter_auto_realm};
|
||||
use crate::script_module::{
|
||||
ModuleScript, ModuleSource, ModuleTree, RethrowError, ScriptFetchOptions,
|
||||
};
|
||||
@@ -157,11 +158,13 @@ impl GlobalScope {
|
||||
|
||||
// TODO Step 3. Record classic script execution start time given script.
|
||||
|
||||
let mut realm = enter_auto_realm(cx, self);
|
||||
let cx = &mut realm.current_realm();
|
||||
|
||||
// Step 4. Prepare to run script given settings.
|
||||
// Once dropped this will run "Step 9. Clean up after running script" steps
|
||||
run_a_script::<DomTypeHolder, _>(self, || {
|
||||
// Step 5. Let evaluationStatus be null.
|
||||
rooted!(&in(cx) let mut evaluation_status = UndefinedValue());
|
||||
let mut result = false;
|
||||
|
||||
match script.record {
|
||||
@@ -188,10 +191,8 @@ impl GlobalScope {
|
||||
},
|
||||
}
|
||||
|
||||
unsafe { JS_GetPendingException(cx, evaluation_status.handle_mut()) };
|
||||
|
||||
// Step 8. If evaluationStatus is an abrupt completion, then:
|
||||
if !evaluation_status.is_undefined() {
|
||||
if unsafe { JS_IsExceptionPending(cx) } {
|
||||
warn!("Error evaluating script");
|
||||
|
||||
match (rethrow_errors, script.muted_errors) {
|
||||
@@ -208,13 +209,10 @@ impl GlobalScope {
|
||||
},
|
||||
// Step 8.3. Otherwise, rethrow errors is false. Perform the following steps:
|
||||
_ => {
|
||||
unsafe { JS_ClearPendingException(cx) };
|
||||
let in_realm_proof = cx.into();
|
||||
let in_realm = InRealm::Already(&in_realm_proof);
|
||||
// Report an exception given by evaluationStatus.[[Value]] for script's settings object's global object.
|
||||
self.report_an_exception(
|
||||
cx.into(),
|
||||
evaluation_status.handle(),
|
||||
CanGc::from_cx(cx),
|
||||
);
|
||||
report_pending_exception(cx.into(), in_realm, CanGc::from_cx(cx));
|
||||
|
||||
// Return evaluationStatus.
|
||||
return Err(Error::JSFailed);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[data-url.html]
|
||||
[Test data URL and scripts errors]
|
||||
expected: FAIL
|
||||
@@ -1,7 +0,0 @@
|
||||
[window-onerror-runtime-error-throw.html]
|
||||
[correct line number passed to window.onerror]
|
||||
expected: FAIL
|
||||
|
||||
[correct url passed to window.onerror]
|
||||
expected: FAIL
|
||||
|
||||
@@ -2,8 +2,3 @@
|
||||
expected: ERROR
|
||||
|
||||
[report-error-cross-origin.sub.any.worker.html]
|
||||
[WorkerGlobalScope error event: lineno]
|
||||
expected: FAIL
|
||||
|
||||
[WorkerGlobalScope error event: filename]
|
||||
expected: FAIL
|
||||
|
||||
@@ -2,8 +2,3 @@
|
||||
expected: ERROR
|
||||
|
||||
[report-error-redirect-to-cross-origin.sub.any.worker.html]
|
||||
[WorkerGlobalScope error event: lineno]
|
||||
expected: FAIL
|
||||
|
||||
[WorkerGlobalScope error event: filename]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
[report-error-setTimeout-cross-origin.sub.any.worker.html]
|
||||
[WorkerGlobalScope error event: lineno]
|
||||
expected: FAIL
|
||||
|
||||
[WorkerGlobalScope error event: filename]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[report-error-setTimeout-cross-origin.sub.any.sharedworker.html]
|
||||
expected: ERROR
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
[report-error-setTimeout-redirect-to-cross-origin.sub.any.worker.html]
|
||||
[WorkerGlobalScope error event: lineno]
|
||||
expected: FAIL
|
||||
|
||||
[WorkerGlobalScope error event: filename]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[report-error-setTimeout-redirect-to-cross-origin.sub.any.sharedworker.html]
|
||||
expected: ERROR
|
||||
|
||||
Reference in New Issue
Block a user