mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:02:45 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									84eecbb10e
								
							
						
					
					
						commit
						a71eaefdf6
					
				
					 11 changed files with 108 additions and 64 deletions
				
			
		|  | @ -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; | ||||
| 
 | ||||
|         // 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; | ||||
| 
 | ||||
|         // 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) | ||||
|                 || (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.
 | ||||
|                 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; | ||||
| 
 | ||||
|                 // 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; | ||||
| 
 | ||||
|                 // 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; | ||||
| 
 | ||||
|                 // 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree.
 | ||||
|  |  | |||
|  | @ -816,4 +816,13 @@ bool EventTarget::has_event_listeners() const | |||
|     return !m_event_listener_list.is_empty(); | ||||
| } | ||||
| 
 | ||||
| bool EventTarget::has_activation_behavior() const | ||||
| { | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void EventTarget::activation_behavior(Event const&) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -45,7 +45,8 @@ public: | |||
| 
 | ||||
|     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.
 | ||||
|     virtual void legacy_pre_activation_behavior() { } | ||||
|  |  | |||
|  | @ -16,9 +16,6 @@ JS_DEFINE_ALLOCATOR(HTMLAnchorElement); | |||
| HTMLAnchorElement::HTMLAnchorElement(DOM::Document& document, DOM::QualifiedName qualified_name) | ||||
|     : HTMLElement(document, move(qualified_name)) | ||||
| { | ||||
|     activation_behavior = [this](auto const& event) { | ||||
|         run_activation_behavior(event); | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| 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)); | ||||
| } | ||||
| 
 | ||||
| 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:
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,7 +41,8 @@ private: | |||
| 
 | ||||
|     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
 | ||||
|     virtual void attribute_changed(FlyString const& name, Optional<String> const& value) override; | ||||
|  |  | |||
|  | @ -15,40 +15,6 @@ JS_DEFINE_ALLOCATOR(HTMLButtonElement); | |||
| HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName 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; | ||||
|  | @ -101,4 +67,45 @@ DeprecatedString HTMLButtonElement::value() const | |||
|     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(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -67,6 +67,9 @@ public: | |||
| 
 | ||||
|     virtual DeprecatedString value() const override; | ||||
| 
 | ||||
|     virtual bool has_activation_behavior() const override; | ||||
|     virtual void activation_behavior(DOM::Event const&) override; | ||||
| 
 | ||||
| private: | ||||
|     virtual bool is_html_button_element() const override { return true; } | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,14 +38,6 @@ HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName q | |||
|     : HTMLElement(document, move(qualified_name)) | ||||
|     , 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; | ||||
|  | @ -1284,4 +1276,20 @@ bool HTMLInputElement::is_submit_button() const | |||
|     return type_state() == TypeAttributeState::SubmitButton | ||||
|         || 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(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -149,6 +149,9 @@ public: | |||
|     JS::GCPtr<Element> placeholder_element() { 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: | ||||
|     HTMLInputElement(DOM::Document&, DOM::QualifiedName); | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,22 +15,29 @@ JS_DEFINE_ALLOCATOR(HTMLSummaryElement); | |||
| HTMLSummaryElement::HTMLSummaryElement(DOM::Document& document, DOM::QualifiedName 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; | ||||
| bool HTMLSummaryElement::has_activation_behavior() const | ||||
| { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|         // 2. Let parent be this summary element's parent.
 | ||||
|         auto* parent = this->parent_element(); | ||||
| void HTMLSummaryElement::activation_behavior(DOM::Event const&) | ||||
| { | ||||
|     // The activation behavior of summary elements is to run the following steps:
 | ||||
| 
 | ||||
|         // 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(); | ||||
|     }; | ||||
|     // 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
 | ||||
|  |  | |||
|  | @ -23,6 +23,9 @@ public: | |||
| 
 | ||||
|     bool is_summary_for_its_parent_details(); | ||||
| 
 | ||||
|     virtual bool has_activation_behavior() const override; | ||||
|     virtual void activation_behavior(DOM::Event const&) override; | ||||
| 
 | ||||
| private: | ||||
|     HTMLSummaryElement(DOM::Document&, DOM::QualifiedName); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling