mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 22:15:07 +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;
|
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.
|
||||||
|
|
|
@ -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&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() { }
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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.
|
bool HTMLSummaryElement::has_activation_behavior() const
|
||||||
if (!is_summary_for_its_parent_details())
|
{
|
||||||
return;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 2. Let parent be this summary element's parent.
|
void HTMLSummaryElement::activation_behavior(DOM::Event const&)
|
||||||
auto* parent = this->parent_element();
|
{
|
||||||
|
// 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.
|
// 1. If this summary element is not the summary for its parent details, then return.
|
||||||
if (parent->has_attribute(HTML::AttributeNames::open))
|
if (!is_summary_for_its_parent_details())
|
||||||
parent->remove_attribute(HTML::AttributeNames::open);
|
return;
|
||||||
else
|
|
||||||
parent->set_attribute(HTML::AttributeNames::open, String {}).release_value_but_fixme_should_propagate_errors();
|
// 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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue