mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:32:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			371 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <AK/TypeCasts.h>
 | |
| #include <LibJS/Runtime/ArrayBuffer.h>
 | |
| #include <LibJS/Runtime/Error.h>
 | |
| #include <LibJS/Runtime/FunctionObject.h>
 | |
| #include <LibJS/Runtime/IteratorOperations.h>
 | |
| #include <LibJS/Runtime/VM.h>
 | |
| #include <LibWeb/Bindings/ExceptionOrUtils.h>
 | |
| #include <LibWeb/Bindings/FetchMethod.h>
 | |
| #include <LibWeb/Bindings/RequestPrototype.h>
 | |
| #include <LibWeb/DOM/AbortSignal.h>
 | |
| #include <LibWeb/Fetch/FetchMethod.h>
 | |
| #include <LibWeb/Fetch/Request.h>
 | |
| #include <LibWeb/FileAPI/Blob.h>
 | |
| #include <LibWeb/Streams/ReadableStream.h>
 | |
| #include <LibWeb/URL/URLSearchParams.h>
 | |
| 
 | |
| // NOTE: This file contains code generated by BindingsGenerator from the following input:
 | |
| // interface Dummy {
 | |
| //    static Promise<Response> fetch(RequestInfo input, optional RequestInfo init = {});
 | |
| // };
 | |
| // This is because the spec defines the fetch() method as a 'partial interface mixin' on
 | |
| // WindowOrWorkerGlobalScope, which we don't support yet - and even if we did, the Window object is
 | |
| // not generated from IDL currently, so we couldn't add a mixin to it that way. The generated code
 | |
| // has _not_ been cleaned up manually, the only changes are:
 | |
| // - Adding only the necessary includes and 'using namespace' declarations
 | |
| // - Deferring to 'Fetch::fetch_impl()' at the very end instead of 'Fetch::Dummy::fetch()'
 | |
| // - Removing all empty lines, there's an excessive amount of them and this isn't supposed to be
 | |
| //   readable code anyway
 | |
| // - Running clang-format :^)
 | |
| // Don't hesitate to sync it with updated output when making changes to BindingsGenerator!
 | |
| 
 | |
| using namespace Web::DOM;
 | |
| using namespace Web::Fetch;
 | |
| using namespace Web::FileAPI;
 | |
| using namespace Web::Streams;
 | |
| using namespace Web::URL;
 | |
| 
 | |
| namespace Web::Bindings {
 | |
| 
 | |
| // NOLINTBEGIN
 | |
| JS::ThrowCompletionOr<JS::Value> fetch(JS::VM& vm)
 | |
| {
 | |
|     [[maybe_unused]] auto& realm = *vm.current_realm();
 | |
|     if (vm.argument_count() < 1)
 | |
|         return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "fetch");
 | |
|     auto arg0 = vm.argument(0);
 | |
|     auto arg0_to_variant = [&vm, &realm](JS::Value arg0) -> JS::ThrowCompletionOr<Variant<JS::Handle<Request>, DeprecatedString>> {
 | |
|         // These might be unused.
 | |
|         (void)vm;
 | |
|         (void)realm;
 | |
|         if (arg0.is_object()) {
 | |
|             [[maybe_unused]] auto& arg0_object = arg0.as_object();
 | |
|             if (is<PlatformObject>(arg0_object)) {
 | |
|                 if (is<Request>(arg0_object))
 | |
|                     return JS::make_handle(static_cast<Request&>(arg0_object));
 | |
|             }
 | |
|         }
 | |
|         return TRY(arg0.to_deprecated_string(vm));
 | |
|     };
 | |
|     Variant<JS::Handle<Request>, DeprecatedString> input = TRY(arg0_to_variant(arg0));
 | |
|     auto arg1 = vm.argument(1);
 | |
|     if (!arg1.is_nullish() && !arg1.is_object())
 | |
|         return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "RequestInit");
 | |
|     RequestInit init {};
 | |
|     auto body_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         body_property_value = TRY(arg1.as_object().get("body"));
 | |
|     if (!body_property_value.is_undefined()) {
 | |
|         auto body_property_value_to_variant = [&vm, &realm](JS::Value body_property_value) -> JS::ThrowCompletionOr<Variant<JS::Handle<ReadableStream>, JS::Handle<Blob>, JS::Handle<JS::Object>, JS::Handle<URLSearchParams>, DeprecatedString>> {
 | |
|             // These might be unused.
 | |
|             (void)vm;
 | |
|             (void)realm;
 | |
|             if (body_property_value.is_object()) {
 | |
|                 [[maybe_unused]] auto& body_property_value_object = body_property_value.as_object();
 | |
|                 if (is<PlatformObject>(body_property_value_object)) {
 | |
|                     if (is<ReadableStream>(body_property_value_object))
 | |
|                         return JS::make_handle(static_cast<ReadableStream&>(body_property_value_object));
 | |
|                     if (is<Blob>(body_property_value_object))
 | |
|                         return JS::make_handle(static_cast<Blob&>(body_property_value_object));
 | |
|                     if (is<URLSearchParams>(body_property_value_object))
 | |
|                         return JS::make_handle(static_cast<URLSearchParams&>(body_property_value_object));
 | |
|                 }
 | |
|                 if (is<JS::ArrayBuffer>(body_property_value_object))
 | |
|                     return JS::make_handle(body_property_value_object);
 | |
|             }
 | |
|             return TRY(body_property_value.to_deprecated_string(vm));
 | |
|         };
 | |
|         Optional<Variant<JS::Handle<ReadableStream>, JS::Handle<Blob>, JS::Handle<JS::Object>, JS::Handle<URLSearchParams>, DeprecatedString>> body_value;
 | |
|         if (!body_property_value.is_nullish())
 | |
|             body_value = TRY(body_property_value_to_variant(body_property_value));
 | |
|         init.body = body_value;
 | |
|     }
 | |
|     auto cache_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         cache_property_value = TRY(arg1.as_object().get("cache"));
 | |
|     if (!cache_property_value.is_undefined()) {
 | |
|         RequestCache cache_value { RequestCache::Default };
 | |
|         if (!cache_property_value.is_undefined()) {
 | |
|             auto cache_property_value_string = TRY(cache_property_value.to_deprecated_string(vm));
 | |
|             if (cache_property_value_string == "only-if-cached"sv)
 | |
|                 cache_value = RequestCache::OnlyIfCached;
 | |
|             else if (cache_property_value_string == "default"sv)
 | |
|                 cache_value = RequestCache::Default;
 | |
|             else if (cache_property_value_string == "no-store"sv)
 | |
|                 cache_value = RequestCache::NoStore;
 | |
|             else if (cache_property_value_string == "force-cache"sv)
 | |
|                 cache_value = RequestCache::ForceCache;
 | |
|             else if (cache_property_value_string == "reload"sv)
 | |
|                 cache_value = RequestCache::Reload;
 | |
|             else if (cache_property_value_string == "no-cache"sv)
 | |
|                 cache_value = RequestCache::NoCache;
 | |
|             else
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, cache_property_value_string, "RequestCache");
 | |
|         }
 | |
|         init.cache = cache_value;
 | |
|     }
 | |
|     auto credentials_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         credentials_property_value = TRY(arg1.as_object().get("credentials"));
 | |
|     if (!credentials_property_value.is_undefined()) {
 | |
|         RequestCredentials credentials_value { RequestCredentials::Omit };
 | |
|         if (!credentials_property_value.is_undefined()) {
 | |
|             auto credentials_property_value_string = TRY(credentials_property_value.to_deprecated_string(vm));
 | |
|             if (credentials_property_value_string == "same-origin"sv)
 | |
|                 credentials_value = RequestCredentials::SameOrigin;
 | |
|             else if (credentials_property_value_string == "include"sv)
 | |
|                 credentials_value = RequestCredentials::Include;
 | |
|             else if (credentials_property_value_string == "omit"sv)
 | |
|                 credentials_value = RequestCredentials::Omit;
 | |
|             else
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, credentials_property_value_string, "RequestCredentials");
 | |
|         }
 | |
|         init.credentials = credentials_value;
 | |
|     }
 | |
|     auto duplex_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         duplex_property_value = TRY(arg1.as_object().get("duplex"));
 | |
|     if (!duplex_property_value.is_undefined()) {
 | |
|         RequestDuplex duplex_value { RequestDuplex::Half };
 | |
|         if (!duplex_property_value.is_undefined()) {
 | |
|             auto duplex_property_value_string = TRY(duplex_property_value.to_deprecated_string(vm));
 | |
|             if (duplex_property_value_string == "half"sv)
 | |
|                 duplex_value = RequestDuplex::Half;
 | |
|             else
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, duplex_property_value_string, "RequestDuplex");
 | |
|         }
 | |
|         init.duplex = duplex_value;
 | |
|     }
 | |
|     auto headers_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         headers_property_value = TRY(arg1.as_object().get("headers"));
 | |
|     if (!headers_property_value.is_undefined()) {
 | |
|         auto headers_property_value_to_variant = [&vm, &realm](JS::Value headers_property_value) -> JS::ThrowCompletionOr<Variant<Vector<Vector<DeprecatedString>>, OrderedHashMap<DeprecatedString, DeprecatedString>>> {
 | |
|             // These might be unused.
 | |
|             (void)vm;
 | |
|             (void)realm;
 | |
|             if (headers_property_value.is_object()) {
 | |
|                 [[maybe_unused]] auto& headers_property_value_object = headers_property_value.as_object();
 | |
|                 auto* method = TRY(headers_property_value.get_method(vm, *vm.well_known_symbol_iterator()));
 | |
|                 if (method) {
 | |
|                     auto iterator1 = TRY(JS::get_iterator(vm, headers_property_value, JS::IteratorHint::Sync, method));
 | |
|                     Vector<Vector<DeprecatedString>> headers_value;
 | |
|                     for (;;) {
 | |
|                         auto* next1 = TRY(JS::iterator_step(vm, iterator1));
 | |
|                         if (!next1)
 | |
|                             break;
 | |
|                         auto next_item1 = TRY(JS::iterator_value(vm, *next1));
 | |
|                         if (!next_item1.is_object())
 | |
|                             return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObject, next_item1.to_string_without_side_effects());
 | |
|                         auto* iterator_method1 = TRY(next_item1.get_method(vm, *vm.well_known_symbol_iterator()));
 | |
|                         if (!iterator_method1)
 | |
|                             return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotIterable, next_item1.to_string_without_side_effects());
 | |
|                         auto iterator2 = TRY(JS::get_iterator(vm, next_item1, JS::IteratorHint::Sync, iterator_method1));
 | |
|                         Vector<DeprecatedString> sequence_item1;
 | |
|                         for (;;) {
 | |
|                             auto* next2 = TRY(JS::iterator_step(vm, iterator2));
 | |
|                             if (!next2)
 | |
|                                 break;
 | |
|                             auto next_item2 = TRY(JS::iterator_value(vm, *next2));
 | |
|                             DeprecatedString sequence_item2;
 | |
|                             if (next_item2.is_null() && false) {
 | |
|                                 sequence_item2 = DeprecatedString::empty();
 | |
|                             } else {
 | |
|                                 sequence_item2 = TRY(next_item2.to_deprecated_string(vm));
 | |
|                             }
 | |
|                             sequence_item1.append(sequence_item2);
 | |
|                         }
 | |
|                         headers_value.append(sequence_item1);
 | |
|                     }
 | |
|                     return headers_value;
 | |
|                 }
 | |
|                 OrderedHashMap<DeprecatedString, DeprecatedString> record_union_type;
 | |
|                 auto record_keys1 = TRY(headers_property_value_object.internal_own_property_keys());
 | |
|                 for (auto& key1 : record_keys1) {
 | |
|                     auto property_key1 = MUST(JS::PropertyKey::from_value(vm, key1));
 | |
|                     auto descriptor1 = TRY(headers_property_value_object.internal_get_own_property(property_key1));
 | |
|                     if (!descriptor1.has_value() || !descriptor1->enumerable.has_value() || !descriptor1->enumerable.value())
 | |
|                         continue;
 | |
|                     DeprecatedString typed_key1;
 | |
|                     if (key1.is_null() && false) {
 | |
|                         typed_key1 = DeprecatedString::empty();
 | |
|                     } else {
 | |
|                         typed_key1 = TRY(key1.to_deprecated_string(vm));
 | |
|                     }
 | |
|                     auto value1 = TRY(headers_property_value_object.get(property_key1));
 | |
|                     DeprecatedString typed_value1;
 | |
|                     if (value1.is_null() && false) {
 | |
|                         typed_value1 = DeprecatedString::empty();
 | |
|                     } else {
 | |
|                         typed_value1 = TRY(value1.to_deprecated_string(vm));
 | |
|                     }
 | |
|                     record_union_type.set(typed_key1, typed_value1);
 | |
|                 }
 | |
|                 return record_union_type;
 | |
|             }
 | |
|             return vm.throw_completion<JS::TypeError>("No union types matched");
 | |
|         };
 | |
|         Optional<Variant<Vector<Vector<DeprecatedString>>, OrderedHashMap<DeprecatedString, DeprecatedString>>> headers_value;
 | |
|         if (!headers_property_value.is_nullish())
 | |
|             headers_value = TRY(headers_property_value_to_variant(headers_property_value));
 | |
|         init.headers = headers_value;
 | |
|     }
 | |
|     auto integrity_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         integrity_property_value = TRY(arg1.as_object().get("integrity"));
 | |
|     if (!integrity_property_value.is_undefined()) {
 | |
|         DeprecatedString integrity_value;
 | |
|         if (!integrity_property_value.is_undefined()) {
 | |
|             if (integrity_property_value.is_null() && false)
 | |
|                 integrity_value = DeprecatedString::empty();
 | |
|             else
 | |
|                 integrity_value = TRY(integrity_property_value.to_deprecated_string(vm));
 | |
|         }
 | |
|         init.integrity = integrity_value;
 | |
|     }
 | |
|     auto keepalive_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         keepalive_property_value = TRY(arg1.as_object().get("keepalive"));
 | |
|     if (!keepalive_property_value.is_undefined()) {
 | |
|         Optional<bool> keepalive_value;
 | |
|         if (!keepalive_property_value.is_undefined())
 | |
|             keepalive_value = keepalive_property_value.to_boolean();
 | |
|         init.keepalive = keepalive_value;
 | |
|     }
 | |
|     auto method_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         method_property_value = TRY(arg1.as_object().get("method"));
 | |
|     if (!method_property_value.is_undefined()) {
 | |
|         DeprecatedString method_value;
 | |
|         if (!method_property_value.is_undefined()) {
 | |
|             if (method_property_value.is_null() && false)
 | |
|                 method_value = DeprecatedString::empty();
 | |
|             else
 | |
|                 method_value = TRY(method_property_value.to_deprecated_string(vm));
 | |
|         }
 | |
|         init.method = method_value;
 | |
|     }
 | |
|     auto mode_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         mode_property_value = TRY(arg1.as_object().get("mode"));
 | |
|     if (!mode_property_value.is_undefined()) {
 | |
|         RequestMode mode_value { RequestMode::Navigate };
 | |
|         if (!mode_property_value.is_undefined()) {
 | |
|             auto mode_property_value_string = TRY(mode_property_value.to_deprecated_string(vm));
 | |
|             if (mode_property_value_string == "navigate"sv)
 | |
|                 mode_value = RequestMode::Navigate;
 | |
|             else if (mode_property_value_string == "same-origin"sv)
 | |
|                 mode_value = RequestMode::SameOrigin;
 | |
|             else if (mode_property_value_string == "no-cors"sv)
 | |
|                 mode_value = RequestMode::NoCors;
 | |
|             else if (mode_property_value_string == "cors"sv)
 | |
|                 mode_value = RequestMode::Cors;
 | |
|             else
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, mode_property_value_string, "RequestMode");
 | |
|         }
 | |
|         init.mode = mode_value;
 | |
|     }
 | |
|     auto redirect_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         redirect_property_value = TRY(arg1.as_object().get("redirect"));
 | |
|     if (!redirect_property_value.is_undefined()) {
 | |
|         RequestRedirect redirect_value { RequestRedirect::Follow };
 | |
|         if (!redirect_property_value.is_undefined()) {
 | |
|             auto redirect_property_value_string = TRY(redirect_property_value.to_deprecated_string(vm));
 | |
|             if (redirect_property_value_string == "follow"sv)
 | |
|                 redirect_value = RequestRedirect::Follow;
 | |
|             else if (redirect_property_value_string == "manual"sv)
 | |
|                 redirect_value = RequestRedirect::Manual;
 | |
|             else if (redirect_property_value_string == "error"sv)
 | |
|                 redirect_value = RequestRedirect::Error;
 | |
|             else
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, redirect_property_value_string, "RequestRedirect");
 | |
|         }
 | |
|         init.redirect = redirect_value;
 | |
|     }
 | |
|     auto referrer_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         referrer_property_value = TRY(arg1.as_object().get("referrer"));
 | |
|     if (!referrer_property_value.is_undefined()) {
 | |
|         DeprecatedString referrer_value;
 | |
|         if (!referrer_property_value.is_undefined()) {
 | |
|             if (referrer_property_value.is_null() && false)
 | |
|                 referrer_value = DeprecatedString::empty();
 | |
|             else
 | |
|                 referrer_value = TRY(referrer_property_value.to_deprecated_string(vm));
 | |
|         }
 | |
|         init.referrer = referrer_value;
 | |
|     }
 | |
|     auto referrer_policy_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         referrer_policy_property_value = TRY(arg1.as_object().get("referrerPolicy"));
 | |
|     if (!referrer_policy_property_value.is_undefined()) {
 | |
|         ReferrerPolicy referrer_policy_value { ReferrerPolicy::Empty };
 | |
|         if (!referrer_policy_property_value.is_undefined()) {
 | |
|             auto referrer_policy_property_value_string = TRY(referrer_policy_property_value.to_deprecated_string(vm));
 | |
|             if (referrer_policy_property_value_string == ""sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::Empty;
 | |
|             else if (referrer_policy_property_value_string == "same-origin"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::SameOrigin;
 | |
|             else if (referrer_policy_property_value_string == "origin"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::Origin;
 | |
|             else if (referrer_policy_property_value_string == "origin-when-cross-origin"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::OriginWhenCrossOrigin;
 | |
|             else if (referrer_policy_property_value_string == "strict-origin"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::StrictOrigin;
 | |
|             else if (referrer_policy_property_value_string == "no-referrer"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::NoReferrer;
 | |
|             else if (referrer_policy_property_value_string == "unsafe-url"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::UnsafeUrl;
 | |
|             else if (referrer_policy_property_value_string == "no-referrer-when-downgrade"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::NoReferrerWhenDowngrade;
 | |
|             else if (referrer_policy_property_value_string == "strict-origin-when-cross-origin"sv)
 | |
|                 referrer_policy_value = ReferrerPolicy::StrictOriginWhenCrossOrigin;
 | |
|             else
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, referrer_policy_property_value_string, "ReferrerPolicy");
 | |
|         }
 | |
|         init.referrer_policy = referrer_policy_value;
 | |
|     }
 | |
|     auto signal_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         signal_property_value = TRY(arg1.as_object().get("signal"));
 | |
|     if (!signal_property_value.is_undefined()) {
 | |
|         AbortSignal* signal_value = nullptr;
 | |
|         if (!signal_property_value.is_nullish()) {
 | |
|             if (!signal_property_value.is_object() || !is<AbortSignal>(signal_property_value.as_object()))
 | |
|                 return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "AbortSignal");
 | |
|             signal_value = &static_cast<AbortSignal&>(signal_property_value.as_object());
 | |
|         }
 | |
|         init.signal = signal_value;
 | |
|     }
 | |
|     auto window_property_value = JS::js_undefined();
 | |
|     if (arg1.is_object())
 | |
|         window_property_value = TRY(arg1.as_object().get("window"));
 | |
|     if (!window_property_value.is_undefined()) {
 | |
|         JS::Value window_value = JS::js_undefined();
 | |
|         if (!window_property_value.is_undefined())
 | |
|             window_value = window_property_value;
 | |
|         init.window = window_value;
 | |
|     }
 | |
|     [[maybe_unused]] auto retval = TRY(throw_dom_exception_if_needed(vm, [&] { return Fetch::fetch_impl(vm, input, init); }));
 | |
|     return retval;
 | |
| }
 | |
| // NOLINTEND
 | |
| 
 | |
| }
 | 
