LibWeb: Don't relocate fragments across atomic inline boundary
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Push notes / build (push) Waiting to run

All fragments inside an atomic inline box should stay within that box,
otherwise we'll screw up the paint order and paint them behind things
that they're supposed to be on top of.

This fixes an issue with inline-block content not appearing on sites
like Google Docs and Reddit, among others.
This commit is contained in:
Andreas Kling 2025-08-24 17:34:46 +02:00 committed by Andreas Kling
commit 0d2800e411
Notes: github-actions[bot] 2025-08-24 19:01:02 +00:00
8 changed files with 47 additions and 7 deletions

View file

@ -258,6 +258,8 @@ void LayoutState::commit(Box& root)
auto try_to_relocate_fragment_in_inline_node = [&](auto& fragment, size_t line_index) -> bool { auto try_to_relocate_fragment_in_inline_node = [&](auto& fragment, size_t line_index) -> bool {
for (auto const* parent = fragment.layout_node().parent(); parent; parent = parent->parent()) { for (auto const* parent = fragment.layout_node().parent(); parent; parent = parent->parent()) {
if (parent->is_atomic_inline())
break;
if (is<InlineNode>(*parent)) { if (is<InlineNode>(*parent)) {
auto& inline_node = const_cast<InlineNode&>(static_cast<InlineNode const&>(*parent)); auto& inline_node = const_cast<InlineNode&>(static_cast<InlineNode const&>(*parent));
auto line_paintable = inline_node.create_paintable_for_line_with_index(line_index); auto line_paintable = inline_node.create_paintable_for_line_with_index(line_index);

View file

@ -68,7 +68,7 @@ Utf16View LineBoxFragment::text() const
bool LineBoxFragment::is_atomic_inline() const bool LineBoxFragment::is_atomic_inline() const
{ {
return layout_node().is_replaced_box() || (layout_node().display().is_inline_outside() && !layout_node().display().is_flow_inside()); return layout_node().is_atomic_inline();
} }
CSS::Direction LineBoxFragment::resolve_glyph_run_direction(Gfx::GlyphRun::TextType text_type) const CSS::Direction LineBoxFragment::resolve_glyph_run_direction(Gfx::GlyphRun::TextType text_type) const

View file

@ -1125,6 +1125,14 @@ bool Node::is_inline_table() const
return display.is_inline_outside() && display.is_table_inside(); return display.is_inline_outside() && display.is_table_inside();
} }
bool Node::is_atomic_inline() const
{
if (is_replaced_box())
return true;
auto display = this->display();
return display.is_inline_outside() && !display.is_flow_inside();
}
GC::Ref<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const GC::Ref<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
{ {
auto wrapper = heap().allocate<BlockContainer>(const_cast<DOM::Document&>(document()), nullptr, computed_values().clone_inherited_values()); auto wrapper = heap().allocate<BlockContainer>(const_cast<DOM::Document&>(document()), nullptr, computed_values().clone_inherited_values());

View file

@ -95,6 +95,8 @@ public:
bool is_inline_block() const; bool is_inline_block() const;
bool is_inline_table() const; bool is_inline_table() const;
bool is_atomic_inline() const;
bool is_out_of_flow(FormattingContext const&) const; bool is_out_of_flow(FormattingContext const&) const;
// These are used to optimize hot is<T> variants for some classes where dynamic_cast is too slow. // These are used to optimize hot is<T> variants for some classes where dynamic_cast is too slow.

View file

@ -2,15 +2,15 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x18 [BFC] children: inline BlockContainer <html> at (0,0) content-size 800x18 [BFC] children: inline
InlineNode <body> InlineNode <body>
frag 0 from BlockContainer start: 0, length: 0, rect: [8,13 0x0] baseline: 0 frag 0 from BlockContainer start: 0, length: 0, rect: [8,13 0x0] baseline: 0
frag 1 from TextNode start: 0, length: 5, rect: [8,0 36.84375x18] baseline: 13.796875
"hello"
BlockContainer <main> at (8,13) content-size 0x0 inline-block [BFC] children: not-inline BlockContainer <main> at (8,13) content-size 0x0 inline-block [BFC] children: not-inline
BlockContainer <div> at (8,0) content-size 36.84375x18 positioned [BFC] children: inline BlockContainer <div> at (8,0) content-size 36.84375x18 positioned [BFC] children: inline
frag 0 from TextNode start: 0, length: 5, rect: [8,0 36.84375x18] baseline: 13.796875
"hello"
TextNode <#text> TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600] ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x18] PaintableWithLines (BlockContainer<HTML>) [0,0 800x18]
PaintableWithLines (InlineNode<BODY>) [8,13 36.84375x18] PaintableWithLines (InlineNode<BODY>) [0,13 36.84375x0]
PaintableWithLines (BlockContainer<MAIN>) [8,13 0x0] PaintableWithLines (BlockContainer<MAIN>) [8,13 0x0]
PaintableWithLines (BlockContainer<DIV>) [8,0 36.84375x18] PaintableWithLines (BlockContainer<DIV>) [8,0 36.84375x18]
TextPaintable (TextNode<#text>) TextPaintable (TextNode<#text>)

View file

@ -0,0 +1,17 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x18 [BFC] children: inline
InlineNode <body>
frag 0 from BlockContainer start: 0, length: 0, rect: [8,0 11.796875x18] baseline: 13.796875
BlockContainer <div> at (8,0) content-size 11.796875x18 positioned inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [8,0 11.796875x18] baseline: 13.796875
"$"
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x18]
PaintableWithLines (InlineNode<BODY>) [0,0 23.59375x18]
PaintableWithLines (BlockContainer<DIV>) [8,0 11.796875x18]
TextPaintable (TextNode<#text>)
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)
SC for BlockContainer<HTML> [0,0 800x18] [children: 0] (z-index: auto)

View file

@ -2,16 +2,16 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x18 [BFC] children: inline BlockContainer <html> at (0,0) content-size 800x18 [BFC] children: inline
InlineNode <body> InlineNode <body>
frag 0 from BlockContainer start: 0, length: 0, rect: [8,0 36.84375x18] baseline: 13.796875 frag 0 from BlockContainer start: 0, length: 0, rect: [8,0 36.84375x18] baseline: 13.796875
frag 1 from TextNode start: 0, length: 5, rect: [8,0 36.84375x18] baseline: 13.796875
"hello"
BlockContainer <main> at (8,0) content-size 36.84375x18 inline-block [BFC] children: not-inline BlockContainer <main> at (8,0) content-size 36.84375x18 inline-block [BFC] children: not-inline
BlockContainer <div> at (8,0) content-size 36.84375x18 children: inline BlockContainer <div> at (8,0) content-size 36.84375x18 children: inline
frag 0 from TextNode start: 0, length: 5, rect: [8,0 36.84375x18] baseline: 13.796875
"hello"
TextNode <#text> TextNode <#text>
TextNode <#text> TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600] ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x18] PaintableWithLines (BlockContainer<HTML>) [0,0 800x18]
PaintableWithLines (InlineNode<BODY>) [8,0 73.6875x18] PaintableWithLines (InlineNode<BODY>) [0,0 73.6875x18]
PaintableWithLines (BlockContainer<MAIN>) [8,0 36.84375x18] PaintableWithLines (BlockContainer<MAIN>) [8,0 36.84375x18]
PaintableWithLines (BlockContainer<DIV>) [8,0 36.84375x18] PaintableWithLines (BlockContainer<DIV>) [8,0 36.84375x18]
TextPaintable (TextNode<#text>) TextPaintable (TextNode<#text>)

View file

@ -0,0 +1,11 @@
<!doctype html><style>
* { outline: 1px solid black; }
div {
position: relative;
display: inline-block;
background-color: lime;
}
body {
display: inline;
}
</style><body><div>$