mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibWeb: Actually traverse the shadow root of the inclusive descendant
Previously, the inclusive descendant, which is the node that for_each_shadow_including_inclusive_descendant was called on, would not have it's shadow root traversed if it had one. This is because the shadow root traversal was in the `for` loop, which begins with the node's first child. The fix here is to move the shadow root traversal outside of the loop, and check if the current node is an element instead.
This commit is contained in:
parent
d3c21e4038
commit
6df4e5f5e7
Notes:
github-actions[bot]
2024-11-13 13:41:02 +00:00
Author: https://github.com/Lubrsi Commit: https://github.com/LadybirdBrowser/ladybird/commit/6df4e5f5e75 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2310
3 changed files with 37 additions and 12 deletions
|
@ -97,21 +97,37 @@ private:
|
|||
template<>
|
||||
inline bool Node::fast_is<ShadowRoot>() const { return node_type() == to_underlying(NodeType::DOCUMENT_FRAGMENT_NODE) && is_shadow_root(); }
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
|
||||
// In shadow-including tree order is shadow-including preorder, depth-first traversal of a node tree.
|
||||
// Shadow-including preorder, depth-first traversal of a node tree tree is preorder, depth-first traversal
|
||||
// of tree, with for each shadow host encountered in tree, shadow-including preorder, depth-first traversal
|
||||
// of that element’s shadow root’s node tree just after it is encountered.
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-shadow-including-descendant
|
||||
// An object A is a shadow-including descendant of an object B, if A is a descendant of B, or A’s root is a
|
||||
// shadow root and A’s root’s host is a shadow-including inclusive descendant of B.
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant
|
||||
// A shadow-including inclusive descendant is an object or one of its shadow-including descendants.
|
||||
|
||||
template<typename Callback>
|
||||
inline TraversalDecision Node::for_each_shadow_including_inclusive_descendant(Callback callback)
|
||||
{
|
||||
if (callback(*this) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||
if (child->is_element()) {
|
||||
if (auto shadow_root = static_cast<Element*>(child)->shadow_root()) {
|
||||
if (shadow_root->for_each_shadow_including_inclusive_descendant(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
|
||||
if (is_element()) {
|
||||
if (auto shadow_root = static_cast<Element*>(this)->shadow_root()) {
|
||||
if (shadow_root->for_each_shadow_including_inclusive_descendant(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||
if (child->for_each_shadow_including_inclusive_descendant(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
|
||||
return TraversalDecision::Continue;
|
||||
}
|
||||
|
||||
|
@ -119,12 +135,6 @@ template<typename Callback>
|
|||
inline TraversalDecision Node::for_each_shadow_including_descendant(Callback callback)
|
||||
{
|
||||
for (auto* child = first_child(); child; child = child->next_sibling()) {
|
||||
if (child->is_element()) {
|
||||
if (JS::GCPtr<ShadowRoot> shadow_root = static_cast<Element*>(child)->shadow_root()) {
|
||||
if (shadow_root->for_each_shadow_including_inclusive_descendant(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
}
|
||||
if (child->for_each_shadow_including_inclusive_descendant(callback) == TraversalDecision::Break)
|
||||
return TraversalDecision::Break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Hello from script in the shadow root of the just inserted div!
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const div = document.createElement("div");
|
||||
const shadowRoot = div.attachShadow({ mode: "closed" });
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.innerText = "println('Hello from script in the shadow root of the just inserted div!')";
|
||||
shadowRoot.appendChild(script);
|
||||
|
||||
document.body.appendChild(div);
|
||||
});
|
||||
</script>
|
Loading…
Reference in a new issue