1use std::convert::TryFrom;
2use std::fmt;
3use wasm_bindgen::{JsCast, JsValue};
4
5pub struct JsError {
9 pub name: String,
11 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
26pub 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 {}