avm2: Add `error_backtrace` feature to capture RustError backtrace
This off-by-default feature is useful when debugging a RustError (e.g. `TypeError: null is not an Object`) that wasn't handled by a caller like `coerce_to_type`
This commit is contained in:
parent
fe08638d26
commit
1517e4037c
|
@ -91,6 +91,7 @@ jpegxr = ["dep:jpegxr", "lzma"]
|
|||
default_font = []
|
||||
test_only_as3 = []
|
||||
serde = ["serde/derive"]
|
||||
error_backtrace = []
|
||||
|
||||
[build-dependencies]
|
||||
build_playerglobal = { path = "build_playerglobal" }
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::avm2::object::TObject;
|
|||
use crate::avm2::{Activation, AvmString, Class, Multiname, Value};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Debug;
|
||||
use std::mem::size_of;
|
||||
|
||||
use super::function::display_function;
|
||||
use super::method::Method;
|
||||
|
@ -20,7 +19,54 @@ pub enum Error<'gc> {
|
|||
/// An internal VM error. This cannot be caught by ActionScript code -
|
||||
/// it will either be logged by Ruffle, or cause the player to
|
||||
/// stop executing.
|
||||
RustError(Box<dyn std::error::Error>),
|
||||
RustError(RustError),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub struct RustError {
|
||||
#[source]
|
||||
source: Box<dyn std::error::Error>,
|
||||
#[cfg(feature = "error_backtrace")]
|
||||
backtrace: Option<std::backtrace::Backtrace>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RustError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.source)?;
|
||||
#[cfg(feature = "error_backtrace")]
|
||||
if let Some(backtrace) = &self.backtrace {
|
||||
write!(f, "\n{}", backtrace)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl RustError {
|
||||
pub fn new(source: Box<dyn std::error::Error>) -> Self {
|
||||
RustError {
|
||||
source,
|
||||
#[cfg(feature = "error_backtrace")]
|
||||
backtrace: Some(std::backtrace::Backtrace::capture()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<dyn std::error::Error>> for RustError {
|
||||
fn from(source: Box<dyn std::error::Error>) -> Self {
|
||||
RustError::new(source)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for RustError {
|
||||
fn from(source: &str) -> Self {
|
||||
RustError::new(source.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for RustError {
|
||||
fn from(source: String) -> Self {
|
||||
RustError::new(source.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Debug for Error<'gc> {
|
||||
|
@ -37,17 +83,17 @@ impl<'gc> Debug for Error<'gc> {
|
|||
|
||||
match self {
|
||||
Error::AvmError(error) => write!(f, "AvmError({:?})", error),
|
||||
Error::RustError(error) => write!(f, "RustError({:?})", error),
|
||||
Error::RustError(error) => write!(f, "RustError({})", error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This type is used very frequently, so make sure it doesn't unexpectedly grow.
|
||||
#[cfg(target_family = "wasm")]
|
||||
const _: () = assert!(size_of::<Result<Value<'_>, Error<'_>>>() == 24);
|
||||
#[cfg(all(target_family = "wasm", not(feature = "error_backtrace")))]
|
||||
const _: () = assert!(std::mem::size_of::<Result<Value<'_>, Error<'_>>>() == 24);
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const _: () = assert!(size_of::<Result<Value<'_>, Error<'_>>>() == 32);
|
||||
#[cfg(all(target_pointer_width = "64", not(feature = "error_backtrace")))]
|
||||
const _: () = assert!(std::mem::size_of::<Result<Value<'_>, Error<'_>>>() == 32);
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
|
@ -813,7 +859,7 @@ impl<'gc, 'a> From<&'a str> for Error<'gc> {
|
|||
|
||||
impl<'gc, 'a> From<Cow<'a, str>> for Error<'gc> {
|
||||
fn from(val: Cow<'a, str>) -> Error<'gc> {
|
||||
Error::RustError(val.into())
|
||||
Error::RustError((*val).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,6 +871,6 @@ impl<'gc> From<String> for Error<'gc> {
|
|||
|
||||
impl<'gc> From<ruffle_render::error::Error> for Error<'gc> {
|
||||
fn from(val: ruffle_render::error::Error) -> Error<'gc> {
|
||||
Error::RustError(val.into())
|
||||
Error::RustError(RustError::new(val.into()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ jpegxr = ["ruffle_core/jpegxr"]
|
|||
|
||||
# core features
|
||||
avm_debug = ["ruffle_core/avm_debug"]
|
||||
error_backtrace = ["ruffle_core/error_backtrace"]
|
||||
lzma = ["ruffle_core/lzma"]
|
||||
software_video = ["ruffle_video_software"]
|
||||
external_video = ["ruffle_video_external"]
|
||||
|
|
Loading…
Reference in New Issue