Browse Source

LibWeb: Cache parsed inline style of DOM elements

Instead of invoking the CSS parser every time we compute the style for
an element that has a "style" attribute, we now cache the result of
parsing the inline style whenever the "style" attribute is set.

This is a nice boost to relayout performance since we no longer hit the
CSS parser at all.
Andreas Kling 4 years ago
parent
commit
d65bebd8cf

+ 3 - 6
Libraries/LibWeb/CSS/StyleResolver.cpp

@@ -567,12 +567,9 @@ NonnullRefPtr<StyleProperties> StyleResolver::resolve_style(const DOM::Element&
         }
         }
     }
     }
 
 
-    auto style_attribute = element.attribute(HTML::AttributeNames::style);
-    if (!style_attribute.is_null()) {
-        if (auto declaration = parse_css_declaration(CSS::ParsingContext(document()), style_attribute)) {
-            for (auto& property : declaration->properties()) {
-                set_property_expanding_shorthands(style, property.property_id, property.value, m_document);
-            }
+    if (auto* inline_style = element.inline_style()) {
+        for (auto& property : inline_style->properties()) {
+            set_property_expanding_shorthands(style, property.property_id, property.value, m_document);
         }
         }
     }
     }
 
 

+ 4 - 1
Libraries/LibWeb/DOM/Element.cpp

@@ -26,6 +26,7 @@
 
 
 #include <AK/StringBuilder.h>
 #include <AK/StringBuilder.h>
 #include <LibWeb/CSS/Length.h>
 #include <LibWeb/CSS/Length.h>
+#include <LibWeb/CSS/Parser/CSSParser.h>
 #include <LibWeb/CSS/PropertyID.h>
 #include <LibWeb/CSS/PropertyID.h>
 #include <LibWeb/CSS/StyleResolver.h>
 #include <LibWeb/CSS/StyleResolver.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Document.h>
@@ -153,13 +154,15 @@ RefPtr<Layout::Node> Element::create_layout_node(const CSS::StyleProperties* par
 
 
 void Element::parse_attribute(const FlyString& name, const String& value)
 void Element::parse_attribute(const FlyString& name, const String& value)
 {
 {
-    if (name == "class") {
+    if (name == HTML::AttributeNames::class_) {
         auto new_classes = value.split_view(' ');
         auto new_classes = value.split_view(' ');
         m_classes.clear();
         m_classes.clear();
         m_classes.ensure_capacity(new_classes.size());
         m_classes.ensure_capacity(new_classes.size());
         for (auto& new_class : new_classes) {
         for (auto& new_class : new_classes) {
             m_classes.unchecked_append(new_class);
             m_classes.unchecked_append(new_class);
         }
         }
+    } else if (name == HTML::AttributeNames::style) {
+        m_inline_style = parse_css_declaration(CSS::ParsingContext(document()), value);
     }
     }
 }
 }
 
 

+ 4 - 0
Libraries/LibWeb/DOM/Element.h

@@ -90,6 +90,8 @@ public:
     const CSS::StyleProperties* resolved_style() const { return m_resolved_style.ptr(); }
     const CSS::StyleProperties* resolved_style() const { return m_resolved_style.ptr(); }
     NonnullRefPtr<CSS::StyleProperties> computed_style();
     NonnullRefPtr<CSS::StyleProperties> computed_style();
 
 
+    const CSS::StyleDeclaration* inline_style() const { return m_inline_style; }
+
     // FIXME: innerHTML also appears on shadow roots. https://w3c.github.io/DOM-Parsing/#dom-innerhtml
     // FIXME: innerHTML also appears on shadow roots. https://w3c.github.io/DOM-Parsing/#dom-innerhtml
     String inner_html() const;
     String inner_html() const;
     void set_inner_html(StringView);
     void set_inner_html(StringView);
@@ -107,6 +109,8 @@ private:
     QualifiedName m_qualified_name;
     QualifiedName m_qualified_name;
     Vector<Attribute> m_attributes;
     Vector<Attribute> m_attributes;
 
 
+    RefPtr<CSS::StyleDeclaration> m_inline_style;
+
     RefPtr<CSS::StyleProperties> m_resolved_style;
     RefPtr<CSS::StyleProperties> m_resolved_style;
 
 
     Vector<FlyString> m_classes;
     Vector<FlyString> m_classes;

+ 1 - 0
Libraries/LibWeb/Forward.h

@@ -28,6 +28,7 @@
 
 
 namespace Web::CSS {
 namespace Web::CSS {
 class Selector;
 class Selector;
+class StyleDeclaration;
 class StyleProperties;
 class StyleProperties;
 class StyleResolver;
 class StyleResolver;
 class StyleRule;
 class StyleRule;