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;