layout: Use ServoThreadSafeLayoutNode in more places (#38626)

Use `ServoThreadSafeLayoutNode` in more places in layout rather than
`ServoLayoutNode`. The former is meant to be used during layout, but
layout 2020 was written against the latter. In general, this reduces the
amount of conversion to the thread-safe version in many places in
layout.

In addition, an unused iterator from the `script` crate
`ServoThreadSafeLayoutNodeChildrenIterator` is replaced with the child
iterator from `layout`. The `layout` version must be directly in
`script` now as it uses the dangerous variants of `next_sibling` and
`first_child`, which allow encapsulating the unsafe bits into one
module.

This will ultimately be useful for storing the layout data of
pseudo-element children of pseudo-elements properly.

Testing: This should not change any behavior and thus is covered by
existing tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2025-08-13 16:55:19 +02:00 committed by GitHub
parent 20ad1ce84e
commit ee7c1d9109
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 258 additions and 321 deletions

View file

@ -6,9 +6,8 @@ use std::vec::IntoIter;
use app_units::Au;
use fonts::FontMetrics;
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use malloc_size_of_derive::MallocSizeOf;
use script::layout_dom::ServoLayoutNode;
use script::layout_dom::ServoThreadSafeLayoutNode;
use servo_arc::Arc as ServoArc;
use style::properties::ComputedValues;
@ -73,12 +72,12 @@ impl InlineBox {
pub(crate) fn repair_style(
&mut self,
node: &ServoLayoutNode,
node: &ServoThreadSafeLayoutNode,
new_style: &ServoArc<ComputedValues>,
) {
self.base.repair_style(new_style);
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
*self.shared_inline_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
*self.shared_inline_styles.selected.borrow_mut() = node.selected_style();
}
}

View file

@ -83,7 +83,6 @@ use bitflags::bitflags;
use construct::InlineFormattingContextBuilder;
use fonts::{ByteIndex, FontMetrics, GlyphStore};
use inline_box::{InlineBox, InlineBoxContainerState, InlineBoxIdentifier, InlineBoxes};
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use line::{
AbsolutelyPositionedLineItem, AtomicLineItem, FloatLineItem, LineItem, LineItemLayout,
TextRunLineItem,
@ -91,7 +90,7 @@ use line::{
use line_breaker::LineBreaker;
use malloc_size_of_derive::MallocSizeOf;
use range::Range;
use script::layout_dom::ServoLayoutNode;
use script::layout_dom::ServoThreadSafeLayoutNode;
use servo_arc::Arc;
use style::Zero;
use style::computed_values::text_wrap_mode::T as TextWrapMode;
@ -188,7 +187,7 @@ impl From<&NodeAndStyleInfo<'_>> for SharedInlineStyles {
fn from(info: &NodeAndStyleInfo) -> Self {
Self {
style: SharedStyle::new(info.style.clone()),
selected: SharedStyle::new(info.get_selected_style()),
selected: SharedStyle::new(info.node.selected_style()),
}
}
}
@ -222,7 +221,7 @@ impl InlineItem {
pub(crate) fn repair_style(
&self,
context: &SharedStyleContext,
node: &ServoLayoutNode,
node: &ServoThreadSafeLayoutNode,
new_style: &Arc<ComputedValues>,
) {
match self {
@ -1696,9 +1695,13 @@ impl InlineFormattingContext {
}
}
pub(crate) fn repair_style(&self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
pub(crate) fn repair_style(
&self,
node: &ServoThreadSafeLayoutNode,
new_style: &Arc<ComputedValues>,
) {
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
*self.shared_inline_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
*self.shared_inline_styles.selected.borrow_mut() = node.selected_style();
}
pub(super) fn layout(

View file

@ -7,9 +7,10 @@
use app_units::{Au, MAX_AU};
use inline::InlineFormattingContext;
use layout_api::wrapper_traits::ThreadSafeLayoutNode;
use malloc_size_of_derive::MallocSizeOf;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use script::layout_dom::ServoLayoutNode;
use script::layout_dom::ServoThreadSafeLayoutNode;
use servo_arc::Arc;
use style::Zero;
use style::computed_values::clear::T as StyleClear;
@ -23,7 +24,6 @@ use style::values::specified::{Display, TextAlignKeyword};
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::flow::float::{
Clear, ContainingBlockPositionInfo, FloatBox, FloatSide, PlacementAmongFloats,
SequentialLayoutState,
@ -76,7 +76,11 @@ impl BlockContainer {
}
}
pub(crate) fn repair_style(&mut self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
pub(crate) fn repair_style(
&mut self,
node: &ServoThreadSafeLayoutNode,
new_style: &Arc<ComputedValues>,
) {
match self {
BlockContainer::BlockLevelBoxes(..) => {},
BlockContainer::InlineFormattingContext(inline_formatting_context) => {
@ -103,7 +107,7 @@ impl BlockLevelBox {
pub(crate) fn repair_style(
&mut self,
context: &SharedStyleContext,
node: &ServoLayoutNode,
node: &ServoThreadSafeLayoutNode,
new_style: &Arc<ComputedValues>,
) {
self.with_base_mut(|base| {
@ -412,7 +416,7 @@ impl OutsideMarker {
fn repair_style(
&mut self,
context: &SharedStyleContext,
node: &ServoLayoutNode,
node: &ServoThreadSafeLayoutNode,
new_style: &Arc<ComputedValues>,
) {
self.list_item_style = node.style(context);
@ -477,7 +481,11 @@ impl BlockFormattingContext {
LayoutStyle::Default(&base.style)
}
pub(crate) fn repair_style(&mut self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
pub(crate) fn repair_style(
&mut self,
node: &ServoThreadSafeLayoutNode,
new_style: &Arc<ComputedValues>,
) {
self.contents.repair_style(node, new_style);
}
}

View file

@ -10,7 +10,7 @@ use euclid::default::Size2D as UntypedSize2D;
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use layout_api::{LayoutElementType, LayoutNodeType};
use malloc_size_of_derive::MallocSizeOf;
use script::layout_dom::ServoLayoutNode;
use script::layout_dom::{ServoLayoutNode, ServoThreadSafeLayoutNode};
use servo_arc::Arc;
use style::dom::{NodeInfo, TNode};
use style::properties::ComputedValues;
@ -20,7 +20,7 @@ use style_traits::CSSPixel;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::{LayoutBox, NodeExt};
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, iter_child_nodes};
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents};
use crate::flexbox::FlexLevelBox;
use crate::flow::float::FloatBox;
use crate::flow::inline::InlineItem;
@ -47,6 +47,7 @@ pub struct BoxTree {
impl BoxTree {
#[servo_tracing::instrument(name = "Box Tree Construction", skip_all)]
pub(crate) fn construct(context: &LayoutContext, root_element: ServoLayoutNode<'_>) -> Self {
let root_element = root_element.to_threadsafe();
let boxes = construct_for_root_element(context, root_element);
// Zero box for `:root { display: none }`, one for the root element otherwise.
@ -68,9 +69,8 @@ impl BoxTree {
viewport_overflow_y == Overflow::Visible &&
!root_style.get_box().display.is_none()
{
for child in iter_child_nodes(root_element) {
for child in root_element.children() {
if !child
.to_threadsafe()
.as_element()
.is_some_and(|element| element.is_body_element_of_html_element_root())
{
@ -138,7 +138,7 @@ impl BoxTree {
fn construct_for_root_element(
context: &LayoutContext,
root_element: ServoLayoutNode<'_>,
root_element: ServoThreadSafeLayoutNode<'_>,
) -> Vec<ArcRefCell<BlockLevelBox>> {
let info = NodeAndStyleInfo::new(
root_element,
@ -292,7 +292,8 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
}
// Don't update unstyled nodes or nodes that have pseudo-elements.
let element_data = potential_dirty_root_node
let potential_thread_safe_dirty_root_node = potential_dirty_root_node.to_threadsafe();
let element_data = potential_thread_safe_dirty_root_node
.style_data()?
.element_data
.borrow();
@ -300,7 +301,7 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
return None;
}
let layout_data = NodeExt::layout_data(&potential_dirty_root_node)?;
let layout_data = NodeExt::layout_data(&potential_thread_safe_dirty_root_node)?;
if !layout_data.pseudo_boxes.is_empty() {
return None;
}
@ -377,14 +378,12 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
#[servo_tracing::instrument(name = "Box Tree Update From Dirty Root", skip_all)]
fn update_from_dirty_root(&self, context: &LayoutContext) {
let contents = ReplacedContents::for_element(self.node, context)
let node = self.node.to_threadsafe();
let contents = ReplacedContents::for_element(node, context)
.map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced);
let info = NodeAndStyleInfo::new(
self.node,
self.primary_style.clone(),
self.node.take_restyle_damage(),
);
let info =
NodeAndStyleInfo::new(node, self.primary_style.clone(), node.take_restyle_damage());
let out_of_flow_absolutely_positioned_box = ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, self.display_inside, contents),
@ -424,7 +423,7 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
//
// TODO: This isn't going to be good enough for incremental fragment tree
// reconstruction, as fragment tree damage might extend further up the tree.
parent_node.take_restyle_damage();
parent_node.to_threadsafe().take_restyle_damage();
invalidate_start_point = parent_node;
}