diff --git a/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Libraries/LibWeb/HTML/HTMLOptionElement.cpp
index 0b74da36390..7d1da5a9b9e 100644
--- a/Libraries/LibWeb/HTML/HTMLOptionElement.cpp
+++ b/Libraries/LibWeb/HTML/HTMLOptionElement.cpp
@@ -191,24 +191,32 @@ bool HTMLOptionElement::disabled() const
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-form
-GC::Ptr HTMLOptionElement::form() const
+GC::Ptr HTMLOptionElement::form() const
{
// The form IDL attribute's behavior depends on whether the option element is in a select element or not.
// If the option has a select element as its parent, or has an optgroup element as its parent and that optgroup element has a select element as its parent,
// then the form IDL attribute must return the same value as the form IDL attribute on that select element.
// Otherwise, it must return null.
- auto const* parent = parent_element();
- if (is(parent))
- parent = parent->parent_element();
-
- if (is(parent)) {
- auto const* select_element = as(parent);
- return const_cast(select_element->form());
- }
+ if (auto select_element = owner_select_element())
+ return select_element->form();
return {};
}
+GC::Ptr HTMLOptionElement::owner_select_element()
+{
+ if (auto* maybe_parent = parent()) {
+ if (auto* select_element = as_if(*maybe_parent))
+ return select_element;
+ if (auto* opt_group_element = as_if(*maybe_parent)) {
+ if (auto* maybe_parent = opt_group_element->parent())
+ return as_if(*maybe_parent);
+ }
+ }
+
+ return nullptr;
+}
+
Optional HTMLOptionElement::default_role() const
{
// https://www.w3.org/TR/html-aria/#el-option
@@ -226,10 +234,8 @@ void HTMLOptionElement::inserted()
// If insertedNode's parent is a select element,
// or insertedNode's parent is an optgroup element whose parent is a select element,
// then run that select element's selectedness setting algorithm.
- if (is(*parent()))
- static_cast(*parent()).update_selectedness();
- else if (is(parent()) && parent()->parent() && is(*parent()->parent()))
- static_cast(*parent()->parent()).update_selectedness();
+ if (auto select_element = owner_select_element())
+ select_element->update_selectedness();
}
void HTMLOptionElement::removed_from(Node* old_parent, Node& old_root)
diff --git a/Libraries/LibWeb/HTML/HTMLOptionElement.h b/Libraries/LibWeb/HTML/HTMLOptionElement.h
index 08f42f706ea..ae0f1a56b8f 100644
--- a/Libraries/LibWeb/HTML/HTMLOptionElement.h
+++ b/Libraries/LibWeb/HTML/HTMLOptionElement.h
@@ -36,10 +36,13 @@ public:
bool disabled() const;
- GC::Ptr form() const;
+ GC::Ptr form() const;
virtual Optional default_role() const override;
+ GC::Ptr owner_select_element();
+ GC::Ptr owner_select_element() const { return const_cast(*this).owner_select_element(); }
+
private:
friend class Bindings::OptionConstructor;
friend class HTMLSelectElement;