From 9621439db08f6e16ad6c443033addf337f98158c Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Fri, 13 Sep 2024 22:42:43 +0200 Subject: [PATCH] LibWeb: Assign static position for abspos boxes nested into TFC TFC is not aware of how to correctly calculate a static position for abspos boxes, but assigning (0, 0) is better than crashing during abspos item layout. Fixes https://github.com/LadybirdBrowser/ladybird/issues/1382 --- .../abspos-pseudo-element-inside-table.txt | 18 ++++++++++++ .../abspos-pseudo-element-inside-table.html | 21 ++++++++++++++ .../LibWeb/Layout/FormattingContext.cpp | 1 - .../LibWeb/Layout/TableFormattingContext.cpp | 29 +++++++++++++++++++ .../LibWeb/Layout/TableFormattingContext.h | 2 ++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Layout/expected/table/abspos-pseudo-element-inside-table.txt create mode 100644 Tests/LibWeb/Layout/input/table/abspos-pseudo-element-inside-table.html diff --git a/Tests/LibWeb/Layout/expected/table/abspos-pseudo-element-inside-table.txt b/Tests/LibWeb/Layout/expected/table/abspos-pseudo-element-inside-table.txt new file mode 100644 index 00000000000..0d167dbccb5 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/table/abspos-pseudo-element-inside-table.txt @@ -0,0 +1,18 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x20 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x4 children: not-inline + TableWrapper <(anonymous)> at (8,8) content-size 784x4 [BFC] children: not-inline + Box at (8,8) content-size 784x4 table-box [TFC] children: not-inline + Box at (8,8) content-size 0x0 table-header-group children: not-inline + Box at (10,10) content-size 0x0 table-row children: not-inline + BlockContainer <(anonymous)> at (0,590) content-size 800x10 positioned [BFC] children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x20] overflow: [0,0 800x600] + PaintableWithLines (BlockContainer) [8,8 784x4] overflow: [0,8 800x592] + PaintableWithLines (TableWrapper(anonymous)) [8,8 784x4] overflow: [0,8 800x592] + PaintableBox (Box
) [8,8 784x4] overflow: [0,8 800x592] + PaintableBox (Box) [8,8 0x0] overflow: [0,10 800x590] + PaintableBox (Box) [10,10 0x0] overflow: [0,590 800x10] + PaintableWithLines (BlockContainer(anonymous)) [0,590 800x10] diff --git a/Tests/LibWeb/Layout/input/table/abspos-pseudo-element-inside-table.html b/Tests/LibWeb/Layout/input/table/abspos-pseudo-element-inside-table.html new file mode 100644 index 00000000000..702e671f536 --- /dev/null +++ b/Tests/LibWeb/Layout/input/table/abspos-pseudo-element-inside-table.html @@ -0,0 +1,21 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 8c7e593e0aa..b4cbec91b6c 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -152,7 +152,6 @@ Optional FormattingContext::formatting_context_type_cre // FIXME: We need this for elements return Type::InternalDummy; } - return {}; } diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp index 62d72d8d753..c33c40bdb43 100644 --- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp @@ -1607,6 +1607,35 @@ void TableFormattingContext::run_until_width_calculation(AvailableSpace const& a compute_table_width(); } +void TableFormattingContext::parent_context_did_dimension_child_root_box() +{ + if (m_layout_mode != LayoutMode::Normal) + return; + + context_box().for_each_in_subtree_of_type([&](Layout::Box const& box) { + if (box.is_absolutely_positioned()) { + // FIXME: calculate_static_position_rect() is not aware of how to correctly calculate static position for + // a box nested inside a table, but we need to set some value, so layout_absolutely_positioned_element() + // won't crash trying to access it. + m_state.get_mutable(box).set_static_position_rect(calculate_static_position_rect(box)); + } + + if (formatting_context_type_created_by_box(box).has_value()) { + return TraversalDecision::SkipChildrenAndContinue; + } + + return TraversalDecision::Continue; + }); + + for (auto& child : context_box().contained_abspos_children()) { + auto& box = verify_cast(*child); + auto& cb_state = m_state.get(*box.containing_block()); + auto available_width = AvailableSize::make_definite(cb_state.content_width() + cb_state.padding_left + cb_state.padding_right); + auto available_height = AvailableSize::make_definite(cb_state.content_height() + cb_state.padding_top + cb_state.padding_bottom); + layout_absolutely_positioned_element(box, AvailableSpace(available_width, available_height)); + } +} + void TableFormattingContext::run(AvailableSpace const& available_space) { m_available_space = available_space; diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h index e8c9ae8754e..a5a3fecb8d8 100644 --- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h @@ -37,6 +37,8 @@ public: static bool border_is_less_specific(const CSS::BorderData& a, const CSS::BorderData& b); + virtual void parent_context_did_dimension_child_root_box() override; + private: CSSPixels run_caption_layout(CSS::CaptionSide); CSSPixels compute_capmin();