Home | History | Annotate | Download | only in dom
      1 /*
      2  * (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  * (C) 2000 Gunnstein Lye (gunnstein (at) netcom.no)
      4  * (C) 2000 Frederik Holljen (frederik.holljen (at) hig.no)
      5  * (C) 2001 Peter Kelly (pmk (at) post.com)
      6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      7  * Copyright (C) 2011 Motorola Mobility. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  */
     24 
     25 #include "config.h"
     26 #include "core/dom/Range.h"
     27 
     28 #include "bindings/v8/ExceptionState.h"
     29 #include "bindings/v8/ExceptionStatePlaceholder.h"
     30 #include "core/dom/ClientRect.h"
     31 #include "core/dom/ClientRectList.h"
     32 #include "core/dom/DocumentFragment.h"
     33 #include "core/dom/ExceptionCode.h"
     34 #include "core/dom/Node.h"
     35 #include "core/dom/NodeTraversal.h"
     36 #include "core/dom/NodeWithIndex.h"
     37 #include "core/dom/ProcessingInstruction.h"
     38 #include "core/dom/ScopedEventQueue.h"
     39 #include "core/dom/Text.h"
     40 #include "core/editing/TextIterator.h"
     41 #include "core/editing/VisiblePosition.h"
     42 #include "core/editing/VisibleUnits.h"
     43 #include "core/editing/markup.h"
     44 #include "core/html/HTMLElement.h"
     45 #include "core/platform/graphics/FloatQuad.h"
     46 #include "core/rendering/RenderBoxModelObject.h"
     47 #include "core/rendering/RenderText.h"
     48 #include "wtf/RefCountedLeakCounter.h"
     49 #include "wtf/Vector.h"
     50 #include "wtf/text/CString.h"
     51 #include "wtf/text/StringBuilder.h"
     52 #include <stdio.h>
     53 
     54 namespace WebCore {
     55 
     56 using namespace std;
     57 using namespace HTMLNames;
     58 
     59 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, rangeCounter, ("Range"));
     60 
     61 inline Range::Range(PassRefPtr<Document> ownerDocument)
     62     : m_ownerDocument(ownerDocument)
     63     , m_start(m_ownerDocument)
     64     , m_end(m_ownerDocument)
     65 {
     66 #ifndef NDEBUG
     67     rangeCounter.increment();
     68 #endif
     69 
     70     ScriptWrappable::init(this);
     71     m_ownerDocument->attachRange(this);
     72 }
     73 
     74 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument)
     75 {
     76     return adoptRef(new Range(ownerDocument));
     77 }
     78 
     79 inline Range::Range(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
     80     : m_ownerDocument(ownerDocument)
     81     , m_start(m_ownerDocument)
     82     , m_end(m_ownerDocument)
     83 {
     84 #ifndef NDEBUG
     85     rangeCounter.increment();
     86 #endif
     87 
     88     ScriptWrappable::init(this);
     89     m_ownerDocument->attachRange(this);
     90 
     91     // Simply setting the containers and offsets directly would not do any of the checking
     92     // that setStart and setEnd do, so we call those functions.
     93     setStart(startContainer, startOffset);
     94     setEnd(endContainer, endOffset);
     95 }
     96 
     97 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset)
     98 {
     99     return adoptRef(new Range(ownerDocument, startContainer, startOffset, endContainer, endOffset));
    100 }
    101 
    102 PassRefPtr<Range> Range::create(PassRefPtr<Document> ownerDocument, const Position& start, const Position& end)
    103 {
    104     return adoptRef(new Range(ownerDocument, start.containerNode(), start.computeOffsetInContainerNode(), end.containerNode(), end.computeOffsetInContainerNode()));
    105 }
    106 
    107 Range::~Range()
    108 {
    109     // Always detach (even if we've already detached) to fix https://bugs.webkit.org/show_bug.cgi?id=26044
    110     m_ownerDocument->detachRange(this);
    111 
    112 #ifndef NDEBUG
    113     rangeCounter.decrement();
    114 #endif
    115 }
    116 
    117 void Range::setDocument(Document* document)
    118 {
    119     ASSERT(m_ownerDocument != document);
    120     if (m_ownerDocument)
    121         m_ownerDocument->detachRange(this);
    122     m_ownerDocument = document;
    123     m_start.setToStartOfNode(document);
    124     m_end.setToStartOfNode(document);
    125     m_ownerDocument->attachRange(this);
    126 }
    127 
    128 Node* Range::startContainer(ExceptionState& es) const
    129 {
    130     if (!m_start.container()) {
    131         es.throwDOMException(InvalidStateError);
    132         return 0;
    133     }
    134 
    135     return m_start.container();
    136 }
    137 
    138 int Range::startOffset(ExceptionState& es) const
    139 {
    140     if (!m_start.container()) {
    141         es.throwDOMException(InvalidStateError);
    142         return 0;
    143     }
    144 
    145     return m_start.offset();
    146 }
    147 
    148 Node* Range::endContainer(ExceptionState& es) const
    149 {
    150     if (!m_start.container()) {
    151         es.throwDOMException(InvalidStateError);
    152         return 0;
    153     }
    154 
    155     return m_end.container();
    156 }
    157 
    158 int Range::endOffset(ExceptionState& es) const
    159 {
    160     if (!m_start.container()) {
    161         es.throwDOMException(InvalidStateError);
    162         return 0;
    163     }
    164 
    165     return m_end.offset();
    166 }
    167 
    168 Node* Range::commonAncestorContainer(ExceptionState& es) const
    169 {
    170     if (!m_start.container()) {
    171         es.throwDOMException(InvalidStateError);
    172         return 0;
    173     }
    174 
    175     return commonAncestorContainer(m_start.container(), m_end.container());
    176 }
    177 
    178 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
    179 {
    180     for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
    181         for (Node* parentB = containerB; parentB; parentB = parentB->parentNode()) {
    182             if (parentA == parentB)
    183                 return parentA;
    184         }
    185     }
    186     return 0;
    187 }
    188 
    189 bool Range::collapsed(ExceptionState& es) const
    190 {
    191     if (!m_start.container()) {
    192         es.throwDOMException(InvalidStateError);
    193         return 0;
    194     }
    195 
    196     return m_start == m_end;
    197 }
    198 
    199 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& start, const RangeBoundaryPoint& end)
    200 {
    201     Node* endRootContainer = end.container();
    202     while (endRootContainer->parentNode())
    203         endRootContainer = endRootContainer->parentNode();
    204     Node* startRootContainer = start.container();
    205     while (startRootContainer->parentNode())
    206         startRootContainer = startRootContainer->parentNode();
    207 
    208     return startRootContainer != endRootContainer || (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0);
    209 }
    210 
    211 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& es)
    212 {
    213     if (!m_start.container()) {
    214         es.throwDOMException(InvalidStateError);
    215         return;
    216     }
    217 
    218     if (!refNode) {
    219         es.throwDOMException(NotFoundError);
    220         return;
    221     }
    222 
    223     bool didMoveDocument = false;
    224     if (refNode->document() != m_ownerDocument) {
    225         setDocument(refNode->document());
    226         didMoveDocument = true;
    227     }
    228 
    229     Node* childNode = checkNodeWOffset(refNode.get(), offset, es);
    230     if (es.hadException())
    231         return;
    232 
    233     m_start.set(refNode, offset, childNode);
    234 
    235     if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
    236         collapse(true, es);
    237 }
    238 
    239 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& es)
    240 {
    241     if (!m_start.container()) {
    242         es.throwDOMException(InvalidStateError);
    243         return;
    244     }
    245 
    246     if (!refNode) {
    247         es.throwDOMException(NotFoundError);
    248         return;
    249     }
    250 
    251     bool didMoveDocument = false;
    252     if (refNode->document() != m_ownerDocument) {
    253         setDocument(refNode->document());
    254         didMoveDocument = true;
    255     }
    256 
    257     Node* childNode = checkNodeWOffset(refNode.get(), offset, es);
    258     if (es.hadException())
    259         return;
    260 
    261     m_end.set(refNode, offset, childNode);
    262 
    263     if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
    264         collapse(false, es);
    265 }
    266 
    267 void Range::setStart(const Position& start, ExceptionState& es)
    268 {
    269     Position parentAnchored = start.parentAnchoredEquivalent();
    270     setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode(), es);
    271 }
    272 
    273 void Range::setEnd(const Position& end, ExceptionState& es)
    274 {
    275     Position parentAnchored = end.parentAnchoredEquivalent();
    276     setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode(), es);
    277 }
    278 
    279 void Range::collapse(bool toStart, ExceptionState& es)
    280 {
    281     if (!m_start.container()) {
    282         es.throwDOMException(InvalidStateError);
    283         return;
    284     }
    285 
    286     if (toStart)
    287         m_end = m_start;
    288     else
    289         m_start = m_end;
    290 }
    291 
    292 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& es)
    293 {
    294     if (!m_start.container()) {
    295         es.throwDOMException(InvalidStateError);
    296         return false;
    297     }
    298 
    299     if (!refNode) {
    300         es.throwDOMException(HierarchyRequestError);
    301         return false;
    302     }
    303 
    304     if (!refNode->attached() || refNode->document() != m_ownerDocument) {
    305         return false;
    306     }
    307 
    308     checkNodeWOffset(refNode, offset, es);
    309     if (es.hadException())
    310         return false;
    311 
    312     return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset(), es) >= 0 && !es.hadException()
    313         && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset(), es) <= 0 && !es.hadException();
    314 }
    315 
    316 short Range::comparePoint(Node* refNode, int offset, ExceptionState& es) const
    317 {
    318     // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
    319     // This method returns -1, 0 or 1 depending on if the point described by the
    320     // refNode node and an offset within the node is before, same as, or after the range respectively.
    321 
    322     if (!m_start.container()) {
    323         es.throwDOMException(InvalidStateError);
    324         return 0;
    325     }
    326 
    327     if (!refNode) {
    328         es.throwDOMException(HierarchyRequestError);
    329         return 0;
    330     }
    331 
    332     if (!refNode->attached() || refNode->document() != m_ownerDocument) {
    333         es.throwDOMException(WrongDocumentError);
    334         return 0;
    335     }
    336 
    337     checkNodeWOffset(refNode, offset, es);
    338     if (es.hadException())
    339         return 0;
    340 
    341     // compare to start, and point comes before
    342     if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offset(), es) < 0)
    343         return -1;
    344 
    345     if (es.hadException())
    346         return 0;
    347 
    348     // compare to end, and point comes after
    349     if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset(), es) > 0 && !es.hadException())
    350         return 1;
    351 
    352     // point is in the middle of this range, or on the boundary points
    353     return 0;
    354 }
    355 
    356 Range::CompareResults Range::compareNode(Node* refNode, ExceptionState& es) const
    357 {
    358     // http://developer.mozilla.org/en/docs/DOM:range.compareNode
    359     // This method returns 0, 1, 2, or 3 based on if the node is before, after,
    360     // before and after(surrounds), or inside the range, respectively
    361 
    362     if (!refNode) {
    363         es.throwDOMException(NotFoundError);
    364         return NODE_BEFORE;
    365     }
    366 
    367     if (!m_start.container() && refNode->attached()) {
    368         es.throwDOMException(InvalidStateError);
    369         return NODE_BEFORE;
    370     }
    371 
    372     if (m_start.container() && !refNode->attached()) {
    373         // Firefox doesn't throw an exception for this case; it returns 0.
    374         return NODE_BEFORE;
    375     }
    376 
    377     if (refNode->document() != m_ownerDocument) {
    378         // Firefox doesn't throw an exception for this case; it returns 0.
    379         return NODE_BEFORE;
    380     }
    381 
    382     ContainerNode* parentNode = refNode->parentNode();
    383     int nodeIndex = refNode->nodeIndex();
    384 
    385     if (!parentNode) {
    386         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
    387         // but we throw to match firefox behavior
    388         es.throwDOMException(NotFoundError);
    389         return NODE_BEFORE;
    390     }
    391 
    392     if (comparePoint(parentNode, nodeIndex, es) < 0) { // starts before
    393         if (comparePoint(parentNode, nodeIndex + 1, es) > 0) // ends after the range
    394             return NODE_BEFORE_AND_AFTER;
    395         return NODE_BEFORE; // ends before or in the range
    396     }
    397     // starts at or after the range start
    398     if (comparePoint(parentNode, nodeIndex + 1, es) > 0) // ends after the range
    399         return NODE_AFTER;
    400     return NODE_INSIDE; // ends inside the range
    401 }
    402 
    403 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, ExceptionState& es) const
    404 {
    405     if (!m_start.container()) {
    406         es.throwDOMException(InvalidStateError);
    407         return 0;
    408     }
    409 
    410     if (!sourceRange) {
    411         es.throwDOMException(NotFoundError);
    412         return 0;
    413     }
    414 
    415     Node* thisCont = commonAncestorContainer(es);
    416     if (es.hadException())
    417         return 0;
    418     Node* sourceCont = sourceRange->commonAncestorContainer(es);
    419     if (es.hadException())
    420         return 0;
    421 
    422     if (thisCont->document() != sourceCont->document()) {
    423         es.throwDOMException(WrongDocumentError);
    424         return 0;
    425     }
    426 
    427     Node* thisTop = thisCont;
    428     Node* sourceTop = sourceCont;
    429     while (thisTop->parentNode())
    430         thisTop = thisTop->parentNode();
    431     while (sourceTop->parentNode())
    432         sourceTop = sourceTop->parentNode();
    433     if (thisTop != sourceTop) { // in different DocumentFragments
    434         es.throwDOMException(WrongDocumentError);
    435         return 0;
    436     }
    437 
    438     switch (how) {
    439         case START_TO_START:
    440             return compareBoundaryPoints(m_start, sourceRange->m_start, es);
    441         case START_TO_END:
    442             return compareBoundaryPoints(m_end, sourceRange->m_start, es);
    443         case END_TO_END:
    444             return compareBoundaryPoints(m_end, sourceRange->m_end, es);
    445         case END_TO_START:
    446             return compareBoundaryPoints(m_start, sourceRange->m_end, es);
    447     }
    448 
    449     es.throwDOMException(SyntaxError);
    450     return 0;
    451 }
    452 
    453 short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containerB, int offsetB, ExceptionState& es)
    454 {
    455     ASSERT(containerA);
    456     ASSERT(containerB);
    457 
    458     if (!containerA)
    459         return -1;
    460     if (!containerB)
    461         return 1;
    462 
    463     // see DOM2 traversal & range section 2.5
    464 
    465     // case 1: both points have the same container
    466     if (containerA == containerB) {
    467         if (offsetA == offsetB)
    468             return 0;           // A is equal to B
    469         if (offsetA < offsetB)
    470             return -1;          // A is before B
    471         else
    472             return 1;           // A is after B
    473     }
    474 
    475     // case 2: node C (container B or an ancestor) is a child node of A
    476     Node* c = containerB;
    477     while (c && c->parentNode() != containerA)
    478         c = c->parentNode();
    479     if (c) {
    480         int offsetC = 0;
    481         Node* n = containerA->firstChild();
    482         while (n != c && offsetC < offsetA) {
    483             offsetC++;
    484             n = n->nextSibling();
    485         }
    486 
    487         if (offsetA <= offsetC)
    488             return -1;              // A is before B
    489         else
    490             return 1;               // A is after B
    491     }
    492 
    493     // case 3: node C (container A or an ancestor) is a child node of B
    494     c = containerA;
    495     while (c && c->parentNode() != containerB)
    496         c = c->parentNode();
    497     if (c) {
    498         int offsetC = 0;
    499         Node* n = containerB->firstChild();
    500         while (n != c && offsetC < offsetB) {
    501             offsetC++;
    502             n = n->nextSibling();
    503         }
    504 
    505         if (offsetC < offsetB)
    506             return -1;              // A is before B
    507         else
    508             return 1;               // A is after B
    509     }
    510 
    511     // case 4: containers A & B are siblings, or children of siblings
    512     // ### we need to do a traversal here instead
    513     Node* commonAncestor = commonAncestorContainer(containerA, containerB);
    514     if (!commonAncestor) {
    515         es.throwDOMException(WrongDocumentError);
    516         return 0;
    517     }
    518     Node* childA = containerA;
    519     while (childA && childA->parentNode() != commonAncestor)
    520         childA = childA->parentNode();
    521     if (!childA)
    522         childA = commonAncestor;
    523     Node* childB = containerB;
    524     while (childB && childB->parentNode() != commonAncestor)
    525         childB = childB->parentNode();
    526     if (!childB)
    527         childB = commonAncestor;
    528 
    529     if (childA == childB)
    530         return 0; // A is equal to B
    531 
    532     Node* n = commonAncestor->firstChild();
    533     while (n) {
    534         if (n == childA)
    535             return -1; // A is before B
    536         if (n == childB)
    537             return 1; // A is after B
    538         n = n->nextSibling();
    539     }
    540 
    541     // Should never reach this point.
    542     ASSERT_NOT_REACHED();
    543     return 0;
    544 }
    545 
    546 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const RangeBoundaryPoint& boundaryB, ExceptionState& es)
    547 {
    548     return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boundaryB.container(), boundaryB.offset(), es);
    549 }
    550 
    551 bool Range::boundaryPointsValid() const
    552 {
    553     TrackExceptionState es;
    554     return m_start.container() && compareBoundaryPoints(m_start, m_end, es) <= 0 && !es.hadException();
    555 }
    556 
    557 void Range::deleteContents(ExceptionState& es)
    558 {
    559     checkDeleteExtract(es);
    560     if (es.hadException())
    561         return;
    562 
    563     processContents(DELETE_CONTENTS, es);
    564 }
    565 
    566 bool Range::intersectsNode(Node* refNode, ExceptionState& es)
    567 {
    568     // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
    569     // Returns a bool if the node intersects the range.
    570 
    571     // Throw exception if the range is already detached.
    572     if (!m_start.container()) {
    573         es.throwDOMException(InvalidStateError);
    574         return false;
    575     }
    576     if (!refNode) {
    577         es.throwDOMException(NotFoundError);
    578         return false;
    579     }
    580 
    581     if (!refNode->attached() || refNode->document() != m_ownerDocument) {
    582         // Firefox doesn't throw an exception for these cases; it returns false.
    583         return false;
    584     }
    585 
    586     ContainerNode* parentNode = refNode->parentNode();
    587     int nodeIndex = refNode->nodeIndex();
    588 
    589     if (!parentNode) {
    590         // if the node is the top document we should return NODE_BEFORE_AND_AFTER
    591         // but we throw to match firefox behavior
    592         es.throwDOMException(NotFoundError);
    593         return false;
    594     }
    595 
    596     if (comparePoint(parentNode, nodeIndex, es) < 0 // starts before start
    597         && comparePoint(parentNode, nodeIndex + 1, es) < 0) { // ends before start
    598         return false;
    599     }
    600 
    601     if (comparePoint(parentNode, nodeIndex, es) > 0 // starts after end
    602         && comparePoint(parentNode, nodeIndex + 1, es) > 0) { // ends after end
    603         return false;
    604     }
    605 
    606     return true; // all other cases
    607 }
    608 
    609 static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot)
    610 {
    611     if (node == commonRoot)
    612         return 0;
    613 
    614     ASSERT(commonRoot->contains(node));
    615 
    616     while (node->parentNode() != commonRoot)
    617         node = node->parentNode();
    618 
    619     return node;
    620 }
    621 
    622 static inline Node* childOfCommonRootBeforeOffset(Node* container, unsigned offset, Node* commonRoot)
    623 {
    624     ASSERT(container);
    625     ASSERT(commonRoot);
    626 
    627     if (!commonRoot->contains(container))
    628         return 0;
    629 
    630     if (container == commonRoot) {
    631         container = container->firstChild();
    632         for (unsigned i = 0; container && i < offset; i++)
    633             container = container->nextSibling();
    634     } else {
    635         while (container->parentNode() != commonRoot)
    636             container = container->parentNode();
    637     }
    638 
    639     return container;
    640 }
    641 
    642 static inline unsigned lengthOfContentsInNode(Node* node)
    643 {
    644     // This switch statement must be consistent with that of Range::processContentsBetweenOffsets.
    645     switch (node->nodeType()) {
    646     case Node::TEXT_NODE:
    647     case Node::CDATA_SECTION_NODE:
    648     case Node::COMMENT_NODE:
    649         return static_cast<CharacterData*>(node)->length();
    650     case Node::PROCESSING_INSTRUCTION_NODE:
    651         return static_cast<ProcessingInstruction*>(node)->data().length();
    652     case Node::ELEMENT_NODE:
    653     case Node::ATTRIBUTE_NODE:
    654     case Node::ENTITY_NODE:
    655     case Node::DOCUMENT_NODE:
    656     case Node::DOCUMENT_TYPE_NODE:
    657     case Node::DOCUMENT_FRAGMENT_NODE:
    658     case Node::NOTATION_NODE:
    659     case Node::XPATH_NAMESPACE_NODE:
    660         return node->childNodeCount();
    661     }
    662     ASSERT_NOT_REACHED();
    663     return 0;
    664 }
    665 
    666 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionState& es)
    667 {
    668     typedef Vector<RefPtr<Node> > NodeVector;
    669 
    670     RefPtr<DocumentFragment> fragment;
    671     if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
    672         fragment = DocumentFragment::create(m_ownerDocument.get());
    673 
    674     if (collapsed(es))
    675         return fragment.release();
    676     if (es.hadException())
    677         return 0;
    678 
    679     RefPtr<Node> commonRoot = commonAncestorContainer(es);
    680     if (es.hadException())
    681         return 0;
    682     ASSERT(commonRoot);
    683 
    684     if (m_start.container() == m_end.container()) {
    685         processContentsBetweenOffsets(action, fragment, m_start.container(), m_start.offset(), m_end.offset(), es);
    686         return fragment;
    687     }
    688 
    689     // Since mutation observers can modify the range during the process, the boundary points need to be saved.
    690     RangeBoundaryPoint originalStart(m_start);
    691     RangeBoundaryPoint originalEnd(m_end);
    692 
    693     // what is the highest node that partially selects the start / end of the range?
    694     RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(originalStart.container(), commonRoot.get());
    695     RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(originalEnd.container(), commonRoot.get());
    696 
    697     // Start and end containers are different.
    698     // There are three possibilities here:
    699     // 1. Start container == commonRoot (End container must be a descendant)
    700     // 2. End container == commonRoot (Start container must be a descendant)
    701     // 3. Neither is commonRoot, they are both descendants
    702     //
    703     // In case 3, we grab everything after the start (up until a direct child
    704     // of commonRoot) into leftContents, and everything before the end (up until
    705     // a direct child of commonRoot) into rightContents. Then we process all
    706     // commonRoot children between leftContents and rightContents
    707     //
    708     // In case 1 or 2, we skip either processing of leftContents or rightContents,
    709     // in which case the last lot of nodes either goes from the first or last
    710     // child of commonRoot.
    711     //
    712     // These are deleted, cloned, or extracted (i.e. both) depending on action.
    713 
    714     // Note that we are verifying that our common root hierarchy is still intact
    715     // after any DOM mutation event, at various stages below. See webkit bug 60350.
    716 
    717     RefPtr<Node> leftContents;
    718     if (originalStart.container() != commonRoot && commonRoot->contains(originalStart.container())) {
    719         leftContents = processContentsBetweenOffsets(action, 0, originalStart.container(), originalStart.offset(), lengthOfContentsInNode(originalStart.container()), es);
    720         leftContents = processAncestorsAndTheirSiblings(action, originalStart.container(), ProcessContentsForward, leftContents, commonRoot.get(), es);
    721     }
    722 
    723     RefPtr<Node> rightContents;
    724     if (m_end.container() != commonRoot && commonRoot->contains(originalEnd.container())) {
    725         rightContents = processContentsBetweenOffsets(action, 0, originalEnd.container(), 0, originalEnd.offset(), es);
    726         rightContents = processAncestorsAndTheirSiblings(action, originalEnd.container(), ProcessContentsBackward, rightContents, commonRoot.get(), es);
    727     }
    728 
    729     // delete all children of commonRoot between the start and end container
    730     RefPtr<Node> processStart = childOfCommonRootBeforeOffset(originalStart.container(), originalStart.offset(), commonRoot.get());
    731     if (processStart && originalStart.container() != commonRoot) // processStart contains nodes before m_start.
    732         processStart = processStart->nextSibling();
    733     RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(originalEnd.container(), originalEnd.offset(), commonRoot.get());
    734 
    735     // Collapse the range, making sure that the result is not within a node that was partially selected.
    736     if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
    737         if (partialStart && commonRoot->contains(partialStart.get())) {
    738             // FIXME: We should not continue if we have an earlier error.
    739             es.clearException();
    740             setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, es);
    741         } else if (partialEnd && commonRoot->contains(partialEnd.get())) {
    742             // FIXME: We should not continue if we have an earlier error.
    743             es.clearException();
    744             setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), es);
    745         }
    746         if (es.hadException())
    747             return 0;
    748         m_end = m_start;
    749     }
    750 
    751     originalStart.clear();
    752     originalEnd.clear();
    753 
    754     // Now add leftContents, stuff in between, and rightContents to the fragment
    755     // (or just delete the stuff in between)
    756 
    757     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
    758         fragment->appendChild(leftContents, es);
    759 
    760     if (processStart) {
    761         NodeVector nodes;
    762         for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibling())
    763             nodes.append(n);
    764         processNodes(action, nodes, commonRoot, fragment, es);
    765     }
    766 
    767     if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
    768         fragment->appendChild(rightContents, es);
    769 
    770     return fragment.release();
    771 }
    772 
    773 static inline void deleteCharacterData(PassRefPtr<CharacterData> data, unsigned startOffset, unsigned endOffset, ExceptionState& es)
    774 {
    775     if (data->length() - endOffset)
    776         data->deleteData(endOffset, data->length() - endOffset, es);
    777     if (startOffset)
    778         data->deleteData(0, startOffset, es);
    779 }
    780 
    781 PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRefPtr<DocumentFragment> fragment,
    782     Node* container, unsigned startOffset, unsigned endOffset, ExceptionState& es)
    783 {
    784     ASSERT(container);
    785     ASSERT(startOffset <= endOffset);
    786 
    787     // This switch statement must be consistent with that of lengthOfContentsInNode.
    788     RefPtr<Node> result;
    789     switch (container->nodeType()) {
    790     case Node::TEXT_NODE:
    791     case Node::CDATA_SECTION_NODE:
    792     case Node::COMMENT_NODE:
    793         ASSERT(endOffset <= static_cast<CharacterData*>(container)->length());
    794         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    795             RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(container->cloneNode(true));
    796             deleteCharacterData(c, startOffset, endOffset, es);
    797             if (fragment) {
    798                 result = fragment;
    799                 result->appendChild(c.release(), es);
    800             } else
    801                 result = c.release();
    802         }
    803         if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
    804             static_cast<CharacterData*>(container)->deleteData(startOffset, endOffset - startOffset, es);
    805         break;
    806     case Node::PROCESSING_INSTRUCTION_NODE:
    807         ASSERT(endOffset <= static_cast<ProcessingInstruction*>(container)->data().length());
    808         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    809             RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(container->cloneNode(true));
    810             c->setData(c->data().substring(startOffset, endOffset - startOffset));
    811             if (fragment) {
    812                 result = fragment;
    813                 result->appendChild(c.release(), es);
    814             } else
    815                 result = c.release();
    816         }
    817         if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
    818             ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(container);
    819             String data(pi->data());
    820             data.remove(startOffset, endOffset - startOffset);
    821             pi->setData(data);
    822         }
    823         break;
    824     case Node::ELEMENT_NODE:
    825     case Node::ATTRIBUTE_NODE:
    826     case Node::ENTITY_NODE:
    827     case Node::DOCUMENT_NODE:
    828     case Node::DOCUMENT_TYPE_NODE:
    829     case Node::DOCUMENT_FRAGMENT_NODE:
    830     case Node::NOTATION_NODE:
    831     case Node::XPATH_NAMESPACE_NODE:
    832         // FIXME: Should we assert that some nodes never appear here?
    833         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    834             if (fragment)
    835                 result = fragment;
    836             else
    837                 result = container->cloneNode(false);
    838         }
    839 
    840         Node* n = container->firstChild();
    841         Vector<RefPtr<Node> > nodes;
    842         for (unsigned i = startOffset; n && i; i--)
    843             n = n->nextSibling();
    844         for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibling())
    845             nodes.append(n);
    846 
    847         processNodes(action, nodes, container, result, es);
    848         break;
    849     }
    850 
    851     return result.release();
    852 }
    853 
    854 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionState& es)
    855 {
    856     for (unsigned i = 0; i < nodes.size(); i++) {
    857         switch (action) {
    858         case DELETE_CONTENTS:
    859             oldContainer->removeChild(nodes[i].get(), es);
    860             break;
    861         case EXTRACT_CONTENTS:
    862             newContainer->appendChild(nodes[i].release(), es); // will remove n from its parent
    863             break;
    864         case CLONE_CONTENTS:
    865             newContainer->appendChild(nodes[i]->cloneNode(true), es);
    866             break;
    867         }
    868     }
    869 }
    870 
    871 PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedContainer, Node* commonRoot, ExceptionState& es)
    872 {
    873     typedef Vector<RefPtr<Node> > NodeVector;
    874 
    875     RefPtr<Node> clonedContainer = passedClonedContainer;
    876     Vector<RefPtr<Node> > ancestors;
    877     for (ContainerNode* n = container->parentNode(); n && n != commonRoot; n = n->parentNode())
    878         ancestors.append(n);
    879 
    880     RefPtr<Node> firstChildInAncestorToProcess = direction == ProcessContentsForward ? container->nextSibling() : container->previousSibling();
    881     for (Vector<RefPtr<Node> >::const_iterator it = ancestors.begin(); it != ancestors.end(); it++) {
    882         RefPtr<Node> ancestor = *it;
    883         if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
    884             if (RefPtr<Node> clonedAncestor = ancestor->cloneNode(false)) { // Might have been removed already during mutation event.
    885                 clonedAncestor->appendChild(clonedContainer, es);
    886                 clonedContainer = clonedAncestor;
    887             }
    888         }
    889 
    890         // Copy siblings of an ancestor of start/end containers
    891         // FIXME: This assertion may fail if DOM is modified during mutation event
    892         // FIXME: Share code with Range::processNodes
    893         ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->parentNode() == ancestor);
    894 
    895         NodeVector nodes;
    896         for (Node* child = firstChildInAncestorToProcess.get(); child;
    897             child = (direction == ProcessContentsForward) ? child->nextSibling() : child->previousSibling())
    898             nodes.append(child);
    899 
    900         for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) {
    901             Node* child = it->get();
    902             switch (action) {
    903             case DELETE_CONTENTS:
    904                 ancestor->removeChild(child, es);
    905                 break;
    906             case EXTRACT_CONTENTS: // will remove child from ancestor
    907                 if (direction == ProcessContentsForward)
    908                     clonedContainer->appendChild(child, es);
    909                 else
    910                     clonedContainer->insertBefore(child, clonedContainer->firstChild(), es);
    911                 break;
    912             case CLONE_CONTENTS:
    913                 if (direction == ProcessContentsForward)
    914                     clonedContainer->appendChild(child->cloneNode(true), es);
    915                 else
    916                     clonedContainer->insertBefore(child->cloneNode(true), clonedContainer->firstChild(), es);
    917                 break;
    918             }
    919         }
    920         firstChildInAncestorToProcess = direction == ProcessContentsForward ? ancestor->nextSibling() : ancestor->previousSibling();
    921     }
    922 
    923     return clonedContainer.release();
    924 }
    925 
    926 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionState& es)
    927 {
    928     checkDeleteExtract(es);
    929     if (es.hadException())
    930         return 0;
    931 
    932     return processContents(EXTRACT_CONTENTS, es);
    933 }
    934 
    935 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& es)
    936 {
    937     if (!m_start.container()) {
    938         es.throwDOMException(InvalidStateError);
    939         return 0;
    940     }
    941 
    942     return processContents(CLONE_CONTENTS, es);
    943 }
    944 
    945 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& es)
    946 {
    947     RefPtr<Node> newNode = prpNewNode;
    948 
    949     if (!m_start.container()) {
    950         es.throwDOMException(InvalidStateError);
    951         return;
    952     }
    953 
    954     if (!newNode) {
    955         es.throwDOMException(NotFoundError);
    956         return;
    957     }
    958 
    959     // HierarchyRequestError: Raised if the container of the start of the Range is of a type that
    960     // does not allow children of the type of newNode or if newNode is an ancestor of the container.
    961 
    962     // an extra one here - if a text node is going to split, it must have a parent to insert into
    963     bool startIsText = m_start.container()->isTextNode();
    964     if (startIsText && !m_start.container()->parentNode()) {
    965         es.throwDOMException(HierarchyRequestError);
    966         return;
    967     }
    968 
    969     // In the case where the container is a text node, we check against the container's parent, because
    970     // text nodes get split up upon insertion.
    971     Node* checkAgainst;
    972     if (startIsText)
    973         checkAgainst = m_start.container()->parentNode();
    974     else
    975         checkAgainst = m_start.container();
    976 
    977     Node::NodeType newNodeType = newNode->nodeType();
    978     int numNewChildren;
    979     if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE && !newNode->isShadowRoot()) {
    980         // check each child node, not the DocumentFragment itself
    981         numNewChildren = 0;
    982         for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) {
    983             if (!checkAgainst->childTypeAllowed(c->nodeType())) {
    984                 es.throwDOMException(HierarchyRequestError);
    985                 return;
    986             }
    987             ++numNewChildren;
    988         }
    989     } else {
    990         numNewChildren = 1;
    991         if (!checkAgainst->childTypeAllowed(newNodeType)) {
    992             es.throwDOMException(HierarchyRequestError);
    993             return;
    994         }
    995     }
    996 
    997     for (Node* n = m_start.container(); n; n = n->parentNode()) {
    998         if (n == newNode) {
    999             es.throwDOMException(HierarchyRequestError);
   1000             return;
   1001         }
   1002     }
   1003 
   1004     // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, ShadowRoot or Document node.
   1005     switch (newNodeType) {
   1006     case Node::ATTRIBUTE_NODE:
   1007     case Node::ENTITY_NODE:
   1008     case Node::NOTATION_NODE:
   1009     case Node::DOCUMENT_NODE:
   1010         es.throwDOMException(InvalidNodeTypeError);
   1011         return;
   1012     default:
   1013         if (newNode->isShadowRoot()) {
   1014             es.throwDOMException(InvalidNodeTypeError);
   1015             return;
   1016         }
   1017         break;
   1018     }
   1019 
   1020     EventQueueScope scope;
   1021     bool collapsed = m_start == m_end;
   1022     RefPtr<Node> container;
   1023     if (startIsText) {
   1024         container = m_start.container();
   1025         RefPtr<Text> newText = toText(container.get())->splitText(m_start.offset(), es);
   1026         if (es.hadException())
   1027             return;
   1028 
   1029         container = m_start.container();
   1030         container->parentNode()->insertBefore(newNode.release(), newText.get(), es);
   1031         if (es.hadException())
   1032             return;
   1033 
   1034         if (collapsed)
   1035             m_end.setToBeforeChild(newText.get());
   1036     } else {
   1037         RefPtr<Node> lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
   1038         if (lastChild && lastChild == m_start.childBefore()) {
   1039             // The insertion will do nothing, but we need to extend the range to include
   1040             // the inserted nodes.
   1041             Node* firstChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->firstChild() : newNode.get();
   1042             ASSERT(firstChild);
   1043             m_start.setToBeforeChild(firstChild);
   1044             return;
   1045         }
   1046 
   1047         int startOffset = m_start.offset();
   1048         container = m_start.container();
   1049         container->insertBefore(newNode.release(), container->childNode(startOffset), es);
   1050         if (es.hadException())
   1051             return;
   1052 
   1053         if (collapsed && numNewChildren)
   1054             m_end.set(m_start.container(), startOffset + numNewChildren, lastChild.get());
   1055     }
   1056 }
   1057 
   1058 String Range::toString(ExceptionState& es) const
   1059 {
   1060     if (!m_start.container()) {
   1061         es.throwDOMException(InvalidStateError);
   1062         return String();
   1063     }
   1064 
   1065     StringBuilder builder;
   1066 
   1067     Node* pastLast = pastLastNode();
   1068     for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(n)) {
   1069         if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
   1070             String data = static_cast<CharacterData*>(n)->data();
   1071             int length = data.length();
   1072             int start = (n == m_start.container()) ? min(max(0, m_start.offset()), length) : 0;
   1073             int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length;
   1074             builder.append(data, start, end - start);
   1075         }
   1076     }
   1077 
   1078     return builder.toString();
   1079 }
   1080 
   1081 String Range::toHTML() const
   1082 {
   1083     return createMarkup(this);
   1084 }
   1085 
   1086 String Range::text() const
   1087 {
   1088     if (!m_start.container())
   1089         return String();
   1090 
   1091     // We need to update layout, since plainText uses line boxes in the render tree.
   1092     // FIXME: As with innerText, we'd like this to work even if there are no render objects.
   1093     m_start.container()->document()->updateLayout();
   1094 
   1095     return plainText(this);
   1096 }
   1097 
   1098 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionState& es)
   1099 {
   1100     if (!m_start.container()) {
   1101         es.throwDOMException(InvalidStateError);
   1102         return 0;
   1103     }
   1104 
   1105     Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
   1106     if (!element || !element->isHTMLElement()) {
   1107         es.throwDOMException(NotSupportedError);
   1108         return 0;
   1109     }
   1110 
   1111     RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, es);
   1112     if (!fragment)
   1113         return 0;
   1114 
   1115     return fragment.release();
   1116 }
   1117 
   1118 
   1119 void Range::detach(ExceptionState& es)
   1120 {
   1121     // Check first to see if we've already detached:
   1122     if (!m_start.container()) {
   1123         es.throwDOMException(InvalidStateError);
   1124         return;
   1125     }
   1126 
   1127     m_ownerDocument->detachRange(this);
   1128 
   1129     m_start.clear();
   1130     m_end.clear();
   1131 }
   1132 
   1133 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& es) const
   1134 {
   1135     switch (n->nodeType()) {
   1136         case Node::DOCUMENT_TYPE_NODE:
   1137         case Node::ENTITY_NODE:
   1138         case Node::NOTATION_NODE:
   1139             es.throwDOMException(InvalidNodeTypeError);
   1140             return 0;
   1141         case Node::CDATA_SECTION_NODE:
   1142         case Node::COMMENT_NODE:
   1143         case Node::TEXT_NODE:
   1144             if (static_cast<unsigned>(offset) > static_cast<CharacterData*>(n)->length())
   1145                 es.throwDOMException(IndexSizeError);
   1146             return 0;
   1147         case Node::PROCESSING_INSTRUCTION_NODE:
   1148             if (static_cast<unsigned>(offset) > static_cast<ProcessingInstruction*>(n)->data().length())
   1149                 es.throwDOMException(IndexSizeError);
   1150             return 0;
   1151         case Node::ATTRIBUTE_NODE:
   1152         case Node::DOCUMENT_FRAGMENT_NODE:
   1153         case Node::DOCUMENT_NODE:
   1154         case Node::ELEMENT_NODE:
   1155         case Node::XPATH_NAMESPACE_NODE: {
   1156             if (!offset)
   1157                 return 0;
   1158             Node* childBefore = n->childNode(offset - 1);
   1159             if (!childBefore)
   1160                 es.throwDOMException(IndexSizeError);
   1161             return childBefore;
   1162         }
   1163     }
   1164     ASSERT_NOT_REACHED();
   1165     return 0;
   1166 }
   1167 
   1168 void Range::checkNodeBA(Node* n, ExceptionState& es) const
   1169 {
   1170     // InvalidNodeTypeError: Raised if the root container of refNode is not an
   1171     // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG shadow DOM tree,
   1172     // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation node.
   1173 
   1174     switch (n->nodeType()) {
   1175         case Node::ATTRIBUTE_NODE:
   1176         case Node::DOCUMENT_FRAGMENT_NODE:
   1177         case Node::DOCUMENT_NODE:
   1178         case Node::ENTITY_NODE:
   1179         case Node::NOTATION_NODE:
   1180             es.throwDOMException(InvalidNodeTypeError);
   1181             return;
   1182         case Node::CDATA_SECTION_NODE:
   1183         case Node::COMMENT_NODE:
   1184         case Node::DOCUMENT_TYPE_NODE:
   1185         case Node::ELEMENT_NODE:
   1186         case Node::PROCESSING_INSTRUCTION_NODE:
   1187         case Node::TEXT_NODE:
   1188         case Node::XPATH_NAMESPACE_NODE:
   1189             break;
   1190     }
   1191 
   1192     Node* root = n;
   1193     while (ContainerNode* parent = root->parentNode())
   1194         root = parent;
   1195 
   1196     switch (root->nodeType()) {
   1197         case Node::ATTRIBUTE_NODE:
   1198         case Node::DOCUMENT_NODE:
   1199         case Node::DOCUMENT_FRAGMENT_NODE:
   1200             break;
   1201         case Node::CDATA_SECTION_NODE:
   1202         case Node::COMMENT_NODE:
   1203         case Node::DOCUMENT_TYPE_NODE:
   1204         case Node::ELEMENT_NODE:
   1205         case Node::ENTITY_NODE:
   1206         case Node::NOTATION_NODE:
   1207         case Node::PROCESSING_INSTRUCTION_NODE:
   1208         case Node::TEXT_NODE:
   1209         case Node::XPATH_NAMESPACE_NODE:
   1210             es.throwDOMException(InvalidNodeTypeError);
   1211             return;
   1212     }
   1213 }
   1214 
   1215 PassRefPtr<Range> Range::cloneRange(ExceptionState& es) const
   1216 {
   1217     if (!m_start.container()) {
   1218         es.throwDOMException(InvalidStateError);
   1219         return 0;
   1220     }
   1221 
   1222     return Range::create(m_ownerDocument, m_start.container(), m_start.offset(), m_end.container(), m_end.offset());
   1223 }
   1224 
   1225 void Range::setStartAfter(Node* refNode, ExceptionState& es)
   1226 {
   1227     if (!m_start.container()) {
   1228         es.throwDOMException(InvalidStateError);
   1229         return;
   1230     }
   1231 
   1232     if (!refNode) {
   1233         es.throwDOMException(NotFoundError);
   1234         return;
   1235     }
   1236 
   1237     checkNodeBA(refNode, es);
   1238     if (es.hadException())
   1239         return;
   1240 
   1241     setStart(refNode->parentNode(), refNode->nodeIndex() + 1, es);
   1242 }
   1243 
   1244 void Range::setEndBefore(Node* refNode, ExceptionState& es)
   1245 {
   1246     if (!m_start.container()) {
   1247         es.throwDOMException(InvalidStateError);
   1248         return;
   1249     }
   1250 
   1251     if (!refNode) {
   1252         es.throwDOMException(NotFoundError);
   1253         return;
   1254     }
   1255 
   1256     checkNodeBA(refNode, es);
   1257     if (es.hadException())
   1258         return;
   1259 
   1260     setEnd(refNode->parentNode(), refNode->nodeIndex(), es);
   1261 }
   1262 
   1263 void Range::setEndAfter(Node* refNode, ExceptionState& es)
   1264 {
   1265     if (!m_start.container()) {
   1266         es.throwDOMException(InvalidStateError);
   1267         return;
   1268     }
   1269 
   1270     if (!refNode) {
   1271         es.throwDOMException(NotFoundError);
   1272         return;
   1273     }
   1274 
   1275     checkNodeBA(refNode, es);
   1276     if (es.hadException())
   1277         return;
   1278 
   1279     setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, es);
   1280 }
   1281 
   1282 void Range::selectNode(Node* refNode, ExceptionState& es)
   1283 {
   1284     if (!m_start.container()) {
   1285         es.throwDOMException(InvalidStateError);
   1286         return;
   1287     }
   1288 
   1289     if (!refNode) {
   1290         es.throwDOMException(NotFoundError);
   1291         return;
   1292     }
   1293 
   1294     // InvalidNodeTypeError: Raised if an ancestor of refNode is an Entity, Notation or
   1295     // DocumentType node or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation
   1296     // node.
   1297     for (ContainerNode* anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
   1298         switch (anc->nodeType()) {
   1299             case Node::ATTRIBUTE_NODE:
   1300             case Node::CDATA_SECTION_NODE:
   1301             case Node::COMMENT_NODE:
   1302             case Node::DOCUMENT_FRAGMENT_NODE:
   1303             case Node::DOCUMENT_NODE:
   1304             case Node::ELEMENT_NODE:
   1305             case Node::PROCESSING_INSTRUCTION_NODE:
   1306             case Node::TEXT_NODE:
   1307             case Node::XPATH_NAMESPACE_NODE:
   1308                 break;
   1309             case Node::DOCUMENT_TYPE_NODE:
   1310             case Node::ENTITY_NODE:
   1311             case Node::NOTATION_NODE:
   1312                 es.throwDOMException(InvalidNodeTypeError);
   1313                 return;
   1314         }
   1315     }
   1316 
   1317     switch (refNode->nodeType()) {
   1318         case Node::CDATA_SECTION_NODE:
   1319         case Node::COMMENT_NODE:
   1320         case Node::DOCUMENT_TYPE_NODE:
   1321         case Node::ELEMENT_NODE:
   1322         case Node::PROCESSING_INSTRUCTION_NODE:
   1323         case Node::TEXT_NODE:
   1324         case Node::XPATH_NAMESPACE_NODE:
   1325             break;
   1326         case Node::ATTRIBUTE_NODE:
   1327         case Node::DOCUMENT_FRAGMENT_NODE:
   1328         case Node::DOCUMENT_NODE:
   1329         case Node::ENTITY_NODE:
   1330         case Node::NOTATION_NODE:
   1331             es.throwDOMException(InvalidNodeTypeError);
   1332             return;
   1333     }
   1334 
   1335     if (m_ownerDocument != refNode->document())
   1336         setDocument(refNode->document());
   1337 
   1338     setStartBefore(refNode, es);
   1339     if (es.hadException())
   1340         return;
   1341     setEndAfter(refNode, es);
   1342 }
   1343 
   1344 void Range::selectNodeContents(Node* refNode, ExceptionState& es)
   1345 {
   1346     if (!m_start.container()) {
   1347         es.throwDOMException(InvalidStateError);
   1348         return;
   1349     }
   1350 
   1351     if (!refNode) {
   1352         es.throwDOMException(NotFoundError);
   1353         return;
   1354     }
   1355 
   1356     // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an Entity, Notation
   1357     // or DocumentType node.
   1358     for (Node* n = refNode; n; n = n->parentNode()) {
   1359         switch (n->nodeType()) {
   1360             case Node::ATTRIBUTE_NODE:
   1361             case Node::CDATA_SECTION_NODE:
   1362             case Node::COMMENT_NODE:
   1363             case Node::DOCUMENT_FRAGMENT_NODE:
   1364             case Node::DOCUMENT_NODE:
   1365             case Node::ELEMENT_NODE:
   1366             case Node::PROCESSING_INSTRUCTION_NODE:
   1367             case Node::TEXT_NODE:
   1368             case Node::XPATH_NAMESPACE_NODE:
   1369                 break;
   1370             case Node::DOCUMENT_TYPE_NODE:
   1371             case Node::ENTITY_NODE:
   1372             case Node::NOTATION_NODE:
   1373                 es.throwDOMException(InvalidNodeTypeError);
   1374                 return;
   1375         }
   1376     }
   1377 
   1378     if (m_ownerDocument != refNode->document())
   1379         setDocument(refNode->document());
   1380 
   1381     m_start.setToStartOfNode(refNode);
   1382     m_end.setToEndOfNode(refNode);
   1383 }
   1384 
   1385 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& es)
   1386 {
   1387     RefPtr<Node> newParent = passNewParent;
   1388 
   1389     if (!m_start.container()) {
   1390         es.throwDOMException(InvalidStateError);
   1391         return;
   1392     }
   1393 
   1394     if (!newParent) {
   1395         es.throwDOMException(NotFoundError);
   1396         return;
   1397     }
   1398 
   1399     // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, Notation,
   1400     // Document, or DocumentFragment node.
   1401     switch (newParent->nodeType()) {
   1402         case Node::ATTRIBUTE_NODE:
   1403         case Node::DOCUMENT_FRAGMENT_NODE:
   1404         case Node::DOCUMENT_NODE:
   1405         case Node::DOCUMENT_TYPE_NODE:
   1406         case Node::ENTITY_NODE:
   1407         case Node::NOTATION_NODE:
   1408             es.throwDOMException(InvalidNodeTypeError);
   1409             return;
   1410         case Node::CDATA_SECTION_NODE:
   1411         case Node::COMMENT_NODE:
   1412         case Node::ELEMENT_NODE:
   1413         case Node::PROCESSING_INSTRUCTION_NODE:
   1414         case Node::TEXT_NODE:
   1415         case Node::XPATH_NAMESPACE_NODE:
   1416             break;
   1417     }
   1418 
   1419     // Raise a HierarchyRequestError if m_start.container() doesn't accept children like newParent.
   1420     Node* parentOfNewParent = m_start.container();
   1421 
   1422     // If m_start.container() is a character data node, it will be split and it will be its parent that will
   1423     // need to accept newParent (or in the case of a comment, it logically "would" be inserted into the parent,
   1424     // although this will fail below for another reason).
   1425     if (parentOfNewParent->isCharacterDataNode())
   1426         parentOfNewParent = parentOfNewParent->parentNode();
   1427     if (!parentOfNewParent || !parentOfNewParent->childTypeAllowed(newParent->nodeType())) {
   1428         es.throwDOMException(HierarchyRequestError);
   1429         return;
   1430     }
   1431 
   1432     if (newParent->contains(m_start.container())) {
   1433         es.throwDOMException(HierarchyRequestError);
   1434         return;
   1435     }
   1436 
   1437     // FIXME: Do we need a check if the node would end up with a child node of a type not
   1438     // allowed by the type of node?
   1439 
   1440     // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text node.
   1441     Node* startNonTextContainer = m_start.container();
   1442     if (startNonTextContainer->nodeType() == Node::TEXT_NODE)
   1443         startNonTextContainer = startNonTextContainer->parentNode();
   1444     Node* endNonTextContainer = m_end.container();
   1445     if (endNonTextContainer->nodeType() == Node::TEXT_NODE)
   1446         endNonTextContainer = endNonTextContainer->parentNode();
   1447     if (startNonTextContainer != endNonTextContainer) {
   1448         es.throwDOMException(InvalidStateError);
   1449         return;
   1450     }
   1451 
   1452     while (Node* n = newParent->firstChild()) {
   1453         toContainerNode(newParent.get())->removeChild(n, es);
   1454         if (es.hadException())
   1455             return;
   1456     }
   1457     RefPtr<DocumentFragment> fragment = extractContents(es);
   1458     if (es.hadException())
   1459         return;
   1460     insertNode(newParent, es);
   1461     if (es.hadException())
   1462         return;
   1463     newParent->appendChild(fragment.release(), es);
   1464     if (es.hadException())
   1465         return;
   1466     selectNode(newParent.get(), es);
   1467 }
   1468 
   1469 void Range::setStartBefore(Node* refNode, ExceptionState& es)
   1470 {
   1471     if (!m_start.container()) {
   1472         es.throwDOMException(InvalidStateError);
   1473         return;
   1474     }
   1475 
   1476     if (!refNode) {
   1477         es.throwDOMException(NotFoundError);
   1478         return;
   1479     }
   1480 
   1481     checkNodeBA(refNode, es);
   1482     if (es.hadException())
   1483         return;
   1484 
   1485     setStart(refNode->parentNode(), refNode->nodeIndex(), es);
   1486 }
   1487 
   1488 void Range::checkDeleteExtract(ExceptionState& es)
   1489 {
   1490     if (!m_start.container()) {
   1491         es.throwDOMException(InvalidStateError);
   1492         return;
   1493     }
   1494 
   1495     if (!commonAncestorContainer(es) || es.hadException())
   1496         return;
   1497 
   1498     Node* pastLast = pastLastNode();
   1499     for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(n)) {
   1500         if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
   1501             es.throwDOMException(HierarchyRequestError);
   1502             return;
   1503         }
   1504     }
   1505 }
   1506 
   1507 Node* Range::firstNode() const
   1508 {
   1509     if (!m_start.container())
   1510         return 0;
   1511     if (m_start.container()->offsetInCharacters())
   1512         return m_start.container();
   1513     if (Node* child = m_start.container()->childNode(m_start.offset()))
   1514         return child;
   1515     if (!m_start.offset())
   1516         return m_start.container();
   1517     return NodeTraversal::nextSkippingChildren(m_start.container());
   1518 }
   1519 
   1520 ShadowRoot* Range::shadowRoot() const
   1521 {
   1522     return startContainer() ? startContainer()->containingShadowRoot() : 0;
   1523 }
   1524 
   1525 Node* Range::pastLastNode() const
   1526 {
   1527     if (!m_start.container() || !m_end.container())
   1528         return 0;
   1529     if (m_end.container()->offsetInCharacters())
   1530         return NodeTraversal::nextSkippingChildren(m_end.container());
   1531     if (Node* child = m_end.container()->childNode(m_end.offset()))
   1532         return child;
   1533     return NodeTraversal::nextSkippingChildren(m_end.container());
   1534 }
   1535 
   1536 IntRect Range::boundingBox() const
   1537 {
   1538     IntRect result;
   1539     Vector<IntRect> rects;
   1540     textRects(rects);
   1541     const size_t n = rects.size();
   1542     for (size_t i = 0; i < n; ++i)
   1543         result.unite(rects[i]);
   1544     return result;
   1545 }
   1546 
   1547 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFixedPosition* inFixed) const
   1548 {
   1549     Node* startContainer = m_start.container();
   1550     Node* endContainer = m_end.container();
   1551 
   1552     if (!startContainer || !endContainer) {
   1553         if (inFixed)
   1554             *inFixed = NotFixedPosition;
   1555         return;
   1556     }
   1557 
   1558     bool allFixed = true;
   1559     bool someFixed = false;
   1560 
   1561     Node* stopNode = pastLastNode();
   1562     for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
   1563         RenderObject* r = node->renderer();
   1564         if (!r || !r->isText())
   1565             continue;
   1566         RenderText* renderText = toRenderText(r);
   1567         int startOffset = node == startContainer ? m_start.offset() : 0;
   1568         int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
   1569         bool isFixed = false;
   1570         renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSelectionHeight, &isFixed);
   1571         allFixed &= isFixed;
   1572         someFixed |= isFixed;
   1573     }
   1574 
   1575     if (inFixed)
   1576         *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixedPosition : NotFixedPosition);
   1577 }
   1578 
   1579 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeInFixedPosition* inFixed) const
   1580 {
   1581     Node* startContainer = m_start.container();
   1582     Node* endContainer = m_end.container();
   1583 
   1584     if (!startContainer || !endContainer) {
   1585         if (inFixed)
   1586             *inFixed = NotFixedPosition;
   1587         return;
   1588     }
   1589 
   1590     bool allFixed = true;
   1591     bool someFixed = false;
   1592 
   1593     Node* stopNode = pastLastNode();
   1594     for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
   1595         RenderObject* r = node->renderer();
   1596         if (!r || !r->isText())
   1597             continue;
   1598         RenderText* renderText = toRenderText(r);
   1599         int startOffset = node == startContainer ? m_start.offset() : 0;
   1600         int endOffset = node == endContainer ? m_end.offset() : numeric_limits<int>::max();
   1601         bool isFixed = false;
   1602         renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight, &isFixed);
   1603         allFixed &= isFixed;
   1604         someFixed |= isFixed;
   1605     }
   1606 
   1607     if (inFixed)
   1608         *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixedPosition : NotFixedPosition);
   1609 }
   1610 
   1611 #ifndef NDEBUG
   1612 void Range::formatForDebugger(char* buffer, unsigned length) const
   1613 {
   1614     StringBuilder result;
   1615     String s;
   1616 
   1617     if (!m_start.container() || !m_end.container())
   1618         result.appendLiteral("<empty>");
   1619     else {
   1620         const int FormatBufferSize = 1024;
   1621         char s[FormatBufferSize];
   1622         result.appendLiteral("from offset ");
   1623         result.appendNumber(m_start.offset());
   1624         result.appendLiteral(" of ");
   1625         m_start.container()->formatForDebugger(s, FormatBufferSize);
   1626         result.append(s);
   1627         result.appendLiteral(" to offset ");
   1628         result.appendNumber(m_end.offset());
   1629         result.appendLiteral(" of ");
   1630         m_end.container()->formatForDebugger(s, FormatBufferSize);
   1631         result.append(s);
   1632     }
   1633 
   1634     strncpy(buffer, result.toString().utf8().data(), length - 1);
   1635 }
   1636 #endif
   1637 
   1638 bool areRangesEqual(const Range* a, const Range* b)
   1639 {
   1640     if (a == b)
   1641         return true;
   1642     if (!a || !b)
   1643         return false;
   1644     return a->startPosition() == b->startPosition() && a->endPosition() == b->endPosition();
   1645 }
   1646 
   1647 PassRefPtr<Range> rangeOfContents(Node* node)
   1648 {
   1649     ASSERT(node);
   1650     RefPtr<Range> range = Range::create(node->document());
   1651     range->selectNodeContents(node, IGNORE_EXCEPTION);
   1652     return range.release();
   1653 }
   1654 
   1655 int Range::maxStartOffset() const
   1656 {
   1657     if (!m_start.container())
   1658         return 0;
   1659     if (!m_start.container()->offsetInCharacters())
   1660         return m_start.container()->childNodeCount();
   1661     return m_start.container()->maxCharacterOffset();
   1662 }
   1663 
   1664 int Range::maxEndOffset() const
   1665 {
   1666     if (!m_end.container())
   1667         return 0;
   1668     if (!m_end.container()->offsetInCharacters())
   1669         return m_end.container()->childNodeCount();
   1670     return m_end.container()->maxCharacterOffset();
   1671 }
   1672 
   1673 static inline void boundaryNodeChildrenChanged(RangeBoundaryPoint& boundary, ContainerNode* container)
   1674 {
   1675     if (!boundary.childBefore())
   1676         return;
   1677     if (boundary.container() != container)
   1678         return;
   1679     boundary.invalidateOffset();
   1680 }
   1681 
   1682 void Range::nodeChildrenChanged(ContainerNode* container)
   1683 {
   1684     ASSERT(container);
   1685     ASSERT(container->document() == m_ownerDocument);
   1686     boundaryNodeChildrenChanged(m_start, container);
   1687     boundaryNodeChildrenChanged(m_end, container);
   1688 }
   1689 
   1690 static inline void boundaryNodeChildrenWillBeRemoved(RangeBoundaryPoint& boundary, ContainerNode* container)
   1691 {
   1692     for (Node* nodeToBeRemoved = container->firstChild(); nodeToBeRemoved; nodeToBeRemoved = nodeToBeRemoved->nextSibling()) {
   1693         if (boundary.childBefore() == nodeToBeRemoved) {
   1694             boundary.setToStartOfNode(container);
   1695             return;
   1696         }
   1697 
   1698         for (Node* n = boundary.container(); n; n = n->parentNode()) {
   1699             if (n == nodeToBeRemoved) {
   1700                 boundary.setToStartOfNode(container);
   1701                 return;
   1702             }
   1703         }
   1704     }
   1705 }
   1706 
   1707 void Range::nodeChildrenWillBeRemoved(ContainerNode* container)
   1708 {
   1709     ASSERT(container);
   1710     ASSERT(container->document() == m_ownerDocument);
   1711     boundaryNodeChildrenWillBeRemoved(m_start, container);
   1712     boundaryNodeChildrenWillBeRemoved(m_end, container);
   1713 }
   1714 
   1715 static inline void boundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, Node* nodeToBeRemoved)
   1716 {
   1717     if (boundary.childBefore() == nodeToBeRemoved) {
   1718         boundary.childBeforeWillBeRemoved();
   1719         return;
   1720     }
   1721 
   1722     for (Node* n = boundary.container(); n; n = n->parentNode()) {
   1723         if (n == nodeToBeRemoved) {
   1724             boundary.setToBeforeChild(nodeToBeRemoved);
   1725             return;
   1726         }
   1727     }
   1728 }
   1729 
   1730 void Range::nodeWillBeRemoved(Node* node)
   1731 {
   1732     ASSERT(node);
   1733     ASSERT(node->document() == m_ownerDocument);
   1734     ASSERT(node != m_ownerDocument);
   1735     ASSERT(node->parentNode());
   1736     boundaryNodeWillBeRemoved(m_start, node);
   1737     boundaryNodeWillBeRemoved(m_end, node);
   1738 }
   1739 
   1740 static inline void boundaryTextInserted(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
   1741 {
   1742     if (boundary.container() != text)
   1743         return;
   1744     unsigned boundaryOffset = boundary.offset();
   1745     if (offset >= boundaryOffset)
   1746         return;
   1747     boundary.setOffset(boundaryOffset + length);
   1748 }
   1749 
   1750 void Range::textInserted(Node* text, unsigned offset, unsigned length)
   1751 {
   1752     ASSERT(text);
   1753     ASSERT(text->document() == m_ownerDocument);
   1754     boundaryTextInserted(m_start, text, offset, length);
   1755     boundaryTextInserted(m_end, text, offset, length);
   1756 }
   1757 
   1758 static inline void boundaryTextRemoved(RangeBoundaryPoint& boundary, Node* text, unsigned offset, unsigned length)
   1759 {
   1760     if (boundary.container() != text)
   1761         return;
   1762     unsigned boundaryOffset = boundary.offset();
   1763     if (offset >= boundaryOffset)
   1764         return;
   1765     if (offset + length >= boundaryOffset)
   1766         boundary.setOffset(offset);
   1767     else
   1768         boundary.setOffset(boundaryOffset - length);
   1769 }
   1770 
   1771 void Range::textRemoved(Node* text, unsigned offset, unsigned length)
   1772 {
   1773     ASSERT(text);
   1774     ASSERT(text->document() == m_ownerDocument);
   1775     boundaryTextRemoved(m_start, text, offset, length);
   1776     boundaryTextRemoved(m_end, text, offset, length);
   1777 }
   1778 
   1779 static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, NodeWithIndex& oldNode, unsigned offset)
   1780 {
   1781     if (boundary.container() == oldNode.node())
   1782         boundary.set(oldNode.node()->previousSibling(), boundary.offset() + offset, 0);
   1783     else if (boundary.container() == oldNode.node()->parentNode() && boundary.offset() == oldNode.index())
   1784         boundary.set(oldNode.node()->previousSibling(), offset, 0);
   1785 }
   1786 
   1787 void Range::textNodesMerged(NodeWithIndex& oldNode, unsigned offset)
   1788 {
   1789     ASSERT(oldNode.node());
   1790     ASSERT(oldNode.node()->document() == m_ownerDocument);
   1791     ASSERT(oldNode.node()->parentNode());
   1792     ASSERT(oldNode.node()->isTextNode());
   1793     ASSERT(oldNode.node()->previousSibling());
   1794     ASSERT(oldNode.node()->previousSibling()->isTextNode());
   1795     boundaryTextNodesMerged(m_start, oldNode, offset);
   1796     boundaryTextNodesMerged(m_end, oldNode, offset);
   1797 }
   1798 
   1799 static inline void boundaryTextNodesSplit(RangeBoundaryPoint& boundary, Text* oldNode)
   1800 {
   1801     if (boundary.container() != oldNode)
   1802         return;
   1803     unsigned boundaryOffset = boundary.offset();
   1804     if (boundaryOffset <= oldNode->length())
   1805         return;
   1806     boundary.set(oldNode->nextSibling(), boundaryOffset - oldNode->length(), 0);
   1807 }
   1808 
   1809 void Range::textNodeSplit(Text* oldNode)
   1810 {
   1811     ASSERT(oldNode);
   1812     ASSERT(oldNode->document() == m_ownerDocument);
   1813     ASSERT(oldNode->parentNode());
   1814     ASSERT(oldNode->isTextNode());
   1815     ASSERT(oldNode->nextSibling());
   1816     ASSERT(oldNode->nextSibling()->isTextNode());
   1817     boundaryTextNodesSplit(m_start, oldNode);
   1818     boundaryTextNodesSplit(m_end, oldNode);
   1819 }
   1820 
   1821 void Range::expand(const String& unit, ExceptionState& es)
   1822 {
   1823     VisiblePosition start(startPosition());
   1824     VisiblePosition end(endPosition());
   1825     if (unit == "word") {
   1826         start = startOfWord(start);
   1827         end = endOfWord(end);
   1828     } else if (unit == "sentence") {
   1829         start = startOfSentence(start);
   1830         end = endOfSentence(end);
   1831     } else if (unit == "block") {
   1832         start = startOfParagraph(start);
   1833         end = endOfParagraph(end);
   1834     } else if (unit == "document") {
   1835         start = startOfDocument(start);
   1836         end = endOfDocument(end);
   1837     } else
   1838         return;
   1839     setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), es);
   1840     setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), es);
   1841 }
   1842 
   1843 PassRefPtr<ClientRectList> Range::getClientRects() const
   1844 {
   1845     if (!m_start.container())
   1846         return ClientRectList::create();
   1847 
   1848     m_ownerDocument->updateLayoutIgnorePendingStylesheets();
   1849 
   1850     Vector<FloatQuad> quads;
   1851     getBorderAndTextQuads(quads);
   1852 
   1853     return ClientRectList::create(quads);
   1854 }
   1855 
   1856 PassRefPtr<ClientRect> Range::getBoundingClientRect() const
   1857 {
   1858     return ClientRect::create(boundingRect());
   1859 }
   1860 
   1861 void Range::getBorderAndTextQuads(Vector<FloatQuad>& quads) const
   1862 {
   1863     Node* startContainer = m_start.container();
   1864     Node* endContainer = m_end.container();
   1865     Node* stopNode = pastLastNode();
   1866 
   1867     HashSet<Node*> nodeSet;
   1868     for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
   1869         if (node->isElementNode())
   1870             nodeSet.add(node);
   1871     }
   1872 
   1873     for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next(node)) {
   1874         if (node->isElementNode()) {
   1875             if (!nodeSet.contains(node->parentNode())) {
   1876                 if (RenderBoxModelObject* renderBoxModelObject = toElement(node)->renderBoxModelObject()) {
   1877                     Vector<FloatQuad> elementQuads;
   1878                     renderBoxModelObject->absoluteQuads(elementQuads);
   1879                     m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(elementQuads, renderBoxModelObject);
   1880 
   1881                     quads.append(elementQuads);
   1882                 }
   1883             }
   1884         } else if (node->isTextNode()) {
   1885             if (RenderObject* renderer = toText(node)->renderer()) {
   1886                 RenderText* renderText = toRenderText(renderer);
   1887                 int startOffset = (node == startContainer) ? m_start.offset() : 0;
   1888                 int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX;
   1889 
   1890                 Vector<FloatQuad> textQuads;
   1891                 renderText->absoluteQuadsForRange(textQuads, startOffset, endOffset);
   1892                 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, renderText);
   1893 
   1894                 quads.append(textQuads);
   1895             }
   1896         }
   1897     }
   1898 }
   1899 
   1900 FloatRect Range::boundingRect() const
   1901 {
   1902     if (!m_start.container())
   1903         return FloatRect();
   1904 
   1905     m_ownerDocument->updateLayoutIgnorePendingStylesheets();
   1906 
   1907     Vector<FloatQuad> quads;
   1908     getBorderAndTextQuads(quads);
   1909     if (quads.isEmpty())
   1910         return FloatRect();
   1911 
   1912     FloatRect result;
   1913     for (size_t i = 0; i < quads.size(); ++i)
   1914         result.unite(quads[i].boundingBox());
   1915 
   1916     return result;
   1917 }
   1918 
   1919 } // namespace WebCore
   1920 
   1921 #ifndef NDEBUG
   1922 
   1923 void showTree(const WebCore::Range* range)
   1924 {
   1925     if (range && range->boundaryPointsValid()) {
   1926         range->startContainer()->showTreeAndMark(range->startContainer(), "S", range->endContainer(), "E");
   1927         fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset(), range->endOffset());
   1928     }
   1929 }
   1930 
   1931 #endif
   1932