Skip to content

Commit

Permalink
Cherry-pick ff897ca. rdar://123733686
Browse files Browse the repository at this point in the history
    Extract a portion of NodeIteratorBase::acceptNode which checks bit flags into its own function
    https://bugs.webkit.org/show_bug.cgi?id=270210
    <rdar://problem/123733686>

    Reviewed by Chris Dumez.

    Extracted matchesWhatToShow out of acceptNode and deployed in TreeWalker::nextNode and
    TreeWalker::previousNode.

    * Source/WebCore/dom/Traversal.cpp:
    (WebCore::NodeIteratorBase::acceptNodeSlowCase):
    * Source/WebCore/dom/Traversal.h:
    (WebCore::NodeIteratorBase::acceptNode):
    (WebCore::NodeIteratorBase::matchesWhatToShow):
    * Source/WebCore/dom/TreeWalker.cpp:
    (WebCore::TreeWalker::previousNode):
    (WebCore::TreeWalker::nextNode):

    Canonical link: https://commits.webkit.org/275468@main

Canonical link: https://commits.webkit.org/272448.862@safari-7618-branch
  • Loading branch information
rniwa authored and Dan Robson committed Apr 3, 2024
1 parent cf7ab1a commit 131221a
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 11 deletions.
10 changes: 3 additions & 7 deletions Source/WebCore/dom/Traversal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,15 @@ NodeIteratorBase::NodeIteratorBase(Node& rootNode, unsigned whatToShow, RefPtr<N
}

// https://dom.spec.whatwg.org/#concept-node-filter
ExceptionOr<unsigned short> NodeIteratorBase::acceptNode(Node& node)
ExceptionOr<unsigned short> NodeIteratorBase::acceptNodeSlowCase(Node& node)
{
ASSERT(m_filter);
if (m_isActive)
return Exception { ExceptionCode::InvalidStateError, "Recursive filters are not allowed"_s };

// The bit twiddling here is done to map DOM node types, which are given as integers from
// 1 through 14, to whatToShow bit masks.
if (!(((1 << (node.nodeType() - 1)) & m_whatToShow)))
if (!matchesWhatToShow(node))
return NodeFilter::FILTER_SKIP;

if (!m_filter)
return NodeFilter::FILTER_ACCEPT;

SetForScope isActive(m_isActive, true);
auto callbackResult = m_filter->acceptNode(node);
if (callbackResult.type() == CallbackResultType::ExceptionThrown)
Expand Down
21 changes: 17 additions & 4 deletions Source/WebCore/dom/Traversal.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@
#pragma once

#include "ExceptionOr.h"
#include "Node.h"
#include "NodeFilter.h"
#include <wtf/RefPtr.h>

namespace WebCore {

class Node;
class NodeFilter;

class NodeIteratorBase {
public:
Node& root() { return m_root.get(); }
Expand All @@ -43,9 +42,23 @@ class NodeIteratorBase {

protected:
NodeIteratorBase(Node&, unsigned whatToShow, RefPtr<NodeFilter>&&);
ExceptionOr<unsigned short> acceptNode(Node&);
ExceptionOr<unsigned short> acceptNode(Node& node)
{
// https://dom.spec.whatwg.org/#concept-node-filter
if (!m_filter)
return matchesWhatToShow(node) ? NodeFilter::FILTER_ACCEPT : NodeFilter::FILTER_SKIP;
return acceptNodeSlowCase(node);
}

bool matchesWhatToShow(const Node& node) const
{
unsigned nodeMask = 1 << (node.nodeType() - 1);
return nodeMask & m_whatToShow;
}

private:
ExceptionOr<unsigned short> acceptNodeSlowCase(Node&);

Ref<Node> m_root;
RefPtr<NodeFilter> m_filter;
unsigned m_whatToShow;
Expand Down
18 changes: 18 additions & 0 deletions Source/WebCore/dom/TreeWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ ExceptionOr<Node*> TreeWalker::nextSibling()

ExceptionOr<Node*> TreeWalker::previousNode()
{
if (!filter()) {
if (m_current.ptr() == &root())
return nullptr;
for (RefPtr node = NodeTraversal::previous(m_current); node; node = NodeTraversal::previous(*node)) {
if (matchesWhatToShow(*node))
return setCurrent(node.releaseNonNull());
if (node == &root())
break;
}
return nullptr;
}
RefPtr node = m_current.ptr();
while (node != &root()) {
while (RefPtr previousSibling = node->previousSibling()) {
Expand Down Expand Up @@ -230,6 +241,13 @@ ExceptionOr<Node*> TreeWalker::previousNode()

ExceptionOr<Node*> TreeWalker::nextNode()
{
if (!filter()) {
for (RefPtr node = NodeTraversal::next(m_current, &root()); node; node = NodeTraversal::next(*node, &root())) {
if (matchesWhatToShow(*node))
return setCurrent(node.releaseNonNull());
}
return nullptr;
}
RefPtr node = m_current.ptr();
Children:
while (RefPtr firstChild = node->firstChild()) {
Expand Down

0 comments on commit 131221a

Please sign in to comment.