mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:37: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
|
@ -20,9 +20,9 @@
|
|||
|
||||
namespace Web::Fetch {
|
||||
|
||||
Request::Request(JS::Realm& realm, NonnullRefPtr<Infrastructure::Request> request)
|
||||
Request::Request(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Request> 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<Infrastructure::Body&> Request::body_impl()
|
|||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#request-create
|
||||
JS::NonnullGCPtr<Request> Request::create(NonnullRefPtr<Infrastructure::Request> request, Headers::Guard guard, JS::Realm& realm)
|
||||
JS::NonnullGCPtr<Request> Request::create(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Request> 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<Request>(realm, realm, move(request));
|
||||
auto* request_object = realm.heap().allocate<Request>(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<Headers>(realm, realm);
|
||||
request_object->m_headers->set_header_list(move(request_reader_list));
|
||||
request_object->m_headers = realm.heap().allocate<Headers>(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> Request::create(NonnullRefPtr<Infrastructure::Request>
|
|||
// https://fetch.spec.whatwg.org/#dom-request
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> 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<Request>(realm, realm, Infrastructure::Request::create()) };
|
||||
auto request_object = JS::NonnullGCPtr { *realm.heap().allocate<Request>(realm, realm, Infrastructure::Request::create(vm)) };
|
||||
|
||||
// 1. Let request be null.
|
||||
RefPtr<Infrastructure::Request> input_request;
|
||||
JS::GCPtr<Infrastructure::Request> input_request;
|
||||
|
||||
// 2. Let fallbackMode be null.
|
||||
Optional<Infrastructure::Request::Mode> fallback_mode;
|
||||
|
@ -125,7 +124,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> 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<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm
|
|||
|
||||
// header list
|
||||
// A copy of request’s header list.
|
||||
auto header_list_copy = make_ref_counted<Infrastructure::HeaderList>();
|
||||
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<JS::NonnullGCPtr<Request>> 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<Headers>(realm, realm);
|
||||
request_object->m_headers->set_header_list(request->header_list());
|
||||
request_object->m_headers = realm.heap().allocate<Headers>(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<JS::NonnullGCPtr<Request>> 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<HeadersInit, NonnullRefPtr<Infrastructure::HeaderList>> { request_object->headers()->header_list() };
|
||||
auto headers = Variant<HeadersInit, JS::NonnullGCPtr<Infrastructure::HeaderList>> { 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<JS::NonnullGCPtr<Request>> 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<NonnullRefPtr<Infrastructure::HeaderList>>()) {
|
||||
auto& header_list = *headers.get<NonnullRefPtr<Infrastructure::HeaderList>>();
|
||||
for (auto& header : header_list)
|
||||
if (auto* header_list = headers.get_pointer<JS::NonnullGCPtr<Infrastructure::HeaderList>>()) {
|
||||
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<JS::NonnullGCPtr<Request>> 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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue