diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs index bdca1e5d77a..504725ae7c5 100644 --- a/components/layout_2020/display_list/stacking_context.rs +++ b/components/layout_2020/display_list/stacking_context.rs @@ -474,7 +474,7 @@ impl StackingContext { if effects.filter.0.is_empty() && effects.opacity == 1.0 && effects.mix_blend_mode == ComputedMixBlendMode::Normal && - !style.has_transform_or_perspective() + !style.has_transform_or_perspective(FragmentFlags::empty()) { return false; } @@ -896,7 +896,7 @@ struct ReferenceFrameData { impl BoxFragment { fn get_stacking_context_type(&self) -> Option { - if self.style.establishes_stacking_context() { + if self.style.establishes_stacking_context(self.base.flags) { return Some(StackingContextType::RealStackingContext); } @@ -986,7 +986,7 @@ impl BoxFragment { // properties will be replaced before recursing into children. assert!(self .style - .establishes_containing_block_for_all_descendants()); + .establishes_containing_block_for_all_descendants(self.base.flags)); let adjusted_containing_block = ContainingBlock::new( containing_block .rect @@ -1168,7 +1168,7 @@ impl BoxFragment { // absolute and fixed descendants. let new_containing_block_info = if self .style - .establishes_containing_block_for_all_descendants() + .establishes_containing_block_for_all_descendants(self.base.flags) { containing_block_info.new_for_absolute_and_fixed_descendants( &for_non_absolute_descendants, @@ -1176,7 +1176,7 @@ impl BoxFragment { ) } else if self .style - .establishes_containing_block_for_absolute_descendants() + .establishes_containing_block_for_absolute_descendants(self.base.flags) { containing_block_info.new_for_absolute_descendants( &for_non_absolute_descendants, @@ -1389,7 +1389,7 @@ impl BoxFragment { &self, containing_block_rect: &PhysicalRect, ) -> Option { - if !self.style.has_transform_or_perspective() { + if !self.style.has_transform_or_perspective(self.base.flags) { return None; } diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 347e88ad96e..1b15baa7eca 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -16,7 +16,7 @@ use crate::dom::NodeExt; use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::flexbox::FlexContainer; use crate::flow::BlockFormattingContext; -use crate::fragment_tree::{BaseFragmentInfo, Fragment}; +use crate::fragment_tree::{BaseFragmentInfo, Fragment, FragmentFlags}; use crate::positioned::PositioningContext; use crate::replaced::ReplacedContent; use crate::sizing::{self, ContentSizes}; @@ -131,11 +131,15 @@ impl IndependentFormattingContext { contents, }) }, - Err(contents) => Self::Replaced(ReplacedFormattingContext { - base_fragment_info: node_and_style_info.into(), - style: Arc::clone(&node_and_style_info.style), - contents, - }), + Err(contents) => { + let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into(); + base_fragment_info.flags.insert(FragmentFlags::IS_REPLACED); + Self::Replaced(ReplacedFormattingContext { + base_fragment_info, + style: Arc::clone(&node_and_style_info.style), + contents, + }) + }, } } diff --git a/components/layout_2020/fragment_tree/base_fragment.rs b/components/layout_2020/fragment_tree/base_fragment.rs index ac29bcc976d..b5e7fb3fbc5 100644 --- a/components/layout_2020/fragment_tree/base_fragment.rs +++ b/components/layout_2020/fragment_tree/base_fragment.rs @@ -88,6 +88,9 @@ bitflags! { const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 0b00000001; /// Whether or not the node that created this Fragment is a `
` element. const IS_BR_ELEMENT = 0b00000010; + /// Whether or not this Fragment was created to contain a replaced element or is + /// a replaced element. + const IS_REPLACED = 0b00000100; } } diff --git a/components/layout_2020/fragment_tree/fragment.rs b/components/layout_2020/fragment_tree/fragment.rs index 151a004aa13..b13fab0ddd4 100644 --- a/components/layout_2020/fragment_tree/fragment.rs +++ b/components/layout_2020/fragment_tree/fragment.rs @@ -192,12 +192,12 @@ impl Fragment { .translate(containing_block.origin.to_vector()); let new_manager = if fragment .style - .establishes_containing_block_for_all_descendants() + .establishes_containing_block_for_all_descendants(fragment.base.flags) { manager.new_for_absolute_and_fixed_descendants(&content_rect, &padding_rect) } else if fragment .style - .establishes_containing_block_for_absolute_descendants() + .establishes_containing_block_for_absolute_descendants(fragment.base.flags) { manager.new_for_absolute_descendants(&content_rect, &padding_rect) } else { diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 024f1ed5399..0b26e8638dd 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -18,7 +18,8 @@ use crate::dom::NodeExt; use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::{ - AbsoluteBoxOffsets, BoxFragment, CollapsedBlockMargins, Fragment, HoistedSharedFragment, + AbsoluteBoxOffsets, BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags, + HoistedSharedFragment, }; use crate::geom::{ AuOrAuto, LengthOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, @@ -144,9 +145,13 @@ impl PositioningContext { } pub(crate) fn new_for_style(style: &ComputedValues) -> Option { - if style.establishes_containing_block_for_all_descendants() { + // NB: We never make PositioningContexts for replaced elements, which is why we always + // pass false here. + if style.establishes_containing_block_for_all_descendants(FragmentFlags::empty()) { Some(Self::new_for_containing_block_for_all_descendants()) - } else if style.establishes_containing_block_for_absolute_descendants() { + } else if style + .establishes_containing_block_for_absolute_descendants(FragmentFlags::empty()) + { Some(Self { for_nearest_positioned_ancestor: Some(Vec::new()), for_nearest_containing_block_for_all_descendants: Vec::new(), diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index 243b6bf3083..3430d2ffd8b 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -20,6 +20,7 @@ use style::Zero; use webrender_api as wr; use crate::dom_traversal::Contents; +use crate::fragment_tree::FragmentFlags; use crate::geom::{ AuOrAuto, LengthOrAuto, LengthPercentageOrAuto, LogicalSides, LogicalVec2, PhysicalSides, PhysicalSize, @@ -179,13 +180,19 @@ pub(crate) trait ComputedValuesExt { &self, containing_block_writing_mode: WritingMode, ) -> LogicalSides>; - fn has_transform_or_perspective(&self) -> bool; + fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool; fn effective_z_index(&self) -> i32; fn establishes_block_formatting_context(&self) -> bool; - fn establishes_stacking_context(&self) -> bool; + fn establishes_stacking_context(&self, fragment_flags: FragmentFlags) -> bool; fn establishes_scroll_container(&self) -> bool; - fn establishes_containing_block_for_absolute_descendants(&self) -> bool; - fn establishes_containing_block_for_all_descendants(&self) -> bool; + fn establishes_containing_block_for_absolute_descendants( + &self, + fragment_flags: FragmentFlags, + ) -> bool; + fn establishes_containing_block_for_all_descendants( + &self, + fragment_flags: FragmentFlags, + ) -> bool; fn background_is_transparent(&self) -> bool; fn get_webrender_primitive_flags(&self) -> wr::PrimitiveFlags; } @@ -411,7 +418,7 @@ impl ComputedValuesExt for ComputedValues { /// Returns true if this style has a transform, or perspective property set and /// it applies to this element. - fn has_transform_or_perspective(&self) -> bool { + fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool { // "A transformable element is an element in one of these categories: // * all elements whose layout is governed by the CSS box model except for // non-replaced inline boxes, table-column boxes, and table-column-group @@ -420,8 +427,9 @@ impl ComputedValuesExt for ComputedValues { // elements with the exception of any descendant element of text content // elements." // https://drafts.csswg.org/css-transforms/#transformable-element - // FIXME(mrobinson): Properly handle tables and replaced elements here. - if self.get_box().display.is_inline_flow() { + if self.get_box().display.is_inline_flow() && + !fragment_flags.contains(FragmentFlags::IS_REPLACED) + { return false; } @@ -464,7 +472,7 @@ impl ComputedValuesExt for ComputedValues { } /// Returns true if this fragment establishes a new stacking context and false otherwise. - fn establishes_stacking_context(&self) -> bool { + fn establishes_stacking_context(&self, fragment_flags: FragmentFlags) -> bool { let effects = self.get_effects(); if effects.opacity != 1.0 { return true; @@ -474,7 +482,7 @@ impl ComputedValuesExt for ComputedValues { return true; } - if self.has_transform_or_perspective() { + if self.has_transform_or_perspective(fragment_flags) { return true; } @@ -513,8 +521,11 @@ impl ComputedValuesExt for ComputedValues { /// descendants) this method will return true, but a true return value does /// not imply that the style establishes a containing block for all descendants. /// Use `establishes_containing_block_for_all_descendants()` instead. - fn establishes_containing_block_for_absolute_descendants(&self) -> bool { - if self.establishes_containing_block_for_all_descendants() { + fn establishes_containing_block_for_absolute_descendants( + &self, + fragment_flags: FragmentFlags, + ) -> bool { + if self.establishes_containing_block_for_all_descendants(fragment_flags) { return true; } @@ -525,8 +536,11 @@ impl ComputedValuesExt for ComputedValues { /// all descendants, including fixed descendants (`position: fixed`). /// Note that this also implies that it establishes a containing block /// for absolute descendants (`position: absolute`). - fn establishes_containing_block_for_all_descendants(&self) -> bool { - if self.has_transform_or_perspective() { + fn establishes_containing_block_for_all_descendants( + &self, + fragment_flags: FragmentFlags, + ) -> bool { + if self.has_transform_or_perspective(fragment_flags) { return true; } diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index ea223ea0cce..32531b3c383 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -22,7 +22,7 @@ use super::{Table, TableSlot, TableSlotCell, TableTrack, TableTrackGroup}; use crate::context::LayoutContext; use crate::formatting_contexts::{Baselines, IndependentLayout}; use crate::fragment_tree::{ - BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, + BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags, PositioningFragment, }; use crate::geom::{AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2}; @@ -985,11 +985,15 @@ impl<'a> TableLayout<'a> { row.group_index.map_or(false, |group_index| { self.table.row_groups[group_index] .style - .establishes_containing_block_for_absolute_descendants() + .establishes_containing_block_for_absolute_descendants( + FragmentFlags::empty(), + ) }); row_group_collects_for_nearest_positioned_ancestor || row.style - .establishes_containing_block_for_absolute_descendants() + .establishes_containing_block_for_absolute_descendants( + FragmentFlags::empty(), + ) }); let mut cells_laid_out_row = Vec::new(); diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 0654489de5b..282124d4b21 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -260846,6 +260846,19 @@ {} ] ], + "transform-iframe-002.html": [ + "b9b10ea368324efa93e73476fc8084dadb89f2d0", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "transform-image-001.html": [ "0565b8dbeeb86b82993847a139c8f38b66c0b163", [ @@ -415399,6 +415412,10 @@ "d92c3705b6b9dd270d17c64fce9010a5ab1fe4f3", [] ], + "transform-iframe-002-contents.html": [ + "84f079c90bcb590e81ba39753edf723bcb123858", + [] + ], "transform-lime-square.png": [ "8f939993332e1101b921615723ec6067f3bb90a3", [] diff --git a/tests/wpt/meta/css/css-transforms/transform3d-image-scale-001.html.ini b/tests/wpt/meta/css/css-transforms/transform3d-image-scale-001.html.ini deleted file mode 100644 index 11da067d959..00000000000 --- a/tests/wpt/meta/css/css-transforms/transform3d-image-scale-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform3d-image-scale-001.html] - expected: FAIL diff --git a/tests/wpt/tests/css/css-transforms/support/transform-iframe-002-contents.html b/tests/wpt/tests/css/css-transforms/support/transform-iframe-002-contents.html new file mode 100644 index 00000000000..84f079c90bc --- /dev/null +++ b/tests/wpt/tests/css/css-transforms/support/transform-iframe-002-contents.html @@ -0,0 +1,14 @@ + + + + CSS Test (Transforms): Iframe (contents) + + + + + + diff --git a/tests/wpt/tests/css/css-transforms/transform-iframe-002.html b/tests/wpt/tests/css/css-transforms/transform-iframe-002.html new file mode 100644 index 00000000000..b9b10ea3683 --- /dev/null +++ b/tests/wpt/tests/css/css-transforms/transform-iframe-002.html @@ -0,0 +1,20 @@ + + + + CSS Test (Transforms): Iframe + + + + + +

Test passes if there is a filled green square.

+ + +