fix: root element not establishing stacking context (#35390) (#36174)

- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #35390 
- [X] There are tests for these changes

[Successful WPT
run](1409767962)
(which includes the new test files)

(I didn't make the formatting changes intentionally--those came from
`mach format` following `mach test-tidy`.)

---------

Signed-off-by: Michael Rees <mrees@noeontheend.com>
This commit is contained in:
Michael Rees 2025-04-03 12:30:42 -05:00 committed by GitHub
parent f29c182929
commit dfcd9de138
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 53 additions and 0 deletions

View file

@ -105,6 +105,7 @@ where
if element.is_body_element_of_html_element_root() { if element.is_body_element_of_html_element_root() {
flags.insert(FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT); flags.insert(FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT);
} }
match element.get_local_name() { match element.get_local_name() {
&local_name!("br") => { &local_name!("br") => {
flags.insert(FragmentFlags::IS_BR_ELEMENT); flags.insert(FragmentFlags::IS_BR_ELEMENT);
@ -123,6 +124,10 @@ where
) { ) {
flags.insert(FragmentFlags::IS_TEXT_CONTROL); flags.insert(FragmentFlags::IS_TEXT_CONTROL);
} }
if ThreadSafeLayoutElement::is_root(&element) {
flags.insert(FragmentFlags::IS_ROOT_ELEMENT);
}
}; };
Self { Self {

View file

@ -102,6 +102,8 @@ bitflags! {
/// and the fragment can be a flex item. This flag is used to cache items during flex /// and the fragment can be a flex item. This flag is used to cache items during flex
/// layout. /// layout.
const SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM = 1 << 8; const SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM = 1 << 8;
/// Whether or not the node that created this fragment is the root element.
const IS_ROOT_ELEMENT = 1 << 9;
} }
} }

View file

@ -746,6 +746,12 @@ impl ComputedValuesExt for ComputedValues {
return true; return true;
} }
// From https://www.w3.org/TR/CSS22/visuren.html#z-index:
// > The root element forms the root stacking context.
if fragment_flags.contains(FragmentFlags::IS_ROOT_ELEMENT) {
return true;
}
// TODO: We need to handle CSS Contain here. // TODO: We need to handle CSS Contain here.
false false
} }

View file

@ -868,6 +868,10 @@ impl<'dom> ThreadSafeLayoutElement<'dom> for ServoThreadSafeLayoutElement<'dom>
fn is_body_element_of_html_element_root(&self) -> bool { fn is_body_element_of_html_element_root(&self) -> bool {
self.element.is_html_document_body_element() self.element.is_html_document_body_element()
} }
fn is_root(&self) -> bool {
self.element.is_root()
}
} }
/// This implementation of `::selectors::Element` is used for implementing lazy /// This implementation of `::selectors::Element` is used for implementing lazy

View file

@ -390,4 +390,10 @@ pub trait ThreadSafeLayoutElement<'dom>:
/// of the parent data is fine, since the bottom-up traversal will not process /// of the parent data is fine, since the bottom-up traversal will not process
/// the parent until all the children have been processed. /// the parent until all the children have been processed.
fn is_body_element_of_html_element_root(&self) -> bool; fn is_body_element_of_html_element_root(&self) -> bool;
/// Returns whether this node is the root element in an HTML document element.
///
/// Note that, like `Self::is_body_element_of_html_element_root`, this accesses the parent.
/// As in that case, since this is an immutable borrow, we do not violate thread safety.
fn is_root(&self) -> bool;
} }

View file

@ -102180,6 +102180,19 @@
{} {}
] ]
], ],
"root-element-creates-stacking-context.html": [
"be7b027ee791d8d83d6fcecae60654eb22ff960c",
[
null,
[
[
"/css/CSS2/stacking-context/root-element-creates-stacking-context-ref.html",
"=="
]
],
{}
]
],
"zindex-affects-block-in-inline.html": [ "zindex-affects-block-in-inline.html": [
"5a5c9e3dcca6171910f85790e13dc754acda58e0", "5a5c9e3dcca6171910f85790e13dc754acda58e0",
[ [
@ -405642,6 +405655,10 @@
"65138c9a66713e1ed8c2f649751deb1ceb22eac3", "65138c9a66713e1ed8c2f649751deb1ceb22eac3",
[] []
], ],
"root-element-creates-stacking-context-ref.html": [
"9bb42041498c4a5b2b86e6b282ec49e603a0880b",
[]
],
"zindex-affects-block-in-inline-ref.html": [ "zindex-affects-block-in-inline-ref.html": [
"c0fdb338d08198cfd058ccdabd7766a9e57375fd", "c0fdb338d08198cfd058ccdabd7766a9e57375fd",
[] []

View file

@ -0,0 +1,4 @@
<!DOCTYPE html>
<body style="width: 100px; margin: 0">
<div style="height: 100px; background: green"></div>
</body>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html style="width: 0; height: 0; border: 50px solid red">
<link rel="help" href="https://drafts.csswg.org/css2/#stacking-context">
<link rel="match" href="root-element-creates-stacking-context-ref.html">
<link rel="author" title="Michael Rees" href="mailto:mrees@noeontheend.com">
<meta name="assert" content="root element forms the root stacking context">
<body style="border: 50px solid green; margin: -50px; position: relative; z-index: -1">
</body>
</html>