LibGC+Everywhere: Factor out a LibGC from LibJS

Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
This commit is contained in:
Shannon Booth 2024-11-15 04:01:23 +13:00 committed by Andreas Kling
parent ce23efc5f6
commit f87041bf3a
Notes: github-actions[bot] 2024-11-15 13:50:17 +00:00
1722 changed files with 9939 additions and 9906 deletions

View file

@ -16,24 +16,24 @@
namespace Web::Fetch::Infrastructure {
JS_DEFINE_ALLOCATOR(Body);
GC_DEFINE_ALLOCATOR(Body);
JS::NonnullGCPtr<Body> Body::create(JS::VM& vm, JS::NonnullGCPtr<Streams::ReadableStream> stream)
GC::Ref<Body> Body::create(JS::VM& vm, GC::Ref<Streams::ReadableStream> stream)
{
return vm.heap().allocate<Body>(stream);
}
JS::NonnullGCPtr<Body> Body::create(JS::VM& vm, JS::NonnullGCPtr<Streams::ReadableStream> stream, SourceType source, Optional<u64> length)
GC::Ref<Body> Body::create(JS::VM& vm, GC::Ref<Streams::ReadableStream> stream, SourceType source, Optional<u64> length)
{
return vm.heap().allocate<Body>(stream, source, length);
}
Body::Body(JS::NonnullGCPtr<Streams::ReadableStream> stream)
Body::Body(GC::Ref<Streams::ReadableStream> stream)
: m_stream(move(stream))
{
}
Body::Body(JS::NonnullGCPtr<Streams::ReadableStream> stream, SourceType source, Optional<u64> length)
Body::Body(GC::Ref<Streams::ReadableStream> stream, SourceType source, Optional<u64> length)
: m_stream(move(stream))
, m_source(move(source))
, m_length(move(length))
@ -47,7 +47,7 @@ void Body::visit_edges(Cell::Visitor& visitor)
}
// https://fetch.spec.whatwg.org/#concept-body-clone
JS::NonnullGCPtr<Body> Body::clone(JS::Realm& realm)
GC::Ref<Body> Body::clone(JS::Realm& realm)
{
HTML::TemporaryExecutionContext execution_context { realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
@ -68,21 +68,21 @@ void Body::fully_read(JS::Realm& realm, Web::Fetch::Infrastructure::Body::Proces
// FIXME: 1. If taskDestination is null, then set taskDestination to the result of starting a new parallel queue.
// FIXME: Handle 'parallel queue' task destination
VERIFY(!task_destination.has<Empty>());
auto task_destination_object = task_destination.get<JS::NonnullGCPtr<JS::Object>>();
auto task_destination_object = task_destination.get<GC::Ref<JS::Object>>();
// 2. Let successSteps given a byte sequence bytes be to queue a fetch task to run processBody given bytes, with taskDestination.
auto success_steps = [&realm, process_body, task_destination_object = task_destination_object](ReadonlyBytes bytes) -> ErrorOr<void> {
// Make a copy of the bytes, as the source of the bytes may disappear between the time the task is queued and executed.
auto bytes_copy = TRY(ByteBuffer::copy(bytes));
queue_fetch_task(*task_destination_object, JS::create_heap_function(realm.heap(), [process_body, bytes_copy = move(bytes_copy)]() mutable {
queue_fetch_task(*task_destination_object, GC::create_function(realm.heap(), [process_body, bytes_copy = move(bytes_copy)]() mutable {
process_body->function()(move(bytes_copy));
}));
return {};
};
// 3. Let errorSteps optionally given an exception exception be to queue a fetch task to run processBodyError given exception, with taskDestination.
auto error_steps = [&realm, process_body_error, task_destination_object](JS::GCPtr<WebIDL::DOMException> exception) {
queue_fetch_task(*task_destination_object, JS::create_heap_function(realm.heap(), [process_body_error, exception]() {
auto error_steps = [&realm, process_body_error, task_destination_object](GC::Ptr<WebIDL::DOMException> exception) {
queue_fetch_task(*task_destination_object, GC::create_function(realm.heap(), [process_body_error, exception]() {
process_body_error->function()(exception);
}));
};
@ -95,7 +95,7 @@ void Body::fully_read(JS::Realm& realm, Web::Fetch::Infrastructure::Body::Proces
if (auto result = success_steps(byte_buffer); result.is_error())
error_steps(WebIDL::UnknownError::create(realm, "Out-of-memory"_string));
},
[&](JS::Handle<FileAPI::Blob> const& blob) {
[&](GC::Root<FileAPI::Blob> const& blob) {
if (auto result = success_steps(blob->raw_bytes()); result.is_error())
error_steps(WebIDL::UnknownError::create(realm, "Out-of-memory"_string));
},
@ -109,7 +109,7 @@ void Body::incrementally_read(ProcessBodyChunkCallback process_body_chunk, Proce
{
HTML::TemporaryExecutionContext const execution_context { m_stream->realm(), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes };
VERIFY(task_destination.has<JS::NonnullGCPtr<JS::Object>>());
VERIFY(task_destination.has<GC::Ref<JS::Object>>());
// FIXME: 1. If taskDestination is null, then set taskDestination to the result of starting a new parallel queue.
// FIXME: Handle 'parallel queue' task destination
@ -118,11 +118,11 @@ void Body::incrementally_read(ProcessBodyChunkCallback process_body_chunk, Proce
auto reader = MUST(Streams::acquire_readable_stream_default_reader(m_stream));
// 3. Perform the incrementally-read loop given reader, taskDestination, processBodyChunk, processEndOfBody, and processBodyError.
incrementally_read_loop(reader, task_destination.get<JS::NonnullGCPtr<JS::Object>>(), process_body_chunk, process_end_of_body, process_body_error);
incrementally_read_loop(reader, task_destination.get<GC::Ref<JS::Object>>(), process_body_chunk, process_end_of_body, process_body_error);
}
// https://fetch.spec.whatwg.org/#incrementally-read-loop
void Body::incrementally_read_loop(Streams::ReadableStreamDefaultReader& reader, JS::NonnullGCPtr<JS::Object> task_destination, ProcessBodyChunkCallback process_body_chunk, ProcessEndOfBodyCallback process_end_of_body, ProcessBodyErrorCallback process_body_error)
void Body::incrementally_read_loop(Streams::ReadableStreamDefaultReader& reader, GC::Ref<JS::Object> task_destination, ProcessBodyChunkCallback process_body_chunk, ProcessEndOfBodyCallback process_end_of_body, ProcessBodyErrorCallback process_body_error)
{
auto& realm = reader.realm();
@ -134,7 +134,7 @@ void Body::incrementally_read_loop(Streams::ReadableStreamDefaultReader& reader,
}
// https://fetch.spec.whatwg.org/#byte-sequence-as-a-body
WebIDL::ExceptionOr<JS::NonnullGCPtr<Body>> byte_sequence_as_body(JS::Realm& realm, ReadonlyBytes bytes)
WebIDL::ExceptionOr<GC::Ref<Body>> byte_sequence_as_body(JS::Realm& realm, ReadonlyBytes bytes)
{
// To get a byte sequence bytes as a body, return the body of the result of safely extracting bytes.
auto [body, _] = TRY(safely_extract_body(realm, bytes));

View file

@ -11,8 +11,8 @@
#include <AK/NonnullRefPtr.h>
#include <AK/Optional.h>
#include <AK/Variant.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Heap/Handle.h>
#include <LibGC/Ptr.h>
#include <LibGC/Root.h>
#include <LibWeb/Fetch/Infrastructure/Task.h>
#include <LibWeb/FileAPI/Blob.h>
#include <LibWeb/Streams/ReadableStream.h>
@ -22,43 +22,43 @@ namespace Web::Fetch::Infrastructure {
// https://fetch.spec.whatwg.org/#concept-body
class Body final : public JS::Cell {
JS_CELL(Body, JS::Cell);
JS_DECLARE_ALLOCATOR(Body);
GC_CELL(Body, JS::Cell);
GC_DECLARE_ALLOCATOR(Body);
public:
using SourceType = Variant<Empty, ByteBuffer, JS::Handle<FileAPI::Blob>>;
using SourceType = Variant<Empty, ByteBuffer, GC::Root<FileAPI::Blob>>;
// processBody must be an algorithm accepting a byte sequence.
using ProcessBodyCallback = JS::NonnullGCPtr<JS::HeapFunction<void(ByteBuffer)>>;
using ProcessBodyCallback = GC::Ref<GC::Function<void(ByteBuffer)>>;
// processBodyError must be an algorithm optionally accepting an exception.
using ProcessBodyErrorCallback = JS::NonnullGCPtr<JS::HeapFunction<void(JS::Value)>>;
using ProcessBodyErrorCallback = GC::Ref<GC::Function<void(JS::Value)>>;
// processBodyChunk must be an algorithm accepting a byte sequence.
using ProcessBodyChunkCallback = JS::NonnullGCPtr<JS::HeapFunction<void(ByteBuffer)>>;
using ProcessBodyChunkCallback = GC::Ref<GC::Function<void(ByteBuffer)>>;
// processEndOfBody must be an algorithm accepting no arguments
using ProcessEndOfBodyCallback = JS::NonnullGCPtr<JS::HeapFunction<void()>>;
using ProcessEndOfBodyCallback = GC::Ref<GC::Function<void()>>;
[[nodiscard]] static JS::NonnullGCPtr<Body> create(JS::VM&, JS::NonnullGCPtr<Streams::ReadableStream>);
[[nodiscard]] static JS::NonnullGCPtr<Body> create(JS::VM&, JS::NonnullGCPtr<Streams::ReadableStream>, SourceType, Optional<u64>);
[[nodiscard]] static GC::Ref<Body> create(JS::VM&, GC::Ref<Streams::ReadableStream>);
[[nodiscard]] static GC::Ref<Body> create(JS::VM&, GC::Ref<Streams::ReadableStream>, SourceType, Optional<u64>);
[[nodiscard]] JS::NonnullGCPtr<Streams::ReadableStream> stream() const { return *m_stream; }
void set_stream(JS::NonnullGCPtr<Streams::ReadableStream> value) { m_stream = value; }
[[nodiscard]] GC::Ref<Streams::ReadableStream> stream() const { return *m_stream; }
void set_stream(GC::Ref<Streams::ReadableStream> value) { m_stream = value; }
[[nodiscard]] SourceType const& source() const { return m_source; }
[[nodiscard]] Optional<u64> const& length() const { return m_length; }
[[nodiscard]] JS::NonnullGCPtr<Body> clone(JS::Realm&);
[[nodiscard]] GC::Ref<Body> clone(JS::Realm&);
void fully_read(JS::Realm&, ProcessBodyCallback process_body, ProcessBodyErrorCallback process_body_error, TaskDestination task_destination) const;
void incrementally_read(ProcessBodyChunkCallback process_body_chunk, ProcessEndOfBodyCallback process_end_of_body, ProcessBodyErrorCallback process_body_error, TaskDestination task_destination);
void incrementally_read_loop(Streams::ReadableStreamDefaultReader& reader, JS::NonnullGCPtr<JS::Object> task_destination, ProcessBodyChunkCallback process_body_chunk, ProcessEndOfBodyCallback process_end_of_body, ProcessBodyErrorCallback process_body_error);
void incrementally_read_loop(Streams::ReadableStreamDefaultReader& reader, GC::Ref<JS::Object> task_destination, ProcessBodyChunkCallback process_body_chunk, ProcessEndOfBodyCallback process_end_of_body, ProcessBodyErrorCallback process_body_error);
virtual void visit_edges(JS::Cell::Visitor&) override;
private:
explicit Body(JS::NonnullGCPtr<Streams::ReadableStream>);
Body(JS::NonnullGCPtr<Streams::ReadableStream>, SourceType, Optional<u64>);
explicit Body(GC::Ref<Streams::ReadableStream>);
Body(GC::Ref<Streams::ReadableStream>, SourceType, Optional<u64>);
// https://fetch.spec.whatwg.org/#concept-body-stream
// A stream (a ReadableStream object).
JS::NonnullGCPtr<Streams::ReadableStream> m_stream;
GC::Ref<Streams::ReadableStream> m_stream;
// https://fetch.spec.whatwg.org/#concept-body-source
// A source (null, a byte sequence, a Blob object, or a FormData object), initially null.
@ -72,10 +72,10 @@ private:
// https://fetch.spec.whatwg.org/#body-with-type
// A body with type is a tuple that consists of a body (a body) and a type (a header value or null).
struct BodyWithType {
JS::NonnullGCPtr<Body> body;
GC::Ref<Body> body;
Optional<ByteBuffer> type;
};
WebIDL::ExceptionOr<JS::NonnullGCPtr<Body>> byte_sequence_as_body(JS::Realm&, ReadonlyBytes);
WebIDL::ExceptionOr<GC::Ref<Body>> byte_sequence_as_body(JS::Realm&, ReadonlyBytes);
}

View file

@ -12,7 +12,7 @@
#include <AK/QuickSort.h>
#include <AK/ScopeGuard.h>
#include <AK/StringUtils.h>
#include <LibJS/Heap/Heap.h>
#include <LibGC/Heap.h>
#include <LibJS/Runtime/VM.h>
#include <LibRegex/Regex.h>
#include <LibTextCodec/Decoder.h>
@ -26,7 +26,7 @@
namespace Web::Fetch::Infrastructure {
JS_DEFINE_ALLOCATOR(HeaderList);
GC_DEFINE_ALLOCATOR(HeaderList);
template<typename T>
requires(IsSameIgnoringCV<T, u8>) struct CaseInsensitiveBytesTraits : public Traits<Span<T>> {
@ -58,7 +58,7 @@ Header Header::from_string_pair(StringView name, StringView value)
};
}
JS::NonnullGCPtr<HeaderList> HeaderList::create(JS::VM& vm)
GC::Ref<HeaderList> HeaderList::create(JS::VM& vm)
{
return vm.heap().allocate<HeaderList>();
}

View file

@ -13,10 +13,10 @@
#include <AK/Optional.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibGC/Heap.h>
#include <LibGC/Ptr.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Heap/Heap.h>
#include <LibWeb/MimeSniff/MimeType.h>
namespace Web::Fetch::Infrastructure {
@ -36,8 +36,8 @@ struct Header {
class HeaderList final
: public JS::Cell
, public Vector<Header> {
JS_CELL(HeaderList, JS::Cell);
JS_DECLARE_ALLOCATOR(HeaderList);
GC_CELL(HeaderList, JS::Cell);
GC_DECLARE_ALLOCATOR(HeaderList);
public:
using Vector::begin;
@ -45,7 +45,7 @@ public:
using Vector::end;
using Vector::is_empty;
[[nodiscard]] static JS::NonnullGCPtr<HeaderList> create(JS::VM&);
[[nodiscard]] static GC::Ref<HeaderList> create(JS::VM&);
[[nodiscard]] bool contains(ReadonlyBytes) const;
[[nodiscard]] Optional<ByteBuffer> get(ReadonlyBytes) const;

View file

@ -5,7 +5,7 @@
*/
#include <AK/Array.h>
#include <LibJS/Heap/Heap.h>
#include <LibGC/Heap.h>
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/DOMURL/DOMURL.h>
#include <LibWeb/Fetch/Fetching/PendingResponse.h>
@ -13,9 +13,9 @@
namespace Web::Fetch::Infrastructure {
JS_DEFINE_ALLOCATOR(Request);
GC_DEFINE_ALLOCATOR(Request);
Request::Request(JS::NonnullGCPtr<HeaderList> header_list)
Request::Request(GC::Ref<HeaderList> header_list)
: m_header_list(header_list)
{
}
@ -26,16 +26,16 @@ void Request::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_header_list);
visitor.visit(m_client);
m_body.visit(
[&](JS::NonnullGCPtr<Body>& body) { visitor.visit(body); },
[&](GC::Ref<Body>& body) { visitor.visit(body); },
[](auto&) {});
visitor.visit(m_reserved_client);
m_window.visit(
[&](JS::GCPtr<HTML::EnvironmentSettingsObject> const& value) { visitor.visit(value); },
[&](GC::Ptr<HTML::EnvironmentSettingsObject> const& value) { visitor.visit(value); },
[](auto const&) {});
visitor.visit(m_pending_responses);
}
JS::NonnullGCPtr<Request> Request::create(JS::VM& vm)
GC::Ref<Request> Request::create(JS::VM& vm)
{
return vm.heap().allocate<Request>(HeaderList::create(vm));
}
@ -205,7 +205,7 @@ ByteBuffer Request::byte_serialize_origin() const
}
// https://fetch.spec.whatwg.org/#concept-request-clone
JS::NonnullGCPtr<Request> Request::clone(JS::Realm& realm) const
GC::Ref<Request> Request::clone(JS::Realm& realm) const
{
// To clone a request request, run these steps:
auto& vm = realm.vm();
@ -253,7 +253,7 @@ JS::NonnullGCPtr<Request> Request::clone(JS::Realm& realm) const
new_request->set_buffer_policy(m_buffer_policy);
// 2. If requests body is non-null, set newRequests body to the result of cloning requests body.
if (auto const* body = m_body.get_pointer<JS::NonnullGCPtr<Body>>())
if (auto const* body = m_body.get_pointer<GC::Ref<Body>>())
new_request->set_body((*body)->clone(realm));
// 3. Return newRequest.

View file

@ -14,9 +14,9 @@
#include <AK/String.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <LibGC/Ptr.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibURL/Origin.h>
#include <LibURL/URL.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
@ -28,8 +28,8 @@ namespace Web::Fetch::Infrastructure {
// https://fetch.spec.whatwg.org/#concept-request
class Request final : public JS::Cell {
JS_CELL(Request, JS::Cell);
JS_DECLARE_ALLOCATOR(Request);
GC_CELL(Request, JS::Cell);
GC_DECLARE_ALLOCATOR(Request);
public:
enum class CacheMode {
@ -169,14 +169,14 @@ public:
// Members are implementation-defined
struct InternalPriority { };
using BodyType = Variant<Empty, ByteBuffer, JS::NonnullGCPtr<Body>>;
using BodyType = Variant<Empty, ByteBuffer, GC::Ref<Body>>;
using OriginType = Variant<Origin, URL::Origin>;
using PolicyContainerType = Variant<PolicyContainer, HTML::PolicyContainer>;
using ReferrerType = Variant<Referrer, URL::URL>;
using ReservedClientType = JS::GCPtr<HTML::Environment>;
using WindowType = Variant<Window, JS::GCPtr<HTML::EnvironmentSettingsObject>>;
using ReservedClientType = GC::Ptr<HTML::Environment>;
using WindowType = Variant<Window, GC::Ptr<HTML::EnvironmentSettingsObject>>;
[[nodiscard]] static JS::NonnullGCPtr<Request> create(JS::VM&);
[[nodiscard]] static GC::Ref<Request> create(JS::VM&);
[[nodiscard]] ReadonlyBytes method() const { return m_method; }
void set_method(ByteBuffer method) { m_method = move(method); }
@ -184,8 +184,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]] 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]] GC::Ref<HeaderList> header_list() const { return m_header_list; }
void set_header_list(GC::Ref<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; }
@ -194,8 +194,8 @@ public:
[[nodiscard]] BodyType& body() { return m_body; }
void set_body(BodyType body) { m_body = move(body); }
[[nodiscard]] JS::GCPtr<HTML::EnvironmentSettingsObject const> client() const { return m_client; }
[[nodiscard]] JS::GCPtr<HTML::EnvironmentSettingsObject> client() { return m_client; }
[[nodiscard]] GC::Ptr<HTML::EnvironmentSettingsObject const> client() const { return m_client; }
[[nodiscard]] GC::Ptr<HTML::EnvironmentSettingsObject> client() { return m_client; }
void set_client(HTML::EnvironmentSettingsObject* client) { m_client = client; }
[[nodiscard]] ReservedClientType const& reserved_client() const { return m_reserved_client; }
@ -313,7 +313,7 @@ public:
[[nodiscard]] String serialize_origin() const;
[[nodiscard]] ByteBuffer byte_serialize_origin() const;
[[nodiscard]] JS::NonnullGCPtr<Request> clone(JS::Realm&) const;
[[nodiscard]] GC::Ref<Request> clone(JS::Realm&) const;
void add_range_header(u64 first, Optional<u64> const& last);
void add_origin_header();
@ -321,13 +321,13 @@ public:
[[nodiscard]] bool cross_origin_embedder_policy_allows_credentials() const;
// Non-standard
void add_pending_response(Badge<Fetching::PendingResponse>, JS::NonnullGCPtr<Fetching::PendingResponse> pending_response)
void add_pending_response(Badge<Fetching::PendingResponse>, GC::Ref<Fetching::PendingResponse> pending_response)
{
VERIFY(!m_pending_responses.contains_slow(pending_response));
m_pending_responses.append(pending_response);
}
void remove_pending_response(Badge<Fetching::PendingResponse>, JS::NonnullGCPtr<Fetching::PendingResponse> pending_response)
void remove_pending_response(Badge<Fetching::PendingResponse>, GC::Ref<Fetching::PendingResponse> pending_response)
{
m_pending_responses.remove_first_matching([&](auto gc_ptr) { return gc_ptr == pending_response; });
}
@ -336,7 +336,7 @@ public:
void set_buffer_policy(BufferPolicy buffer_policy) { m_buffer_policy = buffer_policy; }
private:
explicit Request(JS::NonnullGCPtr<HeaderList>);
explicit Request(GC::Ref<HeaderList>);
virtual void visit_edges(JS::Cell::Visitor&) override;
@ -350,7 +350,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.
JS::NonnullGCPtr<HeaderList> m_header_list;
GC::Ref<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.
@ -362,7 +362,7 @@ private:
// https://fetch.spec.whatwg.org/#concept-request-client
// A request has an associated client (null or an environment settings object).
JS::GCPtr<HTML::EnvironmentSettingsObject> m_client;
GC::Ptr<HTML::EnvironmentSettingsObject> m_client;
// https://fetch.spec.whatwg.org/#concept-request-reserved-client
// A request has an associated reserved client (null, an environment, or an environment settings object). Unless
@ -524,7 +524,7 @@ private:
bool m_timing_allow_failed { false };
// Non-standard
Vector<JS::NonnullGCPtr<Fetching::PendingResponse>> m_pending_responses;
Vector<GC::Ref<Fetching::PendingResponse>> m_pending_responses;
BufferPolicy m_buffer_policy { BufferPolicy::BufferResponse };
};

View file

@ -6,7 +6,7 @@
#include <AK/Debug.h>
#include <AK/TypeCasts.h>
#include <LibJS/Heap/Heap.h>
#include <LibGC/Heap.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/MainThreadVM.h>
@ -17,13 +17,13 @@
namespace Web::Fetch::Infrastructure {
JS_DEFINE_ALLOCATOR(Response);
JS_DEFINE_ALLOCATOR(BasicFilteredResponse);
JS_DEFINE_ALLOCATOR(CORSFilteredResponse);
JS_DEFINE_ALLOCATOR(OpaqueFilteredResponse);
JS_DEFINE_ALLOCATOR(OpaqueRedirectFilteredResponse);
GC_DEFINE_ALLOCATOR(Response);
GC_DEFINE_ALLOCATOR(BasicFilteredResponse);
GC_DEFINE_ALLOCATOR(CORSFilteredResponse);
GC_DEFINE_ALLOCATOR(OpaqueFilteredResponse);
GC_DEFINE_ALLOCATOR(OpaqueRedirectFilteredResponse);
Response::Response(JS::NonnullGCPtr<HeaderList> header_list)
Response::Response(GC::Ref<HeaderList> header_list)
: m_header_list(header_list)
, m_response_time(UnixDateTime::now())
{
@ -36,7 +36,7 @@ void Response::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_body);
}
JS::NonnullGCPtr<Response> Response::create(JS::VM& vm)
GC::Ref<Response> Response::create(JS::VM& vm)
{
return vm.heap().allocate<Response>(HeaderList::create(vm));
}
@ -45,14 +45,14 @@ JS::NonnullGCPtr<Response> Response::create(JS::VM& vm)
// 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.
JS::NonnullGCPtr<Response> Response::aborted_network_error(JS::VM& vm)
GC::Ref<Response> Response::aborted_network_error(JS::VM& vm)
{
auto response = network_error(vm, "Fetch has been aborted"sv);
response->set_aborted(true);
return response;
}
JS::NonnullGCPtr<Response> Response::network_error(JS::VM& vm, Variant<String, StringView> message)
GC::Ref<Response> Response::network_error(JS::VM& vm, Variant<String, StringView> message)
{
dbgln_if(WEB_FETCH_DEBUG, "Fetch: Creating network error response with message: {}", message.visit([](auto const& s) -> StringView { return s; }));
auto response = Response::create(vm);
@ -64,7 +64,7 @@ JS::NonnullGCPtr<Response> Response::network_error(JS::VM& vm, Variant<String, S
}
// https://fetch.spec.whatwg.org/#appropriate-network-error
JS::NonnullGCPtr<Response> Response::appropriate_network_error(JS::VM& vm, FetchParams const& fetch_params)
GC::Ref<Response> Response::appropriate_network_error(JS::VM& vm, FetchParams const& fetch_params)
{
// 1. Assert: fetchParams is canceled.
VERIFY(fetch_params.is_canceled());
@ -147,7 +147,7 @@ ErrorOr<Optional<URL::URL>> Response::location_url(Optional<String> const& reque
}
// https://fetch.spec.whatwg.org/#concept-response-clone
JS::NonnullGCPtr<Response> Response::clone(JS::Realm& realm) const
GC::Ref<Response> Response::clone(JS::Realm& realm) const
{
// To clone a response response, run these steps:
auto& vm = realm.vm();
@ -192,7 +192,7 @@ JS::NonnullGCPtr<Response> Response::clone(JS::Realm& realm) const
}
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#unsafe-response
JS::NonnullGCPtr<Response> Response::unsafe_response()
GC::Ref<Response> Response::unsafe_response()
{
// A response's unsafe response is its internal response if it has one, and the response itself otherwise.
if (is<FilteredResponse>(this))
@ -334,7 +334,7 @@ Optional<StringView> Response::network_error_message() const
return m_network_error_message->visit([](auto const& s) -> StringView { return s; });
}
FilteredResponse::FilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
FilteredResponse::FilteredResponse(GC::Ref<Response> internal_response, GC::Ref<HeaderList> header_list)
: Response(header_list)
, m_internal_response(internal_response)
{
@ -350,7 +350,7 @@ void FilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_internal_response);
}
JS::NonnullGCPtr<BasicFilteredResponse> BasicFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> internal_response)
GC::Ref<BasicFilteredResponse> BasicFilteredResponse::create(JS::VM& vm, GC::Ref<Response> internal_response)
{
// A basic filtered response is a filtered response whose type is "basic" and header list excludes
// any headers in internal responses header list whose name is a forbidden response-header name.
@ -363,7 +363,7 @@ JS::NonnullGCPtr<BasicFilteredResponse> BasicFilteredResponse::create(JS::VM& vm
return vm.heap().allocate<BasicFilteredResponse>(internal_response, header_list);
}
BasicFilteredResponse::BasicFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
BasicFilteredResponse::BasicFilteredResponse(GC::Ref<Response> internal_response, GC::Ref<HeaderList> header_list)
: FilteredResponse(internal_response, header_list)
, m_header_list(header_list)
{
@ -375,7 +375,7 @@ void BasicFilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_header_list);
}
JS::NonnullGCPtr<CORSFilteredResponse> CORSFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> internal_response)
GC::Ref<CORSFilteredResponse> CORSFilteredResponse::create(JS::VM& vm, GC::Ref<Response> internal_response)
{
// A CORS filtered response is a filtered response whose type is "cors" and header list excludes
// any headers in internal responses header list whose name is not a CORS-safelisted response-header
@ -393,7 +393,7 @@ JS::NonnullGCPtr<CORSFilteredResponse> CORSFilteredResponse::create(JS::VM& vm,
return vm.heap().allocate<CORSFilteredResponse>(internal_response, header_list);
}
CORSFilteredResponse::CORSFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
CORSFilteredResponse::CORSFilteredResponse(GC::Ref<Response> internal_response, GC::Ref<HeaderList> header_list)
: FilteredResponse(internal_response, header_list)
, m_header_list(header_list)
{
@ -405,14 +405,14 @@ void CORSFilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_header_list);
}
JS::NonnullGCPtr<OpaqueFilteredResponse> OpaqueFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> internal_response)
GC::Ref<OpaqueFilteredResponse> OpaqueFilteredResponse::create(JS::VM& vm, GC::Ref<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<OpaqueFilteredResponse>(internal_response, HeaderList::create(vm));
}
OpaqueFilteredResponse::OpaqueFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
OpaqueFilteredResponse::OpaqueFilteredResponse(GC::Ref<Response> internal_response, GC::Ref<HeaderList> header_list)
: FilteredResponse(internal_response, header_list)
, m_header_list(header_list)
{
@ -425,14 +425,14 @@ void OpaqueFilteredResponse::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_body);
}
JS::NonnullGCPtr<OpaqueRedirectFilteredResponse> OpaqueRedirectFilteredResponse::create(JS::VM& vm, JS::NonnullGCPtr<Response> internal_response)
GC::Ref<OpaqueRedirectFilteredResponse> OpaqueRedirectFilteredResponse::create(JS::VM& vm, GC::Ref<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 vm.heap().allocate<OpaqueRedirectFilteredResponse>(internal_response, HeaderList::create(vm));
}
OpaqueRedirectFilteredResponse::OpaqueRedirectFilteredResponse(JS::NonnullGCPtr<Response> internal_response, JS::NonnullGCPtr<HeaderList> header_list)
OpaqueRedirectFilteredResponse::OpaqueRedirectFilteredResponse(GC::Ref<Response> internal_response, GC::Ref<HeaderList> header_list)
: FilteredResponse(internal_response, header_list)
, m_header_list(header_list)
{

View file

@ -12,9 +12,9 @@
#include <AK/Optional.h>
#include <AK/Time.h>
#include <AK/Vector.h>
#include <LibGC/Ptr.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibURL/URL.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
@ -24,8 +24,8 @@ namespace Web::Fetch::Infrastructure {
// https://fetch.spec.whatwg.org/#concept-response
class Response : public JS::Cell {
JS_CELL(Response, JS::Cell);
JS_DECLARE_ALLOCATOR(Response);
GC_CELL(Response, JS::Cell);
GC_DECLARE_ALLOCATOR(Response);
public:
enum class CacheState {
@ -56,10 +56,10 @@ public:
bool operator==(BodyInfo const&) const = default;
};
[[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&, Variant<String, StringView> message);
[[nodiscard]] static JS::NonnullGCPtr<Response> appropriate_network_error(JS::VM&, FetchParams const&);
[[nodiscard]] static GC::Ref<Response> create(JS::VM&);
[[nodiscard]] static GC::Ref<Response> aborted_network_error(JS::VM&);
[[nodiscard]] static GC::Ref<Response> network_error(JS::VM&, Variant<String, StringView> message);
[[nodiscard]] static GC::Ref<Response> appropriate_network_error(JS::VM&, FetchParams const&);
virtual ~Response() = default;
@ -79,12 +79,12 @@ 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 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 GC::Ref<HeaderList> header_list() const { return m_header_list; }
void set_header_list(GC::Ref<HeaderList> header_list) { m_header_list = header_list; }
[[nodiscard]] virtual JS::GCPtr<Body> const& body() const { return m_body; }
[[nodiscard]] virtual JS::GCPtr<Body>& body() { return m_body; }
void set_body(JS::GCPtr<Body> body) { m_body = move(body); }
[[nodiscard]] virtual GC::Ptr<Body> const& body() const { return m_body; }
[[nodiscard]] virtual GC::Ptr<Body>& body() { return m_body; }
void set_body(GC::Ptr<Body> body) { m_body = move(body); }
[[nodiscard]] virtual Optional<CacheState> const& cache_state() const { return m_cache_state; }
void set_cache_state(Optional<CacheState> cache_state) { m_cache_state = move(cache_state); }
@ -113,9 +113,9 @@ public:
[[nodiscard]] Optional<URL::URL const&> url() const;
[[nodiscard]] ErrorOr<Optional<URL::URL>> location_url(Optional<String> const& request_fragment) const;
[[nodiscard]] JS::NonnullGCPtr<Response> clone(JS::Realm&) const;
[[nodiscard]] GC::Ref<Response> clone(JS::Realm&) const;
[[nodiscard]] JS::NonnullGCPtr<Response> unsafe_response();
[[nodiscard]] GC::Ref<Response> unsafe_response();
[[nodiscard]] bool is_cors_cross_origin() const;
@ -127,7 +127,7 @@ public:
[[nodiscard]] Optional<StringView> network_error_message() const;
protected:
explicit Response(JS::NonnullGCPtr<HeaderList>);
explicit Response(GC::Ref<HeaderList>);
virtual void visit_edges(JS::Cell::Visitor&) override;
@ -154,11 +154,11 @@ 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.
JS::NonnullGCPtr<HeaderList> m_header_list;
GC::Ref<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.
JS::GCPtr<Body> m_body;
GC::Ptr<Body> m_body;
// https://fetch.spec.whatwg.org/#concept-response-cache-state
// A response has an associated cache state (the empty string, "local", or "validated"). Unless stated otherwise, it is the empty string.
@ -209,10 +209,10 @@ public:
// https://fetch.spec.whatwg.org/#concept-filtered-response
class FilteredResponse : public Response {
JS_CELL(FilteredResponse, Response);
GC_CELL(FilteredResponse, Response);
public:
FilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
FilteredResponse(GC::Ref<Response>, GC::Ref<HeaderList>);
virtual ~FilteredResponse() = 0;
[[nodiscard]] virtual Type type() const override { return m_internal_response->type(); }
@ -221,9 +221,9 @@ public:
[[nodiscard]] virtual Vector<URL::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 JS::NonnullGCPtr<HeaderList> header_list() const override { return m_internal_response->header_list(); }
[[nodiscard]] virtual JS::GCPtr<Body> const& body() const override { return m_internal_response->body(); }
[[nodiscard]] virtual JS::GCPtr<Body>& body() override { return m_internal_response->body(); }
[[nodiscard]] virtual GC::Ref<HeaderList> header_list() const override { return m_internal_response->header_list(); }
[[nodiscard]] virtual GC::Ptr<Body> const& body() const override { return m_internal_response->body(); }
[[nodiscard]] virtual GC::Ptr<Body>& body() override { return m_internal_response->body(); }
[[nodiscard]] virtual Optional<CacheState> const& cache_state() const override { return m_internal_response->cache_state(); }
[[nodiscard]] virtual Vector<ByteBuffer> const& cors_exposed_header_name_list() const override { return m_internal_response->cors_exposed_header_name_list(); }
[[nodiscard]] virtual bool range_requested() const override { return m_internal_response->range_requested(); }
@ -231,102 +231,102 @@ 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]] JS::NonnullGCPtr<Response> internal_response() const { return m_internal_response; }
[[nodiscard]] GC::Ref<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
JS::NonnullGCPtr<Response> m_internal_response;
GC::Ref<Response> m_internal_response;
};
// https://fetch.spec.whatwg.org/#concept-filtered-response-basic
class BasicFilteredResponse final : public FilteredResponse {
JS_CELL(BasicFilteredResponse, FilteredResponse);
JS_DECLARE_ALLOCATOR(BasicFilteredResponse);
GC_CELL(BasicFilteredResponse, FilteredResponse);
GC_DECLARE_ALLOCATOR(BasicFilteredResponse);
public:
[[nodiscard]] static JS::NonnullGCPtr<BasicFilteredResponse> create(JS::VM&, JS::NonnullGCPtr<Response>);
[[nodiscard]] static GC::Ref<BasicFilteredResponse> create(JS::VM&, GC::Ref<Response>);
[[nodiscard]] virtual Type type() const override { return Type::Basic; }
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
[[nodiscard]] virtual GC::Ref<HeaderList> header_list() const override { return m_header_list; }
private:
BasicFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
BasicFilteredResponse(GC::Ref<Response>, GC::Ref<HeaderList>);
virtual void visit_edges(JS::Cell::Visitor&) override;
JS::NonnullGCPtr<HeaderList> m_header_list;
GC::Ref<HeaderList> m_header_list;
};
// https://fetch.spec.whatwg.org/#concept-filtered-response-cors
class CORSFilteredResponse final : public FilteredResponse {
JS_CELL(CORSFilteredResponse, FilteredResponse);
JS_DECLARE_ALLOCATOR(CORSFilteredResponse);
GC_CELL(CORSFilteredResponse, FilteredResponse);
GC_DECLARE_ALLOCATOR(CORSFilteredResponse);
public:
[[nodiscard]] static JS::NonnullGCPtr<CORSFilteredResponse> create(JS::VM&, JS::NonnullGCPtr<Response>);
[[nodiscard]] static GC::Ref<CORSFilteredResponse> create(JS::VM&, GC::Ref<Response>);
[[nodiscard]] virtual Type type() const override { return Type::CORS; }
[[nodiscard]] virtual JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
[[nodiscard]] virtual GC::Ref<HeaderList> header_list() const override { return m_header_list; }
private:
CORSFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
CORSFilteredResponse(GC::Ref<Response>, GC::Ref<HeaderList>);
virtual void visit_edges(JS::Cell::Visitor&) override;
JS::NonnullGCPtr<HeaderList> m_header_list;
GC::Ref<HeaderList> m_header_list;
};
// https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
class OpaqueFilteredResponse final : public FilteredResponse {
JS_CELL(OpaqueFilteredResponse, FilteredResponse);
JS_DECLARE_ALLOCATOR(OpaqueFilteredResponse);
GC_CELL(OpaqueFilteredResponse, FilteredResponse);
GC_DECLARE_ALLOCATOR(OpaqueFilteredResponse);
public:
[[nodiscard]] static JS::NonnullGCPtr<OpaqueFilteredResponse> create(JS::VM&, JS::NonnullGCPtr<Response>);
[[nodiscard]] static GC::Ref<OpaqueFilteredResponse> create(JS::VM&, GC::Ref<Response>);
[[nodiscard]] virtual Type type() const override { return Type::Opaque; }
[[nodiscard]] virtual Vector<URL::URL> const& url_list() const override { return m_url_list; }
[[nodiscard]] virtual Vector<URL::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 JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
[[nodiscard]] virtual JS::GCPtr<Body> const& body() const override { return m_body; }
[[nodiscard]] virtual JS::GCPtr<Body>& body() override { return m_body; }
[[nodiscard]] virtual GC::Ref<HeaderList> header_list() const override { return m_header_list; }
[[nodiscard]] virtual GC::Ptr<Body> const& body() const override { return m_body; }
[[nodiscard]] virtual GC::Ptr<Body>& body() override { return m_body; }
private:
OpaqueFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
OpaqueFilteredResponse(GC::Ref<Response>, GC::Ref<HeaderList>);
virtual void visit_edges(JS::Cell::Visitor&) override;
Vector<URL::URL> m_url_list;
JS::NonnullGCPtr<HeaderList> m_header_list;
JS::GCPtr<Body> m_body;
GC::Ref<HeaderList> m_header_list;
GC::Ptr<Body> m_body;
};
// https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect
class OpaqueRedirectFilteredResponse final : public FilteredResponse {
JS_CELL(OpaqueRedirectFilteredResponse, FilteredResponse);
JS_DECLARE_ALLOCATOR(OpaqueRedirectFilteredResponse);
GC_CELL(OpaqueRedirectFilteredResponse, FilteredResponse);
GC_DECLARE_ALLOCATOR(OpaqueRedirectFilteredResponse);
public:
[[nodiscard]] static JS::NonnullGCPtr<OpaqueRedirectFilteredResponse> create(JS::VM&, JS::NonnullGCPtr<Response>);
[[nodiscard]] static GC::Ref<OpaqueRedirectFilteredResponse> create(JS::VM&, GC::Ref<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 JS::NonnullGCPtr<HeaderList> header_list() const override { return m_header_list; }
[[nodiscard]] virtual JS::GCPtr<Body> const& body() const override { return m_body; }
[[nodiscard]] virtual JS::GCPtr<Body>& body() override { return m_body; }
[[nodiscard]] virtual GC::Ref<HeaderList> header_list() const override { return m_header_list; }
[[nodiscard]] virtual GC::Ptr<Body> const& body() const override { return m_body; }
[[nodiscard]] virtual GC::Ptr<Body>& body() override { return m_body; }
private:
OpaqueRedirectFilteredResponse(JS::NonnullGCPtr<Response>, JS::NonnullGCPtr<HeaderList>);
OpaqueRedirectFilteredResponse(GC::Ref<Response>, GC::Ref<HeaderList>);
virtual void visit_edges(JS::Cell::Visitor&) override;
JS::NonnullGCPtr<HeaderList> m_header_list;
JS::GCPtr<Body> m_body;
GC::Ref<HeaderList> m_header_list;
GC::Ptr<Body> m_body;
};
}