You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The wasm_bindgen_futures::future_to_promise function does not appear to schedule a future if it is called in a closure used in a JS callback.
I suspect this might be related to the rational for adding must_use to js_sys::Promise (#1927), but as mentioned by @Pauan in that thread I also thought Promises would be eagerly evaluated. In my case, I expected them to be evaluated regardless of whether they are created in a callback.
Steps to Reproduce
The following code reproduces the issue:
use wasm_bindgen::JsValue;#[wasm_bindgen(start)]pubfnstart() -> Result<(),JsValue>{
wasm_bindgen_futures::future_to_promise(async{
web_sys::console::log_1(&JsValue::from("Future works"));Ok::<JsValue,JsValue>(JsValue::undefined())});let mouse_down = Closure::wrap(Box::new(|event:&web_sys::Event| {
web_sys::console::log_1(&JsValue::from("Mouse down sync"));
wasm_bindgen_futures::future_to_promise(async{
web_sys::console::log_1(&JsValue::from("Mouse down async"));Ok::<JsValue,JsValue>(JsValue::undefined())});})asBox<dynFnMut(&web_sys::Event)>);
web_sys::window().expect("Should have window").set_onmousedown(Some(JsCast::unchecked_from_js_ref(mouse_down.as_ref())));
mouse_down.forget();Ok(())}
Expected Behavior
I would expect that "Future works" is printed immediately, while "Mouse down sync" and "Mouse down async" are printed when a mouse button is clicked.
Actual Behavior
While "Future works" is printed immediately, only "Mouse down sync" is printed when the mouse is clicked.
Additional Context
What I am trying to create is an async callback function, which would allow me to call JsPromise::from(...).await. In particular, I am trying to parse a file that is dropped by the user onto the window. I am able to do this with the following code:
But I wish to write it using async/await instead of file.text.then(&cb). Ideally using an async closure, but that does not seem to work since Closure::wrap appears to expect an FnMut, which is why I started dabbling with async blocks instead.
The text was updated successfully, but these errors were encountered:
Ooops... turns out I was wrong about the above example. That actually works. The issue originates from using winits event loop in a spawn_local. I had this in there because I started out with the hello-triangle example from wgpu-rs. The following does not work, for instance:
use wasm_bindgen::prelude::*;use wasm_bindgen::{JsCast,JsValue};use winit::{
dpi::PhysicalPosition,
event::{ElementState,Event,MouseButton,WindowEvent},
event_loop::{ControlFlow,EventLoop,EventLoopProxy},};#[wasm_bindgen(start)]pubfnstart() -> Result<(),JsValue>{let event_loop = EventLoop::new();let mouse_down = Closure::wrap(Box::new(|event:&web_sys::Event| {
web_sys::console::log_1(&JsValue::from("Mouse down sync"));
wasm_bindgen_futures::future_to_promise(async{
web_sys::console::log_1(&JsValue::from("Mouse down async"));Ok::<JsValue,JsValue>(JsValue::undefined())});})asBox<dynFnMut(&web_sys::Event)>);
web_sys::window().expect("Should have window").set_onmousedown(Some(JsCast::unchecked_from_js_ref(mouse_down.as_ref())));
mouse_down.forget();
wasm_bindgen_futures::spawn_local(async{
event_loop.run(move |_, _, _| {});});Ok(())}
However, moving the event loop out of the call to spawn_local works:
use wasm_bindgen::prelude::*;use wasm_bindgen::{JsCast,JsValue};use winit::{
dpi::PhysicalPosition,
event::{ElementState,Event,MouseButton,WindowEvent},
event_loop::{ControlFlow,EventLoop,EventLoopProxy},};#[wasm_bindgen(start)]pubfnstart() -> Result<(),JsValue>{let event_loop = EventLoop::new();let mouse_down = Closure::wrap(Box::new(|event:&web_sys::Event| {
web_sys::console::log_1(&JsValue::from("Mouse down sync"));
wasm_bindgen_futures::future_to_promise(async{
web_sys::console::log_1(&JsValue::from("Mouse down async"));Ok::<JsValue,JsValue>(JsValue::undefined())});})asBox<dynFnMut(&web_sys::Event)>);
web_sys::window().expect("Should have window").set_onmousedown(Some(JsCast::unchecked_from_js_ref(mouse_down.as_ref())));
mouse_down.forget();
wasm_bindgen_futures::spawn_local(async{// do stuff});
event_loop.run(move |_, _, _| {});Ok(())}
I guess this is not too surprising. The event loop might be blocking some types of tasks from getting scheduled.
I will close this now and open an issue over in wgpu-rs instead.
Describe the Bug
The
wasm_bindgen_futures::future_to_promise
function does not appear to schedule a future if it is called in a closure used in a JS callback.I suspect this might be related to the rational for adding
must_use
tojs_sys::Promise
(#1927), but as mentioned by @Pauan in that thread I also thought Promises would be eagerly evaluated. In my case, I expected them to be evaluated regardless of whether they are created in a callback.Steps to Reproduce
The following code reproduces the issue:
Expected Behavior
I would expect that "Future works" is printed immediately, while "Mouse down sync" and "Mouse down async" are printed when a mouse button is clicked.
Actual Behavior
While "Future works" is printed immediately, only "Mouse down sync" is printed when the mouse is clicked.
Additional Context
What I am trying to create is an async callback function, which would allow me to call
JsPromise::from(...).await
. In particular, I am trying to parse a file that is dropped by the user onto the window. I am able to do this with the following code:But I wish to write it using async/await instead of
file.text.then(&cb)
. Ideally using an async closure, but that does not seem to work sinceClosure::wrap
appears to expect an FnMut, which is why I started dabbling with async blocks instead.The text was updated successfully, but these errors were encountered: