mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-11 18:20:43 +09:00
LibWeb: Implement "NodeIterator pre-removing steps"
These steps run when a node is about to be removed from its parent, and adjust the position of any live NodeIterators so that they don't point at a now-removed node. Note that while this commit implements what's in the DOM specification, the specification doesn't fully match what other browsers do. Spec bug: https://github.com/whatwg/dom/issues/907
This commit is contained in:
parent
acbdb95b0a
commit
9c6999ecf2
Notes:
sideshowbarker
2024-07-17 17:40:10 +09:00
Author: https://github.com/awesomekling
Commit: 9c6999ecf2
5 changed files with 91 additions and 2 deletions
|
@ -17,6 +17,12 @@ NodeIterator::NodeIterator(Node& root)
|
|||
: m_root(root)
|
||||
, m_reference(root)
|
||||
{
|
||||
root.document().register_node_iterator({}, *this);
|
||||
}
|
||||
|
||||
NodeIterator::~NodeIterator()
|
||||
{
|
||||
m_root->document().unregister_node_iterator({}, *this);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createnodeiterator
|
||||
|
@ -160,4 +166,44 @@ JS::ThrowCompletionOr<RefPtr<Node>> NodeIterator::previous_node()
|
|||
return traverse(Direction::Previous);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#nodeiterator-pre-removing-steps
|
||||
void NodeIterator::run_pre_removing_steps(Node& to_be_removed_node)
|
||||
{
|
||||
// NOTE: This function implements what the DOM specification tells us to do.
|
||||
// However, it's known to not match other browsers: https://github.com/whatwg/dom/issues/907
|
||||
|
||||
// 1. If toBeRemovedNode is not an inclusive ancestor of nodeIterator’s reference, or toBeRemovedNode is nodeIterator’s root, then return.
|
||||
if (!to_be_removed_node.is_inclusive_ancestor_of(m_reference) || &to_be_removed_node == m_root)
|
||||
return;
|
||||
|
||||
// 2. If nodeIterator’s pointer before reference is true, then:
|
||||
if (m_pointer_before_reference) {
|
||||
// 1. Let next be toBeRemovedNode’s first following node that is an inclusive descendant of nodeIterator’s root and is not an inclusive descendant of toBeRemovedNode, and null if there is no such node.
|
||||
RefPtr<Node> next = to_be_removed_node.next_in_pre_order(m_root);
|
||||
while (next && (!next->is_inclusive_descendant_of(m_root) || next->is_inclusive_descendant_of(to_be_removed_node)))
|
||||
next = next->next_in_pre_order(m_root);
|
||||
|
||||
// 2. If next is non-null, then set nodeIterator’s reference to next and return.
|
||||
if (next) {
|
||||
m_reference = *next;
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Otherwise, set nodeIterator’s pointer before reference to false.
|
||||
m_pointer_before_reference = false;
|
||||
}
|
||||
|
||||
// 3. Set nodeIterator’s reference to toBeRemovedNode’s parent, if toBeRemovedNode’s previous sibling is null,
|
||||
if (!to_be_removed_node.previous_sibling()) {
|
||||
VERIFY(to_be_removed_node.parent());
|
||||
m_reference = *to_be_removed_node.parent();
|
||||
} else {
|
||||
// ...and to the inclusive descendant of toBeRemovedNode’s previous sibling that appears last in tree order otherwise.
|
||||
auto* node = to_be_removed_node.previous_sibling();
|
||||
while (node->last_child())
|
||||
node = node->last_child();
|
||||
m_reference = *node;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue