layout: Simplify and generalize the usage of pseudo-elements (#36202)

- Remove the last remaining Servo-specific PseudoElement enum from
  layout. This was made to select `::before` and `::after` (both eager
  pseudo-elements), but now `traverse_pseudo_element` is called
  `traverse_eager_pseudo_element` and should work on any eager pseudo
  element.
- Expose a single way of getting psuedo-element variants of
  ThreadSafeLayoutElement in the Layout DOM, which returns `None` when
  the pseudo-element doesn't apply (not defined for eager
  pseudo-elements or when trying to get `<details>` related
  pseudo-elements on elements that they don't apply to).
- Ensure that NodeAndStyleInfo always refers to a node. This is done by
  making sure that anonymous boxes are all associated with their
  originating node.

These changes are prepatory work for implementation of the `::marker`
pseudo-element as well as ensuring that all anonymous boxes can be
cached into the box tree eventually.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-03-29 13:41:04 +01:00 committed by GitHub
parent c30ad5a30e
commit b5c8164e99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 278 additions and 354 deletions

View file

@ -5,8 +5,10 @@
//! Layout construction code that is shared between modern layout modes (Flexbox and CSS Grid)
use std::borrow::Cow;
use std::sync::LazyLock;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use style::selector_parser::PseudoElement;
use crate::PropagatedBoxTreeData;
use crate::context::LayoutContext;
@ -136,21 +138,11 @@ where
pub(crate) fn finish(mut self) -> Vec<ModernItem<'dom>> {
self.wrap_any_text_in_anonymous_block_container();
let anonymous_style = if self.has_text_runs {
Some(
self.context
.shared_context()
.stylist
.style_for_anonymous::<Node::ConcreteElement>(
&self.context.shared_context().guards,
&style::selector_parser::PseudoElement::ServoAnonymousBox,
&self.info.style,
),
)
} else {
None
};
let anonymous_info = LazyLock::new(|| {
self.info
.pseudo(self.context, PseudoElement::ServoAnonymousBox)
.expect("Should always be able to construct info for anonymous boxes.")
});
let mut children: Vec<ModernItem> = std::mem::take(&mut self.jobs)
.into_par_iter()
.filter_map(|job| match job {
@ -173,7 +165,7 @@ where
let block_formatting_context = BlockFormattingContext::from_block_container(
BlockContainer::InlineFormattingContext(inline_formatting_context),
);
let info = &self.info.new_anonymous(anonymous_style.clone().unwrap());
let info: &NodeAndStyleInfo<_> = &*anonymous_info;
let formatting_context = IndependentFormattingContext {
base: LayoutBoxBase::new(info.into(), info.style.clone()),
contents: IndependentFormattingContextContents::NonReplaced(