mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
script: Optionally store backtraces when throwing DOM exceptions.
This commit is contained in:
parent
5dc80dd07a
commit
06bca43aee
9 changed files with 51 additions and 2 deletions
|
@ -17,6 +17,7 @@ unstable = []
|
|||
unrooted_must_root_lint = ["script_plugins/unrooted_must_root_lint"]
|
||||
default = ["unrooted_must_root_lint"]
|
||||
webgl_backtrace = ["backtrace", "canvas_traits/webgl_backtrace"]
|
||||
js_backtrace = ["backtrace"]
|
||||
|
||||
[build-dependencies]
|
||||
cmake = "0.1"
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
//! Utilities to throw exceptions from Rust bindings.
|
||||
|
||||
#[cfg(feature = "js_backtrace")]
|
||||
use backtrace::Backtrace;
|
||||
#[cfg(feature = "js_backtrace")]
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
|
||||
use dom::bindings::codegen::PrototypeList::proto_id_to_name;
|
||||
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, ToJSValConvertible};
|
||||
|
@ -24,6 +28,11 @@ use js::rust::wrappers::JS_SetPendingException;
|
|||
use libc::c_uint;
|
||||
use std::slice::from_raw_parts;
|
||||
|
||||
/// An optional stringified JS backtrace and stringified native backtrace from the
|
||||
/// the last DOM exception that was reported.
|
||||
#[cfg(feature = "js_backtrace")]
|
||||
thread_local!(static LAST_EXCEPTION_BACKTRACE: DomRefCell<Option<(Option<String>, String)>> = DomRefCell::new(None));
|
||||
|
||||
/// DOM exceptions that can be thrown by a native DOM method.
|
||||
#[derive(Clone, Debug, MallocSizeOf)]
|
||||
pub enum Error {
|
||||
|
@ -90,6 +99,16 @@ pub type ErrorResult = Fallible<()>;
|
|||
|
||||
/// Set a pending exception for the given `result` on `cx`.
|
||||
pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, result: Error) {
|
||||
#[cfg(feature = "js_backtrace")]
|
||||
{
|
||||
capture_stack!(in(cx) let stack);
|
||||
let js_stack = stack.and_then(|s| s.as_string(None));
|
||||
let rust_stack = Backtrace::new();
|
||||
LAST_EXCEPTION_BACKTRACE.with(|backtrace| {
|
||||
*backtrace.borrow_mut() = Some((js_stack, format!("{:?}", rust_stack)));
|
||||
});
|
||||
}
|
||||
|
||||
let code = match result {
|
||||
Error::IndexSize => DOMErrorName::IndexSizeError,
|
||||
Error::NotFound => DOMErrorName::NotFoundError,
|
||||
|
@ -244,6 +263,17 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
|
|||
"Error at {}:{}:{} {}",
|
||||
error_info.filename, error_info.lineno, error_info.column, error_info.message
|
||||
);
|
||||
#[cfg(feature = "js_backtrace")]
|
||||
{
|
||||
LAST_EXCEPTION_BACKTRACE.with(|backtrace| {
|
||||
if let Some((js_backtrace, rust_backtrace)) = backtrace.borrow_mut().take() {
|
||||
if let Some(stack) = js_backtrace {
|
||||
eprintln!("JS backtrace:\n{}", stack);
|
||||
}
|
||||
eprintln!("Rust backtrace:\n{}", rust_backtrace);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if dispatch_event {
|
||||
GlobalScope::from_context(cx).report_an_error(error_info, value.handle());
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
extern crate app_units;
|
||||
extern crate audio_video_metadata;
|
||||
#[cfg(feature = "webgl_backtrace")]
|
||||
#[cfg(any(feature = "webgl_backtrace", feature = "js_backtrace"))]
|
||||
extern crate backtrace;
|
||||
extern crate base64;
|
||||
#[macro_use]
|
||||
|
|
|
@ -17,6 +17,7 @@ webdriver = ["webdriver_server"]
|
|||
energy-profiling = ["profile_traits/energy-profiling"]
|
||||
debugmozjs = ["script/debugmozjs"]
|
||||
googlevr = ["webvr/googlevr"]
|
||||
js_backtrace = ["script/js_backtrace"]
|
||||
webrender_debugger = ["webrender/debugger"]
|
||||
oculusvr = ["webvr/oculusvr"]
|
||||
unstable = [
|
||||
|
|
|
@ -43,3 +43,4 @@ unstable = ["libservo/unstable"]
|
|||
googlevr = ["libservo/googlevr"]
|
||||
oculusvr = ["libservo/oculusvr"]
|
||||
webgl_backtrace = ["libservo/webgl_backtrace"]
|
||||
js_backtrace = ["libservo/js_backtrace"]
|
||||
|
|
|
@ -31,6 +31,7 @@ energy-profiling = ["libservo/energy-profiling"]
|
|||
debugmozjs = ["libservo/debugmozjs"]
|
||||
unstable = ["libservo/unstable"]
|
||||
webgl_backtrace = ["libservo/webgl_backtrace"]
|
||||
js_backtrace = ["libservo/js_backtrace"]
|
||||
|
||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||
backtrace = "0.3"
|
||||
|
|
|
@ -257,6 +257,11 @@ class MachCommands(CommandBase):
|
|||
if debug_mozjs:
|
||||
features += ["debugmozjs"]
|
||||
|
||||
if self.config["build"]["webgl-backtrace"]:
|
||||
features += ["webgl-backtrace"]
|
||||
if self.config["build"]["dom-backtrace"]:
|
||||
features += ["dom-backtrace"]
|
||||
|
||||
if features:
|
||||
opts += ["--features", "%s" % ' '.join(features)]
|
||||
|
||||
|
|
|
@ -288,6 +288,8 @@ class CommandBase(object):
|
|||
self.config["build"].setdefault("rustflags", "")
|
||||
self.config["build"].setdefault("incremental", None)
|
||||
self.config["build"].setdefault("thinlto", False)
|
||||
self.config["build"].setdefault("webgl-backtrace", False)
|
||||
self.config["build"].setdefault("dom-backtrace", False)
|
||||
|
||||
self.config.setdefault("android", {})
|
||||
self.config["android"].setdefault("sdk", "")
|
||||
|
|
|
@ -32,6 +32,14 @@ android = false
|
|||
# Set "debug-mozjs" or use `mach build --debug-mozjs` to build a debug spidermonkey.
|
||||
debug-mozjs = false
|
||||
|
||||
# When a GL error occurs as a result of a WebGL operation, print the stack trace for the content
|
||||
# JS and native Rust code that triggered the failed operation. Warning: very slow.
|
||||
webgl-backtrace = false
|
||||
|
||||
# When a DOM exception is reported, print the stack trace for the content JS and native Rust code
|
||||
# that triggered it.
|
||||
dom-backtrace = false
|
||||
|
||||
# Set to the path to your ccache binary to enable caching of compiler outputs
|
||||
#ccache = "/usr/local/bin/ccache"
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue