use std::cell::Cell;
use boa_gc::{Finalize, Trace};
use crate::{
JsValue,
builtins::iterable::IteratorRecord,
native_function::{CoroutineBranch, CoroutineState, NativeCoroutine},
object::JsFunction,
};
#[derive(Trace, Finalize, Default)]
#[boa_gc(unsafe_no_drop)]
pub(crate) enum Map {
#[default]
Completed,
Yielding {
iterated: IteratorRecord,
mapper: JsFunction,
counter: u64,
},
}
impl Map {
#[allow(
clippy::new_ret_no_self,
reason = "slightly cleaner to have this be a `new` method"
)]
pub(crate) fn new(iterated: IteratorRecord, mapper: JsFunction) -> NativeCoroutine {
NativeCoroutine::from_copy_closure_with_captures(
|completion, state, context| {
let st = state.take();
match st {
Self::Completed => CoroutineState::Break(Ok(())),
Self::Yielding {
mut iterated,
mapper,
counter,
} => {
iterated.if_abrupt_close_iterator(completion, context)?;
let Some(value) = iterated.step_value(context).branch()? else {
return CoroutineState::Break(Ok(()));
};
let value = if_abrupt_close_iterator!(
mapper.call(&JsValue::undefined(), &[value, counter.into()], context,),
iterated,
context
);
state.set(Self::Yielding {
iterated,
mapper,
counter: counter + 1,
});
CoroutineState::Continue(value)
}
}
},
Cell::new(Self::Yielding {
iterated,
mapper,
counter: 0,
}),
)
}
}