-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Allow conversion from Rust errors to JS throws #1173
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this! This is actually quite clean and I think pretty reasonable. I'd personally be in favor of merging!
@fitzgen how's this look to you?
type Abi = T::Abi; | ||
|
||
fn return_abi(self, extra: &mut Stack) -> Self::Abi { | ||
self.map_err(|err| JsValue::error(&err.to_string())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to include more than .to_string()
here? Sometimes an Error
could be a stack of errors (following .cause()
) which makes the most sense when presented all at once. Using just Error
can we do some iteration here or something like that to build a larger message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but I'm not sure how well that would interact with JS-generated stacktrace... Don't you think it might get a bit confusing to see two different but overlapping stacktraces on one error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right I don't think it'd interact with the JS stack trace, only that we'd use the Rust stack trace to generate a more descriptive message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah but what I mean, when you throw it on the JS side, you'll get Rust stack trace in the message followed by JS stack trace right below (as that's what JS engines normally print right after the message). Hence my concern that it might be somewhat confusing to see both following each other when in fact parts of them overlap in terms of functions... Not sure how to address this nicely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's true yeah it could get a bit garbled, but I actually think that's sort of what we want exactly, a Rust stack trace followed by a JS one!
We could perhaps experiment with various formattings though to see which works out best for the Rust message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not sure how I feel about multiline error message on JS side (it is rather unusual) and also about potential duplication of information within it (since Display implementations often tend to forward printing to nested errors, so adding .source()
chain would produce duplicates of same messages already included in the first line).
While I totally agree that experimentation with different formats is useful, as well as with API itself, I still feel that it's not as simple as it seems at first glance and would prefer to leave such experiments to separate PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to not land this unless it conveys the backtrace information for the Rust error. That often contains critical information about where errors come from needed for debugging, and as a built-in wrapper we in this crate would want to be sure to convey that information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, as mentioned, I'm not sure how this should look like (especially as I never used / looked into the cause
chains in Rust land, usually relying just on stack backtraces) and on the other hand never seen multiline error messages in JS land. Taking these two experiences into account, I'm not really confident with adding this part myself.
Feel free to close the PR, I'm happy for someone else to take over and come up with a better solution.
@fitzgen I'm curious, do you have thoughts on this? I tried rebasing this today and while we can use |
Hm, so I guess an ideal version of this in my mind would be something like:
Alternatively, we do basically the same thing but define our own This is maybe slightly better in that it doesn't involve seemingly out-of-left-field blanket conversion impls for However it is a bit funky that Both of these solutions should work with |
And we should probably send a PR upstream to |
I think actually we would have to implement both, because |
Unfortunately though those two impls conflict :( I think we have to either pick one or the other, I'm not actually sure how we'd support both 'natively' |
I really don't think we should allow arbitrary types that can get converted to |
I'm going to close this since it's quite old at this point, but we're still interested in improving the error story with wasm-bindgen, so a rebase and/or a new PR would always be welcome! |
I decided not to go the separate
JsError
type route because it makes integration more complicated. Namely, JS imports are still returning genericJsValue
which would need to be somehow validated and converted toJsError
or live alongside it to preserve ability of rethrowing. In both cases, it adds complications to the implementation with unclear benefits.Instead, as mentioned in #1017 (comment), I'm adding a support for transparent conversion from arbitrary
std::error::Error
to proper JS error throwing on the other side.This allows user to use any
Result
in exported functions with either an explicitError
type they already use in the codebase or any generic implementation, e.g.Box<dyn Error>
orfailure::Error
.Fixes #1017.