Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom JS error classes/enum #104

Closed
richardhuaaa opened this issue May 4, 2023 · 3 comments
Closed

Custom JS error classes/enum #104

richardhuaaa opened this issue May 4, 2023 · 3 comments

Comments

@richardhuaaa
Copy link
Contributor

richardhuaaa commented May 4, 2023

wasm_bindgen expects a JsValue to be returned from any function that can throw.

Currently, we handle this by returning JsError from all of our wasm bindings. This has the effect of auto-converting from Rust std::err::Error to JsError automatically via JsError::from, and then into JsValue via JsError::into.

The implementation of JsError::from is the JS equivalent of calling new Error(...) with the string generated from calling to_string() on the Rust error, which doesn't give consumers the opportunity to differentiate between different types of errors in code.

A workaround would be to define custom JS Error subclasses and import them into Rust, or define a special JS XMTPError type with an enum field and mappings from all known errors to this enum.

More info at rustwasm/wasm-bindgen#1742 (comment)

@richardhuaaa
Copy link
Contributor Author

richardhuaaa commented May 4, 2023

Another option is to define a trait TaggedError or similar, which expects a method/field called 'tag' which is a string, and implement it on all of our error types (with tag "unclassified" for anything else). And then from wasm, return a custom JS error type that has a 'tag' field and expect consuming clients to match based on that field.

@richardhuaaa
Copy link
Contributor Author

Also, need to somehow get the error message from native errors from localStorage.getItem/setItem, and append them to the error string

richardhuaaa added a commit that referenced this issue May 9, 2023
This achieves a few things:
1. Strongly typed Rust errors, using the thiserror crate. Info [here](https://nick.groenen.me/posts/rust-error-handling/) and [here](https://dev.to/seanchen1991/a-beginner-s-guide-to-handling-errors-in-rust-40k2). I think this is the most commonly used way today, coincidentally vodozemac also uses the same pattern.
2. Allow implementors of `Persistence` bindings to define their own `Error` type depending on the platform, via an associated type on the `Persistence` trait. When an error is encountered in `Persistence` within libxmtp, it will be wrapped with a Rust error and included on the `native_error` field, so that the platform-specific binding code can do whatever they want with it after it bubbles up.
3. In the LocalStorage implementation of Persistence, serialize from bytes to string via base64 instead of utf8.

I think this unblocks us on error handling within the core Rust `xmtp` crate, but the error handling in JS-land is far from perfect. The Rust error is strongly typed, but before it passes over the wasm_bindgen interface, it's effectively wrapped into a JS Error in the following way: `new Error(<rust_error.to_string()>)`. More details and possible solution in #104, but I think it's fine to punt this for now.

Added tests in `xmtp` and `bindings_js`.
@insipx
Copy link
Contributor

insipx commented Aug 28, 2024

closing in favor of #557

@insipx insipx closed this as completed Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants