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

Code before:
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *old_focused_node_root, node);
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *old_focused_node_root, node);
        }
        if (new_focused_node_root) {
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *new_focused_node_root, node);
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *new_focused_node_root, node);
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *new_focused_node_root, node);
        }
    } else {
        invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *common_ancestor, node);
        invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *common_ancestor, node);
        invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *common_ancestor, node);
    }

    m_focused_area = node;

    auto* new_focused_element = as_if<Element>(node.ptr());
    if (new_focused_element)
        new_focused_element->did_receive_focus();

    if (paintable())
        paintable()->set_needs_display();

    // Scroll the viewport if necessary to make the newly focused element visible.
    if (new_focused_element) {
        auto focused_element = GC::make_root(*new_focused_element);
        new_focused_element->queue_an_element_task(HTML::Task::Source::UserInteraction, [focused_element] {
            if (focused_element->document().focused_area().ptr() != focused_element.ptr())
                return;
            ScrollIntoViewOptions scroll_options;
            scroll_options.block = Bindings::ScrollLogicalPosition::Nearest;
            scroll_options.inline_ = Bindings::ScrollLogicalPosition::Nearest;
            (void)focused_element->scroll_into_view(scroll_options);
        });
    }

    update_active_element();
}

void Document::set_active_element(GC::Ptr<Element> element)
{
    if (m_active_element.ptr() == element)
        return;

    auto old_active_element = move(m_active_element);
    auto* common_ancestor = find_common_ancestor(old_active_element, element);

    GC::Ptr<Node> old_active_node_root = nullptr;
    GC::Ptr<Node> new_active_node_root = nullptr;
    if (old_active_element)
        old_active_node_root = old_active_element->root();

Review comment (suggestion):
This should not need any GC root, `queue_an_element_task` calls `queue_a_task` which accepts a `GC::Function` - and a GC function has knowledge of captures and lets the heap visit possible GC pointers as to not free them. In fact making this a root makes this more likely to leak.

Code after:
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *old_focused_node_root, node);
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *old_focused_node_root, node);
        }
        if (new_focused_node_root) {
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *new_focused_node_root, node);
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *new_focused_node_root, node);
            invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *new_focused_node_root, node);
        }
    } else {
        invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *common_ancestor, node);
        invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *common_ancestor, node);
        invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *common_ancestor, node);
    }

    m_focused_area = node;

    auto* new_focused_element = as_if<Element>(node.ptr());
    if (new_focused_element)
        new_focused_element->did_receive_focus();

    if (paintable())
        paintable()->set_needs_display();

    // Scroll the viewport if necessary to make the newly focused element visible.
    if (new_focused_element) {
        new_focused_element->queue_an_element_task(HTML::Task::Source::UserInteraction, [new_focused_element] {
            if (new_focused_element->document().focused_area().ptr() != new_focused_element)
                return;
            ScrollIntoViewOptions scroll_options;
            scroll_options.block = Bindings::ScrollLogicalPosition::Nearest;
            scroll_options.inline_ = Bindings::ScrollLogicalPosition::Nearest;
            (void)new_focused_element->scroll_into_view(scroll_options);
        });
    }

    update_active_element();
}

void Document::set_active_element(GC::Ptr<Element> element)
{
    if (m_active_element.ptr() == element)
        return;

    auto old_active_element = move(m_active_element);
    auto* common_ancestor = find_common_ancestor(old_active_element, element);

    GC::Ptr<Node> old_active_node_root = nullptr;
    GC::Ptr<Node> new_active_node_root = nullptr;
    if (old_active_element)
        old_active_node_root = old_active_element->root();
    if (element)