mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-17 07:50:04 +00:00
LibJS: Use the IteratorStepValue AO in Iterator prototypes
This is an editorial change in the Iterator Helpers proposal. See:
b4ccc31
This commit is contained in:
parent
48bef246a0
commit
e782947a03
Notes:
github-actions[bot]
2024-08-27 17:01:26 +00:00
Author: https://github.com/trflynn89
Commit: e782947a03
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1206
2 changed files with 121 additions and 155 deletions
|
@ -24,6 +24,7 @@ public:
|
||||||
|
|
||||||
static ThrowCompletionOr<NonnullGCPtr<IteratorHelper>> create(Realm&, NonnullGCPtr<IteratorRecord>, NonnullGCPtr<Closure>, GCPtr<AbruptClosure> = {});
|
static ThrowCompletionOr<NonnullGCPtr<IteratorHelper>> create(Realm&, NonnullGCPtr<IteratorRecord>, NonnullGCPtr<Closure>, GCPtr<AbruptClosure> = {});
|
||||||
|
|
||||||
|
IteratorRecord& underlying_iterator() { return m_underlying_iterator; }
|
||||||
IteratorRecord const& underlying_iterator() const { return m_underlying_iterator; }
|
IteratorRecord const& underlying_iterator() const { return m_underlying_iterator; }
|
||||||
|
|
||||||
size_t counter() const { return m_counter; }
|
size_t counter() const { return m_counter; }
|
||||||
|
|
|
@ -99,34 +99,31 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::map)
|
||||||
|
|
||||||
// 5. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
|
// 5. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
|
||||||
auto closure = JS::create_heap_function(realm.heap(), [mapper = NonnullGCPtr { mapper.as_function() }](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
auto closure = JS::create_heap_function(realm.heap(), [mapper = NonnullGCPtr { mapper.as_function() }](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
||||||
auto const& iterated = iterator.underlying_iterator();
|
auto& iterated = iterator.underlying_iterator();
|
||||||
|
|
||||||
// a. Let counter be 0.
|
// a. Let counter be 0.
|
||||||
// b. Repeat,
|
// b. Repeat,
|
||||||
|
|
||||||
// i. Let next be ? IteratorStep(iterated).
|
// i. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// ii. If next is false, return undefined.
|
// ii. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return iterator.result(js_undefined());
|
return iterator.result(js_undefined());
|
||||||
|
|
||||||
// iii. Let value be ? IteratorValue(next).
|
// iii. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto mapped = call(vm, *mapper, js_undefined(), *value, Value { iterator.counter() });
|
||||||
|
|
||||||
// iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
|
// iv. IfAbruptCloseIterator(mapped, iterated).
|
||||||
auto mapped = call(vm, *mapper, js_undefined(), value, Value { iterator.counter() });
|
|
||||||
|
|
||||||
// v. IfAbruptCloseIterator(mapped, iterated).
|
|
||||||
if (mapped.is_error())
|
if (mapped.is_error())
|
||||||
return iterator.close_result(vm, mapped.release_error());
|
return iterator.close_result(vm, mapped.release_error());
|
||||||
|
|
||||||
// viii. Set counter to counter + 1.
|
// vii. Set counter to counter + 1.
|
||||||
// NOTE: We do this step early to ensure it occurs before returning.
|
// NOTE: We do this step early to ensure it occurs before returning.
|
||||||
iterator.increment_counter();
|
iterator.increment_counter();
|
||||||
|
|
||||||
// vi. Let completion be Completion(Yield(mapped)).
|
// v. Let completion be Completion(Yield(mapped)).
|
||||||
// vii. IfAbruptCloseIterator(completion, iterated).
|
// vi. IfAbruptCloseIterator(completion, iterated).
|
||||||
return iterator.result(mapped.release_value());
|
return iterator.result(mapped.release_value());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -158,38 +155,35 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::filter)
|
||||||
|
|
||||||
// 5. Let closure be a new Abstract Closure with no parameters that captures iterated and predicate and performs the following steps when called:
|
// 5. Let closure be a new Abstract Closure with no parameters that captures iterated and predicate and performs the following steps when called:
|
||||||
auto closure = JS::create_heap_function(realm.heap(), [predicate = NonnullGCPtr { predicate.as_function() }](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
auto closure = JS::create_heap_function(realm.heap(), [predicate = NonnullGCPtr { predicate.as_function() }](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
||||||
auto const& iterated = iterator.underlying_iterator();
|
auto& iterated = iterator.underlying_iterator();
|
||||||
|
|
||||||
// a. Let counter be 0.
|
// a. Let counter be 0.
|
||||||
|
|
||||||
// b. Repeat,
|
// b. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// i. Let next be ? IteratorStep(iterated).
|
// i. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// ii. If next is false, return undefined.
|
// ii. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return iterator.result(js_undefined());
|
return iterator.result(js_undefined());
|
||||||
|
|
||||||
// iii. Let value be ? IteratorValue(next).
|
// iii. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto selected = call(vm, *predicate, js_undefined(), *value, Value { iterator.counter() });
|
||||||
|
|
||||||
// iv. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
// iv. IfAbruptCloseIterator(selected, iterated).
|
||||||
auto selected = call(vm, *predicate, js_undefined(), value, Value { iterator.counter() });
|
|
||||||
|
|
||||||
// v. IfAbruptCloseIterator(selected, iterated).
|
|
||||||
if (selected.is_error())
|
if (selected.is_error())
|
||||||
return iterator.close_result(vm, selected.release_error());
|
return iterator.close_result(vm, selected.release_error());
|
||||||
|
|
||||||
// vii. Set counter to counter + 1.
|
// vi. Set counter to counter + 1.
|
||||||
// NOTE: We do this step early to ensure it occurs before returning.
|
// NOTE: We do this step early to ensure it occurs before returning.
|
||||||
iterator.increment_counter();
|
iterator.increment_counter();
|
||||||
|
|
||||||
// vi. If ToBoolean(selected) is true, then
|
// v. If ToBoolean(selected) is true, then
|
||||||
if (selected.value().to_boolean()) {
|
if (selected.value().to_boolean()) {
|
||||||
// 1. Let completion be Completion(Yield(value)).
|
// 1. Let completion be Completion(Yield(value)).
|
||||||
// 2. IfAbruptCloseIterator(completion, iterated).
|
// 2. IfAbruptCloseIterator(completion, iterated).
|
||||||
return iterator.result(value);
|
return iterator.result(*value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -232,7 +226,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::take)
|
||||||
|
|
||||||
// 8. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
|
// 8. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
|
||||||
auto closure = JS::create_heap_function(realm.heap(), [integer_limit](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
auto closure = JS::create_heap_function(realm.heap(), [integer_limit](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
||||||
auto const& iterated = iterator.underlying_iterator();
|
auto& iterated = iterator.underlying_iterator();
|
||||||
|
|
||||||
// a. Let remaining be integerLimit.
|
// a. Let remaining be integerLimit.
|
||||||
// b. Repeat,
|
// b. Repeat,
|
||||||
|
@ -247,16 +241,16 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::take)
|
||||||
// 1. Set remaining to remaining - 1.
|
// 1. Set remaining to remaining - 1.
|
||||||
iterator.increment_counter();
|
iterator.increment_counter();
|
||||||
|
|
||||||
// iii. Let next be ? IteratorStep(iterated).
|
// iii. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// iv. If next is false, return undefined.
|
// iv. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return iterator.result(js_undefined());
|
return iterator.result(js_undefined());
|
||||||
|
|
||||||
// v. Let completion be Completion(Yield(? IteratorValue(next))).
|
// v. Let completion be Completion(Yield(value)).
|
||||||
// vi. IfAbruptCloseIterator(completion, iterated).
|
// vi. IfAbruptCloseIterator(completion, iterated).
|
||||||
return iterator.result(TRY(iterator_value(vm, *next)));
|
return iterator.result(*value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 9. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
|
// 9. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
|
||||||
|
@ -297,7 +291,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::drop)
|
||||||
|
|
||||||
// 8. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
|
// 8. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
|
||||||
auto closure = JS::create_heap_function(realm.heap(), [integer_limit](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
auto closure = JS::create_heap_function(realm.heap(), [integer_limit](VM& vm, IteratorHelper& iterator) -> ThrowCompletionOr<Value> {
|
||||||
auto const& iterated = iterator.underlying_iterator();
|
auto& iterated = iterator.underlying_iterator();
|
||||||
|
|
||||||
// a. Let remaining be integerLimit.
|
// a. Let remaining be integerLimit.
|
||||||
// b. Repeat, while remaining > 0,
|
// b. Repeat, while remaining > 0,
|
||||||
|
@ -316,16 +310,16 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::drop)
|
||||||
|
|
||||||
// c. Repeat,
|
// c. Repeat,
|
||||||
|
|
||||||
// i. Let next be ? IteratorStep(iterated).
|
// i. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// ii. If next is false, return undefined.
|
// ii. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return iterator.result(js_undefined());
|
return iterator.result(js_undefined());
|
||||||
|
|
||||||
// iii. Let completion be Completion(Yield(? IteratorValue(next))).
|
// iii. Let completion be Completion(Yield(value)).
|
||||||
// iv. IfAbruptCloseIterator(completion, iterated).
|
// iv. IfAbruptCloseIterator(completion, iterated).
|
||||||
return iterator.result(TRY(iterator_value(vm, *next)));
|
return iterator.result(*value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 9. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
|
// 9. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
|
||||||
|
@ -341,19 +335,19 @@ class FlatMapIterator : public Cell {
|
||||||
JS_DECLARE_ALLOCATOR(FlatMapIterator);
|
JS_DECLARE_ALLOCATOR(FlatMapIterator);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ThrowCompletionOr<Value> next(VM& vm, IteratorRecord const& iterated, IteratorHelper& iterator, FunctionObject& mapper)
|
ThrowCompletionOr<Value> next(VM& vm, IteratorRecord& iterated, IteratorHelper& iterator, FunctionObject& mapper)
|
||||||
{
|
{
|
||||||
if (m_inner_iterator)
|
if (m_inner_iterator)
|
||||||
return next_inner_iterator(vm, iterated, iterator, mapper);
|
return next_inner_iterator(vm, iterated, iterator, mapper);
|
||||||
return next_outer_iterator(vm, iterated, iterator, mapper);
|
return next_outer_iterator(vm, iterated, iterator, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This implements step 5.b.ix.4.d of Iterator.prototype.flatMap.
|
// NOTE: This implements step 5.b.vii.4.b of Iterator.prototype.flatMap.
|
||||||
ThrowCompletionOr<Value> on_abrupt_completion(VM& vm, IteratorHelper& iterator, Completion const& completion)
|
ThrowCompletionOr<Value> on_abrupt_completion(VM& vm, IteratorHelper& iterator, Completion const& completion)
|
||||||
{
|
{
|
||||||
VERIFY(m_inner_iterator);
|
VERIFY(m_inner_iterator);
|
||||||
|
|
||||||
// d. If completion is an abrupt completion, then
|
// b. If completion is an abrupt completion, then
|
||||||
|
|
||||||
// i. Let backupCompletion be Completion(IteratorClose(innerIterator, completion)).
|
// i. Let backupCompletion be Completion(IteratorClose(innerIterator, completion)).
|
||||||
auto backup_completion = iterator_close(vm, *m_inner_iterator, completion);
|
auto backup_completion = iterator_close(vm, *m_inner_iterator, completion);
|
||||||
|
@ -375,56 +369,53 @@ private:
|
||||||
visitor.visit(m_inner_iterator);
|
visitor.visit(m_inner_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowCompletionOr<Value> next_outer_iterator(VM& vm, IteratorRecord const& iterated, IteratorHelper& iterator, FunctionObject& mapper)
|
ThrowCompletionOr<Value> next_outer_iterator(VM& vm, IteratorRecord& iterated, IteratorHelper& iterator, FunctionObject& mapper)
|
||||||
{
|
{
|
||||||
// i. Let next be ? IteratorStep(iterated).
|
// i. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// ii. If next is false, return undefined.
|
// ii. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return iterator.result(js_undefined());
|
return iterator.result(js_undefined());
|
||||||
|
|
||||||
// iii. Let value be ? IteratorValue(next).
|
// iii. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto mapped = call(vm, mapper, js_undefined(), *value, Value { iterator.counter() });
|
||||||
|
|
||||||
// iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
|
// iv. IfAbruptCloseIterator(mapped, iterated).
|
||||||
auto mapped = call(vm, mapper, js_undefined(), value, Value { iterator.counter() });
|
|
||||||
|
|
||||||
// v. IfAbruptCloseIterator(mapped, iterated).
|
|
||||||
if (mapped.is_error())
|
if (mapped.is_error())
|
||||||
return iterator.close_result(vm, mapped.release_error());
|
return iterator.close_result(vm, mapped.release_error());
|
||||||
|
|
||||||
// vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped, reject-strings)).
|
// v. Let innerIterator be Completion(GetIteratorFlattenable(mapped, reject-strings)).
|
||||||
auto inner_iterator = get_iterator_flattenable(vm, mapped.release_value(), StringHandling::RejectStrings);
|
auto inner_iterator = get_iterator_flattenable(vm, mapped.release_value(), StringHandling::RejectStrings);
|
||||||
|
|
||||||
// vii. IfAbruptCloseIterator(innerIterator, iterated).
|
// vi. IfAbruptCloseIterator(innerIterator, iterated).
|
||||||
if (inner_iterator.is_error())
|
if (inner_iterator.is_error())
|
||||||
return iterator.close_result(vm, inner_iterator.release_error());
|
return iterator.close_result(vm, inner_iterator.release_error());
|
||||||
|
|
||||||
// viii. Let innerAlive be true.
|
// vii. Let innerAlive be true.
|
||||||
m_inner_iterator = inner_iterator.release_value();
|
m_inner_iterator = inner_iterator.release_value();
|
||||||
|
|
||||||
// x. Set counter to counter + 1.
|
// ix. Set counter to counter + 1.
|
||||||
// NOTE: We do this step early to ensure it occurs before returning.
|
// NOTE: We do this step early to ensure it occurs before returning.
|
||||||
iterator.increment_counter();
|
iterator.increment_counter();
|
||||||
|
|
||||||
// ix. Repeat, while innerAlive is true,
|
// viii. Repeat, while innerAlive is true,
|
||||||
return next_inner_iterator(vm, iterated, iterator, mapper);
|
return next_inner_iterator(vm, iterated, iterator, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowCompletionOr<Value> next_inner_iterator(VM& vm, IteratorRecord const& iterated, IteratorHelper& iterator, FunctionObject& mapper)
|
ThrowCompletionOr<Value> next_inner_iterator(VM& vm, IteratorRecord& iterated, IteratorHelper& iterator, FunctionObject& mapper)
|
||||||
{
|
{
|
||||||
VERIFY(m_inner_iterator);
|
VERIFY(m_inner_iterator);
|
||||||
|
|
||||||
// 1. Let innerNext be Completion(IteratorStep(innerIterator)).
|
// 1. Let innerValue be Completion(IteratorStepValue(innerIterator)).
|
||||||
auto inner_next = iterator_step(vm, *m_inner_iterator);
|
auto inner_value = iterator_step_value(vm, *m_inner_iterator);
|
||||||
|
|
||||||
// 2. IfAbruptCloseIterator(innerNext, iterated).
|
// 2. IfAbruptCloseIterator(innerValue, iterated).
|
||||||
if (inner_next.is_error())
|
if (inner_value.is_error())
|
||||||
return iterator.close_result(vm, inner_next.release_error());
|
return iterator.close_result(vm, inner_value.release_error());
|
||||||
|
|
||||||
// 3. If innerNext is false, then
|
// 3. If innerValue is done, then
|
||||||
if (!inner_next.value()) {
|
if (!inner_value.value().has_value()) {
|
||||||
// a. Set innerAlive to false.
|
// a. Set innerAlive to false.
|
||||||
m_inner_iterator = nullptr;
|
m_inner_iterator = nullptr;
|
||||||
|
|
||||||
|
@ -432,16 +423,9 @@ private:
|
||||||
}
|
}
|
||||||
// 4. Else,
|
// 4. Else,
|
||||||
else {
|
else {
|
||||||
// a. Let innerValue be Completion(IteratorValue(innerNext)).
|
// a. Let completion be Completion(Yield(innerValue)).
|
||||||
auto inner_value = iterator_value(vm, *inner_next.release_value());
|
// NOTE: Step b is implemented via on_abrupt_completion.
|
||||||
|
return *inner_value.release_value();
|
||||||
// b. IfAbruptCloseIterator(innerValue, iterated).
|
|
||||||
if (inner_value.is_error())
|
|
||||||
return iterator.close_result(vm, inner_value.release_error());
|
|
||||||
|
|
||||||
// c. Let completion be Completion(Yield(innerValue)).
|
|
||||||
// NOTE: Step d is implemented via on_abrupt_completion.
|
|
||||||
return inner_value.release_value();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +456,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::flat_map)
|
||||||
|
|
||||||
// 5. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
|
// 5. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
|
||||||
auto closure = JS::create_heap_function(realm.heap(), [flat_map_iterator, mapper = NonnullGCPtr { mapper.as_function() }](VM& vm, IteratorHelper& iterator) mutable -> ThrowCompletionOr<Value> {
|
auto closure = JS::create_heap_function(realm.heap(), [flat_map_iterator, mapper = NonnullGCPtr { mapper.as_function() }](VM& vm, IteratorHelper& iterator) mutable -> ThrowCompletionOr<Value> {
|
||||||
auto const& iterated = iterator.underlying_iterator();
|
auto& iterated = iterator.underlying_iterator();
|
||||||
return flat_map_iterator->next(vm, iterated, iterator, *mapper);
|
return flat_map_iterator->next(vm, iterated, iterator, *mapper);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -509,18 +493,17 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::reduce)
|
||||||
|
|
||||||
// 5. If initialValue is not present, then
|
// 5. If initialValue is not present, then
|
||||||
if (vm.argument_count() < 2) {
|
if (vm.argument_count() < 2) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let accumulator be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto maybe_accumulator = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, throw a TypeError exception.
|
// b. If accumulator is done, throw a TypeError exception.
|
||||||
if (!next)
|
if (!maybe_accumulator.has_value())
|
||||||
return vm.throw_completion<TypeError>(ErrorType::ReduceNoInitial);
|
return vm.throw_completion<TypeError>(ErrorType::ReduceNoInitial);
|
||||||
|
|
||||||
// c. Let accumulator be ? IteratorValue(next).
|
|
||||||
accumulator = TRY(iterator_value(vm, *next));
|
|
||||||
|
|
||||||
// d. Let counter be 1.
|
// d. Let counter be 1.
|
||||||
counter = 1;
|
counter = 1;
|
||||||
|
|
||||||
|
accumulator = maybe_accumulator.release_value();
|
||||||
}
|
}
|
||||||
// 6. Else,
|
// 6. Else,
|
||||||
else {
|
else {
|
||||||
|
@ -533,27 +516,24 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::reduce)
|
||||||
|
|
||||||
// 7. Repeat,
|
// 7. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, return accumulator.
|
// b. If value is done, return accumulator.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return accumulator;
|
return accumulator;
|
||||||
|
|
||||||
// c. Let value be ? IteratorValue(next).
|
// c. Let result be Completion(Call(reducer, undefined, « accumulator, value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto result = call(vm, reducer.as_function(), js_undefined(), accumulator, *value, Value { counter });
|
||||||
|
|
||||||
// d. Let result be Completion(Call(reducer, undefined, « accumulator, value, 𝔽(counter) »)).
|
// d. IfAbruptCloseIterator(result, iterated).
|
||||||
auto result = call(vm, reducer.as_function(), js_undefined(), accumulator, value, Value { counter });
|
|
||||||
|
|
||||||
// e. IfAbruptCloseIterator(result, iterated).
|
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
||||||
|
|
||||||
// f. Set accumulator to result.[[Value]].
|
// e. Set accumulator to result.[[Value]].
|
||||||
accumulator = result.release_value();
|
accumulator = result.release_value();
|
||||||
|
|
||||||
// g. Set counter to counter + 1.
|
// f. Set counter to counter + 1.
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,18 +555,15 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::to_array)
|
||||||
|
|
||||||
// 5. Repeat,
|
// 5. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, return CreateArrayFromList(items).
|
// b. If value is done, return CreateArrayFromList(items).
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return Array::create_from(realm, items);
|
return Array::create_from(realm, items);
|
||||||
|
|
||||||
// c. Let value be ? IteratorValue(next).
|
// c. Append value to items.
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
TRY_OR_THROW_OOM(vm, items.try_append(*value));
|
||||||
|
|
||||||
// d. Append value to items.
|
|
||||||
TRY_OR_THROW_OOM(vm, items.try_append(value));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,24 +588,21 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::for_each)
|
||||||
|
|
||||||
// 6. Repeat,
|
// 6. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, return undefined.
|
// b. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
|
||||||
// c. Let value be ? IteratorValue(next).
|
// c. Let result be Completion(Call(fn, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto result = call(vm, function.as_function(), js_undefined(), *value, Value { counter });
|
||||||
|
|
||||||
// d. Let result be Completion(Call(fn, undefined, « value, 𝔽(counter) »)).
|
// d. IfAbruptCloseIterator(result, iterated).
|
||||||
auto result = call(vm, function.as_function(), js_undefined(), value, Value { counter });
|
|
||||||
|
|
||||||
// e. IfAbruptCloseIterator(result, iterated).
|
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
||||||
|
|
||||||
// f. Set counter to counter + 1.
|
// e. Set counter to counter + 1.
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,28 +628,25 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::some)
|
||||||
|
|
||||||
// 6. Repeat,
|
// 6. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, return false.
|
// b. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return Value { false };
|
return Value { false };
|
||||||
|
|
||||||
// c. Let value be ? IteratorValue(next).
|
// c. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto result = call(vm, predicate.as_function(), js_undefined(), *value, Value { counter });
|
||||||
|
|
||||||
// d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
// d. IfAbruptCloseIterator(result, iterated).
|
||||||
auto result = call(vm, predicate.as_function(), js_undefined(), value, Value { counter });
|
|
||||||
|
|
||||||
// e. IfAbruptCloseIterator(result, iterated).
|
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
||||||
|
|
||||||
// f. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(true)).
|
// e. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(true)).
|
||||||
if (result.value().to_boolean())
|
if (result.value().to_boolean())
|
||||||
return *TRY(iterator_close(vm, iterated, normal_completion(Value { true })));
|
return *TRY(iterator_close(vm, iterated, normal_completion(Value { true })));
|
||||||
|
|
||||||
// g. Set counter to counter + 1.
|
// f. Set counter to counter + 1.
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -701,28 +672,25 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::every)
|
||||||
|
|
||||||
// 6. Repeat,
|
// 6. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, return true.
|
// b. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return Value { true };
|
return Value { true };
|
||||||
|
|
||||||
// c. Let value be ? IteratorValue(next).
|
// c. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto result = call(vm, predicate.as_function(), js_undefined(), *value, Value { counter });
|
||||||
|
|
||||||
// d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
// d. IfAbruptCloseIterator(result, iterated).
|
||||||
auto result = call(vm, predicate.as_function(), js_undefined(), value, Value { counter });
|
|
||||||
|
|
||||||
// e. IfAbruptCloseIterator(result, iterated).
|
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
||||||
|
|
||||||
// f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
|
// e. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
|
||||||
if (!result.value().to_boolean())
|
if (!result.value().to_boolean())
|
||||||
return *TRY(iterator_close(vm, iterated, normal_completion(Value { false })));
|
return *TRY(iterator_close(vm, iterated, normal_completion(Value { false })));
|
||||||
|
|
||||||
// g. Set counter to counter + 1.
|
// f. Set counter to counter + 1.
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,28 +716,25 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::find)
|
||||||
|
|
||||||
// 6. Repeat,
|
// 6. Repeat,
|
||||||
while (true) {
|
while (true) {
|
||||||
// a. Let next be ? IteratorStep(iterated).
|
// a. Let value be ? IteratorStepValue(iterated).
|
||||||
auto next = TRY(iterator_step(vm, iterated));
|
auto value = TRY(iterator_step_value(vm, iterated));
|
||||||
|
|
||||||
// b. If next is false, return undefined.
|
// b. If value is done, return undefined.
|
||||||
if (!next)
|
if (!value.has_value())
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
|
|
||||||
// c. Let value be ? IteratorValue(next).
|
// c. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
||||||
auto value = TRY(iterator_value(vm, *next));
|
auto result = call(vm, predicate.as_function(), js_undefined(), *value, Value { counter });
|
||||||
|
|
||||||
// d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
|
// d. IfAbruptCloseIterator(result, iterated).
|
||||||
auto result = call(vm, predicate.as_function(), js_undefined(), value, Value { counter });
|
|
||||||
|
|
||||||
// e. IfAbruptCloseIterator(result, iterated).
|
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
return *TRY(iterator_close(vm, iterated, result.release_error()));
|
||||||
|
|
||||||
// f. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(value)).
|
// e. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(value)).
|
||||||
if (result.value().to_boolean())
|
if (result.value().to_boolean())
|
||||||
return *TRY(iterator_close(vm, iterated, normal_completion(value)));
|
return *TRY(iterator_close(vm, iterated, normal_completion(value)));
|
||||||
|
|
||||||
// g. Set counter to counter + 1.
|
// f. Set counter to counter + 1.
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue