1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! 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 two 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<Item = JsValue, Error = 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<Item = JsValue, Error = JsValue>` into a
//!    JavaScript `Promise`. The future's result will translate to either a
//!    rejected or resolved `Promise` in JavaScript.
//!
//! These two 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.
//!
//! # Example Usage
//!
//! This example wraps JavaScript's `Promise.resolve()` into a Rust `Future` for
//! running tasks on the next tick of the micro task queue. The futures built on
//! top of it can be scheduled for execution by conversion into a JavaScript
//! `Promise`.
//!
//! ```rust,no_run
//! extern crate futures;
//! extern crate js_sys;
//! extern crate wasm_bindgen;
//! extern crate wasm_bindgen_futures;
//!
//! use futures::{Async, Future, Poll};
//! use wasm_bindgen::prelude::*;
//! use wasm_bindgen_futures::{JsFuture, future_to_promise};
//!
//! /// A future that becomes ready after a tick of the micro task queue.
//! pub struct NextTick {
//!     inner: JsFuture,
//! }
//!
//! impl NextTick {
//!     /// Construct a new `NextTick` future.
//!     pub fn new() -> NextTick {
//!         // Create a resolved promise that will run its callbacks on the next
//!         // tick of the micro task queue.
//!         let promise = js_sys::Promise::resolve(&JsValue::NULL);
//!         // Convert the promise into a `JsFuture`.
//!         let inner = JsFuture::from(promise);
//!         NextTick { inner }
//!     }
//! }
//!
//! impl Future for NextTick {
//!     type Item = ();
//!     type Error = ();
//!
//!     fn poll(&mut self) -> Poll<(), ()> {
//!         // Polling a `NextTick` just forwards to polling if the inner promise is
//!         // ready.
//!         match self.inner.poll() {
//!             Ok(Async::Ready(_)) => Ok(Async::Ready(())),
//!             Ok(Async::NotReady) => Ok(Async::NotReady),
//!             Err(_) => unreachable!(
//!                 "We only create NextTick with a resolved inner promise, never \
//!                  a rejected one, so we can't get an error here"
//!             ),
//!         }
//!     }
//! }
//!
//! /// Export a function to JavaScript that does some work in the next tick of the
//! /// micro task queue!
//! #[wasm_bindgen]
//! pub fn schedule_some_work_for_next_tick() -> js_sys::Promise {
//!     let future = NextTick::new()
//!         // Do some work...
//!         .and_then(|_| {
//!             Ok(42)
//!         })
//!         // And then convert the `Item` and `Error` into `JsValue`.
//!         .map(|result| {
//!             JsValue::from(result)
//!         })
//!         .map_err(|error| {
//!             let js_error = js_sys::Error::new(&format!("uh oh! {:?}", error));
//!             JsValue::from(js_error)
//!         });
//!
//!     // Convert the `Future<Item = JsValue, Error = JsValue>` into a JavaScript
//!     // `Promise`!
//!     future_to_promise(future)
//! }
//! ```

#![cfg_attr(target_feature = "atomics", feature(stdsimd))]
#![deny(missing_docs)]

use cfg_if::cfg_if;

mod legacy_shared;
pub use legacy_shared::*;

cfg_if! {
    if #[cfg(target_feature = "atomics")] {
        /// Contains a thread-safe version of this crate, with Futures 0.1
        mod legacy_atomics;
        pub use legacy_atomics::*;

        /// Polyfill for `Atomics.waitAsync` function
        mod wait_async_polyfill;
    } else {
        mod legacy;
        pub use legacy::*;
     }
}

#[cfg(feature = "futures_0_3")]
cfg_if! {
    if #[cfg(target_feature = "atomics")] {
        compile_error!("futures 0.3 support is not implemented with atomics yet");
    } else {
        /// Contains a Futures 0.3 implementation of this crate.
        pub mod futures_0_3;
     }
}