mirror of
https://github.com/servo/servo.git
synced 2025-08-09 15:35:34 +01:00
Move out idle message sending
This commit is contained in:
parent
3640c027f2
commit
851195c3ce
2 changed files with 66 additions and 49 deletions
|
@ -2280,22 +2280,18 @@ impl Window {
|
|||
/// only exceptions are script queries and scroll requests.
|
||||
pub(crate) fn reflow(&self, reflow_goal: ReflowGoal, can_gc: CanGc) -> bool {
|
||||
// Never reflow inactive Documents.
|
||||
if !self.Document().is_fully_active() {
|
||||
let document = self.Document();
|
||||
if !document.is_fully_active() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Count the pending web fonts before layout, in case a font loads during the layout.
|
||||
let waiting_for_web_fonts_to_load = self.font_context.web_fonts_still_loading() != 0;
|
||||
|
||||
self.Document().ensure_safe_to_run_script_or_layout();
|
||||
document.ensure_safe_to_run_script_or_layout();
|
||||
|
||||
let updating_the_rendering = reflow_goal == ReflowGoal::UpdateTheRendering;
|
||||
let issued_reflow = self.force_reflow(reflow_goal);
|
||||
|
||||
let document = self.Document();
|
||||
let font_face_set = document.Fonts(can_gc);
|
||||
let is_ready_state_complete = document.ReadyState() == DocumentReadyState::Complete;
|
||||
|
||||
// From https://drafts.csswg.org/css-font-loading/#font-face-set-ready:
|
||||
// > A FontFaceSet is pending on the environment if any of the following are true:
|
||||
// > - the document is still loading
|
||||
|
@ -2306,49 +2302,60 @@ impl Window {
|
|||
// Thus, we are queueing promise resolution here. This reflow should have been triggered by
|
||||
// a "rendering opportunity" in `ScriptThread::handle_web_font_loaded, which should also
|
||||
// make sure a microtask checkpoint happens, triggering the promise callback.
|
||||
let font_face_set = document.Fonts(can_gc);
|
||||
let is_ready_state_complete = document.ReadyState() == DocumentReadyState::Complete;
|
||||
if !waiting_for_web_fonts_to_load && is_ready_state_complete {
|
||||
font_face_set.fulfill_ready_promise_if_needed(can_gc);
|
||||
}
|
||||
|
||||
// If writing a screenshot, check if the script has reached a state
|
||||
// where it's safe to write the image. This means that:
|
||||
// 1) The reflow is for display (otherwise it could be a query)
|
||||
// 2) The html element doesn't contain the 'reftest-wait' class
|
||||
// 3) The load event has fired.
|
||||
issued_reflow
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_send_idle_document_state_to_constellation(&self) {
|
||||
if !opts::get().wait_for_stable_image {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.has_sent_idle_message.get() {
|
||||
return;
|
||||
}
|
||||
|
||||
let document = self.Document();
|
||||
if document.ReadyState() != DocumentReadyState::Complete {
|
||||
return;
|
||||
}
|
||||
|
||||
// Checks if the html element has reftest-wait attribute present.
|
||||
// See http://testthewebforward.org/docs/reftests.html
|
||||
// and https://web-platform-tests.org/writing-tests/crashtest.html
|
||||
if document.GetDocumentElement().is_some_and(|elem| {
|
||||
elem.has_class(&atom!("reftest-wait"), CaseSensitivity::CaseSensitive) ||
|
||||
elem.has_class(&Atom::from("test-wait"), CaseSensitivity::CaseSensitive)
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.font_context.web_fonts_still_loading() != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if !self.pending_layout_images.borrow().is_empty() ||
|
||||
!self.pending_images_for_rasterization.borrow().is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// When all these conditions are met, notify the constellation
|
||||
// that this pipeline is ready to write the image (from the script thread
|
||||
// perspective at least).
|
||||
if opts::get().wait_for_stable_image && updating_the_rendering {
|
||||
// Checks if the html element has reftest-wait attribute present.
|
||||
// See http://testthewebforward.org/docs/reftests.html
|
||||
// and https://web-platform-tests.org/writing-tests/crashtest.html
|
||||
let html_element = document.GetDocumentElement();
|
||||
let reftest_wait = html_element.is_some_and(|elem| {
|
||||
elem.has_class(&atom!("reftest-wait"), CaseSensitivity::CaseSensitive) ||
|
||||
elem.has_class(&Atom::from("test-wait"), CaseSensitivity::CaseSensitive)
|
||||
});
|
||||
|
||||
let has_sent_idle_message = self.has_sent_idle_message.get();
|
||||
let no_pending_images = self.pending_layout_images.borrow().is_empty() &&
|
||||
self.pending_images_for_rasterization.borrow().is_empty();
|
||||
|
||||
if !has_sent_idle_message &&
|
||||
is_ready_state_complete &&
|
||||
!reftest_wait &&
|
||||
no_pending_images &&
|
||||
!waiting_for_web_fonts_to_load
|
||||
{
|
||||
debug!(
|
||||
"{:?}: Sending DocumentState::Idle to Constellation",
|
||||
self.pipeline_id()
|
||||
);
|
||||
let event = ScriptToConstellationMessage::SetDocumentState(DocumentState::Idle);
|
||||
self.send_to_constellation(event);
|
||||
self.has_sent_idle_message.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
issued_reflow
|
||||
debug!(
|
||||
"{:?}: Sending DocumentState::Idle to Constellation",
|
||||
self.pipeline_id()
|
||||
);
|
||||
self.send_to_constellation(ScriptToConstellationMessage::SetDocumentState(
|
||||
DocumentState::Idle,
|
||||
));
|
||||
self.has_sent_idle_message.set(true);
|
||||
}
|
||||
|
||||
/// If parsing has taken a long time and reflows are still waiting for the `load` event,
|
||||
|
|
|
@ -1369,15 +1369,12 @@ impl ScriptThread {
|
|||
// should be run in a task and a microtask checkpoint is always done when running tasks.
|
||||
self.perform_a_microtask_checkpoint(can_gc);
|
||||
|
||||
self.maybe_schedule_rendering_opportunity_after_rendering_upate(saw_any_reflows);
|
||||
self.maybe_schedule_rendering_opportunity_after_rendering_update(saw_any_reflows);
|
||||
}
|
||||
|
||||
fn maybe_schedule_rendering_opportunity_after_rendering_upate(&self, saw_any_reflows: bool) {
|
||||
fn maybe_schedule_rendering_opportunity_after_rendering_update(&self, saw_any_reflows: bool) {
|
||||
// If there are any pending reflows and we are not having rendering opportunities
|
||||
// driven by the compositor, then schedule the next rendering opportunity.
|
||||
//
|
||||
// TODO: This is a workaround until rendering opportunities can be triggered from a
|
||||
// timer in the script thread.
|
||||
// immediately after running "update the rendering," run it one more time.
|
||||
if self
|
||||
.documents
|
||||
.borrow()
|
||||
|
@ -1403,6 +1400,18 @@ impl ScriptThread {
|
|||
}
|
||||
}
|
||||
|
||||
fn maybe_send_idle_document_state_to_constellation(&self) {
|
||||
if !opts::get().wait_for_stable_image {
|
||||
return;
|
||||
}
|
||||
|
||||
for (_, document) in self.documents.borrow().iter() {
|
||||
document
|
||||
.window()
|
||||
.maybe_send_idle_document_state_to_constellation();
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_schedule_rendering_opportunity_after_ipc_message(&self, can_gc: CanGc) {
|
||||
if self.has_pending_animation_tick.load(Ordering::Relaxed) {
|
||||
self.update_the_rendering(can_gc);
|
||||
|
@ -1650,6 +1659,7 @@ impl ScriptThread {
|
|||
}
|
||||
|
||||
self.maybe_schedule_rendering_opportunity_after_ipc_message(can_gc);
|
||||
self.maybe_send_idle_document_state_to_constellation();
|
||||
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue