From 896c2e2f0f08d20770e63055225b627cd4969241 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 23 Oct 2024 14:00:40 -0400 Subject: [PATCH] LibJS: Close iterator records inside the Iterator{Next,Step} AOs This is an editorial change in the ECMA-262 spec. See: https://github.com/tc39/ecma262/commit/c4c55b6 --- Userland/Libraries/LibJS/Runtime/Iterator.cpp | 112 +++++++++--------- Userland/Libraries/LibJS/Runtime/Iterator.h | 4 +- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Iterator.cpp b/Userland/Libraries/LibJS/Runtime/Iterator.cpp index 9d2b2e8a793..b37bee16748 100644 --- a/Userland/Libraries/LibJS/Runtime/Iterator.cpp +++ b/Userland/Libraries/LibJS/Runtime/Iterator.cpp @@ -143,25 +143,44 @@ ThrowCompletionOr> get_iterator_flattenable(VM& vm, } // 7.4.4 IteratorNext ( iteratorRecord [ , value ] ), https://tc39.es/ecma262/#sec-iteratornext -ThrowCompletionOr> iterator_next(VM& vm, IteratorRecord const& iterator_record, Optional value) +ThrowCompletionOr> iterator_next(VM& vm, IteratorRecord& iterator_record, Optional value) { - Value result; + auto result = [&]() { + // 1. If value is not present, then + if (!value.has_value()) { + // a. Let result be Completion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])). + return call(vm, iterator_record.next_method, iterator_record.iterator); + } + // 2. Else, + else { + // a. Let result be Completion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »)). + return call(vm, iterator_record.next_method, iterator_record.iterator, *value); + } + }(); - // 1. If value is not present, then - if (!value.has_value()) { - // a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]). - result = TRY(call(vm, iterator_record.next_method, iterator_record.iterator)); - } else { - // a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »). - result = TRY(call(vm, iterator_record.next_method, iterator_record.iterator, *value)); + // 3. If result is a throw completion, then + if (result.is_throw_completion()) { + // a. Set iteratorRecord.[[Done]] to true. + iterator_record.done = true; + + // b. Return ? result. + return result.release_error(); } - // 3. If Type(result) is not Object, throw a TypeError exception. - if (!result.is_object()) - return vm.throw_completion(ErrorType::IterableNextBadReturn); + // 4. Set result to ! result. + auto result_value = result.release_value(); - // 4. Return result. - return result.as_object(); + // 5. If result is not an Object, then + if (!result_value.is_object()) { + // a. Set iteratorRecord.[[Done]] to true. + iterator_record.done = true; + + // b. Throw a TypeError exception. + return vm.throw_completion(ErrorType::IterableNextBadReturn); + } + + // 6. Return result. + return result_value.as_object(); } // 7.4.5 IteratorComplete ( iterResult ), https://tc39.es/ecma262/#sec-iteratorcomplete @@ -179,44 +198,15 @@ ThrowCompletionOr iterator_value(VM& vm, Object& iterator_result) } // 7.4.7 IteratorStep ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstep -ThrowCompletionOr> iterator_step(VM& vm, IteratorRecord const& iterator_record) +ThrowCompletionOr> iterator_step(VM& vm, IteratorRecord& iterator_record) { // 1. Let result be ? IteratorNext(iteratorRecord). auto result = TRY(iterator_next(vm, iterator_record)); - // 2. Let done be ? IteratorComplete(result). - auto done = TRY(iterator_complete(vm, result)); + // 2. Let done be Completion(IteratorComplete(result)). + auto done = iterator_complete(vm, result); - // 3. If done is true, return false. - if (done) - return nullptr; - - // 4. Return result. - return result; -} - -// 7.4.8 IteratorStepValue ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstepvalue -ThrowCompletionOr> iterator_step_value(VM& vm, IteratorRecord& iterator_record) -{ - // 1. Let result be Completion(IteratorNext(iteratorRecord)). - auto result = iterator_next(vm, iterator_record); - - // 2. If result is a throw completion, then - if (result.is_throw_completion()) { - // a. Set iteratorRecord.[[Done]] to true. - iterator_record.done = true; - - // b. Return ? result. - return result.release_error(); - } - - // 3. Set result to ! result. - auto result_value = result.release_value(); - - // 4. Let done be Completion(IteratorComplete(result)). - auto done = iterator_complete(vm, result_value); - - // 5. If done is a throw completion, then + // 3. If done is a throw completion, then if (done.is_throw_completion()) { // a. Set iteratorRecord.[[Done]] to true. iterator_record.done = true; @@ -225,28 +215,44 @@ ThrowCompletionOr> iterator_step_value(VM& vm, IteratorRecord& i return done.release_error(); } - // 6. Set done to ! done. + // 4. Set done to ! done. auto done_value = done.release_value(); - // 7. If done is true, then + // 5. If done is true, then if (done_value) { // a. Set iteratorRecord.[[Done]] to true. iterator_record.done = true; // b. Return DONE. + return nullptr; + } + + // 6. Return result. + return result; +} + +// 7.4.8 IteratorStepValue ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstepvalue +ThrowCompletionOr> iterator_step_value(VM& vm, IteratorRecord& iterator_record) +{ + // 1. Let result be ? IteratorStep(iteratorRecord). + auto result = TRY(iterator_step(vm, iterator_record)); + + // 2. If result is done, then + if (!result) { + // a. Return DONE. return OptionalNone {}; } - // 8. Let value be Completion(Get(result, "value")). - auto value = result_value->get(vm.names.value); + // 3. Let value be Completion(IteratorValue(result)). + auto value = iterator_value(vm, *result); - // 9. If value is a throw completion, then + // 4. If value is a throw completion, then if (value.is_throw_completion()) { // a. Set iteratorRecord.[[Done]] to true. iterator_record.done = true; } - // 10. Return ? value. + // 5. Return ? value. return TRY(value); } diff --git a/Userland/Libraries/LibJS/Runtime/Iterator.h b/Userland/Libraries/LibJS/Runtime/Iterator.h index 96266c838a3..593eeb6fc01 100644 --- a/Userland/Libraries/LibJS/Runtime/Iterator.h +++ b/Userland/Libraries/LibJS/Runtime/Iterator.h @@ -74,8 +74,8 @@ ThrowCompletionOr> get_iterator_from_method(VM&, Va ThrowCompletionOr> get_iterator(VM&, Value, IteratorHint); ThrowCompletionOr> get_iterator_direct(VM&, Object&); ThrowCompletionOr> get_iterator_flattenable(VM&, Value, StringHandling); -ThrowCompletionOr> iterator_next(VM&, IteratorRecord const&, Optional = {}); -ThrowCompletionOr> iterator_step(VM&, IteratorRecord const&); +ThrowCompletionOr> iterator_next(VM&, IteratorRecord&, Optional = {}); +ThrowCompletionOr> iterator_step(VM&, IteratorRecord&); ThrowCompletionOr> iterator_step_value(VM&, IteratorRecord&); ThrowCompletionOr iterator_complete(VM&, Object& iterator_result); ThrowCompletionOr iterator_value(VM&, Object& iterator_result);