Просмотр исходного кода

LibJS: Implement the IteratorStepValue AO

This is an editorial change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/12d3687

This AO is meant to replace usages of IteratorNext followed by
IteratorValue with a single operation.
Timothy Flynn 1 год назад
Родитель
Сommit
2b96e732dd

+ 61 - 6
Userland/Libraries/LibJS/Runtime/Iterator.cpp

@@ -195,8 +195,63 @@ ThrowCompletionOr<GCPtr<Object>> iterator_step(VM& vm, IteratorRecord const& ite
     return result;
 }
 
-// 7.4.8 IteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-iteratorclose
-// 7.4.10 AsyncIteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-asynciteratorclose
+// 7.4.8 IteratorStepValue ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstepvalue
+ThrowCompletionOr<Optional<Value>> 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
+    if (done.is_throw_completion()) {
+        // a. Set iteratorRecord.[[Done]] to true.
+        iterator_record.done = true;
+
+        // b. Return ? done.
+        return done.release_error();
+    }
+
+    // 6. Set done to ! done.
+    auto done_value = done.release_value();
+
+    // 7. If done is true, then
+    if (done_value) {
+        // a. Set iteratorRecord.[[Done]] to true.
+        iterator_record.done = true;
+
+        // b. Return DONE.
+        return OptionalNone {};
+    }
+
+    // 8. Let value be Completion(Get(result, "value")).
+    auto value = result_value->get(vm.names.value);
+
+    // 9. 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.
+    return TRY(value);
+}
+
+// 7.4.9 IteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-iteratorclose
+// 7.4.11 AsyncIteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-asynciteratorclose
 // NOTE: These only differ in that async awaits the inner value after the call.
 static Completion iterator_close_impl(VM& vm, IteratorRecord const& iterator_record, Completion completion, IteratorHint iterator_hint)
 {
@@ -246,19 +301,19 @@ static Completion iterator_close_impl(VM& vm, IteratorRecord const& iterator_rec
     return completion;
 }
 
-// 7.4.8 IteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-iteratorclose
+// 7.4.9 IteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-iteratorclose
 Completion iterator_close(VM& vm, IteratorRecord const& iterator_record, Completion completion)
 {
     return iterator_close_impl(vm, iterator_record, move(completion), IteratorHint::Sync);
 }
 
-// 7.4.10 AsyncIteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-asynciteratorclose
+// 7.4.11 AsyncIteratorClose ( iteratorRecord, completion ), https://tc39.es/ecma262/#sec-asynciteratorclose
 Completion async_iterator_close(VM& vm, IteratorRecord const& iterator_record, Completion completion)
 {
     return iterator_close_impl(vm, iterator_record, move(completion), IteratorHint::Async);
 }
 
-// 7.4.11 CreateIterResultObject ( value, done ), https://tc39.es/ecma262/#sec-createiterresultobject
+// 7.4.12 CreateIterResultObject ( value, done ), https://tc39.es/ecma262/#sec-createiterresultobject
 NonnullGCPtr<Object> create_iterator_result_object(VM& vm, Value value, bool done)
 {
     auto& realm = *vm.current_realm();
@@ -276,7 +331,7 @@ NonnullGCPtr<Object> create_iterator_result_object(VM& vm, Value value, bool don
     return object;
 }
 
-// 7.4.13 IteratorToList ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratortolist
+// 7.4.14 IteratorToList ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratortolist
 ThrowCompletionOr<MarkedVector<Value>> iterator_to_list(VM& vm, IteratorRecord const& iterator_record)
 {
     // 1. Let values be a new empty List.

+ 1 - 0
Userland/Libraries/LibJS/Runtime/Iterator.h

@@ -76,6 +76,7 @@ ThrowCompletionOr<NonnullGCPtr<IteratorRecord>> get_iterator_direct(VM&, Object&
 ThrowCompletionOr<NonnullGCPtr<IteratorRecord>> get_iterator_flattenable(VM&, Value, StringHandling);
 ThrowCompletionOr<NonnullGCPtr<Object>> iterator_next(VM&, IteratorRecord const&, Optional<Value> = {});
 ThrowCompletionOr<GCPtr<Object>> iterator_step(VM&, IteratorRecord const&);
+ThrowCompletionOr<Optional<Value>> iterator_step_value(VM&, IteratorRecord&);
 ThrowCompletionOr<bool> iterator_complete(VM&, Object& iterator_result);
 ThrowCompletionOr<Value> iterator_value(VM&, Object& iterator_result);
 Completion iterator_close(VM&, IteratorRecord const&, Completion);