Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / editing / TextIterator.cpp
index 84525be..1cc9a9d 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "Document.h"
 #include "ExceptionCodePlaceholder.h"
-#include "Font.h"
+#include "FontCascade.h"
 #include "Frame.h"
 #include "HTMLElement.h"
 #include "HTMLNames.h"
@@ -44,6 +44,8 @@
 #include "RenderTextControl.h"
 #include "RenderTextFragment.h"
 #include "ShadowRoot.h"
+#include "SimpleLineLayout.h"
+#include "SimpleLineLayoutResolver.h"
 #include "TextBoundaries.h"
 #include "TextBreakIterator.h"
 #include "TextControlInnerElements.h"
@@ -279,7 +281,7 @@ inline void TextIteratorCopyableText::reset()
 inline void TextIteratorCopyableText::set(String&& string)
 {
     m_singleCharacter = 0;
-    m_string = WTF::move(string);
+    m_string = WTFMove(string);
     m_offset = 0;
     m_length = m_string.length();
 }
@@ -291,7 +293,7 @@ inline void TextIteratorCopyableText::set(String&& string, unsigned offset, unsi
     ASSERT(length <= string.length() - offset);
 
     m_singleCharacter = 0;
-    m_string = WTF::move(string);
+    m_string = WTFMove(string);
     m_offset = offset;
     m_length = length;
 }
@@ -340,17 +342,14 @@ TextIterator::TextIterator(const Range* range, TextIteratorBehavior behavior)
 
     range->ownerDocument().updateLayoutIgnorePendingStylesheets();
 
-    m_startContainer = range->startContainer();
-    if (!m_startContainer)
-        return;
-    ASSERT(range->endContainer());
+    m_startContainer = &range->startContainer();
 
     // Callers should be handing us well-formed ranges. If we discover that this isn't
     // the case, we could consider changing this assertion to an early return.
     ASSERT(range->boundaryPointsValid());
 
     m_startOffset = range->startOffset();
-    m_endContainer = range->endContainer();
+    m_endContainer = &range->endContainer();
     m_endOffset = range->endOffset();
 
     // Set up the current node for processing.
@@ -449,7 +448,7 @@ void TextIterator::advance()
         if (!next) {
             next = m_node->nextSibling();
             if (!next) {
-                bool pastEnd = NodeTraversal::next(m_node) == m_pastEndNode;
+                bool pastEnd = NodeTraversal::next(*m_node) == m_pastEndNode;
                 Node* parentNode = m_node->parentOrShadowHostNode();
                 while (!next && parentNode) {
                     if ((pastEnd && parentNode == m_endContainer) || m_endContainer->isDescendantOf(parentNode))
@@ -499,6 +498,25 @@ static bool hasVisibleTextNode(RenderText& renderer)
     return false;
 }
 
+static unsigned textNodeOffsetInFlow(const Text& firstTextNodeInRange)
+{
+    // Calculate the text offset for simple lines.
+    RenderObject* renderer = firstTextNodeInRange.renderer();
+    if (!renderer)
+        return 0;
+    unsigned textOffset = 0;
+    for (renderer = renderer->previousSibling(); renderer; renderer = renderer->previousSibling()) {
+        if (is<RenderText>(renderer))
+            textOffset += downcast<RenderText>(renderer)->textLength();
+    }
+    return textOffset;
+}
+
+static bool isNewLineOrTabCharacter(UChar character)
+{
+    return character == '\n' || character == '\t';
+}
+
 bool TextIterator::handleTextNode()
 {
     Text& textNode = downcast<Text>(*m_node);
@@ -507,7 +525,6 @@ bool TextIterator::handleTextNode()
         return false;
 
     auto& renderer = *textNode.renderer();
-        
     m_lastTextNode = &textNode;
     String rendererText = renderer.text();
 
@@ -541,35 +558,81 @@ bool TextIterator::handleTextNode()
         return true;
     }
 
-    if (renderer.simpleLineLayout()) {
+    if (const auto* layout = renderer.simpleLineLayout()) {
         if (renderer.style().visibility() != VISIBLE && !(m_behavior & TextIteratorIgnoresStyleVisibility))
             return true;
-        // This code aims to produce same results as handleTextBox() below so test results don't change. It does not make much logical sense.
-        unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : rendererText.length();
-        unsigned runEnd = m_offset;
-        unsigned runStart = m_offset;
-        while (runEnd < end && (renderer.style().isCollapsibleWhiteSpace(rendererText[runEnd]) || rendererText[runEnd] == '\t'))
-            ++runEnd;
-        bool addSpaceForPrevious = m_lastTextNodeEndedWithCollapsedSpace && m_lastCharacter && !renderer.style().isCollapsibleWhiteSpace(m_lastCharacter);
-        if (runEnd > runStart || addSpaceForPrevious) {
-            if (runEnd == rendererText.length()) {
-                m_lastTextNodeEndedWithCollapsedSpace = true;
-                return true;
+        ASSERT(renderer.parent());
+        ASSERT(is<RenderBlockFlow>(*renderer.parent()));
+        const auto& blockFlow = downcast<RenderBlockFlow>(*renderer.parent());
+        // Use the simple layout runs to iterate over the text content.
+        bool isNewTextNode = m_previousSimpleTextNodeInFlow && m_previousSimpleTextNodeInFlow != &textNode;
+        // Simple line layout run positions are all absolute to the parent flow.
+        // Offsetting is required when multiple renderers are present.
+        m_accumulatedSimpleTextLengthInFlow += isNewTextNode ? m_previousSimpleTextNodeInFlow->renderer()->text()->length() : 0;
+        m_previousSimpleTextNodeInFlow = &textNode;
+
+        unsigned endPosition = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : rendererText.length();
+        if (!m_flowRunResolverCache || &m_flowRunResolverCache->flow() != &blockFlow) {
+            m_accumulatedSimpleTextLengthInFlow = m_flowRunResolverCache ? 0 : textNodeOffsetInFlow(textNode);
+            m_flowRunResolverCache = std::make_unique<SimpleLineLayout::RunResolver>(blockFlow, *layout);
+        }
+        // Skip to m_offset position.
+        auto range = m_flowRunResolverCache->rangeForRenderer(renderer);
+        auto it = range.begin();
+        auto end = range.end();
+        while (it != end && (*it).end() <= (static_cast<unsigned>(m_offset) + m_accumulatedSimpleTextLengthInFlow))
+            ++it;
+        if (m_nextRunNeedsWhitespace && rendererText[m_offset - 1] == '\n') {
+            emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1);
+            return it == end;
+        }
+        if (it == end) {
+            // Collapsed trailing whitespace.
+            m_offset = endPosition;
+            m_lastTextNodeEndedWithCollapsedSpace = true;
+            return true;
+        }
+        if (m_nextRunNeedsWhitespace) {
+            emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1);
+            return false;
+        }
+        const auto run = *it;
+        ASSERT(run.end() - run.start() <= rendererText.length());
+        // contentStart skips leading whitespace.
+        unsigned contentStart = std::max<unsigned>(m_offset, run.start() - m_accumulatedSimpleTextLengthInFlow);
+        unsigned contentEnd = std::min(endPosition, run.end() - m_accumulatedSimpleTextLengthInFlow);
+        ASSERT_WITH_SECURITY_IMPLICATION(contentStart <= contentEnd);
+        // Check if whitespace adjustment is needed when crossing renderer boundary.
+        if (isNewTextNode) {
+            bool lastCharacterIsNotWhitespace = m_lastCharacter && !renderer.style().isCollapsibleWhiteSpace(m_lastCharacter);
+            bool addTrailingWhitespaceForPrevious = m_lastTextNodeEndedWithCollapsedSpace && lastCharacterIsNotWhitespace;
+            bool leadingWhitespaceIsNeededForCurrent = contentStart > static_cast<unsigned>(m_offset) && lastCharacterIsNotWhitespace;
+            if (addTrailingWhitespaceForPrevious || leadingWhitespaceIsNeededForCurrent) {
+                emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1);
+                return false;
             }
-            bool addSpaceForCurrent = runStart || (m_lastCharacter && !renderer.style().isCollapsibleWhiteSpace(m_lastCharacter));
-            if (addSpaceForCurrent || addSpaceForPrevious) {
-                emitCharacter(' ', textNode, nullptr, runStart, runEnd);
-                m_offset = runEnd;
+        }
+        // \n \t single whitespace characters need replacing so that the new line/tab characters don't show up.
+        unsigned stopPosition = contentStart;
+        while (stopPosition < contentEnd && !isNewLineOrTabCharacter(rendererText[stopPosition]))
+            ++stopPosition;
+        // Emit the text up to the new line/tab character.
+        if (stopPosition < contentEnd) {
+            if (stopPosition == contentStart) {
+                emitCharacter(' ', textNode, nullptr, contentStart, contentStart + 1);
+                m_offset = contentStart + 1;
                 return false;
             }
-            runStart = runEnd;
+            emitText(textNode, renderer, contentStart, stopPosition);
+            m_offset = stopPosition + 1;
+            m_nextRunNeedsWhitespace = true;
+            return false;
         }
-        while (runEnd < end && !renderer.style().isCollapsibleWhiteSpace(rendererText[runEnd]))
-            ++runEnd;
-        if (runStart < end)
-            emitText(textNode, renderer, runStart, runEnd);
-        m_offset = runEnd;
-        return runEnd == end;
+        emitText(textNode, renderer, contentStart, contentEnd);
+        // When line ending with collapsed whitespace is present, we need to carry over one whitespace: foo(end of line)bar -> foo bar (otherwise we would end up with foobar).
+        m_nextRunNeedsWhitespace = run.isEndOfLine() && contentEnd < endPosition && renderer.style().isCollapsibleWhiteSpace(rendererText[contentEnd]);
+        m_offset = contentEnd;
+        return static_cast<unsigned>(m_offset) == endPosition;
     }
 
     if (renderer.firstTextBox())
@@ -764,7 +827,7 @@ bool TextIterator::handleReplacedElement()
         String altText = downcast<RenderImage>(renderer).altText();
         if (unsigned length = altText.length()) {
             m_lastCharacter = altText[length - 1];
-            m_copyableText.set(WTF::move(altText));
+            m_copyableText.set(WTFMove(altText));
             m_text = m_copyableText.text();
             return true;
         }
@@ -795,7 +858,7 @@ static bool shouldEmitNewlineForNode(Node* node, bool emitsOriginalText)
     auto* renderer = node->renderer();
     if (!(renderer ? renderer->isBR() : node->hasTagName(brTag)))
         return false;
-    return emitsOriginalText || !(node->isInShadowTree() && node->shadowHost()->toInputElement());
+    return emitsOriginalText || !(node->isInShadowTree() && is<HTMLInputElement>(*node->shadowHost()));
 }
 
 static bool hasHeaderTag(HTMLElement& element)
@@ -861,7 +924,7 @@ static bool shouldEmitNewlineAfterNode(Node& node)
     // Check if this is the very last renderer in the document.
     // If so, then we should not emit a newline.
     Node* subsequentNode = &node;
-    while ((subsequentNode = NodeTraversal::nextSkippingChildren(subsequentNode))) {
+    while ((subsequentNode = NodeTraversal::nextSkippingChildren(*subsequentNode))) {
         if (subsequentNode->renderer())
             return true;
     }
@@ -1065,6 +1128,7 @@ void TextIterator::emitCharacter(UChar character, Node& characterNode, Node* off
     m_text = m_copyableText.text();
     m_lastCharacter = character;
     m_lastTextNodeEndedWithCollapsedSpace = false;
+    m_nextRunNeedsWhitespace = false;
 }
 
 void TextIterator::emitText(Text& textNode, RenderText& renderer, int textStartOffset, int textEndOffset)
@@ -1085,14 +1149,15 @@ void TextIterator::emitText(Text& textNode, RenderText& renderer, int textStartO
     m_positionEndOffset = textEndOffset;
 
     m_lastCharacter = string[textEndOffset - 1];
-    m_copyableText.set(WTF::move(string), textStartOffset, textEndOffset - textStartOffset);
+    m_copyableText.set(WTFMove(string), textStartOffset, textEndOffset - textStartOffset);
     m_text = m_copyableText.text();
 
     m_lastTextNodeEndedWithCollapsedSpace = false;
+    m_nextRunNeedsWhitespace = false;
     m_hasEmitted = true;
 }
 
-PassRefPtr<Range> TextIterator::range() const
+Ref<Range> TextIterator::range() const
 {
     ASSERT(!atEnd());
 
@@ -1108,13 +1173,13 @@ PassRefPtr<Range> TextIterator::range() const
     
 Node* TextIterator::node() const
 {
-    RefPtr<Range> textRange = range();
+    Ref<Range> textRange = range();
 
-    Node* node = textRange->startContainer();
-    if (node->offsetInCharacters())
-        return node;
+    Node& node = textRange->startContainer();
+    if (node.offsetInCharacters())
+        return &node;
     
-    return node->traverseToChildAt(textRange->startOffset());
+    return node.traverseToChildAt(textRange->startOffset());
 }
 
 // --------
@@ -1141,10 +1206,8 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range& ra
 
     range.ownerDocument().updateLayoutIgnorePendingStylesheets();
 
-    Node* startNode = range.startContainer();
-    if (!startNode)
-        return;
-    Node* endNode = range.endContainer();
+    Node* startNode = &range.startContainer();
+    Node* endNode = &range.endContainer();
     int startOffset = range.startOffset();
     int endOffset = range.endOffset();
 
@@ -1293,7 +1356,7 @@ bool SimplifiedBackwardsTextIterator::handleTextNode()
     ASSERT(m_positionEndOffset - offsetInNode <= static_cast<int>(text.length()));
 
     m_lastCharacter = text[m_positionEndOffset - offsetInNode - 1];
-    m_copyableText.set(WTF::move(text), m_positionStartOffset - offsetInNode, m_positionEndOffset - m_positionStartOffset);
+    m_copyableText.set(WTFMove(text), m_positionStartOffset - offsetInNode, m_positionEndOffset - m_positionStartOffset);
     m_text = m_copyableText.text();
 
     return !m_shouldHandleFirstLetter;
@@ -1382,7 +1445,7 @@ bool SimplifiedBackwardsTextIterator::advanceRespectingRange(Node* next)
     return true;
 }
 
-PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const
+Ref<Range> SimplifiedBackwardsTextIterator::range() const
 {
     ASSERT(!atEnd());
 
@@ -1401,21 +1464,21 @@ CharacterIterator::CharacterIterator(const Range& range, TextIteratorBehavior be
         m_underlyingIterator.advance();
 }
 
-PassRefPtr<Range> CharacterIterator::range() const
+Ref<Range> CharacterIterator::range() const
 {
-    RefPtr<Range> r = m_underlyingIterator.range();
+    Ref<Range> range = m_underlyingIterator.range();
     if (!m_underlyingIterator.atEnd()) {
         if (m_underlyingIterator.text().length() <= 1) {
             ASSERT(m_runOffset == 0);
         } else {
-            Node* n = r->startContainer();
-            ASSERT(n == r->endContainer());
-            int offset = r->startOffset() + m_runOffset;
-            r->setStart(n, offset);
-            r->setEnd(n, offset + 1);
+            Node& node = range->startContainer();
+            ASSERT(&node == &range->endContainer());
+            int offset = range->startOffset() + m_runOffset;
+            range->setStart(&node, offset);
+            range->setEnd(&node, offset + 1);
         }
     }
-    return r.release();
+    return range;
 }
 
 void CharacterIterator::advance(int count)
@@ -1463,18 +1526,22 @@ void CharacterIterator::advance(int count)
     m_runOffset = 0;
 }
 
-static PassRefPtr<Range> characterSubrange(CharacterIterator& it, int offset, int length)
+static Ref<Range> characterSubrange(Document& document, CharacterIterator& it, int offset, int length)
 {
     it.advance(offset);
-    RefPtr<Range> start = it.range();
+    if (it.atEnd())
+        return Range::create(document);
+
+    Ref<Range> start = it.range();
 
     if (length > 1)
         it.advance(length - 1);
-    RefPtr<Range> end = it.range();
+    if (it.atEnd())
+        return Range::create(document);
+
+    Ref<Range> end = it.range();
 
-    return Range::create(start->startContainer()->document(),
-        start->startContainer(), start->startOffset(), 
-        end->endContainer(), end->endOffset());
+    return Range::create(document, &start->startContainer(), start->startOffset(), &end->endContainer(), end->endOffset());
 }
 
 BackwardsCharacterIterator::BackwardsCharacterIterator(const Range& range)
@@ -1487,21 +1554,21 @@ BackwardsCharacterIterator::BackwardsCharacterIterator(const Range& range)
         m_underlyingIterator.advance();
 }
 
-PassRefPtr<Range> BackwardsCharacterIterator::range() const
+Ref<Range> BackwardsCharacterIterator::range() const
 {
-    RefPtr<Range> r = m_underlyingIterator.range();
+    Ref<Range> r = m_underlyingIterator.range();
     if (!m_underlyingIterator.atEnd()) {
         if (m_underlyingIterator.text().length() <= 1)
             ASSERT(m_runOffset == 0);
         else {
-            Node* n = r->startContainer();
-            ASSERT(n == r->endContainer());
+            Node& node = r->startContainer();
+            ASSERT(&node == &r->endContainer());
             int offset = r->endOffset() - m_runOffset;
-            r->setStart(n, offset - 1);
-            r->setEnd(n, offset);
+            r->setStart(&node, offset - 1);
+            r->setEnd(&node, offset);
         }
     }
-    return r.release();
+    return r;
 }
 
 void BackwardsCharacterIterator::advance(int count)
@@ -2179,7 +2246,7 @@ inline bool SearchBuffer::isWordStartMatch(size_t start, size_t length) const
 
     // Chinese and Japanese lack word boundary marks, and there is no clear agreement on what constitutes
     // a word, so treat the position before any CJK character as a word start.
-    if (Font::isCJKIdeographOrSymbol(firstCharacter))
+    if (FontCascade::isCJKIdeographOrSymbol(firstCharacter))
         return true;
 
     size_t wordBreakSearchStart = start + length;
@@ -2379,10 +2446,10 @@ int TextIterator::rangeLength(const Range* range, bool forSelectionPreservation)
     return length;
 }
 
-PassRefPtr<Range> TextIterator::subrange(Range* entireRange, int characterOffset, int characterCount)
+Ref<Range> TextIterator::subrange(Range* entireRange, int characterOffset, int characterCount)
 {
     CharacterIterator entireRangeIterator(*entireRange);
-    return characterSubrange(entireRangeIterator, characterOffset, characterCount);
+    return characterSubrange(entireRange->ownerDocument(), entireRangeIterator, characterOffset, characterCount);
 }
 
 static inline bool isInsideReplacedElement(TextIterator& iterator)
@@ -2393,23 +2460,23 @@ static inline bool isInsideReplacedElement(TextIterator& iterator)
     return node && isRendererReplacedElement(node->renderer());
 }
 
-PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(ContainerNode* scope, int rangeLocation, int rangeLength, bool forSelectionPreservation)
+RefPtr<Range> TextIterator::rangeFromLocationAndLength(ContainerNode* scope, int rangeLocation, int rangeLength, bool forSelectionPreservation)
 {
-    RefPtr<Range> resultRange = scope->document().createRange();
+    Ref<Range> resultRange = scope->document().createRange();
 
     int docTextPosition = 0;
     int rangeEnd = rangeLocation + rangeLength;
     bool startRangeFound = false;
 
-    RefPtr<Range> textRunRange = rangeOfContents(*scope);
+    Ref<Range> textRunRange = rangeOfContents(*scope);
 
-    TextIterator it(textRunRange.get(), forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior);
+    TextIterator it(textRunRange.ptr(), forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior);
     
     // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>.
     if (!rangeLocation && !rangeLength && it.atEnd()) {
-        resultRange->setStart(textRunRange->startContainer(), 0);
-        resultRange->setEnd(textRunRange->startContainer(), 0);
-        return resultRange.release();
+        resultRange->setStart(&textRunRange->startContainer(), 0);
+        resultRange->setEnd(&textRunRange->startContainer(), 0);
+        return WTFMove(resultRange);
     }
 
     for (; !it.atEnd(); it.advance()) {
@@ -2425,8 +2492,8 @@ PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(ContainerNode* scope,
             if (length == 1 && (it.text()[0] == '\n' || isInsideReplacedElement(it))) {
                 it.advance();
                 if (!it.atEnd()) {
-                    RefPtr<Range> range = it.range();
-                    textRunRange->setEnd(range->startContainer(), range->startOffset());
+                    Ref<Range> range = it.range();
+                    textRunRange->setEnd(&range->startContainer(), range->startOffset());
                 } else {
                     Position runStart = textRunRange->startPosition();
                     Position runEnd = VisiblePosition(runStart).next().deepEquivalent();
@@ -2438,26 +2505,26 @@ PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(ContainerNode* scope,
 
         if (foundStart) {
             startRangeFound = true;
-            if (textRunRange->startContainer()->isTextNode()) {
+            if (textRunRange->startContainer().isTextNode()) {
                 int offset = rangeLocation - docTextPosition;
-                resultRange->setStart(textRunRange->startContainer(), offset + textRunRange->startOffset());
+                resultRange->setStart(&textRunRange->startContainer(), offset + textRunRange->startOffset());
             } else {
                 if (rangeLocation == docTextPosition)
-                    resultRange->setStart(textRunRange->startContainer(), textRunRange->startOffset());
+                    resultRange->setStart(&textRunRange->startContainer(), textRunRange->startOffset());
                 else
-                    resultRange->setStart(textRunRange->endContainer(), textRunRange->endOffset());
+                    resultRange->setStart(&textRunRange->endContainer(), textRunRange->endOffset());
             }
         }
 
         if (foundEnd) {
-            if (textRunRange->startContainer()->isTextNode()) {
+            if (textRunRange->startContainer().isTextNode()) {
                 int offset = rangeEnd - docTextPosition;
-                resultRange->setEnd(textRunRange->startContainer(), offset + textRunRange->startOffset());
+                resultRange->setEnd(&textRunRange->startContainer(), offset + textRunRange->startOffset());
             } else {
                 if (rangeEnd == docTextPosition)
-                    resultRange->setEnd(textRunRange->startContainer(), textRunRange->startOffset());
+                    resultRange->setEnd(&textRunRange->startContainer(), textRunRange->startOffset());
                 else
-                    resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffset());
+                    resultRange->setEnd(&textRunRange->endContainer(), textRunRange->endOffset());
             }
             docTextPosition += length;
             break;
@@ -2470,9 +2537,9 @@ PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(ContainerNode* scope,
         return nullptr;
     
     if (rangeLength && rangeEnd > docTextPosition) // rangeEnd is out of bounds
-        resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffset());
+        resultRange->setEnd(&textRunRange->endContainer(), textRunRange->endOffset());
     
-    return resultRange.release();
+    return WTFMove(resultRange);
 }
 
 bool TextIterator::getLocationAndLengthFromRange(Node* scope, const Range* range, size_t& location, size_t& length)
@@ -2480,26 +2547,23 @@ bool TextIterator::getLocationAndLengthFromRange(Node* scope, const Range* range
     location = notFound;
     length = 0;
 
-    if (!range->startContainer())
-        return false;
-
     // The critical assumption is that this only gets called with ranges that
     // concentrate on a given area containing the selection root. This is done
     // because of text fields and textareas. The DOM for those is not
     // directly in the document DOM, so ensure that the range does not cross a
     // boundary of one of those.
-    if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
+    if (&range->startContainer() != scope && !range->startContainer().isDescendantOf(scope))
         return false;
-    if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
+    if (&range->endContainer() != scope && !range->endContainer().isDescendantOf(scope))
         return false;
 
-    RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
-    ASSERT(testRange->startContainer() == scope);
-    location = TextIterator::rangeLength(testRange.get());
+    Ref<Range> testRange = Range::create(scope->document(), scope, 0, &range->startContainer(), range->startOffset());
+    ASSERT(&testRange->startContainer() == scope);
+    location = TextIterator::rangeLength(testRange.ptr());
 
-    testRange->setEnd(range->endContainer(), range->endOffset(), IGNORE_EXCEPTION);
-    ASSERT(testRange->startContainer() == scope);
-    length = TextIterator::rangeLength(testRange.get()) - location;
+    testRange->setEnd(&range->endContainer(), range->endOffset(), IGNORE_EXCEPTION);
+    ASSERT(&testRange->startContainer() == scope);
+    length = TextIterator::rangeLength(testRange.ptr()) - location;
     return true;
 }
 
@@ -2538,11 +2602,11 @@ String plainTextReplacingNoBreakSpace(const Range* range, TextIteratorBehavior d
     return plainText(range, defaultBehavior, isDisplayString).replace(noBreakSpace, ' ');
 }
 
-static PassRefPtr<Range> collapsedToBoundary(const Range& range, bool forward)
+static Ref<Range> collapsedToBoundary(const Range& range, bool forward)
 {
-    RefPtr<Range> result = range.cloneRange(ASSERT_NO_EXCEPTION);
-    result->collapse(!forward, ASSERT_NO_EXCEPTION);
-    return result.release();
+    Ref<Range> result = range.cloneRange();
+    result->collapse(!forward);
+    return result;
 }
 
 static size_t findPlainText(const Range& range, const String& target, FindOptions options, size_t& matchStart)
@@ -2553,9 +2617,9 @@ static size_t findPlainText(const Range& range, const String& target, FindOption
     SearchBuffer buffer(target, options);
 
     if (buffer.needsMoreContext()) {
-        RefPtr<Range> beforeStartRange = range.ownerDocument().createRange();
-        beforeStartRange->setEnd(range.startContainer(), range.startOffset());
-        for (SimplifiedBackwardsTextIterator backwardsIterator(*beforeStartRange); !backwardsIterator.atEnd(); backwardsIterator.advance()) {
+        Ref<Range> beforeStartRange = range.ownerDocument().createRange();
+        beforeStartRange->setEnd(&range.startContainer(), range.startOffset());
+        for (SimplifiedBackwardsTextIterator backwardsIterator(beforeStartRange.get()); !backwardsIterator.atEnd(); backwardsIterator.advance()) {
             buffer.prependContext(backwardsIterator.text());
             if (!buffer.needsMoreContext())
                 break;
@@ -2589,7 +2653,7 @@ tryAgain:
     return matchLength;
 }
 
-PassRefPtr<Range> findPlainText(const Range& range, const String& target, FindOptions options)
+Ref<Range> findPlainText(const Range& range, const String& target, FindOptions options)
 {
     // First, find the text.
     size_t matchStart;
@@ -2602,7 +2666,7 @@ PassRefPtr<Range> findPlainText(const Range& range, const String& target, FindOp
 
     // Then, find the document position of the start and the end of the text.
     CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls);
-    return characterSubrange(computeRangeIterator, matchStart, matchLength);
+    return characterSubrange(range.ownerDocument(), computeRangeIterator, matchStart, matchLength);
 }
 
 }