1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-23 18:55:08 +00:00

LibWeb+LibJS: Make the EventTarget hierarchy (incl. DOM) GC-allocated

This is a monster patch that turns all EventTargets into GC-allocated
PlatformObjects. Their C++ wrapper classes are removed, and the LibJS
garbage collector is now responsible for their lifetimes.

There's a fair amount of hacks and band-aids in this patch, and we'll
have a lot of cleanup to do after this.
This commit is contained in:
Andreas Kling 2022-08-28 13:42:07 +02:00
parent bb547ce1c4
commit 6f433c8656
445 changed files with 4797 additions and 4268 deletions

View file

@ -17,9 +17,9 @@ StackOfOpenElements::~StackOfOpenElements() = default;
bool StackOfOpenElements::has_in_scope_impl(FlyString const& tag_name, Vector<FlyString> const& list) const
{
for (auto const& element : m_elements.in_reverse()) {
if (element.local_name() == tag_name)
if (element->local_name() == tag_name)
return true;
if (list.contains_slow(element.local_name()))
if (list.contains_slow(element->local_name()))
return false;
}
VERIFY_NOT_REACHED();
@ -33,9 +33,9 @@ bool StackOfOpenElements::has_in_scope(FlyString const& tag_name) const
bool StackOfOpenElements::has_in_scope_impl(const DOM::Element& target_node, Vector<FlyString> const& list) const
{
for (auto& element : m_elements.in_reverse()) {
if (&element == &target_node)
if (element.ptr() == &target_node)
return true;
if (list.contains_slow(element.local_name()))
if (list.contains_slow(element->local_name()))
return false;
}
VERIFY_NOT_REACHED();
@ -78,11 +78,11 @@ bool StackOfOpenElements::has_in_select_scope(FlyString const& tag_name) const
// 1. Initialize node to be the current node (the bottommost node of the stack).
for (auto& node : m_elements.in_reverse()) {
// 2. If node is the target node, terminate in a match state.
if (node.local_name() == tag_name)
if (node->local_name() == tag_name)
return true;
// 3. Otherwise, if node is one of the element types in list, terminate in a failure state.
// NOTE: Here "list" refers to all elements except option and optgroup
if (node.local_name() != HTML::TagNames::option && node.local_name() != HTML::TagNames::optgroup)
if (node->local_name() != HTML::TagNames::option && node->local_name() != HTML::TagNames::optgroup)
return false;
// 4. Otherwise, set node to the previous entry in the stack of open elements and return to step 2.
}
@ -94,7 +94,7 @@ bool StackOfOpenElements::has_in_select_scope(FlyString const& tag_name) const
bool StackOfOpenElements::contains(const DOM::Element& element) const
{
for (auto& element_on_stack : m_elements) {
if (&element == &element_on_stack)
if (&element == element_on_stack.ptr())
return true;
}
return false;
@ -103,7 +103,7 @@ bool StackOfOpenElements::contains(const DOM::Element& element) const
bool StackOfOpenElements::contains(FlyString const& tag_name) const
{
for (auto& element_on_stack : m_elements) {
if (element_on_stack.local_name() == tag_name)
if (element_on_stack->local_name() == tag_name)
return true;
}
return false;
@ -111,68 +111,68 @@ bool StackOfOpenElements::contains(FlyString const& tag_name) const
void StackOfOpenElements::pop_until_an_element_with_tag_name_has_been_popped(FlyString const& tag_name)
{
while (m_elements.last().local_name() != tag_name)
while (m_elements.last()->local_name() != tag_name)
(void)pop();
(void)pop();
}
DOM::Element* StackOfOpenElements::topmost_special_node_below(const DOM::Element& formatting_element)
JS::GCPtr<DOM::Element> StackOfOpenElements::topmost_special_node_below(DOM::Element const& formatting_element)
{
DOM::Element* found_element = nullptr;
JS::GCPtr<DOM::Element> found_element = nullptr;
for (auto& element : m_elements.in_reverse()) {
if (&element == &formatting_element)
if (element.ptr() == &formatting_element)
break;
if (HTMLParser::is_special_tag(element.local_name(), element.namespace_()))
found_element = &element;
if (HTMLParser::is_special_tag(element->local_name(), element->namespace_()))
found_element = element.ptr();
}
return found_element;
return found_element.ptr();
}
StackOfOpenElements::LastElementResult StackOfOpenElements::last_element_with_tag_name(FlyString const& tag_name)
{
for (ssize_t i = m_elements.size() - 1; i >= 0; --i) {
auto& element = m_elements[i];
if (element.local_name() == tag_name)
return { &element, i };
if (element->local_name() == tag_name)
return { element.ptr(), i };
}
return { nullptr, -1 };
}
DOM::Element* StackOfOpenElements::element_immediately_above(DOM::Element const& target)
JS::GCPtr<DOM::Element> StackOfOpenElements::element_immediately_above(DOM::Element const& target)
{
bool found_target = false;
for (auto& element : m_elements.in_reverse()) {
if (&element == &target) {
if (element.ptr() == &target) {
found_target = true;
} else if (found_target)
return &element;
return element.ptr();
}
return nullptr;
}
void StackOfOpenElements::remove(const DOM::Element& element)
void StackOfOpenElements::remove(DOM::Element const& element)
{
m_elements.remove_first_matching([&element](DOM::Element const& other) {
return &other == &element;
m_elements.remove_first_matching([&element](auto& other) {
return other.ptr() == &element;
});
}
void StackOfOpenElements::replace(const DOM::Element& to_remove, NonnullRefPtr<DOM::Element> to_add)
void StackOfOpenElements::replace(DOM::Element const& to_remove, JS::NonnullGCPtr<DOM::Element> to_add)
{
for (size_t i = 0; i < m_elements.size(); i++) {
if (&m_elements[i] == &to_remove) {
if (m_elements[i].ptr() == &to_remove) {
m_elements.remove(i);
m_elements.insert(i, move(to_add));
m_elements.insert(i, JS::make_handle(*to_add));
break;
}
}
}
void StackOfOpenElements::insert_immediately_below(NonnullRefPtr<DOM::Element> element_to_add, DOM::Element const& target)
void StackOfOpenElements::insert_immediately_below(JS::NonnullGCPtr<DOM::Element> element_to_add, DOM::Element const& target)
{
for (size_t i = 0; i < m_elements.size(); i++) {
if (&m_elements[i] == &target) {
m_elements.insert(i + 1, move(element_to_add));
if (m_elements[i].ptr() == &target) {
m_elements.insert(i + 1, JS::make_handle(*element_to_add));
break;
}
}