From dfcd9de138ece3c7999c76cd9ba1d170c27af97b Mon Sep 17 00:00:00 2001 From: Michael Rees Date: Thu, 3 Apr 2025 12:30:42 -0500 Subject: [PATCH] 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](https://github.com/reesmichael1/servo/actions/runs/14097679625) (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 --- components/layout_2020/dom_traversal.rs | 5 +++++ .../layout_2020/fragment_tree/base_fragment.rs | 2 ++ components/layout_2020/style_ext.rs | 6 ++++++ components/script/layout_dom/element.rs | 4 ++++ .../shared/script_layout/wrapper_traits.rs | 6 ++++++ tests/wpt/meta/MANIFEST.json | 17 +++++++++++++++++ ...ot-element-creates-stacking-context-ref.html | 4 ++++ .../root-element-creates-stacking-context.html | 9 +++++++++ 8 files changed, 53 insertions(+) create mode 100644 tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context-ref.html create mode 100644 tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context.html diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index 33e500bfe87..bcb6555fd13 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -105,6 +105,7 @@ where if element.is_body_element_of_html_element_root() { flags.insert(FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT); } + match element.get_local_name() { &local_name!("br") => { flags.insert(FragmentFlags::IS_BR_ELEMENT); @@ -123,6 +124,10 @@ where ) { flags.insert(FragmentFlags::IS_TEXT_CONTROL); } + + if ThreadSafeLayoutElement::is_root(&element) { + flags.insert(FragmentFlags::IS_ROOT_ELEMENT); + } }; Self { diff --git a/components/layout_2020/fragment_tree/base_fragment.rs b/components/layout_2020/fragment_tree/base_fragment.rs index 8e529f40ba6..d26ae71264f 100644 --- a/components/layout_2020/fragment_tree/base_fragment.rs +++ b/components/layout_2020/fragment_tree/base_fragment.rs @@ -102,6 +102,8 @@ bitflags! { /// and the fragment can be a flex item. This flag is used to cache items during flex /// layout. 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; } } diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index 4a8d15b9fd3..f3269fb5461 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -746,6 +746,12 @@ impl ComputedValuesExt for ComputedValues { 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. false } diff --git a/components/script/layout_dom/element.rs b/components/script/layout_dom/element.rs index 6a267f16077..85c04039323 100644 --- a/components/script/layout_dom/element.rs +++ b/components/script/layout_dom/element.rs @@ -868,6 +868,10 @@ impl<'dom> ThreadSafeLayoutElement<'dom> for ServoThreadSafeLayoutElement<'dom> fn is_body_element_of_html_element_root(&self) -> bool { 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 diff --git a/components/shared/script_layout/wrapper_traits.rs b/components/shared/script_layout/wrapper_traits.rs index f64ec94a777..3e021052280 100644 --- a/components/shared/script_layout/wrapper_traits.rs +++ b/components/shared/script_layout/wrapper_traits.rs @@ -390,4 +390,10 @@ pub trait ThreadSafeLayoutElement<'dom>: /// of the parent data is fine, since the bottom-up traversal will not process /// the parent until all the children have been processed. 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; } diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 5798aa29c28..70903a3077a 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -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": [ "5a5c9e3dcca6171910f85790e13dc754acda58e0", [ @@ -405642,6 +405655,10 @@ "65138c9a66713e1ed8c2f649751deb1ceb22eac3", [] ], + "root-element-creates-stacking-context-ref.html": [ + "9bb42041498c4a5b2b86e6b282ec49e603a0880b", + [] + ], "zindex-affects-block-in-inline-ref.html": [ "c0fdb338d08198cfd058ccdabd7766a9e57375fd", [] diff --git a/tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context-ref.html b/tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context-ref.html new file mode 100644 index 00000000000..9bb42041498 --- /dev/null +++ b/tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context-ref.html @@ -0,0 +1,4 @@ + + +
+ diff --git a/tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context.html b/tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context.html new file mode 100644 index 00000000000..be7b027ee79 --- /dev/null +++ b/tests/wpt/tests/css/CSS2/stacking-context/root-element-creates-stacking-context.html @@ -0,0 +1,9 @@ + + + + + + + + +