Browse Source

LibWeb: Stop allowing invalid tokens in `display` values

Previously we were overly generous in what we accepted for `display`.
For example, we accepted:
- Multiple outside or inside identifiers
- Unrecognized identifiers
- Non-identifier tokens

Now, we reject all these cases. This makes us stop accepting the
`display: block math;` declaration in `MathML/Default.css`, and so the
one layout test we have containing MathML elements has changed to
reflect that.
Sam Atkins 1 year ago
parent
commit
3b0980c89f

+ 19 - 21
Tests/LibWeb/Layout/expected/css-namespace-tag-name-selector.txt

@@ -1,41 +1,39 @@
 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 784x299.6875 children: not-inline
-      BlockContainer <(anonymous)> at (8,8) content-size 784x152 children: inline
-        line 0 width: 302, height: 152, bottom: 152, baseline: 152
+    BlockContainer <body> at (8,8) content-size 784x201.125 children: not-inline
+      BlockContainer <(anonymous)> at (8,8) content-size 784x155.46875 children: inline
+        line 0 width: 312, height: 155.46875, bottom: 155.46875, baseline: 152
           frag 0 from SVGSVGBox start: 0, length: 0, rect: [9,9 300x150]
+          frag 1 from TextNode start: 0, length: 1, rect: [310,146 8x17.46875]
+            " "
+          frag 2 from Box start: 0, length: 0, rect: [319,51 0x108]
         SVGSVGBox <svg> at (9,9) content-size 300x150 [SVG] children: inline
           InlineNode <a>
             SVGTextBox <text> at (9,9) content-size 0x0 children: inline
               TextNode <#text>
         TextNode <#text>
-        InlineNode <math>
-      BlockContainer <a> at (9,161) content-size 100x100 children: inline
-        line 0 width: 99.453125, height: 43.6875, bottom: 43.6875, baseline: 33.84375
-          frag 0 from TextNode start: 0, length: 5, rect: [9,161 99.453125x43.671875]
-            "Hello"
-        TextNode <#text>
-      BlockContainer <(anonymous)> at (8,262) content-size 784x0 children: inline
+        Box <math> at (319,51) content-size 0x108 children: not-inline
+          Box <a> at (8,8) content-size 100x100 children: inline
+            TextNode <#text>
         TextNode <#text>
-      BlockContainer <div> at (9,263) content-size 782x43.6875 children: inline
-        line 0 width: 101.453125, height: 43.6875, bottom: 43.6875, baseline: 33.84375
-          frag 0 from TextNode start: 0, length: 5, rect: [10,263 99.453125x43.671875]
+      BlockContainer <div> at (9,164.46875) content-size 782x43.65625 children: inline
+        line 0 width: 101.453125, height: 43.65625, bottom: 43.65625, baseline: 33.828125
+          frag 0 from TextNode start: 0, length: 5, rect: [10,164.46875 99.453125x43.671875]
             "Hello"
         InlineNode <a>
           TextNode <#text>
-      BlockContainer <(anonymous)> at (8,307.6875) content-size 784x0 children: inline
+      BlockContainer <(anonymous)> at (8,209.125) content-size 784x0 children: inline
         TextNode <#text>
 
 ViewportPaintable (Viewport<#document>) [0,0 800x600]
   PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
-    PaintableWithLines (BlockContainer<BODY>) [8,8 784x299.6875]
-      PaintableWithLines (BlockContainer(anonymous)) [8,8 784x152]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x201.125]
+      PaintableWithLines (BlockContainer(anonymous)) [8,8 784x155.46875]
         SVGSVGPaintable (SVGSVGBox<svg>) [8,8 302x152]
-        InlinePaintable (InlineNode<math>)
-      PaintableWithLines (BlockContainer<a>) [8,160 102x102]
         TextPaintable (TextNode<#text>)
-      PaintableWithLines (BlockContainer(anonymous)) [8,262 784x0]
-      PaintableWithLines (BlockContainer<DIV>) [8,262 784x45.6875]
+        PaintableBox (Box<math>) [318,50 2x110] overflow: [8,8 100x100]
+          PaintableBox (Box<a>) [8,8 100x100]
+      PaintableWithLines (BlockContainer<DIV>) [8,163.46875 784x45.65625] overflow: [9,164.46875 782x43.671875]
         InlinePaintable (InlineNode<A>)
           TextPaintable (TextNode<#text>)
-      PaintableWithLines (BlockContainer(anonymous)) [8,307.6875 784x0]
+      PaintableWithLines (BlockContainer(anonymous)) [8,209.125 784x0]

+ 19 - 10
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -3655,34 +3655,43 @@ RefPtr<StyleValue> Parser::parse_display_value(Vector<ComponentValue> const& com
 
     auto parse_multi_component_display = [&](Vector<ComponentValue> const& component_values) -> Optional<Display> {
         auto list_item = Display::ListItem::No;
-        Display::Inside inside = Display::Inside::Flow;
-        Display::Outside outside = Display::Outside::Block;
+        Optional<Display::Inside> inside;
+        Optional<Display::Outside> outside;
 
         for (size_t i = 0; i < component_values.size(); ++i) {
             if (auto value = parse_identifier_value(component_values[i])) {
                 auto identifier = value->to_identifier();
-                if (ValueID::ListItem == identifier) {
+                if (identifier == ValueID::ListItem) {
+                    if (list_item == Display::ListItem::Yes)
+                        return {};
                     list_item = Display::ListItem::Yes;
                     continue;
                 }
-                auto inside_value = parse_inside(identifier);
-                if (inside_value.has_value()) {
+                if (auto inside_value = parse_inside(identifier); inside_value.has_value()) {
+                    if (inside.has_value())
+                        return {};
                     inside = inside_value.value();
                     continue;
                 }
-                auto outside_value = parse_outside(identifier);
-                if (outside_value.has_value()) {
+                if (auto outside_value = parse_outside(identifier); outside_value.has_value()) {
+                    if (outside.has_value())
+                        return {};
                     outside = outside_value.value();
+                    continue;
                 }
             }
+
+            // Not a display value, abort.
+            dbgln_if(CSS_PARSER_DEBUG, "Unrecognized display value: `{}`", component_values[i].to_string());
+            return {};
         }
 
         // The spec does not allow any other inside values to be combined with list-item
         // <display-outside>? && [ flow | flow-root ]? && list-item
-        if (list_item == Display::ListItem::Yes && inside != Display::Inside::Flow && inside != Display::Inside::FlowRoot)
-            return OptionalNone {};
+        if (list_item == Display::ListItem::Yes && inside.has_value() && inside != Display::Inside::Flow && inside != Display::Inside::FlowRoot)
+            return {};
 
-        return Display { outside, inside, list_item };
+        return Display { outside.value_or(Display::Outside::Block), inside.value_or(Display::Inside::Flow), list_item };
     };
 
     Optional<Display> display;