diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index fa2e3c2dd1..dc72e4d99a 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -681,16 +681,11 @@ inline ThrowCompletionOr> iterator_to_array(VM& vm, Value it size_t index = 0; while (true) { - auto iterator_result = TRY(iterator_next(vm, iterator_record)); - - auto complete = TRY(iterator_complete(vm, iterator_result)); - - if (complete) + auto value = TRY(iterator_step_value(vm, iterator_record)); + if (!value.has_value()) return array; - auto value = TRY(iterator_value(vm, iterator_result)); - - MUST(array->create_data_property_or_throw(index, value)); + MUST(array->create_data_property_or_throw(index, value.release_value())); index++; } } diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index f73d3bcdaf..119804563d 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -241,17 +241,17 @@ ThrowCompletionOr group_by(VM& vm, Value items, Value callback_funct return iterator_close(vm, iterator_record, move(error)); } - // b. Let next be ? IteratorStep(iteratorRecord). - auto next = TRY(iterator_step(vm, iterator_record)); + // b. Let next be ? IteratorStepValue(iteratorRecord). + auto next = TRY(iterator_step_value(vm, iterator_record)); - // c. If next is false, then - if (!next) { + // c. If next is DONE, then + if (!next.has_value()) { // i. Return groups. return ThrowCompletionOr { move(groups) }; } - // d. Let value be ? IteratorValue(next). - auto value = TRY(iterator_value(vm, *next)); + // d. Let value be next. + auto value = next.release_value(); // e. Let key be Completion(Call(callbackfn, undefined, « value, 𝔽(k) »)). auto key = call(vm, callback_function, js_undefined(), value, Value(k)); diff --git a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 78610347c7..859a99677e 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -197,11 +197,11 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from) // ii. Let Pk be ! ToString(𝔽(k)). auto property_key = PropertyKey { k }; - // iii. Let next be ? IteratorStep(iteratorRecord). - auto next = TRY(iterator_step(vm, iterator)); + // iii. Let next be ? IteratorStepValue(iteratorRecord). + auto next = TRY(iterator_step_value(vm, iterator)); - // iv. If next is false, then - if (!next) { + // iv. If next is DONE, then + if (!next.has_value()) { // 1. Perform ? Set(A, "length", 𝔽(k), true). TRY(array->set(vm.names.length, Value(k), Object::ShouldThrowExceptions::Yes)); @@ -209,34 +209,31 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from) return array; } - // v. Let nextValue be ? IteratorValue(next). - auto next_value = TRY(iterator_value(vm, *next)); - Value mapped_value; - // vi. If mapping is true, then + // v. If mapping is true, then if (mapfn) { // 1. Let mappedValue be Completion(Call(mapfn, thisArg, « nextValue, 𝔽(k) »)). - auto mapped_value_or_error = JS::call(vm, *mapfn, this_arg, next_value, Value(k)); + auto mapped_value_or_error = JS::call(vm, *mapfn, this_arg, next.release_value(), Value(k)); // 2. IfAbruptCloseIterator(mappedValue, iteratorRecord). if (mapped_value_or_error.is_error()) return *TRY(iterator_close(vm, iterator, mapped_value_or_error.release_error())); mapped_value = mapped_value_or_error.release_value(); } - // vii. Else, let mappedValue be nextValue. + // vi. Else, let mappedValue be nextValue. else { - mapped_value = next_value; + mapped_value = next.release_value(); } - // viii. Let defineStatus be Completion(CreateDataPropertyOrThrow(A, Pk, mappedValue)). + // vii. Let defineStatus be Completion(CreateDataPropertyOrThrow(A, Pk, mappedValue)). auto result_or_error = array->create_data_property_or_throw(property_key, mapped_value); - // IfAbruptCloseIterator(defineStatus, iteratorRecord). + // viii. IfAbruptCloseIterator(defineStatus, iteratorRecord). if (result_or_error.is_error()) return *TRY(iterator_close(vm, iterator, result_or_error.release_error())); - // x. Set k to k + 1. + // ix. Set k to k + 1. } } diff --git a/Userland/Libraries/LibJS/Runtime/Iterator.cpp b/Userland/Libraries/LibJS/Runtime/Iterator.cpp index fb029e8c3e..bbf7a0a747 100644 --- a/Userland/Libraries/LibJS/Runtime/Iterator.cpp +++ b/Userland/Libraries/LibJS/Runtime/Iterator.cpp @@ -332,31 +332,25 @@ NonnullGCPtr create_iterator_result_object(VM& vm, Value value, bool don } // 7.4.14 IteratorToList ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratortolist -ThrowCompletionOr> iterator_to_list(VM& vm, IteratorRecord const& iterator_record) +ThrowCompletionOr> iterator_to_list(VM& vm, IteratorRecord& iterator_record) { // 1. Let values be a new empty List. MarkedVector values(vm.heap()); - // 2. Let next be true. - GCPtr next; + // 2. Repeat, + while (true) { + // a. Let next be ? IteratorStepValue(iteratorRecord). + auto next = TRY(iterator_step_value(vm, iterator_record)); - // 3. Repeat, while next is not false, - do { - // a. Set next to ? IteratorStep(iteratorRecord). - next = TRY(iterator_step(vm, iterator_record)); - - // b. If next is not false, then - if (next) { - // i. Let nextValue be ? IteratorValue(next). - auto next_value = TRY(iterator_value(vm, *next)); - - // ii. Append nextValue to values. - TRY_OR_THROW_OOM(vm, values.try_append(next_value)); + // b. If next is DONE, then + if (!next.has_value()) { + // i. Return values. + return values; } - } while (next); - // 4. Return values. - return values; + // c. Append next to values. + values.append(next.release_value()); + } } // Non-standard @@ -365,13 +359,11 @@ Completion get_iterator_values(VM& vm, Value iterable, IteratorValueCallback cal auto iterator_record = TRY(get_iterator(vm, iterable, IteratorHint::Sync)); while (true) { - auto next_object = TRY(iterator_step(vm, iterator_record)); - if (!next_object) + auto next = TRY(iterator_step_value(vm, iterator_record)); + if (!next.has_value()) return {}; - auto next_value = TRY(iterator_value(vm, *next_object)); - - if (auto completion = callback(next_value); completion.has_value()) + if (auto completion = callback(next.release_value()); completion.has_value()) return iterator_close(vm, iterator_record, completion.release_value()); } } diff --git a/Userland/Libraries/LibJS/Runtime/Iterator.h b/Userland/Libraries/LibJS/Runtime/Iterator.h index 7d8a56f79a..04a165ac3e 100644 --- a/Userland/Libraries/LibJS/Runtime/Iterator.h +++ b/Userland/Libraries/LibJS/Runtime/Iterator.h @@ -82,7 +82,7 @@ ThrowCompletionOr iterator_value(VM&, Object& iterator_result); Completion iterator_close(VM&, IteratorRecord const&, Completion); Completion async_iterator_close(VM&, IteratorRecord const&, Completion); NonnullGCPtr create_iterator_result_object(VM&, Value, bool done); -ThrowCompletionOr> iterator_to_list(VM&, IteratorRecord const&); +ThrowCompletionOr> iterator_to_list(VM&, IteratorRecord&); using IteratorValueCallback = Function(Value)>; Completion get_iterator_values(VM&, Value iterable, IteratorValueCallback callback); diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp index 92347275c9..696e6e8f9a 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp @@ -56,59 +56,37 @@ static ThrowCompletionOr perform_promise_common(VM& vm, IteratorRecord& i // 4. Repeat, while (true) { - // a. Let next be Completion(IteratorStep(iteratorRecord)). - auto next_or_error = iterator_step(vm, iterator_record); + // a. Let next be ? IteratorStepValue(iteratorRecord). + auto next = TRY(iterator_step_value(vm, iterator_record)); - // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. - // c. ReturnIfAbrupt(next). - if (next_or_error.is_throw_completion()) { - iterator_record.done = true; - return next_or_error.release_error(); - } - auto next = next_or_error.release_value(); - - // d. If next is false, then - if (!next) { - // i. Set iteratorRecord.[[Done]] to true. - iterator_record.done = true; - - // ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. - // iii. If remainingElementsCount.[[Value]] is 0, then + // b. If next is DONE, then + if (!next.has_value()) { + // i. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + // ii. If remainingElementsCount.[[Value]] = 0, then if (--remaining_elements_count->value == 0) { - // 1-2/3. are handled in `end_of_list` + // 1-2. are handled in `end_of_list` return TRY(end_of_list(*values)); } - // iv. Return resultCapability.[[Promise]]. + // iii. Return resultCapability.[[Promise]]. return result_capability.promise(); } - // e. Let nextValue be Completion(IteratorValue(next)). - auto next_value_or_error = iterator_value(vm, *next); - - // f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. - // g. ReturnIfAbrupt(nextValue). - if (next_value_or_error.is_throw_completion()) { - iterator_record.done = true; - return next_value_or_error.release_error(); - } - auto next_value = next_value_or_error.release_value(); - - // h. Append undefined to values. + // c. Append undefined to values. values->values().append(js_undefined()); - // i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). - auto next_promise = TRY(call(vm, promise_resolve.as_function(), constructor, next_value)); + // d. Let nextPromise be ? Call(promiseResolve, constructor, « next »). + auto next_promise = TRY(call(vm, promise_resolve.as_function(), constructor, next.release_value())); - // j-q. are handled in `invoke_element_function` + // e-l. are handled in `invoke_element_function` - // r. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1. + // m. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1. ++remaining_elements_count->value; - // s. Perform ? Invoke(nextPromise, "then", « ... »). + // n. Perform ? Invoke(nextPromise, "then", « ... »). TRY(invoke_element_function(*values, *remaining_elements_count, next_promise, index)); - // t. Set index to index + 1. + // o. Set index to index + 1. ++index; } } diff --git a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp index 59a0c0c2d6..22da3539fd 100644 --- a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp @@ -66,12 +66,12 @@ ThrowCompletionOr> SetConstructor::construct(FunctionObject // 7. Let iteratorRecord be ? GetIterator(iterable, sync). // 8. Repeat, - // a. Let next be ? IteratorStep(iteratorRecord). - // c. Let nextValue be ? IteratorValue(next). - (void)TRY(get_iterator_values(vm, iterable, [&](Value next_value) -> Optional { - // d. Let status be Completion(Call(adder, set, « nextValue »)). - // e. IfAbruptCloseIterator(status, iteratorRecord). - TRY(JS::call(vm, adder.as_function(), set, next_value)); + (void)TRY(get_iterator_values(vm, iterable, [&](Value next) -> Optional { + // a. Let next be ? IteratorStepValue(iteratorRecord). + // b. If next is DONE, return set. + // c. Let status be Completion(Call(adder, set, « nextValue »)). + // d. IfAbruptCloseIterator(status, iteratorRecord). + TRY(JS::call(vm, adder.as_function(), set, next)); return {}; })); diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index e100c10153..8e38d4f4ab 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -420,46 +420,27 @@ ThrowCompletionOr VM::iterator_binding_initialization(BindingPattern const // 3. Let n be 0. // 4. Repeat, while (true) { - ThrowCompletionOr> next { nullptr }; + // a. Let next be DONE. + Optional next; - // a. If iteratorRecord.[[Done]] is false, then + // b. If iteratorRecord.[[Done]] is false, then if (!iterator_record.done) { - // i. Let next be Completion(IteratorStep(iteratorRecord)). - next = iterator_step(vm, iterator_record); - - // ii. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. - // iii. ReturnIfAbrupt(next). - if (next.is_error()) { - iterator_record.done = true; - return next.release_error(); - } - - // iv. If next is false, set iteratorRecord.[[Done]] to true. - if (!next.value()) - iterator_record.done = true; + // i. Set next to ? IteratorStepValue(iteratorRecord). + next = TRY(iterator_step_value(vm, iterator_record)); } - // b. If iteratorRecord.[[Done]] is true, then - if (iterator_record.done) { + // c. If next is DONE, then + if (!next.has_value()) { // NOTE: Step i. and ii. are handled below. break; } - // c. Let nextValue be Completion(IteratorValue(next)). - auto next_value = iterator_value(vm, *next.value()); + // d. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next). + array->indexed_properties().append(next.release_value()); - // d. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. - // e. ReturnIfAbrupt(nextValue). - if (next_value.is_error()) { - iterator_record.done = true; - return next_value.release_error(); - } - - // f. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue). - array->indexed_properties().append(next_value.value()); - - // g. Set n to n + 1. + // e. Set n to n + 1. } + value = array; } // SingleNameBinding : BindingIdentifier Initializer[opt] @@ -470,32 +451,13 @@ ThrowCompletionOr VM::iterator_binding_initialization(BindingPattern const // 2. If iteratorRecord.[[Done]] is false, then if (!iterator_record.done) { - // a. Let next be Completion(IteratorStep(iteratorRecord)). - auto next = iterator_step(vm, iterator_record); + // a. Let next be ? IteratorStepValue(iteratorRecord). + auto next = TRY(iterator_step_value(vm, iterator_record)); - // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. - // c. ReturnIfAbrupt(next). - if (next.is_error()) { - iterator_record.done = true; - return next.release_error(); - } - - // d. If next is false, set iteratorRecord.[[Done]] to true. - if (!next.value()) { - iterator_record.done = true; - } - // e. Else, - else { - // i. Set v to Completion(IteratorValue(next)). - auto value_or_error = iterator_value(vm, *next.value()); - - // ii. If v is an abrupt completion, set iteratorRecord.[[Done]] to true. - // iii. ReturnIfAbrupt(v). - if (value_or_error.is_throw_completion()) { - iterator_record.done = true; - return value_or_error.release_error(); - } - value = value_or_error.release_value(); + // b. If next is not DONE, then + if (next.has_value()) { + // i. Set v to next. + value = next.release_value(); } } diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp index bc21497416..3c79c269ed 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp @@ -63,12 +63,12 @@ ThrowCompletionOr> WeakSetConstructor::construct(FunctionOb // 7. Let iteratorRecord be ? GetIterator(iterable, sync). // 8. Repeat, - // a. Let next be ? IteratorStep(iteratorRecord). - // c. Let nextValue be ? IteratorValue(next). - (void)TRY(get_iterator_values(vm, iterable, [&](Value next_value) -> Optional { - // d. Let status be Completion(Call(adder, set, « nextValue »)). - // e. IfAbruptCloseIterator(status, iteratorRecord). - TRY(JS::call(vm, adder.as_function(), set, next_value)); + (void)TRY(get_iterator_values(vm, iterable, [&](Value next) -> Optional { + // a. Let next be ? IteratorStepValue(iteratorRecord). + // c. If next is DONE, return set. + // c. Let status be Completion(Call(adder, set, « nextValue »)). + // d. IfAbruptCloseIterator(status, iteratorRecord). + TRY(JS::call(vm, adder.as_function(), set, next)); return {}; }));