LibWeb: Fix style updates for table box nodes
On style update, we have to preserve the invariant established when we built the layout tree - some properties are applied to the table wrapper and the table box values are reset to their initial values. This also ensures that the containing block of a table box is always a table wrapper, which isn't the case if we set absolute position on the box instead of the wrapper. Fixes #19452.
This commit is contained in:
parent
e28578363a
commit
55f1a70577
Notes:
sideshowbarker
2024-07-17 11:33:34 +09:00
Author: https://github.com/axgallo Commit: https://github.com/SerenityOS/serenity/commit/55f1a70577 Pull-request: https://github.com/SerenityOS/serenity/pull/19558 Issue: https://github.com/SerenityOS/serenity/issues/19452
5 changed files with 57 additions and 15 deletions
|
@ -0,0 +1,18 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x0 children: not-inline
|
||||
TableWrapper <(anonymous)> at (8,8) content-size 6x6 positioned [BFC] children: not-inline
|
||||
Box <table#t> at (8,8) content-size 6x6 table-box [TFC] children: not-inline
|
||||
BlockContainer <(anonymous)> (not painted) children: inline
|
||||
TextNode <#text>
|
||||
Box <tbody> at (8,8) content-size 2x2 table-row-group children: not-inline
|
||||
Box <tr> at (10,10) content-size 2x2 table-row children: not-inline
|
||||
BlockContainer <(anonymous)> (not painted) children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <td> at (11,11) content-size 0x0 table-cell [BFC] children: not-inline
|
||||
BlockContainer <(anonymous)> (not painted) children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> (not painted) children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
|
@ -0,0 +1,12 @@
|
|||
<table id="t">
|
||||
<tr>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
t = document.querySelector("#t");
|
||||
console.log(t);
|
||||
t.style.position = "absolute";
|
||||
window.getComputedStyle(t);
|
||||
</script>
|
|
@ -26,6 +26,7 @@
|
|||
#include <LibWeb/Layout/BlockContainer.h>
|
||||
#include <LibWeb/Layout/FormattingContext.h>
|
||||
#include <LibWeb/Layout/Node.h>
|
||||
#include <LibWeb/Layout/TableWrapper.h>
|
||||
#include <LibWeb/Layout/TextNode.h>
|
||||
#include <LibWeb/Layout/Viewport.h>
|
||||
#include <LibWeb/Platform/FontPlugin.h>
|
||||
|
@ -734,6 +735,10 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
|
|||
} else if (aspect_ratio->is_ratio()) {
|
||||
computed_values.set_aspect_ratio({ false, aspect_ratio->as_ratio().ratio() });
|
||||
}
|
||||
if (display().is_table_inside() && is<TableWrapper>(parent())) {
|
||||
auto& wrapper_computed_values = static_cast<TableWrapper*>(parent())->m_computed_values;
|
||||
transfer_table_box_computed_values_to_wrapper_computed_values(wrapper_computed_values);
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::is_root_element() const
|
||||
|
@ -810,6 +815,24 @@ void NodeWithStyle::reset_table_box_computed_values_used_by_wrapper_to_init_valu
|
|||
mutable_computed_values.set_margin(CSS::InitialValues::margin());
|
||||
}
|
||||
|
||||
void NodeWithStyle::transfer_table_box_computed_values_to_wrapper_computed_values(CSS::ComputedValues& wrapper_computed_values)
|
||||
{
|
||||
// The computed values of properties 'position', 'float', 'margin-*', 'top', 'right', 'bottom', and 'left' on the table element are used on the table wrapper box and not the table box;
|
||||
// all other values of non-inheritable properties are used on the table box and not the table wrapper box.
|
||||
// (Where the table element's values are not used on the table and table wrapper boxes, the initial values are used instead.)
|
||||
auto& mutable_wrapper_computed_values = static_cast<CSS::MutableComputedValues&>(wrapper_computed_values);
|
||||
if (display().is_inline_outside())
|
||||
mutable_wrapper_computed_values.set_display(CSS::Display::from_short(CSS::Display::Short::InlineBlock));
|
||||
else
|
||||
mutable_wrapper_computed_values.set_display(CSS::Display::from_short(CSS::Display::Short::FlowRoot));
|
||||
mutable_wrapper_computed_values.set_position(computed_values().position());
|
||||
mutable_wrapper_computed_values.set_inset(computed_values().inset());
|
||||
mutable_wrapper_computed_values.set_float(computed_values().float_());
|
||||
mutable_wrapper_computed_values.set_clear(computed_values().clear());
|
||||
mutable_wrapper_computed_values.set_margin(computed_values().margin());
|
||||
reset_table_box_computed_values_used_by_wrapper_to_init_values();
|
||||
}
|
||||
|
||||
void Node::set_paintable(JS::GCPtr<Painting::Paintable> paintable)
|
||||
{
|
||||
m_paintable = move(paintable);
|
||||
|
|
|
@ -195,13 +195,15 @@ public:
|
|||
|
||||
JS::NonnullGCPtr<NodeWithStyle> create_anonymous_wrapper() const;
|
||||
|
||||
void reset_table_box_computed_values_used_by_wrapper_to_init_values();
|
||||
void transfer_table_box_computed_values_to_wrapper_computed_values(CSS::ComputedValues& wrapper_computed_values);
|
||||
|
||||
protected:
|
||||
NodeWithStyle(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
|
||||
NodeWithStyle(DOM::Document&, DOM::Node*, CSS::ComputedValues);
|
||||
|
||||
private:
|
||||
void reset_table_box_computed_values_used_by_wrapper_to_init_values();
|
||||
|
||||
CSS::ComputedValues m_computed_values;
|
||||
RefPtr<Gfx::Font const> m_font;
|
||||
CSSPixels m_line_height { 0 };
|
||||
|
|
|
@ -592,20 +592,7 @@ void TreeBuilder::generate_missing_parents(NodeWithStyle& root)
|
|||
auto& parent = *table_box->parent();
|
||||
|
||||
CSS::ComputedValues wrapper_computed_values;
|
||||
// The computed values of properties 'position', 'float', 'margin-*', 'top', 'right', 'bottom', and 'left' on the table element are used on the table wrapper box and not the table box;
|
||||
// all other values of non-inheritable properties are used on the table box and not the table wrapper box.
|
||||
// (Where the table element's values are not used on the table and table wrapper boxes, the initial values are used instead.)
|
||||
auto& mutable_wrapper_computed_values = static_cast<CSS::MutableComputedValues&>(wrapper_computed_values);
|
||||
if (table_box->display().is_inline_outside())
|
||||
mutable_wrapper_computed_values.set_display(CSS::Display::from_short(CSS::Display::Short::InlineBlock));
|
||||
else
|
||||
mutable_wrapper_computed_values.set_display(CSS::Display::from_short(CSS::Display::Short::FlowRoot));
|
||||
mutable_wrapper_computed_values.set_position(table_box->computed_values().position());
|
||||
mutable_wrapper_computed_values.set_inset(table_box->computed_values().inset());
|
||||
mutable_wrapper_computed_values.set_float(table_box->computed_values().float_());
|
||||
mutable_wrapper_computed_values.set_clear(table_box->computed_values().clear());
|
||||
mutable_wrapper_computed_values.set_margin(table_box->computed_values().margin());
|
||||
table_box->reset_table_box_computed_values_used_by_wrapper_to_init_values();
|
||||
table_box->transfer_table_box_computed_values_to_wrapper_computed_values(wrapper_computed_values);
|
||||
|
||||
auto wrapper = parent.heap().allocate_without_realm<TableWrapper>(parent.document(), nullptr, move(wrapper_computed_values));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue