Skip to main content

wry_bindgen/
js_error.rs

1//! JavaScript `Error` wrapper.
2
3use crate::{__rt, IntoJsGeneric, JsCast, JsValue, convert};
4
5/// A JavaScript Error object.
6///
7/// This type is used to create JavaScript Error objects that can be thrown or returned.
8#[derive(Debug, Clone)]
9#[repr(transparent)]
10pub struct JsError {
11    value: JsValue,
12}
13
14impl JsError {
15    /// Create a new JavaScript Error with the given message.
16    pub fn new(s: &str) -> JsError {
17        JsError {
18            value: crate::__wry_call_js_function!(
19                "(msg) => new Error(msg)",
20                fn(&str) -> JsValue,
21                (s)
22            ),
23        }
24    }
25}
26
27impl From<JsError> for JsValue {
28    fn from(error: JsError) -> Self {
29        error.value
30    }
31}
32
33impl From<JsValue> for JsError {
34    fn from(value: JsValue) -> Self {
35        JsError { value }
36    }
37}
38
39// Matches wasm-bindgen: `JsError` implements `From<E> where E: std::error::Error`,
40// which is what enables `?` on `Result<_, JsError>`. For this blanket impl to avoid
41// colliding with core's reflexive `From<T> for T`, `JsError` itself must NOT implement
42// `std::error::Error` (upstream deliberately does not implement it either).
43#[cfg(feature = "std")]
44impl<E> From<E> for JsError
45where
46    E: std::error::Error,
47{
48    fn from(error: E) -> Self {
49        use alloc::string::ToString;
50
51        JsError::new(&error.to_string())
52    }
53}
54
55impl AsRef<JsValue> for JsError {
56    fn as_ref(&self) -> &JsValue {
57        &self.value
58    }
59}
60
61impl core::fmt::Display for JsError {
62    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63        write!(f, "JsError")
64    }
65}
66
67impl JsCast for JsError {
68    fn instanceof(val: &JsValue) -> bool {
69        crate::js_helpers::js_is_error(val)
70    }
71
72    fn unchecked_from_js(val: JsValue) -> Self {
73        JsError { value: val }
74    }
75
76    fn unchecked_from_js_ref(val: &JsValue) -> &Self {
77        // SAFETY: #[repr(transparent)] guarantees same layout
78        unsafe { &*(val as *const JsValue as *const JsError) }
79    }
80}
81
82impl_js_value_wire!(for JsError, field value);
83
84unsafe impl __rt::marker::ErasableGeneric for JsError {
85    type Repr = JsValue;
86}
87
88impl IntoJsGeneric for JsError {
89    type JsCanon = Self;
90
91    fn to_js(self) -> Self {
92        self
93    }
94}
95
96impl convert::UpcastFrom<JsError> for JsError {}
97impl convert::UpcastFrom<JsError> for JsValue {}