diff options
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)) { } |