From 6e95ba20f1b24a2e01515094142f6649c4c58e31 Mon Sep 17 00:00:00 2001 From: Alexander Kryvomaz Date: Tue, 3 Jul 2018 23:42:49 +0300 Subject: [PATCH 1/4] bindings for Generator.next() --- src/js.rs | 13 ++++++++ tests/all/js_globals/Generator.rs | 51 +++++++++++++++++++++++++++++++ tests/all/js_globals/mod.rs | 1 + 3 files changed, 65 insertions(+) create mode 100644 tests/all/js_globals/Generator.rs diff --git a/src/js.rs b/src/js.rs index e7278b602..a9cdd098e 100644 --- a/src/js.rs +++ b/src/js.rs @@ -369,6 +369,19 @@ extern "C" { pub fn to_string(this: &Function) -> JsString; } +// Generator +#[wasm_bindgen] +extern { + pub type Generator; + + /// The next() method returns an object with two properties done and value. + /// You can also provide a parameter to the next method to send a value to the generator. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next + #[wasm_bindgen(method, structural)] + pub fn next(this: &Generator, value: &JsValue) -> JsValue; +} + // Map #[wasm_bindgen] extern { diff --git a/tests/all/js_globals/Generator.rs b/tests/all/js_globals/Generator.rs new file mode 100644 index 000000000..f0543f63f --- /dev/null +++ b/tests/all/js_globals/Generator.rs @@ -0,0 +1,51 @@ +#![allow(non_snake_case)] + +use project; + +#[test] +fn next() { + project() + .file( + "src/lib.rs", + r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn next(this: &js::Generator, value: &JsValue) -> JsValue { + this.next(value) + } + "#, + ) + .file( + "test.ts", + r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + function* generator() { + const reply = yield '2 * 2'; + + return reply === 4; + } + + const gen = generator(); + + const q = wasm.next(gen, undefined); + + assert.equal(q.value, '2 * 2'); + assert.equal(q.done, false); + + const a = wasm.next(gen, 4); + + assert.equal(a.value, true); + assert.equal(a.done, true); + } + "#, + ) + .test() +} diff --git a/tests/all/js_globals/mod.rs b/tests/all/js_globals/mod.rs index 632898e09..8c02811c1 100644 --- a/tests/all/js_globals/mod.rs +++ b/tests/all/js_globals/mod.rs @@ -8,6 +8,7 @@ mod Boolean; mod Date; mod Error; mod Function; +mod Generator; mod JsString; mod Map; mod MapIterator; From 39d79eb0371db096506fbd7fe99b012de2762987 Mon Sep 17 00:00:00 2001 From: Alexander Kryvomaz Date: Tue, 3 Jul 2018 23:47:10 +0300 Subject: [PATCH 2/4] bindings for Generator.return() --- src/js.rs | 6 ++++ tests/all/js_globals/Generator.rs | 52 +++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/js.rs b/src/js.rs index a9cdd098e..9618d57fc 100644 --- a/src/js.rs +++ b/src/js.rs @@ -374,6 +374,12 @@ extern "C" { extern { pub type Generator; + /// The return() method returns the given value and finishes the generator. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return + #[wasm_bindgen(method, structural, js_name = return)] + pub fn gen_return(this: &Generator, value: &JsValue) -> JsValue; + /// The next() method returns an object with two properties done and value. /// You can also provide a parameter to the next method to send a value to the generator. /// diff --git a/tests/all/js_globals/Generator.rs b/tests/all/js_globals/Generator.rs index f0543f63f..ee061c271 100644 --- a/tests/all/js_globals/Generator.rs +++ b/tests/all/js_globals/Generator.rs @@ -2,6 +2,50 @@ use project; +#[test] +fn gen_return() { + project() + .file( + "src/lib.rs", + r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn gen_return(this: &js::Generator, value: &JsValue) -> JsValue { + this.gen_return(value) + } + "#, + ) + .file( + "test.ts", + r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + function* generator() { + yield 1; + yield 2; + } + + const gen = generator(); + gen.next(); + + const res = wasm.gen_return(gen, 42); + assert.deepEqual(res, { value: 42, done: true }); + + const next = gen.next(); + assert.deepEqual(next, { value: undefined, done: true }); + } + "#, + ) + .test() +} + #[test] fn next() { project() @@ -36,14 +80,10 @@ fn next() { const gen = generator(); const q = wasm.next(gen, undefined); - - assert.equal(q.value, '2 * 2'); - assert.equal(q.done, false); + assert.deepEqual(q, { value: '2 * 2', done: false }); const a = wasm.next(gen, 4); - - assert.equal(a.value, true); - assert.equal(a.done, true); + assert.deepEqual(a, { value: true, done: true }); } "#, ) From b797bbc39cde31db616917046374e4f3986fcdac Mon Sep 17 00:00:00 2001 From: Alexander Kryvomaz Date: Tue, 3 Jul 2018 23:48:54 +0300 Subject: [PATCH 3/4] bindings for Generator.throw() --- src/js.rs | 7 +++++ tests/all/js_globals/Generator.rs | 46 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/js.rs b/src/js.rs index 9618d57fc..ca415c662 100644 --- a/src/js.rs +++ b/src/js.rs @@ -386,6 +386,13 @@ extern { /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next #[wasm_bindgen(method, structural)] pub fn next(this: &Generator, value: &JsValue) -> JsValue; + + /// The throw() method resumes the execution of a generator by throwing an error into it + /// and returns an object with two properties done and value. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw + #[wasm_bindgen(method, structural)] + pub fn throw(this: &Generator, error: &Error) -> JsValue; } // Map diff --git a/tests/all/js_globals/Generator.rs b/tests/all/js_globals/Generator.rs index ee061c271..e50cf33ce 100644 --- a/tests/all/js_globals/Generator.rs +++ b/tests/all/js_globals/Generator.rs @@ -89,3 +89,49 @@ fn next() { ) .test() } + +#[test] +fn throw() { + project() + .file( + "src/lib.rs", + r#" + #![feature(proc_macro, wasm_custom_section)] + + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + use wasm_bindgen::js; + + #[wasm_bindgen] + pub fn gen_throw(this: &js::Generator, error: &js::Error) -> JsValue { + this.throw(error) + } + "#, + ) + .file( + "test.ts", + r#" + import * as assert from "assert"; + import * as wasm from "./out"; + + export function test() { + function* generator() { + yield 1; + yield 2; + } + + const gen = generator(); + gen.next(); + + try { + wasm.gen_throw(gen, new Error('Something went wrong')); + } catch(err) { + assert.equal(err.message, 'Something went wrong'); + } + + assert.deepEqual(gen.next(), { value: undefined, done: true }); + } + "#, + ) + .test() +} From eac2b05b1b82d2941cd43c84c6bc12fec116edc9 Mon Sep 17 00:00:00 2001 From: Alexander Kryvomaz Date: Wed, 4 Jul 2018 01:22:56 +0300 Subject: [PATCH 4/4] added catch attribute to the Generator methods, consistent rust keyword name --- src/js.rs | 20 ++++++++++---------- tests/all/js_globals/Generator.rs | 29 +++++++++++++++++++---------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/js.rs b/src/js.rs index ca415c662..c980f1b67 100644 --- a/src/js.rs +++ b/src/js.rs @@ -374,25 +374,25 @@ extern "C" { extern { pub type Generator; - /// The return() method returns the given value and finishes the generator. - /// - /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return - #[wasm_bindgen(method, structural, js_name = return)] - pub fn gen_return(this: &Generator, value: &JsValue) -> JsValue; - /// The next() method returns an object with two properties done and value. /// You can also provide a parameter to the next method to send a value to the generator. /// /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next - #[wasm_bindgen(method, structural)] - pub fn next(this: &Generator, value: &JsValue) -> JsValue; + #[wasm_bindgen(method, structural, catch)] + pub fn next(this: &Generator, value: &JsValue) -> Result; + + /// The return() method returns the given value and finishes the generator. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return + #[wasm_bindgen(method, structural, js_name = return)] + pub fn return_(this: &Generator, value: &JsValue) -> JsValue; /// The throw() method resumes the execution of a generator by throwing an error into it /// and returns an object with two properties done and value. /// /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw - #[wasm_bindgen(method, structural)] - pub fn throw(this: &Generator, error: &Error) -> JsValue; + #[wasm_bindgen(method, structural, catch)] + pub fn throw(this: &Generator, error: &Error) -> Result; } // Map diff --git a/tests/all/js_globals/Generator.rs b/tests/all/js_globals/Generator.rs index e50cf33ce..315e0e82d 100644 --- a/tests/all/js_globals/Generator.rs +++ b/tests/all/js_globals/Generator.rs @@ -3,7 +3,7 @@ use project; #[test] -fn gen_return() { +fn return_() { project() .file( "src/lib.rs", @@ -16,7 +16,7 @@ fn gen_return() { #[wasm_bindgen] pub fn gen_return(this: &js::Generator, value: &JsValue) -> JsValue { - this.gen_return(value) + this.return_(value) } "#, ) @@ -61,6 +61,13 @@ fn next() { #[wasm_bindgen] pub fn next(this: &js::Generator, value: &JsValue) -> JsValue { this.next(value) + .ok() + .expect("generator throws an error") + } + + #[wasm_bindgen] + pub fn next_throws_error(this: &js::Generator, value: &JsValue) -> bool { + this.next(value).is_err() } "#, ) @@ -84,6 +91,13 @@ fn next() { const a = wasm.next(gen, 4); assert.deepEqual(a, { value: true, done: true }); + + function* brokenGenerator() { + throw new Error('Something went wrong'); + yield 1; + } + + assert(wasm.next_throws_error(brokenGenerator(), undefined)); } "#, ) @@ -103,8 +117,8 @@ fn throw() { use wasm_bindgen::js; #[wasm_bindgen] - pub fn gen_throw(this: &js::Generator, error: &js::Error) -> JsValue { - this.throw(error) + pub fn gen_throws_error(this: &js::Generator, error: &js::Error) -> bool { + this.throw(error).is_err() } "#, ) @@ -123,12 +137,7 @@ fn throw() { const gen = generator(); gen.next(); - try { - wasm.gen_throw(gen, new Error('Something went wrong')); - } catch(err) { - assert.equal(err.message, 'Something went wrong'); - } - + assert(wasm.gen_throws_error(gen, new Error('Something went wrong'))); assert.deepEqual(gen.next(), { value: undefined, done: true }); } "#,