layout: Use ServoLayoutNode directly instead of a generic impl (#36876)

This makes it so that layout is no longer generic on the node type,
depending directly on `script`'s `ServoLayoutNode`. In addition to
greatly simplifying layout, this is necessary because incremental layout
needs to be able to create pseudo-element styles without having a handle
on the original `impl LayoutNode`. We feel this is a reasonable
tradeoff.

Testing: No functional changes, so covered by existing WPT 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-05-06 16:27:51 +02:00 committed by GitHub
parent 51b95a6246
commit d5e008fd6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 217 additions and 309 deletions

View file

@ -12,7 +12,7 @@ use style::selector_parser::PseudoElement;
use crate::PropagatedBoxTreeData;
use crate::context::LayoutContext;
use crate::dom::{BoxSlot, NodeExt};
use crate::dom::BoxSlot;
use crate::dom_traversal::{Contents, NodeAndStyleInfo, TraversalHandler};
use crate::flow::inline::construct::InlineFormattingContextBuilder;
use crate::flow::{BlockContainer, BlockFormattingContext};
@ -24,32 +24,32 @@ use crate::layout_box_base::LayoutBoxBase;
use crate::style_ext::DisplayGeneratingBox;
/// A builder used for both flex and grid containers.
pub(crate) struct ModernContainerBuilder<'a, 'dom, Node> {
pub(crate) struct ModernContainerBuilder<'a, 'dom> {
context: &'a LayoutContext<'a>,
info: &'a NodeAndStyleInfo<Node>,
info: &'a NodeAndStyleInfo<'dom>,
propagated_data: PropagatedBoxTreeData,
contiguous_text_runs: Vec<ModernContainerTextRun<'dom, Node>>,
contiguous_text_runs: Vec<ModernContainerTextRun<'dom>>,
/// To be run in parallel with rayon in `finish`
jobs: Vec<ModernContainerJob<'dom, Node>>,
jobs: Vec<ModernContainerJob<'dom>>,
has_text_runs: bool,
}
enum ModernContainerJob<'dom, Node> {
enum ModernContainerJob<'dom> {
ElementOrPseudoElement {
info: NodeAndStyleInfo<Node>,
info: NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
},
TextRuns(Vec<ModernContainerTextRun<'dom, Node>>),
TextRuns(Vec<ModernContainerTextRun<'dom>>),
}
struct ModernContainerTextRun<'dom, Node> {
info: NodeAndStyleInfo<Node>,
struct ModernContainerTextRun<'dom> {
info: NodeAndStyleInfo<'dom>,
text: Cow<'dom, str>,
}
impl<Node> ModernContainerTextRun<'_, Node> {
impl ModernContainerTextRun<'_> {
/// <https://drafts.csswg.org/css-text/#white-space>
fn is_only_document_white_space(&self) -> bool {
// FIXME: is this the right definition? See
@ -73,11 +73,8 @@ pub(crate) struct ModernItem<'dom> {
pub formatting_context: IndependentFormattingContext,
}
impl<'dom, Node: 'dom> TraversalHandler<'dom, Node> for ModernContainerBuilder<'_, 'dom, Node>
where
Node: NodeExt<'dom>,
{
fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>) {
impl<'dom> TraversalHandler<'dom> for ModernContainerBuilder<'_, 'dom> {
fn handle_text(&mut self, info: &NodeAndStyleInfo<'dom>, text: Cow<'dom, str>) {
self.contiguous_text_runs.push(ModernContainerTextRun {
info: info.clone(),
text,
@ -87,7 +84,7 @@ where
/// Or pseudo-element
fn handle_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -103,13 +100,10 @@ where
}
}
impl<'a, 'dom, Node: 'dom> ModernContainerBuilder<'a, 'dom, Node>
where
Node: NodeExt<'dom>,
{
impl<'a, 'dom> ModernContainerBuilder<'a, 'dom> {
pub fn new(
context: &'a LayoutContext<'a>,
info: &'a NodeAndStyleInfo<Node>,
info: &'a NodeAndStyleInfo<'dom>,
propagated_data: PropagatedBoxTreeData,
) -> Self {
ModernContainerBuilder {
@ -165,7 +159,7 @@ where
let block_formatting_context = BlockFormattingContext::from_block_container(
BlockContainer::InlineFormattingContext(inline_formatting_context),
);
let info: &NodeAndStyleInfo<_> = &*anonymous_info;
let info: &NodeAndStyleInfo = &anonymous_info;
let formatting_context = IndependentFormattingContext {
base: LayoutBoxBase::new(info.into(), info.style.clone()),
contents: IndependentFormattingContextContents::NonReplaced(

View file

@ -11,6 +11,7 @@ use base::id::{BrowsingContextId, PipelineId};
use html5ever::{local_name, ns};
use malloc_size_of_derive::MallocSizeOf;
use pixels::Image;
use script::layout_dom::ServoLayoutNode;
use script_layout_interface::wrapper_traits::{
LayoutDataTrait, LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
};
@ -158,34 +159,31 @@ impl Drop for BoxSlot<'_> {
}
}
pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> {
pub(crate) trait NodeExt<'dom> {
/// Returns the image if its loaded, and its size in image pixels
/// adjusted for `image_density`.
fn as_image(self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)>;
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>;
fn as_video(self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)>;
fn as_typeless_object_with_data_attribute(self) -> Option<String>;
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>;
fn as_image(&self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)>;
fn as_canvas(&self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
fn as_iframe(&self) -> Option<(PipelineId, BrowsingContextId)>;
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)>;
fn as_typeless_object_with_data_attribute(&self) -> Option<String>;
fn style(&self, context: &LayoutContext) -> ServoArc<ComputedValues>;
fn layout_data_mut(self) -> AtomicRefMut<'dom, InnerDOMLayoutData>;
fn layout_data(self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>>;
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData>;
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>>;
fn element_box_slot(&self) -> BoxSlot<'dom>;
fn pseudo_element_box_slot(&self, which: PseudoElement) -> BoxSlot<'dom>;
fn unset_pseudo_element_box(self, which: PseudoElement);
fn unset_pseudo_element_box(&self, which: PseudoElement);
/// Remove boxes for the element itself, and its `:before` and `:after` if any.
fn unset_all_boxes(self);
fn unset_all_boxes(&self);
fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment>;
fn invalidate_cached_fragment(self);
fn invalidate_cached_fragment(&self);
}
impl<'dom, LayoutNodeType> NodeExt<'dom> for LayoutNodeType
where
LayoutNodeType: 'dom + LayoutNode<'dom>,
{
fn as_image(self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)> {
impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
fn as_image(&self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)> {
let node = self.to_threadsafe();
let (resource, metadata) = node.image_data()?;
let (width, height) = resource
@ -201,7 +199,7 @@ where
Some((resource, PhysicalSize::new(width, height)))
}
fn as_video(self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)> {
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)> {
let node = self.to_threadsafe();
let data = node.media_data()?;
let natural_size = if let Some(frame) = data.current_frame {
@ -216,7 +214,7 @@ where
))
}
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
fn as_canvas(&self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
let node = self.to_threadsafe();
let canvas_data = node.canvas_data()?;
let source = canvas_data.source;
@ -226,7 +224,7 @@ where
))
}
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)> {
fn as_iframe(&self) -> Option<(PipelineId, BrowsingContextId)> {
let node = self.to_threadsafe();
match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) {
(Some(pipeline_id), Some(browsing_context_id)) => {
@ -236,8 +234,10 @@ where
}
}
fn as_typeless_object_with_data_attribute(self) -> Option<String> {
if self.type_id() != ScriptLayoutNodeType::Element(LayoutElementType::HTMLObjectElement) {
fn as_typeless_object_with_data_attribute(&self) -> Option<String> {
if LayoutNode::type_id(self) !=
ScriptLayoutNodeType::Element(LayoutElementType::HTMLObjectElement)
{
return None;
}
@ -253,15 +253,15 @@ where
.map(|string| string.to_owned())
}
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues> {
fn style(&self, context: &LayoutContext) -> ServoArc<ComputedValues> {
self.to_threadsafe().style(context.shared_context())
}
fn layout_data_mut(self) -> AtomicRefMut<'dom, InnerDOMLayoutData> {
if LayoutNode::layout_data(&self).is_none() {
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData> {
if LayoutNode::layout_data(self).is_none() {
self.initialize_layout_data::<DOMLayoutData>();
}
LayoutNode::layout_data(&self)
LayoutNode::layout_data(self)
.unwrap()
.as_any()
.downcast_ref::<DOMLayoutData>()
@ -270,8 +270,8 @@ where
.borrow_mut()
}
fn layout_data(self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>> {
LayoutNode::layout_data(&self).map(|data| {
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>> {
LayoutNode::layout_data(self).map(|data| {
data.as_any()
.downcast_ref::<DOMLayoutData>()
.unwrap()
@ -298,7 +298,7 @@ where
BoxSlot::new(cell.clone())
}
fn unset_pseudo_element_box(self, pseudo_element_type: PseudoElement) {
fn unset_pseudo_element_box(&self, pseudo_element_type: PseudoElement) {
let data = self.layout_data_mut();
let cell = match pseudo_element_type {
PseudoElement::Before => &data.pseudo_before_box,
@ -312,7 +312,7 @@ where
*cell.borrow_mut() = None;
}
fn unset_all_boxes(self) {
fn unset_all_boxes(&self) {
let data = self.layout_data_mut();
*data.self_box.borrow_mut() = None;
*data.pseudo_before_box.borrow_mut() = None;
@ -322,7 +322,7 @@ where
// for DOM descendants of elements with `display: none`.
}
fn invalidate_cached_fragment(self) {
fn invalidate_cached_fragment(&self) {
let data = self.layout_data_mut();
if let Some(data) = data.self_box.borrow_mut().as_mut() {
data.invalidate_cached_fragment();
@ -330,7 +330,7 @@ where
}
fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment> {
NodeExt::layout_data(*self)
NodeExt::layout_data(self)
.and_then(|layout_data| {
layout_data
.for_pseudo(pseudo_element)

View file

@ -8,11 +8,14 @@ use std::iter::FusedIterator;
use fonts::ByteIndex;
use html5ever::{LocalName, local_name};
use range::Range;
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script::layout_dom::ServoLayoutNode;
use script_layout_interface::wrapper_traits::{
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
};
use script_layout_interface::{LayoutElementType, LayoutNodeType};
use selectors::Element as SelectorsElement;
use servo_arc::Arc as ServoArc;
use style::dom::{TElement, TShadowRoot};
use style::dom::{NodeInfo, TElement, TNode, TShadowRoot};
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
use style::values::generics::counters::{Content, ContentItem};
@ -28,15 +31,15 @@ use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOuts
/// A data structure used to pass and store related layout information together to
/// avoid having to repeat the same arguments in argument lists.
#[derive(Clone)]
pub(crate) struct NodeAndStyleInfo<Node> {
pub node: Node,
pub(crate) struct NodeAndStyleInfo<'dom> {
pub node: ServoLayoutNode<'dom>,
pub pseudo_element_type: Option<PseudoElement>,
pub style: ServoArc<ComputedValues>,
}
impl<'dom, Node: NodeExt<'dom>> NodeAndStyleInfo<Node> {
impl<'dom> NodeAndStyleInfo<'dom> {
fn new_with_pseudo(
node: Node,
node: ServoLayoutNode<'dom>,
pseudo_element_type: PseudoElement,
style: ServoArc<ComputedValues>,
) -> Self {
@ -47,7 +50,7 @@ impl<'dom, Node: NodeExt<'dom>> NodeAndStyleInfo<Node> {
}
}
pub(crate) fn new(node: Node, style: ServoArc<ComputedValues>) -> Self {
pub(crate) fn new(node: ServoLayoutNode<'dom>, style: ServoArc<ComputedValues>) -> Self {
Self {
node,
pseudo_element_type: None,
@ -86,11 +89,8 @@ impl<'dom, Node: NodeExt<'dom>> NodeAndStyleInfo<Node> {
}
}
impl<'dom, Node> From<&NodeAndStyleInfo<Node>> for BaseFragmentInfo
where
Node: NodeExt<'dom>,
{
fn from(info: &NodeAndStyleInfo<Node>) -> Self {
impl<'dom> From<&NodeAndStyleInfo<'dom>> for BaseFragmentInfo {
fn from(info: &NodeAndStyleInfo<'dom>) -> Self {
let node = info.node;
let pseudo = info.pseudo_element_type;
let threadsafe_node = node.to_threadsafe();
@ -174,29 +174,24 @@ pub(super) enum PseudoElementContentItem {
Replaced(ReplacedContents),
}
pub(super) trait TraversalHandler<'dom, Node>
where
Node: 'dom,
{
fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>);
pub(super) trait TraversalHandler<'dom> {
fn handle_text(&mut self, info: &NodeAndStyleInfo<'dom>, text: Cow<'dom, str>);
/// Or pseudo-element
fn handle_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
);
}
fn traverse_children_of<'dom, Node>(
parent_element: Node,
fn traverse_children_of<'dom>(
parent_element: ServoLayoutNode<'dom>,
context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
handler: &mut impl TraversalHandler<'dom>,
) {
traverse_eager_pseudo_element(PseudoElement::Before, parent_element, context, handler);
let is_text_input_element = matches!(
@ -240,13 +235,11 @@ fn traverse_children_of<'dom, Node>(
traverse_eager_pseudo_element(PseudoElement::After, parent_element, context, handler);
}
fn traverse_element<'dom, Node>(
element: Node,
fn traverse_element<'dom>(
element: ServoLayoutNode<'dom>,
context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
handler: &mut impl TraversalHandler<'dom>,
) {
// Clear any existing pseudo-element box slot, because markers are not handled like
// `::before`` and `::after`. They are processed during box tree creation.
element.unset_pseudo_element_box(PseudoElement::Marker);
@ -286,14 +279,12 @@ fn traverse_element<'dom, Node>(
}
}
fn traverse_eager_pseudo_element<'dom, Node>(
fn traverse_eager_pseudo_element<'dom>(
pseudo_element_type: PseudoElement,
node: Node,
node: ServoLayoutNode<'dom>,
context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
handler: &mut impl TraversalHandler<'dom>,
) {
assert!(pseudo_element_type.is_eager());
// First clear any old contents from the node.
@ -329,14 +320,12 @@ fn traverse_eager_pseudo_element<'dom, Node>(
}
}
fn traverse_pseudo_element_contents<'dom, Node>(
info: &NodeAndStyleInfo<Node>,
fn traverse_pseudo_element_contents<'dom>(
info: &NodeAndStyleInfo<'dom>,
context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom, Node>,
handler: &mut impl TraversalHandler<'dom>,
items: Vec<PseudoElementContentItem>,
) where
Node: NodeExt<'dom>,
{
) {
let mut anonymous_info = None;
for item in items {
match item {
@ -396,14 +385,12 @@ impl std::convert::TryFrom<Contents> for NonReplacedContents {
}
impl NonReplacedContents {
pub(crate) fn traverse<'dom, Node>(
pub(crate) fn traverse<'dom>(
self,
context: &LayoutContext,
info: &NodeAndStyleInfo<Node>,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
info: &NodeAndStyleInfo<'dom>,
handler: &mut impl TraversalHandler<'dom>,
) {
match self {
NonReplacedContents::OfElement | NonReplacedContents::OfTextControl => {
traverse_children_of(info.node, context, handler)
@ -427,14 +414,11 @@ where
}
/// <https://www.w3.org/TR/CSS2/generate.html#propdef-content>
fn generate_pseudo_element_content<'dom, Node>(
fn generate_pseudo_element_content(
pseudo_element_style: &ComputedValues,
element: Node,
element: ServoLayoutNode<'_>,
context: &LayoutContext,
) -> Vec<PseudoElementContentItem>
where
Node: NodeExt<'dom>,
{
) -> Vec<PseudoElementContentItem> {
match &pseudo_element_style.get_counters().content {
Content::Items(items) => {
let mut vec = vec![];
@ -517,18 +501,14 @@ where
}
}
pub enum ChildNodeIterator<Node> {
pub enum ChildNodeIterator<'dom> {
/// Iterating over the children of a node
Node(Option<Node>),
Node(Option<ServoLayoutNode<'dom>>),
/// Iterating over the assigned nodes of a `HTMLSlotElement`
Slottables(<Vec<Node> as IntoIterator>::IntoIter),
Slottables(<Vec<ServoLayoutNode<'dom>> as IntoIterator>::IntoIter),
}
#[allow(clippy::unnecessary_to_owned)] // Clippy is wrong.
pub(crate) fn iter_child_nodes<'dom, Node>(parent: Node) -> ChildNodeIterator<Node>
where
Node: NodeExt<'dom>,
{
pub(crate) fn iter_child_nodes(parent: ServoLayoutNode<'_>) -> ChildNodeIterator<'_> {
if let Some(element) = parent.as_element() {
if let Some(shadow) = element.shadow_root() {
return iter_child_nodes(shadow.as_node());
@ -536,6 +516,7 @@ where
let slotted_nodes = element.slotted_nodes();
if !slotted_nodes.is_empty() {
#[allow(clippy::unnecessary_to_owned)] // Clippy is wrong.
return ChildNodeIterator::Slottables(slotted_nodes.to_owned().into_iter());
}
}
@ -544,11 +525,8 @@ where
ChildNodeIterator::Node(first)
}
impl<'dom, Node> Iterator for ChildNodeIterator<Node>
where
Node: NodeExt<'dom>,
{
type Item = Node;
impl<'dom> Iterator for ChildNodeIterator<'dom> {
type Item = ServoLayoutNode<'dom>;
fn next(&mut self) -> Option<Self::Item> {
match self {
@ -562,4 +540,4 @@ where
}
}
impl<'dom, Node> FusedIterator for ChildNodeIterator<Node> where Node: NodeExt<'dom> {}
impl FusedIterator for ChildNodeIterator<'_> {}

View file

@ -17,7 +17,7 @@ use crate::PropagatedBoxTreeData;
use crate::cell::ArcRefCell;
use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
use crate::context::LayoutContext;
use crate::dom::{LayoutBox, NodeExt};
use crate::dom::LayoutBox;
use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::{BaseFragmentInfo, Fragment};
@ -98,9 +98,9 @@ pub(crate) struct FlexContainer {
}
impl FlexContainer {
pub fn construct<'dom>(
pub fn construct(
context: &LayoutContext,
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
info: &NodeAndStyleInfo<'_>,
contents: NonReplacedContents,
propagated_data: PropagatedBoxTreeData,
) -> Self {

View file

@ -33,16 +33,13 @@ use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, D
use crate::table::{AnonymousTableContent, Table};
impl BlockFormattingContext {
pub(crate) fn construct<'dom, Node>(
pub(crate) fn construct(
context: &LayoutContext,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'_>,
contents: NonReplacedContents,
propagated_data: PropagatedBoxTreeData,
is_list_item: bool,
) -> Self
where
Node: NodeExt<'dom>,
{
) -> Self {
Self::from_block_container(BlockContainer::construct(
context,
info,
@ -61,8 +58,8 @@ impl BlockFormattingContext {
}
}
struct BlockLevelJob<'dom, Node> {
info: NodeAndStyleInfo<Node>,
struct BlockLevelJob<'dom> {
info: NodeAndStyleInfo<'dom>,
box_slot: BoxSlot<'dom>,
propagated_data: PropagatedBoxTreeData,
kind: BlockLevelCreator,
@ -111,12 +108,12 @@ enum IntermediateBlockContainer {
///
/// This builder starts from the first child of a given DOM node
/// and does a preorder traversal of all of its inclusive siblings.
pub(crate) struct BlockContainerBuilder<'dom, 'style, Node> {
pub(crate) struct BlockContainerBuilder<'dom, 'style> {
context: &'style LayoutContext<'style>,
/// This NodeAndStyleInfo contains the root node, the corresponding pseudo
/// content designator, and the block container style.
info: &'style NodeAndStyleInfo<Node>,
info: &'style NodeAndStyleInfo<'dom>,
/// The list of block-level boxes to be built for the final block container.
///
@ -131,7 +128,7 @@ pub(crate) struct BlockContainerBuilder<'dom, 'style, Node> {
/// doesn't have a next sibling, we either reached the end of the container
/// root or there are ongoing inline-level boxes
/// (see `handle_block_level_element`).
block_level_boxes: Vec<BlockLevelJob<'dom, Node>>,
block_level_boxes: Vec<BlockLevelJob<'dom>>,
/// Whether or not this builder has yet produced a block which would be
/// be considered the first line for the purposes of `text-indent`.
@ -144,25 +141,22 @@ pub(crate) struct BlockContainerBuilder<'dom, 'style, Node> {
/// The [`NodeAndStyleInfo`] to use for anonymous block boxes pushed to the list of
/// block-level boxes, lazily initialized (see `end_ongoing_inline_formatting_context`).
anonymous_box_info: Option<NodeAndStyleInfo<Node>>,
anonymous_box_info: Option<NodeAndStyleInfo<'dom>>,
/// A collection of content that is being added to an anonymous table. This is
/// composed of any sequence of internal table elements or table captions that
/// are found outside of a table.
anonymous_table_content: Vec<AnonymousTableContent<'dom, Node>>,
anonymous_table_content: Vec<AnonymousTableContent<'dom>>,
}
impl BlockContainer {
pub fn construct<'dom, Node>(
pub fn construct(
context: &LayoutContext,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'_>,
contents: NonReplacedContents,
propagated_data: PropagatedBoxTreeData,
is_list_item: bool,
) -> BlockContainer
where
Node: NodeExt<'dom>,
{
) -> BlockContainer {
let mut builder = BlockContainerBuilder::new(context, info, propagated_data);
if is_list_item {
@ -186,13 +180,10 @@ impl BlockContainer {
}
}
impl<'dom, 'style, Node> BlockContainerBuilder<'dom, 'style, Node>
where
Node: NodeExt<'dom>,
{
impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> {
pub(crate) fn new(
context: &'style LayoutContext,
info: &'style NodeAndStyleInfo<Node>,
info: &'style NodeAndStyleInfo<'dom>,
propagated_data: PropagatedBoxTreeData,
) -> Self {
BlockContainerBuilder {
@ -274,7 +265,7 @@ where
false => self.propagated_data,
};
let contents: Vec<AnonymousTableContent<'dom, Node>> =
let contents: Vec<AnonymousTableContent<'dom>> =
self.anonymous_table_content.drain(..).collect();
let last_text = match contents.last() {
Some(AnonymousTableContent::Text(info, text)) => Some((info.clone(), text.clone())),
@ -312,13 +303,10 @@ where
}
}
impl<'dom, Node> TraversalHandler<'dom, Node> for BlockContainerBuilder<'dom, '_, Node>
where
Node: NodeExt<'dom>,
{
impl<'dom> TraversalHandler<'dom> for BlockContainerBuilder<'dom, '_> {
fn handle_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -359,7 +347,7 @@ where
}
}
fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>) {
fn handle_text(&mut self, info: &NodeAndStyleInfo<'dom>, text: Cow<'dom, str>) {
if text.is_empty() {
return;
}
@ -379,14 +367,11 @@ where
}
}
impl<'dom, Node> BlockContainerBuilder<'dom, '_, Node>
where
Node: NodeExt<'dom>,
{
impl<'dom> BlockContainerBuilder<'dom, '_> {
fn handle_list_item_marker_inside(
&mut self,
marker_info: &NodeAndStyleInfo<Node>,
container_info: &NodeAndStyleInfo<Node>,
marker_info: &NodeAndStyleInfo<'dom>,
container_info: &NodeAndStyleInfo<'dom>,
contents: Vec<crate::dom_traversal::PseudoElementContentItem>,
) {
// TODO: We do not currently support saving box slots for ::marker pseudo-elements
@ -411,8 +396,8 @@ where
fn handle_list_item_marker_outside(
&mut self,
marker_info: &NodeAndStyleInfo<Node>,
container_info: &NodeAndStyleInfo<Node>,
marker_info: &NodeAndStyleInfo<'dom>,
container_info: &NodeAndStyleInfo<'dom>,
contents: Vec<crate::dom_traversal::PseudoElementContentItem>,
list_item_style: Arc<ComputedValues>,
) {
@ -439,7 +424,7 @@ where
fn handle_inline_level_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display_inside: DisplayInside,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -497,7 +482,7 @@ where
fn handle_block_level_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display_inside: DisplayInside,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -565,7 +550,7 @@ where
fn handle_absolutely_positioned_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display_inside: DisplayInside,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -597,7 +582,7 @@ where
fn handle_float_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display_inside: DisplayInside,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -670,10 +655,7 @@ where
}
}
impl<'dom, Node> BlockLevelJob<'dom, Node>
where
Node: NodeExt<'dom>,
{
impl BlockLevelJob<'_> {
fn finish(self, context: &LayoutContext) -> ArcRefCell<BlockLevelBox> {
let info = &self.info;
let block_level_box = match self.kind {
@ -747,14 +729,7 @@ where
}
impl IntermediateBlockContainer {
fn finish<'dom, Node>(
self,
context: &LayoutContext,
info: &NodeAndStyleInfo<Node>,
) -> BlockContainer
where
Node: NodeExt<'dom>,
{
fn finish(self, context: &LayoutContext, info: &NodeAndStyleInfo<'_>) -> BlockContainer {
match self {
IntermediateBlockContainer::Deferred {
contents,

View file

@ -22,7 +22,6 @@ use style::properties::ComputedValues;
use style::values::computed::Clear as StyleClear;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::{BoxFragment, CollapsedMargin};
@ -885,9 +884,9 @@ impl FloatBandLink {
impl FloatBox {
/// Creates a new float box.
pub fn construct<'dom>(
pub fn construct(
context: &LayoutContext,
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
info: &NodeAndStyleInfo<'_>,
display_inside: DisplayInside,
contents: Contents,
propagated_data: PropagatedBoxTreeData,

View file

@ -17,7 +17,6 @@ use super::{InlineBox, InlineBoxIdentifier, InlineBoxes, InlineFormattingContext
use crate::PropagatedBoxTreeData;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::NodeAndStyleInfo;
use crate::flow::float::FloatBox;
use crate::formatting_contexts::IndependentFormattingContext;
@ -225,11 +224,7 @@ impl InlineFormattingContextBuilder {
(identifier, block_in_inline_splits)
}
pub(crate) fn push_text<'dom, Node: NodeExt<'dom>>(
&mut self,
text: Cow<'dom, str>,
info: &NodeAndStyleInfo<Node>,
) {
pub(crate) fn push_text<'dom>(&mut self, text: Cow<'dom, str>, info: &NodeAndStyleInfo<'dom>) {
let white_space_collapse = info.style.clone_white_space_collapse();
let collapsed = WhitespaceCollapse::new(
text.chars(),

View file

@ -12,7 +12,6 @@ use super::{InlineContainerState, InlineContainerStateFlags, inline_container_ne
use crate::ContainingBlock;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::NodeAndStyleInfo;
use crate::fragment_tree::BaseFragmentInfo;
use crate::layout_box_base::LayoutBoxBase;
@ -35,7 +34,7 @@ pub(crate) struct InlineBox {
}
impl InlineBox {
pub(crate) fn new<'dom, Node: NodeExt<'dom>>(info: &NodeAndStyleInfo<Node>) -> Self {
pub(crate) fn new(info: &NodeAndStyleInfo) -> Self {
Self {
base: LayoutBoxBase::new(info.into(), info.style.clone()),
// This will be assigned later, when the box is actually added to the IFC.

View file

@ -6,12 +6,13 @@ use app_units::Au;
use atomic_refcell::AtomicRef;
use compositing_traits::display_list::AxesScrollSensitivity;
use malloc_size_of_derive::MallocSizeOf;
use script::layout_dom::ServoLayoutNode;
use script_layout_interface::wrapper_traits::{
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
};
use script_layout_interface::{LayoutElementType, LayoutNodeType};
use servo_arc::Arc;
use style::dom::OpaqueNode;
use style::dom::{NodeInfo, OpaqueNode, TNode};
use style::properties::ComputedValues;
use style::values::computed::Overflow;
use style_traits::CSSPixel;
@ -47,10 +48,7 @@ pub struct BoxTree {
}
impl BoxTree {
pub fn construct<'dom, Node>(context: &LayoutContext, root_element: Node) -> Self
where
Node: 'dom + Copy + LayoutNode<'dom> + Send + Sync,
{
pub fn construct(context: &LayoutContext, root_element: ServoLayoutNode<'_>) -> Self {
let boxes = construct_for_root_element(context, root_element);
// Zero box for `:root { display: none }`, one for the root element otherwise.
@ -129,10 +127,7 @@ impl BoxTree {
/// * how intrinsic content sizes are computed eagerly makes it hard
/// to update those sizes for ancestors of the node from which we
/// made an incremental update.
pub fn update<'dom, Node>(context: &LayoutContext, mut dirty_node: Node) -> bool
where
Node: 'dom + Copy + LayoutNode<'dom> + Send + Sync,
{
pub fn update(context: &LayoutContext, mut dirty_node: ServoLayoutNode<'_>) -> bool {
#[allow(clippy::enum_variant_names)]
enum UpdatePoint {
AbsolutelyPositionedBlockLevelBox(ArcRefCell<BlockLevelBox>),
@ -141,12 +136,9 @@ impl BoxTree {
AbsolutelyPositionedTaffyLevelBox(ArcRefCell<TaffyItemBox>),
}
fn update_point<'dom, Node>(
node: Node,
) -> Option<(Arc<ComputedValues>, DisplayInside, UpdatePoint)>
where
Node: NodeExt<'dom>,
{
fn update_point(
node: ServoLayoutNode<'_>,
) -> Option<(Arc<ComputedValues>, DisplayInside, UpdatePoint)> {
if !node.is_element() {
return None;
}
@ -162,7 +154,7 @@ impl BoxTree {
return None;
}
let layout_data = node.layout_data()?;
let layout_data = NodeExt::layout_data(&node)?;
if layout_data.pseudo_before_box.borrow().is_some() {
return None;
}
@ -301,9 +293,9 @@ impl BoxTree {
}
}
fn construct_for_root_element<'dom>(
fn construct_for_root_element(
context: &LayoutContext,
root_element: impl NodeExt<'dom>,
root_element: ServoLayoutNode<'_>,
) -> Vec<ArcRefCell<BlockLevelBox>> {
let info = NodeAndStyleInfo::new(root_element, root_element.style(context));
let box_style = info.style.get_box();
@ -456,7 +448,7 @@ pub struct CanvasBackground {
}
impl CanvasBackground {
fn for_root_element<'dom>(context: &LayoutContext, root_element: impl NodeExt<'dom>) -> Self {
fn for_root_element(context: &LayoutContext, root_element: ServoLayoutNode<'_>) -> Self {
let root_style = root_element.style(context);
let mut style = root_style;

View file

@ -4,12 +4,12 @@
use app_units::Au;
use malloc_size_of_derive::MallocSizeOf;
use script::layout_dom::ServoLayoutElement;
use servo_arc::Arc;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
use crate::flexbox::FlexContainer;
use crate::flow::BlockFormattingContext;
@ -69,9 +69,9 @@ impl Baselines {
}
impl IndependentFormattingContext {
pub fn construct<'dom, Node: NodeExt<'dom>>(
pub fn construct(
context: &LayoutContext,
node_and_style_info: &NodeAndStyleInfo<Node>,
node_and_style_info: &NodeAndStyleInfo,
display_inside: DisplayInside,
contents: Contents,
propagated_data: PropagatedBoxTreeData,
@ -111,11 +111,11 @@ impl IndependentFormattingContext {
let table_grid_style = context
.shared_context()
.stylist
.style_for_anonymous::<Node::ConcreteElement>(
&context.shared_context().guards,
&PseudoElement::ServoTableGrid,
&node_and_style_info.style,
);
.style_for_anonymous::<ServoLayoutElement>(
&context.shared_context().guards,
&PseudoElement::ServoTableGrid,
&node_and_style_info.style,
);
base_fragment_info.flags.insert(FragmentFlags::DO_NOT_PAINT);
IndependentNonReplacedContents::Table(Table::construct(
context,

View file

@ -7,18 +7,14 @@ use style::properties::style_structs;
use style::values::computed::Image;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::{NodeAndStyleInfo, PseudoElementContentItem};
use crate::replaced::ReplacedContents;
/// <https://drafts.csswg.org/css-lists/#content-property>
pub(crate) fn make_marker<'dom, Node>(
pub(crate) fn make_marker<'dom>(
context: &LayoutContext,
info: &NodeAndStyleInfo<Node>,
) -> Option<(NodeAndStyleInfo<Node>, Vec<PseudoElementContentItem>)>
where
Node: NodeExt<'dom>,
{
info: &NodeAndStyleInfo<'dom>,
) -> Option<(NodeAndStyleInfo<'dom>, Vec<PseudoElementContentItem>)> {
let marker_info = info.pseudo(context, style::selector_parser::PseudoElement::Marker)?;
let style = &marker_info.style;
let list_style = style.get_list();

View file

@ -16,7 +16,6 @@ use style::values::specified::align::AlignFlags;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
use crate::formatting_contexts::{
IndependentFormattingContext, IndependentFormattingContextContents,
@ -57,9 +56,9 @@ impl AbsolutelyPositionedBox {
Self { context }
}
pub fn construct<'dom>(
pub fn construct(
context: &LayoutContext,
node_info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
node_info: &NodeAndStyleInfo,
display_inside: DisplayInside,
contents: Contents,
) -> Self {

View file

@ -9,6 +9,7 @@ use app_units::Au;
use euclid::default::{Point2D, Rect};
use euclid::{SideOffsets2D, Size2D};
use itertools::Itertools;
use script::layout_dom::ServoLayoutNode;
use script_layout_interface::wrapper_traits::{
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
};
@ -20,7 +21,7 @@ use style::computed_values::position::T as Position;
use style::computed_values::visibility::T as Visibility;
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapseValue;
use style::context::{QuirksMode, SharedStyleContext, StyleContext, ThreadLocalStyleContext};
use style::dom::{OpaqueNode, TElement};
use style::dom::{NodeInfo, OpaqueNode, TElement, TNode};
use style::properties::style_structs::Font;
use style::properties::{
ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, PropertyDeclarationId,
@ -46,7 +47,7 @@ use crate::fragment_tree::{
};
use crate::taffy::SpecificTaffyGridInfo;
pub fn process_content_box_request<'dom>(node: impl LayoutNode<'dom> + 'dom) -> Option<Rect<Au>> {
pub fn process_content_box_request(node: ServoLayoutNode<'_>) -> Option<Rect<Au>> {
let rects: Vec<_> = node
.fragments_for_pseudo(None)
.iter()
@ -61,7 +62,7 @@ pub fn process_content_box_request<'dom>(node: impl LayoutNode<'dom> + 'dom) ->
}))
}
pub fn process_content_boxes_request<'dom>(node: impl LayoutNode<'dom> + 'dom) -> Vec<Rect<Au>> {
pub fn process_content_boxes_request(node: ServoLayoutNode<'_>) -> Vec<Rect<Au>> {
node.fragments_for_pseudo(None)
.iter()
.filter_map(Fragment::cumulative_border_box_rect)
@ -69,7 +70,7 @@ pub fn process_content_boxes_request<'dom>(node: impl LayoutNode<'dom> + 'dom) -
.collect()
}
pub fn process_client_rect_request<'dom>(node: impl LayoutNode<'dom> + 'dom) -> Rect<i32> {
pub fn process_client_rect_request(node: ServoLayoutNode<'_>) -> Rect<i32> {
node.fragments_for_pseudo(None)
.first()
.map(Fragment::client_rect)
@ -77,8 +78,8 @@ pub fn process_client_rect_request<'dom>(node: impl LayoutNode<'dom> + 'dom) ->
}
/// <https://drafts.csswg.org/cssom-view/#scrolling-area>
pub fn process_node_scroll_area_request<'dom>(
requested_node: Option<impl LayoutNode<'dom> + 'dom>,
pub fn process_node_scroll_area_request(
requested_node: Option<ServoLayoutNode<'_>>,
fragment_tree: Option<Arc<FragmentTree>>,
) -> Rect<i32> {
let Some(tree) = fragment_tree else {
@ -105,9 +106,9 @@ pub fn process_node_scroll_area_request<'dom>(
/// Return the resolved value of property for a given (pseudo)element.
/// <https://drafts.csswg.org/cssom/#resolved-value>
pub fn process_resolved_style_request<'dom>(
pub fn process_resolved_style_request(
context: &SharedStyleContext,
node: impl LayoutNode<'dom> + 'dom,
node: ServoLayoutNode<'_>,
pseudo: &Option<PseudoElement>,
property: &PropertyId,
) -> String {
@ -361,9 +362,9 @@ fn resolve_grid_template(
}
}
pub fn process_resolved_style_request_for_unstyled_node<'dom>(
pub fn process_resolved_style_request_for_unstyled_node(
context: &SharedStyleContext,
node: impl LayoutNode<'dom>,
node: ServoLayoutNode<'_>,
pseudo: &Option<PseudoElement>,
property: &PropertyId,
) -> String {
@ -434,9 +435,7 @@ struct OffsetParentFragments {
}
/// <https://www.w3.org/TR/2016/WD-cssom-view-1-20160317/#dom-htmlelement-offsetparent>
fn offset_parent_fragments<'dom>(
node: impl LayoutNode<'dom> + 'dom,
) -> Option<OffsetParentFragments> {
fn offset_parent_fragments(node: ServoLayoutNode<'_>) -> Option<OffsetParentFragments> {
// 1. If any of the following holds true return null and terminate this algorithm:
// * The element does not have an associated CSS layout box.
// * The element is the root element.
@ -498,9 +497,7 @@ fn offset_parent_fragments<'dom>(
}
#[inline]
pub fn process_offset_parent_query<'dom>(
node: impl LayoutNode<'dom> + 'dom,
) -> Option<OffsetParentResponse> {
pub fn process_offset_parent_query(node: ServoLayoutNode<'_>) -> Option<OffsetParentResponse> {
// Only consider the first fragment of the node found as per a
// possible interpretation of the specification: "[...] return the
// y-coordinate of the top border edge of the first CSS layout box
@ -580,7 +577,7 @@ pub fn process_offset_parent_query<'dom>(
}
/// <https://html.spec.whatwg.org/multipage/#get-the-text-steps>
pub fn get_the_text_steps<'dom>(node: impl LayoutNode<'dom>) -> String {
pub fn get_the_text_steps(node: ServoLayoutNode<'_>) -> String {
// Step 1: If element is not being rendered or if the user agent is a non-CSS user agent, then
// return element's descendant text content.
// This is taken care of in HTMLElemnent code
@ -668,8 +665,8 @@ impl Default for RenderedTextCollectionState {
}
/// <https://html.spec.whatwg.org/multipage/#rendered-text-collection-steps>
fn rendered_text_collection_steps<'dom>(
node: impl LayoutNode<'dom>,
fn rendered_text_collection_steps(
node: ServoLayoutNode<'_>,
state: &mut RenderedTextCollectionState,
) -> Vec<InnerOrOuterTextItem> {
// Step 1. Let items be the result of running the rendered text collection

View file

@ -13,10 +13,12 @@ use euclid::{Scale, Size2D};
use malloc_size_of_derive::MallocSizeOf;
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
use pixels::Image;
use script::layout_dom::ServoLayoutNode;
use script_layout_interface::IFrameSize;
use servo_arc::Arc as ServoArc;
use style::Zero;
use style::computed_values::object_fit::T as ObjectFit;
use style::dom::TNode;
use style::logical_geometry::{Direction, WritingMode};
use style::properties::ComputedValues;
use style::servo::url::ComputedUrl;
@ -120,7 +122,7 @@ pub(crate) enum ReplacedContentKind {
}
impl ReplacedContents {
pub fn for_element<'dom>(element: impl NodeExt<'dom>, context: &LayoutContext) -> Option<Self> {
pub fn for_element(element: ServoLayoutNode<'_>, context: &LayoutContext) -> Option<Self> {
if let Some(ref data_attribute_string) = element.as_typeless_object_with_data_attribute() {
if let Some(url) = try_to_parse_image_data_url(data_attribute_string) {
return Self::from_image_url(
@ -184,8 +186,8 @@ impl ReplacedContents {
})
}
pub fn from_image_url<'dom>(
element: impl NodeExt<'dom>,
pub fn from_image_url(
element: ServoLayoutNode<'_>,
context: &LayoutContext,
image_url: &ComputedUrl,
) -> Option<Self> {
@ -213,8 +215,8 @@ impl ReplacedContents {
None
}
pub fn from_image<'dom>(
element: impl NodeExt<'dom>,
pub fn from_image(
element: ServoLayoutNode<'_>,
context: &LayoutContext,
image: &ComputedImage,
) -> Option<Self> {

View file

@ -8,7 +8,7 @@ use std::iter::repeat;
use atomic_refcell::AtomicRef;
use log::warn;
use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use servo_arc::Arc;
use style::properties::ComputedValues;
use style::properties::style_structs::Font;
@ -22,7 +22,7 @@ use super::{
use crate::PropagatedBoxTreeData;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::{BoxSlot, LayoutBox, NodeExt};
use crate::dom::{BoxSlot, LayoutBox};
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler};
use crate::flow::{BlockContainerBuilder, BlockFormattingContext};
use crate::formatting_contexts::{
@ -50,17 +50,17 @@ impl ResolvedSlotAndLocation<'_> {
}
}
pub(crate) enum AnonymousTableContent<'dom, Node> {
Text(NodeAndStyleInfo<Node>, Cow<'dom, str>),
pub(crate) enum AnonymousTableContent<'dom> {
Text(NodeAndStyleInfo<'dom>, Cow<'dom, str>),
Element {
info: NodeAndStyleInfo<Node>,
info: NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
},
}
impl<Node> AnonymousTableContent<'_, Node> {
impl AnonymousTableContent<'_> {
fn is_whitespace_only(&self) -> bool {
match self {
Self::Element { .. } => false,
@ -74,9 +74,9 @@ impl<Node> AnonymousTableContent<'_, Node> {
}
impl Table {
pub(crate) fn construct<'dom>(
pub(crate) fn construct(
context: &LayoutContext,
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
info: &NodeAndStyleInfo,
grid_style: Arc<ComputedValues>,
contents: NonReplacedContents,
propagated_data: PropagatedBoxTreeData,
@ -91,15 +91,12 @@ impl Table {
traversal.finish()
}
pub(crate) fn construct_anonymous<'dom, Node>(
pub(crate) fn construct_anonymous<'dom>(
context: &LayoutContext,
parent_info: &NodeAndStyleInfo<Node>,
contents: Vec<AnonymousTableContent<'dom, Node>>,
parent_info: &NodeAndStyleInfo<'dom>,
contents: Vec<AnonymousTableContent<'dom>>,
propagated_data: PropagatedBoxTreeData,
) -> (NodeAndStyleInfo<Node>, IndependentFormattingContext)
where
Node: crate::dom::NodeExt<'dom>,
{
) -> (NodeAndStyleInfo<'dom>, IndependentFormattingContext) {
let table_info = parent_info
.pseudo(context, PseudoElement::ServoAnonymousTable)
.expect("Should never fail to create anonymous table info.");
@ -645,9 +642,9 @@ impl TableBuilder {
}
}
pub(crate) struct TableBuilderTraversal<'style, 'dom, Node> {
pub(crate) struct TableBuilderTraversal<'style, 'dom> {
context: &'style LayoutContext<'style>,
info: &'style NodeAndStyleInfo<Node>,
info: &'style NodeAndStyleInfo<'dom>,
/// The value of the [`PropagatedBoxTreeData`] to use, either for the row group
/// if processing one or for the table itself if outside a row group.
@ -657,19 +654,16 @@ pub(crate) struct TableBuilderTraversal<'style, 'dom, Node> {
/// into another struct so that we can write unit tests against the builder.
builder: TableBuilder,
current_anonymous_row_content: Vec<AnonymousTableContent<'dom, Node>>,
current_anonymous_row_content: Vec<AnonymousTableContent<'dom>>,
/// The index of the current row group, if there is one.
current_row_group_index: Option<usize>,
}
impl<'style, 'dom, Node> TableBuilderTraversal<'style, 'dom, Node>
where
Node: NodeExt<'dom>,
{
impl<'style, 'dom> TableBuilderTraversal<'style, 'dom> {
pub(crate) fn new(
context: &'style LayoutContext<'style>,
info: &'style NodeAndStyleInfo<Node>,
info: &'style NodeAndStyleInfo<'dom>,
grid_style: Arc<ComputedValues>,
propagated_data: PropagatedBoxTreeData,
) -> Self {
@ -745,11 +739,8 @@ where
}
}
impl<'dom, Node: 'dom> TraversalHandler<'dom, Node> for TableBuilderTraversal<'_, 'dom, Node>
where
Node: NodeExt<'dom>,
{
fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>) {
impl<'dom> TraversalHandler<'dom> for TableBuilderTraversal<'_, 'dom> {
fn handle_text(&mut self, info: &NodeAndStyleInfo<'dom>, text: Cow<'dom, str>) {
self.current_anonymous_row_content
.push(AnonymousTableContent::Text(info.clone(), text));
}
@ -757,7 +748,7 @@ where
/// <https://html.spec.whatwg.org/multipage/#forming-a-table>
fn handle_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -916,26 +907,23 @@ where
}
}
struct TableRowBuilder<'style, 'builder, 'dom, 'a, Node> {
table_traversal: &'builder mut TableBuilderTraversal<'style, 'dom, Node>,
struct TableRowBuilder<'style, 'builder, 'dom, 'a> {
table_traversal: &'builder mut TableBuilderTraversal<'style, 'dom>,
/// The [`NodeAndStyleInfo`] of this table row, which we use to
/// construct anonymous table cells.
info: &'a NodeAndStyleInfo<Node>,
info: &'a NodeAndStyleInfo<'dom>,
current_anonymous_cell_content: Vec<AnonymousTableContent<'dom, Node>>,
current_anonymous_cell_content: Vec<AnonymousTableContent<'dom>>,
/// The [`PropagatedBoxTreeData`] to use for all children of this row.
propagated_data: PropagatedBoxTreeData,
}
impl<'style, 'builder, 'dom, 'a, Node: 'dom> TableRowBuilder<'style, 'builder, 'dom, 'a, Node>
where
Node: NodeExt<'dom>,
{
impl<'style, 'builder, 'dom, 'a> TableRowBuilder<'style, 'builder, 'dom, 'a> {
fn new(
table_traversal: &'builder mut TableBuilderTraversal<'style, 'dom, Node>,
info: &'a NodeAndStyleInfo<Node>,
table_traversal: &'builder mut TableBuilderTraversal<'style, 'dom>,
info: &'a NodeAndStyleInfo<'dom>,
propagated_data: PropagatedBoxTreeData,
) -> Self {
table_traversal.builder.start_row();
@ -996,11 +984,8 @@ where
}
}
impl<'dom, Node: 'dom> TraversalHandler<'dom, Node> for TableRowBuilder<'_, '_, 'dom, '_, Node>
where
Node: NodeExt<'dom>,
{
fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>) {
impl<'dom> TraversalHandler<'dom> for TableRowBuilder<'_, '_, 'dom, '_> {
fn handle_text(&mut self, info: &NodeAndStyleInfo<'dom>, text: Cow<'dom, str>) {
self.current_anonymous_cell_content
.push(AnonymousTableContent::Text(info.clone(), text));
}
@ -1008,7 +993,7 @@ where
/// <https://html.spec.whatwg.org/multipage/#algorithm-for-processing-rows>
fn handle_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
@ -1091,14 +1076,11 @@ struct TableColumnGroupBuilder {
columns: Vec<ArcRefCell<TableTrack>>,
}
impl<'dom, Node: 'dom> TraversalHandler<'dom, Node> for TableColumnGroupBuilder
where
Node: NodeExt<'dom>,
{
fn handle_text(&mut self, _info: &NodeAndStyleInfo<Node>, _text: Cow<'dom, str>) {}
impl<'dom> TraversalHandler<'dom> for TableColumnGroupBuilder {
fn handle_text(&mut self, _info: &NodeAndStyleInfo<'dom>, _text: Cow<'dom, str>) {}
fn handle_element(
&mut self,
info: &NodeAndStyleInfo<Node>,
info: &NodeAndStyleInfo<'dom>,
display: DisplayGeneratingBox,
_contents: Contents,
box_slot: BoxSlot<'dom>,
@ -1134,9 +1116,9 @@ impl From<DisplayLayoutInternal> for TableTrackGroupType {
}
}
fn add_column<'dom, Node: NodeExt<'dom>>(
fn add_column(
collection: &mut Vec<ArcRefCell<TableTrack>>,
column_info: &NodeAndStyleInfo<Node>,
column_info: &NodeAndStyleInfo,
group_index: Option<usize>,
is_anonymous: bool,
) -> ArcRefCell<TableTrack> {

View file

@ -15,7 +15,7 @@ use crate::PropagatedBoxTreeData;
use crate::cell::ArcRefCell;
use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
use crate::context::LayoutContext;
use crate::dom::{LayoutBox, NodeExt};
use crate::dom::LayoutBox;
use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::Fragment;
@ -29,9 +29,9 @@ pub(crate) struct TaffyContainer {
}
impl TaffyContainer {
pub fn construct<'dom>(
pub fn construct(
context: &LayoutContext,
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
info: &NodeAndStyleInfo,
contents: NonReplacedContents,
propagated_data: PropagatedBoxTreeData,
) -> Self {