mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
script: Expose a LayoutNode::is_root_of_user_agent_widget method (#44197)
The main goal here is to have layout not depend on `ServoLayoutElement` directly and instead use the layout DOM interface exposed by `layout-api`. This change allows layout to determine if replaced content is the root of a user agent widget without having to access `ServoDangerousStyleShadowRoot` which isn't really safe to use in layout code. `LayoutElement::shadow_root()` is now no longer exposed to layout. Testing: This should not change behavior, so should be covered by existing test. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
@@ -150,34 +150,33 @@ impl IndependentFormattingContext {
|
||||
let non_replaced_contents = match contents {
|
||||
Contents::Replaced(contents) => {
|
||||
base_fragment_info.flags.insert(FragmentFlags::IS_REPLACED);
|
||||
|
||||
// Some replaced elements can have inner widgets, e.g. `<video controls>`.
|
||||
let widget = Some(node_and_style_info.node)
|
||||
.filter(|node| node.pseudo_element_chain().is_empty())
|
||||
.and_then(|node| node.as_element())
|
||||
.and_then(|element| element.shadow_root())
|
||||
.is_some_and(|shadow_root| shadow_root.is_ua_widget())
|
||||
.then(|| {
|
||||
let widget_info = node_and_style_info
|
||||
.with_pseudo_element(context, PseudoElement::ServoAnonymousBox)
|
||||
.expect("Should always be able to construct info for anonymous boxes.");
|
||||
// Use a block formatting context for the widget, since the display inside is always flow.
|
||||
let widget_contents = IndependentFormattingContextContents::Flow(
|
||||
BlockFormattingContext::construct(
|
||||
context,
|
||||
&widget_info,
|
||||
NonReplacedContents::OfElement,
|
||||
propagated_data,
|
||||
false, /* is_list_item */
|
||||
),
|
||||
);
|
||||
let widget_base =
|
||||
LayoutBoxBase::new((&widget_info).into(), widget_info.style);
|
||||
ArcRefCell::new(IndependentFormattingContext::new(
|
||||
widget_base,
|
||||
widget_contents,
|
||||
let node = node_and_style_info.node;
|
||||
let widget = (node.pseudo_element_chain().is_empty() &&
|
||||
node.is_root_of_user_agent_widget())
|
||||
.then(|| {
|
||||
let widget_info = node_and_style_info
|
||||
.with_pseudo_element(context, PseudoElement::ServoAnonymousBox)
|
||||
.expect("Should always be able to construct info for anonymous boxes.");
|
||||
// Use a block formatting context for the widget, since the display inside is always flow.
|
||||
let widget_contents = IndependentFormattingContextContents::Flow(
|
||||
BlockFormattingContext::construct(
|
||||
context,
|
||||
&widget_info,
|
||||
NonReplacedContents::OfElement,
|
||||
propagated_data,
|
||||
))
|
||||
});
|
||||
false, /* is_list_item */
|
||||
),
|
||||
);
|
||||
let widget_base = LayoutBoxBase::new((&widget_info).into(), widget_info.style);
|
||||
ArcRefCell::new(IndependentFormattingContext::new(
|
||||
widget_base,
|
||||
widget_contents,
|
||||
propagated_data,
|
||||
))
|
||||
});
|
||||
|
||||
return IndependentFormattingContextContents::Replaced(contents, widget);
|
||||
},
|
||||
Contents::Widget(non_replaced_contents) => {
|
||||
|
||||
@@ -2368,6 +2368,14 @@ impl<'dom> LayoutDom<'dom, Node> {
|
||||
pub(crate) fn is_in_ua_widget(&self) -> bool {
|
||||
self.unsafe_get().is_in_ua_widget()
|
||||
}
|
||||
|
||||
pub(crate) fn is_root_of_user_agent_widget(&self) -> bool {
|
||||
self.downcast::<Element>().is_some_and(|element| {
|
||||
element
|
||||
.get_shadow_root_for_layout()
|
||||
.is_some_and(|shadow_root| shadow_root.is_user_agent_widget())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -654,7 +654,7 @@ impl<'dom> LayoutDom<'dom, ShadowRoot> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_ua_widget(&self) -> bool {
|
||||
pub(crate) fn is_user_agent_widget(&self) -> bool {
|
||||
self.unsafe_get().is_user_agent_widget()
|
||||
}
|
||||
|
||||
|
||||
@@ -54,11 +54,3 @@ impl<'dom> TShadowRoot for ServoDangerousStyleShadowRoot<'dom> {
|
||||
Some(self.shadow_root.get_style_data_for_layout())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'dom> ServoDangerousStyleShadowRoot<'dom> {
|
||||
/// Whether or not this [`ServoDangerousStyleShadowRoot`] is the root
|
||||
/// of a user agent widget.
|
||||
pub fn is_ua_widget(&self) -> bool {
|
||||
self.shadow_root.is_ua_widget()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,10 @@ impl<'dom> ServoLayoutElement<'dom> {
|
||||
self.element.is_html_element()
|
||||
}
|
||||
|
||||
/// The shadow root this element is a host of.
|
||||
pub fn shadow_root(&self) -> Option<ServoDangerousStyleShadowRoot<'dom>> {
|
||||
/// The shadow root that this [`ServoLayoutElement`] is a host of, if it has one.
|
||||
///
|
||||
/// Note: This should *not* be exposed to layout as it allows access to an ancestor element.
|
||||
pub(super) fn shadow_root(&self) -> Option<ServoDangerousStyleShadowRoot<'dom>> {
|
||||
self.element.get_shadow_root_for_layout().map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,6 +318,10 @@ impl<'dom> LayoutNode<'dom> for ServoLayoutNode<'dom> {
|
||||
fn is_single_line_text_input(&self) -> bool {
|
||||
self.pseudo_element_chain.is_empty() && self.node.is_text_container_of_single_line_input()
|
||||
}
|
||||
|
||||
fn is_root_of_user_agent_widget(&self) -> bool {
|
||||
self.node.is_root_of_user_agent_widget()
|
||||
}
|
||||
}
|
||||
|
||||
impl NodeInfo for ServoLayoutNode<'_> {
|
||||
|
||||
@@ -221,6 +221,9 @@ pub trait LayoutNode<'dom>: Copy + Debug + NodeInfo + Send + Sync {
|
||||
/// <https://html.spec.whatwg.org/multipage/#the-input-element-as-a-text-entry-widget>
|
||||
fn is_single_line_text_input(&self) -> bool;
|
||||
|
||||
/// Whether or not this [`LayoutNode`] is in a user agent widget shadow DOM.
|
||||
fn is_root_of_user_agent_widget(&self) -> bool;
|
||||
|
||||
/// Set whether or not this node has an active pseudo-element style with a `content`
|
||||
/// attribute that uses `attr`.
|
||||
fn set_uses_content_attribute_with_attr(&self, _uses_content_attribute_with_attr: bool);
|
||||
|
||||
Reference in New Issue
Block a user