Serenity Operating System
at master 88 lines 3.2 kB view raw
1/* 2 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibJS/Runtime/Array.h> 8#include <LibJS/Runtime/IteratorOperations.h> 9#include <LibWeb/Bindings/HeadersIteratorPrototype.h> 10#include <LibWeb/Bindings/Intrinsics.h> 11#include <LibWeb/Fetch/HeadersIterator.h> 12 13namespace Web::Bindings { 14 15template<> 16void Intrinsics::create_web_prototype_and_constructor<HeadersIteratorPrototype>(JS::Realm& realm) 17{ 18 auto prototype = heap().allocate<HeadersIteratorPrototype>(realm, realm).release_allocated_value_but_fixme_should_propagate_errors(); 19 m_prototypes.set("HeadersIterator"sv, prototype); 20} 21 22} 23 24namespace Web::Fetch { 25 26WebIDL::ExceptionOr<JS::NonnullGCPtr<HeadersIterator>> HeadersIterator::create(Headers const& headers, JS::Object::PropertyKind iteration_kind) 27{ 28 return MUST_OR_THROW_OOM(headers.heap().allocate<HeadersIterator>(headers.realm(), headers, iteration_kind)); 29} 30 31HeadersIterator::HeadersIterator(Headers const& headers, JS::Object::PropertyKind iteration_kind) 32 : PlatformObject(headers.realm()) 33 , m_headers(headers) 34 , m_iteration_kind(iteration_kind) 35{ 36} 37 38HeadersIterator::~HeadersIterator() = default; 39 40JS::ThrowCompletionOr<void> HeadersIterator::initialize(JS::Realm& realm) 41{ 42 MUST_OR_THROW_OOM(Base::initialize(realm)); 43 set_prototype(&Bindings::ensure_web_prototype<Bindings::HeadersIteratorPrototype>(realm, "HeadersIterator")); 44 45 return {}; 46} 47 48void HeadersIterator::visit_edges(JS::Cell::Visitor& visitor) 49{ 50 Base::visit_edges(visitor); 51 visitor.visit(&m_headers); 52} 53 54// https://webidl.spec.whatwg.org/#es-iterable, Step 2 55JS::ThrowCompletionOr<JS::Object*> HeadersIterator::next() 56{ 57 // The value pairs to iterate over are the return value of running sort and combine with this’s header list. 58 auto value_pairs_to_iterate_over = [&]() -> JS::ThrowCompletionOr<Vector<Fetch::Infrastructure::Header>> { 59 auto headers_or_error = m_headers.m_header_list->sort_and_combine(); 60 if (headers_or_error.is_error()) 61 return vm().throw_completion<JS::InternalError>(JS::ErrorType::NotEnoughMemoryToAllocate); 62 return headers_or_error.release_value(); 63 }; 64 65 auto pairs = TRY(value_pairs_to_iterate_over()); 66 67 if (m_index >= pairs.size()) 68 return create_iterator_result_object(vm(), JS::js_undefined(), true); 69 70 auto const& pair = pairs[m_index++]; 71 StringView pair_name { pair.name }; 72 StringView pair_value { pair.value }; 73 74 switch (m_iteration_kind) { 75 case JS::Object::PropertyKind::Key: 76 return create_iterator_result_object(vm(), MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm(), pair_name)), false); 77 case JS::Object::PropertyKind::Value: 78 return create_iterator_result_object(vm(), MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm(), pair_value)), false); 79 case JS::Object::PropertyKind::KeyAndValue: { 80 auto array = JS::Array::create_from(realm(), { MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm(), pair_name)), MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm(), pair_value)) }); 81 return create_iterator_result_object(vm(), array, false); 82 } 83 default: 84 VERIFY_NOT_REACHED(); 85 } 86} 87 88}