mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-05 23:59:49 +00:00
LibWeb: Move non-DOM-related methods from DOM::Node to TreeNode
Motivated by wanting to do `is_before()` on a Layout::Node, and thought I might as well move as many as possible while I was at it.
This commit is contained in:
parent
5fad6b1938
commit
ea33bdc975
Notes:
github-actions[bot]
2025-06-07 14:51:50 +00:00
Author: https://github.com/AtkinsSJ
Commit: ea33bdc975
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5022
3 changed files with 154 additions and 156 deletions
|
@ -575,17 +575,6 @@ String Node::child_text_content() const
|
||||||
return MUST(builder.to_string());
|
return MUST(builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-tree-root
|
|
||||||
Node& Node::root()
|
|
||||||
{
|
|
||||||
// The root of an object is itself, if its parent is null, or else it is the root of its parent.
|
|
||||||
// The root of a tree is any object participating in that tree whose parent is null.
|
|
||||||
Node* root = this;
|
|
||||||
while (root->parent())
|
|
||||||
root = root->parent();
|
|
||||||
return *root;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-shadow-including-root
|
// https://dom.spec.whatwg.org/#concept-shadow-including-root
|
||||||
Node& Node::shadow_including_root()
|
Node& Node::shadow_including_root()
|
||||||
{
|
{
|
||||||
|
@ -1977,13 +1966,6 @@ bool Node::is_scripting_disabled() const
|
||||||
return !is_scripting_enabled();
|
return !is_scripting_enabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-node-contains
|
|
||||||
bool Node::contains(GC::Ptr<Node> other) const
|
|
||||||
{
|
|
||||||
// The contains(other) method steps are to return true if other is an inclusive descendant of this; otherwise false (including when other is null).
|
|
||||||
return other && other->is_inclusive_descendant_of(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-shadow-including-descendant
|
// https://dom.spec.whatwg.org/#concept-shadow-including-descendant
|
||||||
bool Node::is_shadow_including_descendant_of(Node const& other) const
|
bool Node::is_shadow_including_descendant_of(Node const& other) const
|
||||||
{
|
{
|
||||||
|
@ -2588,28 +2570,6 @@ void Node::remove_child_impl(GC::Ref<Node> node)
|
||||||
TreeNode::remove_child(node);
|
TreeNode::remove_child(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Node::is_descendant_of(Node const& other) const
|
|
||||||
{
|
|
||||||
return other.is_ancestor_of(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Node::is_inclusive_descendant_of(Node const& other) const
|
|
||||||
{
|
|
||||||
return other.is_inclusive_ancestor_of(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-tree-following
|
|
||||||
bool Node::is_following(Node const& other) const
|
|
||||||
{
|
|
||||||
// An object A is following an object B if A and B are in the same tree and A comes after B in tree order.
|
|
||||||
for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) {
|
|
||||||
if (node == &other)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Node::build_accessibility_tree(AccessibilityTreeNode& parent)
|
void Node::build_accessibility_tree(AccessibilityTreeNode& parent)
|
||||||
{
|
{
|
||||||
if (is_uninteresting_whitespace_node())
|
if (is_uninteresting_whitespace_node())
|
||||||
|
|
|
@ -280,12 +280,6 @@ public:
|
||||||
|
|
||||||
String child_text_content() const;
|
String child_text_content() const;
|
||||||
|
|
||||||
Node& root();
|
|
||||||
Node const& root() const
|
|
||||||
{
|
|
||||||
return const_cast<Node*>(this)->root();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node& shadow_including_root();
|
Node& shadow_including_root();
|
||||||
Node const& shadow_including_root() const
|
Node const& shadow_including_root() const
|
||||||
{
|
{
|
||||||
|
@ -376,8 +370,6 @@ public:
|
||||||
bool is_scripting_enabled() const;
|
bool is_scripting_enabled() const;
|
||||||
bool is_scripting_disabled() const;
|
bool is_scripting_disabled() const;
|
||||||
|
|
||||||
bool contains(GC::Ptr<Node>) const;
|
|
||||||
|
|
||||||
// Used for dumping the DOM Tree
|
// Used for dumping the DOM Tree
|
||||||
void serialize_tree_as_json(JsonObjectSerializer<StringBuilder>&) const;
|
void serialize_tree_as_json(JsonObjectSerializer<StringBuilder>&) const;
|
||||||
|
|
||||||
|
@ -424,98 +416,6 @@ public:
|
||||||
|
|
||||||
Slottable as_slottable();
|
Slottable as_slottable();
|
||||||
|
|
||||||
size_t child_count() const
|
|
||||||
{
|
|
||||||
size_t count = 0;
|
|
||||||
for (auto* child = first_child(); child; child = child->next_sibling())
|
|
||||||
++count;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* child_at_index(int index)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
|
||||||
if (count == index)
|
|
||||||
return child;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node const* child_at_index(int index) const
|
|
||||||
{
|
|
||||||
return const_cast<Node*>(this)->child_at_index(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_descendant_of(Node const&) const;
|
|
||||||
bool is_inclusive_descendant_of(Node const&) const;
|
|
||||||
|
|
||||||
bool is_following(Node const&) const;
|
|
||||||
|
|
||||||
bool is_before(Node const& other) const
|
|
||||||
{
|
|
||||||
if (this == &other)
|
|
||||||
return false;
|
|
||||||
for (auto* node = this; node; node = node->next_in_pre_order()) {
|
|
||||||
if (node == &other)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-tree-preceding (Object A is 'typename U' and Object B is 'this')
|
|
||||||
template<typename U>
|
|
||||||
bool has_preceding_node_of_type_in_tree_order() const
|
|
||||||
{
|
|
||||||
for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) {
|
|
||||||
if (is<U>(node))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-tree-following (Object A is 'typename U' and Object B is 'this')
|
|
||||||
template<typename U>
|
|
||||||
bool has_following_node_of_type_in_tree_order() const
|
|
||||||
{
|
|
||||||
for (auto* node = next_in_pre_order(); node; node = node->next_in_pre_order()) {
|
|
||||||
if (is<U>(node))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
void for_each_ancestor(Callback callback) const
|
|
||||||
{
|
|
||||||
return const_cast<Node*>(this)->for_each_ancestor(move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
void for_each_ancestor(Callback callback)
|
|
||||||
{
|
|
||||||
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
|
|
||||||
if (callback(*ancestor) == IterationDecision::Break)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
void for_each_inclusive_ancestor(Callback callback) const
|
|
||||||
{
|
|
||||||
return const_cast<Node*>(this)->for_each_inclusive_ancestor(move(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
void for_each_inclusive_ancestor(Callback callback)
|
|
||||||
{
|
|
||||||
for (auto* ancestor = this; ancestor; ancestor = ancestor->parent()) {
|
|
||||||
if (callback(*ancestor) == IterationDecision::Break)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U, typename Callback>
|
template<typename U, typename Callback>
|
||||||
WebIDL::ExceptionOr<void> for_each_child_of_type_fallible(Callback callback)
|
WebIDL::ExceptionOr<void> for_each_child_of_type_fallible(Callback callback)
|
||||||
{
|
{
|
||||||
|
@ -527,13 +427,6 @@ public:
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
bool has_child_of_type() const
|
|
||||||
{
|
|
||||||
return first_child_of_type<U>() != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
U const* shadow_including_first_ancestor_of_type() const
|
U const* shadow_including_first_ancestor_of_type() const
|
||||||
{
|
{
|
||||||
|
@ -543,15 +436,6 @@ public:
|
||||||
template<typename U>
|
template<typename U>
|
||||||
U* shadow_including_first_ancestor_of_type();
|
U* shadow_including_first_ancestor_of_type();
|
||||||
|
|
||||||
bool is_parent_of(Node const& other) const
|
|
||||||
{
|
|
||||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
|
||||||
if (&other == child)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<String> accessible_name(Document const&, ShouldComputeRole = ShouldComputeRole::Yes) const;
|
ErrorOr<String> accessible_name(Document const&, ShouldComputeRole = ShouldComputeRole::Yes) const;
|
||||||
ErrorOr<String> accessible_description(Document const&) const;
|
ErrorOr<String> accessible_description(Document const&) const;
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,57 @@ public:
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // https://dom.spec.whatwg.org/#concept-tree-root
|
||||||
|
T& root()
|
||||||
|
{
|
||||||
|
// The root of an object is itself, if its parent is null, or else it is the root of its parent.
|
||||||
|
// The root of a tree is any object participating in that tree whose parent is null.
|
||||||
|
T* root = static_cast<T*>(this);
|
||||||
|
while (root->parent())
|
||||||
|
root = root->parent();
|
||||||
|
return *root;
|
||||||
|
}
|
||||||
|
T const& root() const { return const_cast<TreeNode*>(this)->root(); }
|
||||||
|
|
||||||
bool is_ancestor_of(TreeNode const&) const;
|
bool is_ancestor_of(TreeNode const&) const;
|
||||||
bool is_inclusive_ancestor_of(TreeNode const&) const;
|
bool is_inclusive_ancestor_of(TreeNode const&) const;
|
||||||
|
bool contains(GC::Ptr<T>) const;
|
||||||
|
bool is_descendant_of(TreeNode const&) const;
|
||||||
|
bool is_inclusive_descendant_of(TreeNode const&) const;
|
||||||
|
|
||||||
|
bool is_following(TreeNode const&) const;
|
||||||
|
bool is_before(TreeNode const&) const;
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#concept-tree-preceding (Object A is 'typename U' and Object B is 'this')
|
||||||
|
template<typename U>
|
||||||
|
bool has_preceding_node_of_type_in_tree_order() const
|
||||||
|
{
|
||||||
|
for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) {
|
||||||
|
if (is<U>(node))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#concept-tree-following (Object A is 'typename U' and Object B is 'this')
|
||||||
|
template<typename U>
|
||||||
|
bool has_following_node_of_type_in_tree_order() const
|
||||||
|
{
|
||||||
|
for (auto* node = next_in_pre_order(); node; node = node->next_in_pre_order()) {
|
||||||
|
if (is<U>(node))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_parent_of(TreeNode const& other) const
|
||||||
|
{
|
||||||
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||||
|
if (&other == child)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void append_child(GC::Ref<T> node);
|
void append_child(GC::Ref<T> node);
|
||||||
void prepend_child(GC::Ref<T> node);
|
void prepend_child(GC::Ref<T> node);
|
||||||
|
@ -87,6 +136,30 @@ public:
|
||||||
m_parent->remove_child(*static_cast<T*>(this));
|
m_parent->remove_child(*static_cast<T*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t child_count() const
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto* child = first_child(); child; child = child->next_sibling())
|
||||||
|
++count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* child_at_index(int index)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||||
|
if (count == index)
|
||||||
|
return child;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T const* child_at_index(int index) const
|
||||||
|
{
|
||||||
|
return const_cast<TreeNode*>(this)->child_at_index(index);
|
||||||
|
}
|
||||||
|
|
||||||
T* next_in_pre_order()
|
T* next_in_pre_order()
|
||||||
{
|
{
|
||||||
if (first_child())
|
if (first_child())
|
||||||
|
@ -280,6 +353,12 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
bool has_child_of_type() const
|
||||||
|
{
|
||||||
|
return first_child_of_type<U>() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
U const* first_child_of_type() const
|
U const* first_child_of_type() const
|
||||||
{
|
{
|
||||||
|
@ -328,6 +407,36 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
void for_each_ancestor(Callback callback) const
|
||||||
|
{
|
||||||
|
return const_cast<TreeNode*>(this)->for_each_ancestor(move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
void for_each_ancestor(Callback callback)
|
||||||
|
{
|
||||||
|
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
|
||||||
|
if (callback(static_cast<T&>(*ancestor)) == IterationDecision::Break)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
void for_each_inclusive_ancestor(Callback callback) const
|
||||||
|
{
|
||||||
|
return const_cast<TreeNode*>(this)->for_each_inclusive_ancestor(move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
void for_each_inclusive_ancestor(Callback callback)
|
||||||
|
{
|
||||||
|
for (auto* ancestor = this; ancestor; ancestor = ancestor->parent()) {
|
||||||
|
if (callback(static_cast<T&>(*ancestor)) == IterationDecision::Break)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~TreeNode() = default;
|
~TreeNode() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -464,4 +573,49 @@ inline bool TreeNode<T>::is_inclusive_ancestor_of(TreeNode<T> const& other) cons
|
||||||
return &other == this || is_ancestor_of(other);
|
return &other == this || is_ancestor_of(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#dom-node-contains
|
||||||
|
template<typename T>
|
||||||
|
inline bool TreeNode<T>::contains(GC::Ptr<T> other) const
|
||||||
|
{
|
||||||
|
// The contains(other) method steps are to return true if other is an inclusive descendant of this; otherwise false (including when other is null).
|
||||||
|
return other && other->is_inclusive_descendant_of(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool TreeNode<T>::is_descendant_of(TreeNode<T> const& other) const
|
||||||
|
{
|
||||||
|
return other.is_ancestor_of(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool TreeNode<T>::is_inclusive_descendant_of(TreeNode<T> const& other) const
|
||||||
|
{
|
||||||
|
return other.is_inclusive_ancestor_of(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#concept-tree-following
|
||||||
|
template<typename T>
|
||||||
|
inline bool TreeNode<T>::is_following(TreeNode const& other) const
|
||||||
|
{
|
||||||
|
// An object A is following an object B if A and B are in the same tree and A comes after B in tree order.
|
||||||
|
for (auto* node = previous_in_pre_order(); node; node = node->previous_in_pre_order()) {
|
||||||
|
if (node == &other)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool TreeNode<T>::is_before(TreeNode const& other) const
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return false;
|
||||||
|
for (auto* node = this; node; node = node->next_in_pre_order()) {
|
||||||
|
if (node == &other)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue