Move font.ready trigger out of reflow

This commit is contained in:
Martin Robinson 2025-07-31 12:57:08 +02:00
parent 31096e1a0f
commit 4b8a25afab
19 changed files with 130 additions and 151 deletions

View file

@ -1475,11 +1475,10 @@ impl CanvasState {
};
let node = canvas.upcast::<Node>();
let window = canvas.owner_window();
let resolved_font_style =
match window.resolved_font_style_query(node, value.to_string(), can_gc) {
Some(value) => value,
None => return, // syntax error
};
let resolved_font_style = match window.resolved_font_style_query(node, value.to_string()) {
Some(value) => value,
None => return, // syntax error
};
self.state.borrow_mut().font_style = Some((*resolved_font_style).clone());
}

View file

@ -395,7 +395,7 @@ pub(crate) fn handle_get_layout(
}
fn determine_auto_margins(node: &Node, can_gc: CanGc) -> AutoMargins {
let style = node.style(can_gc).unwrap();
let style = node.style().unwrap();
let margin = style.get_margin();
AutoMargins {
top: margin.margin_top.is_auto(),

View file

@ -280,7 +280,7 @@ impl CSSStyleDeclaration {
}
let addr = node.to_trusted_node_address();
node.owner_window()
.resolved_style_query(addr, self.pseudo, property, can_gc)
.resolved_style_query(addr, self.pseudo, property)
},
CSSStyleOwner::Null => DOMString::new(),
}

View file

@ -2886,7 +2886,7 @@ impl Document {
// We finished loading the page, so if the `Window` is still waiting for
// the first layout, allow it.
if self.has_browsing_context && self.is_fully_active() {
self.window().allow_layout_if_necessary(can_gc);
self.window().allow_layout_if_necessary();
}
// Deferred scripts have to wait for page to finish loading,
@ -3688,7 +3688,7 @@ impl Document {
// > doc and its node navigable to reflect the current state.
//
// Returns true if a reflow occured.
pub(crate) fn update_the_rendering(&self, can_gc: CanGc) -> bool {
pub(crate) fn update_the_rendering(&self) -> bool {
self.update_animating_images();
// All dirty canvases are flushed before updating the rendering.
@ -3723,7 +3723,41 @@ impl Document {
receiver.recv().unwrap();
}
self.window().reflow(ReflowGoal::UpdateTheRendering, can_gc)
self.window().reflow(ReflowGoal::UpdateTheRendering)
}
/// 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
/// > - the document has pending stylesheet requests
/// > - the document has pending layout operations which might cause the user agent to request
/// > a font, or which depend on recently-loaded fonts
pub(crate) fn maybe_send_document_fonts_ready_message(&self, can_gc: CanGc) {
if !self.is_fully_active() {
return;
}
let fonts = self.Fonts(can_gc);
//println!(
// "fonts: {:?} {:?} {:?} {:?}",
// fonts.waiting_to_fullfill_promise(),
// self.window().font_context().web_fonts_still_loading() == 0,
// self.ReadyState() == DocumentReadyState::Complete,
// !self.needs_rendering_update()
//);
if !fonts.waiting_to_fullfill_promise() {
return;
}
if self.window().font_context().web_fonts_still_loading() != 0 {
return;
}
if self.ReadyState() != DocumentReadyState::Complete {
return;
}
if self.needs_rendering_update() {
return;
}
fonts.fulfill_ready_promise_if_needed(can_gc);
}
pub(crate) fn id_map(&self) -> Ref<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {

View file

@ -141,10 +141,8 @@ impl DocumentOrShadowRoot {
&self,
client_point: &Point2D<f32>,
query_type: NodesFromPointQueryType,
can_gc: CanGc,
) -> Vec<UntrustedNodeAddress> {
self.window
.layout_reflow(QueryMsg::NodesFromPointQuery, can_gc);
self.window.layout_reflow(QueryMsg::NodesFromPointQuery);
self.window
.layout()
.query_nodes_from_point(*client_point, query_type)
@ -174,7 +172,7 @@ impl DocumentOrShadowRoot {
}
match self
.nodes_from_point(point, NodesFromPointQueryType::Topmost, can_gc)
.nodes_from_point(point, NodesFromPointQueryType::Topmost)
.first()
{
Some(address) => {
@ -223,7 +221,7 @@ impl DocumentOrShadowRoot {
}
// Step 1 and Step 3
let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All, can_gc);
let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All);
let mut elements: Vec<DomRoot<Element>> = nodes
.iter()
.flat_map(|&untrusted_node_address| {

View file

@ -465,7 +465,7 @@ impl Element {
/// style will be `None` for elements in a `display: none` subtree. otherwise, the element has a
/// layout box iff it doesn't have `display: none`.
pub(crate) fn style(&self, can_gc: CanGc) -> Option<Arc<ComputedValues>> {
self.upcast::<Node>().style(can_gc)
self.upcast::<Node>().style()
}
// https://drafts.csswg.org/cssom-view/#css-layout-box
@ -2524,7 +2524,7 @@ impl Element {
}
// Step 11
win.scroll_node(node, x, y, behavior, can_gc);
win.scroll_node(node, x, y, behavior);
}
/// <https://html.spec.whatwg.org/multipage/#fragment-parsing-algorithm-steps>
@ -3057,7 +3057,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
// https://drafts.csswg.org/cssom-view/#dom-element-getclientrects
fn GetClientRects(&self, can_gc: CanGc) -> DomRoot<DOMRectList> {
let win = self.owner_window();
let raw_rects = self.upcast::<Node>().content_boxes(can_gc);
let raw_rects = self.upcast::<Node>().content_boxes();
let rects: Vec<DomRoot<DOMRect>> = raw_rects
.iter()
.map(|rect| {
@ -3175,7 +3175,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
}
// Step 9
let point = win.scroll_offset_query(node, can_gc);
let point = win.scroll_offset_query(node);
point.y.abs() as f64
}
@ -3229,7 +3229,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
}
// Step 11
win.scroll_node(node, self.ScrollLeft(can_gc), y, behavior, can_gc);
win.scroll_node(node, self.ScrollLeft(can_gc), y, behavior);
}
// https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
@ -3274,7 +3274,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
}
// Step 9
let point = win.scroll_offset_query(node, can_gc);
let point = win.scroll_offset_query(node);
point.x.abs() as f64
}
@ -3329,7 +3329,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
}
// Step 11
win.scroll_node(node, x, self.ScrollTop(can_gc), behavior, can_gc);
win.scroll_node(node, x, self.ScrollTop(can_gc), behavior);
}
// https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth
@ -4789,7 +4789,7 @@ impl Element {
}
}
let mut rect = self.upcast::<Node>().client_rect(can_gc);
let mut rect = self.upcast::<Node>().client_rect();
let in_quirks_mode = doc.quirks_mode() == QuirksMode::Quirks;
if (in_quirks_mode && doc.GetBody().as_deref() == self.downcast::<HTMLElement>()) ||

View file

@ -74,6 +74,10 @@ impl FontFaceSet {
self.promise.resolve_native(self, can_gc);
}
}
pub(crate) fn waiting_to_fullfill_promise(&self) -> bool {
!self.promise.is_fulfilled()
}
}
impl FontFaceSetMethods<crate::DomTypeHolder> for FontFaceSet {

View file

@ -127,7 +127,7 @@ impl HTMLElement {
return node.GetTextContent().unwrap();
}
window.layout_reflow(QueryMsg::ElementInnerOuterTextQuery, can_gc);
window.layout_reflow(QueryMsg::ElementInnerOuterTextQuery);
let text = window
.layout()
.query_element_inner_outer_text(node.to_trusted_node_address());
@ -445,7 +445,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
let node = self.upcast::<Node>();
let window = self.owner_window();
let (element, _) = window.offset_parent_query(node, can_gc);
let (element, _) = window.offset_parent_query(node);
element
}
@ -458,7 +458,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
let node = self.upcast::<Node>();
let window = self.owner_window();
let (_, rect) = window.offset_parent_query(node, can_gc);
let (_, rect) = window.offset_parent_query(node);
rect.origin.y.to_nearest_px()
}
@ -471,7 +471,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
let node = self.upcast::<Node>();
let window = self.owner_window();
let (_, rect) = window.offset_parent_query(node, can_gc);
let (_, rect) = window.offset_parent_query(node);
rect.origin.x.to_nearest_px()
}
@ -480,7 +480,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
fn OffsetWidth(&self, can_gc: CanGc) -> i32 {
let node = self.upcast::<Node>();
let window = self.owner_window();
let (_, rect) = window.offset_parent_query(node, can_gc);
let (_, rect) = window.offset_parent_query(node);
rect.size.width.to_nearest_px()
}
@ -489,7 +489,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
fn OffsetHeight(&self, can_gc: CanGc) -> i32 {
let node = self.upcast::<Node>();
let window = self.owner_window();
let (_, rect) = window.offset_parent_query(node, can_gc);
let (_, rect) = window.offset_parent_query(node);
rect.size.height.to_nearest_px()
}

View file

@ -210,7 +210,7 @@ impl HTMLIFrameElement {
};
let viewport_details = window
.get_iframe_viewport_details_if_known(browsing_context_id, can_gc)
.get_iframe_viewport_details_if_known(browsing_context_id)
.unwrap_or_else(|| ViewportDetails {
hidpi_scale_factor: window.device_pixel_ratio(),
..Default::default()

View file

@ -1657,7 +1657,7 @@ impl HTMLImageElementMethods<crate::DomTypeHolder> for HTMLImageElement {
// https://html.spec.whatwg.org/multipage/#dom-img-width
fn Width(&self, can_gc: CanGc) -> u32 {
let node = self.upcast::<Node>();
match node.bounding_content_box(can_gc) {
match node.bounding_content_box() {
Some(rect) => rect.size.width.to_px() as u32,
None => self.NaturalWidth(),
}
@ -1671,7 +1671,7 @@ impl HTMLImageElementMethods<crate::DomTypeHolder> for HTMLImageElement {
// https://html.spec.whatwg.org/multipage/#dom-img-height
fn Height(&self, can_gc: CanGc) -> u32 {
let node = self.upcast::<Node>();
match node.bounding_content_box(can_gc) {
match node.bounding_content_box() {
Some(rect) => rect.size.height.to_px() as u32,
None => self.NaturalHeight(),
}

View file

@ -3074,11 +3074,8 @@ impl VirtualMethods for HTMLInputElement {
// now.
if let Some(point_in_target) = mouse_event.point_in_target() {
let window = self.owner_window();
let index = window.text_index_query(
self.upcast::<Node>(),
point_in_target.to_untyped(),
can_gc,
);
let index = window
.text_index_query(self.upcast::<Node>(), point_in_target.to_untyped());
// Position the caret at the click position or at the end of the current
// value.
let edit_point_index = match index {

View file

@ -278,7 +278,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
) -> Fallible<DomRoot<MouseEvent>> {
let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable);
let scroll_offset = window.scroll_offset(can_gc);
let scroll_offset = window.scroll_offset();
let page_point = Point2D::new(
scroll_offset.x as i32 + init.clientX,
scroll_offset.y as i32 + init.clientY,
@ -384,7 +384,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
let Some(node) = target.downcast::<Node>() else {
return 0;
};
return self.ClientX() - node.client_rect(can_gc).origin.x;
return self.ClientX() - node.client_rect().origin.x;
}
// > 2. Return the value of the events pageX attribute.
@ -406,7 +406,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
let Some(node) = target.downcast::<Node>() else {
return 0;
};
return self.ClientY() - node.client_rect(can_gc).origin.y;
return self.ClientY() - node.client_rect().origin.y;
}
// 2. Return the value of the events pageY attribute.
@ -498,7 +498,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
.set(Point2D::new(client_x_arg, client_y_arg));
let global = self.global();
let scroll_offset = global.as_window().scroll_offset(can_gc);
let scroll_offset = global.as_window().scroll_offset();
self.page_point.set(Point2D::new(
scroll_offset.x as i32 + client_x_arg,
scroll_offset.y as i32 + client_y_arg,

View file

@ -944,24 +944,24 @@ impl Node {
/// Returns the rendered bounding content box if the element is rendered,
/// and none otherwise.
pub(crate) fn bounding_content_box(&self, can_gc: CanGc) -> Option<Rect<Au>> {
self.owner_window().content_box_query(self, can_gc)
pub(crate) fn bounding_content_box(&self) -> Option<Rect<Au>> {
self.owner_window().content_box_query(self)
}
pub(crate) fn bounding_content_box_or_zero(&self, can_gc: CanGc) -> Rect<Au> {
self.bounding_content_box(can_gc).unwrap_or_else(Rect::zero)
self.bounding_content_box().unwrap_or_else(Rect::zero)
}
pub(crate) fn bounding_content_box_no_reflow(&self) -> Option<Rect<Au>> {
self.owner_window().content_box_query_unchecked(self)
}
pub(crate) fn content_boxes(&self, can_gc: CanGc) -> Vec<Rect<Au>> {
self.owner_window().content_boxes_query(self, can_gc)
pub(crate) fn content_boxes(&self) -> Vec<Rect<Au>> {
self.owner_window().content_boxes_query(self)
}
pub(crate) fn client_rect(&self, can_gc: CanGc) -> Rect<i32> {
self.owner_window().client_rect_query(self, can_gc)
pub(crate) fn client_rect(&self) -> Rect<i32> {
self.owner_window().client_rect_query(self)
}
/// <https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth>
@ -992,7 +992,7 @@ impl Node {
// element is not potentially scrollable, return max(viewport scrolling area
// width, viewport width)."
if (is_root && !in_quirks_mode) || (is_body_element && in_quirks_mode) {
let viewport_scrolling_area = window.scrolling_area_query(None, can_gc);
let viewport_scrolling_area = window.scrolling_area_query(None);
return Rect::new(
viewport_scrolling_area.origin,
viewport_scrolling_area.size.max(viewport),
@ -1002,7 +1002,7 @@ impl Node {
// "6. If the element does not have any associated box return zero and terminate
// these steps."
// "7. Return the width of the elements scrolling area."
window.scrolling_area_query(Some(self), can_gc)
window.scrolling_area_query(Some(self))
}
/// <https://dom.spec.whatwg.org/#dom-childnode-before>
@ -1461,9 +1461,8 @@ impl Node {
})
}
pub(crate) fn style(&self, can_gc: CanGc) -> Option<Arc<ComputedValues>> {
self.owner_window()
.layout_reflow(QueryMsg::StyleQuery, can_gc);
pub(crate) fn style(&self) -> Option<Arc<ComputedValues>> {
self.owner_window().layout_reflow(QueryMsg::StyleQuery);
self.style_data
.borrow()
.as_ref()

View file

@ -233,7 +233,7 @@ impl PointerEventMethods<crate::DomTypeHolder> for PointerEvent {
) -> DomRoot<PointerEvent> {
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
let scroll_offset = window.scroll_offset(can_gc);
let scroll_offset = window.scroll_offset();
let page_point = Point2D::new(
scroll_offset.x as i32 + init.parent.clientX,
scroll_offset.y as i32 + init.parent.clientY,

View file

@ -341,7 +341,7 @@ impl Range {
.following_nodes(document.upcast::<Node>())
.take_while(move |node| node != &end)
.chain(iter::once(end_clone))
.flat_map(move |node| node.content_boxes(can_gc))
.flat_map(move |node| node.content_boxes())
}
/// <https://dom.spec.whatwg.org/#concept-range-bp-set>

View file

@ -312,7 +312,7 @@ fn calculate_box_size(
// but the spec will expand to cover all fragments.
target
.upcast::<Node>()
.content_boxes(can_gc)
.content_boxes()
.pop()
.unwrap_or_else(Rect::zero)
},

View file

@ -204,7 +204,7 @@ impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
) -> Fallible<DomRoot<WheelEvent>> {
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
let scroll_offset = window.scroll_offset(can_gc);
let scroll_offset = window.scroll_offset();
let page_point = Point2D::<i32, CSSPixel>::new(
scroll_offset.x as i32 + init.parent.clientX,

View file

@ -1615,7 +1615,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
/// <https://drafts.csswg.org/cssom-view/#dom-window-scrollx>
fn ScrollX(&self) -> i32 {
self.scroll_offset(CanGc::note()).x as i32
self.scroll_offset().x as i32
}
// https://drafts.csswg.org/cssom-view/#dom-window-pagexoffset
@ -1625,7 +1625,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
/// <https://drafts.csswg.org/cssom-view/#dom-window-scrolly>
fn ScrollY(&self) -> i32 {
self.scroll_offset(CanGc::note()).y as i32
self.scroll_offset().y as i32
}
// https://drafts.csswg.org/cssom-view/#dom-window-pageyoffset
@ -1667,7 +1667,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
// https://drafts.csswg.org/cssom-view/#dom-window-scrollby
fn ScrollBy_(&self, x: f64, y: f64, can_gc: CanGc) {
let scroll_offset = self.scroll_offset(can_gc);
let scroll_offset = self.scroll_offset();
// Step 3
let left = x + scroll_offset.x as f64;
// Step 4
@ -1993,11 +1993,8 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
}
impl Window {
pub(crate) fn scroll_offset(&self, can_gc: CanGc) -> Vector2D<f32, LayoutPixel> {
self.scroll_offset_query_with_external_scroll_id(
self.pipeline_id().root_scroll_id(),
can_gc,
)
pub(crate) fn scroll_offset(&self) -> Vector2D<f32, LayoutPixel> {
self.scroll_offset_query_with_external_scroll_id(self.pipeline_id().root_scroll_id())
}
// https://heycam.github.io/webidl/#named-properties-object
@ -2108,7 +2105,7 @@ impl Window {
// Step 7 & 8
// TODO: Consider `block-end` and `inline-end` overflow direction.
let scrolling_area = self.scrolling_area_query(None, can_gc);
let scrolling_area = self.scrolling_area_query(None);
let x = xfinite
.min(scrolling_area.width() as f64 - viewport.width as f64)
.max(0.0f64);
@ -2118,7 +2115,7 @@ impl Window {
// Step 10
//TODO handling ongoing smooth scrolling
let scroll_offset = self.scroll_offset(can_gc);
let scroll_offset = self.scroll_offset();
if x == scroll_offset.x as f64 && y == scroll_offset.y as f64 {
return;
}
@ -2134,7 +2131,6 @@ impl Window {
self.pipeline_id().root_scroll_id(),
behavior,
None,
can_gc,
);
}
@ -2146,15 +2142,11 @@ impl Window {
scroll_id: ExternalScrollId,
_behavior: ScrollBehavior,
_element: Option<&Element>,
can_gc: CanGc,
) {
// TODO Step 1
// TODO(mrobinson, #18709): Add smooth scrolling support to WebRender so that we can
// properly process ScrollBehavior here.
self.reflow(
ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(x, y)),
can_gc,
);
self.reflow(ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(x, y)));
}
pub(crate) fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
@ -2278,37 +2270,15 @@ impl Window {
/// NOTE: This method should almost never be called directly! Layout and rendering updates
/// should happen as part of the HTML event loop via *update the rendering*. Currerntly, the
/// 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) -> bool {
// Never reflow inactive Documents.
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;
document.ensure_safe_to_run_script_or_layout();
let issued_reflow = self.force_reflow(reflow_goal);
// 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
// > - the document has pending stylesheet requests
// > - the document has pending layout operations which might cause the user agent to request
// > a font, or which depend on recently-loaded fonts
//
// 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);
}
issued_reflow
self.force_reflow(reflow_goal)
}
pub(crate) fn maybe_send_idle_document_state_to_constellation(&self) {
@ -2373,7 +2343,7 @@ impl Window {
) {
return;
}
self.allow_layout_if_necessary(can_gc);
self.allow_layout_if_necessary();
}
/// Block layout for this `Window` until parsing is done. If parsing takes a long time,
@ -2392,7 +2362,7 @@ impl Window {
/// Inform the [`Window`] that layout is allowed either because `load` has happened
/// or because parsing the `<body>` took so long that we cannot wait any longer.
pub(crate) fn allow_layout_if_necessary(&self, can_gc: CanGc) {
pub(crate) fn allow_layout_if_necessary(&self) {
if matches!(
self.layout_blocker.get(),
LayoutBlocker::FiredLoadEventOrParsingTimerExpired
@ -2414,7 +2384,7 @@ impl Window {
// iframe size updates.
//
// See <https://github.com/servo/servo/issues/14719>
self.Document().update_the_rendering(can_gc);
self.Document().update_the_rendering();
}
pub(crate) fn layout_blocked(&self) -> bool {
@ -2439,17 +2409,16 @@ impl Window {
let _ = receiver.recv();
}
pub(crate) fn layout_reflow(&self, query_msg: QueryMsg, can_gc: CanGc) -> bool {
self.reflow(ReflowGoal::LayoutQuery(query_msg), can_gc)
pub(crate) fn layout_reflow(&self, query_msg: QueryMsg) -> bool {
self.reflow(ReflowGoal::LayoutQuery(query_msg))
}
pub(crate) fn resolved_font_style_query(
&self,
node: &Node,
value: String,
can_gc: CanGc,
) -> Option<ServoArc<Font>> {
self.layout_reflow(QueryMsg::ResolvedFontStyleQuery, can_gc);
self.layout_reflow(QueryMsg::ResolvedFontStyleQuery);
let document = self.Document();
let animations = document.animations().sets.clone();
@ -2468,20 +2437,20 @@ impl Window {
.query_content_box(node.to_trusted_node_address())
}
pub(crate) fn content_box_query(&self, node: &Node, can_gc: CanGc) -> Option<UntypedRect<Au>> {
self.layout_reflow(QueryMsg::ContentBox, can_gc);
pub(crate) fn content_box_query(&self, node: &Node) -> Option<UntypedRect<Au>> {
self.layout_reflow(QueryMsg::ContentBox);
self.content_box_query_unchecked(node)
}
pub(crate) fn content_boxes_query(&self, node: &Node, can_gc: CanGc) -> Vec<UntypedRect<Au>> {
self.layout_reflow(QueryMsg::ContentBoxes, can_gc);
pub(crate) fn content_boxes_query(&self, node: &Node) -> Vec<UntypedRect<Au>> {
self.layout_reflow(QueryMsg::ContentBoxes);
self.layout
.borrow()
.query_content_boxes(node.to_trusted_node_address())
}
pub(crate) fn client_rect_query(&self, node: &Node, can_gc: CanGc) -> UntypedRect<i32> {
self.layout_reflow(QueryMsg::ClientRectQuery, can_gc);
pub(crate) fn client_rect_query(&self, node: &Node) -> UntypedRect<i32> {
self.layout_reflow(QueryMsg::ClientRectQuery);
self.layout
.borrow()
.query_client_rect(node.to_trusted_node_address())
@ -2489,35 +2458,26 @@ impl Window {
/// Find the scroll area of the given node, if it is not None. If the node
/// is None, find the scroll area of the viewport.
pub(crate) fn scrolling_area_query(
&self,
node: Option<&Node>,
can_gc: CanGc,
) -> UntypedRect<i32> {
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery, can_gc);
pub(crate) fn scrolling_area_query(&self, node: Option<&Node>) -> UntypedRect<i32> {
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery);
self.layout
.borrow()
.query_scrolling_area(node.map(Node::to_trusted_node_address))
}
pub(crate) fn scroll_offset_query(
&self,
node: &Node,
can_gc: CanGc,
) -> Vector2D<f32, LayoutPixel> {
pub(crate) fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32, LayoutPixel> {
let external_scroll_id = ExternalScrollId(
combine_id_with_fragment_type(node.to_opaque().id(), FragmentType::FragmentBody),
self.pipeline_id().into(),
);
self.scroll_offset_query_with_external_scroll_id(external_scroll_id, can_gc)
self.scroll_offset_query_with_external_scroll_id(external_scroll_id)
}
fn scroll_offset_query_with_external_scroll_id(
&self,
external_scroll_id: ExternalScrollId,
can_gc: CanGc,
) -> Vector2D<f32, LayoutPixel> {
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery, can_gc);
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery);
self.layout
.borrow()
.scroll_offset(external_scroll_id)
@ -2525,14 +2485,7 @@ impl Window {
}
// https://drafts.csswg.org/cssom-view/#element-scrolling-members
pub(crate) fn scroll_node(
&self,
node: &Node,
x_: f64,
y_: f64,
behavior: ScrollBehavior,
can_gc: CanGc,
) {
pub(crate) fn scroll_node(&self, node: &Node, x_: f64, y_: f64, behavior: ScrollBehavior) {
let scroll_id = ExternalScrollId(
combine_id_with_fragment_type(node.to_opaque().id(), FragmentType::FragmentBody),
self.pipeline_id().into(),
@ -2545,7 +2498,6 @@ impl Window {
scroll_id,
behavior,
None,
can_gc,
);
}
@ -2554,9 +2506,8 @@ impl Window {
element: TrustedNodeAddress,
pseudo: Option<PseudoElement>,
property: PropertyId,
can_gc: CanGc,
) -> DOMString {
self.layout_reflow(QueryMsg::ResolvedStyleQuery, can_gc);
self.layout_reflow(QueryMsg::ResolvedStyleQuery);
let document = self.Document();
let animations = document.animations().sets.clone();
@ -2575,10 +2526,9 @@ impl Window {
pub(crate) fn get_iframe_viewport_details_if_known(
&self,
browsing_context_id: BrowsingContextId,
can_gc: CanGc,
) -> Option<ViewportDetails> {
// Reflow might fail, but do a best effort to return the right size.
self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery, can_gc);
self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery);
self.Document()
.iframes()
.get(browsing_context_id)
@ -2589,9 +2539,8 @@ impl Window {
pub(crate) fn offset_parent_query(
&self,
node: &Node,
can_gc: CanGc,
) -> (Option<DomRoot<Element>>, UntypedRect<Au>) {
self.layout_reflow(QueryMsg::OffsetParentQuery, can_gc);
self.layout_reflow(QueryMsg::OffsetParentQuery);
let response = self
.layout
.borrow()
@ -2607,9 +2556,8 @@ impl Window {
&self,
node: &Node,
point_in_node: UntypedPoint2D<f32>,
can_gc: CanGc,
) -> Option<usize> {
self.layout_reflow(QueryMsg::TextIndexQuery, can_gc);
self.layout_reflow(QueryMsg::TextIndexQuery);
self.layout
.borrow()
.query_text_indext(node.to_opaque(), point_in_node)

View file

@ -1359,7 +1359,7 @@ impl ScriptThread {
// > Step 22: For each doc of docs, update the rendering or user interface of
// > doc and its node navigable to reflect the current state.
saw_any_reflows = document.update_the_rendering(can_gc) || saw_any_reflows;
saw_any_reflows = document.update_the_rendering() || saw_any_reflows;
// TODO: Process top layer removals according to
// https://drafts.csswg.org/css-position-4/#process-top-layer-removals.
@ -1437,15 +1437,15 @@ impl ScriptThread {
);
}
fn maybe_send_idle_document_state_to_constellation(&self) {
if !opts::get().wait_for_stable_image {
return;
}
fn maybe_send_document_state_messages(&self, can_gc: CanGc) {
let waiting_for_stable_image = opts::get().wait_for_stable_image;
for (_, document) in self.documents.borrow().iter() {
document
.window()
.maybe_send_idle_document_state_to_constellation();
if waiting_for_stable_image {
document
.window()
.maybe_send_idle_document_state_to_constellation();
}
document.maybe_send_document_fonts_ready_message(can_gc);
}
}
@ -1659,7 +1659,7 @@ impl ScriptThread {
}
self.maybe_schedule_rendering_opportunity_after_ipc_message(can_gc);
self.maybe_send_idle_document_state_to_constellation();
self.maybe_send_document_state_messages(can_gc);
true
}