Merge pull request #1450 from RReverser/iter-is-type-of

Leverage new `is_type_of` for iterator protocol
This commit is contained in:
Alex Crichton 2019-04-12 14:45:05 -05:00 committed by GitHub
commit 744b031ad4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1025,6 +1025,7 @@ extern "C" {
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)
#[derive(Clone, Debug)]
#[wasm_bindgen(is_type_of = Iterator::looks_like_iterator)]
pub type Iterator;
/// The next method always has to return an object with appropriate
@ -1035,6 +1036,26 @@ extern "C" {
pub fn next(this: &Iterator) -> Result<IteratorNext, JsValue>;
}
impl Iterator {
fn looks_like_iterator(it: &JsValue) -> bool {
#[wasm_bindgen]
extern "C" {
type MaybeIterator;
#[wasm_bindgen(method, getter)]
fn next(this: &MaybeIterator) -> JsValue;
}
if !it.is_object() {
return false;
}
let it = it.unchecked_ref::<MaybeIterator>();
it.next().is_function()
}
}
/// An iterator over the JS `Symbol.iterator` iteration protocol.
///
/// Use the `IntoIterator for &js_sys::Iterator` implementation to create this.
@ -1123,37 +1144,20 @@ impl IterState {
/// Create an iterator over `val` using the JS iteration protocol and
/// `Symbol.iterator`.
pub fn try_iter(val: &JsValue) -> Result<Option<IntoIter>, JsValue> {
#[wasm_bindgen]
extern "C" {
type MaybeIterator;
#[wasm_bindgen(method, getter)]
fn next(this: &MaybeIterator) -> JsValue;
}
let iter_sym = Symbol::iterator();
let iter_fn = Reflect::get(val, iter_sym.as_ref())?;
if !iter_fn.is_function() {
return Ok(None);
}
let iter_fn: Function = match iter_fn.dyn_into() {
Ok(iter_fn) => iter_fn,
Err(_) => return Ok(None)
Err(_) => return Ok(None),
};
let it = iter_fn.call0(val)?;
if !it.is_object() {
return Ok(None);
}
let next = it.unchecked_ref::<MaybeIterator>().next();
let it: Iterator = match iter_fn.call0(val)?.dyn_into() {
Ok(it) => it,
Err(_) => return Ok(None),
};
Ok(if next.is_function() {
let it: Iterator = it.unchecked_into();
Some(it.into_iter())
} else {
None
})
Ok(Some(it.into_iter()))
}
// IteratorNext