LibWeb: Don't (anonymously) wrap table boxes that are already wrapped

Instead just update the existing wrapper with computed values from the
table box, to insure that upside-down "inheritance" works as expected.

This allows table fixup to run on partially updated layout trees without
adding a new layer of unnecessary wrappers every time.
This commit is contained in:
Andreas Kling 2025-01-11 20:22:24 +01:00 committed by Andreas Kling
parent e8b5667a9e
commit b41a490e40
Notes: github-actions[bot] 2025-01-18 20:02:13 +00:00
3 changed files with 25 additions and 0 deletions

View file

@ -1109,6 +1109,11 @@ GC::Ref<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
return *wrapper;
}
void NodeWithStyle::set_computed_values(NonnullOwnPtr<CSS::ComputedValues> computed_values)
{
m_computed_values = move(computed_values);
}
void NodeWithStyle::reset_table_box_computed_values_used_by_wrapper_to_init_values()
{
VERIFY(this->display().is_table_inside());

View file

@ -191,6 +191,9 @@ public:
// https://drafts.csswg.org/css-ui/#propdef-user-select
CSS::UserSelect user_select_used_value() const;
[[nodiscard]] bool has_been_wrapped_in_table_wrapper() const { return m_has_been_wrapped_in_table_wrapper; }
void set_has_been_wrapped_in_table_wrapper(bool value) { m_has_been_wrapped_in_table_wrapper = value; }
protected:
Node(DOM::Document&, DOM::Node*);
@ -211,6 +214,8 @@ private:
bool m_is_flex_item { false };
bool m_is_grid_item { false };
bool m_has_been_wrapped_in_table_wrapper { false };
GeneratedFor m_generated_for { GeneratedFor::NotGenerated };
u32 m_initial_quote_nesting_level { 0 };
@ -240,6 +245,8 @@ public:
virtual void visit_edges(Cell::Visitor& visitor) override;
void set_computed_values(NonnullOwnPtr<CSS::ComputedValues>);
protected:
NodeWithStyle(DOM::Document&, DOM::Node*, GC::Ref<CSS::ComputedProperties>);
NodeWithStyle(DOM::Document&, DOM::Node*, NonnullOwnPtr<CSS::ComputedValues>);

View file

@ -784,6 +784,11 @@ Vector<GC::Root<Box>> TreeBuilder::generate_missing_parents(NodeWithStyle& root)
// An anonymous table-wrapper box must be generated around each table-root.
if (parent.display().is_table_inside()) {
if (parent.has_been_wrapped_in_table_wrapper()) {
VERIFY(parent.parent());
VERIFY(parent.parent()->is_table_wrapper());
return TraversalDecision::Continue;
}
table_roots_to_wrap.append(parent);
}
@ -797,6 +802,12 @@ Vector<GC::Root<Box>> TreeBuilder::generate_missing_parents(NodeWithStyle& root)
auto wrapper_computed_values = table_box->computed_values().clone_inherited_values();
table_box->transfer_table_box_computed_values_to_wrapper_computed_values(*wrapper_computed_values);
if (parent.is_table_wrapper()) {
auto& existing_wrapper = static_cast<TableWrapper&>(parent);
existing_wrapper.set_computed_values(move(wrapper_computed_values));
continue;
}
auto wrapper = parent.heap().allocate<TableWrapper>(parent.document(), nullptr, move(wrapper_computed_values));
parent.remove_child(*table_box);
@ -806,6 +817,8 @@ Vector<GC::Root<Box>> TreeBuilder::generate_missing_parents(NodeWithStyle& root)
parent.insert_before(*wrapper, *nearest_sibling);
else
parent.append_child(*wrapper);
table_box->set_has_been_wrapped_in_table_wrapper(true);
}
return table_roots_to_wrap;