mirror of
https://github.com/servo/servo.git
synced 2025-08-09 23:45:35 +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.
|
/// only exceptions are script queries and scroll requests.
|
||||||
pub(crate) fn reflow(&self, reflow_goal: ReflowGoal, can_gc: CanGc) -> bool {
|
pub(crate) fn reflow(&self, reflow_goal: ReflowGoal, can_gc: CanGc) -> bool {
|
||||||
// Never reflow inactive Documents.
|
// Never reflow inactive Documents.
|
||||||
if !self.Document().is_fully_active() {
|
let document = self.Document();
|
||||||
|
if !document.is_fully_active() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the pending web fonts before layout, in case a font loads during the layout.
|
// 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;
|
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 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:
|
// 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:
|
// > A FontFaceSet is pending on the environment if any of the following are true:
|
||||||
// > - the document is still loading
|
// > - 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
|
// 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
|
// a "rendering opportunity" in `ScriptThread::handle_web_font_loaded, which should also
|
||||||
// make sure a microtask checkpoint happens, triggering the promise callback.
|
// 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 {
|
if !waiting_for_web_fonts_to_load && is_ready_state_complete {
|
||||||
font_face_set.fulfill_ready_promise_if_needed(can_gc);
|
font_face_set.fulfill_ready_promise_if_needed(can_gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If writing a screenshot, check if the script has reached a state
|
issued_reflow
|
||||||
// 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
|
pub(crate) fn maybe_send_idle_document_state_to_constellation(&self) {
|
||||||
// 3) The load event has fired.
|
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
|
// When all these conditions are met, notify the constellation
|
||||||
// that this pipeline is ready to write the image (from the script thread
|
// that this pipeline is ready to write the image (from the script thread
|
||||||
// perspective at least).
|
// perspective at least).
|
||||||
if opts::get().wait_for_stable_image && updating_the_rendering {
|
debug!(
|
||||||
// Checks if the html element has reftest-wait attribute present.
|
"{:?}: Sending DocumentState::Idle to Constellation",
|
||||||
// See http://testthewebforward.org/docs/reftests.html
|
self.pipeline_id()
|
||||||
// and https://web-platform-tests.org/writing-tests/crashtest.html
|
);
|
||||||
let html_element = document.GetDocumentElement();
|
self.send_to_constellation(ScriptToConstellationMessage::SetDocumentState(
|
||||||
let reftest_wait = html_element.is_some_and(|elem| {
|
DocumentState::Idle,
|
||||||
elem.has_class(&atom!("reftest-wait"), CaseSensitivity::CaseSensitive) ||
|
));
|
||||||
elem.has_class(&Atom::from("test-wait"), CaseSensitivity::CaseSensitive)
|
self.has_sent_idle_message.set(true);
|
||||||
});
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If parsing has taken a long time and reflows are still waiting for the `load` event,
|
/// 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.
|
// should be run in a task and a microtask checkpoint is always done when running tasks.
|
||||||
self.perform_a_microtask_checkpoint(can_gc);
|
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
|
// If there are any pending reflows and we are not having rendering opportunities
|
||||||
// driven by the compositor, then schedule the next rendering opportunity.
|
// immediately after running "update the rendering," run it one more time.
|
||||||
//
|
|
||||||
// TODO: This is a workaround until rendering opportunities can be triggered from a
|
|
||||||
// timer in the script thread.
|
|
||||||
if self
|
if self
|
||||||
.documents
|
.documents
|
||||||
.borrow()
|
.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) {
|
fn maybe_schedule_rendering_opportunity_after_ipc_message(&self, can_gc: CanGc) {
|
||||||
if self.has_pending_animation_tick.load(Ordering::Relaxed) {
|
if self.has_pending_animation_tick.load(Ordering::Relaxed) {
|
||||||
self.update_the_rendering(can_gc);
|
self.update_the_rendering(can_gc);
|
||||||
|
@ -1650,6 +1659,7 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maybe_schedule_rendering_opportunity_after_ipc_message(can_gc);
|
self.maybe_schedule_rendering_opportunity_after_ipc_message(can_gc);
|
||||||
|
self.maybe_send_idle_document_state_to_constellation();
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue