LibWeb+Browser+Ladybird: Use JS::SafeFunction for EventLoop callbacks

This automatically protects captured objects from being GC'd before the
callback runs.
This commit is contained in:
Sam Atkins 2023-04-21 12:13:04 +01:00 committed by Linus Groh
parent 892470a912
commit 6d93e03211
Notes: sideshowbarker 2024-07-17 02:57:43 +09:00
11 changed files with 19 additions and 19 deletions

View file

@ -18,13 +18,13 @@ namespace Ladybird {
EventLoopPluginQt::EventLoopPluginQt() = default;
EventLoopPluginQt::~EventLoopPluginQt() = default;
void EventLoopPluginQt::spin_until(Function<bool()> goal_condition)
void EventLoopPluginQt::spin_until(JS::SafeFunction<bool()> goal_condition)
{
while (!goal_condition())
QCoreApplication::processEvents(QEventLoop::ProcessEventsFlag::AllEvents | QEventLoop::ProcessEventsFlag::WaitForMoreEvents);
}
void EventLoopPluginQt::deferred_invoke(Function<void()> function)
void EventLoopPluginQt::deferred_invoke(JS::SafeFunction<void()> function)
{
VERIFY(function);
QTimer::singleShot(0, [function = move(function)] {

View file

@ -15,8 +15,8 @@ public:
EventLoopPluginQt();
virtual ~EventLoopPluginQt() override;
virtual void spin_until(Function<bool()> goal_condition) override;
virtual void deferred_invoke(Function<void()>) override;
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) override;
virtual void deferred_invoke(JS::SafeFunction<void()>) override;
virtual NonnullRefPtr<Web::Platform::Timer> create_timer() override;
virtual void quit() override;
};

View file

@ -35,7 +35,7 @@ public:
struct CustomData {
virtual ~CustomData() = default;
virtual void spin_event_loop_until(Function<bool()> goal_condition) = 0;
virtual void spin_event_loop_until(JS::SafeFunction<bool()> goal_condition) = 0;
};
static ErrorOr<NonnullRefPtr<VM>> create(OwnPtr<CustomData> = {});

View file

@ -499,7 +499,7 @@ NonnullOwnPtr<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM& vm, Fu
return realm_execution_context;
}
void WebEngineCustomData::spin_event_loop_until(Function<bool()> goal_condition)
void WebEngineCustomData::spin_event_loop_until(JS::SafeFunction<bool()> goal_condition)
{
Platform::EventLoopPlugin::the().spin_until(move(goal_condition));
}

View file

@ -38,7 +38,7 @@ struct CustomElementReactionsStack {
struct WebEngineCustomData final : public JS::VM::CustomData {
virtual ~WebEngineCustomData() override = default;
virtual void spin_event_loop_until(Function<bool()> goal_condition) override;
virtual void spin_event_loop_until(JS::SafeFunction<bool()> goal_condition) override;
HTML::EventLoop event_loop;

View file

@ -56,9 +56,9 @@ void PendingResponse::run_callback()
{
VERIFY(m_callback);
VERIFY(m_response);
Platform::EventLoopPlugin::the().deferred_invoke([strong_this = JS::make_handle(*this)] {
strong_this->m_callback(*strong_this->m_response);
strong_this->m_request->remove_pending_response({}, *strong_this.ptr());
Platform::EventLoopPlugin::the().deferred_invoke([this] {
m_callback(*m_response);
m_request->remove_pending_response({}, *this);
});
}

View file

@ -51,7 +51,7 @@ EventLoop& main_thread_event_loop()
}
// https://html.spec.whatwg.org/multipage/webappapis.html#spin-the-event-loop
void EventLoop::spin_until(Function<bool()> goal_condition)
void EventLoop::spin_until(JS::SafeFunction<bool()> goal_condition)
{
// FIXME: 1. Let task be the event loop's currently running task.

View file

@ -37,7 +37,7 @@ public:
TaskQueue& microtask_queue() { return m_microtask_queue; }
TaskQueue const& microtask_queue() const { return m_microtask_queue; }
void spin_until(Function<bool()> goal_condition);
void spin_until(JS::SafeFunction<bool()> goal_condition);
void process();
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#termination-nesting-level

View file

@ -7,6 +7,7 @@
#pragma once
#include <AK/Forward.h>
#include <LibJS/SafeFunction.h>
#include <LibWeb/Forward.h>
namespace Web::Platform {
@ -18,8 +19,8 @@ public:
virtual ~EventLoopPlugin();
virtual void spin_until(Function<bool()> goal_condition) = 0;
virtual void deferred_invoke(Function<void()>) = 0;
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) = 0;
virtual void deferred_invoke(JS::SafeFunction<void()>) = 0;
virtual NonnullRefPtr<Timer> create_timer() = 0;
virtual void quit() = 0;
};

View file

@ -5,7 +5,6 @@
*/
#include "EventLoopPluginSerenity.h"
#include <AK/Function.h>
#include <AK/NonnullRefPtr.h>
#include <LibCore/EventLoop.h>
#include <LibWeb/Platform/TimerSerenity.h>
@ -15,12 +14,12 @@ namespace Web::Platform {
EventLoopPluginSerenity::EventLoopPluginSerenity() = default;
EventLoopPluginSerenity::~EventLoopPluginSerenity() = default;
void EventLoopPluginSerenity::spin_until(Function<bool()> goal_condition)
void EventLoopPluginSerenity::spin_until(JS::SafeFunction<bool()> goal_condition)
{
Core::EventLoop::current().spin_until(move(goal_condition));
}
void EventLoopPluginSerenity::deferred_invoke(Function<void()> function)
void EventLoopPluginSerenity::deferred_invoke(JS::SafeFunction<void()> function)
{
VERIFY(function);
Core::deferred_invoke(move(function));

View file

@ -15,8 +15,8 @@ public:
EventLoopPluginSerenity();
virtual ~EventLoopPluginSerenity() override;
virtual void spin_until(Function<bool()> goal_condition) override;
virtual void deferred_invoke(Function<void()>) override;
virtual void spin_until(JS::SafeFunction<bool()> goal_condition) override;
virtual void deferred_invoke(JS::SafeFunction<void()>) override;
virtual NonnullRefPtr<Timer> create_timer() override;
virtual void quit() override;
};