瀏覽代碼

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.
Victor Tran 1 年之前
父節點
當前提交
31698281b6

+ 8 - 0
Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp

@@ -12,6 +12,7 @@
 #include <LibWeb/HTML/BrowsingContext.h>
 #include <LibWeb/HTML/EventLoop/EventLoop.h>
 #include <LibWeb/HTML/Scripting/Environments.h>
+#include <LibWeb/HTML/TraversableNavigable.h>
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HighResolutionTime/Performance.h>
 #include <LibWeb/HighResolutionTime/TimeOrigin.h>
@@ -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

+ 1 - 0
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&) { }

+ 1 - 0
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; }

+ 6 - 1
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)

+ 1 - 0
Userland/Services/WebContent/PageClient.h

@@ -44,6 +44,7 @@ public:
     ErrorOr<void> 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&);

+ 1 - 0
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 {};