From 44126a33cf1d76efd38b95a7aab3ef84f6e0e667 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Wed, 13 Sep 2023 14:04:43 +0200 Subject: [PATCH 1/3] `wasm-bindgen-futures`: use `queueMicrotask` for next tick runs (#3203) but use the old `Promise.then` mechanism as a fallback. Cache the existance of `queueMicrotask` in the queue instance. Signed-off-by: Dominik Csapak --- CHANGELOG.md | 7 +++++++ crates/futures/src/queue.rs | 31 +++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f3b664e66a..6213af8b033 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,13 @@ `#[repr(C)]` types. [#3595](https://github.com/rustwasm/wasm-bindgen/pull/3595) +* Use `queueMicrotask` in `wasm-bindgen-futures` for scheduling tasks on the next tick. + If that is not available, use the previous `Promise.then` mechanism as a fallback. + This should avoid quirks, like exceptions thrown get now properly reported + as normal exceptions rather than as rejected promises. + [#3611](https://github.com/rustwasm/wasm-bindgen/pull/3611) + [#2392](https://github.com/rustwasm/wasm-bindgen/issues/2392) + ### Fixed * Fixed bindings and comments for `Atomics.wait`. diff --git a/crates/futures/src/queue.rs b/crates/futures/src/queue.rs index 9a78571cd84..4d8e48800d2 100644 --- a/crates/futures/src/queue.rs +++ b/crates/futures/src/queue.rs @@ -4,6 +4,19 @@ use std::collections::VecDeque; use std::rc::Rc; use wasm_bindgen::prelude::*; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen] + fn queueMicrotask(closure: &Closure); +} + +#[wasm_bindgen] +extern "C" { + type Global; + #[wasm_bindgen(method, getter, js_name = queueMicrotask)] + fn hasQueueMicrotask(this: &Global) -> JsValue; +} + struct QueueState { // The queue of Tasks which are to be run in order. In practice this is all the // synchronous work of futures, and each `Task` represents calling `poll` on @@ -42,17 +55,21 @@ pub(crate) struct Queue { state: Rc, promise: Promise, closure: Closure, + has_queue_microtask: bool, } impl Queue { // Schedule a task to run on the next tick pub(crate) fn schedule_task(&self, task: Rc) { self.state.tasks.borrow_mut().push_back(task); - // Note that we currently use a promise and a closure to do this, but - // eventually we should probably use something like `queueMicrotask`: - // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask + // Use queueMicrotask to execute as soon as possible. If it does not exist + // fall back to the promise resolution if !self.state.is_scheduled.replace(true) { - let _ = self.promise.then(&self.closure); + if self.has_queue_microtask { + queueMicrotask(&self.closure); + } else { + let _ = self.promise.then(&self.closure); + } } } // Append a task to the currently running queue, or schedule it @@ -70,6 +87,11 @@ impl Queue { tasks: RefCell::new(VecDeque::new()), }); + let has_queue_microtask = js_sys::global() + .unchecked_into::() + .hasQueueMicrotask() + .is_function(); + Self { promise: Promise::resolve(&JsValue::undefined()), @@ -82,6 +104,7 @@ impl Queue { }, state, + has_queue_microtask, } } } From 1e985475606357ed8fee27fac09ce8fbd3bbf432 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Fri, 15 Sep 2023 15:01:13 +0200 Subject: [PATCH 2/3] `wasm-bindgen-futures`: queue: combine #[wasm_bindgen] blocks Signed-off-by: Dominik Csapak --- crates/futures/src/queue.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/futures/src/queue.rs b/crates/futures/src/queue.rs index 4d8e48800d2..2e17eb5ecf1 100644 --- a/crates/futures/src/queue.rs +++ b/crates/futures/src/queue.rs @@ -8,11 +8,9 @@ use wasm_bindgen::prelude::*; extern "C" { #[wasm_bindgen] fn queueMicrotask(closure: &Closure); -} -#[wasm_bindgen] -extern "C" { type Global; + #[wasm_bindgen(method, getter, js_name = queueMicrotask)] fn hasQueueMicrotask(this: &Global) -> JsValue; } From d8795d2d418b2ab849c784e66e18dd32df663de4 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Fri, 15 Sep 2023 15:01:59 +0200 Subject: [PATCH 3/3] remove related issue from changelog only the pull request is relevant Signed-off-by: Dominik Csapak --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6213af8b033..9201b1fa8b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,7 +97,6 @@ This should avoid quirks, like exceptions thrown get now properly reported as normal exceptions rather than as rejected promises. [#3611](https://github.com/rustwasm/wasm-bindgen/pull/3611) - [#2392](https://github.com/rustwasm/wasm-bindgen/issues/2392) ### Fixed