Browse Source

LibWeb: Implement CSS declaration block's "updating flag"

This flag is used to prevent reparsing the style attribute after it is
automatically updated after using the CSSOM API to mutate style.
Andreas Kling 3 years ago
parent
commit
a8afb883c1

+ 12 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.cpp

@@ -125,10 +125,22 @@ DOM::ExceptionOr<String> PropertyOwningCSSStyleDeclaration::remove_property(Prop
 // https://drafts.csswg.org/cssom/#update-style-attribute-for
 // https://drafts.csswg.org/cssom/#update-style-attribute-for
 void ElementInlineCSSStyleDeclaration::update_style_attribute()
 void ElementInlineCSSStyleDeclaration::update_style_attribute()
 {
 {
+    // 1. Assert: declaration block’s computed flag is unset.
+    // NOTE: Unnecessary, only relevant for ResolvedCSSStyleDeclaration.
+
+    // 2. Let owner node be declaration block’s owner node.
+    // 3. If owner node is null, then return.
     if (!m_element)
     if (!m_element)
         return;
         return;
 
 
+    // 4. Set declaration block’s updating flag.
+    m_updating = true;
+
+    // 5. Set an attribute value for owner node using "style" and the result of serializing declaration block.
     m_element->set_attribute(HTML::AttributeNames::style, serialized());
     m_element->set_attribute(HTML::AttributeNames::style, serialized());
+
+    // 6. Unset declaration block’s updating flag.
+    m_updating = false;
 }
 }
 
 
 // https://drafts.csswg.org/cssom/#set-a-css-declaration
 // https://drafts.csswg.org/cssom/#set-a-css-declaration

+ 5 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleDeclaration.h

@@ -101,12 +101,17 @@ public:
     DOM::Element* element() { return m_element.ptr(); }
     DOM::Element* element() { return m_element.ptr(); }
     const DOM::Element* element() const { return m_element.ptr(); }
     const DOM::Element* element() const { return m_element.ptr(); }
 
 
+    bool is_updating() const { return m_updating; }
+
 private:
 private:
     explicit ElementInlineCSSStyleDeclaration(DOM::Element&, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties);
     explicit ElementInlineCSSStyleDeclaration(DOM::Element&, Vector<StyleProperty> properties, HashMap<String, StyleProperty> custom_properties);
 
 
     virtual void update_style_attribute() override;
     virtual void update_style_attribute() override;
 
 
     WeakPtr<DOM::Element> m_element;
     WeakPtr<DOM::Element> m_element;
+
+    // https://drafts.csswg.org/cssom/#cssstyledeclaration-updating-flag
+    bool m_updating { false };
 };
 };
 
 
 }
 }

+ 8 - 0
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -293,6 +293,11 @@ RefPtr<Layout::Node> Element::create_layout_node_for_display_type(DOM::Document&
     TODO();
     TODO();
 }
 }
 
 
+CSS::CSSStyleDeclaration const* Element::inline_style() const
+{
+    return m_inline_style;
+}
+
 void Element::parse_attribute(FlyString const& name, String const& value)
 void Element::parse_attribute(FlyString const& name, String const& value)
 {
 {
     if (name == HTML::AttributeNames::class_) {
     if (name == HTML::AttributeNames::class_) {
@@ -305,6 +310,9 @@ void Element::parse_attribute(FlyString const& name, String const& value)
         if (m_class_list)
         if (m_class_list)
             m_class_list->associated_attribute_changed(value);
             m_class_list->associated_attribute_changed(value);
     } else if (name == HTML::AttributeNames::style) {
     } else if (name == HTML::AttributeNames::style) {
+        // https://drafts.csswg.org/cssom/#ref-for-cssstyledeclaration-updating-flag
+        if (m_inline_style && m_inline_style->is_updating())
+            return;
         m_inline_style = parse_css_style_attribute(CSS::ParsingContext(document()), value, *this);
         m_inline_style = parse_css_style_attribute(CSS::ParsingContext(document()), value, *this);
         set_needs_style_update(true);
         set_needs_style_update(true);
     }
     }

+ 2 - 2
Userland/Libraries/LibWeb/DOM/Element.h

@@ -103,7 +103,7 @@ public:
     void set_computed_css_values(RefPtr<CSS::StyleProperties> style) { m_computed_css_values = move(style); }
     void set_computed_css_values(RefPtr<CSS::StyleProperties> style) { m_computed_css_values = move(style); }
     NonnullRefPtr<CSS::StyleProperties> resolved_css_values();
     NonnullRefPtr<CSS::StyleProperties> resolved_css_values();
 
 
-    const CSS::CSSStyleDeclaration* inline_style() const { return m_inline_style; }
+    CSS::CSSStyleDeclaration const* inline_style() const;
 
 
     NonnullRefPtr<CSS::CSSStyleDeclaration> style_for_bindings();
     NonnullRefPtr<CSS::CSSStyleDeclaration> style_for_bindings();
 
 
@@ -152,7 +152,7 @@ private:
     String m_html_uppercased_qualified_name;
     String m_html_uppercased_qualified_name;
     NonnullRefPtr<NamedNodeMap> m_attributes;
     NonnullRefPtr<NamedNodeMap> m_attributes;
 
 
-    RefPtr<CSS::CSSStyleDeclaration> m_inline_style;
+    RefPtr<CSS::ElementInlineCSSStyleDeclaration> m_inline_style;
 
 
     RefPtr<CSS::StyleProperties> m_computed_css_values;
     RefPtr<CSS::StyleProperties> m_computed_css_values;
     HashMap<FlyString, CSS::StyleProperty> m_custom_properties;
     HashMap<FlyString, CSS::StyleProperty> m_custom_properties;