Commit c8c02414 authored by yosin@chromium.org's avatar yosin@chromium.org

Introduce ComposedTreeTraversal::previousPostOrder()

This patch introduces |ComposedTreeTraversal::previousPostOrder()| which is
composed tree version of |NodeTraversal::previousPostOrder()| as a preparation
of implementing composed tree version of |startOfParagraph()|.

This patch is a preparation of making selection to handle granularity for web
component, http://crrev.com/1277863002

BUG=513568
TEST=n/a; no behavior changes

Review URL: https://codereview.chromium.org/1308063008

git-svn-id: svn://svn.chromium.org/blink/trunk@201965 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 4c1b6e1d
...@@ -191,6 +191,38 @@ Node* ComposedTreeTraversal::previousSkippingChildren(const Node& node) ...@@ -191,6 +191,38 @@ Node* ComposedTreeTraversal::previousSkippingChildren(const Node& node)
return traversePreviousAncestorSibling(node); return traversePreviousAncestorSibling(node);
} }
static Node* previousAncestorSiblingPostOrder(const Node& current, const Node* stayWithin)
{
ASSERT(!ComposedTreeTraversal::previousSibling(current));
for (Node* parent = ComposedTreeTraversal::parent(current); parent; parent = ComposedTreeTraversal::parent(*parent)) {
if (parent == stayWithin)
return nullptr;
if (Node* previousSibling = ComposedTreeTraversal::previousSibling(*parent))
return previousSibling;
}
return nullptr;
}
// TODO(yosin) We should consider introducing template class to share code
// between DOM tree traversal and composed tree tarversal.
Node* ComposedTreeTraversal::previousPostOrder(const Node& current, const Node* stayWithin)
{
assertPrecondition(current);
if (stayWithin)
assertPrecondition(*stayWithin);
if (Node* lastChild = traverseLastChild(current)) {
assertPostcondition(lastChild);
return lastChild;
}
if (current == stayWithin)
return nullptr;
if (Node* previousSibling = traversePreviousSibling(current)) {
assertPostcondition(previousSibling);
return previousSibling;
}
return previousAncestorSiblingPostOrder(current, stayWithin);
}
bool ComposedTreeTraversal::isDescendantOf(const Node& node, const Node& other) bool ComposedTreeTraversal::isDescendantOf(const Node& node, const Node& other)
{ {
assertPrecondition(node); assertPrecondition(node);
......
...@@ -82,6 +82,9 @@ public: ...@@ -82,6 +82,9 @@ public:
// similar to |previous()| but skipping child nodes of the specified node. // similar to |previous()| but skipping child nodes of the specified node.
static Node* previousSkippingChildren(const Node&); static Node* previousSkippingChildren(const Node&);
// Like previous, but visits parents before their children.
static Node* previousPostOrder(const Node&, const Node* stayWithin = nullptr);
// Composed tree version of |Node::isDescendantOf(other)|. This function // Composed tree version of |Node::isDescendantOf(other)|. This function
// returns true if |other| contains |node|, otherwise returns // returns true if |other| contains |node|, otherwise returns
// false. If |other| is |node|, this function returns false. // false. If |other| is |node|, this function returns false.
......
...@@ -324,4 +324,52 @@ TEST_F(ComposedTreeTraversalTest, lastWithin) ...@@ -324,4 +324,52 @@ TEST_F(ComposedTreeTraversalTest, lastWithin)
EXPECT_EQ(*m10->firstChild(), ComposedTreeTraversal::lastWithinOrSelf(*s12)); EXPECT_EQ(*m10->firstChild(), ComposedTreeTraversal::lastWithinOrSelf(*s12));
} }
TEST_F(ComposedTreeTraversalTest, previousPostOrder)
{
const char* mainHTML =
"<div id='m0'>m0</div>"
"<div id='m1'>"
"<span id='m10'>m10</span>"
"<span id='m11'>m11</span>"
"</div>"
"<div id='m2'>m2</div>";
const char* shadowHTML =
"<content select='#m11'></content>"
"<a id='s11'>s11</a>"
"<a id='s12'>"
"<b id='s120'>s120</b>"
"<content select='#m10'></content>"
"</a>";
setupSampleHTML(mainHTML, shadowHTML, 1);
RefPtrWillBeRawPtr<Element> body = document().body();
RefPtrWillBeRawPtr<Element> m0 = body->querySelector("#m0", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<Element> m1 = body->querySelector("#m1", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<Element> m2 = body->querySelector("#m2", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<Element> m10 = body->querySelector("#m10", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<Element> m11 = body->querySelector("#m11", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = m1->openShadowRoot();
RefPtrWillBeRawPtr<Element> s11 = shadowRoot->querySelector("#s11", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<Element> s12 = shadowRoot->querySelector("#s12", ASSERT_NO_EXCEPTION);
RefPtrWillBeRawPtr<Element> s120 = shadowRoot->querySelector("#s120", ASSERT_NO_EXCEPTION);
EXPECT_EQ(*m0->firstChild(), ComposedTreeTraversal::previousPostOrder(*m0));
EXPECT_EQ(*s12, ComposedTreeTraversal::previousPostOrder(*m1));
EXPECT_EQ(*m10->firstChild(), ComposedTreeTraversal::previousPostOrder(*m10));
EXPECT_EQ(*s120, ComposedTreeTraversal::previousPostOrder(*m10->firstChild()));
EXPECT_EQ(*s120, ComposedTreeTraversal::previousPostOrder(*m10->firstChild(), s12.get()));
EXPECT_EQ(*m11->firstChild(), ComposedTreeTraversal::previousPostOrder(*m11));
EXPECT_EQ(*m0, ComposedTreeTraversal::previousPostOrder(*m11->firstChild()));
EXPECT_EQ(nullptr, ComposedTreeTraversal::previousPostOrder(*m11->firstChild(), m11.get()));
EXPECT_EQ(*m2->firstChild(), ComposedTreeTraversal::previousPostOrder(*m2));
EXPECT_EQ(*s11->firstChild(), ComposedTreeTraversal::previousPostOrder(*s11));
EXPECT_EQ(*m10, ComposedTreeTraversal::previousPostOrder(*s12));
EXPECT_EQ(*s120->firstChild(), ComposedTreeTraversal::previousPostOrder(*s120));
EXPECT_EQ(*s11, ComposedTreeTraversal::previousPostOrder(*s120->firstChild()));
EXPECT_EQ(nullptr, ComposedTreeTraversal::previousPostOrder(*s120->firstChild(), s12.get()));
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment