diff --git a/Userland/Libraries/LibWeb/Bindings/FetchMethod.cpp b/Userland/Libraries/LibWeb/Bindings/FetchMethod.cpp deleted file mode 100644 index ec57e8007e2..00000000000 --- a/Userland/Libraries/LibWeb/Bindings/FetchMethod.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2022-2023, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// NOTE: This file contains code generated by BindingsGenerator from the following input: -// ```idl -// #import -// #import -// [Exposed=Window, UseNewAKString] -// interface Dummy { -// static Promise fetch(RequestInfo input, optional RequestInit 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 fetch(JS::VM& vm) -{ - [[maybe_unused]] auto& realm = *vm.current_realm(); - if (vm.argument_count() < 1) - return vm.throw_completion(JS::ErrorType::BadArgCountOne, "fetch"); - auto arg0 = vm.argument(0); - auto arg0_to_variant = [&vm, &realm](JS::Value arg0) -> JS::ThrowCompletionOr, String>> { - // These might be unused. - (void)vm; - (void)realm; - if (arg0.is_object()) { - [[maybe_unused]] auto& arg0_object = arg0.as_object(); - if (is(arg0_object)) { - if (is(arg0_object)) - return JS::make_handle(static_cast(arg0_object)); - } - } - return TRY(arg0.to_string(vm)); - }; - Variant, String> input = TRY(arg0_to_variant(arg0)); - auto arg1 = vm.argument(1); - if (!arg1.is_nullish() && !arg1.is_object()) - return vm.throw_completion(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, JS::Handle, JS::Handle, JS::Handle, String>> { - // 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(body_property_value_object)) { - if (is(body_property_value_object)) - return JS::make_handle(static_cast(body_property_value_object)); - if (is(body_property_value_object)) - return JS::make_handle(static_cast(body_property_value_object)); - if (is(body_property_value_object)) - return JS::make_handle(static_cast(body_property_value_object)); - } - if (is(body_property_value_object)) - return JS::make_handle(body_property_value_object); - } - return TRY(body_property_value.to_string(vm)); - }; - Optional, JS::Handle, JS::Handle, JS::Handle, String>> 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_string(vm)); - 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 == "reload"sv) - cache_value = RequestCache::Reload; - else if (cache_property_value_string == "no-cache"sv) - cache_value = RequestCache::NoCache; - else if (cache_property_value_string == "force-cache"sv) - cache_value = RequestCache::ForceCache; - else if (cache_property_value_string == "only-if-cached"sv) - cache_value = RequestCache::OnlyIfCached; - else - return vm.throw_completion(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_string(vm)); - if (credentials_property_value_string == "omit"sv) - credentials_value = RequestCredentials::Omit; - else 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 - return vm.throw_completion(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_string(vm)); - if (duplex_property_value_string == "half"sv) - duplex_value = RequestDuplex::Half; - else - return vm.throw_completion(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>, OrderedHashMap>> { - // 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> 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::ErrorType::NotAnObject, TRY_OR_THROW_OOM(vm, 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::ErrorType::NotIterable, TRY_OR_THROW_OOM(vm, next_item1.to_string_without_side_effects())); - auto iterator2 = TRY(JS::get_iterator(vm, next_item1, JS::IteratorHint::Sync, iterator_method1)); - Vector sequence_item1; - for (;;) { - auto* next2 = TRY(JS::iterator_step(vm, iterator2)); - if (!next2) - break; - auto next_item2 = TRY(JS::iterator_value(vm, *next2)); - String sequence_item2; - if (!false || !next_item2.is_null()) { - sequence_item2 = TRY(next_item2.to_string(vm)); - } - sequence_item1.append(sequence_item2); - } - headers_value.append(sequence_item1); - } - return headers_value; - } - OrderedHashMap 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; - String typed_key1; - if (!false || !key1.is_null()) { - typed_key1 = TRY(key1.to_string(vm)); - } - auto value1 = TRY(headers_property_value_object.get(property_key1)); - String typed_value1; - if (!false || !value1.is_null()) { - typed_value1 = TRY(value1.to_string(vm)); - } - record_union_type.set(typed_key1, typed_value1); - } - return record_union_type; - } - return vm.throw_completion("No union types matched"sv); - }; - Optional>, OrderedHashMap>> 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()) { - Optional integrity_value; - if (!integrity_property_value.is_undefined()) { - if (!false || !integrity_property_value.is_null()) - integrity_value = TRY(integrity_property_value.to_string(vm)); - } - if (integrity_value.has_value()) - init.integrity = integrity_value.release_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 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()) { - Optional method_value; - if (!method_property_value.is_undefined()) { - if (!false || !method_property_value.is_null()) - method_value = TRY(method_property_value.to_string(vm)); - } - if (method_value.has_value()) - init.method = method_value.release_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_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::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_string(vm)); - if (redirect_property_value_string == "follow"sv) - redirect_value = RequestRedirect::Follow; - else if (redirect_property_value_string == "error"sv) - redirect_value = RequestRedirect::Error; - else if (redirect_property_value_string == "manual"sv) - redirect_value = RequestRedirect::Manual; - else - return vm.throw_completion(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()) { - Optional referrer_value; - if (!referrer_property_value.is_undefined()) { - if (!false || !referrer_property_value.is_null()) - referrer_value = TRY(referrer_property_value.to_string(vm)); - } - if (referrer_value.has_value()) - init.referrer = referrer_value.release_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_string(vm)); - if (referrer_policy_property_value_string == ""sv) - referrer_policy_value = ReferrerPolicy::Empty; - else if (referrer_policy_property_value_string == "no-referrer"sv) - referrer_policy_value = ReferrerPolicy::NoReferrer; - else if (referrer_policy_property_value_string == "no-referrer-when-downgrade"sv) - referrer_policy_value = ReferrerPolicy::NoReferrerWhenDowngrade; - 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 == "strict-origin"sv) - referrer_policy_value = ReferrerPolicy::StrictOrigin; - 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-when-cross-origin"sv) - referrer_policy_value = ReferrerPolicy::StrictOriginWhenCrossOrigin; - else if (referrer_policy_property_value_string == "unsafe-url"sv) - referrer_policy_value = ReferrerPolicy::UnsafeUrl; - else - return vm.throw_completion(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(signal_property_value.as_object())) - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "AbortSignal"); - signal_value = &static_cast(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 - -} diff --git a/Userland/Libraries/LibWeb/Bindings/FetchMethod.h b/Userland/Libraries/LibWeb/Bindings/FetchMethod.h deleted file mode 100644 index 75ab4ebda04..00000000000 --- a/Userland/Libraries/LibWeb/Bindings/FetchMethod.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2022, Linus Groh - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Web::Bindings { - -JS::ThrowCompletionOr fetch(JS::VM&); - -} diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 9edac65af15..a5428477736 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -6,7 +6,6 @@ set(SOURCES ARIA/Roles.cpp Bindings/AudioConstructor.cpp Bindings/CSSNamespace.cpp - Bindings/FetchMethod.cpp Bindings/HostDefined.cpp Bindings/ImageConstructor.cpp Bindings/Intrinsics.cpp diff --git a/Userland/Libraries/LibWeb/Fetch/FetchMethod.cpp b/Userland/Libraries/LibWeb/Fetch/FetchMethod.cpp index 1743c9715f5..cbad7543b62 100644 --- a/Userland/Libraries/LibWeb/Fetch/FetchMethod.cpp +++ b/Userland/Libraries/LibWeb/Fetch/FetchMethod.cpp @@ -19,12 +19,13 @@ #include #include #include +#include #include namespace Web::Fetch { // https://fetch.spec.whatwg.org/#dom-global-fetch -JS::NonnullGCPtr fetch_impl(JS::VM& vm, RequestInfo const& input, RequestInit const& init) +JS::NonnullGCPtr fetch(JS::VM& vm, RequestInfo const& input, RequestInit const& init) { auto& realm = *vm.current_realm(); diff --git a/Userland/Libraries/LibWeb/Fetch/FetchMethod.h b/Userland/Libraries/LibWeb/Fetch/FetchMethod.h index b722850a1c4..77b906426cf 100644 --- a/Userland/Libraries/LibWeb/Fetch/FetchMethod.h +++ b/Userland/Libraries/LibWeb/Fetch/FetchMethod.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Linus Groh + * Copyright (c) 2022-2023, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -14,7 +14,7 @@ namespace Web::Fetch { -JS::NonnullGCPtr fetch_impl(JS::VM&, RequestInfo const& input, RequestInit const& init = {}); +JS::NonnullGCPtr fetch(JS::VM&, RequestInfo const& input, RequestInit const& init = {}); void abort_fetch(JS::Realm&, WebIDL::Promise const&, JS::NonnullGCPtr, JS::GCPtr, JS::Value error); } diff --git a/Userland/Libraries/LibWeb/Fetch/Request.h b/Userland/Libraries/LibWeb/Fetch/Request.h index c794e3d39b4..3f54e159064 100644 --- a/Userland/Libraries/LibWeb/Fetch/Request.h +++ b/Userland/Libraries/LibWeb/Fetch/Request.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Fetch/Response.h b/Userland/Libraries/LibWeb/Fetch/Response.h index b78bdf047ba..e56045bd2b4 100644 --- a/Userland/Libraries/LibWeb/Fetch/Response.h +++ b/Userland/Libraries/LibWeb/Fetch/Response.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 134204410c4..65aa384bb44 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -896,8 +895,6 @@ WebIDL::ExceptionOr Window::initialize_web_interfaces(Badge(realm, realm)), 0); define_native_accessor(realm, "localStorage", local_storage_getter, {}, attr); diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index bc5eadfe22b..1b32aafa529 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -60,6 +60,7 @@ public: using WindowOrWorkerGlobalScopeMixin::atob; using WindowOrWorkerGlobalScopeMixin::btoa; + using WindowOrWorkerGlobalScopeMixin::fetch; // ^DOM::EventTarget virtual bool dispatch_event(DOM::Event&) override; diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp index 9670ea53104..82eadeed5b2 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -83,4 +84,10 @@ WebIDL::ExceptionOr WindowOrWorkerGlobalScopeMixin::atob(String const& d return TRY_OR_THROW_OOM(vm, decoder->to_utf8(decoded_data.value())); } +JS::NonnullGCPtr WindowOrWorkerGlobalScopeMixin::fetch(Fetch::RequestInfo const& input, Fetch::RequestInit const& init) const +{ + auto& vm = this_impl().vm(); + return Fetch::fetch(vm, input, init); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h index 4eb32ad3132..c99e9e3229c 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h @@ -8,6 +8,7 @@ #include #include +#include #include namespace Web::HTML { @@ -26,6 +27,7 @@ public: bool cross_origin_isolated() const; WebIDL::ExceptionOr btoa(String const& data) const; WebIDL::ExceptionOr atob(String const& data) const; + JS::NonnullGCPtr fetch(Fetch::RequestInfo const&, Fetch::RequestInit const&) const; }; } diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.idl b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.idl index 82e66c92bf8..d7541952e14 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.idl +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.idl @@ -1,3 +1,6 @@ +#import +#import + // https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope interface mixin WindowOrWorkerGlobalScope { [Replaceable] readonly attribute USVString origin; @@ -25,4 +28,7 @@ interface mixin WindowOrWorkerGlobalScope { // structured cloning // FIXME: any structuredClone(any value, optional StructuredSerializeOptions options = {}); + + // https://fetch.spec.whatwg.org/#fetch-method + [NewObject] Promise fetch(RequestInfo input, optional RequestInit init = {}); };