diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index c45b580383..acadf7a0b1 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -243,6 +243,7 @@ set(SOURCES UIEvents/MouseEvent.cpp URL/URL.cpp URL/URLSearchParams.cpp + URL/URLSearchParamsIterator.cpp WebAssembly/WebAssemblyInstanceConstructor.cpp WebAssembly/WebAssemblyInstanceObject.cpp WebAssembly/WebAssemblyInstanceObjectPrototype.cpp @@ -458,7 +459,7 @@ libweb_js_wrapper(XHR/ProgressEvent) libweb_js_wrapper(XHR/XMLHttpRequest) libweb_js_wrapper(XHR/XMLHttpRequestEventTarget) libweb_js_wrapper(URL/URL) -libweb_js_wrapper(URL/URLSearchParams) +libweb_js_wrapper(URL/URLSearchParams ITERABLE) add_custom_command( OUTPUT CSS/PropertyID.h diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 70d9eb29fc..b943c2e964 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -251,6 +251,7 @@ class XMLHttpRequestEventTarget; namespace Web::URL { class URL; class URLSearchParams; +class URLSearchParamsIterator; } namespace Web::Bindings { @@ -391,4 +392,6 @@ class URLWrapper; class URLSearchParamsConstructor; class URLSearchParamsPrototype; class URLSearchParamsWrapper; +class URLSearchParamsIteratorPrototype; +class URLSearchParamsIteratorWrapper; } diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp b/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp index 3ff4368c89..82a556c09d 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp @@ -195,4 +195,13 @@ String URLSearchParams::to_string() return url_encode(m_list, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded); } +void URLSearchParams::for_each(Function callback) +{ + for (auto i = 0u; i < m_list.size(); ++i) { + auto& query_param = m_list[i]; // We are explicitly iterating over the indices here as the callback might delete items from the list + if (callback(query_param.name, query_param.value) == IterationDecision::Break) + break; + } +} + } diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.h b/Userland/Libraries/LibWeb/URL/URLSearchParams.h index f3547a9ba7..b097e787a6 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.h +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.h @@ -42,8 +42,11 @@ public: String to_string(); + void for_each(Function); + private: friend class URL; + friend class URLSearchParamsIterator; explicit URLSearchParams(Vector list) : m_list(move(list)) {}; diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.idl b/Userland/Libraries/LibWeb/URL/URLSearchParams.idl index 874e457280..1ca944d8d7 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.idl +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.idl @@ -12,6 +12,6 @@ interface URLSearchParams { undefined sort(); - // TODO: iterable; + iterable; stringifier; }; diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp b/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp new file mode 100644 index 0000000000..bd92b24515 --- /dev/null +++ b/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Idan Horowitz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Web::URL { + +JS::Object* URLSearchParamsIterator::next() +{ + auto& global_object = wrapper()->global_object(); + auto& vm = global_object.vm(); + + if (m_index >= m_url_search_params.m_list.size()) + return create_iterator_result_object(global_object, JS::js_undefined(), true); + + auto& entry = m_url_search_params.m_list[m_index++]; + if (m_iteration_kind == JS::Object::PropertyKind::Key) + return create_iterator_result_object(global_object, JS::js_string(vm, entry.name), false); + else if (m_iteration_kind == JS::Object::PropertyKind::Value) + return create_iterator_result_object(global_object, JS::js_string(vm, entry.value), false); + + return create_iterator_result_object(global_object, JS::Array::create_from(global_object, { JS::js_string(vm, entry.name), JS::js_string(vm, entry.value) }), false); +} + +void URLSearchParamsIterator::visit_edges(JS::Cell::Visitor& visitor) +{ + visitor.visit(m_url_search_params.wrapper()); +} + +} diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.h b/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.h new file mode 100644 index 0000000000..880a087d0c --- /dev/null +++ b/Userland/Libraries/LibWeb/URL/URLSearchParamsIterator.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Idan Horowitz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "URLSearchParams.h" +#include +#include + +namespace Web::URL { + +class URLSearchParamsIterator : public Bindings::Wrappable + , public RefCounted { +public: + using WrapperType = Bindings::URLSearchParamsIteratorWrapper; + + static NonnullRefPtr create(URLSearchParams const& url_search_params, JS::Object::PropertyKind iteration_kind) + { + return adopt_ref(*new URLSearchParamsIterator(url_search_params, iteration_kind)); + } + + JS::Object* next(); + + void visit_edges(JS::Cell::Visitor&); + +private: + explicit URLSearchParamsIterator(URLSearchParams const& url_search_params, JS::Object::PropertyKind iteration_kind) + : m_url_search_params(url_search_params) + , m_iteration_kind(iteration_kind) + { + } + + URLSearchParams const& m_url_search_params; + JS::Object::PropertyKind m_iteration_kind; + size_t m_index { 0 }; +}; +} + +namespace Web::Bindings { + +URLSearchParamsIteratorWrapper* wrap(JS::GlobalObject&, URL::URLSearchParamsIterator&); + +}