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 = String::from(js_sys::JsString::from(js_value.clone()));
56                Err(NotJsError {
57                    js_value,
58                    js_to_string,
59                })
60            }
61        }
62    }
63}
64
65impl fmt::Display for JsError {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        write!(f, "{}", self.js_to_string)
68    }
69}
70
71impl fmt::Debug for JsError {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        f.debug_struct("JsError")
74            .field("name", &self.name)
75            .field("message", &self.message)
76            .finish()
77    }
78}
79
80impl std::error::Error for JsError {}