Support asynchronous tests (#600)

* Tweak the implementation of heap closures

This commit updates the implementation of the `Closure` type to internally store
an `Rc` and be suitable for dropping a `Closure` during the execution of the
closure. This is currently needed for promises but may be generally useful as
well!

* Support asynchronous tests

This commit adds support for executing tests asynchronously. This is modeled
by tests returning a `Future` instead of simply executing inline, and is
signified with `#[wasm_bindgen_test(async)]`.

Support for this is added through a new `wasm-bindgen-futures` crate which is a
binding between the `futures` crate and JS `Promise` objects.

Lots more details can be found in the details of the commit, but one of the end
results is that the `web-sys` tests are now entirely contained in the same test
suite and don't need `npm install` to be run to execute them!

* Review tweaks

* Add some bindings for `Function.call` to `js_sys`

Name them `call0`, `call1`, `call2`, ... for the number of arguments being
passed.

* Use oneshots channels with `JsFuture`

It did indeed clean up the implementation!
This commit is contained in:
Alex Crichton
2018-08-01 15:52:24 -05:00
committed by GitHub
parent 4181afea45
commit eee71de0ce
34 changed files with 1167 additions and 333 deletions

View File

@ -740,6 +740,34 @@ extern "C" {
#[wasm_bindgen(method, catch)]
pub fn apply(this: &Function, context: &JsValue, args: &Array) -> Result<JsValue, JsValue>;
/// The `call()` method calls a function with a given this value and
/// arguments provided individually.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
#[wasm_bindgen(method, catch, js_name = call)]
pub fn call0(this: &Function, context: &JsValue) -> Result<JsValue, JsValue>;
/// The `call()` method calls a function with a given this value and
/// arguments provided individually.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
#[wasm_bindgen(method, catch, js_name = call)]
pub fn call1(this: &Function, context: &JsValue, arg1: &JsValue) -> Result<JsValue, JsValue>;
/// The `call()` method calls a function with a given this value and
/// arguments provided individually.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
#[wasm_bindgen(method, catch, js_name = call)]
pub fn call2(this: &Function, context: &JsValue, arg1: &JsValue, arg2: &JsValue) -> Result<JsValue, JsValue>;
/// The `call()` method calls a function with a given this value and
/// arguments provided individually.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
#[wasm_bindgen(method, catch, js_name = call)]
pub fn call3(this: &Function, context: &JsValue, arg1: &JsValue, arg2: &JsValue, arg3: &JsValue) -> Result<JsValue, JsValue>;
/// The bind() method creates a new function that, when called, has its this keyword set to the provided value,
/// with a given sequence of arguments preceding any provided when the new function is called.
///
@ -3009,3 +3037,101 @@ extern "C" {
#[wasm_bindgen(static_method_of = Intl, js_name = getCanonicalLocales)]
pub fn get_canonical_locales(s: &JsValue) -> Array;
}
// Promise
#[wasm_bindgen]
extern {
/// The `Promise` object represents the eventual completion (or failure) of
/// an asynchronous operation, and its resulting value.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
pub type Promise;
/// Creates a new `Promise` with the provided executor `cb`
///
/// The `cb` is a function that is passed with the arguments `resolve` and
/// `reject`. The `cb` function is executed immediately by the `Promise`
/// implementation, passing `resolve` and `reject` functions (the executor
/// is called before the `Promise` constructor even returns the created
/// object). The `resolve` and `reject` functions, when called, resolve or
/// reject the promise, respectively. The executor normally initiates
/// some asynchronous work, and then, once that completes, either calls
/// the `resolve` function to resolve the promise or else rejects it if an
/// error occurred.
///
/// If an error is thrown in the executor function, the promise is rejected.
/// The return value of the executor is ignored.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
#[wasm_bindgen(constructor)]
pub fn new(cb: &mut FnMut(Function, Function)) -> Promise;
/// The `Promise.all(iterable)` method returns a single `Promise` that
/// resolves when all of the promises in the iterable argument have resolved
/// or when the iterable argument contains no promises. It rejects with the
/// reason of the first promise that rejects.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
#[wasm_bindgen(static_method_of = Promise)]
pub fn all(obj: JsValue) -> Promise;
/// The `Promise.race(iterable)` method returns a promise that resolves or
/// rejects as soon as one of the promises in the iterable resolves or
/// rejects, with the value or reason from that promise.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
#[wasm_bindgen(static_method_of = Promise)]
pub fn race(obj: JsValue) -> Promise;
/// The `Promise.reject(reason)` method returns a `Promise` object that is
/// rejected with the given reason.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject
#[wasm_bindgen(static_method_of = Promise)]
pub fn reject(obj: JsValue) -> Promise;
/// The `Promise.resolve(value)` method returns a `Promise` object that is
/// resolved with the given value. If the value is a promise, that promise
/// is returned; if the value is a thenable (i.e. has a "then" method), the
/// returned promise will "follow" that thenable, adopting its eventual
/// state; otherwise the returned promise will be fulfilled with the value.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve
#[wasm_bindgen(static_method_of = Promise)]
pub fn resolve(obj: JsValue) -> Promise;
/// The `catch()` method returns a `Promise` and deals with rejected cases
/// only. It behaves the same as calling `Promise.prototype.then(undefined,
/// onRejected)` (in fact, calling `obj.catch(onRejected)` internally calls
/// `obj.then(undefined, onRejected)`).
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
#[wasm_bindgen(method)]
pub fn catch(this: &Promise, cb: &Closure<FnMut(JsValue)>) -> Promise;
/// The `then()` method returns a `Promise`. It takes up to two arguments:
/// callback functions for the success and failure cases of the `Promise`.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
#[wasm_bindgen(method)]
pub fn then(this: &Promise, cb: &Closure<FnMut(JsValue)>) -> Promise;
/// Same as `then`, only with both arguments provided.
#[wasm_bindgen(method, js_name = then)]
pub fn then2(this: &Promise,
resolve: &Closure<FnMut(JsValue)>,
reject: &Closure<FnMut(JsValue)>) -> Promise;
/// The `finally()` method returns a `Promise`. When the promise is settled,
/// whether fulfilled or rejected, the specified callback function is
/// executed. This provides a way for code that must be executed once the
/// `Promise` has been dealt with to be run whether the promise was
/// fulfilled successfully or rejected.
///
/// This lets you avoid duplicating code in both the promise's `then()` and
/// `catch()` handlers.
///
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
#[wasm_bindgen(method)]
pub fn finally(this: &Promise, cb: &Closure<FnMut()>) -> Promise;
}

View File

@ -1,4 +1,3 @@
use wasm_bindgen::JsValue;
use wasm_bindgen_test::*;
use js_sys::*;