mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-09 18:16:09 +03:00
LibWeb: Add preceding and following Node cases in tree constraints
This also does some east-const changes in TreeNode.
This commit is contained in:
parent
24ed8511dd
commit
1a28fc3cb5
Notes:
sideshowbarker
2024-07-18 04:29:49 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/1a28fc3cb5e Pull-request: https://github.com/SerenityOS/serenity/pull/9868 Reviewed-by: https://github.com/alimpfard
@ -242,14 +242,14 @@ ExceptionOr<void> Node::ensure_pre_insertion_validity(NonnullRefPtr<Node> node,
|
||||
if (is<DocumentFragment>(*node)) {
|
||||
auto node_element_child_count = verify_cast<DocumentFragment>(*node).child_element_count();
|
||||
if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
|
||||
|| (node_element_child_count == 1 && (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) /* FIXME: or child is non-null and a doctype is following child. */))) {
|
||||
|| (node_element_child_count == 1 && (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order<DocumentType>())))) {
|
||||
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
|
||||
}
|
||||
} else if (is<Element>(*node)) {
|
||||
if (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) /* FIXME: or child is non-null and a doctype is following child. */)
|
||||
if (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) || (child && child->has_following_node_of_type_in_tree_order<DocumentType>()))
|
||||
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
|
||||
} else if (is<DocumentType>(*node)) {
|
||||
if (has_child_of_type<DocumentType>() /* FIXME: or child is non-null and an element is preceding child */ || (!child && has_child_of_type<Element>()))
|
||||
if (has_child_of_type<DocumentType>() || (child && child->has_preceding_node_of_type_in_tree_order<Element>()) || (!child && has_child_of_type<Element>()))
|
||||
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
|
||||
}
|
||||
}
|
||||
@ -424,14 +424,14 @@ ExceptionOr<NonnullRefPtr<Node>> Node::replace_child(NonnullRefPtr<Node> node, N
|
||||
if (is<DocumentFragment>(*node)) {
|
||||
auto node_element_child_count = verify_cast<DocumentFragment>(*node).child_element_count();
|
||||
if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
|
||||
|| (node_element_child_count == 1 && (first_child_of_type<Element>() != child /* FIXME: or a doctype is following child. */))) {
|
||||
|| (node_element_child_count == 1 && (first_child_of_type<Element>() != child || child->has_following_node_of_type_in_tree_order<DocumentType>()))) {
|
||||
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
|
||||
}
|
||||
} else if (is<Element>(*node)) {
|
||||
if (first_child_of_type<Element>() != child /* FIXME: or a doctype is following child. */)
|
||||
if (first_child_of_type<Element>() != child || child->has_following_node_of_type_in_tree_order<DocumentType>())
|
||||
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
|
||||
} else if (is<DocumentType>(*node)) {
|
||||
if (first_child_of_type<DocumentType>() != node /* FIXME: or an element is preceding child */)
|
||||
if (first_child_of_type<DocumentType>() != node || child->has_preceding_node_of_type_in_tree_order<Element>())
|
||||
return DOM::HierarchyRequestError::create("Invalid node type for insertion");
|
||||
}
|
||||
}
|
||||
|
@ -137,12 +137,29 @@ public:
|
||||
return node;
|
||||
}
|
||||
|
||||
const T* next_in_pre_order() const
|
||||
T const* next_in_pre_order() const
|
||||
{
|
||||
return const_cast<TreeNode*>(this)->next_in_pre_order();
|
||||
}
|
||||
|
||||
bool is_before(const T& other) const
|
||||
T* previous_in_pre_order()
|
||||
{
|
||||
if (auto* node = previous_sibling()) {
|
||||
while (node->last_child())
|
||||
node = node->last_child();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
return parent();
|
||||
}
|
||||
|
||||
T const* previous_in_pre_order() const
|
||||
{
|
||||
return const_cast<TreeNode*>(this)->previous_in_pre_order();
|
||||
}
|
||||
|
||||
bool is_before(T const& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return false;
|
||||
@ -153,6 +170,28 @@ public:
|
||||
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>
|
||||
IterationDecision for_each_in_inclusive_subtree(Callback callback) const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user