Browse Source

LibWeb: Make EventTarget::activation_behavior a virtual function

(Instead of using an AK::Function on EventTarget). This shaves 48 bytes
off of every EventTarget instance.
Andreas Kling 1 year ago
parent
commit
a71eaefdf6

+ 3 - 3
Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp

@@ -242,7 +242,7 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> target, Event& even
         bool is_activation_event = is<UIEvents::MouseEvent>(event) && event.type() == HTML::EventNames::click;
         bool is_activation_event = is<UIEvents::MouseEvent>(event) && event.type() == HTML::EventNames::click;
 
 
         // 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target.
         // 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target.
-        if (is_activation_event && target->activation_behavior)
+        if (is_activation_event && target->has_activation_behavior())
             activation_target = target;
             activation_target = target;
 
 
         // 6. Let slottable be target, if target is a slottable and is assigned, and null otherwise.
         // 6. Let slottable be target, if target is a slottable and is assigned, and null otherwise.
@@ -293,7 +293,7 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> target, Event& even
             if (is<HTML::Window>(parent)
             if (is<HTML::Window>(parent)
                 || (is<Node>(parent) && verify_cast<Node>(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*parent)))) {
                 || (is<Node>(parent) && verify_cast<Node>(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*parent)))) {
                 // 1. If isActivationEvent is true, event’s bubbles attribute is true, activationTarget is null, and parent has activation behavior, then set activationTarget to parent.
                 // 1. If isActivationEvent is true, event’s bubbles attribute is true, activationTarget is null, and parent has activation behavior, then set activationTarget to parent.
-                if (is_activation_event && event.bubbles() && !activation_target && parent->activation_behavior)
+                if (is_activation_event && event.bubbles() && !activation_target && parent->has_activation_behavior())
                     activation_target = parent;
                     activation_target = parent;
 
 
                 // 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree.
                 // 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree.
@@ -309,7 +309,7 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> target, Event& even
                 target = *parent;
                 target = *parent;
 
 
                 // 1. If isActivationEvent is true, activationTarget is null, and target has activation behavior, then set activationTarget to target.
                 // 1. If isActivationEvent is true, activationTarget is null, and target has activation behavior, then set activationTarget to target.
-                if (is_activation_event && !activation_target && target->activation_behavior)
+                if (is_activation_event && !activation_target && target->has_activation_behavior())
                     activation_target = target;
                     activation_target = target;
 
 
                 // 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree.
                 // 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree.

+ 9 - 0
Userland/Libraries/LibWeb/DOM/EventTarget.cpp

@@ -816,4 +816,13 @@ bool EventTarget::has_event_listeners() const
     return !m_event_listener_list.is_empty();
     return !m_event_listener_list.is_empty();
 }
 }
 
 
+bool EventTarget::has_activation_behavior() const
+{
+    return false;
+}
+
+void EventTarget::activation_behavior(Event const&)
+{
+}
+
 }
 }

+ 2 - 1
Userland/Libraries/LibWeb/DOM/EventTarget.h

@@ -45,7 +45,8 @@ public:
 
 
     Vector<JS::Handle<DOMEventListener>> event_listener_list();
     Vector<JS::Handle<DOMEventListener>> event_listener_list();
 
 
-    Function<void(Event const&)> activation_behavior;
+    virtual bool has_activation_behavior() const;
+    virtual void activation_behavior(Event const&);
 
 
     // NOTE: These only exist for checkbox and radio input elements.
     // NOTE: These only exist for checkbox and radio input elements.
     virtual void legacy_pre_activation_behavior() { }
     virtual void legacy_pre_activation_behavior() { }

+ 6 - 4
Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp

@@ -16,9 +16,6 @@ JS_DEFINE_ALLOCATOR(HTMLAnchorElement);
 HTMLAnchorElement::HTMLAnchorElement(DOM::Document& document, DOM::QualifiedName qualified_name)
 HTMLAnchorElement::HTMLAnchorElement(DOM::Document& document, DOM::QualifiedName qualified_name)
     : HTMLElement(document, move(qualified_name))
     : HTMLElement(document, move(qualified_name))
 {
 {
-    activation_behavior = [this](auto const& event) {
-        run_activation_behavior(event);
-    };
 }
 }
 
 
 HTMLAnchorElement::~HTMLAnchorElement() = default;
 HTMLAnchorElement::~HTMLAnchorElement() = default;
@@ -47,7 +44,12 @@ WebIDL::ExceptionOr<void> HTMLAnchorElement::set_hyperlink_element_utils_href(St
     return set_attribute(HTML::AttributeNames::href, move(href));
     return set_attribute(HTML::AttributeNames::href, move(href));
 }
 }
 
 
-void HTMLAnchorElement::run_activation_behavior(Web::DOM::Event const&)
+bool HTMLAnchorElement::has_activation_behavior() const
+{
+    return true;
+}
+
+void HTMLAnchorElement::activation_behavior(Web::DOM::Event const&)
 {
 {
     // The activation behavior of an a element element given an event event is:
     // The activation behavior of an a element element given an event event is:
 
 

+ 2 - 1
Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h

@@ -41,7 +41,8 @@ private:
 
 
     virtual void initialize(JS::Realm&) override;
     virtual void initialize(JS::Realm&) override;
 
 
-    void run_activation_behavior(Web::DOM::Event const&);
+    virtual bool has_activation_behavior() const override;
+    virtual void activation_behavior(Web::DOM::Event const&) override;
 
 
     // ^DOM::Element
     // ^DOM::Element
     virtual void attribute_changed(FlyString const& name, Optional<String> const& value) override;
     virtual void attribute_changed(FlyString const& name, Optional<String> const& value) override;

+ 41 - 34
Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp

@@ -15,40 +15,6 @@ JS_DEFINE_ALLOCATOR(HTMLButtonElement);
 HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName qualified_name)
 HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName qualified_name)
     : HTMLElement(document, move(qualified_name))
     : HTMLElement(document, move(qualified_name))
 {
 {
-    // https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour
-    activation_behavior = [this](auto&) {
-        // 1. If element is disabled, then return.
-        if (!enabled())
-            return;
-
-        // 2. If element does not have a form owner, then return.
-        if (!form())
-            return;
-
-        // 3. If element's node document is not fully active, then return.
-        if (!this->document().is_fully_active())
-            return;
-
-        // 4. Switch on element's type attribute's state:
-        switch (type_state()) {
-        case TypeAttributeState::Submit:
-            // Submit Button
-            // Submit element's form owner from element.
-            form()->submit_form(*this).release_value_but_fixme_should_propagate_errors();
-            break;
-        case TypeAttributeState::Reset:
-            // Reset Button
-            // Reset element's form owner.
-            form()->reset_form();
-            break;
-        case TypeAttributeState::Button:
-            // Button
-            // Do nothing.
-            break;
-        default:
-            VERIFY_NOT_REACHED();
-        }
-    };
 }
 }
 
 
 HTMLButtonElement::~HTMLButtonElement() = default;
 HTMLButtonElement::~HTMLButtonElement() = default;
@@ -101,4 +67,45 @@ DeprecatedString HTMLButtonElement::value() const
     return deprecated_attribute(AttributeNames::value);
     return deprecated_attribute(AttributeNames::value);
 }
 }
 
 
+bool HTMLButtonElement::has_activation_behavior() const
+{
+    return true;
+}
+
+void HTMLButtonElement::activation_behavior(DOM::Event const&)
+{
+    // https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour
+    // 1. If element is disabled, then return.
+    if (!enabled())
+        return;
+
+    // 2. If element does not have a form owner, then return.
+    if (!form())
+        return;
+
+    // 3. If element's node document is not fully active, then return.
+    if (!this->document().is_fully_active())
+        return;
+
+    // 4. Switch on element's type attribute's state:
+    switch (type_state()) {
+    case TypeAttributeState::Submit:
+        // Submit Button
+        // Submit element's form owner from element.
+        form()->submit_form(*this).release_value_but_fixme_should_propagate_errors();
+        break;
+    case TypeAttributeState::Reset:
+        // Reset Button
+        // Reset element's form owner.
+        form()->reset_form();
+        break;
+    case TypeAttributeState::Button:
+        // Button
+        // Do nothing.
+        break;
+    default:
+        VERIFY_NOT_REACHED();
+    }
+}
+
 }
 }

+ 3 - 0
Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h

@@ -67,6 +67,9 @@ public:
 
 
     virtual DeprecatedString value() const override;
     virtual DeprecatedString value() const override;
 
 
+    virtual bool has_activation_behavior() const override;
+    virtual void activation_behavior(DOM::Event const&) override;
+
 private:
 private:
     virtual bool is_html_button_element() const override { return true; }
     virtual bool is_html_button_element() const override { return true; }
 
 

+ 16 - 8
Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp

@@ -38,14 +38,6 @@ HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName q
     : HTMLElement(document, move(qualified_name))
     : HTMLElement(document, move(qualified_name))
     , m_value(DeprecatedString::empty())
     , m_value(DeprecatedString::empty())
 {
 {
-    activation_behavior = [this](auto&) {
-        // The activation behavior for input elements are these steps:
-
-        // FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return.
-
-        // 2. Run this element's input activation behavior, if any, and do nothing otherwise.
-        run_input_activation_behavior().release_value_but_fixme_should_propagate_errors();
-    };
 }
 }
 
 
 HTMLInputElement::~HTMLInputElement() = default;
 HTMLInputElement::~HTMLInputElement() = default;
@@ -1284,4 +1276,20 @@ bool HTMLInputElement::is_submit_button() const
     return type_state() == TypeAttributeState::SubmitButton
     return type_state() == TypeAttributeState::SubmitButton
         || type_state() == TypeAttributeState::ImageButton;
         || type_state() == TypeAttributeState::ImageButton;
 }
 }
+
+bool HTMLInputElement::has_activation_behavior() const
+{
+    return true;
+}
+
+void HTMLInputElement::activation_behavior(DOM::Event const&)
+{
+    // The activation behavior for input elements are these steps:
+
+    // FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return.
+
+    // 2. Run this element's input activation behavior, if any, and do nothing otherwise.
+    run_input_activation_behavior().release_value_but_fixme_should_propagate_errors();
+}
+
 }
 }

+ 3 - 0
Userland/Libraries/LibWeb/HTML/HTMLInputElement.h

@@ -149,6 +149,9 @@ public:
     JS::GCPtr<Element> placeholder_element() { return m_placeholder_element; }
     JS::GCPtr<Element> placeholder_element() { return m_placeholder_element; }
     JS::GCPtr<Element const> placeholder_element() const { return m_placeholder_element; }
     JS::GCPtr<Element const> placeholder_element() const { return m_placeholder_element; }
 
 
+    virtual bool has_activation_behavior() const override;
+    virtual void activation_behavior(DOM::Event const&) override;
+
 private:
 private:
     HTMLInputElement(DOM::Document&, DOM::QualifiedName);
     HTMLInputElement(DOM::Document&, DOM::QualifiedName);
 
 

+ 23 - 16
Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.cpp

@@ -15,22 +15,29 @@ JS_DEFINE_ALLOCATOR(HTMLSummaryElement);
 HTMLSummaryElement::HTMLSummaryElement(DOM::Document& document, DOM::QualifiedName qualified_name)
 HTMLSummaryElement::HTMLSummaryElement(DOM::Document& document, DOM::QualifiedName qualified_name)
     : HTMLElement(document, move(qualified_name))
     : HTMLElement(document, move(qualified_name))
 {
 {
-    activation_behavior = [this](auto&) {
-        // The activation behavior of summary elements is to run the following steps:
-
-        // 1. If this summary element is not the summary for its parent details, then return.
-        if (!is_summary_for_its_parent_details())
-            return;
-
-        // 2. Let parent be this summary element's parent.
-        auto* parent = this->parent_element();
-
-        // 3. If the open attribute is present on parent, then remove it. Otherwise, set parent's open attribute to the empty string.
-        if (parent->has_attribute(HTML::AttributeNames::open))
-            parent->remove_attribute(HTML::AttributeNames::open);
-        else
-            parent->set_attribute(HTML::AttributeNames::open, String {}).release_value_but_fixme_should_propagate_errors();
-    };
+}
+
+bool HTMLSummaryElement::has_activation_behavior() const
+{
+    return true;
+}
+
+void HTMLSummaryElement::activation_behavior(DOM::Event const&)
+{
+    // The activation behavior of summary elements is to run the following steps:
+
+    // 1. If this summary element is not the summary for its parent details, then return.
+    if (!is_summary_for_its_parent_details())
+        return;
+
+    // 2. Let parent be this summary element's parent.
+    auto* parent = this->parent_element();
+
+    // 3. If the open attribute is present on parent, then remove it. Otherwise, set parent's open attribute to the empty string.
+    if (parent->has_attribute(HTML::AttributeNames::open))
+        parent->remove_attribute(HTML::AttributeNames::open);
+    else
+        parent->set_attribute(HTML::AttributeNames::open, String {}).release_value_but_fixme_should_propagate_errors();
 }
 }
 
 
 // https://html.spec.whatwg.org/multipage/interactive-elements.html#summary-for-its-parent-details
 // https://html.spec.whatwg.org/multipage/interactive-elements.html#summary-for-its-parent-details

+ 3 - 0
Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.h

@@ -23,6 +23,9 @@ public:
 
 
     bool is_summary_for_its_parent_details();
     bool is_summary_for_its_parent_details();
 
 
+    virtual bool has_activation_behavior() const override;
+    virtual void activation_behavior(DOM::Event const&) override;
+
 private:
 private:
     HTMLSummaryElement(DOM::Document&, DOM::QualifiedName);
     HTMLSummaryElement(DOM::Document&, DOM::QualifiedName);