Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/CSS/SelectorEngine.cpp (C++)

Code before:
    // From within shadow tree, only :host pseudo-class can match the host element
    if (component.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
        auto const& pseudo_class = component.pseudo_class();
        return pseudo_class.type != CSS::PseudoClass::Host
            && pseudo_class.type != CSS::PseudoClass::Has
            && pseudo_class.type != CSS::PseudoClass::Is
            && pseudo_class.type != CSS::PseudoClass::Where;
    }

    // Allow nesting and PseudoElement as it may contain :host class
    if (component.type == CSS::Selector::SimpleSelector::Type::Nesting || component.type == CSS::Selector::SimpleSelector::Type::PseudoElement)
        return false;

    return true;
}
// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-write
static bool matches_read_write_pseudo_class(DOM::Element const& element)
{
    // The :read-write pseudo-class must match any element falling into one of the following categories,
    // which for the purposes of Selectors are thus considered user-alterable: [SELECTORS]
    // - input elements to which the readonly attribute applies, and that are mutable
    //   (i.e. that do not have the readonly attribute specified and that are not disabled)
    if (is<HTML::HTMLInputElement>(element)) {
        auto const& input_element = static_cast<HTML::HTMLInputElement const&>(element);
        return input_element.is_allowed_to_be_readonly()
            && (!input_element.has_attribute(HTML::AttributeNames::readonly) && input_element.enabled());
    }
    // - textarea elements that do not have a readonly attribute, and that are not disabled
    if (is<HTML::HTMLTextAreaElement>(element)) {
        auto& input_element = static_cast<HTML::HTMLTextAreaElement const&>(element);
        if (input_element.has_attribute(HTML::AttributeNames::readonly))
            return false;
        if (!input_element.enabled())
            return false;
        return true;
    }
    // - elements that are editing hosts or editable and are neither input elements nor textarea elements
    return element.is_editable_or_editing_host();
}

// https://drafts.csswg.org/selectors-4/#open-state
static bool matches_open_state_pseudo_class(DOM::Element const& element, bool open)
{
    // The :open pseudo-class represents an element that has both “open” and “closed” states,
    // and which is currently in the “open” state.

    // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-open
    // The :open pseudo-class must match any element falling into one of the following categories:
    // - details elements that have an open attribute
    // - dialog elements that have an open attribute
    if (is<HTML::HTMLDetailsElement>(element) || is<HTML::HTMLDialogElement>(element))

Review comment (suggestion):
A couple of nits:
- While you're here, could you change this to use `as_if<HTML::HTMLInputElement>` instead of `is` and `static_cast`? eg, `if (auto* input_element = as_if<HTML::HTMLInputElement>(element)) { ... }`
- You don't need the extra `()` in the return statement, and I think it'd be clearer without them.

Code after:
    // From within shadow tree, only :host pseudo-class can match the host element
    if (component.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
        auto const& pseudo_class = component.pseudo_class();
        return pseudo_class.type != CSS::PseudoClass::Host
            && pseudo_class.type != CSS::PseudoClass::Has
            && pseudo_class.type != CSS::PseudoClass::Is
            && pseudo_class.type != CSS::PseudoClass::Where;
    }

    // Allow nesting and PseudoElement as it may contain :host class
    if (component.type == CSS::Selector::SimpleSelector::Type::Nesting || component.type == CSS::Selector::SimpleSelector::Type::PseudoElement)
        return false;

    return true;
}
// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-write
static bool matches_read_write_pseudo_class(DOM::Element const& element)
{
    // The :read-write pseudo-class must match any element falling into one of the following categories,
    // which for the purposes of Selectors are thus considered user-alterable: [SELECTORS]
    // - input elements to which the readonly attribute applies, and that are mutable
    //   (i.e. that do not have the readonly attribute specified and that are not disabled)
    if (auto const* input_element = as_if<HTML::HTMLInputElement>(element))
        return input_element->is_allowed_to_be_readonly()
            && !input_element->has_attribute(HTML::AttributeNames::readonly) && input_element->enabled();
    // - textarea elements that do not have a readonly attribute, and that are not disabled
    if (auto const* input_element = as_if<HTML::HTMLTextAreaElement>(element))
        return !input_element->has_attribute(HTML::AttributeNames::readonly) && input_element->enabled();
    // - elements that are editing hosts or editable and are neither input elements nor textarea elements
    return element.is_editable_or_editing_host();
}

// https://drafts.csswg.org/selectors-4/#open-state
static bool matches_open_state_pseudo_class(DOM::Element const& element, bool open)
{
    // The :open pseudo-class represents an element that has both “open” and “closed” states,
    // and which is currently in the “open” state.

    // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-open
    // The :open pseudo-class must match any element falling into one of the following categories:
    // - details elements that have an open attribute
    // - dialog elements that have an open attribute
    if (is<HTML::HTMLDetailsElement>(element) || is<HTML::HTMLDialogElement>(element))
        return open == element.has_attribute(HTML::AttributeNames::open);
    // - select elements that are a drop-down box and whose drop-down boxes are open
    if (auto const* select = as_if<HTML::HTMLSelectElement>(element))
        return open == select->is_open();
    // - input elements that support a picker and whose pickers are open
    if (auto const* input = as_if<HTML::HTMLInputElement>(element))
        return open == (input->supports_a_picker() && input->is_open());