diff --git a/components/layout/construct.rs b/components/layout/construct.rs index c14c6b61b74..b0980716f2e 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -2379,14 +2379,14 @@ impl Legalizer { FlowClass::TableRow => self.push_new_anonymous_flow::( context, parent, - &[PseudoElement::ServoLegacyAnonymousTableCell], + &[PseudoElement::ServoAnonymousTableCell], SpecificFragmentInfo::TableCell, TableCellFlow::from_fragment, ), FlowClass::Table | FlowClass::TableRowGroup => self.push_new_anonymous_flow::( context, parent, - &[PseudoElement::ServoLegacyAnonymousTableRow], + &[PseudoElement::ServoAnonymousTableRow], SpecificFragmentInfo::TableRow, TableRowFlow::from_fragment, ), diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 9fb5cb2509b..6f017461aaa 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -11,6 +11,7 @@ use style::computed_values::white_space::T as WhiteSpace; use style::properties::longhands::list_style_position::computed_value::T as ListStylePosition; use style::properties::ComputedValues; use style::selector_parser::PseudoElement; +use style::str::char_is_whitespace; use style::values::specified::text::TextDecorationLine; use crate::cell::ArcRefCell; @@ -23,9 +24,10 @@ use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::formatting_contexts::IndependentFormattingContext; use crate::positioned::AbsolutelyPositionedBox; use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside}; +use crate::table::{AnonymousTableContent, Table}; impl BlockFormattingContext { - pub fn construct<'dom, Node>( + pub(crate) fn construct<'dom, Node>( context: &LayoutContext, info: &NodeAndStyleInfo, contents: NonReplacedContents, @@ -35,15 +37,17 @@ impl BlockFormattingContext { where Node: NodeExt<'dom>, { - let contents = BlockContainer::construct( + Self::from_block_container(BlockContainer::construct( context, info, contents, propagated_text_decoration_line, is_list_item, - ); - let contains_floats = contents.contains_floats(); + )) + } + pub(crate) fn from_block_container(contents: BlockContainer) -> Self { + let contains_floats = contents.contains_floats(); Self { contents, contains_floats, @@ -96,6 +100,9 @@ enum BlockLevelCreator { display_inside: DisplayInside, contents: Contents, }, + AnonymousTable { + table_block: ArcRefCell, + }, } /// A block container that may still have to be constructed. @@ -118,7 +125,7 @@ enum IntermediateBlockContainer { /// /// This builder starts from the first child of a given DOM node /// and does a preorder traversal of all of its inclusive siblings. -struct BlockContainerBuilder<'dom, 'style, Node> { +pub(crate) struct BlockContainerBuilder<'dom, 'style, Node> { context: &'style LayoutContext<'style>, /// This NodeAndStyleInfo contains the root node, the corresponding pseudo @@ -167,6 +174,11 @@ struct BlockContainerBuilder<'dom, 'style, Node> { /// The style of the anonymous block boxes pushed to the list of block-level /// boxes, if any (see `end_ongoing_inline_formatting_context`). anonymous_style: Option>, + + /// A collection of content that is being added to an anonymous table. This is + /// composed of any sequence of internal table elements or table captions that + /// are found outside of a table. + anonymous_table_content: Vec>, } impl BlockContainer { @@ -180,20 +192,8 @@ impl BlockContainer { where Node: NodeExt<'dom>, { - let text_decoration_line = - propagated_text_decoration_line | info.style.clone_text_decoration_line(); - let mut builder = BlockContainerBuilder { - context, - info, - block_level_boxes: Vec::new(), - ongoing_inline_formatting_context: InlineFormattingContext::new( - text_decoration_line, - /* has_first_formatted_line = */ true, - /* ends_with_whitespace */ false, - ), - ongoing_inline_boxes_stack: Vec::new(), - anonymous_style: None, - }; + let mut builder = + BlockContainerBuilder::new(context, info, propagated_text_decoration_line); if is_list_item { if let Some(marker_contents) = crate::lists::make_marker(context, info) { @@ -214,27 +214,58 @@ impl BlockContainer { } contents.traverse(context, info, &mut builder); + builder.finish() + } +} - debug_assert!(builder.ongoing_inline_boxes_stack.is_empty()); +impl<'dom, 'style, Node> BlockContainerBuilder<'dom, 'style, Node> +where + Node: NodeExt<'dom>, +{ + pub(crate) fn new( + context: &'style LayoutContext, + info: &'style NodeAndStyleInfo, + propagated_text_decoration_line: TextDecorationLine, + ) -> Self { + let text_decoration_line = + propagated_text_decoration_line | info.style.clone_text_decoration_line(); + BlockContainerBuilder { + context, + info, + block_level_boxes: Vec::new(), + ongoing_inline_formatting_context: InlineFormattingContext::new( + text_decoration_line, + /* has_first_formatted_line = */ true, + /* ends_with_whitespace */ false, + ), + ongoing_inline_boxes_stack: Vec::new(), + anonymous_style: None, + anonymous_table_content: Vec::new(), + } + } - if !builder.ongoing_inline_formatting_context.is_empty() { - if builder.block_level_boxes.is_empty() { + pub(crate) fn finish(mut self) -> BlockContainer { + debug_assert!(self.ongoing_inline_boxes_stack.is_empty()); + + self.finish_anonymous_table_if_needed(); + + if !self.ongoing_inline_formatting_context.is_empty() { + if self.block_level_boxes.is_empty() { return BlockContainer::InlineFormattingContext( - builder.ongoing_inline_formatting_context, + self.ongoing_inline_formatting_context, ); } - builder.end_ongoing_inline_formatting_context(); + self.end_ongoing_inline_formatting_context(); } - let block_level_boxes = if context.use_rayon { - builder - .block_level_boxes + let context = self.context; + let block_level_boxes = if self.context.use_rayon { + self.block_level_boxes .into_par_iter() .map(|block_level_job| block_level_job.finish(context)) .collect() } else { - builder - .block_level_boxes + self.block_level_boxes .into_iter() .map(|block_level_job| block_level_job.finish(context)) .collect() @@ -242,6 +273,65 @@ impl BlockContainer { BlockContainer::BlockLevelBoxes(block_level_boxes) } + + fn finish_anonymous_table_if_needed(&mut self) { + if self.anonymous_table_content.is_empty() { + return; + } + + // Text decorations are not propagated to atomic inline-level descendants. + // From https://drafts.csswg.org/css2/#lining-striking-props: + // > Note that text decorations are not propagated to floating and absolutely + // > positioned descendants, nor to the contents of atomic inline-level descendants + // > such as inline blocks and inline tables. + let inline_table = !self.ongoing_inline_boxes_stack.is_empty(); + let propagated_text_decoration_line = if inline_table { + TextDecorationLine::NONE + } else { + self.ongoing_inline_formatting_context.text_decoration_line + }; + + let contents: Vec> = + self.anonymous_table_content.drain(..).collect(); + let last_text = match contents.last() { + Some(AnonymousTableContent::Text(info, text)) => Some((info.clone(), text.clone())), + _ => None, + }; + + let ifc = Table::construct_anonymous( + self.context, + self.info, + contents, + propagated_text_decoration_line, + ); + + if inline_table { + self.ongoing_inline_formatting_context.ends_with_whitespace = false; + self.current_inline_level_boxes() + .push(ArcRefCell::new(InlineLevelBox::Atomic(ifc))); + } else { + let anonymous_info = self.info.new_replacing_style(ifc.style().clone()); + let table_block = ArcRefCell::new(BlockLevelBox::Independent(ifc)); + self.block_level_boxes.push(BlockLevelJob { + info: anonymous_info, + box_slot: BoxSlot::dummy(), + kind: BlockLevelCreator::AnonymousTable { table_block }, + }); + } + + // If the last element in the anonymous table content is whitespace, that + // whitespace doesn't actually belong to the table. It should be processed outside + // ie become a space between the anonymous table and the rest of the block + // content. Anonymous tables are really only constructed around internal table + // elements and the whitespace between them, so this trailing whitespace should + // not be included. + // + // See https://drafts.csswg.org/css-tables/#fixup-algorithm sections "Remove + // irrelevant boxes" and "Generate missing parents." + if let Some((info, text)) = last_text { + self.handle_text(&info, text); + } + } } impl<'dom, Node> TraversalHandler<'dom, Node> for BlockContainerBuilder<'dom, '_, Node> @@ -256,25 +346,37 @@ where box_slot: BoxSlot<'dom>, ) { match display { - DisplayGeneratingBox::OutsideInside { outside, inside } => match outside { - DisplayOutside::Inline => box_slot.set(LayoutBox::InlineLevel( - self.handle_inline_level_element(info, inside, contents), - )), - DisplayOutside::Block => { - let box_style = info.style.get_box(); - // Floats and abspos cause blockification, so they only happen in this case. - // https://drafts.csswg.org/css2/visuren.html#dis-pos-flo - if box_style.position.is_absolutely_positioned() { - self.handle_absolutely_positioned_element(info, inside, contents, box_slot) - } else if box_style.float.is_floating() { - self.handle_float_element(info, inside, contents, box_slot) - } else { - self.handle_block_level_element(info, inside, contents, box_slot) - } - }, + DisplayGeneratingBox::OutsideInside { outside, inside } => { + self.finish_anonymous_table_if_needed(); + + match outside { + DisplayOutside::Inline => box_slot.set(LayoutBox::InlineLevel( + self.handle_inline_level_element(info, inside, contents), + )), + DisplayOutside::Block => { + let box_style = info.style.get_box(); + // Floats and abspos cause blockification, so they only happen in this case. + // https://drafts.csswg.org/css2/visuren.html#dis-pos-flo + if box_style.position.is_absolutely_positioned() { + self.handle_absolutely_positioned_element( + info, inside, contents, box_slot, + ) + } else if box_style.float.is_floating() { + self.handle_float_element(info, inside, contents, box_slot) + } else { + self.handle_block_level_element(info, inside, contents, box_slot) + } + }, + }; }, DisplayGeneratingBox::LayoutInternal(_) => { - unreachable!("The result of blockification should never be layout-internal value."); + self.anonymous_table_content + .push(AnonymousTableContent::Element { + info: info.clone(), + display, + contents, + box_slot, + }); }, } } @@ -284,6 +386,17 @@ where return; } + // If we are building an anonymous table ie this text directly followed internal + // table elements that did not have a `` ancestor, then we forward all + // whitespace to the table builder. + if !self.anonymous_table_content.is_empty() && input.chars().all(char_is_whitespace) { + self.anonymous_table_content + .push(AnonymousTableContent::Text(info.clone(), input)); + return; + } else { + self.finish_anonymous_table_if_needed(); + } + let (output, has_uncollapsible_content) = collapse_and_transform_whitespace( &input, info.style.get_inherited_text().white_space, @@ -776,6 +889,7 @@ where display_inside, contents, ))), + BlockLevelCreator::AnonymousTable { table_block } => table_block, }; self.box_slot .set(LayoutBox::BlockLevel(block_level_box.clone())); diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 8b18bc5cdbd..0d552988eaf 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -38,6 +38,7 @@ pub mod float; pub mod inline; mod root; +pub(crate) use construct::BlockContainerBuilder; pub use root::{BoxTree, CanvasBackground}; #[derive(Debug, Serialize)] diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs index 40bec8188de..92920a728f9 100644 --- a/components/layout_2020/table/construct.rs +++ b/components/layout_2020/table/construct.rs @@ -7,13 +7,19 @@ use std::convert::{TryFrom, TryInto}; use log::warn; use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode; +use style::selector_parser::PseudoElement; +use style::str::char_is_whitespace; use style::values::specified::TextDecorationLine; use super::{Table, TableSlot, TableSlotCell, TableSlotCoordinates, TableSlotOffset}; use crate::context::LayoutContext; use crate::dom::{BoxSlot, NodeExt}; use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler}; -use crate::flow::BlockFormattingContext; +use crate::flow::{BlockContainerBuilder, BlockFormattingContext}; +use crate::formatting_contexts::{ + IndependentFormattingContext, NonReplacedFormattingContext, + NonReplacedFormattingContextContents, +}; use crate::style_ext::{DisplayGeneratingBox, DisplayLayoutInternal}; /// A reference to a slot and its coordinates in the table @@ -33,6 +39,16 @@ impl<'a> ResolvedSlotAndLocation<'a> { } } +pub(crate) enum AnonymousTableContent<'dom, Node> { + Text(NodeAndStyleInfo, Cow<'dom, str>), + Element { + info: NodeAndStyleInfo, + display: DisplayGeneratingBox, + contents: Contents, + box_slot: BoxSlot<'dom>, + }, +} + impl Table { pub(crate) fn construct<'dom>( context: &LayoutContext, @@ -40,14 +56,60 @@ impl Table { contents: NonReplacedContents, propagated_text_decoration_line: TextDecorationLine, ) -> Self { - let mut traversal = TableBuilderTraversal { - context, - _info: info, - propagated_text_decoration_line, - builder: Default::default(), - }; + let mut traversal = + TableBuilderTraversal::new(context, info, propagated_text_decoration_line); contents.traverse(context, info, &mut traversal); - traversal.builder.finish() + traversal.finish() + } + + pub(crate) fn construct_anonymous<'dom, Node>( + context: &LayoutContext, + parent_info: &NodeAndStyleInfo, + contents: Vec>, + propagated_text_decoration_line: style::values::specified::TextDecorationLine, + ) -> IndependentFormattingContext + where + Node: crate::dom::NodeExt<'dom>, + { + let anonymous_style = context + .shared_context() + .stylist + .style_for_anonymous::( + &context.shared_context().guards, + // TODO: This should be updated for Layout 2020 once we've determined + // which styles should be inherited for tables. + &PseudoElement::ServoLegacyAnonymousTable, + &parent_info.style, + ); + let anonymous_info = parent_info.new_replacing_style(anonymous_style.clone()); + + let mut table_builder = + TableBuilderTraversal::new(context, &anonymous_info, propagated_text_decoration_line); + + for content in contents { + match content { + AnonymousTableContent::Element { + info, + display, + contents, + box_slot, + } => { + table_builder.handle_element(&info, display, contents, box_slot); + }, + AnonymousTableContent::Text(..) => { + // This only happens if there was whitespace between our internal table elements. + // We only collect that whitespace in case we need to re-emit trailing whitespace + // after we've added our anonymous table. + }, + } + } + + IndependentFormattingContext::NonReplaced(NonReplacedFormattingContext { + base_fragment_info: (&anonymous_info).into(), + style: anonymous_style, + content_sizes: None, + contents: NonReplacedFormattingContextContents::Table(table_builder.finish()), + }) } /// Push a new slot into the last row of this table. @@ -295,9 +357,9 @@ impl TableBuilder { } } -struct TableBuilderTraversal<'a, Node> { - context: &'a LayoutContext<'a>, - _info: &'a NodeAndStyleInfo, +pub(crate) struct TableBuilderTraversal<'style, 'dom, Node> { + context: &'style LayoutContext<'style>, + info: &'style NodeAndStyleInfo, /// Propagated value for text-decoration-line, used to construct the block /// contents of table cells. @@ -306,14 +368,83 @@ struct TableBuilderTraversal<'a, Node> { /// The [`TableBuilder`] for this [`TableBuilderTraversal`]. This is separated /// into another struct so that we can write unit tests against the builder. builder: TableBuilder, + + current_anonymous_row_content: Vec>, } -impl<'a, 'dom, Node: 'dom> TraversalHandler<'dom, Node> for TableBuilderTraversal<'a, Node> +impl<'style, 'dom, Node> TableBuilderTraversal<'style, 'dom, Node> where Node: NodeExt<'dom>, { - fn handle_text(&mut self, _info: &NodeAndStyleInfo, _text: Cow<'dom, str>) { - // TODO: We should collect these contents into a new table cell. + pub(crate) fn new( + context: &'style LayoutContext<'style>, + info: &'style NodeAndStyleInfo, + propagated_text_decoration_line: TextDecorationLine, + ) -> Self { + TableBuilderTraversal { + context, + info, + propagated_text_decoration_line, + builder: Default::default(), + current_anonymous_row_content: Vec::new(), + } + } + + pub(crate) fn finish(mut self) -> Table { + self.finish_anonymous_row_if_needed(); + self.builder.finish() + } + + fn finish_anonymous_row_if_needed(&mut self) { + if self.current_anonymous_row_content.is_empty() { + return; + } + + let row_content = std::mem::replace(&mut self.current_anonymous_row_content, Vec::new()); + let context = self.context; + let anonymous_style = self + .context + .shared_context() + .stylist + .style_for_anonymous::( + &context.shared_context().guards, + &PseudoElement::ServoAnonymousTableCell, + &self.info.style, + ); + let anonymous_info = self.info.new_replacing_style(anonymous_style); + let mut row_builder = TableRowBuilder::new(self, &anonymous_info); + + for cell_content in row_content { + match cell_content { + AnonymousTableContent::Element { + info, + display, + contents, + box_slot, + } => { + row_builder.handle_element(&info, display, contents, box_slot); + }, + AnonymousTableContent::Text(info, text) => { + row_builder.handle_text(&info, text); + }, + } + } + + row_builder.finish(); + } +} + +impl<'style, 'dom, Node: 'dom> TraversalHandler<'dom, Node> + for TableBuilderTraversal<'style, 'dom, Node> +where + Node: NodeExt<'dom>, +{ + fn handle_text(&mut self, info: &NodeAndStyleInfo, text: Cow<'dom, str>) { + if text.chars().all(char_is_whitespace) { + return; + } + self.current_anonymous_row_content + .push(AnonymousTableContent::Text(info.clone(), text)); } /// https://html.spec.whatwg.org/multipage/#forming-a-table @@ -326,7 +457,11 @@ where ) { match display { DisplayGeneratingBox::LayoutInternal(internal) => match internal { - DisplayLayoutInternal::TableRowGroup => { + DisplayLayoutInternal::TableRowGroup | + DisplayLayoutInternal::TableFooterGroup | + DisplayLayoutInternal::TableHeaderGroup => { + self.finish_anonymous_row_if_needed(); + // TODO: Should we fixup `rowspan=0` to the actual resolved value and // any other rowspans that have been cut short? self.builder.incoming_rowspans.clear(); @@ -337,47 +472,147 @@ where ); // TODO: Handle style for row groups here. + + // We are doing this until we have actually set a Box for this `BoxSlot`. + ::std::mem::forget(box_slot) }, DisplayLayoutInternal::TableRow => { - self.builder.start_row(); + self.finish_anonymous_row_if_needed(); + + let context = self.context; + + let mut row_builder = TableRowBuilder::new(self, info); NonReplacedContents::try_from(contents).unwrap().traverse( - self.context, + context, info, - &mut TableRowBuilder::new(self), + &mut row_builder, ); - self.builder.end_row(); + row_builder.finish(); + + // We are doing this until we have actually set a Box for this `BoxSlot`. + ::std::mem::forget(box_slot) }, - _ => { - // TODO: Handle other types of unparented table content, colgroups, and captions. + DisplayLayoutInternal::TableCaption | + DisplayLayoutInternal::TableColumn | + DisplayLayoutInternal::TableColumnGroup => { + // TODO: Handle these other types of table elements. + + // We are doing this until we have actually set a Box for this `BoxSlot`. + ::std::mem::forget(box_slot) + }, + DisplayLayoutInternal::TableCell => { + self.current_anonymous_row_content + .push(AnonymousTableContent::Element { + info: info.clone(), + display, + contents, + box_slot, + }); }, }, _ => { - // TODO: Create an anonymous row and cell for other unwrapped content. + self.current_anonymous_row_content + .push(AnonymousTableContent::Element { + info: info.clone(), + display, + contents, + box_slot, + }); }, } - - // We are doing this until we have actually set a Box for this `BoxSlot`. - ::std::mem::forget(box_slot) } } -struct TableRowBuilder<'a, 'builder, Node> { - table_traversal: &'builder mut TableBuilderTraversal<'a, Node>, +struct TableRowBuilder<'style, 'builder, 'dom, 'a, Node> { + table_traversal: &'builder mut TableBuilderTraversal<'style, 'dom, Node>, + + /// The [`NodeAndStyleInfo`] of this table row, which we use to + /// construct anonymous table cells. + info: &'a NodeAndStyleInfo, + + current_anonymous_cell_content: Vec>, } -impl<'a, 'builder, Node> TableRowBuilder<'a, 'builder, Node> { - fn new(table_traversal: &'builder mut TableBuilderTraversal<'a, Node>) -> Self { - TableRowBuilder { table_traversal } - } -} - -impl<'a, 'builder, 'dom, Node: 'dom> TraversalHandler<'dom, Node> - for TableRowBuilder<'a, 'builder, Node> +impl<'style, 'builder, 'dom, 'a, Node: 'dom> TableRowBuilder<'style, 'builder, 'dom, 'a, Node> where Node: NodeExt<'dom>, { - fn handle_text(&mut self, _info: &NodeAndStyleInfo, _text: Cow<'dom, str>) { - // TODO: We should collect these contents into a new table cell. + fn new( + table_traversal: &'builder mut TableBuilderTraversal<'style, 'dom, Node>, + info: &'a NodeAndStyleInfo, + ) -> Self { + table_traversal.builder.start_row(); + + TableRowBuilder { + table_traversal, + info, + current_anonymous_cell_content: Vec::new(), + } + } + + fn finish(mut self) { + self.finish_current_anonymous_cell_if_needed(); + self.table_traversal.builder.end_row(); + } + + fn finish_current_anonymous_cell_if_needed(&mut self) { + if self.current_anonymous_cell_content.is_empty() { + return; + } + + let context = self.table_traversal.context; + let anonymous_style = context + .shared_context() + .stylist + .style_for_anonymous::( + &context.shared_context().guards, + &PseudoElement::ServoAnonymousTableCell, + &self.info.style, + ); + let anonymous_info = self.info.new_replacing_style(anonymous_style); + let mut builder = BlockContainerBuilder::new( + context, + &anonymous_info, + self.table_traversal.propagated_text_decoration_line, + ); + + for cell_content in self.current_anonymous_cell_content.drain(..) { + match cell_content { + AnonymousTableContent::Element { + info, + display, + contents, + box_slot, + } => { + builder.handle_element(&info, display, contents, box_slot); + }, + AnonymousTableContent::Text(info, text) => { + builder.handle_text(&info, text); + }, + } + } + + let block_container = builder.finish(); + self.table_traversal.builder.add_cell(TableSlotCell { + contents: BlockFormattingContext::from_block_container(block_container), + colspan: 1, + rowspan: 1, + id: 0, // This is just an id used for testing purposes. + }); + } +} + +impl<'style, 'builder, 'dom, 'a, Node: 'dom> TraversalHandler<'dom, Node> + for TableRowBuilder<'style, 'builder, 'dom, 'a, Node> +where + Node: NodeExt<'dom>, +{ + fn handle_text(&mut self, info: &NodeAndStyleInfo, text: Cow<'dom, str>) { + if text.chars().all(char_is_whitespace) { + return; + } + self.current_anonymous_cell_content + .push(AnonymousTableContent::Text(info.clone(), text)); } /// https://html.spec.whatwg.org/multipage/#algorithm-for-processing-rows @@ -417,23 +652,37 @@ where }, }; + self.finish_current_anonymous_cell_if_needed(); self.table_traversal.builder.add_cell(TableSlotCell { contents, colspan, rowspan, id: 0, // This is just an id used for testing purposes. }); + + // We are doing this until we have actually set a Box for this `BoxSlot`. + ::std::mem::forget(box_slot) }, _ => { - // TODO: Properly handle other table-like elements in the middle of a row. + //// TODO: Properly handle other table-like elements in the middle of a row. + self.current_anonymous_cell_content + .push(AnonymousTableContent::Element { + info: info.clone(), + display, + contents, + box_slot, + }); }, }, _ => { - // TODO: We should collect these contents into a new table cell. + self.current_anonymous_cell_content + .push(AnonymousTableContent::Element { + info: info.clone(), + display, + contents, + box_slot, + }); }, } - - // We are doing this until we have actually set a Box for this `BoxSlot`. - ::std::mem::forget(box_slot) } } diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs index a228ccc6907..6d3c75b0b9a 100644 --- a/components/layout_2020/table/mod.rs +++ b/components/layout_2020/table/mod.rs @@ -7,6 +7,7 @@ mod construct; +pub(crate) use construct::AnonymousTableContent; pub use construct::TableBuilder; use euclid::{Point2D, UnknownUnit, Vector2D}; use serde::Serialize; diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index 08431dba684..0df3fe6b0ec 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -54,13 +54,13 @@ pub enum PseudoElement { DetailsSummary, DetailsContent, ServoAnonymousBox, + ServoAnonymousTableCell, + ServoAnonymousTableRow, ServoLegacyText, ServoLegacyInputText, ServoLegacyTableWrapper, ServoLegacyAnonymousTableWrapper, ServoLegacyAnonymousTable, - ServoLegacyAnonymousTableRow, - ServoLegacyAnonymousTableCell, ServoLegacyAnonymousBlock, ServoLegacyInlineBlockWrapper, ServoLegacyInlineAbsolute, @@ -82,13 +82,13 @@ impl ToCss for PseudoElement { DetailsSummary => "::-servo-details-summary", DetailsContent => "::-servo-details-content", ServoAnonymousBox => "::-servo-anonymous-box", + ServoAnonymousTableCell => "::-servo-anonymous-table-cell", + ServoAnonymousTableRow => "::-servo-anonymous-table-row", ServoLegacyText => "::-servo-legacy-text", ServoLegacyInputText => "::-servo-legacy-input-text", ServoLegacyTableWrapper => "::-servo-legacy-table-wrapper", ServoLegacyAnonymousTableWrapper => "::-servo-legacy-anonymous-table-wrapper", ServoLegacyAnonymousTable => "::-servo-legacy-anonymous-table", - ServoLegacyAnonymousTableRow => "::-servo-legacy-anonymous-table-row", - ServoLegacyAnonymousTableCell => "::-servo-legacy-anonymous-table-cell", ServoLegacyAnonymousBlock => "::-servo-legacy-anonymous-block", ServoLegacyInlineBlockWrapper => "::-servo-legacy-inline-block-wrapper", ServoLegacyInlineAbsolute => "::-servo-legacy-inline-absolute", @@ -229,13 +229,13 @@ impl PseudoElement { PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy, PseudoElement::DetailsContent | PseudoElement::ServoAnonymousBox | + PseudoElement::ServoAnonymousTableCell | + PseudoElement::ServoAnonymousTableRow | PseudoElement::ServoLegacyText | PseudoElement::ServoLegacyInputText | PseudoElement::ServoLegacyTableWrapper | PseudoElement::ServoLegacyAnonymousTableWrapper | PseudoElement::ServoLegacyAnonymousTable | - PseudoElement::ServoLegacyAnonymousTableRow | - PseudoElement::ServoLegacyAnonymousTableCell | PseudoElement::ServoLegacyAnonymousBlock | PseudoElement::ServoLegacyInlineBlockWrapper | PseudoElement::ServoLegacyInlineAbsolute => PseudoElementCascadeType::Precomputed, @@ -554,17 +554,17 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } ServoLegacyAnonymousTable }, - "-servo-legacy-anonymous-table-row" => { + "-servo-anonymous-table-row" => { if !self.in_user_agent_stylesheet() { return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) } - ServoLegacyAnonymousTableRow + ServoAnonymousTableRow }, - "-servo-legacy-anonymous-table-cell" => { + "-servo-anonymous-table-cell" => { if !self.in_user_agent_stylesheet() { return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) } - ServoLegacyAnonymousTableCell + ServoAnonymousTableCell }, "-servo-legacy-anonymous-block" => { if !self.in_user_agent_stylesheet() { diff --git a/resources/servo.css b/resources/servo.css index 739e29cd488..6bea1cc43ad 100644 --- a/resources/servo.css +++ b/resources/servo.css @@ -230,7 +230,7 @@ svg > * { overflow: visible; } -*|*::-servo-legacy-anonymous-table-row { +*|*::-servo-anonymous-table-row { display: table-row; position: static; border: none; @@ -238,7 +238,7 @@ svg > * { overflow: visible; } -*|*::-servo-legacy-anonymous-table-cell { +*|*::-servo-anonymous-table-cell { display: table-cell; position: static; border: none;