From 390492f69bfe46d9b4f5a5ea46ae962d311edebf Mon Sep 17 00:00:00 2001 From: Pauan Date: Mon, 9 Dec 2019 01:09:47 +0100 Subject: [PATCH 1/3] Adding in async support for start --- crates/backend/src/codegen.rs | 36 +++++++++++++++++---- crates/macro/ui-tests/start-function.rs | 18 +++++++++++ crates/macro/ui-tests/start-function.stderr | 20 ++++++++++++ src/lib.rs | 22 +++++++++++++ 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 16ceda1ad34..6fba7301728 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -447,17 +447,41 @@ impl TryToTokens for ast::Export { // since we're returning a promise to JS, and this will implicitly // require that the function returns a `Future>` let (ret_ty, ret_expr) = if self.function.r#async { + if self.start { + ( + quote! { () }, + quote! { + wasm_bindgen_futures::spawn_local(async move { + let val = <#syn_ret as wasm_bindgen::__rt::StartReturn>::into_null_result(#ret.await); + + if let std::result::Result::Err(val) = val { + wasm_bindgen::throw_val(val); + } + }) + }, + ) + + } else { + ( + quote! { wasm_bindgen::JsValue }, + quote! { + wasm_bindgen_futures::future_to_promise(async move { + <#syn_ret as wasm_bindgen::__rt::IntoJsResult>::into_js_result(#ret.await) + }).into() + }, + ) + } + + } else if self.start { ( - quote! { wasm_bindgen::JsValue }, - quote! { - wasm_bindgen_futures::future_to_promise(async { - wasm_bindgen::__rt::IntoJsResult::into_js_result(#ret.await) - }).into() - }, + quote! { std::result::Result<(), wasm_bindgen::JsValue> }, + quote! { <#syn_ret as wasm_bindgen::__rt::StartReturn>::into_null_result(#ret) }, ) + } else { (quote! { #syn_ret }, quote! { #ret }) }; + let projection = quote! { <#ret_ty as wasm_bindgen::convert::ReturnWasmAbi> }; let convert_ret = quote! { #projection::return_abi(#ret_expr) }; let describe_ret = quote! { diff --git a/crates/macro/ui-tests/start-function.rs b/crates/macro/ui-tests/start-function.rs index 3947840cd5b..3c62ee7fea1 100644 --- a/crates/macro/ui-tests/start-function.rs +++ b/crates/macro/ui-tests/start-function.rs @@ -9,4 +9,22 @@ pub fn foo2(x: u32) {} #[wasm_bindgen(start)] pub fn foo3() {} +#[wasm_bindgen(start)] +pub fn foo4() -> Result<(), JsValue> { Ok(()) } + +#[wasm_bindgen(start)] +pub fn foo5() -> Result { Ok(JsValue::from(1u32)) } + +#[wasm_bindgen(start)] +pub async fn foo_async1() {} + +#[wasm_bindgen(start)] +pub async fn foo_async2() -> Result<(), JsValue> { Ok(()) } + +#[wasm_bindgen(start)] +pub async fn foo_async3() -> Result { Err(()) } + +#[wasm_bindgen(start)] +pub async fn foo_async4() -> Result { Ok(JsValue::from(1u32)) } + fn main() {} diff --git a/crates/macro/ui-tests/start-function.stderr b/crates/macro/ui-tests/start-function.stderr index 43d845f94ca..7dca72c94ec 100644 --- a/crates/macro/ui-tests/start-function.stderr +++ b/crates/macro/ui-tests/start-function.stderr @@ -9,3 +9,23 @@ error: the start function cannot have generics | 10 | pub fn foo3() {} | ^^^ + +error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::StartReturn` is not satisfied + --> $DIR/start-function.rs:24:1 + | +24 | #[wasm_bindgen(start)] + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::StartReturn` is not implemented for `std::result::Result` + | + = help: the following implementations were found: + as wasm_bindgen::__rt::StartReturn> + = note: required by `wasm_bindgen::__rt::StartReturn::into_null_result` + +error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::StartReturn` is not satisfied + --> $DIR/start-function.rs:27:1 + | +27 | #[wasm_bindgen(start)] + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::StartReturn` is not implemented for `std::result::Result` + | + = help: the following implementations were found: + as wasm_bindgen::__rt::StartReturn> + = note: required by `wasm_bindgen::__rt::StartReturn::into_null_result` diff --git a/src/lib.rs b/src/lib.rs index 3b54fb47b28..757231c7509 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1116,6 +1116,28 @@ pub mod __rt { } } } + + + /// An internal helper trait for usage in `#[wasm_bindgen(start)]` + /// functions to convert the return value of the function to + /// `Result<(), JsValue>` which is what we'll return to JS. + pub trait StartReturn { + fn into_null_result(self) -> Result<(), JsValue>; + } + + impl StartReturn for () { + #[inline] + fn into_null_result(self) -> Result<(), JsValue> { + Ok(self) + } + } + + impl> StartReturn for Result<(), E> { + #[inline] + fn into_null_result(self) -> Result<(), JsValue> { + self.map_err(|e| e.into()) + } + } } /// A wrapper type around slices and vectors for binding the `Uint8ClampedArray` From 3f7ab8539c6e3c14aa2bff5b907637a1e75d5081 Mon Sep 17 00:00:00 2001 From: Pauan Date: Mon, 9 Dec 2019 01:16:56 +0100 Subject: [PATCH 2/3] Adding in another test case --- crates/macro/ui-tests/start-function.rs | 5 ++++- crates/macro/ui-tests/start-function.stderr | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/macro/ui-tests/start-function.rs b/crates/macro/ui-tests/start-function.rs index 3c62ee7fea1..65ad90bf283 100644 --- a/crates/macro/ui-tests/start-function.rs +++ b/crates/macro/ui-tests/start-function.rs @@ -13,7 +13,10 @@ pub fn foo3() {} pub fn foo4() -> Result<(), JsValue> { Ok(()) } #[wasm_bindgen(start)] -pub fn foo5() -> Result { Ok(JsValue::from(1u32)) } +pub fn foo5() -> Result { Err(()) } + +#[wasm_bindgen(start)] +pub fn foo6() -> Result { Ok(JsValue::from(1u32)) } #[wasm_bindgen(start)] pub async fn foo_async1() {} diff --git a/crates/macro/ui-tests/start-function.stderr b/crates/macro/ui-tests/start-function.stderr index 7dca72c94ec..5d5a3e9db95 100644 --- a/crates/macro/ui-tests/start-function.stderr +++ b/crates/macro/ui-tests/start-function.stderr @@ -11,9 +11,9 @@ error: the start function cannot have generics | ^^^ error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::StartReturn` is not satisfied - --> $DIR/start-function.rs:24:1 + --> $DIR/start-function.rs:27:1 | -24 | #[wasm_bindgen(start)] +27 | #[wasm_bindgen(start)] | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::StartReturn` is not implemented for `std::result::Result` | = help: the following implementations were found: @@ -21,9 +21,9 @@ error[E0277]: the trait bound `std::result::Result: w = note: required by `wasm_bindgen::__rt::StartReturn::into_null_result` error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::StartReturn` is not satisfied - --> $DIR/start-function.rs:27:1 + --> $DIR/start-function.rs:30:1 | -27 | #[wasm_bindgen(start)] +30 | #[wasm_bindgen(start)] | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::StartReturn` is not implemented for `std::result::Result` | = help: the following implementations were found: From ea844ab96ccc67cb0ce943df24865b4400b91163 Mon Sep 17 00:00:00 2001 From: Pauan Date: Mon, 9 Dec 2019 01:25:37 +0100 Subject: [PATCH 3/3] Refactoring the Start trait to be cleaner --- crates/backend/src/codegen.rs | 10 +++------- crates/macro/ui-tests/start-function.stderr | 16 ++++++++-------- src/lib.rs | 21 ++++++++++----------- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 6fba7301728..18d6c33592b 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -452,11 +452,7 @@ impl TryToTokens for ast::Export { quote! { () }, quote! { wasm_bindgen_futures::spawn_local(async move { - let val = <#syn_ret as wasm_bindgen::__rt::StartReturn>::into_null_result(#ret.await); - - if let std::result::Result::Err(val) = val { - wasm_bindgen::throw_val(val); - } + <#syn_ret as wasm_bindgen::__rt::Start>::start(#ret.await); }) }, ) @@ -474,8 +470,8 @@ impl TryToTokens for ast::Export { } else if self.start { ( - quote! { std::result::Result<(), wasm_bindgen::JsValue> }, - quote! { <#syn_ret as wasm_bindgen::__rt::StartReturn>::into_null_result(#ret) }, + quote! { () }, + quote! { <#syn_ret as wasm_bindgen::__rt::Start>::start(#ret) }, ) } else { diff --git a/crates/macro/ui-tests/start-function.stderr b/crates/macro/ui-tests/start-function.stderr index 5d5a3e9db95..81814584cd8 100644 --- a/crates/macro/ui-tests/start-function.stderr +++ b/crates/macro/ui-tests/start-function.stderr @@ -10,22 +10,22 @@ error: the start function cannot have generics 10 | pub fn foo3() {} | ^^^ -error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::StartReturn` is not satisfied +error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::Start` is not satisfied --> $DIR/start-function.rs:27:1 | 27 | #[wasm_bindgen(start)] - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::StartReturn` is not implemented for `std::result::Result` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::Start` is not implemented for `std::result::Result` | = help: the following implementations were found: - as wasm_bindgen::__rt::StartReturn> - = note: required by `wasm_bindgen::__rt::StartReturn::into_null_result` + as wasm_bindgen::__rt::Start> + = note: required by `wasm_bindgen::__rt::Start::start` -error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::StartReturn` is not satisfied +error[E0277]: the trait bound `std::result::Result: wasm_bindgen::__rt::Start` is not satisfied --> $DIR/start-function.rs:30:1 | 30 | #[wasm_bindgen(start)] - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::StartReturn` is not implemented for `std::result::Result` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::Start` is not implemented for `std::result::Result` | = help: the following implementations were found: - as wasm_bindgen::__rt::StartReturn> - = note: required by `wasm_bindgen::__rt::StartReturn::into_null_result` + as wasm_bindgen::__rt::Start> + = note: required by `wasm_bindgen::__rt::Start::start` diff --git a/src/lib.rs b/src/lib.rs index 757231c7509..536dcdb7496 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1119,23 +1119,22 @@ pub mod __rt { /// An internal helper trait for usage in `#[wasm_bindgen(start)]` - /// functions to convert the return value of the function to - /// `Result<(), JsValue>` which is what we'll return to JS. - pub trait StartReturn { - fn into_null_result(self) -> Result<(), JsValue>; + /// functions to throw the error (if it is `Err`). + pub trait Start { + fn start(self); } - impl StartReturn for () { + impl Start for () { #[inline] - fn into_null_result(self) -> Result<(), JsValue> { - Ok(self) - } + fn start(self) {} } - impl> StartReturn for Result<(), E> { + impl> Start for Result<(), E> { #[inline] - fn into_null_result(self) -> Result<(), JsValue> { - self.map_err(|e| e.into()) + fn start(self) { + if let Err(e) = self { + crate::throw_val(e.into()); + } } } }