mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 13:57:35 +00:00
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().
This commit is contained in:
parent
63122d0276
commit
b1968b8bed
19 changed files with 270 additions and 169 deletions
|
@ -11,6 +11,8 @@
|
|||
#include <AK/GenericLexer.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibRegex/Regex.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||
|
@ -42,6 +44,11 @@ ErrorOr<Header> Header::from_string_pair(StringView name, StringView value)
|
|||
};
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<HeaderList> HeaderList::create(JS::VM& vm)
|
||||
{
|
||||
return { *vm.heap().allocate_without_realm<HeaderList>() };
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#header-list-contains
|
||||
bool HeaderList::contains(ReadonlyBytes name) const
|
||||
{
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <AK/Optional.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/Cell.h>
|
||||
#include <LibWeb/MimeSniff/MimeType.h>
|
||||
|
||||
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<HeaderList>
|
||||
: public JS::Cell
|
||||
, Vector<Header> {
|
||||
JS_CELL(HeaderList, JS::Cell);
|
||||
|
||||
public:
|
||||
using Vector::begin;
|
||||
using Vector::clear;
|
||||
using Vector::end;
|
||||
|
||||
[[nodiscard]] static JS::NonnullGCPtr<HeaderList> create(JS::VM&);
|
||||
|
||||
[[nodiscard]] bool contains(ReadonlyBytes) const;
|
||||
[[nodiscard]] ErrorOr<Optional<ByteBuffer>> get(ReadonlyBytes) const;
|
||||
[[nodiscard]] ErrorOr<Optional<Vector<String>>> get_decode_and_split(ReadonlyBytes) const;
|
||||
|
|
|
@ -5,18 +5,26 @@
|
|||
*/
|
||||
|
||||
#include <AK/Array.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||
|
||||
namespace Web::Fetch::Infrastructure {
|
||||
|
||||
Request::Request()
|
||||
: m_header_list(make_ref_counted<HeaderList>())
|
||||
Request::Request(JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: m_header_list(header_list)
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<Request> 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> Request::create(JS::VM& vm)
|
||||
{
|
||||
return { *vm.heap().allocate_without_realm<Request>(HeaderList::create(vm)) };
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-request-url
|
||||
|
@ -181,12 +189,12 @@ ErrorOr<ByteBuffer> Request::byte_serialize_origin() const
|
|||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-request-clone
|
||||
WebIDL::ExceptionOr<NonnullRefPtr<Request>> Request::clone() const
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> 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)
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#include <AK/Error.h>
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/URL.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/Cell.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||
#include <LibWeb/HTML/Origin.h>
|
||||
|
@ -24,7 +25,9 @@
|
|||
namespace Web::Fetch::Infrastructure {
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-request
|
||||
class Request final : public RefCounted<Request> {
|
||||
class Request final : public JS::Cell {
|
||||
JS_CELL(Request, JS::Cell);
|
||||
|
||||
public:
|
||||
enum class CacheMode {
|
||||
Default,
|
||||
|
@ -156,7 +159,7 @@ public:
|
|||
using ReservedClientType = Variant<Empty, HTML::Environment*, HTML::EnvironmentSettingsObject*>;
|
||||
using WindowType = Variant<Window, HTML::EnvironmentSettingsObject*>;
|
||||
|
||||
static NonnullRefPtr<Request> create();
|
||||
[[nodiscard]] static JS::NonnullGCPtr<Request> 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<HeaderList> const& header_list() const { return m_header_list; }
|
||||
[[nodiscard]] NonnullRefPtr<HeaderList>& header_list() { return m_header_list; }
|
||||
void set_header_list(NonnullRefPtr<HeaderList> header_list) { m_header_list = move(header_list); }
|
||||
[[nodiscard]] JS::NonnullGCPtr<HeaderList> header_list() const { return m_header_list; }
|
||||
void set_header_list(JS::NonnullGCPtr<HeaderList> 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<ByteBuffer> byte_serialize_origin() const;
|
||||
|
||||
[[nodiscard]] WebIDL::ExceptionOr<NonnullRefPtr<Request>> clone() const;
|
||||
[[nodiscard]] WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> clone(JS::VM&) const;
|
||||
|
||||
[[nodiscard]] ErrorOr<void> add_range_header(u64 first, Optional<u64> const& last);
|
||||
|
||||
[[nodiscard]] bool cross_origin_embedder_policy_allows_credentials() const;
|
||||
|
||||
private:
|
||||
Request();
|
||||
explicit Request(JS::NonnullGCPtr<HeaderList>);
|
||||
|
||||
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<HeaderList> m_header_list;
|
||||
JS::NonnullGCPtr<HeaderList> 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.
|
||||
|
|
|
@ -4,36 +4,44 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||
|
||||
namespace Web::Fetch::Infrastructure {
|
||||
|
||||
Response::Response()
|
||||
: m_header_list(make_ref_counted<HeaderList>())
|
||||
Response::Response(JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: m_header_list(header_list)
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<Response> 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> Response::create(JS::VM& vm)
|
||||
{
|
||||
return { *vm.heap().allocate_without_realm<Response>(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> Response::aborted_network_error()
|
||||
JS::NonnullGCPtr<Response> Response::aborted_network_error(JS::VM& vm)
|
||||
{
|
||||
auto response = network_error();
|
||||
auto response = network_error(vm);
|
||||
response->set_aborted(true);
|
||||
return response;
|
||||
}
|
||||
|
||||
NonnullRefPtr<Response> Response::network_error()
|
||||
JS::NonnullGCPtr<Response> 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<Optional<AK::URL>> Response::location_url(Optional<String> const& reques
|
|||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-response-clone
|
||||
WebIDL::ExceptionOr<NonnullRefPtr<Response>> Response::clone() const
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<Response>> 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<FilteredResponse>(*this)) {
|
||||
auto internal_response = TRY(static_cast<FilteredResponse const&>(*this).internal_response()->clone());
|
||||
auto internal_response = TRY(static_cast<FilteredResponse const&>(*this).internal_response()->clone(vm));
|
||||
if (is<BasicFilteredResponse>(*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<CORSFilteredResponse>(*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<OpaqueFilteredResponse>(*this))
|
||||
return OpaqueFilteredResponse::create(move(internal_response));
|
||||
return OpaqueFilteredResponse::create(vm, internal_response);
|
||||
if (is<OpaqueRedirectFilteredResponse>(*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<NonnullRefPtr<Response>> Response::clone() const
|
|||
return new_response;
|
||||
}
|
||||
|
||||
FilteredResponse::FilteredResponse(NonnullRefPtr<Response> internal_response)
|
||||
: m_internal_response(move(internal_response))
|
||||
FilteredResponse::FilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: Response(header_list)
|
||||
, m_internal_response(internal_response)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -148,26 +156,38 @@ FilteredResponse::~FilteredResponse()
|
|||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<BasicFilteredResponse>> BasicFilteredResponse::create(NonnullRefPtr<Response> internal_response)
|
||||
void FilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_internal_response);
|
||||
}
|
||||
|
||||
ErrorOr<JS::NonnullGCPtr<BasicFilteredResponse>> BasicFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> 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<HeaderList>();
|
||||
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<BasicFilteredResponse>(internal_response, header_list) };
|
||||
}
|
||||
|
||||
BasicFilteredResponse::BasicFilteredResponse(NonnullRefPtr<Response> internal_response, NonnullRefPtr<HeaderList> header_list)
|
||||
: FilteredResponse(move(internal_response))
|
||||
, m_header_list(move(header_list))
|
||||
BasicFilteredResponse::BasicFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: FilteredResponse(internal_response, header_list)
|
||||
, m_header_list(header_list)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<CORSFilteredResponse>> CORSFilteredResponse::create(NonnullRefPtr<Response> internal_response)
|
||||
void BasicFilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_header_list);
|
||||
}
|
||||
|
||||
ErrorOr<JS::NonnullGCPtr<CORSFilteredResponse>> CORSFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> 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<NonnullRefPtr<CORSFilteredResponse>> 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<HeaderList>();
|
||||
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<CORSFilteredResponse>(internal_response, header_list) };
|
||||
}
|
||||
|
||||
CORSFilteredResponse::CORSFilteredResponse(NonnullRefPtr<Response> internal_response, NonnullRefPtr<HeaderList> header_list)
|
||||
: FilteredResponse(move(internal_response))
|
||||
, m_header_list(move(header_list))
|
||||
CORSFilteredResponse::CORSFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: FilteredResponse(internal_response, header_list)
|
||||
, m_header_list(header_list)
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<OpaqueFilteredResponse> OpaqueFilteredResponse::create(NonnullRefPtr<Response> internal_response)
|
||||
void CORSFilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_header_list);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<OpaqueFilteredResponse> OpaqueFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> 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<OpaqueFilteredResponse>(internal_response, HeaderList::create(vm)) };
|
||||
}
|
||||
|
||||
OpaqueFilteredResponse::OpaqueFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> 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> OpaqueRedirectFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> 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<OpaqueRedirectFilteredResponse>(internal_response, HeaderList::create(vm)) };
|
||||
}
|
||||
|
||||
OpaqueFilteredResponse::OpaqueFilteredResponse(NonnullRefPtr<Response> internal_response)
|
||||
: FilteredResponse(move(internal_response))
|
||||
, m_header_list(make_ref_counted<HeaderList>())
|
||||
OpaqueRedirectFilteredResponse::OpaqueRedirectFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: FilteredResponse(internal_response, header_list)
|
||||
, m_header_list(header_list)
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<OpaqueRedirectFilteredResponse> OpaqueRedirectFilteredResponse::create(NonnullRefPtr<Response> internal_response)
|
||||
{
|
||||
return adopt_ref(*new OpaqueRedirectFilteredResponse(move(internal_response)));
|
||||
}
|
||||
|
||||
OpaqueRedirectFilteredResponse::OpaqueRedirectFilteredResponse(NonnullRefPtr<Response> internal_response)
|
||||
: FilteredResponse(move(internal_response))
|
||||
, m_header_list(make_ref_counted<HeaderList>())
|
||||
void OpaqueRedirectFilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_header_list);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#include <AK/Error.h>
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/URL.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/Cell.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h>
|
||||
|
@ -20,7 +21,9 @@
|
|||
namespace Web::Fetch::Infrastructure {
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-response
|
||||
class Response : public RefCounted<Response> {
|
||||
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<Response> create();
|
||||
[[nodiscard]] static NonnullRefPtr<Response> aborted_network_error();
|
||||
[[nodiscard]] static NonnullRefPtr<Response> network_error();
|
||||
[[nodiscard]] static JS::NonnullGCPtr<Response> create(JS::VM&);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<Response> aborted_network_error(JS::VM&);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<Response> 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<HeaderList> const& header_list() const { return m_header_list; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList>& header_list() { return m_header_list; }
|
||||
void set_header_list(NonnullRefPtr<HeaderList> header_list) { m_header_list = move(header_list); }
|
||||
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const { return m_header_list; }
|
||||
void set_header_list(JS::NonnullGCPtr<HeaderList> header_list) { m_header_list = header_list; }
|
||||
|
||||
[[nodiscard]] virtual Optional<Body> const& body() const { return m_body; }
|
||||
[[nodiscard]] virtual Optional<Body>& body() { return m_body; }
|
||||
|
@ -99,10 +101,12 @@ public:
|
|||
[[nodiscard]] Optional<AK::URL const&> url() const;
|
||||
[[nodiscard]] ErrorOr<Optional<AK::URL>> location_url(Optional<String> const& request_fragment) const;
|
||||
|
||||
[[nodiscard]] WebIDL::ExceptionOr<NonnullRefPtr<Response>> clone() const;
|
||||
[[nodiscard]] WebIDL::ExceptionOr<JS::NonnullGCPtr<Response>> clone(JS::VM&) const;
|
||||
|
||||
protected:
|
||||
Response();
|
||||
explicit Response(JS::NonnullGCPtr<HeaderList>);
|
||||
|
||||
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<HeaderList> m_header_list;
|
||||
JS::NonnullGCPtr<HeaderList> 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<Response>);
|
||||
FilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
|
||||
virtual ~FilteredResponse() = 0;
|
||||
|
||||
[[nodiscard]] virtual Type type() const override { return m_internal_response->type(); }
|
||||
|
@ -173,8 +179,7 @@ public:
|
|||
[[nodiscard]] virtual Vector<AK::URL>& 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<HeaderList> const& header_list() const override { return m_internal_response->header_list(); }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList>& header_list() override { return m_internal_response->header_list(); }
|
||||
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_internal_response->header_list(); }
|
||||
[[nodiscard]] virtual Optional<Body> const& body() const override { return m_internal_response->body(); }
|
||||
[[nodiscard]] virtual Optional<Body>& body() override { return m_internal_response->body(); }
|
||||
[[nodiscard]] virtual Optional<CacheState> 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<Response> internal_response() const { return m_internal_response; }
|
||||
[[nodiscard]] JS::NonnullGCPtr<Response> 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<Response> m_internal_response;
|
||||
JS::NonnullGCPtr<Response> m_internal_response;
|
||||
};
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-filtered-response-basic
|
||||
class BasicFilteredResponse final : public FilteredResponse {
|
||||
JS_CELL(OpaqueRedirectFilteredResponse, FilteredResponse);
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<BasicFilteredResponse>> create(NonnullRefPtr<Response>);
|
||||
[[nodiscard]] static ErrorOr<JS::NonnullGCPtr<BasicFilteredResponse>> create(JS::VM&, JS::NonnullGCPtr<Response>);
|
||||
|
||||
[[nodiscard]] virtual Type type() const override { return Type::Basic; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList> const& header_list() const override { return m_header_list; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList>& header_list() override { return m_header_list; }
|
||||
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
|
||||
|
||||
private:
|
||||
BasicFilteredResponse(NonnullRefPtr<Response>, NonnullRefPtr<HeaderList>);
|
||||
BasicFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
|
||||
|
||||
NonnullRefPtr<HeaderList> m_header_list;
|
||||
virtual void visit_edges(JS::Cell::Visitor&) override;
|
||||
|
||||
JS::NonnullGCPtr<HeaderList> m_header_list;
|
||||
};
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-filtered-response-cors
|
||||
class CORSFilteredResponse final : public FilteredResponse {
|
||||
JS_CELL(CORSFilteredResponse, FilteredResponse);
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<CORSFilteredResponse>> create(NonnullRefPtr<Response>);
|
||||
[[nodiscard]] static ErrorOr<JS::NonnullGCPtr<CORSFilteredResponse>> create(JS::VM&, JS::NonnullGCPtr<Response>);
|
||||
|
||||
[[nodiscard]] virtual Type type() const override { return Type::CORS; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList> const& header_list() const override { return m_header_list; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList>& header_list() override { return m_header_list; }
|
||||
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
|
||||
|
||||
private:
|
||||
CORSFilteredResponse(NonnullRefPtr<Response>, NonnullRefPtr<HeaderList>);
|
||||
CORSFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
|
||||
|
||||
NonnullRefPtr<HeaderList> m_header_list;
|
||||
virtual void visit_edges(JS::Cell::Visitor&) override;
|
||||
|
||||
JS::NonnullGCPtr<HeaderList> m_header_list;
|
||||
};
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
|
||||
class OpaqueFilteredResponse final : public FilteredResponse {
|
||||
JS_CELL(OpaqueFilteredResponse, FilteredResponse);
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<OpaqueFilteredResponse> create(NonnullRefPtr<Response>);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<OpaqueFilteredResponse> create(JS::VM&, JS::NonnullGCPtr<Response>);
|
||||
|
||||
[[nodiscard]] virtual Type type() const override { return Type::Opaque; }
|
||||
[[nodiscard]] virtual Vector<AK::URL> const& url_list() const override { return m_url_list; }
|
||||
[[nodiscard]] virtual Vector<AK::URL>& 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<HeaderList> const& header_list() const override { return m_header_list; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList>& header_list() override { return m_header_list; }
|
||||
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
|
||||
[[nodiscard]] virtual Optional<Body> const& body() const override { return m_body; }
|
||||
[[nodiscard]] virtual Optional<Body>& body() override { return m_body; }
|
||||
|
||||
private:
|
||||
explicit OpaqueFilteredResponse(NonnullRefPtr<Response>);
|
||||
OpaqueFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
|
||||
|
||||
virtual void visit_edges(JS::Cell::Visitor&) override;
|
||||
|
||||
Vector<AK::URL> m_url_list;
|
||||
NonnullRefPtr<HeaderList> m_header_list;
|
||||
JS::NonnullGCPtr<HeaderList> m_header_list;
|
||||
Optional<Body> m_body;
|
||||
};
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect
|
||||
class OpaqueRedirectFilteredResponse final : public FilteredResponse {
|
||||
JS_CELL(OpaqueRedirectFilteredResponse, FilteredResponse);
|
||||
|
||||
public:
|
||||
static NonnullRefPtr<OpaqueRedirectFilteredResponse> create(NonnullRefPtr<Response>);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<OpaqueRedirectFilteredResponse> create(JS::VM&, JS::NonnullGCPtr<Response>);
|
||||
|
||||
[[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<HeaderList> const& header_list() const override { return m_header_list; }
|
||||
[[nodiscard]] virtual NonnullRefPtr<HeaderList>& header_list() override { return m_header_list; }
|
||||
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
|
||||
[[nodiscard]] virtual Optional<Body> const& body() const override { return m_body; }
|
||||
[[nodiscard]] virtual Optional<Body>& body() override { return m_body; }
|
||||
|
||||
private:
|
||||
explicit OpaqueRedirectFilteredResponse(NonnullRefPtr<Response>);
|
||||
OpaqueRedirectFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
|
||||
|
||||
NonnullRefPtr<HeaderList> m_header_list;
|
||||
virtual void visit_edges(JS::Cell::Visitor&) override;
|
||||
|
||||
JS::NonnullGCPtr<HeaderList> m_header_list;
|
||||
Optional<Body> m_body;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue