From b1968b8bedbe4266c3a488589e64492955023799 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 30 Oct 2022 01:52:07 +0000 Subject: [PATCH] LibWeb: Make Fetch::Infrastructure::{Request,Response,HeaderList} GC'd This is the way. On a more serious note, there's no reason to keep adding ref-counted classes to LibWeb now that the majority of classes is GC'd - it only adds the risk of discovering some cycle down the line, and forces us to use handles as we can't visit(). --- Userland/Libraries/LibWeb/Fetch/Headers.cpp | 14 +- Userland/Libraries/LibWeb/Fetch/Headers.h | 12 +- .../Fetch/Infrastructure/HTTP/Headers.cpp | 7 + .../Fetch/Infrastructure/HTTP/Headers.h | 8 +- .../Fetch/Infrastructure/HTTP/Requests.cpp | 20 ++- .../Fetch/Infrastructure/HTTP/Requests.h | 22 +-- .../Fetch/Infrastructure/HTTP/Responses.cpp | 126 ++++++++++++------ .../Fetch/Infrastructure/HTTP/Responses.h | 92 ++++++++----- Userland/Libraries/LibWeb/Fetch/Request.cpp | 43 +++--- Userland/Libraries/LibWeb/Fetch/Request.h | 8 +- Userland/Libraries/LibWeb/Fetch/Response.cpp | 34 ++--- Userland/Libraries/LibWeb/Fetch/Response.h | 8 +- .../Libraries/LibWeb/HTML/BrowsingContext.cpp | 9 +- .../Libraries/LibWeb/HTML/BrowsingContext.h | 5 +- .../LibWeb/HTML/BrowsingContextContainer.cpp | 8 +- .../LibWeb/HTML/BrowsingContextContainer.h | 2 +- .../Libraries/LibWeb/HTML/NavigationParams.h | 4 +- .../Libraries/LibWeb/Loader/FrameLoader.cpp | 13 +- .../Libraries/LibWeb/XHR/XMLHttpRequest.cpp | 4 +- 19 files changed, 270 insertions(+), 169 deletions(-) diff --git a/Userland/Libraries/LibWeb/Fetch/Headers.cpp b/Userland/Libraries/LibWeb/Fetch/Headers.cpp index 2b0c2fea92..e2ee2454c1 100644 --- a/Userland/Libraries/LibWeb/Fetch/Headers.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Headers.cpp @@ -13,8 +13,10 @@ namespace Web::Fetch { // https://fetch.spec.whatwg.org/#dom-headers WebIDL::ExceptionOr> Headers::construct_impl(JS::Realm& realm, Optional const& init) { + auto& vm = realm.vm(); + // The new Headers(init) constructor steps are: - auto* headers = realm.heap().allocate(realm, realm); + auto* headers = realm.heap().allocate(realm, realm, Infrastructure::HeaderList::create(vm)); // 1. Set this’s guard to "none". headers->m_guard = Guard::None; @@ -26,15 +28,21 @@ WebIDL::ExceptionOr> Headers::construct_impl(JS::Realm return JS::NonnullGCPtr(*headers); } -Headers::Headers(JS::Realm& realm) +Headers::Headers(JS::Realm& realm, JS::NonnullGCPtr header_list) : PlatformObject(realm) - , m_header_list(make_ref_counted()) + , m_header_list(header_list) { set_prototype(&Bindings::cached_web_prototype(realm, "Headers")); } Headers::~Headers() = default; +void Headers::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_header_list); +} + // https://fetch.spec.whatwg.org/#dom-headers-append WebIDL::ExceptionOr Headers::append(String const& name_string, String const& value_string) { diff --git a/Userland/Libraries/LibWeb/Fetch/Headers.h b/Userland/Libraries/LibWeb/Fetch/Headers.h index 654b1a1f55..564a668145 100644 --- a/Userland/Libraries/LibWeb/Fetch/Headers.h +++ b/Userland/Libraries/LibWeb/Fetch/Headers.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -35,9 +36,8 @@ public: virtual ~Headers() override; - [[nodiscard]] NonnullRefPtr& header_list() { return m_header_list; } - [[nodiscard]] NonnullRefPtr const& header_list() const { return m_header_list; } - void set_header_list(NonnullRefPtr header_list) { m_header_list = move(header_list); } + [[nodiscard]] JS::NonnullGCPtr header_list() const { return m_header_list; } + void set_header_list(JS::NonnullGCPtr header_list) { m_header_list = header_list; } [[nodiscard]] Guard guard() const { return m_guard; } void set_guard(Guard guard) { m_guard = guard; } @@ -58,13 +58,15 @@ public: private: friend class HeadersIterator; - explicit Headers(JS::Realm&); + Headers(JS::Realm&, JS::NonnullGCPtr); + + virtual void visit_edges(JS::Cell::Visitor&) override; void remove_privileged_no_cors_headers(); // https://fetch.spec.whatwg.org/#concept-headers-header-list // A Headers object has an associated header list (a header list), which is initially empty. - NonnullRefPtr m_header_list; + JS::NonnullGCPtr m_header_list; // https://fetch.spec.whatwg.org/#concept-headers-guard // A Headers object also has an associated guard, which is a headers guard. A headers guard is "immutable", "request", "request-no-cors", "response" or "none". diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp index 0147f03883..838ce31906 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -42,6 +44,11 @@ ErrorOr
Header::from_string_pair(StringView name, StringView value) }; } +JS::NonnullGCPtr HeaderList::create(JS::VM& vm) +{ + return { *vm.heap().allocate_without_realm() }; +} + // https://fetch.spec.whatwg.org/#header-list-contains bool HeaderList::contains(ReadonlyBytes name) const { diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.h b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.h index 71a8932644..15ad9355e2 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.h +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include namespace Web::Fetch::Infrastructure { @@ -29,13 +31,17 @@ struct Header { // https://fetch.spec.whatwg.org/#concept-header-list // A header list is a list of zero or more headers. It is initially the empty list. class HeaderList final - : public RefCounted + : public JS::Cell , Vector
{ + JS_CELL(HeaderList, JS::Cell); + public: using Vector::begin; using Vector::clear; using Vector::end; + [[nodiscard]] static JS::NonnullGCPtr create(JS::VM&); + [[nodiscard]] bool contains(ReadonlyBytes) const; [[nodiscard]] ErrorOr> get(ReadonlyBytes) const; [[nodiscard]] ErrorOr>> get_decode_and_split(ReadonlyBytes) const; diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp index fa9c8d978f..2e2db5be8c 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp @@ -5,18 +5,26 @@ */ #include +#include +#include #include namespace Web::Fetch::Infrastructure { -Request::Request() - : m_header_list(make_ref_counted()) +Request::Request(JS::NonnullGCPtr header_list) + : m_header_list(header_list) { } -NonnullRefPtr Request::create() +void Request::visit_edges(JS::Cell::Visitor& visitor) { - return adopt_ref(*new Request()); + Base::visit_edges(visitor); + visitor.visit(m_header_list); +} + +JS::NonnullGCPtr Request::create(JS::VM& vm) +{ + return { *vm.heap().allocate_without_realm(HeaderList::create(vm)) }; } // https://fetch.spec.whatwg.org/#concept-request-url @@ -181,12 +189,12 @@ ErrorOr Request::byte_serialize_origin() const } // https://fetch.spec.whatwg.org/#concept-request-clone -WebIDL::ExceptionOr> Request::clone() const +WebIDL::ExceptionOr> Request::clone(JS::VM& vm) const { // To clone a request request, run these steps: // 1. Let newRequest be a copy of request, except for its body. - auto new_request = Infrastructure::Request::create(); + auto new_request = Infrastructure::Request::create(vm); new_request->set_method(m_method); new_request->set_local_urls_only(m_local_urls_only); for (auto const& header : *m_header_list) diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h index ff78135a5b..2bca0f6bda 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h @@ -10,11 +10,12 @@ #include #include #include -#include #include #include #include #include +#include +#include #include #include #include @@ -24,7 +25,9 @@ namespace Web::Fetch::Infrastructure { // https://fetch.spec.whatwg.org/#concept-request -class Request final : public RefCounted { +class Request final : public JS::Cell { + JS_CELL(Request, JS::Cell); + public: enum class CacheMode { Default, @@ -156,7 +159,7 @@ public: using ReservedClientType = Variant; using WindowType = Variant; - static NonnullRefPtr create(); + [[nodiscard]] static JS::NonnullGCPtr create(JS::VM&); [[nodiscard]] ReadonlyBytes method() const { return m_method; } void set_method(ByteBuffer method) { m_method = move(method); } @@ -164,9 +167,8 @@ public: [[nodiscard]] bool local_urls_only() const { return m_local_urls_only; } void set_local_urls_only(bool local_urls_only) { m_local_urls_only = local_urls_only; } - [[nodiscard]] NonnullRefPtr const& header_list() const { return m_header_list; } - [[nodiscard]] NonnullRefPtr& header_list() { return m_header_list; } - void set_header_list(NonnullRefPtr header_list) { m_header_list = move(header_list); } + [[nodiscard]] JS::NonnullGCPtr header_list() const { return m_header_list; } + void set_header_list(JS::NonnullGCPtr header_list) { m_header_list = header_list; } [[nodiscard]] bool unsafe_request() const { return m_unsafe_request; } void set_unsafe_request(bool unsafe_request) { m_unsafe_request = unsafe_request; } @@ -294,14 +296,16 @@ public: [[nodiscard]] String serialize_origin() const; [[nodiscard]] ErrorOr byte_serialize_origin() const; - [[nodiscard]] WebIDL::ExceptionOr> clone() const; + [[nodiscard]] WebIDL::ExceptionOr> clone(JS::VM&) const; [[nodiscard]] ErrorOr add_range_header(u64 first, Optional const& last); [[nodiscard]] bool cross_origin_embedder_policy_allows_credentials() const; private: - Request(); + explicit Request(JS::NonnullGCPtr); + + virtual void visit_edges(JS::Cell::Visitor&) override; // https://fetch.spec.whatwg.org/#concept-request-method // A request has an associated method (a method). Unless stated otherwise it is `GET`. @@ -313,7 +317,7 @@ private: // https://fetch.spec.whatwg.org/#concept-request-header-list // A request has an associated header list (a header list). Unless stated otherwise it is empty. - NonnullRefPtr m_header_list; + JS::NonnullGCPtr m_header_list; // https://fetch.spec.whatwg.org/#unsafe-request-flag // A request has an associated unsafe-request flag. Unless stated otherwise it is unset. diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.cpp index 398f7fed19..bc53c3cd21 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.cpp @@ -4,36 +4,44 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include #include namespace Web::Fetch::Infrastructure { -Response::Response() - : m_header_list(make_ref_counted()) +Response::Response(JS::NonnullGCPtr header_list) + : m_header_list(header_list) { } -NonnullRefPtr Response::create() +void Response::visit_edges(JS::Cell::Visitor& visitor) { - return adopt_ref(*new Response()); + Base::visit_edges(visitor); + visitor.visit(m_header_list); +} + +JS::NonnullGCPtr Response::create(JS::VM& vm) +{ + return { *vm.heap().allocate_without_realm(HeaderList::create(vm)) }; } // https://fetch.spec.whatwg.org/#ref-for-concept-network-error%E2%91%A3 // A network error is a response whose status is always 0, status message is always // the empty byte sequence, header list is always empty, and body is always null. -NonnullRefPtr Response::aborted_network_error() +JS::NonnullGCPtr Response::aborted_network_error(JS::VM& vm) { - auto response = network_error(); + auto response = network_error(vm); response->set_aborted(true); return response; } -NonnullRefPtr Response::network_error() +JS::NonnullGCPtr Response::network_error(JS::VM& vm) { - auto response = Response::create(); + auto response = Response::create(vm); response->set_status(0); response->set_type(Type::Error); VERIFY(!response->body().has_value()); @@ -93,29 +101,28 @@ ErrorOr> Response::location_url(Optional const& reques } // https://fetch.spec.whatwg.org/#concept-response-clone -WebIDL::ExceptionOr> Response::clone() const +WebIDL::ExceptionOr> Response::clone(JS::VM& vm) const { // To clone a response response, run these steps: - auto& vm = Bindings::main_thread_vm(); auto& realm = *vm.current_realm(); // 1. If response is a filtered response, then return a new identical filtered response whose internal response is a clone of response’s internal response. if (is(*this)) { - auto internal_response = TRY(static_cast(*this).internal_response()->clone()); + auto internal_response = TRY(static_cast(*this).internal_response()->clone(vm)); if (is(*this)) - return TRY_OR_RETURN_OOM(realm, BasicFilteredResponse::create(move(internal_response))); + return TRY_OR_RETURN_OOM(realm, BasicFilteredResponse::create(vm, internal_response)); if (is(*this)) - return TRY_OR_RETURN_OOM(realm, CORSFilteredResponse::create(move(internal_response))); + return TRY_OR_RETURN_OOM(realm, CORSFilteredResponse::create(vm, internal_response)); if (is(*this)) - return OpaqueFilteredResponse::create(move(internal_response)); + return OpaqueFilteredResponse::create(vm, internal_response); if (is(*this)) - return OpaqueRedirectFilteredResponse::create(move(internal_response)); + return OpaqueRedirectFilteredResponse::create(vm, internal_response); VERIFY_NOT_REACHED(); } // 2. Let newResponse be a copy of response, except for its body. - auto new_response = Infrastructure::Response::create(); + auto new_response = Infrastructure::Response::create(vm); new_response->set_type(m_type); new_response->set_aborted(m_aborted); new_response->set_url_list(m_url_list); @@ -139,8 +146,9 @@ WebIDL::ExceptionOr> Response::clone() const return new_response; } -FilteredResponse::FilteredResponse(NonnullRefPtr internal_response) - : m_internal_response(move(internal_response)) +FilteredResponse::FilteredResponse(JS::NonnullGCPtr internal_response, JS::NonnullGCPtr header_list) + : Response(header_list) + , m_internal_response(internal_response) { } @@ -148,26 +156,38 @@ FilteredResponse::~FilteredResponse() { } -ErrorOr> BasicFilteredResponse::create(NonnullRefPtr internal_response) +void FilteredResponse::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_internal_response); +} + +ErrorOr> BasicFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr internal_response) { // A basic filtered response is a filtered response whose type is "basic" and header list excludes // any headers in internal response’s header list whose name is a forbidden response-header name. - auto header_list = make_ref_counted(); + auto header_list = HeaderList::create(vm); for (auto const& header : *internal_response->header_list()) { if (!is_forbidden_response_header_name(header.name)) TRY(header_list->append(header)); } - return adopt_ref(*new BasicFilteredResponse(move(internal_response), move(header_list))); + return { *vm.heap().allocate_without_realm(internal_response, header_list) }; } -BasicFilteredResponse::BasicFilteredResponse(NonnullRefPtr internal_response, NonnullRefPtr header_list) - : FilteredResponse(move(internal_response)) - , m_header_list(move(header_list)) +BasicFilteredResponse::BasicFilteredResponse(JS::NonnullGCPtr internal_response, JS::NonnullGCPtr header_list) + : FilteredResponse(internal_response, header_list) + , m_header_list(header_list) { } -ErrorOr> CORSFilteredResponse::create(NonnullRefPtr internal_response) +void BasicFilteredResponse::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_header_list); +} + +ErrorOr> CORSFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr internal_response) { // A CORS filtered response is a filtered response whose type is "cors" and header list excludes // any headers in internal response’s header list whose name is not a CORS-safelisted response-header @@ -176,43 +196,63 @@ ErrorOr> CORSFilteredResponse::create(Nonnul for (auto const& header_name : internal_response->cors_exposed_header_name_list()) cors_exposed_header_name_list.append(header_name.span()); - auto header_list = make_ref_counted(); + auto header_list = HeaderList::create(vm); for (auto const& header : *internal_response->header_list()) { if (is_cors_safelisted_response_header_name(header.name, cors_exposed_header_name_list)) TRY(header_list->append(header)); } - return adopt_ref(*new CORSFilteredResponse(move(internal_response), move(header_list))); + return { *vm.heap().allocate_without_realm(internal_response, header_list) }; } -CORSFilteredResponse::CORSFilteredResponse(NonnullRefPtr internal_response, NonnullRefPtr header_list) - : FilteredResponse(move(internal_response)) - , m_header_list(move(header_list)) +CORSFilteredResponse::CORSFilteredResponse(JS::NonnullGCPtr internal_response, JS::NonnullGCPtr header_list) + : FilteredResponse(internal_response, header_list) + , m_header_list(header_list) { } -NonnullRefPtr OpaqueFilteredResponse::create(NonnullRefPtr internal_response) +void CORSFilteredResponse::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_header_list); +} + +JS::NonnullGCPtr OpaqueFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr internal_response) +{ + // An opaque filtered response is a filtered response whose type is "opaque", URL list is the empty list, + // status is 0, status message is the empty byte sequence, header list is empty, and body is null. + return { *vm.heap().allocate_without_realm(internal_response, HeaderList::create(vm)) }; +} + +OpaqueFilteredResponse::OpaqueFilteredResponse(JS::NonnullGCPtr internal_response, JS::NonnullGCPtr header_list) + : FilteredResponse(internal_response, header_list) + , m_header_list(header_list) +{ +} + +void OpaqueFilteredResponse::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_header_list); +} + +JS::NonnullGCPtr OpaqueRedirectFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr internal_response) { // An opaque-redirect filtered response is a filtered response whose type is "opaqueredirect", // status is 0, status message is the empty byte sequence, header list is empty, and body is null. - return adopt_ref(*new OpaqueFilteredResponse(move(internal_response))); + return { *vm.heap().allocate_without_realm(internal_response, HeaderList::create(vm)) }; } -OpaqueFilteredResponse::OpaqueFilteredResponse(NonnullRefPtr internal_response) - : FilteredResponse(move(internal_response)) - , m_header_list(make_ref_counted()) +OpaqueRedirectFilteredResponse::OpaqueRedirectFilteredResponse(JS::NonnullGCPtr internal_response, JS::NonnullGCPtr header_list) + : FilteredResponse(internal_response, header_list) + , m_header_list(header_list) { } -NonnullRefPtr OpaqueRedirectFilteredResponse::create(NonnullRefPtr internal_response) -{ - return adopt_ref(*new OpaqueRedirectFilteredResponse(move(internal_response))); -} - -OpaqueRedirectFilteredResponse::OpaqueRedirectFilteredResponse(NonnullRefPtr internal_response) - : FilteredResponse(move(internal_response)) - , m_header_list(make_ref_counted()) +void OpaqueRedirectFilteredResponse::visit_edges(JS::Cell::Visitor& visitor) { + Base::visit_edges(visitor); + visitor.visit(m_header_list); } } diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.h b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.h index 4df9eb9b50..589bcbbc0f 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.h +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Responses.h @@ -10,9 +10,10 @@ #include #include #include -#include #include #include +#include +#include #include #include #include @@ -20,7 +21,9 @@ namespace Web::Fetch::Infrastructure { // https://fetch.spec.whatwg.org/#concept-response -class Response : public RefCounted { +class Response : public JS::Cell { + JS_CELL(Response, JS::Cell); + public: enum class CacheState { Local, @@ -45,9 +48,9 @@ public: u64 decoded_size { 0 }; }; - [[nodiscard]] static NonnullRefPtr create(); - [[nodiscard]] static NonnullRefPtr aborted_network_error(); - [[nodiscard]] static NonnullRefPtr network_error(); + [[nodiscard]] static JS::NonnullGCPtr create(JS::VM&); + [[nodiscard]] static JS::NonnullGCPtr aborted_network_error(JS::VM&); + [[nodiscard]] static JS::NonnullGCPtr network_error(JS::VM&); virtual ~Response() = default; @@ -67,9 +70,8 @@ public: [[nodiscard]] virtual ReadonlyBytes status_message() const { return m_status_message; } void set_status_message(ByteBuffer status_message) { m_status_message = move(status_message); } - [[nodiscard]] virtual NonnullRefPtr const& header_list() const { return m_header_list; } - [[nodiscard]] virtual NonnullRefPtr& header_list() { return m_header_list; } - void set_header_list(NonnullRefPtr header_list) { m_header_list = move(header_list); } + [[nodiscard]] virtual JS::NonnullGCPtr header_list() const { return m_header_list; } + void set_header_list(JS::NonnullGCPtr header_list) { m_header_list = header_list; } [[nodiscard]] virtual Optional const& body() const { return m_body; } [[nodiscard]] virtual Optional& body() { return m_body; } @@ -99,10 +101,12 @@ public: [[nodiscard]] Optional url() const; [[nodiscard]] ErrorOr> location_url(Optional const& request_fragment) const; - [[nodiscard]] WebIDL::ExceptionOr> clone() const; + [[nodiscard]] WebIDL::ExceptionOr> clone(JS::VM&) const; protected: - Response(); + explicit Response(JS::NonnullGCPtr); + + virtual void visit_edges(JS::Cell::Visitor&) override; private: // https://fetch.spec.whatwg.org/#concept-response-type @@ -127,7 +131,7 @@ private: // https://fetch.spec.whatwg.org/#concept-response-header-list // A response has an associated header list (a header list). Unless stated otherwise it is empty. - NonnullRefPtr m_header_list; + JS::NonnullGCPtr m_header_list; // https://fetch.spec.whatwg.org/#concept-response-body // A response has an associated body (null or a body). Unless stated otherwise it is null. @@ -163,8 +167,10 @@ private: // https://fetch.spec.whatwg.org/#concept-filtered-response class FilteredResponse : public Response { + JS_CELL(FilteredResponse, Response); + public: - explicit FilteredResponse(NonnullRefPtr); + FilteredResponse(JS::NonnullGCPtr, JS::NonnullGCPtr); virtual ~FilteredResponse() = 0; [[nodiscard]] virtual Type type() const override { return m_internal_response->type(); } @@ -173,8 +179,7 @@ public: [[nodiscard]] virtual Vector& url_list() override { return m_internal_response->url_list(); } [[nodiscard]] virtual Status status() const override { return m_internal_response->status(); } [[nodiscard]] virtual ReadonlyBytes status_message() const override { return m_internal_response->status_message(); } - [[nodiscard]] virtual NonnullRefPtr const& header_list() const override { return m_internal_response->header_list(); } - [[nodiscard]] virtual NonnullRefPtr& header_list() override { return m_internal_response->header_list(); } + [[nodiscard]] virtual JS::NonnullGCPtr header_list() const override { return m_internal_response->header_list(); } [[nodiscard]] virtual Optional const& body() const override { return m_internal_response->body(); } [[nodiscard]] virtual Optional& body() override { return m_internal_response->body(); } [[nodiscard]] virtual Optional const& cache_state() const override { return m_internal_response->cache_state(); } @@ -184,83 +189,98 @@ public: [[nodiscard]] virtual bool timing_allow_passed() const override { return m_internal_response->timing_allow_passed(); } [[nodiscard]] virtual BodyInfo const& body_info() const override { return m_internal_response->body_info(); } - [[nodiscard]] NonnullRefPtr internal_response() const { return m_internal_response; } + [[nodiscard]] JS::NonnullGCPtr internal_response() const { return m_internal_response; } protected: + virtual void visit_edges(JS::Cell::Visitor&) override; + +private: // https://fetch.spec.whatwg.org/#concept-internal-response - NonnullRefPtr m_internal_response; + JS::NonnullGCPtr m_internal_response; }; // https://fetch.spec.whatwg.org/#concept-filtered-response-basic class BasicFilteredResponse final : public FilteredResponse { + JS_CELL(OpaqueRedirectFilteredResponse, FilteredResponse); + public: - static ErrorOr> create(NonnullRefPtr); + [[nodiscard]] static ErrorOr> create(JS::VM&, JS::NonnullGCPtr); [[nodiscard]] virtual Type type() const override { return Type::Basic; } - [[nodiscard]] virtual NonnullRefPtr const& header_list() const override { return m_header_list; } - [[nodiscard]] virtual NonnullRefPtr& header_list() override { return m_header_list; } + [[nodiscard]] virtual JS::NonnullGCPtr header_list() const override { return m_header_list; } private: - BasicFilteredResponse(NonnullRefPtr, NonnullRefPtr); + BasicFilteredResponse(JS::NonnullGCPtr, JS::NonnullGCPtr); - NonnullRefPtr m_header_list; + virtual void visit_edges(JS::Cell::Visitor&) override; + + JS::NonnullGCPtr m_header_list; }; // https://fetch.spec.whatwg.org/#concept-filtered-response-cors class CORSFilteredResponse final : public FilteredResponse { + JS_CELL(CORSFilteredResponse, FilteredResponse); + public: - static ErrorOr> create(NonnullRefPtr); + [[nodiscard]] static ErrorOr> create(JS::VM&, JS::NonnullGCPtr); [[nodiscard]] virtual Type type() const override { return Type::CORS; } - [[nodiscard]] virtual NonnullRefPtr const& header_list() const override { return m_header_list; } - [[nodiscard]] virtual NonnullRefPtr& header_list() override { return m_header_list; } + [[nodiscard]] virtual JS::NonnullGCPtr header_list() const override { return m_header_list; } private: - CORSFilteredResponse(NonnullRefPtr, NonnullRefPtr); + CORSFilteredResponse(JS::NonnullGCPtr, JS::NonnullGCPtr); - NonnullRefPtr m_header_list; + virtual void visit_edges(JS::Cell::Visitor&) override; + + JS::NonnullGCPtr m_header_list; }; // https://fetch.spec.whatwg.org/#concept-filtered-response-opaque class OpaqueFilteredResponse final : public FilteredResponse { + JS_CELL(OpaqueFilteredResponse, FilteredResponse); + public: - static NonnullRefPtr create(NonnullRefPtr); + [[nodiscard]] static JS::NonnullGCPtr create(JS::VM&, JS::NonnullGCPtr); [[nodiscard]] virtual Type type() const override { return Type::Opaque; } [[nodiscard]] virtual Vector const& url_list() const override { return m_url_list; } [[nodiscard]] virtual Vector& url_list() override { return m_url_list; } [[nodiscard]] virtual Status status() const override { return 0; } [[nodiscard]] virtual ReadonlyBytes status_message() const override { return {}; } - [[nodiscard]] virtual NonnullRefPtr const& header_list() const override { return m_header_list; } - [[nodiscard]] virtual NonnullRefPtr& header_list() override { return m_header_list; } + [[nodiscard]] virtual JS::NonnullGCPtr header_list() const override { return m_header_list; } [[nodiscard]] virtual Optional const& body() const override { return m_body; } [[nodiscard]] virtual Optional& body() override { return m_body; } private: - explicit OpaqueFilteredResponse(NonnullRefPtr); + OpaqueFilteredResponse(JS::NonnullGCPtr, JS::NonnullGCPtr); + + virtual void visit_edges(JS::Cell::Visitor&) override; Vector m_url_list; - NonnullRefPtr m_header_list; + JS::NonnullGCPtr m_header_list; Optional m_body; }; // https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect class OpaqueRedirectFilteredResponse final : public FilteredResponse { + JS_CELL(OpaqueRedirectFilteredResponse, FilteredResponse); + public: - static NonnullRefPtr create(NonnullRefPtr); + [[nodiscard]] static JS::NonnullGCPtr create(JS::VM&, JS::NonnullGCPtr); [[nodiscard]] virtual Type type() const override { return Type::OpaqueRedirect; } [[nodiscard]] virtual Status status() const override { return 0; } [[nodiscard]] virtual ReadonlyBytes status_message() const override { return {}; } - [[nodiscard]] virtual NonnullRefPtr const& header_list() const override { return m_header_list; } - [[nodiscard]] virtual NonnullRefPtr& header_list() override { return m_header_list; } + [[nodiscard]] virtual JS::NonnullGCPtr header_list() const override { return m_header_list; } [[nodiscard]] virtual Optional const& body() const override { return m_body; } [[nodiscard]] virtual Optional& body() override { return m_body; } private: - explicit OpaqueRedirectFilteredResponse(NonnullRefPtr); + OpaqueRedirectFilteredResponse(JS::NonnullGCPtr, JS::NonnullGCPtr); - NonnullRefPtr m_header_list; + virtual void visit_edges(JS::Cell::Visitor&) override; + + JS::NonnullGCPtr m_header_list; Optional m_body; }; diff --git a/Userland/Libraries/LibWeb/Fetch/Request.cpp b/Userland/Libraries/LibWeb/Fetch/Request.cpp index 319852517e..09db283bf1 100644 --- a/Userland/Libraries/LibWeb/Fetch/Request.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Request.cpp @@ -20,9 +20,9 @@ namespace Web::Fetch { -Request::Request(JS::Realm& realm, NonnullRefPtr request) +Request::Request(JS::Realm& realm, JS::NonnullGCPtr request) : PlatformObject(realm) - , m_request(move(request)) + , m_request(request) { set_prototype(&Bindings::cached_web_prototype(realm, "Request")); } @@ -32,6 +32,7 @@ Request::~Request() = default; void Request::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + visitor.visit(m_request); visitor.visit(m_headers); visitor.visit(m_signal); } @@ -72,18 +73,14 @@ Optional Request::body_impl() } // https://fetch.spec.whatwg.org/#request-create -JS::NonnullGCPtr Request::create(NonnullRefPtr request, Headers::Guard guard, JS::Realm& realm) +JS::NonnullGCPtr Request::create(JS::Realm& realm, JS::NonnullGCPtr request, Headers::Guard guard) { - // Copy a NonnullRefPtr to the request's header list before request is being move()'d. - auto request_reader_list = request->header_list(); - // 1. Let requestObject be a new Request object with realm. // 2. Set requestObject’s request to request. - auto* request_object = realm.heap().allocate(realm, realm, move(request)); + auto* request_object = realm.heap().allocate(realm, realm, request); // 3. Set requestObject’s headers to a new Headers object with realm, whose headers list is request’s headers list and guard is guard. - request_object->m_headers = realm.heap().allocate(realm, realm); - request_object->m_headers->set_header_list(move(request_reader_list)); + request_object->m_headers = realm.heap().allocate(realm, realm, request->header_list()); request_object->m_headers->set_guard(guard); // 4. Set requestObject’s signal to a new AbortSignal object with realm. @@ -96,11 +93,13 @@ JS::NonnullGCPtr Request::create(NonnullRefPtr // https://fetch.spec.whatwg.org/#dom-request WebIDL::ExceptionOr> Request::construct_impl(JS::Realm& realm, RequestInfo const& input, RequestInit const& init) { + auto& vm = realm.vm(); + // Referred to as 'this' in the spec. - auto request_object = JS::NonnullGCPtr { *realm.heap().allocate(realm, realm, Infrastructure::Request::create()) }; + auto request_object = JS::NonnullGCPtr { *realm.heap().allocate(realm, realm, Infrastructure::Request::create(vm)) }; // 1. Let request be null. - RefPtr input_request; + JS::GCPtr input_request; // 2. Let fallbackMode be null. Optional fallback_mode; @@ -125,7 +124,7 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Input URL must not include credentials"sv }; // 4. Set request to a new request whose URL is parsedURL. - input_request = Infrastructure::Request::create(); + input_request = Infrastructure::Request::create(vm); input_request->set_url(move(parsed_url)); // 5. Set fallbackMode to "cors". @@ -179,10 +178,10 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm // header list // A copy of request’s header list. - auto header_list_copy = make_ref_counted(); + auto header_list_copy = Infrastructure::HeaderList::create(vm); for (auto& header : *request->header_list()) TRY_OR_RETURN_OOM(realm, header_list_copy->append(header)); - request->set_header_list(move(header_list_copy)); + request->set_header_list(header_list_copy); // unsafe-request flag // Set. @@ -389,8 +388,7 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm request_object->m_signal->follow(*input_signal); // 30. Set this’s headers to a new Headers object with this’s relevant Realm, whose header list is request’s header list and guard is "request". - request_object->m_headers = realm.heap().allocate(realm, realm); - request_object->m_headers->set_header_list(request->header_list()); + request_object->m_headers = realm.heap().allocate(realm, realm, request->header_list()); request_object->m_headers->set_guard(Headers::Guard::Request); // 31. If this’s request’s mode is "no-cors", then: @@ -406,7 +404,7 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm // 32. If init is not empty, then: if (!init.is_empty()) { // 1. Let headers be a copy of this’s headers and its associated header list. - auto headers = Variant> { request_object->headers()->header_list() }; + auto headers = Variant> { request_object->headers()->header_list() }; // 2. If init["headers"] exists, then set headers to init["headers"]. if (init.headers.has_value()) @@ -416,9 +414,8 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm request_object->headers()->header_list()->clear(); // 4. If headers is a Headers object, then for each header in its header list, append (header’s name, header’s value) to this’s headers. - if (headers.has>()) { - auto& header_list = *headers.get>(); - for (auto& header : header_list) + if (auto* header_list = headers.get_pointer>()) { + for (auto& header : *header_list->ptr()) TRY(request_object->headers()->append(String::copy(header.name), String::copy(header.value))); } // 5. Otherwise, fill this’s headers with headers. @@ -624,15 +621,17 @@ Bindings::RequestDuplex Request::duplex() const // https://fetch.spec.whatwg.org/#dom-request-clone WebIDL::ExceptionOr> Request::clone() const { + auto& vm = this->vm(); + // 1. If this is unusable, then throw a TypeError. if (is_unusable()) return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request is unusable"sv }; // 2. Let clonedRequest be the result of cloning this’s request. - auto cloned_request = TRY(m_request->clone()); + auto cloned_request = TRY(m_request->clone(vm)); // 3. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, this’s headers’s guard, and this’s relevant Realm. - auto cloned_request_object = Request::create(move(cloned_request), m_headers->guard(), HTML::relevant_realm(*this)); + auto cloned_request_object = Request::create(HTML::relevant_realm(*this), cloned_request, m_headers->guard()); // 4. Make clonedRequestObject’s signal follow this’s signal. cloned_request_object->m_signal->follow(*m_signal); diff --git a/Userland/Libraries/LibWeb/Fetch/Request.h b/Userland/Libraries/LibWeb/Fetch/Request.h index 02c2fbf7a6..acad2e5255 100644 --- a/Userland/Libraries/LibWeb/Fetch/Request.h +++ b/Userland/Libraries/LibWeb/Fetch/Request.h @@ -64,7 +64,7 @@ class Request final WEB_PLATFORM_OBJECT(Request, Bindings::PlatformObject); public: - static JS::NonnullGCPtr create(NonnullRefPtr, Headers::Guard, JS::Realm&); + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, JS::NonnullGCPtr, Headers::Guard); static WebIDL::ExceptionOr> construct_impl(JS::Realm&, RequestInfo const& input, RequestInit const& init = {}); virtual ~Request() override; @@ -74,7 +74,7 @@ public: virtual Optional body_impl() override; virtual Optional body_impl() const override; - [[nodiscard]] NonnullRefPtr request() const { return m_request; } + [[nodiscard]] JS::NonnullGCPtr request() const { return m_request; } // JS API functions [[nodiscard]] String method() const; @@ -96,13 +96,13 @@ public: [[nodiscard]] WebIDL::ExceptionOr> clone() const; private: - Request(JS::Realm&, NonnullRefPtr); + Request(JS::Realm&, JS::NonnullGCPtr); virtual void visit_edges(Cell::Visitor&) override; // https://fetch.spec.whatwg.org/#concept-request-request // A Request object has an associated request (a request). - NonnullRefPtr m_request; + JS::NonnullGCPtr m_request; // https://fetch.spec.whatwg.org/#request-headers // A Request object also has an associated headers (null or a Headers object), initially null. diff --git a/Userland/Libraries/LibWeb/Fetch/Response.cpp b/Userland/Libraries/LibWeb/Fetch/Response.cpp index 4a325c6cd2..286846adbc 100644 --- a/Userland/Libraries/LibWeb/Fetch/Response.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Response.cpp @@ -17,9 +17,9 @@ namespace Web::Fetch { -Response::Response(JS::Realm& realm, NonnullRefPtr response) +Response::Response(JS::Realm& realm, JS::NonnullGCPtr response) : PlatformObject(realm) - , m_response(move(response)) + , m_response(response) { set_prototype(&Bindings::cached_web_prototype(realm, "Response")); } @@ -29,6 +29,7 @@ Response::~Response() = default; void Response::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + visitor.visit(m_response); visitor.visit(m_headers); } @@ -64,18 +65,14 @@ Optional Response::body_impl() } // https://fetch.spec.whatwg.org/#response-create -JS::NonnullGCPtr Response::create(NonnullRefPtr response, Headers::Guard guard, JS::Realm& realm) +JS::NonnullGCPtr Response::create(JS::Realm& realm, JS::NonnullGCPtr response, Headers::Guard guard) { - // Copy a NonnullRefPtr to the response's header list before response is being move()'d. - auto response_reader_list = response->header_list(); - // 1. Let responseObject be a new Response object with realm. // 2. Set responseObject’s response to response. - auto* response_object = realm.heap().allocate(realm, realm, move(response)); + auto* response_object = realm.heap().allocate(realm, realm, response); // 3. Set responseObject’s headers to a new Headers object with realm, whose headers list is response’s headers list and guard is guard. - response_object->m_headers = realm.heap().allocate(realm, realm); - response_object->m_headers->set_header_list(move(response_reader_list)); + response_object->m_headers = realm.heap().allocate(realm, realm, response->header_list()); response_object->m_headers->set_guard(guard); // 4. Return responseObject. @@ -126,16 +123,17 @@ WebIDL::ExceptionOr Response::initialize_response(ResponseInit const& init // https://fetch.spec.whatwg.org/#dom-response WebIDL::ExceptionOr> Response::construct_impl(JS::Realm& realm, Optional const& body, ResponseInit const& init) { + auto& vm = realm.vm(); + // Referred to as 'this' in the spec. - auto response_object = JS::NonnullGCPtr { *realm.heap().allocate(realm, realm, Infrastructure::Response::create()) }; + auto response_object = JS::NonnullGCPtr { *realm.heap().allocate(realm, realm, Infrastructure::Response::create(vm)) }; // 1. Set this’s response to a new response. // NOTE: This is done at the beginning as the 'this' value Response object // cannot exist with a null Infrastructure::Response. // 2. Set this’s headers to a new Headers object with this’s relevant Realm, whose header list is this’s response’s header list and guard is "response". - response_object->m_headers = realm.heap().allocate(realm, realm); - response_object->m_headers->set_header_list(response_object->response()->header_list()); + response_object->m_headers = realm.heap().allocate(realm, realm, response_object->response()->header_list()); response_object->m_headers->set_guard(Headers::Guard::Response); // 3. Let bodyWithType be null. @@ -156,7 +154,7 @@ JS::NonnullGCPtr Response::error(JS::VM& vm) { // The static error() method steps are to return the result of creating a Response object, given a new network error, "immutable", and this’s relevant Realm. // FIXME: How can we reliably get 'this', i.e. the object the function was called on, in IDL-defined functions? - return Response::create(Infrastructure::Response::network_error(), Headers::Guard::Immutable, *vm.current_realm()); + return Response::create(*vm.current_realm(), Infrastructure::Response::network_error(vm), Headers::Guard::Immutable); } // https://fetch.spec.whatwg.org/#dom-response-redirect @@ -178,7 +176,7 @@ WebIDL::ExceptionOr> Response::redirect(JS::VM& vm, S // 4. Let responseObject be the result of creating a Response object, given a new response, "immutable", and this’s relevant Realm. // FIXME: How can we reliably get 'this', i.e. the object the function was called on, in IDL-defined functions? - auto response_object = Response::create(Infrastructure::Response::create(), Headers::Guard::Immutable, realm); + auto response_object = Response::create(realm, Infrastructure::Response::create(vm), Headers::Guard::Immutable); // 5. Set responseObject’s response’s status to status. response_object->response()->set_status(status); @@ -207,7 +205,7 @@ WebIDL::ExceptionOr> Response::json(JS::VM& vm, JS::V // 3. Let responseObject be the result of creating a Response object, given a new response, "response", and this’s relevant Realm. // FIXME: How can we reliably get 'this', i.e. the object the function was called on, in IDL-defined functions? - auto response_object = Response::create(Infrastructure::Response::create(), Headers::Guard::Response, realm); + auto response_object = Response::create(realm, Infrastructure::Response::create(vm), Headers::Guard::Response); // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). auto body_with_type = Infrastructure::BodyWithType { @@ -274,15 +272,17 @@ JS::NonnullGCPtr Response::headers() const // https://fetch.spec.whatwg.org/#dom-response-clone WebIDL::ExceptionOr> Response::clone() const { + auto& vm = this->vm(); + // 1. If this is unusable, then throw a TypeError. if (is_unusable()) return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Response is unusable"sv }; // 2. Let clonedResponse be the result of cloning this’s response. - auto cloned_response = TRY(m_response->clone()); + auto cloned_response = TRY(m_response->clone(vm)); // 3. Return the result of creating a Response object, given clonedResponse, this’s headers’s guard, and this’s relevant Realm. - return Response::create(move(cloned_response), m_headers->guard(), HTML::relevant_realm(*this)); + return Response::create(HTML::relevant_realm(*this), cloned_response, m_headers->guard()); } } diff --git a/Userland/Libraries/LibWeb/Fetch/Response.h b/Userland/Libraries/LibWeb/Fetch/Response.h index ece9943e53..2c32f65f5f 100644 --- a/Userland/Libraries/LibWeb/Fetch/Response.h +++ b/Userland/Libraries/LibWeb/Fetch/Response.h @@ -31,7 +31,7 @@ class Response final WEB_PLATFORM_OBJECT(Response, Bindings::PlatformObject); public: - static JS::NonnullGCPtr create(NonnullRefPtr, Headers::Guard, JS::Realm&); + static JS::NonnullGCPtr create(JS::Realm&, JS::NonnullGCPtr, Headers::Guard); static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Optional const& body = {}, ResponseInit const& init = {}); virtual ~Response() override; @@ -41,7 +41,7 @@ public: virtual Optional body_impl() override; virtual Optional body_impl() const override; - [[nodiscard]] NonnullRefPtr response() const { return m_response; } + [[nodiscard]] JS::NonnullGCPtr response() const { return m_response; } // JS API functions [[nodiscard]] static JS::NonnullGCPtr error(JS::VM&); @@ -60,7 +60,7 @@ public: using BodyMixin::json; private: - Response(JS::Realm&, NonnullRefPtr); + Response(JS::Realm&, JS::NonnullGCPtr); virtual void visit_edges(Cell::Visitor&) override; @@ -68,7 +68,7 @@ private: // https://fetch.spec.whatwg.org/#concept-response-response // A Response object has an associated response (a response). - NonnullRefPtr m_response; + JS::NonnullGCPtr m_response; // https://fetch.spec.whatwg.org/#response-headers // A Response object also has an associated headers (null or a Headers object), initially null. diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index 05c070d5d2..2e0006599c 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -885,14 +885,14 @@ void BrowsingContext::remove() // https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate WebIDL::ExceptionOr BrowsingContext::navigate( - NonnullRefPtr resource, + JS::NonnullGCPtr resource, BrowsingContext& source_browsing_context, bool exceptions_enabled, HistoryHandlingBehavior history_handling, Optional history_policy_container, String navigation_type, Optional navigation_id, - Function)> process_response_end_of_body) + Function)> process_response_end_of_body) { // 1. If resource is a URL, then set resource to a new request whose URL is resource. // NOTE: This function only accepts resources that are already a request, so this is irrelevant. @@ -1060,7 +1060,8 @@ WebIDL::ExceptionOr BrowsingContext::traverse_the_history(size_t entry_ind VERIFY(history_handling == HistoryHandlingBehavior::Default); // 2. Let request be a new request whose URL is entry's URL. - auto request = Fetch::Infrastructure::Request::create(); + auto& vm = Bindings::main_thread_vm(); + auto request = Fetch::Infrastructure::Request::create(vm); request->set_url(entry->url); // 3. If explicitHistoryNavigation is true, then set request's history-navigation flag. @@ -1071,7 +1072,7 @@ WebIDL::ExceptionOr BrowsingContext::traverse_the_history(size_t entry_ind // and with historyPolicyContainer set to entry's policy container. // The navigation must be done using the same source browsing context as was used the first time entry was created. VERIFY(entry->original_source_browsing_context); - TRY(navigate(move(request), *entry->original_source_browsing_context, false, HistoryHandlingBehavior::EntryUpdate, entry->policy_container)); + TRY(navigate(request, *entry->original_source_browsing_context, false, HistoryHandlingBehavior::EntryUpdate, entry->policy_container)); // 5. Return. return {}; diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h index 6fb9e8617f..5de51ab530 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -216,14 +217,14 @@ public: // https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate WebIDL::ExceptionOr navigate( - NonnullRefPtr resource, + JS::NonnullGCPtr resource, BrowsingContext& source_browsing_context, bool exceptions_enabled = false, HistoryHandlingBehavior history_handling = HistoryHandlingBehavior::Default, Optional history_policy_container = {}, String navigation_type = "other", Optional navigation_id = {}, - Function)> process_response_end_of_body = {}); + Function)> process_response_end_of_body = {}); // https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate-fragid WebIDL::ExceptionOr navigate_to_a_fragment(AK::URL const&, HistoryHandlingBehavior, String navigation_id); diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp index 1b22820814..fea13d277f 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.cpp @@ -169,7 +169,7 @@ void BrowsingContextContainer::shared_attribute_processing_steps_for_iframe_and_ } // 5. Let resource be a new request whose URL is url and whose referrer policy is the current state of element's referrerpolicy content attribute. - auto resource = Fetch::Infrastructure::Request::create(); + auto resource = Fetch::Infrastructure::Request::create(vm()); resource->set_url(url); // FIXME: Set the referrer policy. @@ -193,11 +193,11 @@ void BrowsingContextContainer::shared_attribute_processing_steps_for_iframe_and_ } // 8. Navigate to the resource: navigate an iframe or frame given element and resource. - navigate_an_iframe_or_frame(move(resource)); + navigate_an_iframe_or_frame(resource); } // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#navigate-an-iframe-or-frame -void BrowsingContextContainer::navigate_an_iframe_or_frame(NonnullRefPtr resource) +void BrowsingContextContainer::navigate_an_iframe_or_frame(JS::NonnullGCPtr resource) { // 1. Let historyHandling be "default". auto history_handling = HistoryHandlingBehavior::Default; @@ -220,7 +220,7 @@ void BrowsingContextContainer::navigate_an_iframe_or_frame(NonnullRefPtrnavigate(move(resource), *source_browsing_context, false, history_handling); + m_nested_browsing_context->navigate(resource, *source_browsing_context, false, history_handling); } } diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h index 5adcb8daed..4ac104d25d 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContextContainer.h @@ -37,7 +37,7 @@ protected: void shared_attribute_processing_steps_for_iframe_and_frame(bool initial_insertion); // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#navigate-an-iframe-or-frame - void navigate_an_iframe_or_frame(NonnullRefPtr); + void navigate_an_iframe_or_frame(JS::NonnullGCPtr); void create_new_nested_browsing_context(); diff --git a/Userland/Libraries/LibWeb/HTML/NavigationParams.h b/Userland/Libraries/LibWeb/HTML/NavigationParams.h index 45855b2625..de2be5bd7d 100644 --- a/Userland/Libraries/LibWeb/HTML/NavigationParams.h +++ b/Userland/Libraries/LibWeb/HTML/NavigationParams.h @@ -23,10 +23,10 @@ struct NavigationParams { String id; // null or a request that started the navigation - RefPtr request; + JS::GCPtr request; // a response that ultimately was navigated to (potentially a network error) - NonnullRefPtr response; + JS::NonnullGCPtr response; // an origin to use for the new Document Origin origin; diff --git a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp index 521c48ba1f..357ad0efbe 100644 --- a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -298,12 +299,13 @@ bool FrameLoader::load(const AK::URL& url, Type type) void FrameLoader::load_html(StringView html, const AK::URL& url) { - auto response = Fetch::Infrastructure::Response::create(); + auto& vm = Bindings::main_thread_vm(); + auto response = Fetch::Infrastructure::Response::create(vm); response->url_list().append(url); HTML::NavigationParams navigation_params { .id = {}, .request = nullptr, - .response = move(response), + .response = response, .origin = HTML::Origin {}, .policy_container = HTML::PolicyContainer {}, .final_sandboxing_flag_set = HTML::SandboxingFlagSet {}, @@ -418,15 +420,16 @@ void FrameLoader::resource_did_load() // FIXME: Pass incumbentNavigationOrigin auto response_origin = HTML::determine_the_origin(browsing_context(), url, final_sandboxing_flag_set, {}); - auto response = Fetch::Infrastructure::Response::create(); + auto& vm = Bindings::main_thread_vm(); + auto response = Fetch::Infrastructure::Response::create(vm); response->url_list().append(url); HTML::NavigationParams navigation_params { .id = {}, .request = nullptr, - .response = move(response), + .response = response, .origin = move(response_origin), .policy_container = HTML::PolicyContainer {}, - .final_sandboxing_flag_set = move(final_sandboxing_flag_set), + .final_sandboxing_flag_set = final_sandboxing_flag_set, .cross_origin_opener_policy = HTML::CrossOriginOpenerPolicy {}, .coop_enforcement_result = HTML::CrossOriginOpenerPolicyEnforcementResult {}, .reserved_environment = {}, diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index 001512452b..150ac7b598 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -236,8 +236,10 @@ MimeSniff::MimeType XMLHttpRequest::get_final_mime_type() const // https://xhr.spec.whatwg.org/#response-mime-type MimeSniff::MimeType XMLHttpRequest::get_response_mime_type() const { + auto& vm = this->vm(); + // FIXME: Use an actual HeaderList for XHR headers. - auto header_list = make_ref_counted(); + auto header_list = Fetch::Infrastructure::HeaderList::create(vm); for (auto const& entry : m_response_headers) { auto header = Fetch::Infrastructure::Header::from_string_pair(entry.key, entry.value).release_value_but_fixme_should_propagate_errors(); header_list->append(move(header)).release_value_but_fixme_should_propagate_errors();