1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:07:44 +00:00

LibJS: Handle abrupt closures from Iterator.prototype.flatMap

This is in preparation of implementing %IteratorHelperPrototype%.return.
That will invoke GeneratorResumeAbrupt, which will execute the generator
with an abrupt completion. At that time, we must take care to close the
current inner iterator.
This commit is contained in:
Timothy Flynn 2023-07-16 15:50:56 -04:00 committed by Linus Groh
parent c04476f09d
commit 57e7112a20
3 changed files with 40 additions and 11 deletions

View file

@ -11,15 +11,16 @@
namespace JS {
ThrowCompletionOr<NonnullGCPtr<IteratorHelper>> IteratorHelper::create(Realm& realm, IteratorRecord underlying_iterator, Closure closure)
ThrowCompletionOr<NonnullGCPtr<IteratorHelper>> IteratorHelper::create(Realm& realm, IteratorRecord underlying_iterator, Closure closure, Optional<AbruptClosure> abrupt_closure)
{
return TRY(realm.heap().allocate<IteratorHelper>(realm, realm, realm.intrinsics().iterator_helper_prototype(), move(underlying_iterator), move(closure)));
return TRY(realm.heap().allocate<IteratorHelper>(realm, realm, realm.intrinsics().iterator_helper_prototype(), move(underlying_iterator), move(closure), move(abrupt_closure)));
}
IteratorHelper::IteratorHelper(Realm& realm, Object& prototype, IteratorRecord underlying_iterator, Closure closure)
IteratorHelper::IteratorHelper(Realm& realm, Object& prototype, IteratorRecord underlying_iterator, Closure closure, Optional<AbruptClosure> abrupt_closure)
: GeneratorObject(realm, prototype, realm.vm().running_execution_context().copy(), "Iterator Helper"sv)
, m_underlying_iterator(move(underlying_iterator))
, m_closure(move(closure))
, m_abrupt_closure(move(abrupt_closure))
{
}
@ -41,9 +42,16 @@ ThrowCompletionOr<Value> IteratorHelper::close_result(VM& vm, Completion complet
return *TRY(iterator_close(vm, underlying_iterator(), move(completion)));
}
ThrowCompletionOr<Value> IteratorHelper::execute(VM& vm, JS::Completion const&)
ThrowCompletionOr<Value> IteratorHelper::execute(VM& vm, JS::Completion const& completion)
{
ScopeGuard guard { [&] { vm.pop_execution_context(); } };
if (completion.is_abrupt()) {
if (m_abrupt_closure.has_value())
return (*m_abrupt_closure)(vm, *this, completion);
return close_result(vm, completion);
}
auto result_value = m_closure(vm, *this);
if (result_value.is_throw_completion()) {