diff --git a/components/layout/block.rs b/components/layout/block.rs index 89342dd7c6b..df5dddaf500 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -903,7 +903,7 @@ impl BlockFlow { /// 10.6.7. /// /// For absolute flows, we store the calculated content block-size for the flow. We defer the - /// calculation of the other values until a later traversal. + /// calculation of the other values until a later traversal at root flow. /// /// When `fragmentation_context` is given (not `None`), this should fit as much of the content /// as possible within the available block size. @@ -1200,6 +1200,8 @@ impl BlockFlow { .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { self.propagate_early_absolute_position_info_to_children(); + // Return early until the absolute flow tree traversal at root flow. + // Assigning block size for absolute flow will happen in `traverse_absolute_flows` below. return None; } diff --git a/components/layout/flow.rs b/components/layout/flow.rs index b8a16933ae6..074f0ad273a 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -557,6 +557,11 @@ pub trait MutableOwnedFlowUtils { /// Set this flow as the Containing Block for all the absolute descendants. fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants); + /// Push absolute descendants to this flow. + /// + /// Set this flow as the Containing Block for the provided absolute descendants. + fn push_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants); + /// Sets the flow as the containing block for all absolute descendants that have been marked /// as having reached their containing block. This is needed in order to handle cases like: /// @@ -1364,6 +1369,26 @@ impl MutableOwnedFlowUtils for FlowRef { } } + /// Push absolute descendants for this flow. + /// + /// Set yourself as the Containing Block for the provided absolute descendants. + /// + /// This is called when retreiving layout root if it's not absolute positioned. We can't just + /// call `set_absolute_descendants` because it might contain other abs_descendants already. + /// We push descendants instead of replace it since it won't cause circular reference. + fn push_absolute_descendants(&mut self, mut abs_descendants: AbsoluteDescendants) { + let this = self.clone(); + let base = FlowRef::deref_mut(self).mut_base(); + + for descendant_link in abs_descendants.descendant_links.iter_mut() { + debug_assert!(!descendant_link.has_reached_containing_block); + let descendant_base = FlowRef::deref_mut(&mut descendant_link.flow).mut_base(); + descendant_base.absolute_cb.set(this.clone()); + } + + base.abs_descendants.push_descendants(abs_descendants); + } + /// Sets the flow as the containing block for all absolute descendants that have been marked /// as having reached their containing block. This is needed in order to handle cases like: /// diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 79d84526b48..ac1a7fe21ef 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -44,7 +44,7 @@ use layout::context::RegisteredPainter; use layout::context::RegisteredPainters; use layout::display_list::items::WebRenderImageInfo; use layout::display_list::{IndexableText, ToLayout}; -use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils}; +use layout::flow::{Flow, FlowFlags, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; use layout::incremental::{RelayoutMode, SpecialRestyleDamage}; use layout::layout_debug; @@ -950,11 +950,20 @@ impl LayoutThread { let mut flow = match result { ConstructionResult::Flow(mut flow, abs_descendants) => { // Note: Assuming that the root has display 'static' (as per - // CSS Section 9.3.1). Otherwise, if it were absolutely - // positioned, it would return a reference to itself in - // `abs_descendants` and would lead to a circular reference. - // Set Root as CB for any remaining absolute descendants. - flow.set_absolute_descendants(abs_descendants); + // CSS Section 9.3.1). If it was absolutely positioned, + // it would return a reference to itself in `abs_descendants` + // and would lead to a circular reference. Otherwise, we + // set Root as CB and push remaining absolute descendants. + if flow + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { + flow.set_absolute_descendants(abs_descendants); + } else { + flow.push_absolute_descendants(abs_descendants); + } + flow }, _ => return None, diff --git a/tests/wpt/metadata/css/CSS2/positioning/abspos-containing-block-005.xht.ini b/tests/wpt/metadata/css/CSS2/positioning/abspos-containing-block-005.xht.ini deleted file mode 100644 index 455df0b3f8b..00000000000 --- a/tests/wpt/metadata/css/CSS2/positioning/abspos-containing-block-005.xht.ini +++ /dev/null @@ -1,3 +0,0 @@ -[abspos-containing-block-005.xht] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata/css/CSS2/positioning/abspos-containing-block-006.xht.ini b/tests/wpt/metadata/css/CSS2/positioning/abspos-containing-block-006.xht.ini deleted file mode 100644 index 4131744de54..00000000000 --- a/tests/wpt/metadata/css/CSS2/positioning/abspos-containing-block-006.xht.ini +++ /dev/null @@ -1,3 +0,0 @@ -[abspos-containing-block-006.xht] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata/css/filter-effects/filtered-html-is-not-container.html.ini b/tests/wpt/metadata/css/filter-effects/filtered-html-is-not-container.html.ini deleted file mode 100644 index b366310b98b..00000000000 --- a/tests/wpt/metadata/css/filter-effects/filtered-html-is-not-container.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[filtered-html-is-not-container.html] - expected: FAIL