Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/DOM/Element.cpp (C++)

Code before:

        //      - If there is no pragma-set default language set, then language information from a higher-level protocol (such as HTTP),
        if (document().http_content_language().has_value()) {
            return document().http_content_language();
        }

        //        if any, must be used as the final fallback language instead.
        //      - In the absence of any such language information, and in cases where the higher-level protocol reports multiple languages,
        //        the language of the node is unknown, and the corresponding language tag is the empty string.
        // Default locale sounds like a reasonable fallback here.
        return {};
    };

    if (!m_lang_value.has_value()) {
        // If the resulting value is the empty string, then it must be interpreted as meaning that the language of the node is explicitly unknown.
        m_lang_value = attempt_to_determine_lang_attribute().value_or(String {});
    }
    if (m_lang_value->is_empty())
        return {};
    return m_lang_value;
}

template<typename Callback>
void Element::for_each_numbered_item_owned_by_list_owner(Callback callback)
{
    for (auto* node = this->first_child(); node != nullptr; node = node->next_in_pre_order(this)) {
        auto* element = as_if<Element>(node);
        if (!element)
            continue;

        element->m_is_contained_in_list_subtree = true;

        if (node->is_html_ol_ul_menu_element()) {
            // Skip list nodes and their descendents. They have their own, unrelated ordinals.
            while (node->last_child() != nullptr) // Find the last node (preorder) in the subtree headed by node. O(1).
                node = node->last_child();

            continue;
        }

        if (!node->layout_node())
            continue; // Skip nodes that do not participate in the layout.

        if (!element->computed_properties()->display().is_list_item())
            continue; // Skip nodes that are not list items.

        if (callback(element) == IterationDecision::Break)
            return;
    }
}


Review comment (performance):
Hm, shouldn't we invalidate this cache if any of the conditions/values in `attempt_to_determine_lang_attribute` have changed?

Code after:
        // 5. Otherwise
        //      - If there is a pragma-set default language set, then that is the language of the node.
        if (document().pragma_set_default_language().has_value()) {
            return document().pragma_set_default_language().value_or({});
        }

        //      - If there is no pragma-set default language set, then language information from a higher-level protocol (such as HTTP),
        if (document().http_content_language().has_value()) {
            return document().http_content_language().value_or({});
        }

        //        if any, must be used as the final fallback language instead.
        //      - In the absence of any such language information, and in cases where the higher-level protocol reports multiple languages,
        //        the language of the node is unknown, and the corresponding language tag is the empty string.
        // Default locale sounds like a reasonable fallback here.
        return {};
    };

    if (!m_lang_value.has_value())
        m_lang_value = determine_lang_attribute();

    // If the resulting value is the empty string, then it must be interpreted as meaning that the language of the node is explicitly unknown.
    if (m_lang_value->is_empty())
        return {};

    return m_lang_value;
}

void Element::invalidate_lang_value()
{
    if (m_lang_value.has_value()) {
        m_lang_value.clear();
        set_needs_style_update(true);
    }
}

template<typename Callback>
void Element::for_each_numbered_item_owned_by_list_owner(Callback callback)
{
    for (auto* node = this->first_child(); node != nullptr; node = node->next_in_pre_order(this)) {
        auto* element = as_if<Element>(node);
        if (!element)
            continue;

        element->m_is_contained_in_list_subtree = true;

        if (node->is_html_ol_ul_menu_element()) {
            // Skip list nodes and their descendents. They have their own, unrelated ordinals.
            while (node->last_child() != nullptr) // Find the last node (preorder) in the subtree headed by node. O(1).
                node = node->last_child();