1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:58:11 +00:00

LibWeb: Register PendingResponse with a Request to keep it alive

This was an oversight from when I converted PendingResponse and various
other classes from being ref-counted to GC-allocated last minute - no
one takes care to keep all of them alive. Some are on the stack, and
some might be captured in another PendingResponse's JS::SafeFunction,
but ultimately, we need a better solution.
Since a PendingResponse is *always* the result of someone having created
a Request, let's just let that keep a list of each PendingResponse that
has been created for it, and visit them until they are resolved. After
that, they can be GC'd with no complaints.
This commit is contained in:
Linus Groh 2022-11-01 19:35:38 +00:00
parent 948bd50197
commit 216f68c566
5 changed files with 65 additions and 42 deletions

View file

@ -7,28 +7,32 @@
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Fetch/Fetching/PendingResponse.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
namespace Web::Fetch::Fetching {
JS::NonnullGCPtr<PendingResponse> PendingResponse::create(JS::VM& vm)
JS::NonnullGCPtr<PendingResponse> PendingResponse::create(JS::VM& vm, JS::NonnullGCPtr<Infrastructure::Request> request)
{
return { *vm.heap().allocate_without_realm<PendingResponse>() };
return { *vm.heap().allocate_without_realm<PendingResponse>(request) };
}
JS::NonnullGCPtr<PendingResponse> PendingResponse::create(JS::VM& vm, JS::NonnullGCPtr<Infrastructure::Response> response)
JS::NonnullGCPtr<PendingResponse> PendingResponse::create(JS::VM& vm, JS::NonnullGCPtr<Infrastructure::Request> request, JS::NonnullGCPtr<Infrastructure::Response> response)
{
return { *vm.heap().allocate_without_realm<PendingResponse>(response) };
return { *vm.heap().allocate_without_realm<PendingResponse>(request, response) };
}
PendingResponse::PendingResponse(JS::NonnullGCPtr<Infrastructure::Response> response)
: m_response(response)
PendingResponse::PendingResponse(JS::NonnullGCPtr<Infrastructure::Request> request, JS::GCPtr<Infrastructure::Response> response)
: m_request(request)
, m_response(response)
{
m_request->add_pending_response({}, *this);
}
void PendingResponse::visit_edges(JS::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_request);
visitor.visit(m_response);
}
@ -52,8 +56,9 @@ void PendingResponse::run_callback() const
{
VERIFY(m_callback);
VERIFY(m_response);
Platform::EventLoopPlugin::the().deferred_invoke([strong_this = JS::make_handle(const_cast<PendingResponse&>(*this))]() {
Platform::EventLoopPlugin::the().deferred_invoke([strong_this = JS::make_handle(const_cast<PendingResponse&>(*this))]() mutable {
strong_this->m_callback(*strong_this->m_response);
strong_this->m_request->remove_pending_response({}, *strong_this.ptr());
});
}