1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-10 06:27:35 +00:00

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
11 changed files with 19 additions and 19 deletions

View file

@ -18,13 +18,13 @@ namespace Ladybird {
EventLoopPluginQt::EventLoopPluginQt() = default; EventLoopPluginQt::EventLoopPluginQt() = default;
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()) while (!goal_condition())
QCoreApplication::processEvents(QEventLoop::ProcessEventsFlag::AllEvents | QEventLoop::ProcessEventsFlag::WaitForMoreEvents); 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); VERIFY(function);
QTimer::singleShot(0, [function = move(function)] { QTimer::singleShot(0, [function = move(function)] {

View file

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

View file

@ -35,7 +35,7 @@ public:
struct CustomData { struct CustomData {
virtual ~CustomData() = default; 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> = {}); 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; 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)); Platform::EventLoopPlugin::the().spin_until(move(goal_condition));
} }

View file

@ -38,7 +38,7 @@ struct CustomElementReactionsStack {
struct WebEngineCustomData final : public JS::VM::CustomData { struct WebEngineCustomData final : public JS::VM::CustomData {
virtual ~WebEngineCustomData() override = default; 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; HTML::EventLoop event_loop;

View file

@ -56,9 +56,9 @@ void PendingResponse::run_callback()
{ {
VERIFY(m_callback); VERIFY(m_callback);
VERIFY(m_response); VERIFY(m_response);
Platform::EventLoopPlugin::the().deferred_invoke([strong_this = JS::make_handle(*this)] { Platform::EventLoopPlugin::the().deferred_invoke([this] {
strong_this->m_callback(*strong_this->m_response); m_callback(*m_response);
strong_this->m_request->remove_pending_response({}, *strong_this.ptr()); 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 // 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. // 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& microtask_queue() { return m_microtask_queue; }
TaskQueue const& microtask_queue() const { 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(); void process();
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#termination-nesting-level // https://html.spec.whatwg.org/multipage/browsing-the-web.html#termination-nesting-level

View file

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

View file

@ -5,7 +5,6 @@
*/ */
#include "EventLoopPluginSerenity.h" #include "EventLoopPluginSerenity.h"
#include <AK/Function.h>
#include <AK/NonnullRefPtr.h> #include <AK/NonnullRefPtr.h>
#include <LibCore/EventLoop.h> #include <LibCore/EventLoop.h>
#include <LibWeb/Platform/TimerSerenity.h> #include <LibWeb/Platform/TimerSerenity.h>
@ -15,12 +14,12 @@ namespace Web::Platform {
EventLoopPluginSerenity::EventLoopPluginSerenity() = default; EventLoopPluginSerenity::EventLoopPluginSerenity() = default;
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)); 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); VERIFY(function);
Core::deferred_invoke(move(function)); Core::deferred_invoke(move(function));

View file

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