-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
WebIDL: Handle Invalid Enum Returns #477
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
Conversation
377219c
to
02feaf0
Compare
crates/backend/src/codegen.rs
Outdated
/// | ||
/// # Panics | ||
/// This function will panic if the `JsValue` isn't a string | ||
#vis fn from_js_value(obj: ::wasm_bindgen::JsValue) -> Result<#name, 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.
Since this doesn't actually need ownership, should this take &JsValue
?
crates/backend/src/codegen.rs
Outdated
@@ -624,17 +624,26 @@ impl ToTokens for ast::ImportEnum { | |||
|
|||
(quote! { | |||
#[allow(bad_style)] | |||
#[derive(Copy, Clone, Debug)] | |||
#[derive(Copy, Clone, PartialEq, Debug)] |
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've just realized (after the fact, sorry!) that in other places in wasm-bindgen we don't explicitly list derive modes but rather pass through the original annotations. Here there's no #[wasm_bindgen]
equivalent for generating an imported enum
so it doesn't matter too too much, but long-term we may want this line to be #(#rust_attrs)*
and store attributes in the ImportEnum
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.
👍
src/convert.rs
Outdated
/// A trait for anything that can be recovered by-value from the wasm ABI | ||
/// but whose conversion might error, for example a JS string being converted | ||
/// to a Rust enum. | ||
pub trait TryFromWasmAbi: WasmDescribe + Sized { |
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 a little wary of adding a trait like this, I'm afraid it'll be difficult to work with in general. The conversion traits are used in various locations throughout imports/exports/closures/etc. This also necessitates FromWasmAbi
for Result
which seems unfortunate in the sense that you can't do:
#[wasm_bindgen]
pub fn foo(a: CustomEnumType) {
// ...
}
but are instead forced to do:
#[wasm_bindgen]
pub fn foo(a: Result<CustomEnumType, String>) {
// ...
}
I might be leaning a bit towards dealing with nonexhaustive enums due to this interaction of how to add implicit conversions? I would also be ok, though, having a fallible constructor in Rust but panicking in the conversions at the boundary (as it seems like that's what may happen most of the time anyway?)
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.
Non-exhaustive enums are fine by me, the only awkward thing with them is the potential panic if the Rust code gets an invalid enum then tries to return it back to JS, which I can't think of a decent way around.
02feaf0
to
e01f16c
Compare
Awesome, thanks! |
As discussed in #260 and #433 there are two main ways to handle invalid enum returns from JS in the WebIDL codegen:
Method 1
Convert enum returns in WebIDL to
Result<ENUM, String>
sAdvantages
String
inErr
Disadvantages
match
s that don't have a wildcard arm(unlike in Method 2, which forces a wildcard match), so the user might have to change their code when they update theirweb-sys
versionMethod 2
Non-exhaustive enums.
Advantages
web-sys
crate's Rust enum variants) don't break code because non-exhaustive enums force wildcard matchesDisadvantages
I opted for Method 1 because it seems like it gives the cleanest code when using enums, and I like the idea of being able to handle browser specific returns that aren't document in WebIDL. Do you folks agree, or should we go with Method 2/something else?
Closes #260