Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/wasm-bindgen-futures/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/wasm-bindgen-futures/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"2c0311031c321b78de96c7890839e6b31edf0ffaa2d14438162fd9f77fdc6cae","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"c5b95b239927e327ff70b25c52c7347f8b37cefea85da332f02a25d9f90c59b7","src/lib.rs":"bc8147fab508a74f1b9a4e9900ff1bc0e01179e2572ea99e5ebfc90921d336f7","src/queue.rs":"4cad1d049a75a20ccf5423e69762ca0aaff736b5879f52251203f153d88fe1d9","src/stream.rs":"5e83d72eb8c339ef0208c367da0004160c9f567ac744bc66e8e49de9589a1825","src/task/multithread.rs":"d25b63e2f0679bce9e79aa85b4c94afb6ba656118f7e813b84eb96f384448bd0","src/task/singlethread.rs":"72b9e40bfeb50e064f1825bfaaae86be3d736ccb23d6f5e0f51517d9af9a972e","src/task/wait_async_polyfill.rs":"6245e6c6040b36025aed6b2d880866ede6e7bd97ec68676d0a754c09916f440c","src/task/worker.js":"1f1b207b7f45925d8c50f51538d3c23caf14073080bfe6e6bc64a3689b93db78","tests/tests.rs":"2355cb43c2348f5889ea3887c7452544f4052b45c1f300ba540ce0546fb1c833"},"package":"76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"}
|
||||
58
third-party/vendor/wasm-bindgen-futures/Cargo.toml
vendored
Normal file
58
third-party/vendor/wasm-bindgen-futures/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.57"
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
description = "Bridging the gap between Rust Futures and JavaScript Promises"
|
||||
homepage = "https://rustwasm.github.io/wasm-bindgen/"
|
||||
documentation = "https://docs.rs/wasm-bindgen-futures"
|
||||
readme = "./README.md"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/futures"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies.futures-core]
|
||||
version = "0.3.8"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.js-sys]
|
||||
version = "0.3.69"
|
||||
|
||||
[dependencies.wasm-bindgen]
|
||||
version = "0.2.92"
|
||||
|
||||
[features]
|
||||
futures-core-03-stream = ["futures-core"]
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.futures-channel-preview]
|
||||
version = "0.3.0-alpha.18"
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.futures-lite]
|
||||
version = "1.11.3"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test]
|
||||
version = "0.3.42"
|
||||
|
||||
[target."cfg(target_feature = \"atomics\")".dependencies.web-sys]
|
||||
version = "0.3.24"
|
||||
features = [
|
||||
"MessageEvent",
|
||||
"Worker",
|
||||
]
|
||||
201
third-party/vendor/wasm-bindgen-futures/LICENSE-APACHE
vendored
Normal file
201
third-party/vendor/wasm-bindgen-futures/LICENSE-APACHE
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
third-party/vendor/wasm-bindgen-futures/LICENSE-MIT
vendored
Normal file
25
third-party/vendor/wasm-bindgen-futures/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014 Alex Crichton
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
16
third-party/vendor/wasm-bindgen-futures/README.md
vendored
Normal file
16
third-party/vendor/wasm-bindgen-futures/README.md
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# `wasm-bindgen-futures`
|
||||
|
||||
[API Documentation][docs]
|
||||
|
||||
This crate bridges the gap between a Rust `Future` and a JavaScript
|
||||
`Promise`. It provides two conversions:
|
||||
|
||||
1. From a JavaScript `Promise` into a Rust `Future`.
|
||||
2. From a Rust `Future` into a JavaScript `Promise`.
|
||||
|
||||
Additionally under the feature flag `futures-core-03-stream` there is experimental
|
||||
support for `AsyncIterator` to `Stream` conversion.
|
||||
|
||||
See the [API documentation][docs] for more info.
|
||||
|
||||
[docs]: https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/
|
||||
232
third-party/vendor/wasm-bindgen-futures/src/lib.rs
vendored
Normal file
232
third-party/vendor/wasm-bindgen-futures/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
//! Converting between JavaScript `Promise`s to Rust `Future`s.
|
||||
//!
|
||||
//! This crate provides a bridge for working with JavaScript `Promise` types as
|
||||
//! a Rust `Future`, and similarly contains utilities to turn a rust `Future`
|
||||
//! into a JavaScript `Promise`. This can be useful when working with
|
||||
//! asynchronous or otherwise blocking work in Rust (wasm), and provides the
|
||||
//! ability to interoperate with JavaScript events and JavaScript I/O
|
||||
//! primitives.
|
||||
//!
|
||||
//! There are three main interfaces in this crate currently:
|
||||
//!
|
||||
//! 1. [**`JsFuture`**](./struct.JsFuture.html)
|
||||
//!
|
||||
//! A type that is constructed with a `Promise` and can then be used as a
|
||||
//! `Future<Output = Result<JsValue, JsValue>>`. This Rust future will resolve
|
||||
//! or reject with the value coming out of the `Promise`.
|
||||
//!
|
||||
//! 2. [**`future_to_promise`**](./fn.future_to_promise.html)
|
||||
//!
|
||||
//! Converts a Rust `Future<Output = Result<JsValue, JsValue>>` into a
|
||||
//! JavaScript `Promise`. The future's result will translate to either a
|
||||
//! resolved or rejected `Promise` in JavaScript.
|
||||
//!
|
||||
//! 3. [**`spawn_local`**](./fn.spawn_local.html)
|
||||
//!
|
||||
//! Spawns a `Future<Output = ()>` on the current thread. This is the
|
||||
//! best way to run a `Future` in Rust without sending it to JavaScript.
|
||||
//!
|
||||
//! These three items should provide enough of a bridge to interoperate the two
|
||||
//! systems and make sure that Rust/JavaScript can work together with
|
||||
//! asynchronous and I/O work.
|
||||
|
||||
#![cfg_attr(target_feature = "atomics", feature(stdarch_wasm_atomic_wait))]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use js_sys::Promise;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod queue;
|
||||
#[cfg(feature = "futures-core-03-stream")]
|
||||
pub mod stream;
|
||||
|
||||
pub use js_sys;
|
||||
pub use wasm_bindgen;
|
||||
|
||||
mod task {
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_feature = "atomics")] {
|
||||
mod wait_async_polyfill;
|
||||
mod multithread;
|
||||
pub(crate) use multithread::*;
|
||||
|
||||
} else {
|
||||
mod singlethread;
|
||||
pub(crate) use singlethread::*;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs a Rust `Future` on the current thread.
|
||||
///
|
||||
/// The `future` must be `'static` because it will be scheduled
|
||||
/// to run in the background and cannot contain any stack references.
|
||||
///
|
||||
/// The `future` will always be run on the next microtask tick even if it
|
||||
/// immediately returns `Poll::Ready`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function has the same panic behavior as `future_to_promise`.
|
||||
#[inline]
|
||||
pub fn spawn_local<F>(future: F)
|
||||
where
|
||||
F: Future<Output = ()> + 'static,
|
||||
{
|
||||
task::Task::spawn(Box::pin(future));
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
result: Option<Result<JsValue, JsValue>>,
|
||||
task: Option<Waker>,
|
||||
callbacks: Option<(Closure<dyn FnMut(JsValue)>, Closure<dyn FnMut(JsValue)>)>,
|
||||
}
|
||||
|
||||
/// A Rust `Future` backed by a JavaScript `Promise`.
|
||||
///
|
||||
/// This type is constructed with a JavaScript `Promise` object and translates
|
||||
/// it to a Rust `Future`. This type implements the `Future` trait from the
|
||||
/// `futures` crate and will either succeed or fail depending on what happens
|
||||
/// with the JavaScript `Promise`.
|
||||
///
|
||||
/// Currently this type is constructed with `JsFuture::from`.
|
||||
pub struct JsFuture {
|
||||
inner: Rc<RefCell<Inner>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for JsFuture {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "JsFuture {{ ... }}")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Promise> for JsFuture {
|
||||
fn from(js: Promise) -> JsFuture {
|
||||
// Use the `then` method to schedule two callbacks, one for the
|
||||
// resolved value and one for the rejected value. We're currently
|
||||
// assuming that JS engines will unconditionally invoke precisely one of
|
||||
// these callbacks, no matter what.
|
||||
//
|
||||
// Ideally we'd have a way to cancel the callbacks getting invoked and
|
||||
// free up state ourselves when this `JsFuture` is dropped. We don't
|
||||
// have that, though, and one of the callbacks is likely always going to
|
||||
// be invoked.
|
||||
//
|
||||
// As a result we need to make sure that no matter when the callbacks
|
||||
// are invoked they are valid to be called at any time, which means they
|
||||
// have to be self-contained. Through the `Closure::once` and some
|
||||
// `Rc`-trickery we can arrange for both instances of `Closure`, and the
|
||||
// `Rc`, to all be destroyed once the first one is called.
|
||||
let state = Rc::new(RefCell::new(Inner {
|
||||
result: None,
|
||||
task: None,
|
||||
callbacks: None,
|
||||
}));
|
||||
|
||||
fn finish(state: &RefCell<Inner>, val: Result<JsValue, JsValue>) {
|
||||
let task = {
|
||||
let mut state = state.borrow_mut();
|
||||
debug_assert!(state.callbacks.is_some());
|
||||
debug_assert!(state.result.is_none());
|
||||
|
||||
// First up drop our closures as they'll never be invoked again and
|
||||
// this is our chance to clean up their state.
|
||||
drop(state.callbacks.take());
|
||||
|
||||
// Next, store the value into the internal state.
|
||||
state.result = Some(val);
|
||||
state.task.take()
|
||||
};
|
||||
|
||||
// And then finally if any task was waiting on the value wake it up and
|
||||
// let them know it's there.
|
||||
if let Some(task) = task {
|
||||
task.wake()
|
||||
}
|
||||
}
|
||||
|
||||
let resolve = {
|
||||
let state = state.clone();
|
||||
Closure::once(move |val| finish(&state, Ok(val)))
|
||||
};
|
||||
|
||||
let reject = {
|
||||
let state = state.clone();
|
||||
Closure::once(move |val| finish(&state, Err(val)))
|
||||
};
|
||||
|
||||
let _ = js.then2(&resolve, &reject);
|
||||
|
||||
state.borrow_mut().callbacks = Some((resolve, reject));
|
||||
|
||||
JsFuture { inner: state }
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for JsFuture {
|
||||
type Output = Result<JsValue, JsValue>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
// If our value has come in then we return it...
|
||||
if let Some(val) = inner.result.take() {
|
||||
return Poll::Ready(val);
|
||||
}
|
||||
|
||||
// ... otherwise we arrange ourselves to get woken up once the value
|
||||
// does come in
|
||||
inner.task = Some(cx.waker().clone());
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a Rust `Future` into a JavaScript `Promise`.
|
||||
///
|
||||
/// This function will take any future in Rust and schedule it to be executed,
|
||||
/// returning a JavaScript `Promise` which can then be passed to JavaScript.
|
||||
///
|
||||
/// The `future` must be `'static` because it will be scheduled to run in the
|
||||
/// background and cannot contain any stack references.
|
||||
///
|
||||
/// The returned `Promise` will be resolved or rejected when the future completes,
|
||||
/// depending on whether it finishes with `Ok` or `Err`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Note that in wasm panics are currently translated to aborts, but "abort" in
|
||||
/// this case means that a JavaScript exception is thrown. The wasm module is
|
||||
/// still usable (likely erroneously) after Rust panics.
|
||||
///
|
||||
/// If the `future` provided panics then the returned `Promise` **will not
|
||||
/// resolve**. Instead it will be a leaked promise. This is an unfortunate
|
||||
/// limitation of wasm currently that's hoped to be fixed one day!
|
||||
pub fn future_to_promise<F>(future: F) -> Promise
|
||||
where
|
||||
F: Future<Output = Result<JsValue, JsValue>> + 'static,
|
||||
{
|
||||
let mut future = Some(future);
|
||||
|
||||
Promise::new(&mut |resolve, reject| {
|
||||
let future = future.take().unwrap_throw();
|
||||
|
||||
spawn_local(async move {
|
||||
match future.await {
|
||||
Ok(val) => {
|
||||
resolve.call1(&JsValue::undefined(), &val).unwrap_throw();
|
||||
}
|
||||
Err(val) => {
|
||||
reject.call1(&JsValue::undefined(), &val).unwrap_throw();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
112
third-party/vendor/wasm-bindgen-futures/src/queue.rs
vendored
Normal file
112
third-party/vendor/wasm-bindgen-futures/src/queue.rs
vendored
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
use js_sys::Promise;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen]
|
||||
fn queueMicrotask(closure: &Closure<dyn FnMut(JsValue)>);
|
||||
|
||||
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
|
||||
// a future "at the right time".
|
||||
tasks: RefCell<VecDeque<Rc<crate::task::Task>>>,
|
||||
|
||||
// This flag indicates whether we've scheduled `run_all` to run in the future.
|
||||
// This is used to ensure that it's only scheduled once.
|
||||
is_scheduled: Cell<bool>,
|
||||
}
|
||||
|
||||
impl QueueState {
|
||||
fn run_all(&self) {
|
||||
// "consume" the schedule
|
||||
let _was_scheduled = self.is_scheduled.replace(false);
|
||||
debug_assert!(_was_scheduled);
|
||||
|
||||
// Stop when all tasks that have been scheduled before this tick have been run.
|
||||
// Tasks that are scheduled while running tasks will run on the next tick.
|
||||
let mut task_count_left = self.tasks.borrow().len();
|
||||
while task_count_left > 0 {
|
||||
task_count_left -= 1;
|
||||
let task = match self.tasks.borrow_mut().pop_front() {
|
||||
Some(task) => task,
|
||||
None => break,
|
||||
};
|
||||
task.run();
|
||||
}
|
||||
|
||||
// All of the Tasks have been run, so it's now possible to schedule the
|
||||
// next tick again
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Queue {
|
||||
state: Rc<QueueState>,
|
||||
promise: Promise,
|
||||
closure: Closure<dyn FnMut(JsValue)>,
|
||||
has_queue_microtask: bool,
|
||||
}
|
||||
|
||||
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);
|
||||
// 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) {
|
||||
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
|
||||
pub(crate) fn push_task(&self, task: Rc<crate::task::Task>) {
|
||||
// It would make sense to run this task on the same tick. For now, we
|
||||
// make the simplifying choice of always scheduling tasks for a future tick.
|
||||
self.schedule_task(task)
|
||||
}
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
fn new() -> Self {
|
||||
let state = Rc::new(QueueState {
|
||||
is_scheduled: Cell::new(false),
|
||||
tasks: RefCell::new(VecDeque::new()),
|
||||
});
|
||||
|
||||
let has_queue_microtask = js_sys::global()
|
||||
.unchecked_into::<Global>()
|
||||
.hasQueueMicrotask()
|
||||
.is_function();
|
||||
|
||||
Self {
|
||||
promise: Promise::resolve(&JsValue::undefined()),
|
||||
|
||||
closure: {
|
||||
let state = Rc::clone(&state);
|
||||
|
||||
// This closure will only be called on the next microtask event
|
||||
// tick
|
||||
Closure::new(move |_| state.run_all())
|
||||
},
|
||||
|
||||
state,
|
||||
has_queue_microtask,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub(crate) static QUEUE: Queue = Queue::new();
|
||||
}
|
||||
81
third-party/vendor/wasm-bindgen-futures/src/stream.rs
vendored
Normal file
81
third-party/vendor/wasm-bindgen-futures/src/stream.rs
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
//! Converting JavaScript `AsyncIterator`s to Rust `Stream`s.
|
||||
//!
|
||||
//! Analogous to the promise to future conversion, this module allows
|
||||
//! turning objects implementing the async iterator protocol into `Stream`s
|
||||
//! that produce values that can be awaited from.
|
||||
//!
|
||||
|
||||
use crate::JsFuture;
|
||||
use core::future::Future;
|
||||
use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
use futures_core::stream::Stream;
|
||||
use js_sys::{AsyncIterator, IteratorNext};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
/// A `Stream` that yields values from an underlying `AsyncIterator`.
|
||||
pub struct JsStream {
|
||||
iter: AsyncIterator,
|
||||
next: Option<JsFuture>,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl JsStream {
|
||||
fn next_future(&self) -> Result<JsFuture, JsValue> {
|
||||
self.iter.next().map(JsFuture::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AsyncIterator> for JsStream {
|
||||
fn from(iter: AsyncIterator) -> Self {
|
||||
JsStream {
|
||||
iter,
|
||||
next: None,
|
||||
done: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for JsStream {
|
||||
type Item = Result<JsValue, JsValue>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
if self.done {
|
||||
return Poll::Ready(None);
|
||||
}
|
||||
|
||||
let future = match self.next.as_mut() {
|
||||
Some(val) => val,
|
||||
None => match self.next_future() {
|
||||
Ok(val) => {
|
||||
self.next = Some(val);
|
||||
self.next.as_mut().unwrap()
|
||||
}
|
||||
Err(e) => {
|
||||
self.done = true;
|
||||
return Poll::Ready(Some(Err(e)));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match Pin::new(future).poll(cx) {
|
||||
Poll::Ready(res) => match res {
|
||||
Ok(iter_next) => {
|
||||
let next = iter_next.unchecked_into::<IteratorNext>();
|
||||
if next.done() {
|
||||
self.done = true;
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
self.next.take();
|
||||
Poll::Ready(Some(Ok(next.value())))
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
self.done = true;
|
||||
Poll::Ready(Some(Err(e)))
|
||||
}
|
||||
},
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
201
third-party/vendor/wasm-bindgen-futures/src/task/multithread.rs
vendored
Normal file
201
third-party/vendor/wasm-bindgen-futures/src/task/multithread.rs
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
const SLEEPING: i32 = 0;
|
||||
const AWAKE: i32 = 1;
|
||||
|
||||
struct AtomicWaker {
|
||||
state: AtomicI32,
|
||||
}
|
||||
|
||||
impl AtomicWaker {
|
||||
fn new() -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
state: AtomicI32::new(AWAKE),
|
||||
})
|
||||
}
|
||||
|
||||
fn wake_by_ref(&self) {
|
||||
// If we're already AWAKE then we previously notified and there's
|
||||
// nothing to do...
|
||||
match self.state.swap(AWAKE, SeqCst) {
|
||||
AWAKE => return,
|
||||
other => debug_assert_eq!(other, SLEEPING),
|
||||
}
|
||||
|
||||
// ... otherwise we execute the native `notify` instruction to wake up
|
||||
// the corresponding `waitAsync` that was waiting for the transition
|
||||
// from SLEEPING to AWAKE.
|
||||
unsafe {
|
||||
core::arch::wasm32::memory_atomic_notify(
|
||||
&self.state as *const AtomicI32 as *mut i32,
|
||||
1, // Number of threads to notify
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as the singlethread module, this creates a standard library
|
||||
/// `RawWaker`. We could use `futures_util::task::ArcWake` but it's small
|
||||
/// enough that we just inline it for now.
|
||||
unsafe fn into_raw_waker(this: Arc<Self>) -> RawWaker {
|
||||
unsafe fn raw_clone(ptr: *const ()) -> RawWaker {
|
||||
let ptr = ManuallyDrop::new(Arc::from_raw(ptr as *const AtomicWaker));
|
||||
AtomicWaker::into_raw_waker((*ptr).clone())
|
||||
}
|
||||
|
||||
unsafe fn raw_wake(ptr: *const ()) {
|
||||
let ptr = Arc::from_raw(ptr as *const AtomicWaker);
|
||||
AtomicWaker::wake_by_ref(&ptr);
|
||||
}
|
||||
|
||||
unsafe fn raw_wake_by_ref(ptr: *const ()) {
|
||||
let ptr = ManuallyDrop::new(Arc::from_raw(ptr as *const AtomicWaker));
|
||||
AtomicWaker::wake_by_ref(&ptr);
|
||||
}
|
||||
|
||||
unsafe fn raw_drop(ptr: *const ()) {
|
||||
drop(Arc::from_raw(ptr as *const AtomicWaker));
|
||||
}
|
||||
|
||||
const VTABLE: RawWakerVTable =
|
||||
RawWakerVTable::new(raw_clone, raw_wake, raw_wake_by_ref, raw_drop);
|
||||
|
||||
RawWaker::new(Arc::into_raw(this) as *const (), &VTABLE)
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
future: Pin<Box<dyn Future<Output = ()> + 'static>>,
|
||||
closure: Closure<dyn FnMut(JsValue)>,
|
||||
}
|
||||
|
||||
pub(crate) struct Task {
|
||||
atomic: Arc<AtomicWaker>,
|
||||
waker: Waker,
|
||||
// See `singlethread.rs` for why this is an internal `Option`.
|
||||
inner: RefCell<Option<Inner>>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub(crate) fn spawn(future: Pin<Box<dyn Future<Output = ()> + 'static>>) {
|
||||
let atomic = AtomicWaker::new();
|
||||
let waker = unsafe { Waker::from_raw(AtomicWaker::into_raw_waker(atomic.clone())) };
|
||||
let this = Rc::new(Task {
|
||||
atomic,
|
||||
waker,
|
||||
inner: RefCell::new(None),
|
||||
});
|
||||
|
||||
let closure = {
|
||||
let this = Rc::clone(&this);
|
||||
Closure::new(move |_| this.run())
|
||||
};
|
||||
*this.inner.borrow_mut() = Some(Inner { future, closure });
|
||||
|
||||
// Queue up the Future's work to happen on the next microtask tick.
|
||||
crate::queue::QUEUE.with(move |queue| queue.schedule_task(this));
|
||||
}
|
||||
|
||||
pub(crate) fn run(&self) {
|
||||
let mut borrow = self.inner.borrow_mut();
|
||||
|
||||
// Same as `singlethread.rs`, handle spurious wakeups happening after we
|
||||
// finished.
|
||||
let inner = match borrow.as_mut() {
|
||||
Some(inner) => inner,
|
||||
None => return,
|
||||
};
|
||||
|
||||
loop {
|
||||
// Also the same as `singlethread.rs`, flag ourselves as ready to
|
||||
// receive a notification.
|
||||
let prev = self.atomic.state.swap(SLEEPING, SeqCst);
|
||||
debug_assert_eq!(prev, AWAKE);
|
||||
|
||||
let poll = {
|
||||
let mut cx = Context::from_waker(&self.waker);
|
||||
inner.future.as_mut().poll(&mut cx)
|
||||
};
|
||||
|
||||
match poll {
|
||||
// Same as `singlethread.rs` (noticing a pattern?) clean up
|
||||
// resources associated with the future ASAP.
|
||||
Poll::Ready(()) => {
|
||||
*borrow = None;
|
||||
}
|
||||
|
||||
// Unlike `singlethread.rs` we are responsible for ensuring there's
|
||||
// a closure to handle the notification that a Future is ready. In
|
||||
// the single-threaded case the notification itself enqueues work,
|
||||
// but in the multithreaded case we don't know what thread a
|
||||
// notification comes from so we need to ensure the current running
|
||||
// thread is the one that enqueues the work. To do that we execute
|
||||
// `Atomics.waitAsync`, creating a local Promise on our own thread
|
||||
// which will resolve once `Atomics.notify` is called.
|
||||
//
|
||||
// We could be in one of two states as we execute this:
|
||||
//
|
||||
// * `SLEEPING` - we'll get notified via `Atomics.notify`
|
||||
// and then this Promise will resolve.
|
||||
//
|
||||
// * `AWAKE` - the Promise will immediately be resolved and
|
||||
// we'll execute the work on the next microtask queue.
|
||||
Poll::Pending => {
|
||||
match wait_async(&self.atomic.state, SLEEPING) {
|
||||
Some(promise) => drop(promise.then(&inner.closure)),
|
||||
// our state has already changed so we can just do the work
|
||||
// again inline.
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wait_async(ptr: &AtomicI32, current_value: i32) -> Option<js_sys::Promise> {
|
||||
// If `Atomics.waitAsync` isn't defined then we use our fallback, otherwise
|
||||
// we use the native function.
|
||||
return if Atomics::get_wait_async().is_undefined() {
|
||||
Some(crate::task::wait_async_polyfill::wait_async(
|
||||
ptr,
|
||||
current_value,
|
||||
))
|
||||
} else {
|
||||
let mem = wasm_bindgen::memory().unchecked_into::<js_sys::WebAssembly::Memory>();
|
||||
let array = js_sys::Int32Array::new(&mem.buffer());
|
||||
let result = Atomics::wait_async(&array, ptr as *const AtomicI32 as i32 / 4, current_value);
|
||||
if result.async_() {
|
||||
Some(result.value())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type Atomics;
|
||||
type WaitAsyncResult;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Atomics, js_name = waitAsync)]
|
||||
fn wait_async(buf: &js_sys::Int32Array, index: i32, value: i32) -> WaitAsyncResult;
|
||||
|
||||
#[wasm_bindgen(static_method_of = Atomics, js_name = waitAsync, getter)]
|
||||
fn get_wait_async() -> JsValue;
|
||||
|
||||
#[wasm_bindgen(method, getter, structural, js_name = async)]
|
||||
fn async_(this: &WaitAsyncResult) -> bool;
|
||||
|
||||
#[wasm_bindgen(method, getter, structural)]
|
||||
fn value(this: &WaitAsyncResult) -> js_sys::Promise;
|
||||
}
|
||||
}
|
||||
130
third-party/vendor/wasm-bindgen-futures/src/task/singlethread.rs
vendored
Normal file
130
third-party/vendor/wasm-bindgen-futures/src/task/singlethread.rs
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::future::Future;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, RawWaker, RawWakerVTable, Waker};
|
||||
|
||||
struct Inner {
|
||||
future: Pin<Box<dyn Future<Output = ()> + 'static>>,
|
||||
waker: Waker,
|
||||
}
|
||||
|
||||
pub(crate) struct Task {
|
||||
// The actual Future that we're executing as part of this task.
|
||||
//
|
||||
// This is an Option so that the Future can be immediately dropped when it's
|
||||
// finished
|
||||
inner: RefCell<Option<Inner>>,
|
||||
|
||||
// This is used to ensure that the Task will only be queued once
|
||||
is_queued: Cell<bool>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub(crate) fn spawn(future: Pin<Box<dyn Future<Output = ()> + 'static>>) {
|
||||
let this = Rc::new(Self {
|
||||
inner: RefCell::new(None),
|
||||
is_queued: Cell::new(true),
|
||||
});
|
||||
|
||||
let waker = unsafe { Waker::from_raw(Task::into_raw_waker(Rc::clone(&this))) };
|
||||
|
||||
*this.inner.borrow_mut() = Some(Inner { future, waker });
|
||||
|
||||
crate::queue::QUEUE.with(|queue| queue.schedule_task(this));
|
||||
}
|
||||
|
||||
fn force_wake(this: Rc<Self>) {
|
||||
crate::queue::QUEUE.with(|queue| {
|
||||
queue.push_task(this);
|
||||
});
|
||||
}
|
||||
|
||||
fn wake(this: Rc<Self>) {
|
||||
// If we've already been placed on the run queue then there's no need to
|
||||
// requeue ourselves since we're going to run at some point in the
|
||||
// future anyway.
|
||||
if this.is_queued.replace(true) {
|
||||
return;
|
||||
}
|
||||
|
||||
Self::force_wake(this);
|
||||
}
|
||||
|
||||
fn wake_by_ref(this: &Rc<Self>) {
|
||||
// If we've already been placed on the run queue then there's no need to
|
||||
// requeue ourselves since we're going to run at some point in the
|
||||
// future anyway.
|
||||
if this.is_queued.replace(true) {
|
||||
return;
|
||||
}
|
||||
|
||||
Self::force_wake(Rc::clone(this));
|
||||
}
|
||||
|
||||
/// Creates a standard library `RawWaker` from an `Rc` of ourselves.
|
||||
///
|
||||
/// Note that in general this is wildly unsafe because everything with
|
||||
/// Futures requires `Sync` + `Send` with regard to Wakers. For wasm,
|
||||
/// however, everything is guaranteed to be singlethreaded (since we're
|
||||
/// compiled without the `atomics` feature) so we "safely lie" and say our
|
||||
/// `Rc` pointer is good enough.
|
||||
///
|
||||
/// The implementation is based off of futures::task::ArcWake
|
||||
unsafe fn into_raw_waker(this: Rc<Self>) -> RawWaker {
|
||||
unsafe fn raw_clone(ptr: *const ()) -> RawWaker {
|
||||
let ptr = ManuallyDrop::new(Rc::from_raw(ptr as *const Task));
|
||||
Task::into_raw_waker(Rc::clone(&ptr))
|
||||
}
|
||||
|
||||
unsafe fn raw_wake(ptr: *const ()) {
|
||||
let ptr = Rc::from_raw(ptr as *const Task);
|
||||
Task::wake(ptr);
|
||||
}
|
||||
|
||||
unsafe fn raw_wake_by_ref(ptr: *const ()) {
|
||||
let ptr = ManuallyDrop::new(Rc::from_raw(ptr as *const Task));
|
||||
Task::wake_by_ref(&ptr);
|
||||
}
|
||||
|
||||
unsafe fn raw_drop(ptr: *const ()) {
|
||||
drop(Rc::from_raw(ptr as *const Task));
|
||||
}
|
||||
|
||||
static VTABLE: RawWakerVTable =
|
||||
RawWakerVTable::new(raw_clone, raw_wake, raw_wake_by_ref, raw_drop);
|
||||
|
||||
RawWaker::new(Rc::into_raw(this) as *const (), &VTABLE)
|
||||
}
|
||||
|
||||
pub(crate) fn run(&self) {
|
||||
let mut borrow = self.inner.borrow_mut();
|
||||
|
||||
// Wakeups can come in after a Future has finished and been destroyed,
|
||||
// so handle this gracefully by just ignoring the request to run.
|
||||
let inner = match borrow.as_mut() {
|
||||
Some(inner) => inner,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Ensure that if poll calls `waker.wake()` we can get enqueued back on
|
||||
// the run queue.
|
||||
self.is_queued.set(false);
|
||||
|
||||
let poll = {
|
||||
let mut cx = Context::from_waker(&inner.waker);
|
||||
inner.future.as_mut().poll(&mut cx)
|
||||
};
|
||||
|
||||
// If a future has finished (`Ready`) then clean up resources associated
|
||||
// with the future ASAP. This ensures that we don't keep anything extra
|
||||
// alive in-memory by accident. Our own struct, `Rc<Task>` won't
|
||||
// actually go away until all wakers referencing us go away, which may
|
||||
// take quite some time, so ensure that the heaviest of resources are
|
||||
// released early.
|
||||
if poll.is_ready() {
|
||||
*borrow = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
third-party/vendor/wasm-bindgen-futures/src/task/wait_async_polyfill.rs
vendored
Normal file
91
third-party/vendor/wasm-bindgen-futures/src/task/wait_async_polyfill.rs
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
//!
|
||||
//! The polyfill was kindly borrowed from https://github.com/tc39/proposal-atomics-wait-async
|
||||
//! and ported to Rust
|
||||
//!
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Author: Lars T Hansen, lhansen@mozilla.com
|
||||
*/
|
||||
|
||||
/* Polyfill for Atomics.waitAsync() for web browsers.
|
||||
*
|
||||
* Any kind of agent that is able to create a new Worker can use this polyfill.
|
||||
*
|
||||
* Load this file in all agents that will use Atomics.waitAsync.
|
||||
*
|
||||
* Agents that don't call Atomics.waitAsync need do nothing special.
|
||||
*
|
||||
* Any kind of agent can wake another agent that is sleeping in
|
||||
* Atomics.waitAsync by just calling Atomics.wake for the location being slept
|
||||
* on, as normal.
|
||||
*
|
||||
* The implementation is not completely faithful to the proposed semantics: in
|
||||
* the case where an agent first asyncWaits and then waits on the same location:
|
||||
* when it is woken, the two waits will be woken in order, while in the real
|
||||
* semantics, the sync wait will be woken first.
|
||||
*
|
||||
* In this polyfill Atomics.waitAsync is not very fast.
|
||||
*/
|
||||
|
||||
/* Implementation:
|
||||
*
|
||||
* For every wait we fork off a Worker to perform the wait. Workers are reused
|
||||
* when possible. The worker communicates with its parent using postMessage.
|
||||
*/
|
||||
|
||||
use js_sys::{Array, Promise};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::{MessageEvent, Worker};
|
||||
|
||||
thread_local! {
|
||||
static HELPERS: RefCell<Vec<Worker>> = RefCell::new(vec![]);
|
||||
}
|
||||
|
||||
fn alloc_helper() -> Worker {
|
||||
HELPERS.with(|helpers| {
|
||||
if let Some(helper) = helpers.borrow_mut().pop() {
|
||||
return helper;
|
||||
}
|
||||
|
||||
let worker_url = wasm_bindgen::link_to!(module = "/src/task/worker.js");
|
||||
Worker::new(&worker_url).unwrap_or_else(|js| wasm_bindgen::throw_val(js))
|
||||
})
|
||||
}
|
||||
|
||||
fn free_helper(helper: Worker) {
|
||||
HELPERS.with(move |helpers| {
|
||||
let mut helpers = helpers.borrow_mut();
|
||||
helpers.push(helper.clone());
|
||||
helpers.truncate(10); // random arbitrary limit chosen here
|
||||
});
|
||||
}
|
||||
|
||||
pub fn wait_async(ptr: &AtomicI32, value: i32) -> Promise {
|
||||
Promise::new(&mut |resolve, _reject| {
|
||||
let helper = alloc_helper();
|
||||
let helper_ref = helper.clone();
|
||||
|
||||
let onmessage_callback = Closure::once_into_js(move |e: MessageEvent| {
|
||||
// Our helper is done waiting so it's available to wait on a
|
||||
// different location, so return it to the free list.
|
||||
free_helper(helper_ref);
|
||||
drop(resolve.call1(&JsValue::NULL, &e.data()));
|
||||
});
|
||||
helper.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
|
||||
|
||||
let data = Array::of3(
|
||||
&wasm_bindgen::memory(),
|
||||
&JsValue::from(ptr as *const AtomicI32 as i32 / 4),
|
||||
&JsValue::from(value),
|
||||
);
|
||||
|
||||
helper
|
||||
.post_message(&data)
|
||||
.unwrap_or_else(|js| wasm_bindgen::throw_val(js));
|
||||
})
|
||||
}
|
||||
6
third-party/vendor/wasm-bindgen-futures/src/task/worker.js
vendored
Normal file
6
third-party/vendor/wasm-bindgen-futures/src/task/worker.js
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
onmessage = function (ev) {
|
||||
let [ia, index, value] = ev.data;
|
||||
ia = new Int32Array(ia.buffer);
|
||||
let result = Atomics.wait(ia, index, value);
|
||||
postMessage(result);
|
||||
};
|
||||
187
third-party/vendor/wasm-bindgen-futures/tests/tests.rs
vendored
Normal file
187
third-party/vendor/wasm-bindgen-futures/tests/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
use futures_channel::oneshot;
|
||||
use js_sys::Promise;
|
||||
use std::ops::FnMut;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::{future_to_promise, spawn_local, JsFuture};
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn promise_resolve_is_ok_future() {
|
||||
let p = js_sys::Promise::resolve(&JsValue::from(42));
|
||||
let x = JsFuture::from(p).await.unwrap();
|
||||
assert_eq!(x, 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn promise_reject_is_error_future() {
|
||||
let p = js_sys::Promise::reject(&JsValue::from(42));
|
||||
let e = JsFuture::from(p).await.unwrap_err();
|
||||
assert_eq!(e, 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn ok_future_is_resolved_promise() {
|
||||
let p = future_to_promise(async { Ok(JsValue::from(42)) });
|
||||
let x = JsFuture::from(p).await.unwrap();
|
||||
assert_eq!(x, 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn error_future_is_rejected_promise() {
|
||||
let p = future_to_promise(async { Err(JsValue::from(42)) });
|
||||
let e = JsFuture::from(p).await.unwrap_err();
|
||||
assert_eq!(e, 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn debug_jsfuture() {
|
||||
let p = js_sys::Promise::resolve(&JsValue::from(42));
|
||||
let f = JsFuture::from(p);
|
||||
assert_eq!(&format!("{:?}", f), "JsFuture { ... }");
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
fn setTimeout(c: &Closure<dyn FnMut()>);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn oneshot_works() {
|
||||
let (tx, rx) = oneshot::channel::<u32>();
|
||||
let mut tx = Some(tx);
|
||||
let closure = Closure::wrap(Box::new(move || {
|
||||
drop(tx.take().unwrap());
|
||||
}) as Box<dyn FnMut()>);
|
||||
setTimeout(&closure);
|
||||
closure.forget();
|
||||
rx.await.unwrap_err();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn spawn_local_runs() {
|
||||
let (tx, rx) = oneshot::channel::<u32>();
|
||||
spawn_local(async {
|
||||
tx.send(42).unwrap();
|
||||
});
|
||||
assert_eq!(rx.await.unwrap(), 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn spawn_local_nested() {
|
||||
let (ta, mut ra) = oneshot::channel::<u32>();
|
||||
let (ts, rs) = oneshot::channel::<u32>();
|
||||
let (tx, rx) = oneshot::channel::<u32>();
|
||||
// The order in which the various promises and tasks run is important!
|
||||
// We want, on different ticks each, the following things to happen
|
||||
// 1. A promise resolves, off of which we can spawn our inbetween assertion
|
||||
// 2. The outer task runs, spawns in the inner task, and the inbetween promise, then yields
|
||||
// 3. The inbetween promise runs and asserts that the inner task hasn't run
|
||||
// 4. The inner task runs
|
||||
// This depends crucially on two facts:
|
||||
// - JsFuture schedules on ticks independently from tasks
|
||||
// - The order of ticks is the same as the code flow
|
||||
let promise = Promise::resolve(&JsValue::null());
|
||||
|
||||
spawn_local(async move {
|
||||
// Create a closure that runs in between the two ticks and
|
||||
// assert that the inner task hasn't run yet
|
||||
let inbetween = Closure::wrap(Box::new(move |_| {
|
||||
assert_eq!(
|
||||
ra.try_recv().unwrap(),
|
||||
None,
|
||||
"Nested task should not have run yet"
|
||||
);
|
||||
}) as Box<dyn FnMut(JsValue)>);
|
||||
let inbetween = promise.then(&inbetween);
|
||||
spawn_local(async {
|
||||
ta.send(0xdead).unwrap();
|
||||
ts.send(0xbeaf).unwrap();
|
||||
});
|
||||
JsFuture::from(inbetween).await.unwrap();
|
||||
assert_eq!(
|
||||
rs.await.unwrap(),
|
||||
0xbeaf,
|
||||
"Nested task should run eventually"
|
||||
);
|
||||
tx.send(42).unwrap();
|
||||
});
|
||||
|
||||
assert_eq!(rx.await.unwrap(), 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn spawn_local_err_no_exception() {
|
||||
let (tx, rx) = oneshot::channel::<u32>();
|
||||
spawn_local(async {});
|
||||
spawn_local(async {
|
||||
tx.send(42).unwrap();
|
||||
});
|
||||
let val = rx.await.unwrap();
|
||||
assert_eq!(val, 42);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
async fn can_create_multiple_futures_from_same_promise() {
|
||||
let promise = js_sys::Promise::resolve(&JsValue::null());
|
||||
let a = JsFuture::from(promise.clone());
|
||||
let b = JsFuture::from(promise);
|
||||
|
||||
a.await.unwrap();
|
||||
b.await.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "futures-core-03-stream")]
|
||||
#[wasm_bindgen_test]
|
||||
async fn can_use_an_async_iterable_as_stream() {
|
||||
use futures_lite::stream::StreamExt;
|
||||
use wasm_bindgen_futures::stream::JsStream;
|
||||
|
||||
let async_iter = js_sys::Function::new_no_args(
|
||||
"return async function*() {
|
||||
yield 42;
|
||||
yield 24;
|
||||
}()",
|
||||
)
|
||||
.call0(&JsValue::undefined())
|
||||
.unwrap()
|
||||
.unchecked_into::<js_sys::AsyncIterator>();
|
||||
|
||||
let mut stream = JsStream::from(async_iter);
|
||||
assert_eq!(stream.next().await, Some(Ok(JsValue::from(42))));
|
||||
assert_eq!(stream.next().await, Some(Ok(JsValue::from(24))));
|
||||
assert_eq!(stream.next().await, None);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
#[should_panic]
|
||||
async fn should_panic() {
|
||||
panic!()
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
#[should_panic = "error message"]
|
||||
async fn should_panic_string() {
|
||||
panic!("error message")
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
#[should_panic(expected = "error message")]
|
||||
async fn should_panic_expected() {
|
||||
panic!("error message")
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
#[ignore]
|
||||
async fn ignore() {
|
||||
panic!("this test should have been ignored")
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
#[ignore = "reason"]
|
||||
async fn ignore_reason() {
|
||||
panic!("this test should have been ignored")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue