diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
index 0e43b48688e..d98e9795158 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
@@ -32,6 +32,10 @@ EventLoop::EventLoop(Type type)
{
m_task_queue = heap().allocate_without_realm(*this);
m_microtask_queue = heap().allocate_without_realm(*this);
+
+ m_rendering_task_function = JS::create_heap_function(heap(), [this] {
+ update_the_rendering();
+ });
}
EventLoop::~EventLoop() = default;
@@ -43,6 +47,7 @@ void EventLoop::visit_edges(Visitor& visitor)
visitor.visit(m_microtask_queue);
visitor.visit(m_currently_running_task);
visitor.visit(m_backup_incumbent_settings_object_stack);
+ visitor.visit(m_rendering_task_function);
}
void EventLoop::schedule()
@@ -239,158 +244,161 @@ void EventLoop::queue_task_to_update_the_rendering()
if (document->is_decoded_svg())
continue;
- queue_global_task(Task::Source::Rendering, *navigable->active_window(), JS::create_heap_function(navigable->heap(), [this] mutable {
- VERIFY(!m_is_running_rendering_task);
- m_is_running_rendering_task = true;
- ScopeGuard const guard = [this] {
- m_is_running_rendering_task = false;
- };
+ queue_global_task(Task::Source::Rendering, *navigable->active_window(), *m_rendering_task_function);
+ }
+}
- // FIXME: 1. Let frameTimestamp be eventLoop's last render opportunity time.
+void EventLoop::update_the_rendering()
+{
+ VERIFY(!m_is_running_rendering_task);
+ m_is_running_rendering_task = true;
+ ScopeGuard const guard = [this] {
+ m_is_running_rendering_task = false;
+ };
- // FIXME: 2. Let docs be all fully active Document objects whose relevant agent's event loop is eventLoop, sorted arbitrarily except that the following conditions must be met:
- auto docs = documents_in_this_event_loop();
- docs.remove_all_matching([&](auto& document) {
- return !document->is_fully_active();
- });
+ // FIXME: 1. Let frameTimestamp be eventLoop's last render opportunity time.
- // 3. Filter non-renderable documents: Remove from docs any Document object doc for which any of the following are true:
- docs.remove_all_matching([&](auto const& document) {
- auto navigable = document->navigable();
- if (!navigable)
- return true;
+ // FIXME: 2. Let docs be all fully active Document objects whose relevant agent's event loop is eventLoop, sorted arbitrarily except that the following conditions must be met:
+ auto docs = documents_in_this_event_loop();
+ docs.remove_all_matching([&](auto& document) {
+ return !document->is_fully_active();
+ });
- // FIXME: doc is render-blocked;
+ // 3. Filter non-renderable documents: Remove from docs any Document object doc for which any of the following are true:
+ docs.remove_all_matching([&](auto const& document) {
+ auto navigable = document->navigable();
+ if (!navigable)
+ return true;
- // doc's visibility state is "hidden";
- if (document->visibility_state() == "hidden"sv)
- return true;
+ // FIXME: doc is render-blocked;
- // FIXME: doc's rendering is suppressed for view transitions; or
+ // doc's visibility state is "hidden";
+ if (document->visibility_state() == "hidden"sv)
+ return true;
- // doc's node navigable doesn't currently have a rendering opportunity.
- if (!navigable->has_a_rendering_opportunity())
- return true;
+ // FIXME: doc's rendering is suppressed for view transitions; or
- return false;
- });
+ // doc's node navigable doesn't currently have a rendering opportunity.
+ if (!navigable->has_a_rendering_opportunity())
+ return true;
- // FIXME: 4. Unnecessary rendering: Remove from docs any Document object doc for which all of the following are true:
+ return false;
+ });
- // FIXME: 5. Remove from docs all Document objects for which the user agent believes that it's preferable to skip updating the rendering for other reasons.
+ // FIXME: 4. Unnecessary rendering: Remove from docs any Document object doc for which all of the following are true:
- // FIXME: 6. For each doc of docs, reveal doc.
+ // FIXME: 5. Remove from docs all Document objects for which the user agent believes that it's preferable to skip updating the rendering for other reasons.
- // FIXME: 7. For each doc of docs, flush autofocus candidates for doc if its node navigable is a top-level traversable.
+ // FIXME: 6. For each doc of docs, reveal doc.
- // 8. For each doc of docs, run the resize steps for doc. [CSSOMVIEW]
- for (auto& document : docs) {
- document->run_the_resize_steps();
+ // FIXME: 7. For each doc of docs, flush autofocus candidates for doc if its node navigable is a top-level traversable.
+
+ // 8. For each doc of docs, run the resize steps for doc. [CSSOMVIEW]
+ for (auto& document : docs) {
+ document->run_the_resize_steps();
+ }
+
+ // 9. For each doc of docs, run the scroll steps for doc. [CSSOMVIEW]
+ for (auto& document : docs) {
+ document->run_the_scroll_steps();
+ }
+
+ // 10. For each doc of docs, evaluate media queries and report changes for doc. [CSSOMVIEW]
+ for (auto& document : docs) {
+ document->evaluate_media_queries_and_report_changes();
+ }
+
+ // 11. For each doc of docs, update animations and send events for doc, passing in relative high resolution time given frameTimestamp and doc's relevant global object as the timestamp [WEBANIMATIONS]
+ for (auto& document : docs) {
+ document->update_animations_and_send_events(document->window()->performance()->now());
+ };
+
+ // FIXME: 12. For each doc of docs, run the fullscreen steps for doc. [FULLSCREEN]
+
+ // FIXME: 13. For each doc of docs, if the user agent detects that the backing storage associated with a CanvasRenderingContext2D or an OffscreenCanvasRenderingContext2D, context, has been lost, then it must run the context lost steps for each such context:
+
+ // 14. For each doc of docs, run the animation frame callbacks for doc, passing in the relative high resolution time given frameTimestamp and doc's relevant global object as the timestamp.
+ auto now = HighResolutionTime::unsafe_shared_current_time();
+ for (auto& document : docs) {
+ run_animation_frame_callbacks(*document, now);
+ }
+
+ // FIXME: 15. Let unsafeStyleAndLayoutStartTime be the unsafe shared current time.
+
+ // 16. For each doc of docs:
+ for (auto& document : docs) {
+ // 1. Let resizeObserverDepth be 0.
+ size_t resize_observer_depth = 0;
+
+ // 2. While true:
+ while (true) {
+ // 1. Recalculate styles and update layout for doc.
+ // NOTE: Recalculation of styles is handled by update_layout()
+ document->update_layout();
+
+ // FIXME: 2. Let hadInitialVisibleContentVisibilityDetermination be false.
+ // FIXME: 3. For each element element with 'auto' used value of 'content-visibility':
+ // FIXME: 4. If hadInitialVisibleContentVisibilityDetermination is true, then continue.
+
+ // 5. Gather active resize observations at depth resizeObserverDepth for doc.
+ document->gather_active_observations_at_depth(resize_observer_depth);
+
+ // 6. If doc has active resize observations:
+ if (document->has_active_resize_observations()) {
+ // 1. Set resizeObserverDepth to the result of broadcasting active resize observations given doc.
+ resize_observer_depth = document->broadcast_active_resize_observations();
+
+ // 2. Continue.
+ continue;
}
- // 9. For each doc of docs, run the scroll steps for doc. [CSSOMVIEW]
- for (auto& document : docs) {
- document->run_the_scroll_steps();
+ // 7. Otherwise, break.
+ break;
+ }
+
+ // 3. If doc has skipped resize observations, then deliver resize loop error given doc.
+ if (document->has_skipped_resize_observations()) {
+ // FIXME: Deliver resize loop error.
+ }
+ }
+
+ // FIXME: 17. For each doc of docs, if the focused area of doc is not a focusable area, then run the focusing steps for doc's viewport, and set doc's relevant global object's navigation API's focus changed during ongoing navigation to false.
+
+ // FIXME: 18. For each doc of docs, perform pending transition operations for doc. [CSSVIEWTRANSITIONS]
+
+ // 19. For each doc of docs, run the update intersection observations steps for doc, passing in the relative high resolution time given now and doc's relevant global object as the timestamp. [INTERSECTIONOBSERVER]
+ for (auto& document : docs) {
+ document->run_the_update_intersection_observations_steps(now);
+ }
+
+ // FIXME: 20. For each doc of docs, record rendering time for doc given unsafeStyleAndLayoutStartTime.
+
+ // FIXME: 21. For each doc of docs, mark paint timing for doc.
+
+ // 22. For each doc of docs, update the rendering or user interface of doc and its node navigable to reflect the current state.
+ for (auto& document : docs) {
+ document->page().client().process_screenshot_requests();
+ auto navigable = document->navigable();
+ if (navigable && document->needs_repaint()) {
+ auto* browsing_context = document->browsing_context();
+ auto& page = browsing_context->page();
+ if (navigable->is_traversable()) {
+ VERIFY(page.client().is_ready_to_paint());
+ page.client().paint_next_frame();
}
+ }
+ }
- // 10. For each doc of docs, evaluate media queries and report changes for doc. [CSSOMVIEW]
- for (auto& document : docs) {
- document->evaluate_media_queries_and_report_changes();
- }
+ // 23. For each doc of docs, process top layer removals given doc.
+ for (auto& document : docs) {
+ document->process_top_layer_removals();
+ }
- // 11. For each doc of docs, update animations and send events for doc, passing in relative high resolution time given frameTimestamp and doc's relevant global object as the timestamp [WEBANIMATIONS]
- for (auto& document : docs) {
- document->update_animations_and_send_events(document->window()->performance()->now());
- };
-
- // FIXME: 12. For each doc of docs, run the fullscreen steps for doc. [FULLSCREEN]
-
- // FIXME: 13. For each doc of docs, if the user agent detects that the backing storage associated with a CanvasRenderingContext2D or an OffscreenCanvasRenderingContext2D, context, has been lost, then it must run the context lost steps for each such context:
-
- // 14. For each doc of docs, run the animation frame callbacks for doc, passing in the relative high resolution time given frameTimestamp and doc's relevant global object as the timestamp.
- auto now = HighResolutionTime::unsafe_shared_current_time();
- for (auto& document : docs) {
- run_animation_frame_callbacks(*document, now);
- }
-
- // FIXME: 15. Let unsafeStyleAndLayoutStartTime be the unsafe shared current time.
-
- // 16. For each doc of docs:
- for (auto& document : docs) {
- // 1. Let resizeObserverDepth be 0.
- size_t resize_observer_depth = 0;
-
- // 2. While true:
- while (true) {
- // 1. Recalculate styles and update layout for doc.
- // NOTE: Recalculation of styles is handled by update_layout()
- document->update_layout();
-
- // FIXME: 2. Let hadInitialVisibleContentVisibilityDetermination be false.
- // FIXME: 3. For each element element with 'auto' used value of 'content-visibility':
- // FIXME: 4. If hadInitialVisibleContentVisibilityDetermination is true, then continue.
-
- // 5. Gather active resize observations at depth resizeObserverDepth for doc.
- document->gather_active_observations_at_depth(resize_observer_depth);
-
- // 6. If doc has active resize observations:
- if (document->has_active_resize_observations()) {
- // 1. Set resizeObserverDepth to the result of broadcasting active resize observations given doc.
- resize_observer_depth = document->broadcast_active_resize_observations();
-
- // 2. Continue.
- continue;
- }
-
- // 7. Otherwise, break.
- break;
- }
-
- // 3. If doc has skipped resize observations, then deliver resize loop error given doc.
- if (document->has_skipped_resize_observations()) {
- // FIXME: Deliver resize loop error.
- }
- }
-
- // FIXME: 17. For each doc of docs, if the focused area of doc is not a focusable area, then run the focusing steps for doc's viewport, and set doc's relevant global object's navigation API's focus changed during ongoing navigation to false.
-
- // FIXME: 18. For each doc of docs, perform pending transition operations for doc. [CSSVIEWTRANSITIONS]
-
- // 19. For each doc of docs, run the update intersection observations steps for doc, passing in the relative high resolution time given now and doc's relevant global object as the timestamp. [INTERSECTIONOBSERVER]
- for (auto& document : docs) {
- document->run_the_update_intersection_observations_steps(now);
- }
-
- // FIXME: 20. For each doc of docs, record rendering time for doc given unsafeStyleAndLayoutStartTime.
-
- // FIXME: 21. For each doc of docs, mark paint timing for doc.
-
- // 22. For each doc of docs, update the rendering or user interface of doc and its node navigable to reflect the current state.
- for (auto& document : docs) {
- document->page().client().process_screenshot_requests();
- auto navigable = document->navigable();
- if (navigable && document->needs_repaint()) {
- auto* browsing_context = document->browsing_context();
- auto& page = browsing_context->page();
- if (navigable->is_traversable()) {
- VERIFY(page.client().is_ready_to_paint());
- page.client().paint_next_frame();
- }
- }
- }
-
- // 23. For each doc of docs, process top layer removals given doc.
- for (auto& document : docs) {
- document->process_top_layer_removals();
- }
-
- for (auto& document : docs) {
- if (document->readiness() == HTML::DocumentReadyState::Complete && document->style_computer().number_of_css_font_faces_with_loading_in_progress() == 0) {
- HTML::TemporaryExecutionContext context(HTML::relevant_settings_object(*document), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
- document->fonts()->resolve_ready_promise();
- }
- }
- }));
+ for (auto& document : docs) {
+ if (document->readiness() == HTML::DocumentReadyState::Complete && document->style_computer().number_of_css_font_faces_with_loading_in_progress() == 0) {
+ HTML::TemporaryExecutionContext context(HTML::relevant_settings_object(*document), HTML::TemporaryExecutionContext::CallbacksEnabled::Yes);
+ document->fonts()->resolve_ready_promise();
+ }
}
}
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
index 3f2cf6722a9..b653d6fc33d 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
@@ -81,6 +81,8 @@ private:
virtual void visit_edges(Visitor&) override;
+ void update_the_rendering();
+
Type m_type { Type::Window };
JS::GCPtr m_task_queue;
@@ -116,6 +118,8 @@ private:
bool m_skip_event_loop_processing_steps { false };
bool m_is_running_rendering_task { false };
+
+ JS::GCPtr> m_rendering_task_function;
};
EventLoop& main_thread_event_loop();