| OLD | NEW |
| 1 /* | 1 /* |
| 2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) | 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) |
| 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) | 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) |
| 5 * (C) 2001 Peter Kelly (pmk@post.com) | 5 * (C) 2001 Peter Kelly (pmk@post.com) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. |
| 7 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 7 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| 11 * License as published by the Free Software Foundation; either | 11 * License as published by the Free Software Foundation; either |
| 12 * version 2 of the License, or (at your option) any later version. | 12 * version 2 of the License, or (at your option) any later version. |
| 13 * | 13 * |
| 14 * This library is distributed in the hope that it will be useful, | 14 * This library is distributed in the hope that it will be useful, |
| 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 * Library General Public License for more details. | 17 * Library General Public License for more details. |
| 18 * | 18 * |
| 19 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 22 * Boston, MA 02110-1301, USA. | 22 * Boston, MA 02110-1301, USA. |
| 23 */ | 23 */ |
| 24 | 24 |
| 25 #include "sky/engine/config.h" | 25 #include "sky/engine/config.h" |
| 26 #include "sky/engine/core/dom/Range.h" | 26 #include "sky/engine/core/dom/Range.h" |
| 27 | 27 |
| 28 #include "sky/engine/bindings/core/v8/ExceptionState.h" | 28 #include "sky/engine/bindings2/exception_state.h" |
| 29 #include "sky/engine/core/dom/ClientRect.h" | 29 #include "sky/engine/core/dom/ClientRect.h" |
| 30 #include "sky/engine/core/dom/ClientRectList.h" | 30 #include "sky/engine/core/dom/ClientRectList.h" |
| 31 #include "sky/engine/core/dom/DocumentFragment.h" | 31 #include "sky/engine/core/dom/DocumentFragment.h" |
| 32 #include "sky/engine/core/dom/ExceptionCode.h" | 32 #include "sky/engine/core/dom/ExceptionCode.h" |
| 33 #include "sky/engine/core/dom/Node.h" | 33 #include "sky/engine/core/dom/Node.h" |
| 34 #include "sky/engine/core/dom/NodeTraversal.h" | 34 #include "sky/engine/core/dom/NodeTraversal.h" |
| 35 #include "sky/engine/core/dom/NodeWithIndex.h" | 35 #include "sky/engine/core/dom/NodeWithIndex.h" |
| 36 #include "sky/engine/core/dom/Text.h" | 36 #include "sky/engine/core/dom/Text.h" |
| 37 #include "sky/engine/core/editing/TextIterator.h" | 37 #include "sky/engine/core/editing/TextIterator.h" |
| 38 #include "sky/engine/core/editing/VisiblePosition.h" | 38 #include "sky/engine/core/editing/VisiblePosition.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 Node* startRootContainer = start.container(); | 144 Node* startRootContainer = start.container(); |
| 145 while (startRootContainer->parentNode()) | 145 while (startRootContainer->parentNode()) |
| 146 startRootContainer = startRootContainer->parentNode(); | 146 startRootContainer = startRootContainer->parentNode(); |
| 147 | 147 |
| 148 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin
ts(start, end, ASSERT_NO_EXCEPTION) > 0); | 148 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin
ts(start, end, ASSERT_NO_EXCEPTION) > 0); |
| 149 } | 149 } |
| 150 | 150 |
| 151 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep
tionState) | 151 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep
tionState) |
| 152 { | 152 { |
| 153 if (!refNode) { | 153 if (!refNode) { |
| 154 exceptionState.throwDOMException(NotFoundError, "The node provided was n
ull."); | 154 exceptionState.ThrowDOMException(NotFoundError, "The node provided was n
ull."); |
| 155 return; | 155 return; |
| 156 } | 156 } |
| 157 | 157 |
| 158 bool didMoveDocument = false; | 158 bool didMoveDocument = false; |
| 159 if (refNode->document() != m_ownerDocument) { | 159 if (refNode->document() != m_ownerDocument) { |
| 160 setDocument(refNode->document()); | 160 setDocument(refNode->document()); |
| 161 didMoveDocument = true; | 161 didMoveDocument = true; |
| 162 } | 162 } |
| 163 | 163 |
| 164 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); | 164 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); |
| 165 if (exceptionState.hadException()) | 165 if (exceptionState.had_exception()) |
| 166 return; | 166 return; |
| 167 | 167 |
| 168 m_start.set(refNode, offset, childNode); | 168 m_start.set(refNode, offset, childNode); |
| 169 | 169 |
| 170 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 170 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
| 171 collapse(true); | 171 collapse(true); |
| 172 } | 172 } |
| 173 | 173 |
| 174 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti
onState) | 174 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti
onState) |
| 175 { | 175 { |
| 176 if (!refNode) { | 176 if (!refNode) { |
| 177 exceptionState.throwDOMException(NotFoundError, "The node provided was n
ull."); | 177 exceptionState.ThrowDOMException(NotFoundError, "The node provided was n
ull."); |
| 178 return; | 178 return; |
| 179 } | 179 } |
| 180 | 180 |
| 181 bool didMoveDocument = false; | 181 bool didMoveDocument = false; |
| 182 if (refNode->document() != m_ownerDocument) { | 182 if (refNode->document() != m_ownerDocument) { |
| 183 setDocument(refNode->document()); | 183 setDocument(refNode->document()); |
| 184 didMoveDocument = true; | 184 didMoveDocument = true; |
| 185 } | 185 } |
| 186 | 186 |
| 187 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); | 187 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); |
| 188 if (exceptionState.hadException()) | 188 if (exceptionState.had_exception()) |
| 189 return; | 189 return; |
| 190 | 190 |
| 191 m_end.set(refNode, offset, childNode); | 191 m_end.set(refNode, offset, childNode); |
| 192 | 192 |
| 193 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 193 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
| 194 collapse(false); | 194 collapse(false); |
| 195 } | 195 } |
| 196 | 196 |
| 197 void Range::setStart(const Position& start, ExceptionState& exceptionState) | 197 void Range::setStart(const Position& start, ExceptionState& exceptionState) |
| 198 { | 198 { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 210 { | 210 { |
| 211 if (toStart) | 211 if (toStart) |
| 212 m_end = m_start; | 212 m_end = m_start; |
| 213 else | 213 else |
| 214 m_start = m_end; | 214 m_start = m_end; |
| 215 } | 215 } |
| 216 | 216 |
| 217 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS
tate) | 217 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS
tate) |
| 218 { | 218 { |
| 219 if (!refNode) { | 219 if (!refNode) { |
| 220 exceptionState.throwDOMException(HierarchyRequestError, "The node provid
ed was null."); | 220 exceptionState.ThrowDOMException(HierarchyRequestError, "The node provid
ed was null."); |
| 221 return false; | 221 return false; |
| 222 } | 222 } |
| 223 | 223 |
| 224 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ | 224 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ |
| 225 return false; | 225 return false; |
| 226 } | 226 } |
| 227 | 227 |
| 228 checkNodeWOffset(refNode, offset, exceptionState); | 228 checkNodeWOffset(refNode, offset, exceptionState); |
| 229 if (exceptionState.hadException()) | 229 if (exceptionState.had_exception()) |
| 230 return false; | 230 return false; |
| 231 | 231 |
| 232 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o
ffset(), exceptionState) >= 0 && !exceptionState.hadException() | 232 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o
ffset(), exceptionState) >= 0 && !exceptionState.had_exception() |
| 233 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse
t(), exceptionState) <= 0 && !exceptionState.hadException(); | 233 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse
t(), exceptionState) <= 0 && !exceptionState.had_exception(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt
ate) const | 236 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt
ate) const |
| 237 { | 237 { |
| 238 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint | 238 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint |
| 239 // This method returns -1, 0 or 1 depending on if the point described by the | 239 // This method returns -1, 0 or 1 depending on if the point described by the |
| 240 // refNode node and an offset within the node is before, same as, or after t
he range respectively. | 240 // refNode node and an offset within the node is before, same as, or after t
he range respectively. |
| 241 | 241 |
| 242 if (!refNode->inActiveDocument()) { | 242 if (!refNode->inActiveDocument()) { |
| 243 exceptionState.throwDOMException(WrongDocumentError, "The node provided
is not in an active document."); | 243 exceptionState.ThrowDOMException(WrongDocumentError, "The node provided
is not in an active document."); |
| 244 return 0; | 244 return 0; |
| 245 } | 245 } |
| 246 | 246 |
| 247 if (refNode->document() != m_ownerDocument) { | 247 if (refNode->document() != m_ownerDocument) { |
| 248 exceptionState.throwDOMException(WrongDocumentError, "The node provided
is not in this Range's Document."); | 248 exceptionState.ThrowDOMException(WrongDocumentError, "The node provided
is not in this Range's Document."); |
| 249 return 0; | 249 return 0; |
| 250 } | 250 } |
| 251 | 251 |
| 252 checkNodeWOffset(refNode, offset, exceptionState); | 252 checkNodeWOffset(refNode, offset, exceptionState); |
| 253 if (exceptionState.hadException()) | 253 if (exceptionState.had_exception()) |
| 254 return 0; | 254 return 0; |
| 255 | 255 |
| 256 // compare to start, and point comes before | 256 // compare to start, and point comes before |
| 257 if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offs
et(), exceptionState) < 0) | 257 if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offs
et(), exceptionState) < 0) |
| 258 return -1; | 258 return -1; |
| 259 | 259 |
| 260 if (exceptionState.hadException()) | 260 if (exceptionState.had_exception()) |
| 261 return 0; | 261 return 0; |
| 262 | 262 |
| 263 // compare to end, and point comes after | 263 // compare to end, and point comes after |
| 264 if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()
, exceptionState) > 0 && !exceptionState.hadException()) | 264 if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()
, exceptionState) > 0 && !exceptionState.had_exception()) |
| 265 return 1; | 265 return 1; |
| 266 | 266 |
| 267 // point is in the middle of this range, or on the boundary points | 267 // point is in the middle of this range, or on the boundary points |
| 268 return 0; | 268 return 0; |
| 269 } | 269 } |
| 270 | 270 |
| 271 Range::CompareResults Range::compareNode(Node* refNode, ExceptionState& exceptio
nState) const | 271 Range::CompareResults Range::compareNode(Node* refNode, ExceptionState& exceptio
nState) const |
| 272 { | 272 { |
| 273 // http://developer.mozilla.org/en/docs/DOM:range.compareNode | 273 // http://developer.mozilla.org/en/docs/DOM:range.compareNode |
| 274 // This method returns 0, 1, 2, or 3 based on if the node is before, after, | 274 // This method returns 0, 1, 2, or 3 based on if the node is before, after, |
| 275 // before and after(surrounds), or inside the range, respectively | 275 // before and after(surrounds), or inside the range, respectively |
| 276 | 276 |
| 277 if (!refNode) { | 277 if (!refNode) { |
| 278 exceptionState.throwDOMException(NotFoundError, "The node provided was n
ull."); | 278 exceptionState.ThrowDOMException(NotFoundError, "The node provided was n
ull."); |
| 279 return NODE_BEFORE; | 279 return NODE_BEFORE; |
| 280 } | 280 } |
| 281 | 281 |
| 282 if (!refNode->inActiveDocument()) { | 282 if (!refNode->inActiveDocument()) { |
| 283 // Firefox doesn't throw an exception for this case; it returns 0. | 283 // Firefox doesn't throw an exception for this case; it returns 0. |
| 284 return NODE_BEFORE; | 284 return NODE_BEFORE; |
| 285 } | 285 } |
| 286 | 286 |
| 287 if (refNode->document() != m_ownerDocument) { | 287 if (refNode->document() != m_ownerDocument) { |
| 288 // Firefox doesn't throw an exception for this case; it returns 0. | 288 // Firefox doesn't throw an exception for this case; it returns 0. |
| 289 return NODE_BEFORE; | 289 return NODE_BEFORE; |
| 290 } | 290 } |
| 291 | 291 |
| 292 ContainerNode* parentNode = refNode->parentNode(); | 292 ContainerNode* parentNode = refNode->parentNode(); |
| 293 int nodeIndex = refNode->nodeIndex(); | 293 int nodeIndex = refNode->nodeIndex(); |
| 294 | 294 |
| 295 if (!parentNode) { | 295 if (!parentNode) { |
| 296 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R | 296 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R |
| 297 // but we throw to match firefox behavior | 297 // but we throw to match firefox behavior |
| 298 exceptionState.throwDOMException(NotFoundError, "The provided node has n
o parent."); | 298 exceptionState.ThrowDOMException(NotFoundError, "The provided node has n
o parent."); |
| 299 return NODE_BEFORE; | 299 return NODE_BEFORE; |
| 300 } | 300 } |
| 301 | 301 |
| 302 if (comparePoint(parentNode, nodeIndex, exceptionState) < 0) { // starts bef
ore | 302 if (comparePoint(parentNode, nodeIndex, exceptionState) < 0) { // starts bef
ore |
| 303 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends
after the range | 303 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends
after the range |
| 304 return NODE_BEFORE_AND_AFTER; | 304 return NODE_BEFORE_AND_AFTER; |
| 305 return NODE_BEFORE; // ends before or in the range | 305 return NODE_BEFORE; // ends before or in the range |
| 306 } | 306 } |
| 307 // starts at or after the range start | 307 // starts at or after the range start |
| 308 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft
er the range | 308 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft
er the range |
| 309 return NODE_AFTER; | 309 return NODE_AFTER; |
| 310 return NODE_INSIDE; // ends inside the range | 310 return NODE_INSIDE; // ends inside the range |
| 311 } | 311 } |
| 312 | 312 |
| 313 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc
eptionState& exceptionState) const | 313 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc
eptionState& exceptionState) const |
| 314 { | 314 { |
| 315 if (!(how == START_TO_START || how == START_TO_END || how == END_TO_END || h
ow == END_TO_START)) { | 315 if (!(how == START_TO_START || how == START_TO_END || how == END_TO_END || h
ow == END_TO_START)) { |
| 316 exceptionState.throwDOMException(NotSupportedError, "The comparison meth
od provided must be one of 'START_TO_START', 'START_TO_END', 'END_TO_END', or 'E
ND_TO_START'."); | 316 exceptionState.ThrowDOMException(NotSupportedError, "The comparison meth
od provided must be one of 'START_TO_START', 'START_TO_END', 'END_TO_END', or 'E
ND_TO_START'."); |
| 317 return 0; | 317 return 0; |
| 318 } | 318 } |
| 319 | 319 |
| 320 Node* thisCont = commonAncestorContainer(); | 320 Node* thisCont = commonAncestorContainer(); |
| 321 Node* sourceCont = sourceRange->commonAncestorContainer(); | 321 Node* sourceCont = sourceRange->commonAncestorContainer(); |
| 322 if (thisCont->document() != sourceCont->document()) { | 322 if (thisCont->document() != sourceCont->document()) { |
| 323 exceptionState.throwDOMException(WrongDocumentError, "The source range i
s in a different document than this range."); | 323 exceptionState.ThrowDOMException(WrongDocumentError, "The source range i
s in a different document than this range."); |
| 324 return 0; | 324 return 0; |
| 325 } | 325 } |
| 326 | 326 |
| 327 Node* thisTop = thisCont; | 327 Node* thisTop = thisCont; |
| 328 Node* sourceTop = sourceCont; | 328 Node* sourceTop = sourceCont; |
| 329 while (thisTop->parentNode()) | 329 while (thisTop->parentNode()) |
| 330 thisTop = thisTop->parentNode(); | 330 thisTop = thisTop->parentNode(); |
| 331 while (sourceTop->parentNode()) | 331 while (sourceTop->parentNode()) |
| 332 sourceTop = sourceTop->parentNode(); | 332 sourceTop = sourceTop->parentNode(); |
| 333 if (thisTop != sourceTop) { // in different DocumentFragments | 333 if (thisTop != sourceTop) { // in different DocumentFragments |
| 334 exceptionState.throwDOMException(WrongDocumentError, "The source range i
s in a different document than this range."); | 334 exceptionState.ThrowDOMException(WrongDocumentError, "The source range i
s in a different document than this range."); |
| 335 return 0; | 335 return 0; |
| 336 } | 336 } |
| 337 | 337 |
| 338 switch (how) { | 338 switch (how) { |
| 339 case START_TO_START: | 339 case START_TO_START: |
| 340 return compareBoundaryPoints(m_start, sourceRange->m_start, exceptio
nState); | 340 return compareBoundaryPoints(m_start, sourceRange->m_start, exceptio
nState); |
| 341 case START_TO_END: | 341 case START_TO_END: |
| 342 return compareBoundaryPoints(m_end, sourceRange->m_start, exceptionS
tate); | 342 return compareBoundaryPoints(m_end, sourceRange->m_start, exceptionS
tate); |
| 343 case END_TO_END: | 343 case END_TO_END: |
| 344 return compareBoundaryPoints(m_end, sourceRange->m_end, exceptionSta
te); | 344 return compareBoundaryPoints(m_end, sourceRange->m_end, exceptionSta
te); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 if (offsetC < offsetB) | 405 if (offsetC < offsetB) |
| 406 return -1; // A is before B | 406 return -1; // A is before B |
| 407 else | 407 else |
| 408 return 1; // A is after B | 408 return 1; // A is after B |
| 409 } | 409 } |
| 410 | 410 |
| 411 // case 4: containers A & B are siblings, or children of siblings | 411 // case 4: containers A & B are siblings, or children of siblings |
| 412 // ### we need to do a traversal here instead | 412 // ### we need to do a traversal here instead |
| 413 Node* commonAncestor = commonAncestorContainer(containerA, containerB); | 413 Node* commonAncestor = commonAncestorContainer(containerA, containerB); |
| 414 if (!commonAncestor) { | 414 if (!commonAncestor) { |
| 415 exceptionState.throwDOMException(WrongDocumentError, "The two ranges are
in separate documents."); | 415 exceptionState.ThrowDOMException(WrongDocumentError, "The two ranges are
in separate documents."); |
| 416 return 0; | 416 return 0; |
| 417 } | 417 } |
| 418 Node* childA = containerA; | 418 Node* childA = containerA; |
| 419 while (childA && childA->parentNode() != commonAncestor) | 419 while (childA && childA->parentNode() != commonAncestor) |
| 420 childA = childA->parentNode(); | 420 childA = childA->parentNode(); |
| 421 if (!childA) | 421 if (!childA) |
| 422 childA = commonAncestor; | 422 childA = commonAncestor; |
| 423 Node* childB = containerB; | 423 Node* childB = containerB; |
| 424 while (childB && childB->parentNode() != commonAncestor) | 424 while (childB && childB->parentNode() != commonAncestor) |
| 425 childB = childB->parentNode(); | 425 childB = childB->parentNode(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 444 } | 444 } |
| 445 | 445 |
| 446 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra
ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState) | 446 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra
ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState) |
| 447 { | 447 { |
| 448 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun
daryB.container(), boundaryB.offset(), exceptionState); | 448 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun
daryB.container(), boundaryB.offset(), exceptionState); |
| 449 } | 449 } |
| 450 | 450 |
| 451 bool Range::boundaryPointsValid() const | 451 bool Range::boundaryPointsValid() const |
| 452 { | 452 { |
| 453 TrackExceptionState exceptionState; | 453 TrackExceptionState exceptionState; |
| 454 return compareBoundaryPoints(m_start, m_end, exceptionState) <= 0 && !except
ionState.hadException(); | 454 return compareBoundaryPoints(m_start, m_end, exceptionState) <= 0 && !except
ionState.had_exception(); |
| 455 } | 455 } |
| 456 | 456 |
| 457 void Range::deleteContents(ExceptionState& exceptionState) | 457 void Range::deleteContents(ExceptionState& exceptionState) |
| 458 { | 458 { |
| 459 ASSERT(boundaryPointsValid()); | 459 ASSERT(boundaryPointsValid()); |
| 460 | 460 |
| 461 { | 461 { |
| 462 EventQueueScope eventQueueScope; | 462 EventQueueScope eventQueueScope; |
| 463 processContents(DELETE_CONTENTS, exceptionState); | 463 processContents(DELETE_CONTENTS, exceptionState); |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState) | 467 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState) |
| 468 { | 468 { |
| 469 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode | 469 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode |
| 470 // Returns a bool if the node intersects the range. | 470 // Returns a bool if the node intersects the range. |
| 471 if (!refNode) { | 471 if (!refNode) { |
| 472 exceptionState.throwDOMException(NotFoundError, "The node provided is nu
ll."); | 472 exceptionState.ThrowDOMException(NotFoundError, "The node provided is nu
ll."); |
| 473 return false; | 473 return false; |
| 474 } | 474 } |
| 475 | 475 |
| 476 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ | 476 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ |
| 477 // Firefox doesn't throw an exception for these cases; it returns false. | 477 // Firefox doesn't throw an exception for these cases; it returns false. |
| 478 return false; | 478 return false; |
| 479 } | 479 } |
| 480 | 480 |
| 481 ContainerNode* parentNode = refNode->parentNode(); | 481 ContainerNode* parentNode = refNode->parentNode(); |
| 482 int nodeIndex = refNode->nodeIndex(); | 482 int nodeIndex = refNode->nodeIndex(); |
| 483 | 483 |
| 484 if (!parentNode) { | 484 if (!parentNode) { |
| 485 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R | 485 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R |
| 486 // but we throw to match firefox behavior | 486 // but we throw to match firefox behavior |
| 487 exceptionState.throwDOMException(NotFoundError, "The node provided has n
o parent."); | 487 exceptionState.ThrowDOMException(NotFoundError, "The node provided has n
o parent."); |
| 488 return false; | 488 return false; |
| 489 } | 489 } |
| 490 | 490 |
| 491 if (comparePoint(parentNode, nodeIndex, exceptionState) < 0 // starts before
start | 491 if (comparePoint(parentNode, nodeIndex, exceptionState) < 0 // starts before
start |
| 492 && comparePoint(parentNode, nodeIndex + 1, exceptionState) < 0) { // end
s before start | 492 && comparePoint(parentNode, nodeIndex + 1, exceptionState) < 0) { // end
s before start |
| 493 return false; | 493 return false; |
| 494 } | 494 } |
| 495 | 495 |
| 496 if (comparePoint(parentNode, nodeIndex, exceptionState) > 0 // starts after
end | 496 if (comparePoint(parentNode, nodeIndex, exceptionState) > 0 // starts after
end |
| 497 && comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) { // end
s after end | 497 && comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) { // end
s after end |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 // delete all children of commonRoot between the start and end container | 596 // delete all children of commonRoot between the start and end container |
| 597 RefPtr<Node> processStart = childOfCommonRootBeforeOffset(originalStart.cont
ainer(), originalStart.offset(), commonRoot.get()); | 597 RefPtr<Node> processStart = childOfCommonRootBeforeOffset(originalStart.cont
ainer(), originalStart.offset(), commonRoot.get()); |
| 598 if (processStart && originalStart.container() != commonRoot) // processStart
contains nodes before m_start. | 598 if (processStart && originalStart.container() != commonRoot) // processStart
contains nodes before m_start. |
| 599 processStart = processStart->nextSibling(); | 599 processStart = processStart->nextSibling(); |
| 600 RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(originalEnd.containe
r(), originalEnd.offset(), commonRoot.get()); | 600 RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(originalEnd.containe
r(), originalEnd.offset(), commonRoot.get()); |
| 601 | 601 |
| 602 // Collapse the range, making sure that the result is not within a node that
was partially selected. | 602 // Collapse the range, making sure that the result is not within a node that
was partially selected. |
| 603 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 603 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
| 604 if (partialStart && commonRoot->contains(partialStart.get())) { | 604 if (partialStart && commonRoot->contains(partialStart.get())) { |
| 605 // FIXME: We should not continue if we have an earlier error. | 605 // FIXME: We should not continue if we have an earlier error. |
| 606 exceptionState.clearException(); | 606 exceptionState.ClearException(); |
| 607 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1,
exceptionState); | 607 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1,
exceptionState); |
| 608 } else if (partialEnd && commonRoot->contains(partialEnd.get())) { | 608 } else if (partialEnd && commonRoot->contains(partialEnd.get())) { |
| 609 // FIXME: We should not continue if we have an earlier error. | 609 // FIXME: We should not continue if we have an earlier error. |
| 610 exceptionState.clearException(); | 610 exceptionState.ClearException(); |
| 611 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), exceptio
nState); | 611 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), exceptio
nState); |
| 612 } | 612 } |
| 613 if (exceptionState.hadException()) | 613 if (exceptionState.had_exception()) |
| 614 return nullptr; | 614 return nullptr; |
| 615 m_end = m_start; | 615 m_end = m_start; |
| 616 } | 616 } |
| 617 | 617 |
| 618 originalStart.clear(); | 618 originalStart.clear(); |
| 619 originalEnd.clear(); | 619 originalEnd.clear(); |
| 620 | 620 |
| 621 // Now add leftContents, stuff in between, and rightContents to the fragment | 621 // Now add leftContents, stuff in between, and rightContents to the fragment |
| 622 // (or just delete the stuff in between) | 622 // (or just delete the stuff in between) |
| 623 | 623 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 } | 764 } |
| 765 firstChildInAncestorToProcess = direction == ProcessContentsForward ? an
cestor->nextSibling() : ancestor->previousSibling(); | 765 firstChildInAncestorToProcess = direction == ProcessContentsForward ? an
cestor->nextSibling() : ancestor->previousSibling(); |
| 766 } | 766 } |
| 767 | 767 |
| 768 return clonedContainer.release(); | 768 return clonedContainer.release(); |
| 769 } | 769 } |
| 770 | 770 |
| 771 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionState& exceptionSta
te) | 771 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionState& exceptionSta
te) |
| 772 { | 772 { |
| 773 checkExtractPrecondition(exceptionState); | 773 checkExtractPrecondition(exceptionState); |
| 774 if (exceptionState.hadException()) | 774 if (exceptionState.had_exception()) |
| 775 return nullptr; | 775 return nullptr; |
| 776 | 776 |
| 777 return processContents(EXTRACT_CONTENTS, exceptionState); | 777 return processContents(EXTRACT_CONTENTS, exceptionState); |
| 778 } | 778 } |
| 779 | 779 |
| 780 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState
) | 780 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState
) |
| 781 { | 781 { |
| 782 return processContents(CLONE_CONTENTS, exceptionState); | 782 return processContents(CLONE_CONTENTS, exceptionState); |
| 783 } | 783 } |
| 784 | 784 |
| 785 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta
te) | 785 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta
te) |
| 786 { | 786 { |
| 787 RefPtr<Node> newNode = prpNewNode; | 787 RefPtr<Node> newNode = prpNewNode; |
| 788 | 788 |
| 789 if (!newNode) { | 789 if (!newNode) { |
| 790 exceptionState.throwDOMException(NotFoundError, "The node provided is nu
ll."); | 790 exceptionState.ThrowDOMException(NotFoundError, "The node provided is nu
ll."); |
| 791 return; | 791 return; |
| 792 } | 792 } |
| 793 | 793 |
| 794 // HierarchyRequestError: Raised if the container of the start of the Range
is of a type that | 794 // HierarchyRequestError: Raised if the container of the start of the Range
is of a type that |
| 795 // does not allow children of the type of newNode or if newNode is an ancest
or of the container. | 795 // does not allow children of the type of newNode or if newNode is an ancest
or of the container. |
| 796 | 796 |
| 797 // an extra one here - if a text node is going to split, it must have a pare
nt to insert into | 797 // an extra one here - if a text node is going to split, it must have a pare
nt to insert into |
| 798 bool startIsText = m_start.container()->isTextNode(); | 798 bool startIsText = m_start.container()->isTextNode(); |
| 799 if (startIsText && !m_start.container()->parentNode()) { | 799 if (startIsText && !m_start.container()->parentNode()) { |
| 800 exceptionState.throwDOMException(HierarchyRequestError, "This operation
would split a text node, but there's no parent into which to insert."); | 800 exceptionState.ThrowDOMException(HierarchyRequestError, "This operation
would split a text node, but there's no parent into which to insert."); |
| 801 return; | 801 return; |
| 802 } | 802 } |
| 803 | 803 |
| 804 // In the case where the container is a text node, we check against the cont
ainer's parent, because | 804 // In the case where the container is a text node, we check against the cont
ainer's parent, because |
| 805 // text nodes get split up upon insertion. | 805 // text nodes get split up upon insertion. |
| 806 Node* checkAgainst; | 806 Node* checkAgainst; |
| 807 if (startIsText) | 807 if (startIsText) |
| 808 checkAgainst = m_start.container()->parentNode(); | 808 checkAgainst = m_start.container()->parentNode(); |
| 809 else | 809 else |
| 810 checkAgainst = m_start.container(); | 810 checkAgainst = m_start.container(); |
| 811 | 811 |
| 812 Node::NodeType newNodeType = newNode->nodeType(); | 812 Node::NodeType newNodeType = newNode->nodeType(); |
| 813 int numNewChildren; | 813 int numNewChildren; |
| 814 if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE && !newNode->isShadowRoot())
{ | 814 if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE && !newNode->isShadowRoot())
{ |
| 815 // check each child node, not the DocumentFragment itself | 815 // check each child node, not the DocumentFragment itself |
| 816 numNewChildren = 0; | 816 numNewChildren = 0; |
| 817 for (Node* c = toDocumentFragment(newNode)->firstChild(); c; c = c->next
Sibling()) { | 817 for (Node* c = toDocumentFragment(newNode)->firstChild(); c; c = c->next
Sibling()) { |
| 818 ++numNewChildren; | 818 ++numNewChildren; |
| 819 } | 819 } |
| 820 } else { | 820 } else { |
| 821 numNewChildren = 1; | 821 numNewChildren = 1; |
| 822 } | 822 } |
| 823 | 823 |
| 824 for (Node* n = m_start.container(); n; n = n->parentNode()) { | 824 for (Node* n = m_start.container(); n; n = n->parentNode()) { |
| 825 if (n == newNode) { | 825 if (n == newNode) { |
| 826 exceptionState.throwDOMException(HierarchyRequestError, "The node to
be inserted contains the insertion point; it may not be inserted into itself.")
; | 826 exceptionState.ThrowDOMException(HierarchyRequestError, "The node to
be inserted contains the insertion point; it may not be inserted into itself.")
; |
| 827 return; | 827 return; |
| 828 } | 828 } |
| 829 } | 829 } |
| 830 | 830 |
| 831 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, Sha
dowRoot or Document node. | 831 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, Sha
dowRoot or Document node. |
| 832 switch (newNodeType) { | 832 switch (newNodeType) { |
| 833 case Node::DOCUMENT_NODE: | 833 case Node::DOCUMENT_NODE: |
| 834 exceptionState.throwDOMException(InvalidNodeTypeError, "The node to be i
nserted is a '" + newNode->nodeName() + "' node, which may not be inserted here.
"); | 834 exceptionState.ThrowDOMException(InvalidNodeTypeError, "The node to be i
nserted is a '" + newNode->nodeName() + "' node, which may not be inserted here.
"); |
| 835 return; | 835 return; |
| 836 default: | 836 default: |
| 837 if (newNode->isShadowRoot()) { | 837 if (newNode->isShadowRoot()) { |
| 838 exceptionState.throwDOMException(InvalidNodeTypeError, "The node to
be inserted is a shadow root, which may not be inserted here."); | 838 exceptionState.ThrowDOMException(InvalidNodeTypeError, "The node to
be inserted is a shadow root, which may not be inserted here."); |
| 839 return; | 839 return; |
| 840 } | 840 } |
| 841 break; | 841 break; |
| 842 } | 842 } |
| 843 | 843 |
| 844 EventQueueScope scope; | 844 EventQueueScope scope; |
| 845 bool collapsed = m_start == m_end; | 845 bool collapsed = m_start == m_end; |
| 846 RefPtr<Node> container = nullptr; | 846 RefPtr<Node> container = nullptr; |
| 847 if (startIsText) { | 847 if (startIsText) { |
| 848 container = m_start.container(); | 848 container = m_start.container(); |
| 849 RefPtr<Text> newText = toText(container)->splitText(m_start.offset(), ex
ceptionState); | 849 RefPtr<Text> newText = toText(container)->splitText(m_start.offset(), ex
ceptionState); |
| 850 if (exceptionState.hadException()) | 850 if (exceptionState.had_exception()) |
| 851 return; | 851 return; |
| 852 | 852 |
| 853 container = m_start.container(); | 853 container = m_start.container(); |
| 854 container->parentNode()->insertBefore(newNode.release(), newText.get(),
exceptionState); | 854 container->parentNode()->insertBefore(newNode.release(), newText.get(),
exceptionState); |
| 855 if (exceptionState.hadException()) | 855 if (exceptionState.had_exception()) |
| 856 return; | 856 return; |
| 857 | 857 |
| 858 if (collapsed) { | 858 if (collapsed) { |
| 859 // The load event would be fired regardless of EventQueueScope; | 859 // The load event would be fired regardless of EventQueueScope; |
| 860 // e.g. by ContainerNode::updateTreeAfterInsertion | 860 // e.g. by ContainerNode::updateTreeAfterInsertion |
| 861 // Given circumstance may mutate the tree so newText->parentNode() m
ay become null | 861 // Given circumstance may mutate the tree so newText->parentNode() m
ay become null |
| 862 if (!newText->parentNode()) { | 862 if (!newText->parentNode()) { |
| 863 exceptionState.throwDOMException(HierarchyRequestError, "This op
eration would set range's end to parent with new offset, but there's no parent i
nto which to continue."); | 863 exceptionState.ThrowDOMException(HierarchyRequestError, "This op
eration would set range's end to parent with new offset, but there's no parent i
nto which to continue."); |
| 864 return; | 864 return; |
| 865 } | 865 } |
| 866 m_end.setToBeforeChild(*newText); | 866 m_end.setToBeforeChild(*newText); |
| 867 } | 867 } |
| 868 } else { | 868 } else { |
| 869 RefPtr<Node> lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ?
toDocumentFragment(newNode)->lastChild() : newNode.get(); | 869 RefPtr<Node> lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ?
toDocumentFragment(newNode)->lastChild() : newNode.get(); |
| 870 if (lastChild && lastChild == m_start.childBefore()) { | 870 if (lastChild && lastChild == m_start.childBefore()) { |
| 871 // The insertion will do nothing, but we need to extend the range to
include | 871 // The insertion will do nothing, but we need to extend the range to
include |
| 872 // the inserted nodes. | 872 // the inserted nodes. |
| 873 Node* firstChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? t
oDocumentFragment(newNode)->firstChild() : newNode.get(); | 873 Node* firstChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? t
oDocumentFragment(newNode)->firstChild() : newNode.get(); |
| 874 ASSERT(firstChild); | 874 ASSERT(firstChild); |
| 875 m_start.setToBeforeChild(*firstChild); | 875 m_start.setToBeforeChild(*firstChild); |
| 876 return; | 876 return; |
| 877 } | 877 } |
| 878 | 878 |
| 879 container = m_start.container(); | 879 container = m_start.container(); |
| 880 container->insertBefore(newNode.release(), NodeTraversal::childAt(*conta
iner, m_start.offset()), exceptionState); | 880 container->insertBefore(newNode.release(), NodeTraversal::childAt(*conta
iner, m_start.offset()), exceptionState); |
| 881 if (exceptionState.hadException()) | 881 if (exceptionState.had_exception()) |
| 882 return; | 882 return; |
| 883 | 883 |
| 884 // Note that m_start.offset() may have changed as a result of container-
>insertBefore, | 884 // Note that m_start.offset() may have changed as a result of container-
>insertBefore, |
| 885 // when the node we are inserting comes before the range in the same con
tainer. | 885 // when the node we are inserting comes before the range in the same con
tainer. |
| 886 if (collapsed && numNewChildren) | 886 if (collapsed && numNewChildren) |
| 887 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la
stChild.get()); | 887 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la
stChild.get()); |
| 888 } | 888 } |
| 889 } | 889 } |
| 890 | 890 |
| 891 String Range::toString() const | 891 String Range::toString() const |
| (...skipping 23 matching lines...) Expand all Loading... |
| 915 void Range::detach() | 915 void Range::detach() |
| 916 { | 916 { |
| 917 // This is now a no-op as per the DOM specification. | 917 // This is now a no-op as per the DOM specification. |
| 918 } | 918 } |
| 919 | 919 |
| 920 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat
e) const | 920 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat
e) const |
| 921 { | 921 { |
| 922 switch (n->nodeType()) { | 922 switch (n->nodeType()) { |
| 923 case Node::TEXT_NODE: | 923 case Node::TEXT_NODE: |
| 924 if (static_cast<unsigned>(offset) > toCharacterData(n)->length()) | 924 if (static_cast<unsigned>(offset) > toCharacterData(n)->length()) |
| 925 exceptionState.throwDOMException(IndexSizeError, "The offset " +
String::number(offset) + " is larger than or equal to the node's length (" + St
ring::number(toCharacterData(n)->length()) + ")."); | 925 exceptionState.ThrowDOMException(IndexSizeError, "The offset " +
String::number(offset) + " is larger than or equal to the node's length (" + St
ring::number(toCharacterData(n)->length()) + ")."); |
| 926 return 0; | 926 return 0; |
| 927 case Node::DOCUMENT_FRAGMENT_NODE: | 927 case Node::DOCUMENT_FRAGMENT_NODE: |
| 928 case Node::DOCUMENT_NODE: | 928 case Node::DOCUMENT_NODE: |
| 929 case Node::ELEMENT_NODE: { | 929 case Node::ELEMENT_NODE: { |
| 930 if (!offset) | 930 if (!offset) |
| 931 return 0; | 931 return 0; |
| 932 Node* childBefore = NodeTraversal::childAt(*n, offset - 1); | 932 Node* childBefore = NodeTraversal::childAt(*n, offset - 1); |
| 933 if (!childBefore) | 933 if (!childBefore) |
| 934 exceptionState.throwDOMException(IndexSizeError, "There is no ch
ild at offset " + String::number(offset) + "."); | 934 exceptionState.ThrowDOMException(IndexSizeError, "There is no ch
ild at offset " + String::number(offset) + "."); |
| 935 return childBefore; | 935 return childBefore; |
| 936 } | 936 } |
| 937 } | 937 } |
| 938 ASSERT_NOT_REACHED(); | 938 ASSERT_NOT_REACHED(); |
| 939 return 0; | 939 return 0; |
| 940 } | 940 } |
| 941 | 941 |
| 942 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const | 942 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const |
| 943 { | 943 { |
| 944 if (!n) { | 944 if (!n) { |
| 945 exceptionState.throwDOMException(NotFoundError, "The node provided is nu
ll."); | 945 exceptionState.ThrowDOMException(NotFoundError, "The node provided is nu
ll."); |
| 946 return; | 946 return; |
| 947 } | 947 } |
| 948 | 948 |
| 949 // InvalidNodeTypeError: Raised if the root container of refNode is not an | 949 // InvalidNodeTypeError: Raised if the root container of refNode is not an |
| 950 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha
dow DOM tree, | 950 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha
dow DOM tree, |
| 951 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity,
or Notation node. | 951 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity,
or Notation node. |
| 952 | 952 |
| 953 if (!n->parentNode()) { | 953 if (!n->parentNode()) { |
| 954 exceptionState.throwDOMException(InvalidNodeTypeError, "the given Node h
as no parent."); | 954 exceptionState.ThrowDOMException(InvalidNodeTypeError, "the given Node h
as no parent."); |
| 955 return; | 955 return; |
| 956 } | 956 } |
| 957 | 957 |
| 958 switch (n->nodeType()) { | 958 switch (n->nodeType()) { |
| 959 case Node::DOCUMENT_FRAGMENT_NODE: | 959 case Node::DOCUMENT_FRAGMENT_NODE: |
| 960 case Node::DOCUMENT_NODE: | 960 case Node::DOCUMENT_NODE: |
| 961 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + n->nodeName() + "'."); | 961 exceptionState.ThrowDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + n->nodeName() + "'."); |
| 962 return; | 962 return; |
| 963 case Node::ELEMENT_NODE: | 963 case Node::ELEMENT_NODE: |
| 964 case Node::TEXT_NODE: | 964 case Node::TEXT_NODE: |
| 965 break; | 965 break; |
| 966 } | 966 } |
| 967 | 967 |
| 968 Node* root = n; | 968 Node* root = n; |
| 969 while (ContainerNode* parent = root->parentNode()) | 969 while (ContainerNode* parent = root->parentNode()) |
| 970 root = parent; | 970 root = parent; |
| 971 | 971 |
| 972 switch (root->nodeType()) { | 972 switch (root->nodeType()) { |
| 973 case Node::DOCUMENT_NODE: | 973 case Node::DOCUMENT_NODE: |
| 974 case Node::DOCUMENT_FRAGMENT_NODE: | 974 case Node::DOCUMENT_FRAGMENT_NODE: |
| 975 case Node::ELEMENT_NODE: | 975 case Node::ELEMENT_NODE: |
| 976 break; | 976 break; |
| 977 case Node::TEXT_NODE: | 977 case Node::TEXT_NODE: |
| 978 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + n->nodeName() + "'."); | 978 exceptionState.ThrowDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + n->nodeName() + "'."); |
| 979 return; | 979 return; |
| 980 } | 980 } |
| 981 } | 981 } |
| 982 | 982 |
| 983 PassRefPtr<Range> Range::cloneRange() const | 983 PassRefPtr<Range> Range::cloneRange() const |
| 984 { | 984 { |
| 985 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of
fset(), m_end.container(), m_end.offset()); | 985 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of
fset(), m_end.container(), m_end.offset()); |
| 986 } | 986 } |
| 987 | 987 |
| 988 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState) | 988 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState) |
| 989 { | 989 { |
| 990 checkNodeBA(refNode, exceptionState); | 990 checkNodeBA(refNode, exceptionState); |
| 991 if (exceptionState.hadException()) | 991 if (exceptionState.had_exception()) |
| 992 return; | 992 return; |
| 993 | 993 |
| 994 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); | 994 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); |
| 995 } | 995 } |
| 996 | 996 |
| 997 void Range::setEndBefore(Node* refNode, ExceptionState& exceptionState) | 997 void Range::setEndBefore(Node* refNode, ExceptionState& exceptionState) |
| 998 { | 998 { |
| 999 checkNodeBA(refNode, exceptionState); | 999 checkNodeBA(refNode, exceptionState); |
| 1000 if (exceptionState.hadException()) | 1000 if (exceptionState.had_exception()) |
| 1001 return; | 1001 return; |
| 1002 | 1002 |
| 1003 setEnd(refNode->parentNode(), refNode->nodeIndex(), exceptionState); | 1003 setEnd(refNode->parentNode(), refNode->nodeIndex(), exceptionState); |
| 1004 } | 1004 } |
| 1005 | 1005 |
| 1006 void Range::setEndAfter(Node* refNode, ExceptionState& exceptionState) | 1006 void Range::setEndAfter(Node* refNode, ExceptionState& exceptionState) |
| 1007 { | 1007 { |
| 1008 checkNodeBA(refNode, exceptionState); | 1008 checkNodeBA(refNode, exceptionState); |
| 1009 if (exceptionState.hadException()) | 1009 if (exceptionState.had_exception()) |
| 1010 return; | 1010 return; |
| 1011 | 1011 |
| 1012 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); | 1012 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); |
| 1013 } | 1013 } |
| 1014 | 1014 |
| 1015 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) | 1015 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) |
| 1016 { | 1016 { |
| 1017 if (!refNode) { | 1017 if (!refNode) { |
| 1018 exceptionState.throwDOMException(NotFoundError, "The node provided is nu
ll."); | 1018 exceptionState.ThrowDOMException(NotFoundError, "The node provided is nu
ll."); |
| 1019 return; | 1019 return; |
| 1020 } | 1020 } |
| 1021 | 1021 |
| 1022 if (!refNode->parentNode()) { | 1022 if (!refNode->parentNode()) { |
| 1023 exceptionState.throwDOMException(InvalidNodeTypeError, "the given Node h
as no parent."); | 1023 exceptionState.ThrowDOMException(InvalidNodeTypeError, "the given Node h
as no parent."); |
| 1024 return; | 1024 return; |
| 1025 } | 1025 } |
| 1026 | 1026 |
| 1027 // InvalidNodeTypeError: Raised if an ancestor of refNode is an Entity, Nota
tion or | 1027 // InvalidNodeTypeError: Raised if an ancestor of refNode is an Entity, Nota
tion or |
| 1028 // DocumentType node or if refNode is a Document, DocumentFragment, ShadowRo
ot, Attr, Entity, or Notation | 1028 // DocumentType node or if refNode is a Document, DocumentFragment, ShadowRo
ot, Attr, Entity, or Notation |
| 1029 // node. | 1029 // node. |
| 1030 switch (refNode->nodeType()) { | 1030 switch (refNode->nodeType()) { |
| 1031 case Node::ELEMENT_NODE: | 1031 case Node::ELEMENT_NODE: |
| 1032 case Node::TEXT_NODE: | 1032 case Node::TEXT_NODE: |
| 1033 break; | 1033 break; |
| 1034 case Node::DOCUMENT_FRAGMENT_NODE: | 1034 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1035 case Node::DOCUMENT_NODE: | 1035 case Node::DOCUMENT_NODE: |
| 1036 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + refNode->nodeName() + "'."); | 1036 exceptionState.ThrowDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + refNode->nodeName() + "'."); |
| 1037 return; | 1037 return; |
| 1038 } | 1038 } |
| 1039 | 1039 |
| 1040 if (m_ownerDocument != refNode->document()) | 1040 if (m_ownerDocument != refNode->document()) |
| 1041 setDocument(refNode->document()); | 1041 setDocument(refNode->document()); |
| 1042 | 1042 |
| 1043 setStartBefore(refNode); | 1043 setStartBefore(refNode); |
| 1044 setEndAfter(refNode); | 1044 setEndAfter(refNode); |
| 1045 } | 1045 } |
| 1046 | 1046 |
| 1047 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) | 1047 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) |
| 1048 { | 1048 { |
| 1049 if (!refNode) { | 1049 if (!refNode) { |
| 1050 exceptionState.throwDOMException(NotFoundError, "The node provided is nu
ll."); | 1050 exceptionState.ThrowDOMException(NotFoundError, "The node provided is nu
ll."); |
| 1051 return; | 1051 return; |
| 1052 } | 1052 } |
| 1053 | 1053 |
| 1054 if (m_ownerDocument != refNode->document()) | 1054 if (m_ownerDocument != refNode->document()) |
| 1055 setDocument(refNode->document()); | 1055 setDocument(refNode->document()); |
| 1056 | 1056 |
| 1057 m_start.setToStartOfNode(*refNode); | 1057 m_start.setToStartOfNode(*refNode); |
| 1058 m_end.setToEndOfNode(*refNode); | 1058 m_end.setToEndOfNode(*refNode); |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc
eptionState) | 1061 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc
eptionState) |
| 1062 { | 1062 { |
| 1063 RefPtr<Node> newParent = passNewParent; | 1063 RefPtr<Node> newParent = passNewParent; |
| 1064 if (!newParent) { | 1064 if (!newParent) { |
| 1065 exceptionState.throwDOMException(NotFoundError, "The node provided is nu
ll."); | 1065 exceptionState.ThrowDOMException(NotFoundError, "The node provided is nu
ll."); |
| 1066 return; | 1066 return; |
| 1067 } | 1067 } |
| 1068 | 1068 |
| 1069 // InvalidStateError: Raised if the Range partially selects a non-Text node. | 1069 // InvalidStateError: Raised if the Range partially selects a non-Text node. |
| 1070 Node* startNonTextContainer = m_start.container(); | 1070 Node* startNonTextContainer = m_start.container(); |
| 1071 if (startNonTextContainer->nodeType() == Node::TEXT_NODE) | 1071 if (startNonTextContainer->nodeType() == Node::TEXT_NODE) |
| 1072 startNonTextContainer = startNonTextContainer->parentNode(); | 1072 startNonTextContainer = startNonTextContainer->parentNode(); |
| 1073 Node* endNonTextContainer = m_end.container(); | 1073 Node* endNonTextContainer = m_end.container(); |
| 1074 if (endNonTextContainer->nodeType() == Node::TEXT_NODE) | 1074 if (endNonTextContainer->nodeType() == Node::TEXT_NODE) |
| 1075 endNonTextContainer = endNonTextContainer->parentNode(); | 1075 endNonTextContainer = endNonTextContainer->parentNode(); |
| 1076 if (startNonTextContainer != endNonTextContainer) { | 1076 if (startNonTextContainer != endNonTextContainer) { |
| 1077 exceptionState.throwDOMException(InvalidStateError, "The Range has parti
ally selected a non-Text node."); | 1077 exceptionState.ThrowDOMException(InvalidStateError, "The Range has parti
ally selected a non-Text node."); |
| 1078 return; | 1078 return; |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No
tation, | 1081 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No
tation, |
| 1082 // Document, or DocumentFragment node. | 1082 // Document, or DocumentFragment node. |
| 1083 switch (newParent->nodeType()) { | 1083 switch (newParent->nodeType()) { |
| 1084 case Node::DOCUMENT_FRAGMENT_NODE: | 1084 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1085 case Node::DOCUMENT_NODE: | 1085 case Node::DOCUMENT_NODE: |
| 1086 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + newParent->nodeName() + "'."); | 1086 exceptionState.ThrowDOMException(InvalidNodeTypeError, "The node pro
vided is of type '" + newParent->nodeName() + "'."); |
| 1087 return; | 1087 return; |
| 1088 case Node::ELEMENT_NODE: | 1088 case Node::ELEMENT_NODE: |
| 1089 case Node::TEXT_NODE: | 1089 case Node::TEXT_NODE: |
| 1090 break; | 1090 break; |
| 1091 } | 1091 } |
| 1092 | 1092 |
| 1093 // Raise a HierarchyRequestError if m_start.container() doesn't accept child
ren like newParent. | 1093 // Raise a HierarchyRequestError if m_start.container() doesn't accept child
ren like newParent. |
| 1094 Node* parentOfNewParent = m_start.container(); | 1094 Node* parentOfNewParent = m_start.container(); |
| 1095 | 1095 |
| 1096 // If m_start.container() is a character data node, it will be split and it
will be its parent that will | 1096 // If m_start.container() is a character data node, it will be split and it
will be its parent that will |
| 1097 // need to accept newParent (or in the case of a comment, it logically "woul
d" be inserted into the parent, | 1097 // need to accept newParent (or in the case of a comment, it logically "woul
d" be inserted into the parent, |
| 1098 // although this will fail below for another reason). | 1098 // although this will fail below for another reason). |
| 1099 if (parentOfNewParent->isTextNode()) | 1099 if (parentOfNewParent->isTextNode()) |
| 1100 parentOfNewParent = parentOfNewParent->parentNode(); | 1100 parentOfNewParent = parentOfNewParent->parentNode(); |
| 1101 | 1101 |
| 1102 if (!parentOfNewParent) { | 1102 if (!parentOfNewParent) { |
| 1103 exceptionState.throwDOMException(HierarchyRequestError, "The container n
ode is a detached character data node; no parent node is available for insertion
."); | 1103 exceptionState.ThrowDOMException(HierarchyRequestError, "The container n
ode is a detached character data node; no parent node is available for insertion
."); |
| 1104 return; | 1104 return; |
| 1105 } | 1105 } |
| 1106 | 1106 |
| 1107 if (newParent->contains(m_start.container())) { | 1107 if (newParent->contains(m_start.container())) { |
| 1108 exceptionState.throwDOMException(HierarchyRequestError, "The node provid
ed contains the insertion point; it may not be inserted into itself."); | 1108 exceptionState.ThrowDOMException(HierarchyRequestError, "The node provid
ed contains the insertion point; it may not be inserted into itself."); |
| 1109 return; | 1109 return; |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 // FIXME: Do we need a check if the node would end up with a child node of a
type not | 1112 // FIXME: Do we need a check if the node would end up with a child node of a
type not |
| 1113 // allowed by the type of node? | 1113 // allowed by the type of node? |
| 1114 | 1114 |
| 1115 while (Node* n = newParent->firstChild()) { | 1115 while (Node* n = newParent->firstChild()) { |
| 1116 toContainerNode(newParent)->removeChild(n, exceptionState); | 1116 toContainerNode(newParent)->removeChild(n, exceptionState); |
| 1117 if (exceptionState.hadException()) | 1117 if (exceptionState.had_exception()) |
| 1118 return; | 1118 return; |
| 1119 } | 1119 } |
| 1120 RefPtr<DocumentFragment> fragment = extractContents(exceptionState); | 1120 RefPtr<DocumentFragment> fragment = extractContents(exceptionState); |
| 1121 if (exceptionState.hadException()) | 1121 if (exceptionState.had_exception()) |
| 1122 return; | 1122 return; |
| 1123 insertNode(newParent, exceptionState); | 1123 insertNode(newParent, exceptionState); |
| 1124 if (exceptionState.hadException()) | 1124 if (exceptionState.had_exception()) |
| 1125 return; | 1125 return; |
| 1126 newParent->appendChild(fragment.release(), exceptionState); | 1126 newParent->appendChild(fragment.release(), exceptionState); |
| 1127 if (exceptionState.hadException()) | 1127 if (exceptionState.had_exception()) |
| 1128 return; | 1128 return; |
| 1129 selectNode(newParent.get(), exceptionState); | 1129 selectNode(newParent.get(), exceptionState); |
| 1130 } | 1130 } |
| 1131 | 1131 |
| 1132 void Range::setStartBefore(Node* refNode, ExceptionState& exceptionState) | 1132 void Range::setStartBefore(Node* refNode, ExceptionState& exceptionState) |
| 1133 { | 1133 { |
| 1134 checkNodeBA(refNode, exceptionState); | 1134 checkNodeBA(refNode, exceptionState); |
| 1135 if (exceptionState.hadException()) | 1135 if (exceptionState.had_exception()) |
| 1136 return; | 1136 return; |
| 1137 | 1137 |
| 1138 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState); | 1138 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState); |
| 1139 } | 1139 } |
| 1140 | 1140 |
| 1141 void Range::checkExtractPrecondition(ExceptionState&) | 1141 void Range::checkExtractPrecondition(ExceptionState&) |
| 1142 { | 1142 { |
| 1143 // FIXME: Remove. | 1143 // FIXME: Remove. |
| 1144 } | 1144 } |
| 1145 | 1145 |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1512 | 1512 |
| 1513 void showTree(const blink::Range* range) | 1513 void showTree(const blink::Range* range) |
| 1514 { | 1514 { |
| 1515 if (range && range->boundaryPointsValid()) { | 1515 if (range && range->boundaryPointsValid()) { |
| 1516 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r
ange->endContainer(), "E"); | 1516 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r
ange->endContainer(), "E"); |
| 1517 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset
(), range->endOffset()); | 1517 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset
(), range->endOffset()); |
| 1518 } | 1518 } |
| 1519 } | 1519 } |
| 1520 | 1520 |
| 1521 #endif | 1521 #endif |
| OLD | NEW |