Skip to main content

wasmer/entities/
trap.rs

1use std::{any::Any, error::Error, fmt::Debug};
2
3#[cfg(feature = "sys")]
4use crate::BackendException;
5use crate::{Exception, RuntimeError, macros::backend::match_rt};
6
7/// An enumeration of all the trap kinds supported by the runtimes.
8#[derive(Debug, derive_more::From)]
9pub enum BackendTrap {
10    #[cfg(feature = "sys")]
11    /// The trap from the `sys` runtime.
12    Sys(crate::backend::sys::vm::Trap),
13
14    #[cfg(feature = "v8")]
15    /// The trap from the `v8` runtime.
16    V8(crate::backend::v8::vm::Trap),
17
18    #[cfg(feature = "js")]
19    /// The trap from the `js` runtime.
20    Js(crate::backend::js::vm::Trap),
21}
22
23impl BackendTrap {
24    /// Construct a new Error with the given a user error.
25    ///
26    /// Internally saves a backtrace when constructed.
27    pub fn user(err: Box<dyn Error + Send + Sync>) -> RuntimeError {
28        #[cfg(feature = "sys")]
29        {
30            return crate::backend::sys::vm::Trap::user(err).into();
31        }
32
33        #[cfg(feature = "v8")]
34        {
35            return crate::backend::v8::vm::Trap::user(err).into();
36        }
37        #[cfg(feature = "js")]
38        {
39            return crate::backend::js::vm::Trap::user(err).into();
40        }
41
42        panic!("No runtime enabled!")
43    }
44    /// Attempts to downcast the `Trap` to a concrete type.
45    #[inline]
46    pub fn downcast<T: Error + 'static>(self) -> Result<T, Self> {
47        match_rt!(on self => s {
48            s.downcast::<T>().map_err(Into::into)
49        })
50    }
51
52    /// Attempts to downcast the `Trap` to a concrete type.
53    #[inline]
54    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
55        match_rt!(on self => s {
56            s.downcast_ref::<T>()
57        })
58    }
59
60    /// Returns true if the `Trap` is the same as T
61    #[inline]
62    pub fn is<T: Error + 'static>(&self) -> bool {
63        match_rt!(on self => s {
64            s.is::<T>()
65        })
66    }
67
68    /// Returns true if the trap is an exception
69    #[inline]
70    pub fn is_exception(&self) -> bool {
71        match_rt!(on self => s {
72            s.is_exception()
73        })
74    }
75
76    /// If the `Trap` is an uncaught exception, returns it.
77    #[inline]
78    pub fn to_exception(&self) -> Option<Exception> {
79        match self {
80            #[cfg(feature = "sys")]
81            Self::Sys(s) => s
82                .to_exception_ref()
83                .map(|e| Exception::from_vm_exceptionref(crate::vm::VMExceptionRef::Sys(e))),
84            #[cfg(feature = "v8")]
85            Self::V8(s) => s
86                .to_exception_ref()
87                .map(|e| Exception::from_vm_exceptionref(crate::vm::VMExceptionRef::V8(e))),
88            #[cfg(feature = "js")]
89            Self::Js(s) => s
90                .to_exception_ref()
91                .map(|e| Exception::from_vm_exceptionref(crate::vm::VMExceptionRef::Js(e))),
92        }
93    }
94}
95
96impl std::fmt::Display for BackendTrap {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        match_rt!(on self => s {
99            (s as &dyn std::fmt::Display).fmt(f)
100        })
101    }
102}
103
104impl std::error::Error for BackendTrap {
105    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
106        match_rt!(on self => s {
107            s.source()
108        })
109    }
110}