use crate::{
Context, JsData, JsResult, JsValue,
builtins::{BuiltInBuilder, IntrinsicObject, iterable::create_iter_result_object},
context::intrinsics::Intrinsics,
error::JsNativeError,
js_string,
object::JsObject,
realm::Realm,
};
use boa_gc::{Finalize, Trace};
use super::IteratorRecord;
#[derive(Debug, Finalize, Trace, JsData)]
pub(crate) struct WrapForValidIterator {
pub(crate) iterated: IteratorRecord,
}
impl IntrinsicObject for WrapForValidIterator {
fn init(realm: &Realm) {
BuiltInBuilder::with_intrinsic::<Self>(realm)
.prototype(realm.intrinsics().constructors().iterator().prototype())
.static_method(Self::next, js_string!("next"), 0)
.static_method(Self::r#return, js_string!("return"), 0)
.build();
}
fn get(intrinsics: &Intrinsics) -> JsObject {
intrinsics
.objects()
.iterator_prototypes()
.wrap_for_valid_iterator()
}
}
impl WrapForValidIterator {
pub(crate) fn next(
this: &JsValue,
_args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
let object = this.as_object().ok_or_else(|| {
JsNativeError::typ().with_message("WrapForValidIterator method called on non-object")
})?;
let wrapper = object.downcast_mut::<Self>().ok_or_else(|| {
JsNativeError::typ()
.with_message("WrapForValidIterator method called on incompatible object")
})?;
let next_method = wrapper.iterated.next_method().clone();
let iterator = wrapper.iterated.iterator().clone();
drop(wrapper);
next_method.call(&iterator.into(), &[], context)
}
pub(crate) fn r#return(
this: &JsValue,
_args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
let object = this.as_object().ok_or_else(|| {
JsNativeError::typ().with_message("WrapForValidIterator method called on non-object")
})?;
let wrapper = object.downcast_mut::<Self>().ok_or_else(|| {
JsNativeError::typ()
.with_message("WrapForValidIterator method called on incompatible object")
})?;
let iterator = wrapper.iterated.iterator().clone();
drop(wrapper);
let return_method = iterator.get_method(js_string!("return"), context)?;
match return_method {
None => {
Ok(create_iter_result_object(
JsValue::undefined(),
true,
context,
))
}
Some(return_method) => return_method.call(&iterator.into(), &[], context),
}
}
}