Bladeren bron

LibWeb: Don't crash on HTML input element with `display: inline`

This would previously assert in InlineFormattingContext because we had
an outwardly inline box that wasn't inwardly flow.

Fix this by converting text-based input boxes to inline-blocks. This is
an ad-hoc solution, and there might be a much better way to solve it.
Andreas Kling 2 jaren geleden
bovenliggende
commit
a6d1307aa4

+ 9 - 0
Tests/LibWeb/Layout/expected/input-element-with-display-inline.txt

@@ -0,0 +1,9 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (1,1) content-size 798x45.835937 children: not-inline
+    BlockContainer <body> at (10,10) content-size 780x27.835937 children: inline
+      line 0 width: 202, height: 27.835937, bottom: 27.835937, baseline: 25.835937
+        frag 0 from BlockContainer start: 0, length: 0, rect: [11,11 200x25.835937]
+      BlockContainer <input> at (11,11) content-size 200x25.835937 inline-block children: not-inline
+        BlockContainer <#shadow-root> at (11,11) content-size 0x0 children: not-inline
+        BlockContainer <div> at (14,13) content-size 194x21.835937 children: inline
+          TextNode <#text>

+ 10 - 0
Tests/LibWeb/Layout/input/input-element-with-display-inline.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html><html><head><style>
+* {
+    border: 1px solid black;
+    font: 20px 'SerenitySans';
+}
+input {
+    display: inline;
+    width: 200px;
+}
+</style></head><body><input/>

+ 6 - 1
Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp

@@ -71,7 +71,12 @@ JS::GCPtr<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::
     if (type_state() == TypeAttributeState::RadioButton)
         return heap().allocate_without_realm<Layout::RadioButton>(document(), *this, move(style));
 
-    return heap().allocate_without_realm<Layout::BlockContainer>(document(), this, move(style));
+    // AD-HOC: We rewrite `display: inline` to `display: inline-block`.
+    //         This is required for the internal shadow tree to work correctly in layout.
+    if (style->display().is_inline_outside() && style->display().is_flow_inside())
+        style->set_property(CSS::PropertyID::Display, CSS::IdentifierStyleValue::create(CSS::ValueID::InlineBlock));
+
+    return Element::create_layout_node_for_display_type(document(), style->display(), style, this);
 }
 
 void HTMLInputElement::set_checked(bool checked, ChangeSource change_source)