Skip to content

Commit

Permalink
Use dynamicDowncast<T> even more in the DOM
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=264792

Reviewed by Darin Adler.

Use dynamicDowncast<T> even more in the DOM instead of is<T>() + downcast<T>().
It is less error-prone and often results in more concise code. I am also hoping
to have downcast<>() do a type check on release builds in the future. It is
currently too expensive to do so but it may become affordable if we use
dynamicDowncast<T>() instead when possible.

* Source/WebCore/dom/ElementTraversal.h:
(WebCore::Traversal<Element>::nextTemplate):
(WebCore::Traversal<ElementType>::firstChildTemplate):
(WebCore::Traversal<ElementType>::lastChildTemplate):
(WebCore::Traversal<ElementType>::firstWithinTemplate):
(WebCore::Traversal<ElementType>::lastWithinTemplate):
(WebCore::Traversal<ElementType>::nextTemplate):
(WebCore::Traversal<ElementType>::previous):
(WebCore::Traversal<ElementType>::nextSibling):
(WebCore::Traversal<ElementType>::previousSibling):
(WebCore::Traversal<ElementType>::nextSkippingChildren):
(WebCore::Traversal<ElementType>::inclusiveFirstWithin):
(WebCore::Traversal<ElementType>::inclusiveLastWithin):
(WebCore::ElementTraversal::previousIncludingPseudo):
(WebCore::ElementTraversal::nextIncludingPseudo):
(WebCore::ElementTraversal::nextIncludingPseudoSkippingChildren):
(WebCore::ElementTraversal::pseudoAwarePreviousSibling):
* Source/WebCore/dom/Event.cpp:
(WebCore::Event::setCurrentTarget):
(WebCore::Event::timeStampForBindings const):
* Source/WebCore/dom/EventContext.cpp:
(WebCore::EventContext::handleLocalEvents const):
(WebCore::EventContext::isUnreachableNode const):
* Source/WebCore/dom/EventNames.h:
(WebCore::EventNames::isTouchRelatedEventType const):
* Source/WebCore/dom/EventPath.cpp:
(WebCore::shouldEventCrossShadowBoundary):
(WebCore::nodeOrHostIfPseudoElement):
(WebCore::EventPath::EventPath):
(WebCore::EventPath::buildPath):
(WebCore::EventPath::retargetTouch):
* Source/WebCore/dom/EventPath.h:
(WebCore::EventPath::eventTargetRespectingTargetRules):
* Source/WebCore/dom/EventTarget.cpp:
(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::innerInvokeEventListeners):
(WebCore::EventTarget::invalidateEventListenerRegions):
* Source/WebCore/dom/FragmentDirectiveRangeFinder.cpp:
(WebCore::FragmentDirectiveRangeFinder::boundaryPointAtIndexInNodes):
(WebCore::FragmentDirectiveRangeFinder::isVisibleTextNode):
(WebCore::FragmentDirectiveRangeFinder::findRangeFromNodeList):
(WebCore::FragmentDirectiveRangeFinder::rangeOfStringInRange):
* Source/WebCore/dom/FullscreenManager.cpp:
(WebCore::markRendererDirtyAfterTopLayerChange):
(WebCore::FullscreenManager::dispatchFullscreenChangeOrErrorEvent):
* Source/WebCore/dom/ImageOverlay.cpp:
(WebCore::ImageOverlay::containerRect):
* Source/WebCore/dom/KeyboardEvent.cpp:
(WebCore::viewIsCompositing):
(WebCore::KeyboardEvent::charCode const):
* Source/WebCore/dom/MessagePort.cpp:
(WebCore::MessagePort::dispatchMessages):
(WebCore::MessagePort::dispatchEvent):
* Source/WebCore/dom/MouseEvent.cpp:
(WebCore::MouseEvent::canTriggerActivationBehavior):
* Source/WebCore/dom/MouseRelatedEvent.cpp:
(WebCore::MouseRelatedEvent::frameViewFromWindowProxy):

Canonical link: https://commits.webkit.org/270710@main
  • Loading branch information
cdumez committed Nov 14, 2023
1 parent 4334033 commit 7b68c9b
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 146 deletions.
178 changes: 98 additions & 80 deletions Source/WebCore/dom/ElementTraversal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,135 +97,149 @@ template <>
template <typename CurrentType>
inline Element* Traversal<Element>::nextTemplate(CurrentType& current)
{
Node* node = NodeTraversal::next(current);
while (node && !is<Element>(*node))
node = NodeTraversal::nextSkippingChildren(*node);
return downcast<Element>(node);
for (auto* node = NodeTraversal::next(current); node; node = NodeTraversal::nextSkippingChildren(*node)) {
if (auto* element = dynamicDowncast<Element>(*node))
return element;
}
return nullptr;
}

template <>
template <typename CurrentType>
inline Element* Traversal<Element>::nextTemplate(CurrentType& current, const Node* stayWithin)
{
Node* node = NodeTraversal::next(current, stayWithin);
while (node && !is<Element>(*node))
node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
return downcast<Element>(node);
for (auto* node = NodeTraversal::next(current, stayWithin); node; node = NodeTraversal::nextSkippingChildren(*node, stayWithin)) {
if (auto* element = dynamicDowncast<Element>(*node))
return element;
}
return nullptr;
}

// Generic versions.
template <typename ElementType>
template <typename CurrentType>
inline ElementType* Traversal<ElementType>::firstChildTemplate(CurrentType& current)
{
Node* node = current.firstChild();
while (node && !is<ElementType>(*node))
node = node->nextSibling();
return downcast<ElementType>(node);
for (auto* node = current.firstChild(); node; node = node->nextSibling()) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
template <typename CurrentType>
inline ElementType* Traversal<ElementType>::lastChildTemplate(CurrentType& current)
{
Node* node = current.lastChild();
while (node && !is<ElementType>(*node))
node = node->previousSibling();
return downcast<ElementType>(node);
for (auto* node = current.lastChild(); node; node = node->previousSibling()) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
template <typename CurrentType>
inline ElementType* Traversal<ElementType>::firstWithinTemplate(CurrentType& current)
{
Node* node = current.firstChild();
while (node && !is<ElementType>(*node))
node = NodeTraversal::next(*node, &current);
return downcast<ElementType>(node);
for (auto* node = current.firstChild(); node; node = NodeTraversal::next(*node, &current)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
template <typename CurrentType>
inline ElementType* Traversal<ElementType>::lastWithinTemplate(CurrentType& current)
{
Node* node = NodeTraversal::last(current);
while (node && !is<ElementType>(*node))
node = NodeTraversal::previous(*node, &current);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::last(current); node; node = NodeTraversal::previous(*node, &current)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
template <typename CurrentType>
inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType& current)
{
Node* node = NodeTraversal::next(current);
while (node && !is<ElementType>(*node))
node = NodeTraversal::next(*node);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::next(current); node; node = NodeTraversal::next(*node)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
template <typename CurrentType>
inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType& current, const Node* stayWithin)
{
Node* node = NodeTraversal::next(current, stayWithin);
while (node && !is<ElementType>(*node))
node = NodeTraversal::next(*node, stayWithin);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::next(current, stayWithin); node; node = NodeTraversal::next(*node, stayWithin)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::previous(const Node& current)
{
Node* node = NodeTraversal::previous(current);
while (node && !is<ElementType>(*node))
node = NodeTraversal::previous(*node);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::previous(current); node; node = NodeTraversal::previous(*node)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::previous(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::previous(current, stayWithin);
while (node && !is<ElementType>(*node))
node = NodeTraversal::previous(*node, stayWithin);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::previous(current, stayWithin); node; node = NodeTraversal::previous(*node, stayWithin)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::nextSibling(const Node& current)
{
Node* node = current.nextSibling();
while (node && !is<ElementType>(*node))
node = node->nextSibling();
return downcast<ElementType>(node);
for (auto* node = current.nextSibling(); node; node = node->nextSibling()) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::previousSibling(const Node& current)
{
Node* node = current.previousSibling();
while (node && !is<ElementType>(*node))
node = node->previousSibling();
return downcast<ElementType>(node);
for (auto* node = current.previousSibling(); node; node = node->previousSibling()) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& current)
{
Node* node = NodeTraversal::nextSkippingChildren(current);
while (node && !is<ElementType>(*node))
node = NodeTraversal::nextSkippingChildren(*node);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::nextSkippingChildren(current); node; node = NodeTraversal::nextSkippingChildren(*node)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
while (node && !is<ElementType>(*node))
node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
return downcast<ElementType>(node);
for (auto* node = NodeTraversal::nextSkippingChildren(current, stayWithin); node; node = NodeTraversal::nextSkippingChildren(*node, stayWithin)) {
if (auto* element = dynamicDowncast<ElementType>(*node))
return element;
}
return nullptr;
}

template <typename ElementType>
Expand All @@ -241,32 +255,32 @@ inline ElementType* Traversal<ElementType>::lastChild(const Node& current) { ret
template <typename ElementType>
inline ElementType* Traversal<ElementType>::inclusiveFirstWithin(ContainerNode& current)
{
if (is<ElementType>(current))
return &downcast<ElementType>(current);
if (auto* element = dynamicDowncast<ElementType>(current))
return element;
return firstWithin(current);
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::inclusiveFirstWithin(Node& current)
{
if (is<ElementType>(current))
return &downcast<ElementType>(current);
if (auto* element = dynamicDowncast<ElementType>(current))
return element;
return firstWithin(current);
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::inclusiveLastWithin(ContainerNode& current)
{
if (is<ElementType>(current))
return &downcast<ElementType>(current);
if (auto* element = dynamicDowncast<ElementType>(current))
return element;
return lastWithin(current);
}

template <typename ElementType>
inline ElementType* Traversal<ElementType>::inclusiveLastWithin(Node& current)
{
if (is<ElementType>(current))
return &downcast<ElementType>(current);
if (auto* element = dynamicDowncast<ElementType>(current))
return element;
return lastWithin(current);
}

Expand All @@ -292,34 +306,38 @@ inline ElementType* Traversal<ElementType>::next(const Node& current, const Node
// FIXME: These should go somewhere else.
inline Element* ElementTraversal::previousIncludingPseudo(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
while (node && !is<Element>(*node))
node = NodeTraversal::previousIncludingPseudo(*node, stayWithin);
return downcast<Element>(node);
for (auto* node = NodeTraversal::previousIncludingPseudo(current, stayWithin); node; node = NodeTraversal::previousIncludingPseudo(*node, stayWithin)) {
if (auto* element = dynamicDowncast<Element>(*node))
return element;
}
return nullptr;
}

inline Element* ElementTraversal::nextIncludingPseudo(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
while (node && !is<Element>(*node))
node = NodeTraversal::nextIncludingPseudo(*node, stayWithin);
return downcast<Element>(node);
for (auto* node = NodeTraversal::nextIncludingPseudo(current, stayWithin); node; node = NodeTraversal::nextIncludingPseudo(*node, stayWithin)) {
if (auto* element = dynamicDowncast<Element>(*node))
return element;
}
return nullptr;
}

inline Element* ElementTraversal::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
{
Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
while (node && !is<Element>(*node))
node = NodeTraversal::nextIncludingPseudoSkippingChildren(*node, stayWithin);
return downcast<Element>(node);
for (auto* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin); node; node = NodeTraversal::nextIncludingPseudoSkippingChildren(*node, stayWithin)) {
if (auto* element = dynamicDowncast<Element>(*node))
return element;
}
return nullptr;
}

inline Element* ElementTraversal::pseudoAwarePreviousSibling(const Node& current)
{
Node* node = current.pseudoAwarePreviousSibling();
while (node && !is<Element>(*node))
node = node->pseudoAwarePreviousSibling();
return downcast<Element>(node);
for (auto* node = current.pseudoAwarePreviousSibling(); node; node = node->pseudoAwarePreviousSibling()) {
if (auto* element = dynamicDowncast<Element>(*node))
return element;
}
return nullptr;
}

} // namespace WebCore
11 changes: 8 additions & 3 deletions Source/WebCore/dom/Event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,12 @@ RefPtr<EventTarget> Event::protectedCurrentTarget() const
void Event::setCurrentTarget(RefPtr<EventTarget>&& currentTarget, std::optional<bool> isInShadowTree)
{
m_currentTarget = WTFMove(currentTarget);
m_currentTargetIsInShadowTree = isInShadowTree ? *isInShadowTree : (is<Node>(m_currentTarget) && downcast<Node>(*m_currentTarget).isInShadowTree());
if (isInShadowTree)
m_currentTargetIsInShadowTree = *isInShadowTree;
else {
auto* targetNode = dynamicDowncast<Node>(m_currentTarget.get());
m_currentTargetIsInShadowTree = targetNode && targetNode->isInShadowTree();
}
}

void Event::setEventPath(const EventPath& path)
Expand Down Expand Up @@ -168,8 +173,8 @@ void Event::setUnderlyingEvent(Event* underlyingEvent)
DOMHighResTimeStamp Event::timeStampForBindings(ScriptExecutionContext& context) const
{
RefPtr<Performance> performance;
if (is<WorkerGlobalScope>(context))
performance = &downcast<WorkerGlobalScope>(context).performance();
if (auto* globalScope = dynamicDowncast<WorkerGlobalScope>(context))
performance = &globalScope->performance();
else if (RefPtr window = downcast<Document>(context).domWindow())
performance = &window->performance();

Expand Down
10 changes: 7 additions & 3 deletions Source/WebCore/dom/EventContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,11 @@ void EventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const
if (!m_node->hasEventTargetData())
return;

if (event.isTrusted() && is<Element>(m_node) && downcast<Element>(*m_node).isDisabledFormControl() && event.isMouseEvent() && !event.isWheelEvent() && !m_node->document().settings().sendMouseEventsToDisabledFormControlsEnabled())
return;
if (event.isTrusted()) {
auto* element = dynamicDowncast<Element>(m_node.get());
if (element && element->isDisabledFormControl() && event.isMouseEvent() && !event.isWheelEvent() && !m_node->document().settings().sendMouseEventsToDisabledFormControlsEnabled())
return;
}

protectedNode()->fireEventListeners(event, phase);
}
Expand All @@ -112,7 +115,8 @@ void EventContext::initializeTouchLists()
bool EventContext::isUnreachableNode(EventTarget* target) const
{
// FIXME: Checks also for SVG elements.
return is<Node>(target) && !downcast<Node>(*target).isSVGElement() && m_node && m_node->isClosedShadowHidden(downcast<Node>(*target));
auto* node = dynamicDowncast<Node>(target);
return node && !node->isSVGElement() && m_node && m_node->isClosedShadowHidden(*node);
}

#endif
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/EventNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ inline bool EventNames::isTouchScrollBlockingEventType(const AtomString& eventTy
inline bool EventNames::isTouchRelatedEventType(const AtomString& eventType, const EventTarget& target) const
{
#if ENABLE(TOUCH_EVENTS)
if (is<Node>(target) && downcast<Node>(target).document().quirks().shouldDispatchSimulatedMouseEvents(&target)) {
if (auto* targetNode = dynamicDowncast<Node>(target); targetNode && targetNode->document().quirks().shouldDispatchSimulatedMouseEvents(&target)) {
if (eventType == mousedownEvent || eventType == mousemoveEvent || eventType == mouseupEvent)
return true;
}
Expand Down
Loading

0 comments on commit 7b68c9b

Please sign in to comment.