@@ -4,6 +4,17 @@ use std::collections::VecDeque;
4
4
use std:: rc:: Rc ;
5
5
use wasm_bindgen:: prelude:: * ;
6
6
7
+ #[ wasm_bindgen]
8
+ extern "C" {
9
+ #[ wasm_bindgen]
10
+ fn queueMicrotask ( closure : & Closure < dyn FnMut ( JsValue ) > ) ;
11
+
12
+ type Global ;
13
+
14
+ #[ wasm_bindgen( method, getter, js_name = queueMicrotask) ]
15
+ fn hasQueueMicrotask ( this : & Global ) -> JsValue ;
16
+ }
17
+
7
18
struct QueueState {
8
19
// The queue of Tasks which are to be run in order. In practice this is all the
9
20
// synchronous work of futures, and each `Task` represents calling `poll` on
@@ -42,17 +53,21 @@ pub(crate) struct Queue {
42
53
state : Rc < QueueState > ,
43
54
promise : Promise ,
44
55
closure : Closure < dyn FnMut ( JsValue ) > ,
56
+ has_queue_microtask : bool ,
45
57
}
46
58
47
59
impl Queue {
48
60
// Schedule a task to run on the next tick
49
61
pub ( crate ) fn schedule_task ( & self , task : Rc < crate :: task:: Task > ) {
50
62
self . state . tasks . borrow_mut ( ) . push_back ( task) ;
51
- // Note that we currently use a promise and a closure to do this, but
52
- // eventually we should probably use something like `queueMicrotask`:
53
- // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask
63
+ // Use queueMicrotask to execute as soon as possible. If it does not exist
64
+ // fall back to the promise resolution
54
65
if !self . state . is_scheduled . replace ( true ) {
55
- let _ = self . promise . then ( & self . closure ) ;
66
+ if self . has_queue_microtask {
67
+ queueMicrotask ( & self . closure ) ;
68
+ } else {
69
+ let _ = self . promise . then ( & self . closure ) ;
70
+ }
56
71
}
57
72
}
58
73
// Append a task to the currently running queue, or schedule it
@@ -70,6 +85,11 @@ impl Queue {
70
85
tasks : RefCell :: new ( VecDeque :: new ( ) ) ,
71
86
} ) ;
72
87
88
+ let has_queue_microtask = js_sys:: global ( )
89
+ . unchecked_into :: < Global > ( )
90
+ . hasQueueMicrotask ( )
91
+ . is_function ( ) ;
92
+
73
93
Self {
74
94
promise : Promise :: resolve ( & JsValue :: undefined ( ) ) ,
75
95
@@ -82,6 +102,7 @@ impl Queue {
82
102
} ,
83
103
84
104
state,
105
+ has_queue_microtask,
85
106
}
86
107
}
87
108
}
0 commit comments