LibWeb: Convert Document's cursor blink timer to GC::Timer

Use GC::Timer instead of Core::Timer for the cursor blink timer so
that capturing [this] in the callback properly protects the Document
from garbage collection.
This commit is contained in:
Andreas Kling 2026-01-29 01:13:54 +01:00 committed by Andreas Kling
parent 4ba14759dc
commit e23ec1f841
4 changed files with 27 additions and 3 deletions

View file

@ -48,6 +48,25 @@ void Timer::start(u64 timeout_ms, GC::Ref<GC::Function<void()>> on_timeout)
m_timer->start();
}
void Timer::start_repeating(u64 interval_ms, GC::Ref<GC::Function<void()>> on_timeout)
{
m_on_timeout = on_timeout;
m_timer->on_timeout = [this]() {
if (m_on_timeout)
m_on_timeout->function()();
};
m_timer->set_interval(static_cast<int>(interval_ms));
m_timer->set_single_shot(false);
m_timer->start();
}
void Timer::restart()
{
m_timer->restart();
}
void Timer::stop_and_fire_timeout_handler()
{
auto on_timeout = m_on_timeout;

View file

@ -25,6 +25,8 @@ public:
virtual void finalize() override;
void start(u64 timeout_ms, GC::Ref<GC::Function<void()>> on_timeout);
void start_repeating(u64 interval_ms, GC::Ref<GC::Function<void()>> on_timeout);
void restart();
void stop_and_fire_timeout_handler();
void stop();

View file

@ -22,6 +22,7 @@
#include <AK/Utf8View.h>
#include <LibCore/Timer.h>
#include <LibGC/RootVector.h>
#include <LibGC/Timer.h>
#include <LibHTTP/Cookie/Cookie.h>
#include <LibHTTP/Cookie/ParsedCookie.h>
#include <LibJS/Console.h>
@ -544,7 +545,8 @@ Document::Document(JS::Realm& realm, URL::URL const& url, TemporaryDocumentForFr
m_is_decoded_svg = m_page->client().is_svg_page_client();
m_cursor_blink_timer = Core::Timer::create_repeating(500, [this] {
m_cursor_blink_timer = heap().allocate<GC::Timer>();
m_cursor_blink_timer->start_repeating(500, GC::create_function(heap(), [this] {
auto cursor_position = this->cursor_position();
if (!cursor_position)
return;
@ -558,7 +560,7 @@ Document::Document(JS::Realm& realm, URL::URL const& url, TemporaryDocumentForFr
m_cursor_blink_state = !m_cursor_blink_state;
node->set_needs_repaint();
}
});
}));
HTML::main_thread_event_loop().register_document({}, *this);
}
@ -747,6 +749,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_open_dialogs_list);
visitor.visit(m_dialog_pointerdown_target);
visitor.visit(m_console_client);
visitor.visit(m_cursor_blink_timer);
visitor.visit(m_editing_host_manager);
visitor.visit(m_local_storage_holder);
visitor.visit(m_session_storage_holder);

View file

@ -1477,7 +1477,7 @@ private:
GC::Ptr<JS::ConsoleClient> m_console_client;
RefPtr<Core::Timer> m_cursor_blink_timer;
GC::Ptr<GC::Timer> m_cursor_blink_timer;
bool m_cursor_blink_state { false };
// NOTE: This is GC::Weak, not GC::Ptr, on purpose. We don't want the document to keep some old detached navigable alive.