aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorMichael Rees <mrees@noeontheend.com>2025-04-03 12:30:42 -0500
committerGitHub <noreply@github.com>2025-04-03 17:30:42 +0000
commitdfcd9de138ece3c7999c76cd9ba1d170c27af97b (patch)
tree7a7f3a77a96630d0b0629cc81648cec837d1c346 /components
parentf29c18292908f1cea00505341f4611f07ef0276b (diff)
downloadservo-dfcd9de138ece3c7999c76cd9ba1d170c27af97b.tar.gz
servo-dfcd9de138ece3c7999c76cd9ba1d170c27af97b.zip
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 <mrees@noeontheend.com>
Diffstat (limited to 'components')
-rw-r--r--components/layout_2020/dom_traversal.rs5
-rw-r--r--components/layout_2020/fragment_tree/base_fragment.rs2
-rw-r--r--components/layout_2020/style_ext.rs6
-rw-r--r--components/script/layout_dom/element.rs4
-rw-r--r--components/shared/script_layout/wrapper_traits.rs6
5 files changed, 23 insertions, 0 deletions
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;
}