1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:07:45 +00:00

LibWeb: Make the node mutation algorithms more spec compliant

The mutation algorithms now more closely follow the spec and
fixes some assertion failures in tests such as Acid3 and Dromaeo.

The main thing that is missing right now is passing exceptions to the
bindings layer. This is because of issue #6075. I spent a while trying
to work it out and got so frustrated I just left it as a FIXME. Besides
that, the algorithms bail at the appropriate points.

This also makes the adopting steps in the document more spec compliant
as it's needed by the insertion algorithm. While I was at it, I added
the adoptNode IDL binding.

This adds a bunch of ancestor/descendant checks to TreeNode as well.
I moved the "remove_all_children" function to Node as it needs to use
the full remove algorithm instead of simply removing it from
the child list.
This commit is contained in:
Luke 2021-04-06 19:34:49 +01:00 committed by Andreas Kling
parent 5b5d7857e3
commit 5beacf08a2
8 changed files with 305 additions and 55 deletions

View file

@ -98,14 +98,15 @@ public:
}
bool is_ancestor_of(const TreeNode&) const;
bool is_inclusive_ancestor_of(const TreeNode&) const;
bool is_descendant_of(const TreeNode&) const;
bool is_inclusive_descendant_of(const TreeNode&) const;
void append_child(NonnullRefPtr<T> node);
void prepend_child(NonnullRefPtr<T> node);
void insert_before(NonnullRefPtr<T> node, RefPtr<T> child);
void remove_child(NonnullRefPtr<T> node);
void remove_all_children();
bool is_child_allowed(const T&) const { return true; }
T* next_in_pre_order()
@ -323,6 +324,12 @@ public:
return nullptr;
}
template<typename U>
bool has_child_of_type() const
{
return first_child_of_type<U>() != nullptr;
}
template<typename U>
const U* first_ancestor_of_type() const
{
@ -365,14 +372,6 @@ private:
T* m_previous_sibling { nullptr };
};
template<typename T>
inline void TreeNode<T>::remove_all_children()
{
while (RefPtr<T> child = first_child())
remove_child(child.release_nonnull());
}
template<typename T>
inline void TreeNode<T>::remove_child(NonnullRefPtr<T> node)
{
@ -470,4 +469,22 @@ inline bool TreeNode<T>::is_ancestor_of(const TreeNode<T>& other) const
return false;
}
template<typename T>
inline bool TreeNode<T>::is_inclusive_ancestor_of(const TreeNode<T>& other) const
{
return &other == this || is_ancestor_of(other);
}
template<typename T>
inline bool TreeNode<T>::is_descendant_of(const TreeNode<T>& other) const
{
return other.is_ancestor_of(*this);
}
template<typename T>
inline bool TreeNode<T>::is_inclusive_descendant_of(const TreeNode<T>& other) const
{
return other.is_inclusive_ancestor_of(*this);
}
}