浏览代码

LibWeb: Convert Element "attribute change steps" from vector to virtual

By using a virtual function and overriding it on HTMLSlotElement, we
shrink every DOM element by 24 bytes. :^)
Andreas Kling 1 年之前
父节点
当前提交
bdac94870c

+ 34 - 39
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -71,38 +71,6 @@ Element::Element(Document& document, DOM::QualifiedName qualified_name)
     , m_qualified_name(move(qualified_name))
 {
     make_html_uppercased_qualified_name();
-
-    // https://dom.spec.whatwg.org/#ref-for-concept-element-attributes-change-ext①
-    add_attribute_change_steps([this](auto const& local_name, auto const& old_value, auto const& value, auto const& namespace_) {
-        // 1. If localName is slot and namespace is null, then:
-        if (local_name == HTML::AttributeNames::slot && !namespace_.has_value()) {
-            // 1. If value is oldValue, then return.
-            if (value == old_value)
-                return;
-
-            // 2. If value is null and oldValue is the empty string, then return.
-            if (!value.has_value() && old_value == String {})
-                return;
-
-            // 3. If value is the empty string and oldValue is null, then return.
-            if (value == String {} && !old_value.has_value())
-                return;
-
-            // 4. If value is null or the empty string, then set element’s name to the empty string.
-            if (!value.has_value() || value->is_empty())
-                set_slottable_name({});
-            // 5. Otherwise, set element’s name to value.
-            else
-                set_slottable_name(*value);
-
-            // 6. If element is assigned, then run assign slottables for element’s assigned slot.
-            if (auto assigned_slot = assigned_slot_internal())
-                assign_slottables(*assigned_slot);
-
-            // 7. Run assign a slot for element.
-            assign_a_slot(JS::NonnullGCPtr { *this });
-        }
-    });
 }
 
 Element::~Element() = default;
@@ -463,15 +431,9 @@ CSS::CSSStyleDeclaration const* Element::inline_style() const
     return m_inline_style.ptr();
 }
 
-void Element::add_attribute_change_steps(AttributeChangeSteps steps)
-{
-    m_attribute_change_steps.append(move(steps));
-}
-
 void Element::run_attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_)
 {
-    for (auto const& attribute_change_steps : m_attribute_change_steps)
-        attribute_change_steps(local_name, old_value, value, namespace_);
+    attribute_change_steps(local_name, old_value, value, namespace_);
 
     // AD-HOC: Run our own internal attribute change handler.
     attribute_changed(local_name, value);
@@ -2270,4 +2232,37 @@ Element::Directionality Element::directionality() const
     VERIFY_NOT_REACHED();
 }
 
+// https://dom.spec.whatwg.org/#ref-for-concept-element-attributes-change-ext①
+void Element::attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_)
+{
+    // 1. If localName is slot and namespace is null, then:
+    if (local_name == HTML::AttributeNames::slot && !namespace_.has_value()) {
+        // 1. If value is oldValue, then return.
+        if (value == old_value)
+            return;
+
+        // 2. If value is null and oldValue is the empty string, then return.
+        if (!value.has_value() && old_value == String {})
+            return;
+
+        // 3. If value is the empty string and oldValue is null, then return.
+        if (value == String {} && !old_value.has_value())
+            return;
+
+        // 4. If value is null or the empty string, then set element’s name to the empty string.
+        if (!value.has_value() || value->is_empty())
+            set_slottable_name({});
+        // 5. Otherwise, set element’s name to value.
+        else
+            set_slottable_name(*value);
+
+        // 6. If element is assigned, then run assign slottables for element’s assigned slot.
+        if (auto assigned_slot = assigned_slot_internal())
+            assign_slottables(*assigned_slot);
+
+        // 7. Run assign a slot for element.
+        assign_a_slot(JS::NonnullGCPtr { *this });
+    }
+}
+
 }

+ 1 - 3
Userland/Libraries/LibWeb/DOM/Element.h

@@ -147,9 +147,8 @@ public:
     virtual void apply_presentational_hints(CSS::StyleProperties&) const { }
 
     // https://dom.spec.whatwg.org/#concept-element-attributes-change-ext
-    using AttributeChangeSteps = Function<void(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_)>;
+    virtual void attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_);
 
-    void add_attribute_change_steps(AttributeChangeSteps steps);
     void run_attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_);
     virtual void attribute_changed(FlyString const& name, Optional<String> const& value);
 
@@ -395,7 +394,6 @@ private:
     FlyString m_html_uppercased_qualified_name;
 
     JS::GCPtr<NamedNodeMap> m_attributes;
-    Vector<AttributeChangeSteps> m_attribute_change_steps;
     JS::GCPtr<CSS::ElementInlineCSSStyleDeclaration> m_inline_style;
     JS::GCPtr<DOMTokenList> m_class_list;
     JS::GCPtr<ShadowRoot> m_shadow_root;

+ 31 - 27
Userland/Libraries/LibWeb/HTML/HTMLSlotElement.cpp

@@ -17,33 +17,6 @@ JS_DEFINE_ALLOCATOR(HTMLSlotElement);
 HTMLSlotElement::HTMLSlotElement(DOM::Document& document, DOM::QualifiedName qualified_name)
     : HTMLElement(document, move(qualified_name))
 {
-    // https://dom.spec.whatwg.org/#ref-for-concept-element-attributes-change-ext
-    add_attribute_change_steps([this](auto const& local_name, auto const& old_value, auto const& value, auto const& namespace_) {
-        // 1. If element is a slot, localName is name, and namespace is null, then:
-        if (local_name == AttributeNames::name && !namespace_.has_value()) {
-            // 1. If value is oldValue, then return.
-            if (value == old_value)
-                return;
-
-            // 2. If value is null and oldValue is the empty string, then return.
-            if (!value.has_value() && old_value == String {})
-                return;
-
-            // 3. If value is the empty string and oldValue is null, then return.
-            if (value == String {} && !old_value.has_value())
-                return;
-
-            // 4. If value is null or the empty string, then set element’s name to the empty string.
-            if (!value.has_value())
-                set_slot_name({});
-            // 5. Otherwise, set element’s name to value.
-            else
-                set_slot_name(*value);
-
-            // 6. Run assign slottables for a tree with element’s root.
-            DOM::assign_slottables_for_a_tree(root());
-        }
-    });
 }
 
 HTMLSlotElement::~HTMLSlotElement() = default;
@@ -142,4 +115,35 @@ void HTMLSlotElement::assign(Vector<SlottableHandle> nodes)
     assign_slottables_for_a_tree(root());
 }
 
+// https://dom.spec.whatwg.org/#ref-for-concept-element-attributes-change-ext
+void HTMLSlotElement::attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_)
+{
+    Base::attribute_change_steps(local_name, old_value, value, namespace_);
+
+    // 1. If element is a slot, localName is name, and namespace is null, then:
+    if (local_name == AttributeNames::name && !namespace_.has_value()) {
+        // 1. If value is oldValue, then return.
+        if (value == old_value)
+            return;
+
+        // 2. If value is null and oldValue is the empty string, then return.
+        if (!value.has_value() && old_value == String {})
+            return;
+
+        // 3. If value is the empty string and oldValue is null, then return.
+        if (value == String {} && !old_value.has_value())
+            return;
+
+        // 4. If value is null or the empty string, then set element’s name to the empty string.
+        if (!value.has_value())
+            set_slot_name({});
+        // 5. Otherwise, set element’s name to value.
+        else
+            set_slot_name(*value);
+
+        // 6. Run assign slottables for a tree with element’s root.
+        DOM::assign_slottables_for_a_tree(root());
+    }
+}
+
 }

+ 2 - 0
Userland/Libraries/LibWeb/HTML/HTMLSlotElement.h

@@ -45,6 +45,8 @@ private:
     virtual void initialize(JS::Realm&) override;
     virtual void visit_edges(JS::Cell::Visitor&) override;
 
+    virtual void attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
+
     // https://html.spec.whatwg.org/multipage/scripting.html#manually-assigned-nodes
     Vector<DOM::Slottable> m_manually_assigned_nodes;
 };