1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:37:45 +00:00

LibWeb: Make Node::root return a reference

The root of a node can never be null, as "the root of an object is
itself, if its parent is null, or else it is the root of its parent."

https://dom.spec.whatwg.org/#concept-tree-root
This commit is contained in:
Luke Wilde 2021-09-02 19:27:42 +01:00 committed by Andreas Kling
parent 7f46022e66
commit f7f37eaa0f
5 changed files with 24 additions and 20 deletions

View file

@ -35,15 +35,15 @@ static EventTarget* retarget(EventTarget* left, EventTarget* right)
return left; return left;
auto* left_node = verify_cast<Node>(left); auto* left_node = verify_cast<Node>(left);
auto* left_root = left_node->root(); auto& left_root = left_node->root();
if (!is<ShadowRoot>(left_root)) if (!is<ShadowRoot>(left_root))
return left; return left;
if (is<Node>(right) && left_root->is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*right))) if (is<Node>(right) && left_root.is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*right)))
return left; return left;
auto* left_shadow_root = verify_cast<ShadowRoot>(left_root); auto& left_shadow_root = verify_cast<ShadowRoot>(left_root);
left = left_shadow_root->host(); left = left_shadow_root.host();
} }
} }

View file

@ -157,25 +157,28 @@ String Node::child_text_content() const
return builder.build(); return builder.build();
} }
Node* Node::root() // https://dom.spec.whatwg.org/#concept-tree-root
Node& Node::root()
{ {
Node* root = this; Node* root = this;
while (root->parent()) while (root->parent())
root = root->parent(); root = root->parent();
return root; return *root;
} }
Node* Node::shadow_including_root() // https://dom.spec.whatwg.org/#concept-shadow-including-root
Node& Node::shadow_including_root()
{ {
auto node_root = root(); auto& node_root = root();
if (is<ShadowRoot>(node_root)) if (is<ShadowRoot>(node_root))
return verify_cast<ShadowRoot>(node_root)->host()->shadow_including_root(); return verify_cast<ShadowRoot>(node_root).host()->shadow_including_root();
return node_root; return node_root;
} }
// https://dom.spec.whatwg.org/#connected
bool Node::is_connected() const bool Node::is_connected() const
{ {
return shadow_including_root() && shadow_including_root()->is_document(); return shadow_including_root().is_document();
} }
Element* Node::parent_element() Element* Node::parent_element()
@ -608,7 +611,7 @@ u16 Node::compare_document_position(RefPtr<Node> other)
// FIXME: Once LibWeb supports attribute nodes fix to follow the specification. // FIXME: Once LibWeb supports attribute nodes fix to follow the specification.
VERIFY(node1->type() != NodeType::ATTRIBUTE_NODE && node2->type() != NodeType::ATTRIBUTE_NODE); VERIFY(node1->type() != NodeType::ATTRIBUTE_NODE && node2->type() != NodeType::ATTRIBUTE_NODE);
if ((node1 == nullptr || node2 == nullptr) || (node1->root() != node2->root())) if ((node1 == nullptr || node2 == nullptr) || (&node1->root() != &node2->root()))
return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | (node1 > node2 ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING); return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | (node1 > node2 ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING);
if (node1->is_ancestor_of(*node2)) if (node1->is_ancestor_of(*node2))
@ -626,7 +629,7 @@ u16 Node::compare_document_position(RefPtr<Node> other)
// https://dom.spec.whatwg.org/#concept-tree-host-including-inclusive-ancestor // https://dom.spec.whatwg.org/#concept-tree-host-including-inclusive-ancestor
bool Node::is_host_including_inclusive_ancestor_of(const Node& other) const bool Node::is_host_including_inclusive_ancestor_of(const Node& other) const
{ {
return is_inclusive_ancestor_of(other) || (is<DocumentFragment>(other.root()) && verify_cast<DocumentFragment>(other.root())->host() && is_inclusive_ancestor_of(*verify_cast<DocumentFragment>(other.root())->host().ptr())); return is_inclusive_ancestor_of(other) || (is<DocumentFragment>(other.root()) && verify_cast<DocumentFragment>(other.root()).host() && is_inclusive_ancestor_of(*verify_cast<DocumentFragment>(other.root()).host().ptr()));
} }
// https://dom.spec.whatwg.org/#dom-node-ownerdocument // https://dom.spec.whatwg.org/#dom-node-ownerdocument
@ -691,10 +694,10 @@ bool Node::is_shadow_including_descendant_of(Node const& other) const
if (!is<ShadowRoot>(root())) if (!is<ShadowRoot>(root()))
return false; return false;
auto shadow_root = verify_cast<ShadowRoot>(root()); auto& shadow_root = verify_cast<ShadowRoot>(root());
// NOTE: While host is nullable because of inheriting from DocumentFragment, shadow roots always have a host. // NOTE: While host is nullable because of inheriting from DocumentFragment, shadow roots always have a host.
return shadow_root->host()->is_shadow_including_inclusive_descendant_of(other); return shadow_root.host()->is_shadow_including_inclusive_descendant_of(other);
} }
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant // https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant

View file

@ -113,14 +113,14 @@ public:
String child_text_content() const; String child_text_content() const;
Node* root(); Node& root();
const Node* root() const const Node& root() const
{ {
return const_cast<Node*>(this)->root(); return const_cast<Node*>(this)->root();
} }
Node* shadow_including_root(); Node& shadow_including_root();
const Node* shadow_including_root() const const Node& shadow_including_root() const
{ {
return const_cast<Node*>(this)->shadow_including_root(); return const_cast<Node*>(this)->shadow_including_root();
} }

View file

@ -16,11 +16,12 @@ ShadowRoot::ShadowRoot(Document& document, Element& host)
set_host(host); set_host(host);
} }
// https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6
EventTarget* ShadowRoot::get_parent(const Event& event) EventTarget* ShadowRoot::get_parent(const Event& event)
{ {
if (!event.composed()) { if (!event.composed()) {
auto& events_first_invocation_target = verify_cast<Node>(*event.path().first().invocation_target); auto& events_first_invocation_target = verify_cast<Node>(*event.path().first().invocation_target);
if (events_first_invocation_target.root() == this) if (&events_first_invocation_target.root() == this)
return nullptr; return nullptr;
} }

View file

@ -72,7 +72,7 @@ bool Node::establishes_stacking_context() const
{ {
if (!has_style()) if (!has_style())
return false; return false;
if (dom_node() == document().root()) if (dom_node() == &document().root())
return true; return true;
auto position = computed_values().position(); auto position = computed_values().position();
if (position == CSS::Position::Absolute || position == CSS::Position::Relative || position == CSS::Position::Fixed || position == CSS::Position::Sticky) if (position == CSS::Position::Absolute || position == CSS::Position::Relative || position == CSS::Position::Fixed || position == CSS::Position::Sticky)