use rquickjs::atom::PredefinedAtom;
use rquickjs::function::{Func, This};
use rquickjs::{Class, Ctx, Object, Value, class::JsClass};
pub type Project<'js, T> = fn(&Ctx<'js>, &Class<'js, T>, usize) -> rquickjs::Result<Option<Value<'js>>>;
pub fn live_iterator<'js, T>(
ctx: &Ctx<'js>,
parent: Class<'js, T>,
project: Project<'js, T>,
) -> rquickjs::Result<Object<'js>>
where
T: JsClass<'js> + 'js,
{
let it = Object::new(ctx.clone())?;
it.set("position", 0usize)?;
it.set("target", parent)?;
it.set(
PredefinedAtom::SymbolIterator,
Func::from(|it: This<Object<'js>>| -> rquickjs::Result<Object<'js>> { Ok(it.0) }),
)?;
it.set(
PredefinedAtom::Next,
Func::from(
move |ctx: Ctx<'js>, it: This<Object<'js>>| -> rquickjs::Result<Object<'js>> {
let position = it.get::<_, usize>("position")?;
let parent: Class<'js, T> = it.get("target")?;
let res = Object::new(ctx.clone())?;
match project(&ctx, &parent, position)? {
None => {
res.set(PredefinedAtom::Value, Value::new_undefined(ctx))?;
res.set(PredefinedAtom::Done, true)?;
},
Some(value) => {
res.set(PredefinedAtom::Value, value)?;
res.set(PredefinedAtom::Done, false)?;
it.set("position", position + 1)?;
},
}
Ok(res)
},
),
)?;
Ok(it)
}