1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:27: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:
Linus Groh 2022-10-30 01:52:07 +00:00
parent 63122d0276
commit b1968b8bed
19 changed files with 270 additions and 169 deletions

View file

@ -17,9 +17,9 @@
namespace Web::Fetch {
Response::Response(JS::Realm& realm, NonnullRefPtr<Infrastructure::Response> response)
Response::Response(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Response> 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<Infrastructure::Body&> Response::body_impl()
}
// https://fetch.spec.whatwg.org/#response-create
JS::NonnullGCPtr<Response> Response::create(NonnullRefPtr<Infrastructure::Response> response, Headers::Guard guard, JS::Realm& realm)
JS::NonnullGCPtr<Response> Response::create(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Response> 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 responseObjects response to response.
auto* response_object = realm.heap().allocate<Response>(realm, realm, move(response));
auto* response_object = realm.heap().allocate<Response>(realm, realm, response);
// 3. Set responseObjects headers to a new Headers object with realm, whose headers list is responses headers list and guard is guard.
response_object->m_headers = realm.heap().allocate<Headers>(realm, realm);
response_object->m_headers->set_header_list(move(response_reader_list));
response_object->m_headers = realm.heap().allocate<Headers>(realm, realm, response->header_list());
response_object->m_headers->set_guard(guard);
// 4. Return responseObject.
@ -126,16 +123,17 @@ WebIDL::ExceptionOr<void> Response::initialize_response(ResponseInit const& init
// https://fetch.spec.whatwg.org/#dom-response
WebIDL::ExceptionOr<JS::NonnullGCPtr<Response>> Response::construct_impl(JS::Realm& realm, Optional<BodyInit> const& body, ResponseInit const& init)
{
auto& vm = realm.vm();
// Referred to as 'this' in the spec.
auto response_object = JS::NonnullGCPtr { *realm.heap().allocate<Response>(realm, realm, Infrastructure::Response::create()) };
auto response_object = JS::NonnullGCPtr { *realm.heap().allocate<Response>(realm, realm, Infrastructure::Response::create(vm)) };
// 1. Set thiss 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 thiss headers to a new Headers object with thiss relevant Realm, whose header list is thiss responses header list and guard is "response".
response_object->m_headers = realm.heap().allocate<Headers>(realm, realm);
response_object->m_headers->set_header_list(response_object->response()->header_list());
response_object->m_headers = realm.heap().allocate<Headers>(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> 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 thiss 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<JS::NonnullGCPtr<Response>> Response::redirect(JS::VM& vm, S
// 4. Let responseObject be the result of creating a Response object, given a new response, "immutable", and thiss 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 responseObjects responses status to status.
response_object->response()->set_status(status);
@ -207,7 +205,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Response>> Response::json(JS::VM& vm, JS::V
// 3. Let responseObject be the result of creating a Response object, given a new response, "response", and thiss 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<Headers> Response::headers() const
// https://fetch.spec.whatwg.org/#dom-response-clone
WebIDL::ExceptionOr<JS::NonnullGCPtr<Response>> 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 thiss 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, thiss headerss guard, and thiss 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());
}
}