Skip to content

Commit

Permalink
Merge pull request #1450 from RReverser/iter-is-type-of
Browse files Browse the repository at this point in the history
Leverage new `is_type_of` for iterator protocol
  • Loading branch information
alexcrichton authored Apr 12, 2019
2 parents c4776be + 2f524ee commit 744b031
Showing 1 changed file with 27 additions and 23 deletions.
50 changes: 27 additions & 23 deletions crates/js-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 744b031

Please sign in to comment.