Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1440)

Unified Diff: third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp

Issue 2131103002: Ensure that TextIterator::m_pastEndNode is not skipped in advance() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: revise unit test Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index f63021a50688d8c38cb7537f8c15af8de6dbd598..c636b95df1b0f1364138f051ef8b7373683d0cbc 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -82,18 +82,32 @@ TextIteratorBehaviorFlags adjustBehaviorFlags<EditingInFlatTreeStrategy>(TextIte
return flags & ~(TextIteratorEntersOpenShadowRoots | TextIteratorEntersTextControls);
}
+// Checks if |advance()| skips the descendants of |node|, which is the case if
+// |node| is neither a shadow root nor the owner of a layout object.
+static bool notSkipping(const Node& node)
+{
+ return node.layoutObject() || (node.isShadowRoot() && node.shadowHost()->layoutObject());
+}
+
// This function is like Range::pastLastNode, except for the fact that it can
-// climb up out of shadow trees.
+// climb up out of shadow trees and ignores all nodes that will be skipped in
+// |advance()|.
template <typename Strategy>
Node* pastLastNode(const Node& rangeEndContainer, int rangeEndOffset)
{
- if (rangeEndOffset >= 0 && !rangeEndContainer.offsetInCharacters()) {
- if (Node* next = Strategy::childAt(rangeEndContainer, rangeEndOffset))
- return next;
+ if (rangeEndOffset >= 0 && !rangeEndContainer.offsetInCharacters() && notSkipping(rangeEndContainer)) {
+ for (Node* next = Strategy::childAt(rangeEndContainer, rangeEndOffset); next; next = Strategy::nextSibling(*next)) {
+ if (notSkipping(*next))
+ return next;
+ }
}
- for (const Node* node = &rangeEndContainer; node; node = parentCrossingShadowBoundaries<Strategy>(*node)) {
- if (Node* next = Strategy::nextSibling(*node))
- return next;
+ for (const Node* node = &rangeEndContainer; node; ) {
+ const Node* parent = parentCrossingShadowBoundaries<Strategy>(*node);
+ if (parent && notSkipping(*parent)) {
+ if (Node* next = Strategy::nextSibling(*node))
+ return next;
+ }
+ node = parent;
}
return nullptr;
}
@@ -170,6 +184,7 @@ void TextIteratorAlgorithm<Strategy>::initialize(Node* startContainer, int start
m_startOffset = startOffset;
m_endContainer = endContainer;
m_endOffset = endOffset;
+ m_endNode = endContainer && !endContainer->offsetInCharacters() && endOffset > 0 ? Strategy::childAt(*endContainer, endOffset - 1) : nullptr;
m_shadowDepth = shadowDepthOf<Strategy>(*startContainer, *endContainer);
@@ -352,10 +367,9 @@ void TextIteratorAlgorithm<Strategy>::advance()
next = Strategy::nextSibling(*m_node);
if (!next) {
// 3. If we are at the last child, go up the node tree until we find a next sibling.
- bool pastEnd = Strategy::next(*m_node) == m_pastEndNode;
ContainerNode* parentNode = Strategy::parent(*m_node);
while (!next && parentNode) {
- if ((pastEnd && parentNode == m_endContainer) || Strategy::isDescendantOf(*m_endContainer, *parentNode))
+ if (m_node == m_endNode || Strategy::isDescendantOf(*m_endContainer, *parentNode))
return;
bool haveLayoutObject = m_node->layoutObject();
m_node = parentNode;

Powered by Google App Engine
This is Rietveld 408576698