Skip to main content

gloo_utils/
errors.rs

1use std::convert::TryFrom;
2use std::fmt;
3use wasm_bindgen::{JsCast, JsValue};
4
5/// Wrapper type around [`js_sys::Error`]
6///
7/// [`Display`][fmt::Display] impl returns the result `error.toString()` from JavaScript
8pub struct JsError {
9    /// `name` from [`js_sys::Error`]
10    pub name: String,
11    /// `message` from [`js_sys::Error`]
12    pub message: String,
13    js_to_string: String,
14}
15
16impl From<js_sys::Error> for JsError {
17    fn from(error: js_sys::Error) -> Self {
18        JsError {
19            name: String::from(error.name()),
20            message: String::from(error.message()),
21            js_to_string: String::from(error.to_string()),
22        }
23    }
24}
25
26/// The [`JsValue`] is not a JavaScript's `Error`.
27pub struct NotJsError {
28    pub js_value: JsValue,
29    js_to_string: String,
30}
31
32impl fmt::Debug for NotJsError {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        f.debug_struct("NotJsError")
35            .field("js_value", &self.js_value)
36            .finish()
37    }
38}
39
40impl fmt::Display for NotJsError {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        f.write_str(&self.js_to_string)
43    }
44}
45
46impl std::error::Error for NotJsError {}
47
48impl TryFrom<JsValue> for JsError {
49    type Error = NotJsError;
50
51    fn try_from(value: JsValue) -> Result<Self, Self::Error> {
52        match value.dyn_into::<js_sys::Error>() {
53            Ok(error) => Ok(JsError::from(error)),
54            Err(js_value) => {
55                let js_to_string = js_value
56                    .clone()
57                    .dyn_into::<js_sys::JsString>()
58                    .map(String::from)
59                    .unwrap_or_else(|_| {
60                        String::from("js_value passed has no string representation")
61                    });
62                Err(NotJsError {
63                    js_value,
64                    js_to_string,
65                })
66            }
67        }
68    }
69}
70
71impl fmt::Display for JsError {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        write!(f, "{}", self.js_to_string)
74    }
75}
76
77impl fmt::Debug for JsError {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        f.debug_struct("JsError")
80            .field("name", &self.name)
81            .field("message", &self.message)
82            .finish()
83    }
84}
85
86impl std::error::Error for JsError {}