From f5a3d282fbc47177285d7635284d9bd1c00dc04a Mon Sep 17 00:00:00 2001 From: Wu Yu Wei Date: Tue, 19 Apr 2022 14:57:03 +0800 Subject: [PATCH] Actually check if root is absolute positioned --- components/layout/block.rs | 4 +++- components/layout/flow.rs | 25 +++++++++++++++++++++++++ components/layout_thread/lib.rs | 21 +++++++++++++++------ 3 files changed, 43 insertions(+), 7 deletions(-) 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,