Anonymous boxes that wrap inlines should not inherit overflow (#30579)

In legacy layout, anonymous text wrappers were inheriting the `overflow`
and `text-overflow` properties. This results in the creation of extra
clipping for these anonymous wrappers which could clip away floats. We
will likely implement `text-overflow` differently in non-legacy layout.

This change marks all legacy layout pseudo elements as "legacy" and also
adds a new pseudo element for non-legacy layout that does not inherit
`overflow`.

Fixes #30562.

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2023-10-19 15:43:55 +02:00 committed by GitHub
parent 634a5d9cf5
commit fd31da9102
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 120 additions and 88 deletions

View file

@ -805,7 +805,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&context.guards, &context.guards,
&PseudoElement::ServoText, &PseudoElement::ServoLegacyText,
&style, &style,
); );
if node_is_input_or_text_area { if node_is_input_or_text_area {
@ -813,7 +813,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&context.guards, &context.guards,
&PseudoElement::ServoInputText, &PseudoElement::ServoLegacyInputText,
&style, &style,
) )
} }
@ -1116,7 +1116,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&context.guards, &context.guards,
&PseudoElement::ServoText, &PseudoElement::ServoLegacyText,
&style, &style,
), ),
node.restyle_damage(), node.restyle_damage(),
@ -1133,7 +1133,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&context.guards, &context.guards,
&PseudoElement::ServoText, &PseudoElement::ServoLegacyText,
&style, &style,
); );
self.create_fragments_for_node_text_content(&mut fragments, node, &text_style) self.create_fragments_for_node_text_content(&mut fragments, node, &text_style)
@ -1176,7 +1176,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&context.guards, &context.guards,
&PseudoElement::ServoInlineBlockWrapper, &PseudoElement::ServoLegacyInlineBlockWrapper,
&style, &style,
); );
let fragment_info = let fragment_info =
@ -1227,7 +1227,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&style_context.guards, &style_context.guards,
&PseudoElement::ServoInlineAbsolute, &PseudoElement::ServoLegacyInlineAbsolute,
&style, &style,
); );
let fragment = Fragment::from_opaque_node_and_style( let fragment = Fragment::from_opaque_node_and_style(
@ -1372,7 +1372,7 @@ where
.stylist .stylist
.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
&context.guards, &context.guards,
&PseudoElement::ServoTableWrapper, &PseudoElement::ServoLegacyTableWrapper,
&table_style, &table_style,
); );
} }
@ -2189,7 +2189,7 @@ where
))); )));
let text_style = context.stylist.style_for_anonymous::<E>( let text_style = context.stylist.style_for_anonymous::<E>(
&context.guards, &context.guards,
&PseudoElement::ServoText, &PseudoElement::ServoLegacyText,
&node.style, &node.style,
); );
@ -2317,7 +2317,7 @@ impl Legalizer {
let mut block_wrapper = Legalizer::create_anonymous_flow::<E, _>( let mut block_wrapper = Legalizer::create_anonymous_flow::<E, _>(
context, context,
parent, parent,
&[PseudoElement::ServoAnonymousBlock], &[PseudoElement::ServoLegacyAnonymousBlock],
SpecificFragmentInfo::Generic, SpecificFragmentInfo::Generic,
BlockFlow::from_fragment, BlockFlow::from_fragment,
); );
@ -2378,21 +2378,21 @@ impl Legalizer {
FlowClass::TableRow => self.push_new_anonymous_flow::<E, _>( FlowClass::TableRow => self.push_new_anonymous_flow::<E, _>(
context, context,
parent, parent,
&[PseudoElement::ServoAnonymousTableCell], &[PseudoElement::ServoLegacyAnonymousTableCell],
SpecificFragmentInfo::TableCell, SpecificFragmentInfo::TableCell,
TableCellFlow::from_fragment, TableCellFlow::from_fragment,
), ),
FlowClass::Table | FlowClass::TableRowGroup => self.push_new_anonymous_flow::<E, _>( FlowClass::Table | FlowClass::TableRowGroup => self.push_new_anonymous_flow::<E, _>(
context, context,
parent, parent,
&[PseudoElement::ServoAnonymousTableRow], &[PseudoElement::ServoLegacyAnonymousTableRow],
SpecificFragmentInfo::TableRow, SpecificFragmentInfo::TableRow,
TableRowFlow::from_fragment, TableRowFlow::from_fragment,
), ),
FlowClass::TableWrapper => self.push_new_anonymous_flow::<E, _>( FlowClass::TableWrapper => self.push_new_anonymous_flow::<E, _>(
context, context,
parent, parent,
&[PseudoElement::ServoAnonymousTable], &[PseudoElement::ServoLegacyAnonymousTable],
SpecificFragmentInfo::Table, SpecificFragmentInfo::Table,
TableFlow::from_fragment, TableFlow::from_fragment,
), ),
@ -2400,8 +2400,8 @@ impl Legalizer {
context, context,
parent, parent,
&[ &[
PseudoElement::ServoTableWrapper, PseudoElement::ServoLegacyTableWrapper,
PseudoElement::ServoAnonymousTableWrapper, PseudoElement::ServoLegacyAnonymousTableWrapper,
], ],
SpecificFragmentInfo::TableWrapper, SpecificFragmentInfo::TableWrapper,
TableWrapperFlow::from_fragment, TableWrapperFlow::from_fragment,

View file

@ -228,7 +228,7 @@ fn traverse_pseudo_element_contents<'dom, Node>(
.stylist .stylist
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&context.shared_context().guards, &context.shared_context().guards,
&PseudoElement::ServoText, &PseudoElement::ServoAnonymousBox,
&info.style, &info.style,
) )
}); });

View file

@ -132,7 +132,7 @@ where
.stylist .stylist
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&self.context.shared_context().guards, &self.context.shared_context().guards,
&style::selector_parser::PseudoElement::ServoText, &style::selector_parser::PseudoElement::ServoAnonymousBox,
&self.info.style, &self.info.style,
), ),
) )

View file

@ -448,7 +448,7 @@ where
.stylist .stylist
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&self.context.shared_context().guards, &self.context.shared_context().guards,
&PseudoElement::ServoText, // FIMXE: use `PseudoElement::Marker` when we add it &PseudoElement::ServoLegacyText, // FIMXE: use `PseudoElement::Marker` when we add it
&info.style, &info.style,
); );
self.handle_inline_level_element( self.handle_inline_level_element(
@ -684,7 +684,7 @@ where
.stylist .stylist
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&context.shared_context().guards, &context.shared_context().guards,
&PseudoElement::ServoText, &PseudoElement::ServoAnonymousBox,
block_container_style, block_container_style,
) )
}); });

View file

@ -52,20 +52,21 @@ pub enum PseudoElement {
// Non-eager pseudos. // Non-eager pseudos.
DetailsSummary, DetailsSummary,
DetailsContent, DetailsContent,
ServoText, ServoAnonymousBox,
ServoInputText, ServoLegacyText,
ServoTableWrapper, ServoLegacyInputText,
ServoAnonymousTableWrapper, ServoLegacyTableWrapper,
ServoAnonymousTable, ServoLegacyAnonymousTableWrapper,
ServoAnonymousTableRow, ServoLegacyAnonymousTable,
ServoAnonymousTableCell, ServoLegacyAnonymousTableRow,
ServoAnonymousBlock, ServoLegacyAnonymousTableCell,
ServoInlineBlockWrapper, ServoLegacyAnonymousBlock,
ServoInlineAbsolute, ServoLegacyInlineBlockWrapper,
ServoLegacyInlineAbsolute,
} }
/// The count of all pseudo-elements. /// The count of all pseudo-elements.
pub const PSEUDO_COUNT: usize = PseudoElement::ServoInlineAbsolute as usize + 1; pub const PSEUDO_COUNT: usize = PseudoElement::ServoLegacyInlineAbsolute as usize + 1;
impl ToCss for PseudoElement { impl ToCss for PseudoElement {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result fn to_css<W>(&self, dest: &mut W) -> fmt::Result
@ -79,16 +80,17 @@ impl ToCss for PseudoElement {
Selection => "::selection", Selection => "::selection",
DetailsSummary => "::-servo-details-summary", DetailsSummary => "::-servo-details-summary",
DetailsContent => "::-servo-details-content", DetailsContent => "::-servo-details-content",
ServoText => "::-servo-text", ServoAnonymousBox => "::-servo-anonymous-box",
ServoInputText => "::-servo-input-text", ServoLegacyText => "::-servo-legacy-text",
ServoTableWrapper => "::-servo-table-wrapper", ServoLegacyInputText => "::-servo-legacy-input-text",
ServoAnonymousTableWrapper => "::-servo-anonymous-table-wrapper", ServoLegacyTableWrapper => "::-servo-legacy-table-wrapper",
ServoAnonymousTable => "::-servo-anonymous-table", ServoLegacyAnonymousTableWrapper => "::-servo-legacy-anonymous-table-wrapper",
ServoAnonymousTableRow => "::-servo-anonymous-table-row", ServoLegacyAnonymousTable => "::-servo-legacy-anonymous-table",
ServoAnonymousTableCell => "::-servo-anonymous-table-cell", ServoLegacyAnonymousTableRow => "::-servo-legacy-anonymous-table-row",
ServoAnonymousBlock => "::-servo-anonymous-block", ServoLegacyAnonymousTableCell => "::-servo-legacy-anonymous-table-cell",
ServoInlineBlockWrapper => "::-servo-inline-block-wrapper", ServoLegacyAnonymousBlock => "::-servo-legacy-anonymous-block",
ServoInlineAbsolute => "::-servo-inline-absolute", ServoLegacyInlineBlockWrapper => "::-servo-legacy-inline-block-wrapper",
ServoLegacyInlineAbsolute => "::-servo-legacy-inline-absolute",
}) })
} }
} }
@ -225,16 +227,17 @@ impl PseudoElement {
}, },
PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy, PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
PseudoElement::DetailsContent | PseudoElement::DetailsContent |
PseudoElement::ServoText | PseudoElement::ServoAnonymousBox |
PseudoElement::ServoInputText | PseudoElement::ServoLegacyText |
PseudoElement::ServoTableWrapper | PseudoElement::ServoLegacyInputText |
PseudoElement::ServoAnonymousTableWrapper | PseudoElement::ServoLegacyTableWrapper |
PseudoElement::ServoAnonymousTable | PseudoElement::ServoLegacyAnonymousTableWrapper |
PseudoElement::ServoAnonymousTableRow | PseudoElement::ServoLegacyAnonymousTable |
PseudoElement::ServoAnonymousTableCell | PseudoElement::ServoLegacyAnonymousTableRow |
PseudoElement::ServoAnonymousBlock | PseudoElement::ServoLegacyAnonymousTableCell |
PseudoElement::ServoInlineBlockWrapper | PseudoElement::ServoLegacyAnonymousBlock |
PseudoElement::ServoInlineAbsolute => PseudoElementCascadeType::Precomputed, PseudoElement::ServoLegacyInlineBlockWrapper |
PseudoElement::ServoLegacyInlineAbsolute => PseudoElementCascadeType::Precomputed,
} }
} }
@ -498,65 +501,71 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
} }
DetailsContent DetailsContent
}, },
"-servo-text" => { "-servo-anonymous-box" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoText ServoAnonymousBox
}, },
"-servo-input-text" => { "-servo-legacy-text" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoInputText ServoLegacyText
}, },
"-servo-table-wrapper" => { "-servo-legacy-input-text" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoTableWrapper ServoLegacyInputText
}, },
"-servo-anonymous-table-wrapper" => { "-servo-legacy-table-wrapper" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoAnonymousTableWrapper ServoLegacyTableWrapper
}, },
"-servo-anonymous-table" => { "-servo-legacy-anonymous-table-wrapper" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoAnonymousTable ServoLegacyAnonymousTableWrapper
}, },
"-servo-anonymous-table-row" => { "-servo-legacy-anonymous-table" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoAnonymousTableRow ServoLegacyAnonymousTable
}, },
"-servo-anonymous-table-cell" => { "-servo-legacy-anonymous-table-row" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoAnonymousTableCell ServoLegacyAnonymousTableRow
}, },
"-servo-anonymous-block" => { "-servo-legacy-anonymous-table-cell" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoAnonymousBlock ServoLegacyAnonymousTableCell
}, },
"-servo-inline-block-wrapper" => { "-servo-legacy-anonymous-block" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoInlineBlockWrapper ServoLegacyAnonymousBlock
}, },
"-servo-inline-absolute" => { "-servo-legacy-inline-block-wrapper" => {
if !self.in_user_agent_stylesheet() { if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
} }
ServoInlineAbsolute ServoLegacyInlineBlockWrapper
},
"-servo-legacy-inline-absolute" => {
if !self.in_user_agent_stylesheet() {
return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
}
ServoLegacyInlineAbsolute
}, },
_ => return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) _ => return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))

View file

@ -190,27 +190,27 @@ svg > * {
* broken for stuff like table backgrounds and such. Gecko explicitly inherits * broken for stuff like table backgrounds and such. Gecko explicitly inherits
* what it wants, which seems a bit better off-hand. * what it wants, which seems a bit better off-hand.
*/ */
*|*::-servo-anonymous-table, *|*::-servo-legacy-anonymous-table,
*|*::-servo-anonymous-table-wrapper, *|*::-servo-legacy-anonymous-table-wrapper,
*|*::-servo-table-wrapper, *|*::-servo-legacy-table-wrapper,
*|*::-servo-anonymous-block, *|*::-servo-legacy-anonymous-block,
*|*::-servo-inline-block-wrapper, *|*::-servo-legacy-inline-block-wrapper,
*|*::-servo-inline-absolute { *|*::-servo-legacy-inline-absolute {
all: inherit; all: inherit;
} }
/* style for text node. */ /* style for text node. */
*|*::-servo-text { *|*::-servo-legacy-text {
text-overflow: inherit; text-overflow: inherit;
overflow: inherit; overflow: inherit;
} }
*|*::-servo-table-wrapper { *|*::-servo-legacy-table-wrapper {
display: table; display: table;
border: none; border: none;
} }
*|*::-servo-anonymous-table-wrapper { *|*::-servo-legacy-anonymous-table-wrapper {
position: static; position: static;
margin: 0; margin: 0;
counter-increment: none; counter-increment: none;
@ -221,7 +221,7 @@ svg > * {
overflow: visible; overflow: visible;
} }
*|*::-servo-anonymous-table { *|*::-servo-legacy-anonymous-table {
display: table; display: table;
position: static; position: static;
border: none; border: none;
@ -230,7 +230,7 @@ svg > * {
overflow: visible; overflow: visible;
} }
*|*::-servo-anonymous-table-row { *|*::-servo-legacy-anonymous-table-row {
display: table-row; display: table-row;
position: static; position: static;
border: none; border: none;
@ -238,7 +238,7 @@ svg > * {
overflow: visible; overflow: visible;
} }
*|*::-servo-anonymous-table-cell { *|*::-servo-legacy-anonymous-table-cell {
display: table-cell; display: table-cell;
position: static; position: static;
border: none; border: none;
@ -246,7 +246,7 @@ svg > * {
overflow: visible; overflow: visible;
} }
*|*::-servo-anonymous-block { *|*::-servo-legacy-anonymous-block {
display: block; display: block;
position: static; position: static;
border: none; border: none;
@ -257,7 +257,7 @@ svg > * {
} }
/* The outer fragment wrapper of an inline-block. */ /* The outer fragment wrapper of an inline-block. */
*|*::-servo-inline-block-wrapper { *|*::-servo-legacy-inline-block-wrapper {
position: static; position: static;
border: none; border: none;
padding: 0; padding: 0;
@ -265,7 +265,7 @@ svg > * {
} }
/* The outer fragment wrapper of an inline absolute hypothetical fragment. */ /* The outer fragment wrapper of an inline absolute hypothetical fragment. */
*|*::-servo-inline-absolute { *|*::-servo-legacy-inline-absolute {
clip: auto; clip: auto;
border: none; border: none;
padding: 0; padding: 0;

View file

@ -61432,6 +61432,19 @@
{} {}
] ]
], ],
"float-in-inline-anonymous-block-with-overflow-hidden.html": [
"948394e7f9b348c72a13cc64f4852a988b2fa59c",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"float-in-nested-multicol-001.html": [ "float-in-nested-multicol-001.html": [
"8e1a257e389d0fdc6a4a69f63b81f32378a7b944", "8e1a257e389d0fdc6a4a69f63b81f32378a7b944",
[ [

View file

@ -1,2 +0,0 @@
[text-overflow-on-flexbox-001.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[position-sticky-hyperlink.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[filtered-inline-is-container.html]
expected: FAIL

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<title>CSS Test: A float wrapped in an anonymous block should be visible within a container with overflow: hidden.</title>
<link rel="author" href="mailto:obrufrau@igalia.com" title="Oriol Brufrau">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level" />
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="overflow: hidden; width: 100px; height: 100px; background: red">
<div style="height: 50px; background: green"></div>
<span>
<div style="float: left; width: 100px; height: 50px; background: green"></div>
</span>
</div>