Description
Motivation
As discussed in #1735, it's not idiomatic to throw JS values, like throw "foo"
, because that loses stack traces.
Instead it's highly recommended to always use throw new Error("foo")
. In wasm-bindgen, this corresponds to Err(js_sys::Error::new("foo"))
Internally, wasm-bindgen itself follows this recommendation, however, because the wasm-bindgen (and js-sys and web-sys) APIs return Result<T, JsValue>
, this encourages user functions to return Result<T, JsValue>
as well, which makes it easy for users to return non-Error
values:
fn foo() -> Result<(), JsValue> {
call_some_wasm_bindgen_api()?;
Err(JsValue::from("hi!"))
}
Proposed Solution
All wasm-bindgen APIs which return Result<T, JsValue>
should instead return Result<T, Error>
.
This includes wasm_bindgen(catch)
(which should have a debug_assert
to verify that it actually is an Error
object)
This uses the static type system to make it impossible to accidentally throw non-Error
types. It also is more "Rust-like", which makes the APIs easier to understand.
This is obviously a very large breaking change.
Alternatives
-
Do nothing. This is a lot less work, and isn't a breaking change, but it does mean that wasm-bindgen is encouraging bad behavior.
-
Keep
Result<T, JsValue>
, but put in runtime checks which verify that theErr
is ajs_sys::Error
. This is also a lot less work, but it does have a small runtime cost, and it's surprising behavior for the user.