Detect body elements during layout

During layout it is often useful, for various specification reasons, to
know if an element is the `<body>` element of an `<html>` element root. There
are a couple places where a brittle heuristic is used to detect `<body>`
elements. This information is going to be even more important to
properly handle `<html>` elements that inherit their overflow property from
their `<body>` children.

Implementing this properly requires updating the DOM wrapper interface.
This check does reach up to the parent of thread-safe nodes, but this is
essentially the same kind of operation that `parent_style()` does, so is
ostensibly safe.

This change should not change any behavior and is just a preparation
step for properly handle `<body>` overflow.
This commit is contained in:
Martin Robinson 2023-04-30 20:21:58 +02:00
parent 77a184a0e7
commit 72302e2dae
26 changed files with 487 additions and 277 deletions

View file

@ -677,18 +677,27 @@ impl Fragment {
let mut restyle_damage = node.restyle_damage();
restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW);
let mut flags = FragmentFlags::empty();
let is_body = node
.as_element()
.map(|element| element.is_body_element_of_html_element_root())
.unwrap_or(false);
if is_body {
flags |= FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT;
}
Fragment {
node: node.opaque(),
style: style,
style,
selected_style: node.selected_style(),
restyle_damage: restyle_damage,
restyle_damage,
border_box: LogicalRect::zero(writing_mode),
border_padding: LogicalMargin::zero(writing_mode),
margin: LogicalMargin::zero(writing_mode),
specific: specific,
specific,
inline_context: None,
pseudo: node.get_pseudo_element_type(),
flags: FragmentFlags::empty(),
flags,
debug_id: DebugId::new(),
stacking_context_id: StackingContextId::root(),
established_reference_frame: None,
@ -3277,16 +3286,24 @@ impl fmt::Debug for Fragment {
"".to_owned()
};
let flags_string = if !self.flags.is_empty() {
format!("\nflags={:?}", self.flags)
} else {
"".to_owned()
};
write!(
f,
"\n{}({}) [{:?}]\nborder_box={:?}{}{}{}",
"\n{}({}) [{:?}]\
\nborder_box={:?}\
{border_padding_string}\
{margin_string}\
{damage_string}\
{flags_string}",
self.specific.get_type(),
self.debug_id,
self.specific,
self.border_box,
border_padding_string,
margin_string,
damage_string
)
}
}
@ -3430,6 +3447,8 @@ bitflags! {
const IS_BLOCK_FLEX_ITEM = 0b0000_0010;
/// Whether this fragment represents the generated text from a text-overflow clip.
const IS_ELLIPSIS = 0b0000_0100;
/// Whether this fragment is for the body element child of a html element root element.
const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 0b0000_1000;
}
}