diff options
author | Simon Wülker <simon.wuelker@arcor.de> | 2025-01-28 22:04:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-28 21:04:32 +0000 |
commit | 1188d2b2e7c18434f06df5505bed7cfd859f47e2 (patch) | |
tree | 6610915adec04c368f355e7b1e973f4ae2a84a00 /components/script/layout_dom/element.rs | |
parent | 7f1eefc182d1f11b6558d0fbffdfb184cab69ea3 (diff) | |
download | servo-1188d2b2e7c18434f06df5505bed7cfd859f47e2.tar.gz servo-1188d2b2e7c18434f06df5505bed7cfd859f47e2.zip |
Never compute style for children of shadow hosts (#35198)
There is some interesting history to this change:
* https://github.com/servo/servo/issues/33495: Servo crashes on
Cloudflare's turnstile, because we didn't compute style for
elements inside shadow trees
* https://github.com/servo/servo/pull/34298: Resolves the issue
by computing style for children of a potential shadow root,
in addition to the children of an element
* https://github.com/servo/servo/pull/34701: Changes layout
of elements with shadow roots such that only the contents
of the shadow root are laid out
Now, we compute style for both the children of the element
and a potential shadow root, but only lay out the contents
of the shadow tree (if there is one).
This behaviour is not technically incorrect,
since regular children are not included in layout
their style doesn't matter. However, it is
inefficient: the only case where we need to compute
style for a child of a shadow host is when
that child is an assigned slottable in a slot
somewhere else.
This part 1/n of upstreaming the changes necessary
to lay out `<slot>` contents. Note that trying to compute
style for `<slot>` contents *and* children of shadow hosts
will crash in stylo, since it expects to see each
element only once.
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Diffstat (limited to 'components/script/layout_dom/element.rs')
-rw-r--r-- | components/script/layout_dom/element.rs | 31 |
1 files changed, 6 insertions, 25 deletions
diff --git a/components/script/layout_dom/element.rs b/components/script/layout_dom/element.rs index 5c5a6da9677..45ff4450542 100644 --- a/components/script/layout_dom/element.rs +++ b/components/script/layout_dom/element.rs @@ -140,41 +140,22 @@ impl<'dom> ServoLayoutElement<'dom> { } } -pub struct DomChildrenIncludingShadowDom<N> { - children: DomChildren<N>, - children_in_shadow_root: Option<DomChildren<N>>, -} - -impl<N> Iterator for DomChildrenIncludingShadowDom<N> -where - N: TNode, -{ - type Item = N; - - fn next(&mut self) -> Option<Self::Item> { - self.children - .next() - .or_else(|| self.children_in_shadow_root.as_mut()?.next()) - } -} - impl<'dom> style::dom::TElement for ServoLayoutElement<'dom> { type ConcreteNode = ServoLayoutNode<'dom>; - type TraversalChildrenIterator = DomChildrenIncludingShadowDom<Self::ConcreteNode>; + type TraversalChildrenIterator = DomChildren<Self::ConcreteNode>; fn as_node(&self) -> ServoLayoutNode<'dom> { ServoLayoutNode::from_layout_js(self.element.upcast()) } fn traversal_children(&self) -> LayoutIterator<Self::TraversalChildrenIterator> { - let children = DomChildrenIncludingShadowDom { - children: self.as_node().dom_children(), - children_in_shadow_root: self - .shadow_root() - .map(|shadow| shadow.as_node().dom_children()), + let iterator = if let Some(shadow_root) = self.shadow_root() { + shadow_root.as_node().dom_children() + } else { + self.as_node().dom_children() }; - LayoutIterator(children) + LayoutIterator(iterator) } fn is_html_element(&self) -> bool { |