summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibWeb/DOM/EventTarget.cpp8
-rw-r--r--Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp41
-rw-r--r--Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h52
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h7
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h7
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLImageElement.h7
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp8
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.h10
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h6
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h7
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h6
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h7
-rw-r--r--Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp11
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h7
21 files changed, 137 insertions, 61 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp
index 2a2e113a03..95c74d0090 100644
--- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp
+++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp
@@ -336,9 +336,11 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin
// 5. If element is not null and element has a form owner, let form owner be that form owner. Otherwise, let form owner be null.
RefPtr<HTML::HTMLFormElement> form_owner;
if (is<HTML::FormAssociatedElement>(element.ptr())) {
- auto& form_associated_element = verify_cast<HTML::FormAssociatedElement>(*element);
- if (form_associated_element.form())
- form_owner = form_associated_element.form();
+ auto* form_associated_element = dynamic_cast<HTML::FormAssociatedElement*>(element.ptr());
+ VERIFY(form_associated_element);
+
+ if (form_associated_element->form())
+ form_owner = form_associated_element->form();
}
// 6. Let settings object be the relevant settings object of document.
diff --git a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
index 5b9c2dd8a0..01fb5f5d9d 100644
--- a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
@@ -12,44 +12,49 @@
#include <LibWeb/HTML/HTMLLegendElement.h>
#include <LibWeb/HTML/HTMLSelectElement.h>
#include <LibWeb/HTML/HTMLTextAreaElement.h>
+#include <LibWeb/HTML/Parser/HTMLParser.h>
namespace Web::HTML {
void FormAssociatedElement::set_form(HTMLFormElement* form)
{
if (m_form)
- m_form->remove_associated_element({}, *this);
+ m_form->remove_associated_element({}, form_associated_element_to_html_element());
m_form = form;
if (m_form)
- m_form->add_associated_element({}, *this);
+ m_form->add_associated_element({}, form_associated_element_to_html_element());
}
bool FormAssociatedElement::enabled() const
{
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-disabled
+ auto const& html_element = const_cast<FormAssociatedElement&>(*this).form_associated_element_to_html_element();
// A form control is disabled if any of the following conditions are met:
// 1. The element is a button, input, select, textarea, or form-associated custom element, and the disabled attribute is specified on this element (regardless of its value).
// FIXME: This doesn't check for form-associated custom elements.
- if ((is<HTMLButtonElement>(this) || is<HTMLInputElement>(this) || is<HTMLSelectElement>(this) || is<HTMLTextAreaElement>(this)) && has_attribute(HTML::AttributeNames::disabled))
+ if ((is<HTMLButtonElement>(html_element) || is<HTMLInputElement>(html_element) || is<HTMLSelectElement>(html_element) || is<HTMLTextAreaElement>(html_element)) && html_element.has_attribute(HTML::AttributeNames::disabled))
return false;
// 2. The element is a descendant of a fieldset element whose disabled attribute is specified, and is not a descendant of that fieldset element's first legend element child, if any.
- auto* fieldset_ancestor = first_ancestor_of_type<HTMLFieldSetElement>();
+ auto* fieldset_ancestor = html_element.first_ancestor_of_type<HTMLFieldSetElement>();
if (fieldset_ancestor && fieldset_ancestor->has_attribute(HTML::AttributeNames::disabled)) {
auto* first_legend_element_child = fieldset_ancestor->first_child_of_type<HTMLLegendElement>();
- if (!first_legend_element_child || !is_descendant_of(*first_legend_element_child))
+ if (!first_legend_element_child || !html_element.is_descendant_of(*first_legend_element_child))
return false;
}
return true;
}
-// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#association-of-controls-and-forms:nodes-are-inserted
-void FormAssociatedElement::inserted()
+void FormAssociatedElement::set_parser_inserted(Badge<HTMLParser>)
{
- HTMLElement::inserted();
+ m_parser_inserted = true;
+}
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#association-of-controls-and-forms:nodes-are-inserted
+void FormAssociatedElement::form_node_was_inserted()
+{
// 1. If the form-associated element's parser inserted flag is set, then return.
if (m_parser_inserted)
return;
@@ -59,18 +64,18 @@ void FormAssociatedElement::inserted()
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#association-of-controls-and-forms:nodes-are-removed
-void FormAssociatedElement::removed_from(DOM::Node* node)
+void FormAssociatedElement::form_node_was_removed()
{
- HTMLElement::removed_from(node);
-
// 1. If the form-associated element has a form owner and the form-associated element and its form owner are no longer in the same tree, then reset the form owner of the form-associated element.
- if (m_form && &root() != &m_form->root())
+ if (m_form && &form_associated_element_to_html_element().root() != &m_form->root())
reset_form_owner();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#reset-the-form-owner
void FormAssociatedElement::reset_form_owner()
{
+ auto& html_element = form_associated_element_to_html_element();
+
// Although these aren't in the "reset form owner" algorithm, these here as they are triggers for this algorithm:
// FIXME: When a listed form-associated element's form attribute is set, changed, or removed, then the user agent must reset the form owner of that element.
// FIXME: When a listed form-associated element has a form attribute and the ID of any of the elements in the tree changes, then the user agent must reset the form owner of that form-associated element.
@@ -85,8 +90,8 @@ void FormAssociatedElement::reset_form_owner()
// - element's form owner is its nearest form element ancestor after the change to the ancestor chain
// then do nothing, and return.
if (m_form
- && (!is_listed() || !has_attribute(HTML::AttributeNames::form))
- && first_ancestor_of_type<HTMLFormElement>() == m_form.ptr()) {
+ && (!is_listed() || !html_element.has_attribute(HTML::AttributeNames::form))
+ && html_element.first_ancestor_of_type<HTMLFormElement>() == m_form.ptr()) {
return;
}
@@ -94,10 +99,10 @@ void FormAssociatedElement::reset_form_owner()
set_form(nullptr);
// 4. If element is listed, has a form content attribute, and is connected, then:
- if (is_listed() && has_attribute(HTML::AttributeNames::form) && is_connected()) {
+ if (is_listed() && html_element.has_attribute(HTML::AttributeNames::form) && html_element.is_connected()) {
// 1. If the first element in element's tree, in tree order, to have an ID that is identical to element's form content attribute's value, is a form element, then associate the element with that form element.
- auto form_value = attribute(HTML::AttributeNames::form);
- root().for_each_in_inclusive_subtree_of_type<HTMLFormElement>([this, &form_value](HTMLFormElement& form_element) mutable {
+ auto form_value = html_element.attribute(HTML::AttributeNames::form);
+ html_element.root().for_each_in_inclusive_subtree_of_type<HTMLFormElement>([this, &form_value](HTMLFormElement& form_element) mutable {
if (form_element.attribute(HTML::AttributeNames::id) == form_value) {
set_form(&form_element);
return IterationDecision::Break;
@@ -109,7 +114,7 @@ void FormAssociatedElement::reset_form_owner()
// 5. Otherwise, if element has an ancestor form element, then associate element with the nearest such ancestor form element.
else {
- auto* form_ancestor = first_ancestor_of_type<HTMLFormElement>();
+ auto* form_ancestor = html_element.first_ancestor_of_type<HTMLFormElement>();
if (form_ancestor)
set_form(form_ancestor);
}
diff --git a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
index 9342244111..1434eedec2 100644
--- a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
+++ b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
@@ -8,11 +8,39 @@
#include <AK/WeakPtr.h>
#include <LibWeb/Forward.h>
-#include <LibWeb/HTML/HTMLElement.h>
namespace Web::HTML {
-class FormAssociatedElement : public HTMLElement {
+// Form-associated elements should invoke this macro to inject overidden FormAssociatedElement and HTMLElement
+// methods as needed. If your class wished to override an HTMLElement method that is overidden here, use the
+// following methods instead:
+//
+// HTMLElement::inserted() -> Use form_associated_element_was_inserted()
+// HTMLElement::removed_from() -> Use form_associated_element_was_removed()
+//
+#define FORM_ASSOCIATED_ELEMENT(ElementBaseClass, ElementClass) \
+private: \
+ virtual HTMLElement& form_associated_element_to_html_element() override \
+ { \
+ static_assert(IsBaseOf<HTMLElement, ElementClass>); \
+ return *this; \
+ } \
+ \
+ virtual void inserted() override \
+ { \
+ ElementBaseClass::inserted(); \
+ form_node_was_inserted(); \
+ form_associated_element_was_inserted(); \
+ } \
+ \
+ virtual void removed_from(DOM::Node* node) override \
+ { \
+ ElementBaseClass::removed_from(node); \
+ form_node_was_removed(); \
+ form_associated_element_was_removed(node); \
+ }
+
+class FormAssociatedElement {
public:
HTMLFormElement* form() { return m_form; }
HTMLFormElement const* form() const { return m_form; }
@@ -21,7 +49,7 @@ public:
bool enabled() const;
- void set_parser_inserted(Badge<HTMLParser>) { m_parser_inserted = true; }
+ void set_parser_inserted(Badge<HTMLParser>);
// https://html.spec.whatwg.org/multipage/forms.html#category-listed
virtual bool is_listed() const { return false; }
@@ -35,14 +63,18 @@ public:
// https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize
virtual bool is_auto_capitalize_inheriting() const { return false; }
-protected:
- FormAssociatedElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : HTMLElement(document, move(qualified_name))
- {
- }
+ virtual HTMLElement& form_associated_element_to_html_element() = 0;
+protected:
+ FormAssociatedElement() = default;
virtual ~FormAssociatedElement() = default;
+ virtual void form_associated_element_was_inserted() { }
+ virtual void form_associated_element_was_removed(DOM::Node*) { }
+
+ void form_node_was_inserted();
+ void form_node_was_removed();
+
private:
WeakPtr<HTMLFormElement> m_form;
@@ -50,10 +82,6 @@ private:
bool m_parser_inserted { false };
void reset_form_owner();
-
- // ^DOM::Node
- virtual void inserted() override;
- virtual void removed_from(DOM::Node*) override;
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp
index 60eca9f5d5..0057e1fcb3 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp
@@ -11,7 +11,7 @@
namespace Web::HTML {
HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(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&) {
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h
index 93e6bc5e09..eba1aacda8 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h
@@ -7,6 +7,7 @@
#pragma once
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
namespace Web::HTML {
@@ -15,7 +16,11 @@ namespace Web::HTML {
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(reset, Reset) \
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(button, Button)
-class HTMLButtonElement final : public FormAssociatedElement {
+class HTMLButtonElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLButtonElement)
+
public:
using WrapperType = Bindings::HTMLButtonElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp
index a5cac9f77c..2d3db560f1 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp
@@ -9,7 +9,7 @@
namespace Web::HTML {
HTMLFieldSetElement::HTMLFieldSetElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
{
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h
index c0b5fe9389..cb3427e697 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h
@@ -7,10 +7,15 @@
#pragma once
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
namespace Web::HTML {
-class HTMLFieldSetElement final : public FormAssociatedElement {
+class HTMLFieldSetElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLFieldSetElement)
+
public:
using WrapperType = Bindings::HTMLFieldSetElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
index d7d5bc5246..7014094cf8 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
@@ -18,7 +18,7 @@
namespace Web::HTML {
HTMLImageElement::HTMLImageElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
, m_image_loader(*this)
{
m_image_loader.on_load = [this] {
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
index 29531f56f2..e488e96f58 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
@@ -10,11 +10,16 @@
#include <AK/OwnPtr.h>
#include <LibGfx/Forward.h>
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
#include <LibWeb/Loader/ImageLoader.h>
namespace Web::HTML {
-class HTMLImageElement final : public FormAssociatedElement {
+class HTMLImageElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLImageElement)
+
public:
using WrapperType = Bindings::HTMLImageElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 27a2486ebb..924640e3b7 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -21,7 +21,7 @@
namespace Web::HTML {
HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
, m_value(String::empty())
{
activation_behavior = [this](auto&) {
@@ -215,7 +215,7 @@ bool HTMLInputElement::is_focusable() const
void HTMLInputElement::parse_attribute(FlyString const& name, String const& value)
{
- FormAssociatedElement::parse_attribute(name, value);
+ HTMLElement::parse_attribute(name, value);
if (name == HTML::AttributeNames::checked) {
// When the checked content attribute is added, if the control does not have dirty checkedness,
// the user agent must set the checkedness of the element to true
@@ -245,7 +245,7 @@ HTMLInputElement::TypeAttributeState HTMLInputElement::parse_type_attribute(Stri
void HTMLInputElement::did_remove_attribute(FlyString const& name)
{
- FormAssociatedElement::did_remove_attribute(name);
+ HTMLElement::did_remove_attribute(name);
if (name == HTML::AttributeNames::checked) {
// When the checked content attribute is removed, if the control does not have dirty checkedness,
// the user agent must set the checkedness of the element to false.
@@ -310,7 +310,7 @@ String HTMLInputElement::value_sanitization_algorithm(String value) const
return value;
}
-void HTMLInputElement::inserted()
+void HTMLInputElement::form_associated_element_was_inserted()
{
create_shadow_tree_if_needed();
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
index 75ddaa1cf0..d567f09dc4 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
@@ -37,7 +37,11 @@ namespace Web::HTML {
__ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(reset, ResetButton) \
__ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(button, Button)
-class HTMLInputElement final : public FormAssociatedElement {
+class HTMLInputElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLInputElement)
+
public:
using WrapperType = Bindings::HTMLInputElementWrapper;
@@ -92,12 +96,12 @@ public:
// https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize
virtual bool is_auto_capitalize_inheriting() const override { return true; }
+ virtual void form_associated_element_was_inserted() override;
+
// ^HTMLElement
// https://html.spec.whatwg.org/multipage/forms.html#category-label
virtual bool is_labelable() const override { return type_state() != TypeAttributeState::Hidden; }
- virtual void inserted() override;
-
private:
// ^DOM::EventTarget
virtual void did_receive_focus() override;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
index 01fe96bb31..152449e0a7 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
@@ -15,7 +15,7 @@
namespace Web::HTML {
HTMLObjectElement::HTMLObjectElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
{
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
index 705fd356d6..b1b99cc13d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
@@ -9,13 +9,17 @@
#include <LibCore/Forward.h>
#include <LibGfx/Forward.h>
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
#include <LibWeb/Loader/ImageLoader.h>
namespace Web::HTML {
class HTMLObjectElement final
- : public FormAssociatedElement
+ : public HTMLElement
+ , public FormAssociatedElement
, public ResourceClient {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLObjectElement)
+
public:
using WrapperType = Bindings::HTMLObjectElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp
index 9c43acc2ca..e9fcc6a941 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.cpp
@@ -9,7 +9,7 @@
namespace Web::HTML {
HTMLOutputElement::HTMLOutputElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
{
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h
index d2662d877a..3e38612e8e 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h
@@ -8,10 +8,15 @@
#pragma once
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
namespace Web::HTML {
-class HTMLOutputElement final : public FormAssociatedElement {
+class HTMLOutputElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLOutputElement)
+
public:
using WrapperType = Bindings::HTMLOutputElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp
index 838987857e..94333e018d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp
@@ -13,7 +13,7 @@
namespace Web::HTML {
HTMLSelectElement::HTMLSelectElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
{
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h
index c8ad0930a6..4408531b1d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h
@@ -14,7 +14,11 @@
namespace Web::HTML {
-class HTMLSelectElement final : public FormAssociatedElement {
+class HTMLSelectElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLSelectElement)
+
public:
using WrapperType = Bindings::HTMLSelectElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
index 35a766e4c7..e9c0db91d4 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
@@ -9,7 +9,7 @@
namespace Web::HTML {
HTMLTextAreaElement::HTMLTextAreaElement(DOM::Document& document, DOM::QualifiedName qualified_name)
- : FormAssociatedElement(document, move(qualified_name))
+ : HTMLElement(document, move(qualified_name))
{
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
index 376d0def13..4ea7124dab 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
@@ -8,10 +8,15 @@
#pragma once
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
namespace Web::HTML {
-class HTMLTextAreaElement final : public FormAssociatedElement {
+class HTMLTextAreaElement final
+ : public HTMLElement
+ , public FormAssociatedElement {
+ FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLTextAreaElement)
+
public:
using WrapperType = Bindings::HTMLTextAreaElementWrapper;
diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
index 01b3e91fba..b8731acec0 100644
--- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp
@@ -632,14 +632,17 @@ NonnullRefPtr<DOM::Element> HTMLParser::create_element_for(HTMLToken const& toke
// then associate element with the form element pointed to by the form element pointer and set element's parser inserted flag.
// FIXME: Check if the element is not a form-associated custom element.
if (is<FormAssociatedElement>(*element)) {
- auto& form_associated_element = static_cast<FormAssociatedElement&>(*element);
+ auto* form_associated_element = dynamic_cast<FormAssociatedElement*>(element.ptr());
+ VERIFY(form_associated_element);
+
+ auto& html_element = form_associated_element->form_associated_element_to_html_element();
if (m_form_element
&& !m_stack_of_open_elements.contains(HTML::TagNames::template_)
- && (!form_associated_element.is_listed() || !form_associated_element.has_attribute(HTML::AttributeNames::form))
+ && (!form_associated_element->is_listed() || !html_element.has_attribute(HTML::AttributeNames::form))
&& &intended_parent.root() == &m_form_element->root()) {
- form_associated_element.set_form(m_form_element);
- form_associated_element.set_parser_inserted({});
+ form_associated_element->set_form(m_form_element);
+ form_associated_element->set_parser_inserted({});
}
}
diff --git a/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h b/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h
index 8186117cb2..8aacbaf93a 100644
--- a/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h
+++ b/Userland/Libraries/LibWeb/Layout/FormAssociatedLabelableNode.h
@@ -8,18 +8,19 @@
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/FormAssociatedElement.h>
+#include <LibWeb/HTML/HTMLElement.h>
#include <LibWeb/Layout/LabelableNode.h>
namespace Web::Layout {
class FormAssociatedLabelableNode : public LabelableNode {
public:
- const HTML::FormAssociatedElement& dom_node() const { return static_cast<const HTML::FormAssociatedElement&>(LabelableNode::dom_node()); }
- HTML::FormAssociatedElement& dom_node() { return static_cast<HTML::FormAssociatedElement&>(LabelableNode::dom_node()); }
+ const HTML::FormAssociatedElement& dom_node() const { return dynamic_cast<const HTML::FormAssociatedElement&>(LabelableNode::dom_node()); }
+ HTML::FormAssociatedElement& dom_node() { return dynamic_cast<HTML::FormAssociatedElement&>(LabelableNode::dom_node()); }
protected:
FormAssociatedLabelableNode(DOM::Document& document, HTML::FormAssociatedElement& element, NonnullRefPtr<CSS::StyleProperties> style)
- : LabelableNode(document, element, move(style))
+ : LabelableNode(document, element.form_associated_element_to_html_element(), move(style))
{
}