From 9d7215c636eebfb03c0f9dc6e5be25d66e82d1b5 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 19 Jul 2023 06:54:48 -0400 Subject: [PATCH] LibJS+LibWeb: Move IteratorOperations.h AOs to Iterator.h Rather than splitting the Iterator type and its AOs into two files, let's combine them into one file to match every other JS runtime object that we have. --- .../BindingsGenerator/IDLGenerators.cpp | 6 +- Userland/Libraries/LibJS/AST.cpp | 2 +- Userland/Libraries/LibJS/Bytecode/Op.cpp | 1 - Userland/Libraries/LibJS/Bytecode/Op.h | 2 +- Userland/Libraries/LibJS/CMakeLists.txt | 1 - .../LibJS/Runtime/AbstractOperations.h | 2 +- .../Runtime/AggregateErrorConstructor.cpp | 2 +- .../LibJS/Runtime/ArrayConstructor.cpp | 2 +- .../LibJS/Runtime/ArrayIteratorPrototype.cpp | 2 +- .../AsyncFromSyncIteratorPrototype.cpp | 2 +- .../LibJS/Runtime/AsyncGeneratorPrototype.cpp | 2 +- .../LibJS/Runtime/GeneratorObject.cpp | 2 +- .../LibJS/Runtime/Intl/ListFormat.cpp | 2 +- .../Runtime/Intl/SegmentIteratorPrototype.cpp | 2 +- Userland/Libraries/LibJS/Runtime/Iterator.cpp | 244 +++++++++++++++++ Userland/Libraries/LibJS/Runtime/Iterator.h | 23 +- .../LibJS/Runtime/IteratorHelper.cpp | 2 +- .../LibJS/Runtime/IteratorHelperPrototype.cpp | 2 +- .../LibJS/Runtime/IteratorOperations.cpp | 256 ------------------ .../LibJS/Runtime/IteratorOperations.h | 39 --- .../LibJS/Runtime/IteratorPrototype.cpp | 2 +- .../LibJS/Runtime/MapConstructor.cpp | 2 +- .../LibJS/Runtime/MapIteratorPrototype.cpp | 2 +- .../LibJS/Runtime/ObjectConstructor.cpp | 2 +- .../LibJS/Runtime/PromiseConstructor.cpp | 2 +- .../Runtime/RegExpStringIteratorPrototype.cpp | 2 +- .../LibJS/Runtime/SetConstructor.cpp | 2 +- .../LibJS/Runtime/SetIteratorPrototype.cpp | 2 +- .../Libraries/LibJS/Runtime/SetPrototype.cpp | 2 +- .../LibJS/Runtime/StringIteratorPrototype.cpp | 2 +- .../Runtime/SuppressedErrorConstructor.cpp | 2 +- .../Runtime/Temporal/AbstractOperations.cpp | 2 +- .../Runtime/Temporal/CalendarPrototype.cpp | 2 +- .../LibJS/Runtime/Temporal/TimeZone.cpp | 2 +- .../Libraries/LibJS/Runtime/TypedArray.cpp | 2 +- .../LibJS/Runtime/TypedArrayConstructor.cpp | 2 +- Userland/Libraries/LibJS/Runtime/VM.cpp | 1 - .../LibJS/Runtime/WeakMapConstructor.cpp | 2 +- .../LibJS/Runtime/WeakSetConstructor.cpp | 2 +- .../Runtime/WrapForValidIteratorPrototype.cpp | 2 +- .../LibWeb/Fetch/HeadersIterator.cpp | 2 +- .../CustomElements/CustomElementRegistry.cpp | 2 +- .../Streams/ReadableStreamDefaultReader.cpp | 2 +- .../LibWeb/URL/URLSearchParamsIterator.cpp | 2 +- .../LibWeb/WebAssembly/WebAssembly.cpp | 2 +- .../Libraries/LibWeb/XHR/FormDataIterator.cpp | 2 +- 46 files changed, 307 insertions(+), 340 deletions(-) delete mode 100644 Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp delete mode 100644 Userland/Libraries/LibJS/Runtime/IteratorOperations.h diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index bb0066d5f3..aa34dd939e 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -3264,7 +3264,7 @@ void generate_constructor_implementation(IDL::Interface const& interface, String #include #include #include -#include +#include #include #include #include @@ -3651,7 +3651,7 @@ void generate_prototype_implementation(IDL::Interface const& interface, StringBu #include #include #include -#include +#include #include #include #include @@ -3954,7 +3954,7 @@ void generate_global_mixin_implementation(IDL::Interface const& interface, Strin #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 99f1161238..c0c6e48cba 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 6152b5f61c..52d5d835bc 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 7a54522dff..e111aaf7e9 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index 0f249e9f37..3e0d8e5f5f 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -147,7 +147,6 @@ set(SOURCES Runtime/IteratorConstructor.cpp Runtime/IteratorHelper.cpp Runtime/IteratorHelperPrototype.cpp - Runtime/IteratorOperations.cpp Runtime/IteratorPrototype.cpp Runtime/JSONObject.cpp Runtime/JobCallback.cpp diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index 153a03f6d6..bbf1e93eee 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp index f14965c9eb..1b8cbf50fc 100644 --- a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp index fa6110bf8c..075b4b3511 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp index 89498d7560..b1f0b85a9c 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp index 8d9aed3627..a261a9a3b6 100644 --- a/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/AsyncFromSyncIteratorPrototype.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp index 0fad0e3c1b..096142d9a8 100644 --- a/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/AsyncGeneratorPrototype.cpp @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp index 39ab4e66fc..63b3a55446 100644 --- a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/Intl/ListFormat.cpp b/Userland/Libraries/LibJS/Runtime/Intl/ListFormat.cpp index 1b16be66a4..7f0d62f4d9 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/ListFormat.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/ListFormat.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include namespace JS::Intl { diff --git a/Userland/Libraries/LibJS/Runtime/Intl/SegmentIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/SegmentIteratorPrototype.cpp index b1f1877694..41f98a7edd 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/SegmentIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/SegmentIteratorPrototype.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include namespace JS::Intl { diff --git a/Userland/Libraries/LibJS/Runtime/Iterator.cpp b/Userland/Libraries/LibJS/Runtime/Iterator.cpp index dc49d57021..f33b6090a7 100644 --- a/Userland/Libraries/LibJS/Runtime/Iterator.cpp +++ b/Userland/Libraries/LibJS/Runtime/Iterator.cpp @@ -1,10 +1,15 @@ /* + * Copyright (c) 2020, Matthew Olsson + * Copyright (c) 2022-2023, Linus Groh * Copyright (c) 2023, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #include +#include +#include +#include #include #include @@ -26,6 +31,66 @@ Iterator::Iterator(Object& prototype) { } +// 7.4.2 GetIteratorFromMethod ( obj, method ), https://tc39.es/ecma262/#sec-getiteratorfrommethod +ThrowCompletionOr get_iterator_from_method(VM& vm, Value object, NonnullGCPtr method) +{ + // 1. Let iterator be ? Call(method, obj). + auto iterator = TRY(call(vm, *method, object)); + + // 2. If iterator is not an Object, throw a TypeError exception. + if (!iterator.is_object()) + return vm.throw_completion(ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, object.to_string_without_side_effects())); + + // 3. Let nextMethod be ? Get(iterator, "next"). + auto next_method = TRY(iterator.get(vm, vm.names.next)); + + // 4. Let iteratorRecord be the Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }. + auto iterator_record = IteratorRecord { .iterator = &iterator.as_object(), .next_method = next_method, .done = false }; + + // 5. Return iteratorRecord. + return iterator_record; +} + +// 7.4.3 GetIterator ( obj, kind ), https://tc39.es/ecma262/#sec-getiterator +ThrowCompletionOr get_iterator(VM& vm, Value object, IteratorHint kind) +{ + JS::GCPtr method; + + // 1. If kind is async, then + if (kind == IteratorHint::Async) { + // a. Let method be ? GetMethod(obj, @@asyncIterator). + method = TRY(object.get_method(vm, vm.well_known_symbol_async_iterator())); + + // b. If method is undefined, then + if (!method) { + // i. Let syncMethod be ? GetMethod(obj, @@iterator). + auto sync_method = TRY(object.get_method(vm, vm.well_known_symbol_iterator())); + + // ii. If syncMethod is undefined, throw a TypeError exception. + if (!sync_method) + return vm.throw_completion(ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, object.to_string_without_side_effects())); + + // iii. Let syncIteratorRecord be ? GetIteratorFromMethod(obj, syncMethod). + auto sync_iterator_record = TRY(get_iterator_from_method(vm, object, *sync_method)); + + // iv. Return CreateAsyncFromSyncIterator(syncIteratorRecord). + return create_async_from_sync_iterator(vm, sync_iterator_record); + } + } + // 2. Else, + else { + // a. Let method be ? GetMethod(obj, @@iterator). + method = TRY(object.get_method(vm, vm.well_known_symbol_iterator())); + } + + // 3. If method is undefined, throw a TypeError exception. + if (!method) + return vm.throw_completion(ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, object.to_string_without_side_effects())); + + // 4. Return ? GetIteratorFromMethod(obj, method). + return TRY(get_iterator_from_method(vm, object, *method)); +} + // 2.1.1 GetIteratorDirect ( obj ), https://tc39.es/proposal-iterator-helpers/#sec-getiteratorflattenable ThrowCompletionOr get_iterator_direct(VM& vm, Object& object) { @@ -73,4 +138,183 @@ ThrowCompletionOr get_iterator_flattenable(VM& vm, Value object, return TRY(get_iterator_direct(vm, iterator.as_object())); } +// 7.4.4 IteratorNext ( iteratorRecord [ , value ] ), https://tc39.es/ecma262/#sec-iteratornext +ThrowCompletionOr> iterator_next(VM& vm, IteratorRecord const& iterator_record, Optional value) +{ + Value result; + + // 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 Type(result) is not Object, throw a TypeError exception. + if (!result.is_object()) + return vm.throw_completion(ErrorType::IterableNextBadReturn); + + // 4. Return result. + return result.as_object(); +} + +// 7.4.5 IteratorComplete ( iterResult ), https://tc39.es/ecma262/#sec-iteratorcomplete +ThrowCompletionOr iterator_complete(VM& vm, Object& iterator_result) +{ + // 1. Return ToBoolean(? Get(iterResult, "done")). + return TRY(iterator_result.get(vm.names.done)).to_boolean(); +} + +// 7.4.6 IteratorValue ( iterResult ), https://tc39.es/ecma262/#sec-iteratorvalue +ThrowCompletionOr iterator_value(VM& vm, Object& iterator_result) +{ + // 1. Return ? Get(iterResult, "value"). + return TRY(iterator_result.get(vm.names.value)); +} + +// 7.4.7 IteratorStep ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstep +ThrowCompletionOr> iterator_step(VM& vm, IteratorRecord const& 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)); + + // 3. If done is true, return false. + if (done) + return nullptr; + + // 4. Return result. + 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 +// 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) +{ + // 1. Assert: Type(iteratorRecord.[[Iterator]]) is Object. + + // 2. Let iterator be iteratorRecord.[[Iterator]]. + auto iterator = iterator_record.iterator; + + // 3. Let innerResult be Completion(GetMethod(iterator, "return")). + auto inner_result = ThrowCompletionOr { js_undefined() }; + auto get_method_result = Value(iterator).get_method(vm, vm.names.return_); + if (get_method_result.is_error()) + inner_result = get_method_result.release_error(); + + // 4. If innerResult.[[Type]] is normal, then + if (!inner_result.is_error()) { + // a. Let return be innerResult.[[Value]]. + auto return_method = get_method_result.value(); + + // b. If return is undefined, return ? completion. + if (!return_method) + return completion; + + // c. Set innerResult to Completion(Call(return, iterator)). + inner_result = call(vm, return_method, iterator); + + // Note: If this is AsyncIteratorClose perform one extra step. + if (iterator_hint == IteratorHint::Async && !inner_result.is_error()) { + // d. If innerResult.[[Type]] is normal, set innerResult to Completion(Await(innerResult.[[Value]])). + inner_result = await(vm, inner_result.value()); + } + } + + // 5. If completion.[[Type]] is throw, return ? completion. + if (completion.is_error()) + return completion; + + // 6. If innerResult.[[Type]] is throw, return ? innerResult. + if (inner_result.is_throw_completion()) + return inner_result; + + // 7. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. + if (!inner_result.value().is_object()) + return vm.throw_completion(ErrorType::IterableReturnBadReturn); + + // 8. Return ? completion. + return completion; +} + +// 7.4.8 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 +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 +NonnullGCPtr create_iterator_result_object(VM& vm, Value value, bool done) +{ + auto& realm = *vm.current_realm(); + + // 1. Let obj be OrdinaryObjectCreate(%Object.prototype%). + auto object = Object::create(realm, realm.intrinsics().object_prototype()); + + // 2. Perform ! CreateDataPropertyOrThrow(obj, "value", value). + MUST(object->create_data_property_or_throw(vm.names.value, value)); + + // 3. Perform ! CreateDataPropertyOrThrow(obj, "done", done). + MUST(object->create_data_property_or_throw(vm.names.done, Value(done))); + + // 4. Return obj. + return object; +} + +// 7.4.13 IteratorToList ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratortolist +ThrowCompletionOr> iterator_to_list(VM& vm, IteratorRecord const& iterator_record) +{ + // 1. Let values be a new empty List. + MarkedVector values(vm.heap()); + + // 2. Let next be true. + GCPtr next; + + // 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)); + } + } while (next); + + // 4. Return values. + return values; +} + +// Non-standard +Completion get_iterator_values(VM& vm, Value iterable, IteratorValueCallback callback) +{ + auto iterator_record = TRY(get_iterator(vm, iterable, IteratorHint::Sync)); + + while (true) { + auto next_object = TRY(iterator_step(vm, iterator_record)); + if (!next_object) + return {}; + + auto next_value = TRY(iterator_value(vm, *next_object)); + + if (auto completion = callback(next_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 27ca5f3117..f826ca3876 100644 --- a/Userland/Libraries/LibJS/Runtime/Iterator.h +++ b/Userland/Libraries/LibJS/Runtime/Iterator.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2022, Linus Groh + * Copyright (c) 2020, Matthew Olsson + * Copyright (c) 2022-2023, Linus Groh * Copyright (c) 2023, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause @@ -7,6 +8,8 @@ #pragma once +#include +#include #include #include #include @@ -35,12 +38,30 @@ private: IteratorRecord m_iterated; // [[Iterated]] }; +enum class IteratorHint { + Sync, + Async, +}; + enum class StringHandling { IterateStrings, RejectStrings, }; +ThrowCompletionOr get_iterator_from_method(VM&, Value, NonnullGCPtr); +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_complete(VM&, Object& iterator_result); +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&); + +using IteratorValueCallback = Function(Value)>; +Completion get_iterator_values(VM&, Value iterable, IteratorValueCallback callback); } diff --git a/Userland/Libraries/LibJS/Runtime/IteratorHelper.cpp b/Userland/Libraries/LibJS/Runtime/IteratorHelper.cpp index 04cab652e3..011e1439b8 100644 --- a/Userland/Libraries/LibJS/Runtime/IteratorHelper.cpp +++ b/Userland/Libraries/LibJS/Runtime/IteratorHelper.cpp @@ -5,8 +5,8 @@ */ #include +#include #include -#include #include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/IteratorHelperPrototype.cpp b/Userland/Libraries/LibJS/Runtime/IteratorHelperPrototype.cpp index cd406e7510..f3f7128b73 100644 --- a/Userland/Libraries/LibJS/Runtime/IteratorHelperPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/IteratorHelperPrototype.cpp @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include -#include #include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp b/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp deleted file mode 100644 index b71171f38e..0000000000 --- a/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2020, Matthew Olsson - * Copyright (c) 2022-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace JS { - -// 7.4.2 GetIteratorFromMethod ( obj, method ), https://tc39.es/ecma262/#sec-getiteratorfrommethod -ThrowCompletionOr get_iterator_from_method(VM& vm, Value object, NonnullGCPtr method) -{ - // 1. Let iterator be ? Call(method, obj). - auto iterator = TRY(call(vm, *method, object)); - - // 2. If iterator is not an Object, throw a TypeError exception. - if (!iterator.is_object()) - return vm.throw_completion(ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, object.to_string_without_side_effects())); - - // 3. Let nextMethod be ? Get(iterator, "next"). - auto next_method = TRY(iterator.get(vm, vm.names.next)); - - // 4. Let iteratorRecord be the Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }. - auto iterator_record = IteratorRecord { .iterator = &iterator.as_object(), .next_method = next_method, .done = false }; - - // 5. Return iteratorRecord. - return iterator_record; -} - -// 7.4.3 GetIterator ( obj, kind ), https://tc39.es/ecma262/#sec-getiterator -ThrowCompletionOr get_iterator(VM& vm, Value object, IteratorHint kind) -{ - JS::GCPtr method; - - // 1. If kind is async, then - if (kind == IteratorHint::Async) { - // a. Let method be ? GetMethod(obj, @@asyncIterator). - method = TRY(object.get_method(vm, vm.well_known_symbol_async_iterator())); - - // b. If method is undefined, then - if (!method) { - // i. Let syncMethod be ? GetMethod(obj, @@iterator). - auto sync_method = TRY(object.get_method(vm, vm.well_known_symbol_iterator())); - - // ii. If syncMethod is undefined, throw a TypeError exception. - if (!sync_method) - return vm.throw_completion(ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, object.to_string_without_side_effects())); - - // iii. Let syncIteratorRecord be ? GetIteratorFromMethod(obj, syncMethod). - auto sync_iterator_record = TRY(get_iterator_from_method(vm, object, *sync_method)); - - // iv. Return CreateAsyncFromSyncIterator(syncIteratorRecord). - return create_async_from_sync_iterator(vm, sync_iterator_record); - } - } - // 2. Else, - else { - // a. Let method be ? GetMethod(obj, @@iterator). - method = TRY(object.get_method(vm, vm.well_known_symbol_iterator())); - } - - // 3. If method is undefined, throw a TypeError exception. - if (!method) - return vm.throw_completion(ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, object.to_string_without_side_effects())); - - // 4. Return ? GetIteratorFromMethod(obj, method). - return TRY(get_iterator_from_method(vm, object, *method)); -} - -// 7.4.4 IteratorNext ( iteratorRecord [ , value ] ), https://tc39.es/ecma262/#sec-iteratornext -ThrowCompletionOr> iterator_next(VM& vm, IteratorRecord const& iterator_record, Optional value) -{ - Value result; - - // 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 Type(result) is not Object, throw a TypeError exception. - if (!result.is_object()) - return vm.throw_completion(ErrorType::IterableNextBadReturn); - - // 4. Return result. - return result.as_object(); -} - -// 7.4.5 IteratorComplete ( iterResult ), https://tc39.es/ecma262/#sec-iteratorcomplete -ThrowCompletionOr iterator_complete(VM& vm, Object& iterator_result) -{ - // 1. Return ToBoolean(? Get(iterResult, "done")). - return TRY(iterator_result.get(vm.names.done)).to_boolean(); -} - -// 7.4.6 IteratorValue ( iterResult ), https://tc39.es/ecma262/#sec-iteratorvalue -ThrowCompletionOr iterator_value(VM& vm, Object& iterator_result) -{ - // 1. Return ? Get(iterResult, "value"). - return TRY(iterator_result.get(vm.names.value)); -} - -// 7.4.7 IteratorStep ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstep -ThrowCompletionOr> iterator_step(VM& vm, IteratorRecord const& 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)); - - // 3. If done is true, return false. - if (done) - return nullptr; - - // 4. Return result. - 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 -// 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) -{ - // 1. Assert: Type(iteratorRecord.[[Iterator]]) is Object. - - // 2. Let iterator be iteratorRecord.[[Iterator]]. - auto iterator = iterator_record.iterator; - - // 3. Let innerResult be Completion(GetMethod(iterator, "return")). - auto inner_result = ThrowCompletionOr { js_undefined() }; - auto get_method_result = Value(iterator).get_method(vm, vm.names.return_); - if (get_method_result.is_error()) - inner_result = get_method_result.release_error(); - - // 4. If innerResult.[[Type]] is normal, then - if (!inner_result.is_error()) { - // a. Let return be innerResult.[[Value]]. - auto return_method = get_method_result.value(); - - // b. If return is undefined, return ? completion. - if (!return_method) - return completion; - - // c. Set innerResult to Completion(Call(return, iterator)). - inner_result = call(vm, return_method, iterator); - - // Note: If this is AsyncIteratorClose perform one extra step. - if (iterator_hint == IteratorHint::Async && !inner_result.is_error()) { - // d. If innerResult.[[Type]] is normal, set innerResult to Completion(Await(innerResult.[[Value]])). - inner_result = await(vm, inner_result.value()); - } - } - - // 5. If completion.[[Type]] is throw, return ? completion. - if (completion.is_error()) - return completion; - - // 6. If innerResult.[[Type]] is throw, return ? innerResult. - if (inner_result.is_throw_completion()) - return inner_result; - - // 7. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. - if (!inner_result.value().is_object()) - return vm.throw_completion(ErrorType::IterableReturnBadReturn); - - // 8. Return ? completion. - return completion; -} - -// 7.4.8 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 -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 -NonnullGCPtr create_iterator_result_object(VM& vm, Value value, bool done) -{ - auto& realm = *vm.current_realm(); - - // 1. Let obj be OrdinaryObjectCreate(%Object.prototype%). - auto object = Object::create(realm, realm.intrinsics().object_prototype()); - - // 2. Perform ! CreateDataPropertyOrThrow(obj, "value", value). - MUST(object->create_data_property_or_throw(vm.names.value, value)); - - // 3. Perform ! CreateDataPropertyOrThrow(obj, "done", done). - MUST(object->create_data_property_or_throw(vm.names.done, Value(done))); - - // 4. Return obj. - return object; -} - -// 7.4.13 IteratorToList ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratortolist -ThrowCompletionOr> iterator_to_list(VM& vm, IteratorRecord const& iterator_record) -{ - // 1. Let values be a new empty List. - MarkedVector values(vm.heap()); - - // 2. Let next be true. - GCPtr next; - - // 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)); - } - } while (next); - - // 4. Return values. - return values; -} - -// Non-standard -Completion get_iterator_values(VM& vm, Value iterable, IteratorValueCallback callback) -{ - auto iterator_record = TRY(get_iterator(vm, iterable, IteratorHint::Sync)); - - while (true) { - auto next_object = TRY(iterator_step(vm, iterator_record)); - if (!next_object) - return {}; - - auto next_value = TRY(iterator_value(vm, *next_object)); - - if (auto completion = callback(next_value); completion.has_value()) - return iterator_close(vm, iterator_record, completion.release_value()); - } -} - -} diff --git a/Userland/Libraries/LibJS/Runtime/IteratorOperations.h b/Userland/Libraries/LibJS/Runtime/IteratorOperations.h deleted file mode 100644 index 6b6a6b2eb3..0000000000 --- a/Userland/Libraries/LibJS/Runtime/IteratorOperations.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020, Matthew Olsson - * Copyright (c) 2022-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace JS { - -// 7.4 Operations on Iterator Objects, https://tc39.es/ecma262/#sec-operations-on-iterator-objects - -enum class IteratorHint { - Sync, - Async, -}; - -ThrowCompletionOr get_iterator_from_method(VM&, Value, NonnullGCPtr); -ThrowCompletionOr get_iterator(VM&, Value, IteratorHint); -ThrowCompletionOr> iterator_next(VM&, IteratorRecord const&, Optional = {}); -ThrowCompletionOr> iterator_step(VM&, IteratorRecord const&); -ThrowCompletionOr iterator_complete(VM&, Object& iterator_result); -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&); - -using IteratorValueCallback = Function(Value)>; -Completion get_iterator_values(VM&, Value iterable, IteratorValueCallback callback); - -} diff --git a/Userland/Libraries/LibJS/Runtime/IteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/IteratorPrototype.cpp index dda30cca57..2600d94fd0 100644 --- a/Userland/Libraries/LibJS/Runtime/IteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/IteratorPrototype.cpp @@ -9,8 +9,8 @@ #include #include #include +#include #include -#include #include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp index d9681d26ec..1a88ad81df 100644 --- a/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/MapIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/MapIteratorPrototype.cpp index f6ec485482..258385303e 100644 --- a/Userland/Libraries/LibJS/Runtime/MapIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/MapIteratorPrototype.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp index f6ca78dfa2..b741c62f11 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp index 864deccaad..6cc318e835 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp index d697751204..36d0a78b1b 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp index 21354b22a5..684aa70804 100644 --- a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/SetIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/SetIteratorPrototype.cpp index e40cfc74e9..321d9482a5 100644 --- a/Userland/Libraries/LibJS/Runtime/SetIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetIteratorPrototype.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include namespace JS { diff --git a/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp b/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp index d17758b751..cfa13dc335 100644 --- a/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp index 28a7691e63..e9f2d3c43a 100644 --- a/Userland/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringIteratorPrototype.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/SuppressedErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/SuppressedErrorConstructor.cpp index ac199d7fc6..184cc86c24 100644 --- a/Userland/Libraries/LibJS/Runtime/SuppressedErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/SuppressedErrorConstructor.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp index f15c4f83af..977b71b738 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp index 5edcf64f7b..02df08c175 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/CalendarPrototype.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp index bc3ace1f53..7f8c3ef1a6 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index e810603c80..6ed2025ce9 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp index 7fd7da49f1..bfd178d463 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 7df48f5100..8aadf050a6 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp index 85516bb3cb..9512ca8b31 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp index 07ecf796f5..d897db4dc2 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/Userland/Libraries/LibJS/Runtime/WrapForValidIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WrapForValidIteratorPrototype.cpp index 167c164695..28beeae0e5 100644 --- a/Userland/Libraries/LibJS/Runtime/WrapForValidIteratorPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/WrapForValidIteratorPrototype.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include namespace JS { diff --git a/Userland/Libraries/LibWeb/Fetch/HeadersIterator.cpp b/Userland/Libraries/LibWeb/Fetch/HeadersIterator.cpp index 145137c8b0..0de77519ec 100644 --- a/Userland/Libraries/LibWeb/Fetch/HeadersIterator.cpp +++ b/Userland/Libraries/LibWeb/Fetch/HeadersIterator.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/HTML/CustomElements/CustomElementRegistry.cpp b/Userland/Libraries/LibWeb/HTML/CustomElements/CustomElementRegistry.cpp index 2b2bccf418..193b9936b7 100644 --- a/Userland/Libraries/LibWeb/HTML/CustomElements/CustomElementRegistry.cpp +++ b/Userland/Libraries/LibWeb/HTML/CustomElements/CustomElementRegistry.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp index ec719813cf..515b0d10be 100644 --- a/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp +++ b/Userland/Libraries/LibWeb/Streams/ReadableStreamDefaultReader.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp b/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp index 0e83251970..fcb4c7af9c 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp +++ b/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp index 1ce0edb9f5..8654e3bc51 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssembly.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp b/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp index 4cea9cdcbd..95ae5af304 100644 --- a/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp +++ b/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include