Skip to content

Commit

Permalink
wasm-bindgen-futures: use queueMicrotask for next tick runs (#3203)
Browse files Browse the repository at this point in the history
but use `catch` to wrap it in a Result to be able to fall back to the
previous `Promsise.then` variant.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
  • Loading branch information
flumm committed Sep 13, 2023
1 parent e7c760f commit 0d54602
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions crates/futures/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use std::collections::VecDeque;
use std::rc::Rc;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(catch)]
fn queueMicrotask(closure: &Closure<dyn FnMut(JsValue)>) -> Result<(), 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
Expand Down Expand Up @@ -48,10 +54,9 @@ impl Queue {
// Schedule a task to run on the next tick
pub(crate) fn schedule_task(&self, task: Rc<crate::task::Task>) {
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
if !self.state.is_scheduled.replace(true) {
// 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) && queueMicrotask(&self.closure).is_err() {
let _ = self.promise.then(&self.closure);
}
}
Expand Down

0 comments on commit 0d54602

Please sign in to comment.