diff --git a/Tests/LibWeb/Text/expected/HTML/HTMLLabelElement-form.txt b/Tests/LibWeb/Text/expected/HTML/HTMLLabelElement-form.txt
new file mode 100644
index 00000000000..c3a4f4c3562
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/HTML/HTMLLabelElement-form.txt
@@ -0,0 +1,12 @@
+ Form for #label-no-for is null
+Control for #label-no-for is null: true
+Form for #parent-of-input2: #form2
+label.form is the same as label.control.form for #parent-of-input2: true
+Form for #label-for-input2: #form2
+label.form is the same as label.control.form for #label-for-input2: true
+Form for #label-for-input1: #form1
+label.form is the same as label.control.form for #label-for-input1: true
+Form for #label-for-non-labelable-element is null
+Control for #label-for-non-labelable-element is null: true
+Form for #label-for-nonexistent-element is null
+Control for #label-for-nonexistent-element is null: true
diff --git a/Tests/LibWeb/Text/input/HTML/HTMLLabelElement-form.html b/Tests/LibWeb/Text/input/HTML/HTMLLabelElement-form.html
new file mode 100644
index 00000000000..4baf43a2cc8
--- /dev/null
+++ b/Tests/LibWeb/Text/input/HTML/HTMLLabelElement-form.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp
index 26f668e8a13..cacff5ff2c4 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.cpp
@@ -6,6 +6,7 @@
#include
#include
+#include
#include
#include
@@ -66,4 +67,21 @@ JS::GCPtr HTMLLabelElement::control() const
return control;
}
+// https://html.spec.whatwg.org/multipage/forms.html#dom-label-form
+JS::GCPtr HTMLLabelElement::form() const
+{
+ auto labeled_control = control();
+
+ // 1. If the label element has no labeled control, then return null.
+ if (!labeled_control)
+ return {};
+
+ // 2. If the label element's labeled control is not a form-associated element, then return null.
+ if (!is(*labeled_control))
+ return {};
+
+ // 3. Return the label element's labeled control's form owner (which can still be null).
+ return dynamic_cast(labeled_control.ptr())->form();
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h
index 698061ceb25..56e1e41d816 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.h
@@ -22,6 +22,7 @@ public:
Optional for_() const { return attribute(HTML::AttributeNames::for_); }
JS::GCPtr control() const;
+ JS::GCPtr form() const;
private:
HTMLLabelElement(DOM::Document&, DOM::QualifiedName);
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.idl
index f54ba425aac..b10132fe7cc 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.idl
+++ b/Userland/Libraries/LibWeb/HTML/HTMLLabelElement.idl
@@ -6,7 +6,7 @@ interface HTMLLabelElement : HTMLElement {
[HTMLConstructor] constructor();
- // FIXME: readonly attribute HTMLFormElement? form;
+ readonly attribute HTMLFormElement? form;
[CEReactions, Reflect=for] attribute DOMString htmlFor;
readonly attribute HTMLElement? control;