This PR contains a few major improvements:
* Code duplication has been removed.
* Everything has been refactored so that the implementation is much easier to understand.
* `future_to_promise` is now implemented with `spawn_local` rather than the other way around (this means `spawn_local` is faster since it doesn't need to create an unneeded `Promise`).
* Both the single threaded and multi threaded executors have been rewritten from scratch:
* They only create 1-2 allocations in Rust per Task, and all of the allocations happen when the Task is created.
* The singlethreaded executor creates 1 Promise per tick, rather than 1 Promise per tick per Task.
* Both executors do *not* create `Closure`s during polling, instead all needed `Closure`s are created ahead of time.
* Both executors now have correct behavior with regard to spurious wakeups and waking up during the call to `poll`.
* Both executors cache the `Waker` so it doesn't need to be recreated all the time.
I believe both executors are now optimal in terms of both Rust and JS performance.
This commit defaults all crates in-tree to use `std::future` by default
and none of them support the crates.io `futures` 0.1 crate any more.
This is a breaking change for `wasm-bindgen-futures` and
`wasm-bindgen-test` so they've both received a major version bump to
reflect the new defaults. Historical versions of these crates should
continue to work if necessary, but they won't receive any more
maintenance after this is merged.
The movement here liberally uses `async`/`await` to remove the need for
using any combinators on the `Future` trait. As a result many of the
crates now rely on a much more recent version of the compiler,
especially to run tests.
The `wasm-bindgen-futures` crate was updated to remove all of its
futures-related dependencies and purely use `std::future`, hopefully
improving its compatibility by not having any version compat
considerations over time. The implementations of the executors here are
relatively simple and only delve slightly into the `RawWaker` business
since there are no other stable APIs in `std::task` for wrapping these.
This commit also adds support for:
#[wasm_bindgen_test]
async fn foo() {
// ...
}
where previously you needed to pass `(async)` now that's inferred
because it's an `async fn`.
Closes#1558Closes#1695
Previously whenever a future readiness notification came in we would
immediately start polling a future. This ends up having two downsides,
however:
* First, the stack depth may run a risk of getting blown. There's no
recursion limit to defer execution to later, which means that if
futures are always ready we'll keep making the stack deeper.
* Second, and more worrisome in the near term, apparently future
adapaters in the `futures` crate (namely the unsync oneshot channel)
doesn't actually work if you immediately poll on readiness. This may
or may not be a bug in the `futures` crate but it's good to fix it
here anyway.
As a result whenever a future is ready to get polled again we defer its
polling to the next turn of the event loop. This should ensure that the
current call stack is always drained and we're effectively enqueueing
the future to be polled in the near future.