diff --git a/Tests/LibWeb/Text/expected/HTML/Form-named-property-access.txt b/Tests/LibWeb/Text/expected/HTML/Form-named-property-access.txt
index 1344a3d714..dee9ba8cbd 100644
--- a/Tests/LibWeb/Text/expected/HTML/Form-named-property-access.txt
+++ b/Tests/LibWeb/Text/expected/HTML/Form-named-property-access.txt
@@ -1,4 +1,4 @@
- == Elements and Names ==
+ == Elements and Names ==
formy.length: 12
elements.length: 12
elements[0] === form.foo
@@ -32,3 +32,9 @@ Can we still use the same name?: true
new hello is goodbye? false
new hello is old hello? false
new hello is newInput? true
+== Changing form attribute ==
+elements in changeForFormAttribute: 0
+elements in changeForFormAttribute: 1
+elements in changeForFormAttribute: 0
+elements in changeForFormAttribute: 1
+elements in changeForFormAttribute: 0
diff --git a/Tests/LibWeb/Text/input/HTML/Form-named-property-access.html b/Tests/LibWeb/Text/input/HTML/Form-named-property-access.html
index 17abba5682..8b492768e7 100644
--- a/Tests/LibWeb/Text/input/HTML/Form-named-property-access.html
+++ b/Tests/LibWeb/Text/input/HTML/Form-named-property-access.html
@@ -60,6 +60,9 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
index c1b4bfd0df..333d424830 100644
--- a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
@@ -72,13 +72,22 @@ void FormAssociatedElement::form_node_was_removed()
reset_form_owner();
}
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#association-of-controls-and-forms:category-listed-3
+void FormAssociatedElement::form_node_attribute_changed(FlyString const& name, Optional const&)
+{
+ // 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.
+ if (name == HTML::AttributeNames::form) {
+ 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.
// FIXME: When a listed form-associated element has a form attribute and an element with an ID is inserted into or removed from the Document, then the user agent must reset the form owner of that form-associated element.
diff --git a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
index b15d052033..90a69f7610 100644
--- a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
+++ b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
@@ -19,26 +19,33 @@ namespace Web::HTML {
// 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); \
- 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); \
+#define FORM_ASSOCIATED_ELEMENT(ElementBaseClass, ElementClass) \
+private: \
+ virtual HTMLElement& form_associated_element_to_html_element() override \
+ { \
+ static_assert(IsBaseOf); \
+ 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); \
+ } \
+ \
+ virtual void attribute_changed(FlyString const& name, Optional const& value) override \
+ { \
+ ElementBaseClass::attribute_changed(name, value); \
+ form_node_attribute_changed(name, value); \
+ form_associated_element_attribute_changed(name, value); \
}
class FormAssociatedElement {
@@ -83,9 +90,11 @@ protected:
virtual void form_associated_element_was_inserted() { }
virtual void form_associated_element_was_removed(DOM::Node*) { }
+ virtual void form_associated_element_attribute_changed(FlyString const&, Optional const&) { }
void form_node_was_inserted();
void form_node_was_removed();
+ void form_node_attribute_changed(FlyString const&, Optional const&);
private:
WeakPtr m_form;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
index 78fb99253b..9f5018bc3f 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp
@@ -97,10 +97,8 @@ void HTMLImageElement::apply_presentational_hints(CSS::StyleProperties& style) c
});
}
-void HTMLImageElement::attribute_changed(FlyString const& name, Optional const& value)
+void HTMLImageElement::form_associated_element_attribute_changed(FlyString const& name, Optional const& value)
{
- HTMLElement::attribute_changed(name, value);
-
if (name == HTML::AttributeNames::crossorigin) {
m_cors_setting = cors_setting_attribute_from_keyword(value);
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
index 364096f368..5a2821fbff 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h
@@ -37,7 +37,7 @@ class HTMLImageElement final
public:
virtual ~HTMLImageElement() override;
- virtual void attribute_changed(FlyString const& name, Optional const& value) override;
+ virtual void form_associated_element_attribute_changed(FlyString const& name, Optional const& value) override;
String alt() const { return get_attribute_value(HTML::AttributeNames::alt); }
String src() const { return get_attribute_value(HTML::AttributeNames::src); }
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 38e2d38667..b421f77b33 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -833,9 +833,8 @@ void HTMLInputElement::did_lose_focus()
commit_pending_changes();
}
-void HTMLInputElement::attribute_changed(FlyString const& name, Optional const& value)
+void HTMLInputElement::form_associated_element_attribute_changed(FlyString const& name, Optional const& value)
{
- HTMLElement::attribute_changed(name, value);
if (name == HTML::AttributeNames::checked) {
if (!value.has_value()) {
// When the checked content attribute is removed, if the control does not have dirty checkedness,
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
index 5f4004addc..236a3b68d4 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
@@ -126,9 +126,6 @@ public:
// https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute:the-input-element
virtual bool is_focusable() const override { return m_type != TypeAttributeState::Hidden; }
- // ^HTMLElement
- virtual void attribute_changed(FlyString const&, Optional const&) override;
-
// ^FormAssociatedElement
// https://html.spec.whatwg.org/multipage/forms.html#category-listed
virtual bool is_listed() const override { return true; }
@@ -152,6 +149,7 @@ public:
virtual void form_associated_element_was_inserted() override;
virtual void form_associated_element_was_removed(DOM::Node*) override;
+ virtual void form_associated_element_attribute_changed(FlyString const&, Optional const&) override;
// ^HTMLElement
// https://html.spec.whatwg.org/multipage/forms.html#category-label
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
index 22197ccd8d..3aa48c5184 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp
@@ -48,10 +48,8 @@ void HTMLObjectElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_image_request);
}
-void HTMLObjectElement::attribute_changed(FlyString const& name, Optional const& value)
+void HTMLObjectElement::form_associated_element_attribute_changed(FlyString const& name, Optional const&)
{
- NavigableContainer::attribute_changed(name, value);
-
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element
// Whenever one of the following conditions occur:
if (
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
index 88118a0cf5..4849df3e34 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h
@@ -35,7 +35,7 @@ class HTMLObjectElement final
public:
virtual ~HTMLObjectElement() override;
- virtual void attribute_changed(FlyString const& name, Optional const& value) override;
+ virtual void form_associated_element_attribute_changed(FlyString const& name, Optional const& value) override;
String data() const;
void set_data(String const& data) { MUST(set_attribute(HTML::AttributeNames::data, data)); }
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
index b5e613e7e7..b41eb4990e 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
@@ -240,9 +240,8 @@ void HTMLTextAreaElement::children_changed()
}
}
-void HTMLTextAreaElement::attribute_changed(FlyString const& name, Optional const& value)
+void HTMLTextAreaElement::form_associated_element_attribute_changed(FlyString const& name, Optional const& value)
{
- HTMLElement::attribute_changed(name, value);
if (name == HTML::AttributeNames::placeholder) {
if (m_placeholder_text_node)
m_placeholder_text_node->set_data(value.value_or(String {}));
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
index 6d38ff9ef7..df311814b2 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
@@ -55,9 +55,6 @@ public:
// https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize
virtual bool is_auto_capitalize_inheriting() const override { return true; }
- // ^HTMLElement
- virtual void attribute_changed(FlyString const&, Optional const&) override;
-
// https://html.spec.whatwg.org/multipage/forms.html#category-label
virtual bool is_labelable() const override { return true; }
@@ -65,6 +62,7 @@ public:
virtual void form_associated_element_was_inserted() override;
virtual void form_associated_element_was_removed(DOM::Node*) override;
+ virtual void form_associated_element_attribute_changed(FlyString const&, Optional const&) override;
virtual void children_changed() override;