mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-10 18:10:56 +09:00
LibWeb: Traverse shadow-including subtree when adopting DOM nodes
This takes care of two FIXMEs and fixes an issue on Google Docs where we'd mix boxes from different documents in the same layout tree. (This happened because shadow trees remained attached to their old document when their host was adopted.)
This commit is contained in:
parent
7d7d5f0b1b
commit
3ee5bdcfb7
Notes:
sideshowbarker
2024-07-17 09:26:19 +09:00
Author: https://github.com/awesomekling
Commit: 3ee5bdcfb7
3 changed files with 24 additions and 4 deletions
|
@ -1116,8 +1116,7 @@ void Document::adopt_node(Node& node)
|
|||
node.remove();
|
||||
|
||||
if (&old_document != this) {
|
||||
// FIXME: This should be shadow-including.
|
||||
node.for_each_in_inclusive_subtree([&](auto& inclusive_descendant) {
|
||||
node.for_each_shadow_including_descendant([&](auto& inclusive_descendant) {
|
||||
inclusive_descendant.set_document({}, *this);
|
||||
// FIXME: If inclusiveDescendant is an element, then set the node document of each attribute in inclusiveDescendant’s attribute list to document.
|
||||
return IterationDecision::Continue;
|
||||
|
@ -1127,8 +1126,7 @@ void Document::adopt_node(Node& node)
|
|||
// enqueue a custom element callback reaction with inclusiveDescendant, callback name "adoptedCallback",
|
||||
// and an argument list containing oldDocument and document.
|
||||
|
||||
// FIXME: This should be shadow-including.
|
||||
node.for_each_in_inclusive_subtree([&](auto& inclusive_descendant) {
|
||||
node.for_each_shadow_including_descendant([&](auto& inclusive_descendant) {
|
||||
inclusive_descendant.adopted_from(old_document);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
|
|
@ -231,6 +231,10 @@ public:
|
|||
|
||||
void queue_mutation_record(FlyString const& type, String attribute_name, String attribute_namespace, String old_value, NonnullRefPtr<NodeList> added_nodes, NonnullRefPtr<NodeList> removed_nodes, Node* previous_sibling, Node* next_sibling);
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-shadow-including-descendant
|
||||
template<typename Callback>
|
||||
IterationDecision for_each_shadow_including_descendant(Callback);
|
||||
|
||||
protected:
|
||||
Node(Document&, NodeType);
|
||||
|
||||
|
|
|
@ -45,4 +45,22 @@ private:
|
|||
template<>
|
||||
inline bool Node::fast_is<ShadowRoot>() const { return is_shadow_root(); }
|
||||
|
||||
template<typename Callback>
|
||||
inline IterationDecision Node::for_each_shadow_including_descendant(Callback callback)
|
||||
{
|
||||
if (callback(*this) == IterationDecision::Break)
|
||||
return IterationDecision::Break;
|
||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||
if (child->is_element()) {
|
||||
if (RefPtr<ShadowRoot> shadow_root = static_cast<Element*>(child)->shadow_root()) {
|
||||
if (shadow_root->for_each_shadow_including_descendant(callback) == IterationDecision::Break)
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
}
|
||||
if (child->for_each_shadow_including_descendant(callback) == IterationDecision::Break)
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue