Commit 44672021 authored by Benjamin Beaudry's avatar Benjamin Beaudry Committed by Chromium LUCI CQ

[LayoutNG] Layout nested abspos in a fragmentation context

In CL:2577757, we enabled fragmentation for absolutely positioned nodes
with `height: auto` and positioned with the bottom property. That
uncovered a bug with nested abspos in a fragmentation context - the
innermost abspos was never laid out.

This CL fixes it. We now query the OOF descendants generated during the
layout pass of the outermost abspos right after the layout is completed
to lay them out - if there are any.

For the moment, the offset of the innermost abspos is still wrong, but
the crash is fixed.

Bug: 1157086
Change-Id: I1031f4837f493032feb5de047e2366afc6d69599
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2587553Reviewed-by: default avatarAlison Maher <almaher@microsoft.com>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Commit-Queue: Benjamin Beaudry <benjamin.beaudry@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#838259}
parent 397c6f3a
...@@ -61,37 +61,7 @@ void NGContainerFragmentBuilder::PropagateChildData( ...@@ -61,37 +61,7 @@ void NGContainerFragmentBuilder::PropagateChildData(
new_inline_container); new_inline_container);
} }
if (const NGPhysicalBoxFragment* fragment = PropagateOOFPositionedFragmentainerDescendants(child, child_offset);
DynamicTo<NGPhysicalBoxFragment>(&child)) {
if (fragment->HasOutOfFlowPositionedFragmentainerDescendants()) {
const auto& out_of_flow_fragmentainer_descendants =
fragment->OutOfFlowPositionedFragmentainerDescendants();
const WritingModeConverter empty_outer_size(GetWritingDirection(),
PhysicalSize());
for (const auto& descendant : out_of_flow_fragmentainer_descendants) {
const NGPhysicalContainerFragment* containing_block_fragment =
descendant.containing_block_fragment.get();
if (!containing_block_fragment)
containing_block_fragment = fragment;
LogicalOffset containing_block_offset = converter.ToLogical(
descendant.containing_block_offset, PhysicalSize());
if (!child.IsFragmentainerBox())
containing_block_offset.block_offset += child_offset.block_offset;
if (IsBlockFragmentationContextRoot()) {
containing_block_offset.block_offset +=
fragmentainer_consumed_block_size_;
}
NGLogicalStaticPosition static_position =
descendant.static_position.ConvertToLogical(empty_outer_size);
oof_positioned_fragmentainer_descendants_.emplace_back(
descendant.node, static_position, descendant.inline_container,
/* needs_block_offset_adjustment */ false, containing_block_offset,
containing_block_fragment);
}
}
}
// We only need to report if inflow or floating elements depend on the // We only need to report if inflow or floating elements depend on the
// percentage resolution block-size. OOF-positioned children resolve their // percentage resolution block-size. OOF-positioned children resolve their
...@@ -301,6 +271,47 @@ void NGContainerFragmentBuilder:: ...@@ -301,6 +271,47 @@ void NGContainerFragmentBuilder::
} }
} }
void NGContainerFragmentBuilder::PropagateOOFPositionedFragmentainerDescendants(
const NGPhysicalContainerFragment& fragment,
LogicalOffset offset) {
const NGPhysicalBoxFragment* box_fragment =
DynamicTo<NGPhysicalBoxFragment>(&fragment);
// Fragmentainer descendants are only on box fragments.
if (!box_fragment ||
!box_fragment->HasOutOfFlowPositionedFragmentainerDescendants()) {
return;
}
const WritingModeConverter converter(GetWritingDirection(), fragment.Size());
const WritingModeConverter empty_outer_size(GetWritingDirection(),
PhysicalSize());
const auto& out_of_flow_fragmentainer_descendants =
box_fragment->OutOfFlowPositionedFragmentainerDescendants();
for (const auto& descendant : out_of_flow_fragmentainer_descendants) {
const NGPhysicalContainerFragment* containing_block_fragment =
descendant.containing_block_fragment.get();
if (!containing_block_fragment)
containing_block_fragment = box_fragment;
LogicalOffset containing_block_offset =
converter.ToLogical(descendant.containing_block_offset, PhysicalSize());
if (!fragment.IsFragmentainerBox())
containing_block_offset.block_offset += offset.block_offset;
if (IsBlockFragmentationContextRoot()) {
containing_block_offset.block_offset +=
fragmentainer_consumed_block_size_;
}
NGLogicalStaticPosition static_position =
descendant.static_position.ConvertToLogical(empty_outer_size);
AddOutOfFlowFragmentainerDescendant(
{descendant.node, static_position, descendant.inline_container,
/* needs_block_offset_adjustment */ false, containing_block_offset,
containing_block_fragment});
}
}
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
String NGContainerFragmentBuilder::ToString() const { String NGContainerFragmentBuilder::ToString() const {
......
...@@ -150,6 +150,14 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -150,6 +150,14 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
// block layout algorithm, to perform the final OOF layout and positioning. // block layout algorithm, to perform the final OOF layout and positioning.
void MoveOutOfFlowDescendantCandidatesToDescendants(); void MoveOutOfFlowDescendantCandidatesToDescendants();
// Propagate the OOF descendants from a fragment to the builder. Since the OOF
// descendants on the fragment are NGPhysicalOutOfFlowPositionedNodes, we
// first have to create NGLogicalOutOfFlowPositionedNodes copies before
// appending them to our list of descendants.
void PropagateOOFPositionedFragmentainerDescendants(
const NGPhysicalContainerFragment& fragment,
LogicalOffset offset);
void SetIsSelfCollapsing() { is_self_collapsing_ = true; } void SetIsSelfCollapsing() { is_self_collapsing_ = true; }
void SetIsPushedByFloats() { is_pushed_by_floats_ = true; } void SetIsPushedByFloats() { is_pushed_by_floats_ = true; }
......
...@@ -632,10 +632,17 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants( ...@@ -632,10 +632,17 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
while (descendants->size() > 0) { while (descendants->size() > 0) {
for (auto& descendant : *descendants) { for (auto& descendant : *descendants) {
LayoutFragmentainerDescendant(descendant); scoped_refptr<const NGLayoutResult> result =
LayoutFragmentainerDescendant(descendant);
// TODO(bebeaudr): The final offset of the innermost abspos is wrong. It
// seems like it is off by exactly the offset of the outermost abspos.
// Don't we already take into account that value?
container_builder_->PropagateOOFPositionedFragmentainerDescendants(
result->PhysicalFragment(), result->OutOfFlowPositionedOffset());
} }
// Sweep any descendants that might have been added. // Sweep any descendants that might have been bubbled up from the fragment
// This happens when an absolute container has a fixed child. // to the |container_builder_|. This happens when we have nested absolute
// position elements.
descendants->Shrink(0); descendants->Shrink(0);
container_builder_->SwapOutOfFlowFragmentainerDescendants(descendants); container_builder_->SwapOutOfFlowFragmentainerDescendants(descendants);
} }
...@@ -652,7 +659,8 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants( ...@@ -652,7 +659,8 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
} }
} }
void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendant( scoped_refptr<const NGLayoutResult>
NGOutOfFlowLayoutPart::LayoutFragmentainerDescendant(
const NGLogicalOutOfFlowPositionedNode& descendant) { const NGLogicalOutOfFlowPositionedNode& descendant) {
NGBlockNode node = descendant.node; NGBlockNode node = descendant.node;
const NGPhysicalContainerFragment* containing_block_fragment = const NGPhysicalContainerFragment* containing_block_fragment =
...@@ -699,10 +707,10 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendant( ...@@ -699,10 +707,10 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendant(
builder.SetPercentageResolutionSize(container_content_size); builder.SetPercentageResolutionSize(container_content_size);
NGConstraintSpace descendant_constraint_space = builder.ToConstraintSpace(); NGConstraintSpace descendant_constraint_space = builder.ToConstraintSpace();
Layout(node, descendant_constraint_space, descendant_static_position, return Layout(node, descendant_constraint_space, descendant_static_position,
container_physical_content_size, container_info, container_physical_content_size, container_info,
default_writing_direction, /* only_layout */ nullptr, default_writing_direction, /* only_layout */ nullptr,
/* is_fragmentainer_descendant */ true); /* is_fragmentainer_descendant */ true);
} }
scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout( scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
......
...@@ -114,7 +114,8 @@ class CORE_EXPORT NGOutOfFlowLayoutPart { ...@@ -114,7 +114,8 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
void LayoutFragmentainerDescendants( void LayoutFragmentainerDescendants(
Vector<NGLogicalOutOfFlowPositionedNode>* descendants); Vector<NGLogicalOutOfFlowPositionedNode>* descendants);
void LayoutFragmentainerDescendant(const NGLogicalOutOfFlowPositionedNode&); scoped_refptr<const NGLayoutResult> LayoutFragmentainerDescendant(
const NGLogicalOutOfFlowPositionedNode&);
scoped_refptr<const NGLayoutResult> Layout( scoped_refptr<const NGLayoutResult> Layout(
NGBlockNode, NGBlockNode,
......
...@@ -1028,7 +1028,7 @@ virtual/layout_ng_block_frag/fast/multicol/vertical-rl/float-edge.html [ Pass ] ...@@ -1028,7 +1028,7 @@ virtual/layout_ng_block_frag/fast/multicol/vertical-rl/float-edge.html [ Pass ]
virtual/layout_ng_block_frag/fast/multicol/vertical-rl/nested-columns.html [ Pass ] virtual/layout_ng_block_frag/fast/multicol/vertical-rl/nested-columns.html [ Pass ]
### Tests failing with LayoutNGBlockFragmentation enabled: ### Tests failing with LayoutNGBlockFragmentation enabled:
crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-break/block-end-aligned-abspos-nested.html [ Failure Crash ] crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-break/block-end-aligned-abspos-nested.html [ Failure ]
crbug.com/1113911 virtual/layout_ng_block_frag/external/wpt/css/css-break/fieldset-001.html [ Failure ] crbug.com/1113911 virtual/layout_ng_block_frag/external/wpt/css/css-break/fieldset-001.html [ Failure ]
crbug.com/1154585 virtual/layout_ng_block_frag/external/wpt/css/css-break/ink-overflow-002.html [ Failure ] crbug.com/1154585 virtual/layout_ng_block_frag/external/wpt/css/css-break/ink-overflow-002.html [ Failure ]
crbug.com/1146973 virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html [ Failure ] crbug.com/1146973 virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html [ Failure ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment