From 4ca330adef5be210b2dd5485e0ee70f9a6ae7224 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 27 Feb 2025 15:41:15 +0100 Subject: [PATCH] LibWeb: Don't take rendering task from queue while running rendering If event loop is already executing rendering task, we should not start the next rendering task until the current one is finished. Fixes https://github.com/LadybirdBrowser/ladybird/issues/3717 --- Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp | 8 ++++---- Libraries/LibWeb/HTML/EventLoop/EventLoop.h | 4 +++- Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index d70b8acfad4..a9ecd1c1087 100644 --- a/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -312,10 +312,10 @@ void EventLoop::process_input_events() const // https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering void EventLoop::update_the_rendering() { - VERIFY(!m_is_running_rendering_task); - m_is_running_rendering_task = true; + VERIFY(!m_running_rendering_task); + m_running_rendering_task = true; ScopeGuard const guard = [this] { - m_is_running_rendering_task = false; + m_running_rendering_task = false; }; process_input_events(); @@ -729,7 +729,7 @@ EventLoop::PauseHandle EventLoop::pause() auto time_before_pause = HighResolutionTime::current_high_resolution_time(global); // 3. If necessary, update the rendering or user interface of any Document or navigable to reflect the current state. - if (!m_is_running_rendering_task) + if (!m_running_rendering_task) update_the_rendering(); // 4. Wait until the condition goal is met. While a user agent has a paused task, the corresponding event loop must diff --git a/Libraries/LibWeb/HTML/EventLoop/EventLoop.h b/Libraries/LibWeb/HTML/EventLoop/EventLoop.h index 69809734804..edc16bfacea 100644 --- a/Libraries/LibWeb/HTML/EventLoop/EventLoop.h +++ b/Libraries/LibWeb/HTML/EventLoop/EventLoop.h @@ -90,6 +90,8 @@ public: void unpause(Badge, JS::Object const& global, HighResolutionTime::DOMHighResTimeStamp); bool execution_paused() const { return m_execution_paused; } + bool running_rendering_task() const { return m_running_rendering_task; } + private: explicit EventLoop(Type); @@ -133,7 +135,7 @@ private: bool m_skip_event_loop_processing_steps { false }; - bool m_is_running_rendering_task { false }; + bool m_running_rendering_task { false }; GC::Ptr> m_rendering_task_function; }; diff --git a/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp b/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp index c811305a9c7..fb093b9d3aa 100644 --- a/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp +++ b/Libraries/LibWeb/HTML/EventLoop/TaskQueue.cpp @@ -38,6 +38,8 @@ GC::Ptr TaskQueue::take_first_runnable() return nullptr; for (size_t i = 0; i < m_tasks.size(); ++i) { + if (m_event_loop->running_rendering_task() && m_tasks[i]->source() == Task::Source::Rendering) + continue; if (m_tasks[i]->is_runnable()) return m_tasks.take(i); } @@ -50,6 +52,8 @@ bool TaskQueue::has_runnable_tasks() const return false; for (auto& task : m_tasks) { + if (m_event_loop->running_rendering_task() && task->source() == Task::Source::Rendering) + continue; if (task->is_runnable()) return true; }