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