From 31698281b6ec9da6abb695625d766a9450536eed Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Wed, 3 Jul 2024 22:12:28 +1000 Subject: [PATCH] LibWeb: Stop deadlocking on unit tests Unit tests on macOS deadlock because the WebContent process is waiting for the next opportunity to render before a screenshot is taken. For some reason unknown to myself, this opportunity never arrives. In order to not deadlock, screenshot requests are now also processed separately from rendering. --- Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp | 8 ++++++++ Userland/Libraries/LibWeb/Page/Page.h | 1 + Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h | 1 + Userland/Services/WebContent/PageClient.cpp | 7 ++++++- Userland/Services/WebContent/PageClient.h | 1 + Userland/Services/WebWorker/PageHost.h | 1 + 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp index 95f748fc452..47f8353e086 100644 --- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp +++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -336,6 +337,13 @@ void EventLoop::process() } }); + // FIXME: Not in the spec: If there is a screenshot request queued, process it now. + // This prevents tests deadlocking on screenshot requests on macOS. + for (auto& document : docs) { + if (document->page().top_level_traversable()->needs_repaint()) + document->page().client().process_screenshot_requests(); + } + // 13. If all of the following are true // - this is a window event loop // - there is no task in this event loop's task queues whose document is fully active diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index 07af9f0af6c..ff5d98ac042 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -304,6 +304,7 @@ public: virtual CSS::PreferredContrast preferred_contrast() const = 0; virtual CSS::PreferredMotion preferred_motion() const = 0; virtual void paint_next_frame() = 0; + virtual void process_screenshot_requests() = 0; virtual void paint(DevicePixelRect const&, Painting::BackingStore&, PaintOptions = {}) = 0; virtual void page_did_change_title(ByteString const&) { } virtual void page_did_change_url(URL::URL const&) { } diff --git a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h index e66898f6c53..b393af1906b 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h +++ b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h @@ -76,6 +76,7 @@ public: virtual CSS::PreferredMotion preferred_motion() const override { return m_host_page->client().preferred_motion(); } virtual void request_file(FileRequest) override { } virtual void paint_next_frame() override { } + virtual void process_screenshot_requests() override { } virtual void paint(DevicePixelRect const&, Painting::BackingStore&, Web::PaintOptions = {}) override { } virtual void schedule_repaint() override { } virtual bool is_ready_to_paint() const override { return true; } diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index 41df7597755..a171f8cdc83 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -187,7 +187,7 @@ Web::Layout::Viewport* PageClient::layout_root() return document->layout_node(); } -void PageClient::paint_next_frame() +void PageClient::process_screenshot_requests() { while (!m_screenshot_tasks.is_empty()) { auto task = m_screenshot_tasks.dequeue(); @@ -210,6 +210,11 @@ void PageClient::paint_next_frame() client().async_did_take_screenshot(m_id, bitmap->to_shareable_bitmap()); } } +} + +void PageClient::paint_next_frame() +{ + process_screenshot_requests(); auto back_store = m_backing_store_manager.back_store(); if (!back_store) diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index a7adb1e51be..141f1e23f43 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -44,6 +44,7 @@ public: ErrorOr connect_to_webdriver(ByteString const& webdriver_ipc_path); virtual void paint_next_frame() override; + virtual void process_screenshot_requests() override; virtual void paint(Web::DevicePixelRect const& content_rect, Web::Painting::BackingStore&, Web::PaintOptions = {}) override; void set_palette_impl(Gfx::PaletteImpl&); diff --git a/Userland/Services/WebWorker/PageHost.h b/Userland/Services/WebWorker/PageHost.h index fd1f6fedd2f..f50884e59c3 100644 --- a/Userland/Services/WebWorker/PageHost.h +++ b/Userland/Services/WebWorker/PageHost.h @@ -32,6 +32,7 @@ public: virtual Web::CSS::PreferredContrast preferred_contrast() const override; virtual Web::CSS::PreferredMotion preferred_motion() const override; virtual void paint_next_frame() override {}; + virtual void process_screenshot_requests() override {}; virtual void paint(Web::DevicePixelRect const&, Web::Painting::BackingStore&, Web::PaintOptions = {}) override; virtual void request_file(Web::FileRequest) override; virtual void schedule_repaint() override {};