From fbb3b06462e8f25033e2e35dc8f7271cf1d96197 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 24 Apr 2025 13:33:20 +0200 Subject: [PATCH] LibWeb: Don't assume table caption box wants to create a BFC Instead, use the generic create_independent_formatting_context_if_needed so that unusual situations like image-as-table-caption don't crash. This logic clearly needs more work, but let's at least do better than crashing. This gives us 26 new subtest passes on WPT. --- Libraries/LibWeb/Layout/FormattingContext.cpp | 4 +- .../LibWeb/Layout/TableFormattingContext.cpp | 17 +- .../css/css-tables/table-model-fixup-2.txt | 46 ++ .../css/css-tables/support/base.css | 21 + .../css/css-tables/table-model-fixup-2.html | 398 ++++++++++++++++++ .../wpt-import/css/support/blue32x32.ico | Bin 0 -> 326 bytes 6 files changed, 477 insertions(+), 9 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/css/css-tables/table-model-fixup-2.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-tables/support/base.css create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-tables/table-model-fixup-2.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/support/blue32x32.ico diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp index db4f4e7f684..b3dfad619ba 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -176,7 +176,7 @@ Optional FormattingContext::formatting_context_type_cre // FIXME: This is a hack. Get rid of it. struct ReplacedFormattingContext : public FormattingContext { ReplacedFormattingContext(LayoutState& state, LayoutMode layout_mode, Box const& box) - : FormattingContext(Type::Block, layout_mode, state, box) + : FormattingContext(Type::InternalReplaced, layout_mode, state, box) { } virtual CSSPixels automatic_content_width() const override { return 0; } @@ -187,7 +187,7 @@ struct ReplacedFormattingContext : public FormattingContext { // FIXME: This is a hack. Get rid of it. struct DummyFormattingContext : public FormattingContext { DummyFormattingContext(LayoutState& state, LayoutMode layout_mode, Box const& box) - : FormattingContext(Type::Block, layout_mode, state, box) + : FormattingContext(Type::InternalDummy, layout_mode, state, box) { } virtual CSSPixels automatic_content_width() const override { return 0; } diff --git a/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Libraries/LibWeb/Layout/TableFormattingContext.cpp index c4277db4b66..74a18425702 100644 --- a/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/TableFormattingContext.cpp @@ -38,15 +38,18 @@ CSSPixels TableFormattingContext::run_caption_layout(CSS::CaptionSide phase) if (!child->display().is_table_caption() || child->computed_values().caption_side() != phase) { continue; } + auto const& child_box = as(*child); // The caption boxes are principal block-level boxes that retain their own content, padding, margin, and border areas, // and are rendered as normal block boxes inside the table wrapper box, as described in https://www.w3.org/TR/CSS22/tables.html#model - auto caption_context = make(m_state, m_layout_mode, *as(child), this); - caption_context->run(*m_available_space); - VERIFY(child->is_box()); - auto const& child_box = static_cast(*child); - // FIXME: Since caption only has inline children, BlockFormattingContext doesn't resolve the vertical metrics. - // We need to do it manually here. - caption_context->resolve_vertical_box_model_metrics(child_box, m_available_space->width.to_px_or_zero()); + if (auto caption_context = create_independent_formatting_context_if_needed(m_state, m_layout_mode, child_box)) { + caption_context->run(*m_available_space); + // FIXME: If caption only has inline children, BlockFormattingContext doesn't resolve the vertical metrics. + // We need to do it manually here. + if (caption_context->type() == FormattingContext::Type::Block) { + static_cast(*caption_context).resolve_vertical_box_model_metrics(child_box, m_available_space->width.to_px_or_zero()); + } + } + auto const& caption_state = m_state.get(child_box); if (phase == CSS::CaptionSide::Top) { m_state.get_mutable(table_box()).set_content_y(caption_state.content_height() + caption_state.margin_box_bottom()); diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-tables/table-model-fixup-2.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-tables/table-model-fixup-2.txt new file mode 100644 index 00000000000..3c2feb3aec9 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-tables/table-model-fixup-2.txt @@ -0,0 +1,46 @@ +Harness status: OK + +Found 40 tests + +26 Pass +14 Fail +Fail Replaced elements inside a table cannot be table-row and are considered inline -- input elements (width) +Fail Replaced elements inside a table cannot be table-row and are considered inline -- input elements (top) +Fail Replaced elements inside a table cannot be table-row and are considered inline -- img elements (width) +Fail Replaced elements inside a table cannot be table-row and are considered inline -- img elements (top) +Fail Replaced elements inside a table cannot be table-column and are considered inline -- input elements (width) +Pass Replaced elements inside a table cannot be table-column and are considered inline -- input elements (top) +Fail Replaced elements inside a table cannot be table-column and are considered inline -- img elements (width) +Pass Replaced elements inside a table cannot be table-column and are considered inline -- img elements (top) +Fail Replaced elements inside a table cannot be table-cell and are considered inline -- input elements (width) +Pass Replaced elements inside a table cannot be table-cell and are considered inline -- input elements (top) +Fail Replaced elements inside a table cannot be table-cell and are considered inline -- img elements (width) +Pass Replaced elements inside a table cannot be table-cell and are considered inline -- img elements (top) +Pass Replaced elements outside a table cannot be inline-table and are considered inline -- input=text elements +Pass Replaced elements outside a table cannot be inline-table and are considered inline -- input=button elements +Pass Replaced elements outside a table cannot be inline-table and are considered inline -- input=file elements +Pass Replaced elements outside a table cannot be inline-table and are considered inline -- img elements +Pass Replaced elements outside a table cannot be table and are considered block -- input=text elements +Pass Replaced elements outside a table cannot be table and are considered block -- input=button elements +Pass Replaced elements outside a table cannot be table and are considered block -- input=file elements +Pass Replaced elements outside a table cannot be table and are considered block -- img elements +Fail Replaced elements outside a table cannot be table-row and are considered inline -- input=text elements +Fail Replaced elements outside a table cannot be table-row and are considered inline -- input=button elements +Fail Replaced elements outside a table cannot be table-row and are considered inline -- input=file elements +Pass Replaced elements outside a table cannot be table-row and are considered inline -- img elements +Fail Replaced elements outside a table cannot be table-row-group and are considered inline -- input=text elements +Fail Replaced elements outside a table cannot be table-row-group and are considered inline -- input=button elements +Fail Replaced elements outside a table cannot be table-row-group and are considered inline -- input=file elements +Pass Replaced elements outside a table cannot be table-row-group and are considered inline -- img elements +Pass Replaced elements outside a table cannot be table-column and are considered inline inline -- input=text elements +Pass Replaced elements outside a table cannot be table-column and are considered inline -- input=button elements +Pass Replaced elements outside a table cannot be table-column and are considered inline -- input=file elements +Pass Replaced elements outside a table cannot be table-column and are considered inline -- img elements +Pass Replaced elements outside a table cannot be table-cell and are considered inline -- input=text elements +Pass Replaced elements outside a table cannot be table-cell and are considered inline -- input=button elements +Pass Replaced elements outside a table cannot be table-cell and are considered inline -- input=file elements +Pass Replaced elements outside a table cannot be table-cell and are considered inline -- img elements +Pass Replaced elements outside a table cannot be table-caption and are considered inline -- input=text elements +Pass Replaced elements outside a table cannot be table-caption and are considered inline -- input=button elements +Pass Replaced elements outside a table cannot be table-caption and are considered inline -- input=file elements +Pass Replaced elements outside a table cannot be table-caption and are considered inline -- img elements \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-tables/support/base.css b/Tests/LibWeb/Text/input/wpt-import/css/css-tables/support/base.css new file mode 100644 index 00000000000..52be1bb4e52 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-tables/support/base.css @@ -0,0 +1,21 @@ +/* custom table tags */ + + x-table { display: table; } + x-colgroup { display: table-column-group; } + x-col { display: table-column; } + x-tbody { display: table-row-group; } + x-thead { display: table-header-group; } + x-tfoot { display: table-footer-group; } + x-tr { display: table-row; } + x-td { display: table-cell; } + x-caption { display: table-caption; } + +/* layout of the page */ + + hr + p { font-weight: bold; margin-bottom: 0; } + p + p { margin-top: 0; } + + html, body { padding: 0; margin: 0; } + main, #log { padding: 10px; width: 50%; box-sizing: border-box; } + main { float: left; } + #log { float: right; background: #eee; } \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-tables/table-model-fixup-2.html b/Tests/LibWeb/Text/input/wpt-import/css/css-tables/table-model-fixup-2.html new file mode 100644 index 00000000000..4c3919dfa53 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-tables/table-model-fixup-2.html @@ -0,0 +1,398 @@ + + + + + + + + + +
+ +

Table fixup

+

Check that replaced elements display types are handled properly in fixup

+ +
+

Both input fields should look identical, on their own line:

+

Replaced elements inside a table cannot be table-row and are considered inline -- input elements (width)

+
+ + + + +
+
+

Both input fields should look identical and be on the same line:

+

Replaced elements inside a table cannot be table-row and are considered inline -- input elements (top)

+
+ + + + +
+ +
+

Both images should look identical, on their own line:

+

Replaced elements inside a table cannot be table-row and are considered inline -- img elements (width)

+
+ + + + +
+
+

Both images should look identical and be on the same line:

+

Replaced elements inside a table cannot be table-row and are considered inline -- img elements (top)

+
+ + + + +
+ +
+

Both input fields should look identical, on their own line:

+

Replaced elements inside a table cannot be table-column and are considered inline -- input elements (width)

+
+ + + + +
+
+

Both input fields should look identical and be on the same line:

+

Replaced elements inside a table cannot be table-column and are considered inline -- input elements (top)

+
+ + + + +
+ +
+

Both images should look identical, on their own line:

+

Replaced elements inside a table cannot be table-column and are considered inline -- img elements (width)

+
+ + + + +
+
+

Both images should look identical and be on the same line:

+

Replaced elements inside a table cannot be table-column and are considered inline -- img elements (top)

+
+ + + + +
+ +
+

Both input fields should look identical, on their own line:

+

Replaced elements inside a table cannot be table-cell and are considered inline -- input elements (width)

+
+ + + + +
+
+

Both input fields should look identical and be on the same line:

+

Replaced elements inside a table cannot be table-cell and are considered inline -- input elements (top)

+
+ + + +
+ +
+

Both images should look identical, on their own line:

+

Replaced elements inside a table cannot be table-cell and are considered inline -- img elements (width)

+
+ + + + +
+
+

Both images should look identical and be on the same line:

+

Replaced elements inside a table cannot be table-cell and are considered inline -- img elements (top)

+
+ + + + +
+ +
+

Both text inputs should share the same line:

+

Replaced elements outside a table cannot be inline-table and are considered inline -- input=text elements

+
+ + +
+ +
+

Both button inputs should share the same line:

+

Replaced elements outside a table cannot be inline-table and are considered inline -- input=button elements

+
+ + +
+ +
+

Both file inputs should share the same line:

+

Replaced elements outside a table cannot be inline-table and are considered inline -- input=file elements

+
+ + +
+ +
+

Both images should share the same line:

+

Replaced elements outside a table cannot be inline-table and are considered inline -- img elements

+
+ + +
+ +
+

Both text inputs should stand on their own line:

+

Replaced elements outside a table cannot be table and are considered block -- input=text elements

+
+ + +
+ +
+

Both button inputs should stand on their own line:

+

Replaced elements outside a table cannot be table and are considered block -- input=button elements

+
+ + +
+ +
+

Both file inputs should stand on their own line:

+

Replaced elements outside a table cannot be table and are considered block -- input=file elements

+
+ + +
+ +
+

Both images should stand on their own line:

+

Replaced elements outside a table cannot be table and are considered block -- img elements

+
+ + +
+ +
+

Both text inputs should share the same line:

+

Replaced elements outside a table cannot be table-row and are considered inline -- input=text elements

+
+ + +
+ +
+

Both button inputs should share the same line:

+

Replaced elements outside a table cannot be table-row and are considered inline -- input=button elements

+
+ + +
+ +
+

Both file inputs should share the same line:

+

Replaced elements outside a table cannot be table-row and are considered inline -- input=file elements

+
+ + +
+ +
+

Both images should share the same line:

+

Replaced elements outside a table cannot be table-row and are considered inline -- img elements

+
+ + +
+ +
+

Both text inputs should share the same line:

+

Replaced elements outside a table cannot be table-row-group and are considered inline -- input=text elements

+
+ + +
+ +
+

Both button inputs should share the same line:

+

Replaced elements outside a table cannot be table-row-group and are considered inline -- input=button elements

+
+ + +
+ +
+

Both file inputs should share the same line:

+

Replaced elements outside a table cannot be table-row-group and are considered inline -- input=file elements

+
+ + +
+ +
+

Both images should share the same line:

+

Replaced elements outside a table cannot be table-row-group and are considered inline -- img elements

+
+ + +
+ +
+

Both text inputs should share the same line:

+

Replaced elements outside a table cannot be table-column and are considered inline inline -- input=text elements

+
+ + +
+ +
+

Both button inputs should share the same line:

+

Replaced elements outside a table cannot be table-column and are considered inline -- input=button elements

+
+ + +
+ +
+

Both file inputs should share the same line:

+

Replaced elements outside a table cannot be table-column and are considered inline -- input=file elements

+
+ + +
+ +
+

Both images should share the same line:

+

Replaced elements outside a table cannot be table-column and are considered inline -- img elements

+
+ + +
+ +
+

Both text inputs should share the same line:

+

Replaced elements outside a table cannot be table-cell and are considered inline -- input=text elements

+
+ + +
+ +
+

Both button inputs should share the same line:

+

Replaced elements outside a table cannot be table-cell and are considered inline -- input=button elements

+
+ + +
+ +
+

Both file inputs should share the same line:

+

Replaced elements outside a table cannot be table-cell and are considered inline -- input=file elements

+
+ + +
+ +
+

Both images should share the same line:

+

Replaced elements outside a table cannot be table-cell and are considered inline -- img elements

+
+ + +
+ +
+

Both text inputs should share the same line:

+

Replaced elements outside a table cannot be table-caption and are considered inline -- input=text elements

+
+ + +
+ +
+

Both button inputs should share the same line:

+

Replaced elements outside a table cannot be table-caption and are considered inline -- input=button elements

+
+ + +
+ +
+

Both file inputs should share the same line:

+

Replaced elements outside a table cannot be table-caption and are considered inline -- input=file elements

+
+ + +
+ +
+

Both images should share the same line:

+

Replaced elements outside a table cannot be table-caption and are considered inline -- img elements

+
+ + +
+ +
diff --git a/Tests/LibWeb/Text/input/wpt-import/css/support/blue32x32.ico b/Tests/LibWeb/Text/input/wpt-import/css/support/blue32x32.ico new file mode 100644 index 0000000000000000000000000000000000000000..5844dd614c22028ce81422233c0aa400a6f41e0d GIT binary patch literal 326 ucmZQzU}RuqP*7k3(*}$T3}Orn3>pj!3qDFPP& literal 0 HcmV?d00001