diff options
author | Kenneth Myhra <kennethmyhra@gmail.com> | 2023-03-05 17:29:11 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-03-08 18:57:36 +0000 |
commit | be52e7171adca720954e18250be0bdce68665982 (patch) | |
tree | a8521ee1ade5aa4fce9ee72fd279efeda22e733b /Userland | |
parent | 680e970597aa292a20fa4e24f6f5c0a905f50c72 (diff) | |
download | serenity-be52e7171adca720954e18250be0bdce68665982.zip |
LibWeb: Add FormDataIterator implementation
This adds the FormDataIterator implementation so we can iterate over
FormData.{keys(),values(),entries()}.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/XHR/FormData.cpp | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/XHR/FormData.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/XHR/FormData.idl | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp | 79 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/XHR/FormDataIterator.h | 35 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/idl_files.cmake | 2 |
8 files changed, 133 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index a542847773..216eebcc17 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -473,6 +473,7 @@ set(SOURCES WebSockets/WebSocket.cpp XHR/EventNames.cpp XHR/FormData.cpp + XHR/FormDataIterator.cpp XHR/ProgressEvent.cpp XHR/XMLHttpRequest.cpp XHR/XMLHttpRequestEventTarget.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 200c2f61d6..26a99cc382 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -489,6 +489,7 @@ class WebGLRenderingContextBase; namespace Web::XHR { class FormData; +class FormDataIterator; class ProgressEvent; class XMLHttpRequest; class XMLHttpRequestEventTarget; diff --git a/Userland/Libraries/LibWeb/XHR/FormData.cpp b/Userland/Libraries/LibWeb/XHR/FormData.cpp index d2fca57323..ca9fe5ef72 100644 --- a/Userland/Libraries/LibWeb/XHR/FormData.cpp +++ b/Userland/Libraries/LibWeb/XHR/FormData.cpp @@ -171,4 +171,14 @@ WebIDL::ExceptionOr<void> FormData::set_impl(String const& name, Variant<JS::Non return {}; } +JS::ThrowCompletionOr<void> FormData::for_each(ForEachCallback callback) +{ + for (auto i = 0u; i < m_entry_list.size(); ++i) { + auto& entry = m_entry_list[i]; + TRY(callback(entry.name, entry.value)); + } + + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/XHR/FormData.h b/Userland/Libraries/LibWeb/XHR/FormData.h index b8a3f300ef..7cfbc9934a 100644 --- a/Userland/Libraries/LibWeb/XHR/FormData.h +++ b/Userland/Libraries/LibWeb/XHR/FormData.h @@ -41,7 +41,12 @@ public: WebIDL::ExceptionOr<void> set(String const& name, String const& value); WebIDL::ExceptionOr<void> set(String const& name, JS::NonnullGCPtr<FileAPI::Blob> const& blob_value, Optional<String> const& filename = {}); + using ForEachCallback = Function<JS::ThrowCompletionOr<void>(String const&, FormDataEntryValue const&)>; + JS::ThrowCompletionOr<void> for_each(ForEachCallback); + private: + friend class FormDataIterator; + explicit FormData(JS::Realm&, Vector<FormDataEntry> entry_list = {}); virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; diff --git a/Userland/Libraries/LibWeb/XHR/FormData.idl b/Userland/Libraries/LibWeb/XHR/FormData.idl index 38af410dfc..269f15801e 100644 --- a/Userland/Libraries/LibWeb/XHR/FormData.idl +++ b/Userland/Libraries/LibWeb/XHR/FormData.idl @@ -19,5 +19,5 @@ interface FormData { boolean has(USVString name); undefined set(USVString name, USVString value); undefined set(USVString name, Blob blobValue, optional USVString filename); - // FIXME: iterable<USVString, FormDataEntryValue>; + iterable<USVString, FormDataEntryValue>; }; diff --git a/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp b/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp new file mode 100644 index 0000000000..32c17eb6ed --- /dev/null +++ b/Userland/Libraries/LibWeb/XHR/FormDataIterator.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023, Kenneth Myhra <kennethmyhra@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/Array.h> +#include <LibJS/Runtime/IteratorOperations.h> +#include <LibWeb/Bindings/FormDataIteratorPrototype.h> +#include <LibWeb/Bindings/Intrinsics.h> +#include <LibWeb/XHR/FormDataIterator.h> + +namespace Web::Bindings { + +template<> +void Intrinsics::create_web_prototype_and_constructor<FormDataIteratorPrototype>(JS::Realm& realm) +{ + auto prototype = heap().allocate<FormDataIteratorPrototype>(realm, realm).release_allocated_value_but_fixme_should_propagate_errors(); + m_prototypes.set("FormDataIterator"sv, prototype); +} + +} + +namespace Web::XHR { + +WebIDL::ExceptionOr<JS::NonnullGCPtr<FormDataIterator>> FormDataIterator::create(FormData const& form_data, JS::Object::PropertyKind iterator_kind) +{ + return MUST_OR_THROW_OOM(form_data.heap().allocate<FormDataIterator>(form_data.realm(), form_data, iterator_kind)); +} + +FormDataIterator::FormDataIterator(Web::XHR::FormData const& form_data, JS::Object::PropertyKind iterator_kind) + : PlatformObject(form_data.realm()) + , m_form_data(form_data) + , m_iterator_kind(iterator_kind) +{ +} + +FormDataIterator::~FormDataIterator() = default; + +JS::ThrowCompletionOr<void> FormDataIterator::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype<Bindings::FormDataIteratorPrototype>(realm, "FormDataIterator")); + + return {}; +} + +void FormDataIterator::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(&m_form_data); +} + +JS::Object* FormDataIterator::next() +{ + auto& vm = this->vm(); + + if (m_index >= m_form_data.m_entry_list.size()) + return create_iterator_result_object(vm, JS::js_undefined(), true); + + auto& entry = m_form_data.m_entry_list[m_index++]; + if (m_iterator_kind == JS::Object::PropertyKind::Key) + return create_iterator_result_object(vm, JS::PrimitiveString::create(vm, entry.name), false); + + auto entry_value = entry.value.visit( + [&](JS::Handle<FileAPI::File> const& file) -> JS::Value { + return file.cell(); + }, + [&](String const& string) -> JS::Value { + return JS::PrimitiveString::create(vm, string); + }); + + if (m_iterator_kind == JS::Object::PropertyKind::Value) + return create_iterator_result_object(vm, entry_value, false); + + return create_iterator_result_object(vm, JS::Array::create_from(realm(), { JS::PrimitiveString::create(vm, entry.name), entry_value }), false); +} + +} diff --git a/Userland/Libraries/LibWeb/XHR/FormDataIterator.h b/Userland/Libraries/LibWeb/XHR/FormDataIterator.h new file mode 100644 index 0000000000..c50153ae09 --- /dev/null +++ b/Userland/Libraries/LibWeb/XHR/FormDataIterator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023, Kenneth Myhra <kennethmyhra@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/Bindings/PlatformObject.h> +#include <LibWeb/XHR/FormData.h> + +namespace Web::XHR { + +class FormDataIterator : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(FormDataIterator, Bindings::PlatformObject); + +public: + static WebIDL::ExceptionOr<JS::NonnullGCPtr<FormDataIterator>> create(FormData const&, JS::Object::PropertyKind iterator_kind); + + virtual ~FormDataIterator() override; + + JS::Object* next(); + +private: + FormDataIterator(FormData const&, JS::Object::PropertyKind iterator_kind); + + virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; + + FormData const& m_form_data; + JS::Object::PropertyKind m_iterator_kind; + size_t m_index { 0 }; +}; + +} diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index cae18ad006..39f39c242b 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -203,7 +203,7 @@ libweb_js_bindings(WebGL/WebGLContextEvent) libweb_js_bindings(WebGL/WebGLRenderingContext) libweb_js_bindings(WebIDL/DOMException) libweb_js_bindings(WebSockets/WebSocket) -libweb_js_bindings(XHR/FormData) +libweb_js_bindings(XHR/FormData ITERABLE) libweb_js_bindings(XHR/ProgressEvent) libweb_js_bindings(XHR/XMLHttpRequest) libweb_js_bindings(XHR/XMLHttpRequestEventTarget) |