Skip to content

Commit e0ffa8f

Browse files
authored
Update waitAsync signature to latest spec (#2362)
* Update `waitAsync` signature to latest spec Looks like Chrome implements this now and the spec has also changed since this was first implemented. Relatively easy to update the implementation though! Closes #2361 * Update UI tests for new stable Rust
1 parent eb0ff9b commit e0ffa8f

File tree

6 files changed

+100
-80
lines changed

6 files changed

+100
-80
lines changed

crates/futures/src/task/multithread.rs

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -115,68 +115,88 @@ impl Task {
115115
None => return,
116116
};
117117

118-
// Also the same as `singlethread.rs`, flag ourselves as ready to
119-
// receive a notification.
120-
let prev = self.atomic.state.swap(SLEEPING, SeqCst);
121-
debug_assert_eq!(prev, AWAKE);
122-
123-
let poll = {
124-
let mut cx = Context::from_waker(&self.waker);
125-
inner.future.as_mut().poll(&mut cx)
126-
};
127-
128-
match poll {
129-
// Same as `singlethread.rs` (noticing a pattern?) clean up
130-
// resources associated with the future ASAP.
131-
Poll::Ready(()) => {
132-
*borrow = None;
133-
}
134-
135-
// Unlike `singlethread.rs` we are responsible for ensuring there's
136-
// a closure to handle the notification that a Future is ready. In
137-
// the single-threaded case the notification itself enqueues work,
138-
// but in the multithreaded case we don't know what thread a
139-
// notification comes from so we need to ensure the current running
140-
// thread is the one that enqueues the work. To do that we execute
141-
// `Atomics.waitAsync`, creating a local Promise on our own thread
142-
// which will resolve once `Atomics.notify` is called.
143-
//
144-
// We could be in one of two states as we execute this:
145-
//
146-
// * `SLEEPING` - we'll get notified via `Atomics.notify`
147-
// and then this Promise will resolve.
148-
//
149-
// * `AWAKE` - the Promise will immediately be resolved and
150-
// we'll execute the work on the next microtask queue.
151-
Poll::Pending => {
152-
drop(wait_async(&self.atomic.state, SLEEPING).then(&inner.closure));
118+
loop {
119+
// Also the same as `singlethread.rs`, flag ourselves as ready to
120+
// receive a notification.
121+
let prev = self.atomic.state.swap(SLEEPING, SeqCst);
122+
debug_assert_eq!(prev, AWAKE);
123+
124+
let poll = {
125+
let mut cx = Context::from_waker(&self.waker);
126+
inner.future.as_mut().poll(&mut cx)
127+
};
128+
129+
match poll {
130+
// Same as `singlethread.rs` (noticing a pattern?) clean up
131+
// resources associated with the future ASAP.
132+
Poll::Ready(()) => {
133+
*borrow = None;
134+
}
135+
136+
// Unlike `singlethread.rs` we are responsible for ensuring there's
137+
// a closure to handle the notification that a Future is ready. In
138+
// the single-threaded case the notification itself enqueues work,
139+
// but in the multithreaded case we don't know what thread a
140+
// notification comes from so we need to ensure the current running
141+
// thread is the one that enqueues the work. To do that we execute
142+
// `Atomics.waitAsync`, creating a local Promise on our own thread
143+
// which will resolve once `Atomics.notify` is called.
144+
//
145+
// We could be in one of two states as we execute this:
146+
//
147+
// * `SLEEPING` - we'll get notified via `Atomics.notify`
148+
// and then this Promise will resolve.
149+
//
150+
// * `AWAKE` - the Promise will immediately be resolved and
151+
// we'll execute the work on the next microtask queue.
152+
Poll::Pending => {
153+
match wait_async(&self.atomic.state, SLEEPING) {
154+
Some(promise) => drop(promise.then(&inner.closure)),
155+
// our state has already changed so we can just do the work
156+
// again inline.
157+
None => continue,
158+
}
159+
}
153160
}
161+
break;
154162
}
155163
}
156164
}
157165

158-
fn wait_async(ptr: &AtomicI32, current_value: i32) -> js_sys::Promise {
159-
// If `Atomics.waitAsync` isn't defined (as it isn't defined anywhere today)
160-
// then we use our fallback, otherwise we use the native function.
166+
fn wait_async(ptr: &AtomicI32, current_value: i32) -> Option<js_sys::Promise> {
167+
// If `Atomics.waitAsync` isn't defined then we use our fallback, otherwise
168+
// we use the native function.
161169
return if Atomics::get_wait_async().is_undefined() {
162-
crate::task::wait_async_polyfill::wait_async(ptr, current_value)
170+
Some(crate::task::wait_async_polyfill::wait_async(
171+
ptr,
172+
current_value,
173+
))
163174
} else {
164175
let mem = wasm_bindgen::memory().unchecked_into::<js_sys::WebAssembly::Memory>();
165-
Atomics::wait_async(
166-
&mem.buffer(),
167-
ptr as *const AtomicI32 as i32 / 4,
168-
current_value,
169-
)
176+
let array = js_sys::Int32Array::new(&mem.buffer());
177+
let result = Atomics::wait_async(&array, ptr as *const AtomicI32 as i32 / 4, current_value);
178+
if result.async_() {
179+
Some(result.value())
180+
} else {
181+
None
182+
}
170183
};
171184

172185
#[wasm_bindgen]
173186
extern "C" {
174187
type Atomics;
188+
type WaitAsyncResult;
175189

176190
#[wasm_bindgen(static_method_of = Atomics, js_name = waitAsync)]
177-
fn wait_async(buf: &JsValue, index: i32, value: i32) -> js_sys::Promise;
191+
fn wait_async(buf: &js_sys::Int32Array, index: i32, value: i32) -> WaitAsyncResult;
178192

179193
#[wasm_bindgen(static_method_of = Atomics, js_name = waitAsync, getter)]
180194
fn get_wait_async() -> JsValue;
195+
196+
#[wasm_bindgen(method, getter, structural, js_name = async)]
197+
fn async_(this: &WaitAsyncResult) -> bool;
198+
199+
#[wasm_bindgen(method, getter, structural)]
200+
fn value(this: &WaitAsyncResult) -> js_sys::Promise;
181201
}
182202
}
Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,52 @@
1-
error[E0277]: the trait bound `std::result::Result<(), ()>: wasm_bindgen::__rt::IntoJsResult` is not satisfied
1+
error[E0277]: the trait bound `std::result::Result<(), ()>: IntoJsResult` is not satisfied
22
--> $DIR/async-errors.rs:30:1
33
|
44
30 | #[wasm_bindgen]
5-
| ^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::IntoJsResult` is not implemented for `std::result::Result<(), ()>`
5+
| ^^^^^^^^^^^^^^^ the trait `IntoJsResult` is not implemented for `std::result::Result<(), ()>`
66
|
77
= help: the following implementations were found:
8-
<std::result::Result<(), E> as wasm_bindgen::__rt::IntoJsResult>
9-
<std::result::Result<T, E> as wasm_bindgen::__rt::IntoJsResult>
10-
= note: required by `wasm_bindgen::__rt::IntoJsResult::into_js_result`
8+
<std::result::Result<(), E> as IntoJsResult>
9+
<std::result::Result<T, E> as IntoJsResult>
10+
= note: required by `into_js_result`
1111
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
1212

13-
error[E0277]: the trait bound `std::result::Result<(), BadType>: wasm_bindgen::__rt::IntoJsResult` is not satisfied
13+
error[E0277]: the trait bound `std::result::Result<(), BadType>: IntoJsResult` is not satisfied
1414
--> $DIR/async-errors.rs:32:1
1515
|
1616
32 | #[wasm_bindgen]
17-
| ^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::IntoJsResult` is not implemented for `std::result::Result<(), BadType>`
17+
| ^^^^^^^^^^^^^^^ the trait `IntoJsResult` is not implemented for `std::result::Result<(), BadType>`
1818
|
1919
= help: the following implementations were found:
20-
<std::result::Result<(), E> as wasm_bindgen::__rt::IntoJsResult>
21-
<std::result::Result<T, E> as wasm_bindgen::__rt::IntoJsResult>
22-
= note: required by `wasm_bindgen::__rt::IntoJsResult::into_js_result`
20+
<std::result::Result<(), E> as IntoJsResult>
21+
<std::result::Result<T, E> as IntoJsResult>
22+
= note: required by `into_js_result`
2323
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
2424

25-
error[E0277]: the trait bound `wasm_bindgen::JsValue: std::convert::From<BadType>` is not satisfied
25+
error[E0277]: the trait bound `wasm_bindgen::JsValue: From<BadType>` is not satisfied
2626
--> $DIR/async-errors.rs:34:1
2727
|
2828
34 | #[wasm_bindgen]
29-
| ^^^^^^^^^^^^^^^ the trait `std::convert::From<BadType>` is not implemented for `wasm_bindgen::JsValue`
29+
| ^^^^^^^^^^^^^^^ the trait `From<BadType>` is not implemented for `wasm_bindgen::JsValue`
3030
|
3131
= help: the following implementations were found:
32-
<wasm_bindgen::JsValue as std::convert::From<&'a T>>
33-
<wasm_bindgen::JsValue as std::convert::From<&'a std::string::String>>
34-
<wasm_bindgen::JsValue as std::convert::From<&'a str>>
35-
<wasm_bindgen::JsValue as std::convert::From<MyType>>
32+
<wasm_bindgen::JsValue as From<&'a String>>
33+
<wasm_bindgen::JsValue as From<&'a T>>
34+
<wasm_bindgen::JsValue as From<&'a str>>
35+
<wasm_bindgen::JsValue as From<MyType>>
3636
and 62 others
37-
= note: required because of the requirements on the impl of `std::convert::Into<wasm_bindgen::JsValue>` for `BadType`
38-
= note: required because of the requirements on the impl of `wasm_bindgen::__rt::IntoJsResult` for `BadType`
39-
= note: required by `wasm_bindgen::__rt::IntoJsResult::into_js_result`
37+
= note: required because of the requirements on the impl of `Into<wasm_bindgen::JsValue>` for `BadType`
38+
= note: required because of the requirements on the impl of `IntoJsResult` for `BadType`
39+
= note: required by `into_js_result`
4040
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
4141

42-
error[E0277]: the trait bound `std::result::Result<BadType, wasm_bindgen::JsValue>: wasm_bindgen::__rt::IntoJsResult` is not satisfied
42+
error[E0277]: the trait bound `std::result::Result<BadType, wasm_bindgen::JsValue>: IntoJsResult` is not satisfied
4343
--> $DIR/async-errors.rs:36:1
4444
|
4545
36 | #[wasm_bindgen]
46-
| ^^^^^^^^^^^^^^^ the trait `wasm_bindgen::__rt::IntoJsResult` is not implemented for `std::result::Result<BadType, wasm_bindgen::JsValue>`
46+
| ^^^^^^^^^^^^^^^ the trait `IntoJsResult` is not implemented for `std::result::Result<BadType, wasm_bindgen::JsValue>`
4747
|
4848
= help: the following implementations were found:
49-
<std::result::Result<(), E> as wasm_bindgen::__rt::IntoJsResult>
50-
<std::result::Result<T, E> as wasm_bindgen::__rt::IntoJsResult>
51-
= note: required by `wasm_bindgen::__rt::IntoJsResult::into_js_result`
49+
<std::result::Result<(), E> as IntoJsResult>
50+
<std::result::Result<T, E> as IntoJsResult>
51+
= note: required by `into_js_result`
5252
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: wasm_bindgen::convert::FromWasmAbi` is not satisfied
1+
error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: FromWasmAbi` is not satisfied
22
--> $DIR/missing-catch.rs:6:9
33
|
44
6 | pub fn foo() -> Result<JsValue, JsValue>;
5-
| ^^^ the trait `wasm_bindgen::convert::FromWasmAbi` is not implemented for `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>`
5+
| ^^^ the trait `FromWasmAbi` is not implemented for `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>`
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
1+
error[E0277]: the trait bound `String: std::marker::Copy` is not satisfied
22
--> $DIR/pub-not-copy.rs:5:16
33
|
44
3 | #[wasm_bindgen]
5-
| --------------- required by this bound in `__wbg_get_a_field::assert_copy`
5+
| --------------- required by this bound in `assert_copy`
66
4 | pub struct A {
77
5 | pub field: String,
8-
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
8+
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `String`

crates/macro/ui-tests/start-function.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, ()>: w
1818
|
1919
= help: the following implementations were found:
2020
<std::result::Result<(), E> as wasm_bindgen::__rt::Start>
21-
= note: required by `wasm_bindgen::__rt::Start::start`
21+
= note: required by `start`
2222
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
2323

2424
error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: wasm_bindgen::__rt::Start` is not satisfied
@@ -29,7 +29,7 @@ error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_b
2929
|
3030
= help: the following implementations were found:
3131
<std::result::Result<(), E> as wasm_bindgen::__rt::Start>
32-
= note: required by `wasm_bindgen::__rt::Start::start`
32+
= note: required by `start`
3333
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
3434

3535
error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, ()>: wasm_bindgen::__rt::Start` is not satisfied
@@ -40,7 +40,7 @@ error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, ()>: w
4040
|
4141
= help: the following implementations were found:
4242
<std::result::Result<(), E> as wasm_bindgen::__rt::Start>
43-
= note: required by `wasm_bindgen::__rt::Start::start`
43+
= note: required by `start`
4444
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
4545

4646
error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: wasm_bindgen::__rt::Start` is not satisfied
@@ -51,5 +51,5 @@ error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_b
5151
|
5252
= help: the following implementations were found:
5353
<std::result::Result<(), E> as wasm_bindgen::__rt::Start>
54-
= note: required by `wasm_bindgen::__rt::Start::start`
54+
= note: required by `start`
5555
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
error[E0277]: the trait bound `A: wasm_bindgen::convert::IntoWasmAbi` is not satisfied
1+
error[E0277]: the trait bound `A: IntoWasmAbi` is not satisfied
22
--> $DIR/traits-not-implemented.rs:8:12
33
|
44
8 | pub fn foo(a: A);
5-
| ^^^ the trait `wasm_bindgen::convert::IntoWasmAbi` is not implemented for `A`
5+
| ^^^ the trait `IntoWasmAbi` is not implemented for `A`

0 commit comments

Comments
 (0)