| 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 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 { | 121 { |
| 122 ASSERT(m_ownerDocument != document); | 122 ASSERT(m_ownerDocument != document); |
| 123 ASSERT(m_ownerDocument); | 123 ASSERT(m_ownerDocument); |
| 124 m_ownerDocument->detachRange(this); | 124 m_ownerDocument->detachRange(this); |
| 125 m_ownerDocument = &document; | 125 m_ownerDocument = &document; |
| 126 m_start.setToStartOfNode(&document); | 126 m_start.setToStartOfNode(&document); |
| 127 m_end.setToStartOfNode(&document); | 127 m_end.setToStartOfNode(&document); |
| 128 m_ownerDocument->attachRange(this); | 128 m_ownerDocument->attachRange(this); |
| 129 } | 129 } |
| 130 | 130 |
| 131 Node* Range::startContainer(ExceptionState& es) const | 131 Node* Range::startContainer(ExceptionState& exceptionState) const |
| 132 { | 132 { |
| 133 if (!m_start.container()) { | 133 if (!m_start.container()) { |
| 134 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("startContainer", "Range", "The range has no container. Perhaps 'detatch()' h
as been invoked on this object?")); | 134 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("startContainer", "Range", "The range has no container. Perhaps '
detatch()' has been invoked on this object?")); |
| 135 return 0; | 135 return 0; |
| 136 } | 136 } |
| 137 | 137 |
| 138 return m_start.container(); | 138 return m_start.container(); |
| 139 } | 139 } |
| 140 | 140 |
| 141 int Range::startOffset(ExceptionState& es) const | 141 int Range::startOffset(ExceptionState& exceptionState) const |
| 142 { | 142 { |
| 143 if (!m_start.container()) { | 143 if (!m_start.container()) { |
| 144 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("startOffset", "Range", "The range has no container. Perhaps 'detatch()' has
been invoked on this object?")); | 144 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("startOffset", "Range", "The range has no container. Perhaps 'det
atch()' has been invoked on this object?")); |
| 145 return 0; | 145 return 0; |
| 146 } | 146 } |
| 147 | 147 |
| 148 return m_start.offset(); | 148 return m_start.offset(); |
| 149 } | 149 } |
| 150 | 150 |
| 151 Node* Range::endContainer(ExceptionState& es) const | 151 Node* Range::endContainer(ExceptionState& exceptionState) const |
| 152 { | 152 { |
| 153 if (!m_start.container()) { | 153 if (!m_start.container()) { |
| 154 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("endContainer", "Range", "The range has no container. Perhaps 'detatch()' has
been invoked on this object?")); | 154 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("endContainer", "Range", "The range has no container. Perhaps 'de
tatch()' has been invoked on this object?")); |
| 155 return 0; | 155 return 0; |
| 156 } | 156 } |
| 157 | 157 |
| 158 return m_end.container(); | 158 return m_end.container(); |
| 159 } | 159 } |
| 160 | 160 |
| 161 int Range::endOffset(ExceptionState& es) const | 161 int Range::endOffset(ExceptionState& exceptionState) const |
| 162 { | 162 { |
| 163 if (!m_start.container()) { | 163 if (!m_start.container()) { |
| 164 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("endOffset", "Range", "The range has no container. Perhaps 'detatch()' has be
en invoked on this object?")); | 164 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("endOffset", "Range", "The range has no container. Perhaps 'detat
ch()' has been invoked on this object?")); |
| 165 return 0; | 165 return 0; |
| 166 } | 166 } |
| 167 | 167 |
| 168 return m_end.offset(); | 168 return m_end.offset(); |
| 169 } | 169 } |
| 170 | 170 |
| 171 Node* Range::commonAncestorContainer(ExceptionState& es) const | 171 Node* Range::commonAncestorContainer(ExceptionState& exceptionState) const |
| 172 { | 172 { |
| 173 if (!m_start.container()) { | 173 if (!m_start.container()) { |
| 174 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("commonAncestorContainer", "Range", "The range has no container. Perhaps 'det
atch()' has been invoked on this object?")); | 174 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("commonAncestorContainer", "Range", "The range has no container.
Perhaps 'detatch()' has been invoked on this object?")); |
| 175 return 0; | 175 return 0; |
| 176 } | 176 } |
| 177 | 177 |
| 178 return commonAncestorContainer(m_start.container(), m_end.container()); | 178 return commonAncestorContainer(m_start.container(), m_end.container()); |
| 179 } | 179 } |
| 180 | 180 |
| 181 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB) | 181 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB) |
| 182 { | 182 { |
| 183 for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) { | 183 for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) { |
| 184 for (Node* parentB = containerB; parentB; parentB = parentB->parentNode(
)) { | 184 for (Node* parentB = containerB; parentB; parentB = parentB->parentNode(
)) { |
| 185 if (parentA == parentB) | 185 if (parentA == parentB) |
| 186 return parentA; | 186 return parentA; |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 return 0; | 189 return 0; |
| 190 } | 190 } |
| 191 | 191 |
| 192 bool Range::collapsed(ExceptionState& es) const | 192 bool Range::collapsed(ExceptionState& exceptionState) const |
| 193 { | 193 { |
| 194 if (!m_start.container()) { | 194 if (!m_start.container()) { |
| 195 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("collapsed", "Range", "The range has no container. Perhaps 'detatch()' has be
en invoked on this object?")); | 195 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("collapsed", "Range", "The range has no container. Perhaps 'detat
ch()' has been invoked on this object?")); |
| 196 return 0; | 196 return 0; |
| 197 } | 197 } |
| 198 | 198 |
| 199 return m_start == m_end; | 199 return m_start == m_end; |
| 200 } | 200 } |
| 201 | 201 |
| 202 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& star
t, const RangeBoundaryPoint& end) | 202 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& star
t, const RangeBoundaryPoint& end) |
| 203 { | 203 { |
| 204 Node* endRootContainer = end.container(); | 204 Node* endRootContainer = end.container(); |
| 205 while (endRootContainer->parentNode()) | 205 while (endRootContainer->parentNode()) |
| 206 endRootContainer = endRootContainer->parentNode(); | 206 endRootContainer = endRootContainer->parentNode(); |
| 207 Node* startRootContainer = start.container(); | 207 Node* startRootContainer = start.container(); |
| 208 while (startRootContainer->parentNode()) | 208 while (startRootContainer->parentNode()) |
| 209 startRootContainer = startRootContainer->parentNode(); | 209 startRootContainer = startRootContainer->parentNode(); |
| 210 | 210 |
| 211 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin
ts(start, end, ASSERT_NO_EXCEPTION) > 0); | 211 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin
ts(start, end, ASSERT_NO_EXCEPTION) > 0); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& es) | 214 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep
tionState) |
| 215 { | 215 { |
| 216 if (!m_start.container()) { | 216 if (!m_start.container()) { |
| 217 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("setStart", "Range", "The range has no container. Perhaps 'detatch()' has bee
n invoked on this object?")); | 217 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("setStart", "Range", "The range has no container. Perhaps 'detatc
h()' has been invoked on this object?")); |
| 218 return; | 218 return; |
| 219 } | 219 } |
| 220 | 220 |
| 221 if (!refNode) { | 221 if (!refNode) { |
| 222 es.throwUninformativeAndGenericDOMException(NotFoundError); | 222 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 223 return; | 223 return; |
| 224 } | 224 } |
| 225 | 225 |
| 226 bool didMoveDocument = false; | 226 bool didMoveDocument = false; |
| 227 if (refNode->document() != m_ownerDocument) { | 227 if (refNode->document() != m_ownerDocument) { |
| 228 setDocument(refNode->document()); | 228 setDocument(refNode->document()); |
| 229 didMoveDocument = true; | 229 didMoveDocument = true; |
| 230 } | 230 } |
| 231 | 231 |
| 232 Node* childNode = checkNodeWOffset(refNode.get(), offset, es); | 232 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); |
| 233 if (es.hadException()) | 233 if (exceptionState.hadException()) |
| 234 return; | 234 return; |
| 235 | 235 |
| 236 m_start.set(refNode, offset, childNode); | 236 m_start.set(refNode, offset, childNode); |
| 237 | 237 |
| 238 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 238 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
| 239 collapse(true, es); | 239 collapse(true, exceptionState); |
| 240 } | 240 } |
| 241 | 241 |
| 242 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& es) | 242 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti
onState) |
| 243 { | 243 { |
| 244 if (!m_start.container()) { | 244 if (!m_start.container()) { |
| 245 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("setEnd", "Range", "The range has no container. Perhaps 'detatch()' has been
invoked on this object?")); | 245 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("setEnd", "Range", "The range has no container. Perhaps 'detatch(
)' has been invoked on this object?")); |
| 246 return; | 246 return; |
| 247 } | 247 } |
| 248 | 248 |
| 249 if (!refNode) { | 249 if (!refNode) { |
| 250 es.throwUninformativeAndGenericDOMException(NotFoundError); | 250 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 251 return; | 251 return; |
| 252 } | 252 } |
| 253 | 253 |
| 254 bool didMoveDocument = false; | 254 bool didMoveDocument = false; |
| 255 if (refNode->document() != m_ownerDocument) { | 255 if (refNode->document() != m_ownerDocument) { |
| 256 setDocument(refNode->document()); | 256 setDocument(refNode->document()); |
| 257 didMoveDocument = true; | 257 didMoveDocument = true; |
| 258 } | 258 } |
| 259 | 259 |
| 260 Node* childNode = checkNodeWOffset(refNode.get(), offset, es); | 260 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); |
| 261 if (es.hadException()) | 261 if (exceptionState.hadException()) |
| 262 return; | 262 return; |
| 263 | 263 |
| 264 m_end.set(refNode, offset, childNode); | 264 m_end.set(refNode, offset, childNode); |
| 265 | 265 |
| 266 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 266 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
| 267 collapse(false, es); | 267 collapse(false, exceptionState); |
| 268 } | 268 } |
| 269 | 269 |
| 270 void Range::setStart(const Position& start, ExceptionState& es) | 270 void Range::setStart(const Position& start, ExceptionState& exceptionState) |
| 271 { | 271 { |
| 272 Position parentAnchored = start.parentAnchoredEquivalent(); | 272 Position parentAnchored = start.parentAnchoredEquivalent(); |
| 273 setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNod
e(), es); | 273 setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNod
e(), exceptionState); |
| 274 } | 274 } |
| 275 | 275 |
| 276 void Range::setEnd(const Position& end, ExceptionState& es) | 276 void Range::setEnd(const Position& end, ExceptionState& exceptionState) |
| 277 { | 277 { |
| 278 Position parentAnchored = end.parentAnchoredEquivalent(); | 278 Position parentAnchored = end.parentAnchoredEquivalent(); |
| 279 setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode(
), es); | 279 setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode(
), exceptionState); |
| 280 } | 280 } |
| 281 | 281 |
| 282 void Range::collapse(bool toStart, ExceptionState& es) | 282 void Range::collapse(bool toStart, ExceptionState& exceptionState) |
| 283 { | 283 { |
| 284 if (!m_start.container()) { | 284 if (!m_start.container()) { |
| 285 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("collapse", "Range", "The range has no container. Perhaps 'detatch()' has bee
n invoked on this object?")); | 285 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("collapse", "Range", "The range has no container. Perhaps 'detatc
h()' has been invoked on this object?")); |
| 286 return; | 286 return; |
| 287 } | 287 } |
| 288 | 288 |
| 289 if (toStart) | 289 if (toStart) |
| 290 m_end = m_start; | 290 m_end = m_start; |
| 291 else | 291 else |
| 292 m_start = m_end; | 292 m_start = m_end; |
| 293 } | 293 } |
| 294 | 294 |
| 295 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& es) | 295 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS
tate) |
| 296 { | 296 { |
| 297 if (!m_start.container()) { | 297 if (!m_start.container()) { |
| 298 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("isPointInRange", "Range", "The range has no container. Perhaps 'detatch()' h
as been invoked on this object?")); | 298 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("isPointInRange", "Range", "The range has no container. Perhaps '
detatch()' has been invoked on this object?")); |
| 299 return false; | 299 return false; |
| 300 } | 300 } |
| 301 | 301 |
| 302 if (!refNode) { | 302 if (!refNode) { |
| 303 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 303 exceptionState.throwUninformativeAndGenericDOMException(HierarchyRequest
Error); |
| 304 return false; | 304 return false; |
| 305 } | 305 } |
| 306 | 306 |
| 307 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ | 307 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ |
| 308 return false; | 308 return false; |
| 309 } | 309 } |
| 310 | 310 |
| 311 checkNodeWOffset(refNode, offset, es); | 311 checkNodeWOffset(refNode, offset, exceptionState); |
| 312 if (es.hadException()) | 312 if (exceptionState.hadException()) |
| 313 return false; | 313 return false; |
| 314 | 314 |
| 315 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o
ffset(), es) >= 0 && !es.hadException() | 315 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o
ffset(), exceptionState) >= 0 && !exceptionState.hadException() |
| 316 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse
t(), es) <= 0 && !es.hadException(); | 316 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse
t(), exceptionState) <= 0 && !exceptionState.hadException(); |
| 317 } | 317 } |
| 318 | 318 |
| 319 short Range::comparePoint(Node* refNode, int offset, ExceptionState& es) const | 319 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt
ate) const |
| 320 { | 320 { |
| 321 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint | 321 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint |
| 322 // This method returns -1, 0 or 1 depending on if the point described by the | 322 // This method returns -1, 0 or 1 depending on if the point described by the |
| 323 // refNode node and an offset within the node is before, same as, or after t
he range respectively. | 323 // refNode node and an offset within the node is before, same as, or after t
he range respectively. |
| 324 | 324 |
| 325 if (!m_start.container()) { | 325 if (!m_start.container()) { |
| 326 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("comparePoint", "Range", "The range has no container. Perhaps 'detatch()' has
been invoked on this object?")); | 326 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("comparePoint", "Range", "The range has no container. Perhaps 'de
tatch()' has been invoked on this object?")); |
| 327 return 0; | 327 return 0; |
| 328 } | 328 } |
| 329 | 329 |
| 330 if (!refNode) { | 330 if (!refNode) { |
| 331 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 331 exceptionState.throwUninformativeAndGenericDOMException(HierarchyRequest
Error); |
| 332 return 0; | 332 return 0; |
| 333 } | 333 } |
| 334 | 334 |
| 335 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ | 335 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ |
| 336 es.throwUninformativeAndGenericDOMException(WrongDocumentError); | 336 exceptionState.throwUninformativeAndGenericDOMException(WrongDocumentErr
or); |
| 337 return 0; | 337 return 0; |
| 338 } | 338 } |
| 339 | 339 |
| 340 checkNodeWOffset(refNode, offset, es); | 340 checkNodeWOffset(refNode, offset, exceptionState); |
| 341 if (es.hadException()) | 341 if (exceptionState.hadException()) |
| 342 return 0; | 342 return 0; |
| 343 | 343 |
| 344 // compare to start, and point comes before | 344 // compare to start, and point comes before |
| 345 if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offs
et(), es) < 0) | 345 if (compareBoundaryPoints(refNode, offset, m_start.container(), m_start.offs
et(), exceptionState) < 0) |
| 346 return -1; | 346 return -1; |
| 347 | 347 |
| 348 if (es.hadException()) | 348 if (exceptionState.hadException()) |
| 349 return 0; | 349 return 0; |
| 350 | 350 |
| 351 // compare to end, and point comes after | 351 // compare to end, and point comes after |
| 352 if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()
, es) > 0 && !es.hadException()) | 352 if (compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offset()
, exceptionState) > 0 && !exceptionState.hadException()) |
| 353 return 1; | 353 return 1; |
| 354 | 354 |
| 355 // point is in the middle of this range, or on the boundary points | 355 // point is in the middle of this range, or on the boundary points |
| 356 return 0; | 356 return 0; |
| 357 } | 357 } |
| 358 | 358 |
| 359 Range::CompareResults Range::compareNode(Node* refNode, ExceptionState& es) cons
t | 359 Range::CompareResults Range::compareNode(Node* refNode, ExceptionState& exceptio
nState) const |
| 360 { | 360 { |
| 361 // http://developer.mozilla.org/en/docs/DOM:range.compareNode | 361 // http://developer.mozilla.org/en/docs/DOM:range.compareNode |
| 362 // This method returns 0, 1, 2, or 3 based on if the node is before, after, | 362 // This method returns 0, 1, 2, or 3 based on if the node is before, after, |
| 363 // before and after(surrounds), or inside the range, respectively | 363 // before and after(surrounds), or inside the range, respectively |
| 364 | 364 |
| 365 if (!refNode) { | 365 if (!refNode) { |
| 366 es.throwUninformativeAndGenericDOMException(NotFoundError); | 366 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 367 return NODE_BEFORE; | 367 return NODE_BEFORE; |
| 368 } | 368 } |
| 369 | 369 |
| 370 if (!m_start.container() && refNode->inActiveDocument()) { | 370 if (!m_start.container() && refNode->inActiveDocument()) { |
| 371 es.throwUninformativeAndGenericDOMException(InvalidStateError); | 371 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateErro
r); |
| 372 return NODE_BEFORE; | 372 return NODE_BEFORE; |
| 373 } | 373 } |
| 374 | 374 |
| 375 if (m_start.container() && !refNode->inActiveDocument()) { | 375 if (m_start.container() && !refNode->inActiveDocument()) { |
| 376 // Firefox doesn't throw an exception for this case; it returns 0. | 376 // Firefox doesn't throw an exception for this case; it returns 0. |
| 377 return NODE_BEFORE; | 377 return NODE_BEFORE; |
| 378 } | 378 } |
| 379 | 379 |
| 380 if (refNode->document() != m_ownerDocument) { | 380 if (refNode->document() != m_ownerDocument) { |
| 381 // Firefox doesn't throw an exception for this case; it returns 0. | 381 // Firefox doesn't throw an exception for this case; it returns 0. |
| 382 return NODE_BEFORE; | 382 return NODE_BEFORE; |
| 383 } | 383 } |
| 384 | 384 |
| 385 ContainerNode* parentNode = refNode->parentNode(); | 385 ContainerNode* parentNode = refNode->parentNode(); |
| 386 int nodeIndex = refNode->nodeIndex(); | 386 int nodeIndex = refNode->nodeIndex(); |
| 387 | 387 |
| 388 if (!parentNode) { | 388 if (!parentNode) { |
| 389 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R | 389 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R |
| 390 // but we throw to match firefox behavior | 390 // but we throw to match firefox behavior |
| 391 es.throwUninformativeAndGenericDOMException(NotFoundError); | 391 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 392 return NODE_BEFORE; | 392 return NODE_BEFORE; |
| 393 } | 393 } |
| 394 | 394 |
| 395 if (comparePoint(parentNode, nodeIndex, es) < 0) { // starts before | 395 if (comparePoint(parentNode, nodeIndex, exceptionState) < 0) { // starts bef
ore |
| 396 if (comparePoint(parentNode, nodeIndex + 1, es) > 0) // ends after the r
ange | 396 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends
after the range |
| 397 return NODE_BEFORE_AND_AFTER; | 397 return NODE_BEFORE_AND_AFTER; |
| 398 return NODE_BEFORE; // ends before or in the range | 398 return NODE_BEFORE; // ends before or in the range |
| 399 } | 399 } |
| 400 // starts at or after the range start | 400 // starts at or after the range start |
| 401 if (comparePoint(parentNode, nodeIndex + 1, es) > 0) // ends after the range | 401 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft
er the range |
| 402 return NODE_AFTER; | 402 return NODE_AFTER; |
| 403 return NODE_INSIDE; // ends inside the range | 403 return NODE_INSIDE; // ends inside the range |
| 404 } | 404 } |
| 405 | 405 |
| 406 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc
eptionState& es) const | 406 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc
eptionState& exceptionState) const |
| 407 { | 407 { |
| 408 if (!m_start.container()) { | 408 if (!m_start.container()) { |
| 409 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("compareBoundaryPoints", "Range", "The range has no container. Perhaps 'detat
ch()' has been invoked on this object?")); | 409 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("compareBoundaryPoints", "Range", "The range has no container. Pe
rhaps 'detatch()' has been invoked on this object?")); |
| 410 return 0; | 410 return 0; |
| 411 } | 411 } |
| 412 | 412 |
| 413 if (!sourceRange) { | 413 if (!sourceRange) { |
| 414 es.throwUninformativeAndGenericDOMException(NotFoundError); | 414 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 415 return 0; | 415 return 0; |
| 416 } | 416 } |
| 417 | 417 |
| 418 Node* thisCont = commonAncestorContainer(es); | 418 Node* thisCont = commonAncestorContainer(exceptionState); |
| 419 if (es.hadException()) | 419 if (exceptionState.hadException()) |
| 420 return 0; | 420 return 0; |
| 421 Node* sourceCont = sourceRange->commonAncestorContainer(es); | 421 Node* sourceCont = sourceRange->commonAncestorContainer(exceptionState); |
| 422 if (es.hadException()) | 422 if (exceptionState.hadException()) |
| 423 return 0; | 423 return 0; |
| 424 | 424 |
| 425 if (thisCont->document() != sourceCont->document()) { | 425 if (thisCont->document() != sourceCont->document()) { |
| 426 es.throwUninformativeAndGenericDOMException(WrongDocumentError); | 426 exceptionState.throwUninformativeAndGenericDOMException(WrongDocumentErr
or); |
| 427 return 0; | 427 return 0; |
| 428 } | 428 } |
| 429 | 429 |
| 430 Node* thisTop = thisCont; | 430 Node* thisTop = thisCont; |
| 431 Node* sourceTop = sourceCont; | 431 Node* sourceTop = sourceCont; |
| 432 while (thisTop->parentNode()) | 432 while (thisTop->parentNode()) |
| 433 thisTop = thisTop->parentNode(); | 433 thisTop = thisTop->parentNode(); |
| 434 while (sourceTop->parentNode()) | 434 while (sourceTop->parentNode()) |
| 435 sourceTop = sourceTop->parentNode(); | 435 sourceTop = sourceTop->parentNode(); |
| 436 if (thisTop != sourceTop) { // in different DocumentFragments | 436 if (thisTop != sourceTop) { // in different DocumentFragments |
| 437 es.throwUninformativeAndGenericDOMException(WrongDocumentError); | 437 exceptionState.throwUninformativeAndGenericDOMException(WrongDocumentErr
or); |
| 438 return 0; | 438 return 0; |
| 439 } | 439 } |
| 440 | 440 |
| 441 switch (how) { | 441 switch (how) { |
| 442 case START_TO_START: | 442 case START_TO_START: |
| 443 return compareBoundaryPoints(m_start, sourceRange->m_start, es); | 443 return compareBoundaryPoints(m_start, sourceRange->m_start, exceptio
nState); |
| 444 case START_TO_END: | 444 case START_TO_END: |
| 445 return compareBoundaryPoints(m_end, sourceRange->m_start, es); | 445 return compareBoundaryPoints(m_end, sourceRange->m_start, exceptionS
tate); |
| 446 case END_TO_END: | 446 case END_TO_END: |
| 447 return compareBoundaryPoints(m_end, sourceRange->m_end, es); | 447 return compareBoundaryPoints(m_end, sourceRange->m_end, exceptionSta
te); |
| 448 case END_TO_START: | 448 case END_TO_START: |
| 449 return compareBoundaryPoints(m_start, sourceRange->m_end, es); | 449 return compareBoundaryPoints(m_start, sourceRange->m_end, exceptionS
tate); |
| 450 } | 450 } |
| 451 | 451 |
| 452 es.throwUninformativeAndGenericDOMException(SyntaxError); | 452 exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); |
| 453 return 0; | 453 return 0; |
| 454 } | 454 } |
| 455 | 455 |
| 456 short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containe
rB, int offsetB, ExceptionState& es) | 456 short Range::compareBoundaryPoints(Node* containerA, int offsetA, Node* containe
rB, int offsetB, ExceptionState& exceptionState) |
| 457 { | 457 { |
| 458 ASSERT(containerA); | 458 ASSERT(containerA); |
| 459 ASSERT(containerB); | 459 ASSERT(containerB); |
| 460 | 460 |
| 461 if (!containerA) | 461 if (!containerA) |
| 462 return -1; | 462 return -1; |
| 463 if (!containerB) | 463 if (!containerB) |
| 464 return 1; | 464 return 1; |
| 465 | 465 |
| 466 // see DOM2 traversal & range section 2.5 | 466 // see DOM2 traversal & range section 2.5 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 if (offsetC < offsetB) | 508 if (offsetC < offsetB) |
| 509 return -1; // A is before B | 509 return -1; // A is before B |
| 510 else | 510 else |
| 511 return 1; // A is after B | 511 return 1; // A is after B |
| 512 } | 512 } |
| 513 | 513 |
| 514 // case 4: containers A & B are siblings, or children of siblings | 514 // case 4: containers A & B are siblings, or children of siblings |
| 515 // ### we need to do a traversal here instead | 515 // ### we need to do a traversal here instead |
| 516 Node* commonAncestor = commonAncestorContainer(containerA, containerB); | 516 Node* commonAncestor = commonAncestorContainer(containerA, containerB); |
| 517 if (!commonAncestor) { | 517 if (!commonAncestor) { |
| 518 es.throwUninformativeAndGenericDOMException(WrongDocumentError); | 518 exceptionState.throwUninformativeAndGenericDOMException(WrongDocumentErr
or); |
| 519 return 0; | 519 return 0; |
| 520 } | 520 } |
| 521 Node* childA = containerA; | 521 Node* childA = containerA; |
| 522 while (childA && childA->parentNode() != commonAncestor) | 522 while (childA && childA->parentNode() != commonAncestor) |
| 523 childA = childA->parentNode(); | 523 childA = childA->parentNode(); |
| 524 if (!childA) | 524 if (!childA) |
| 525 childA = commonAncestor; | 525 childA = commonAncestor; |
| 526 Node* childB = containerB; | 526 Node* childB = containerB; |
| 527 while (childB && childB->parentNode() != commonAncestor) | 527 while (childB && childB->parentNode() != commonAncestor) |
| 528 childB = childB->parentNode(); | 528 childB = childB->parentNode(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 539 if (n == childB) | 539 if (n == childB) |
| 540 return 1; // A is after B | 540 return 1; // A is after B |
| 541 n = n->nextSibling(); | 541 n = n->nextSibling(); |
| 542 } | 542 } |
| 543 | 543 |
| 544 // Should never reach this point. | 544 // Should never reach this point. |
| 545 ASSERT_NOT_REACHED(); | 545 ASSERT_NOT_REACHED(); |
| 546 return 0; | 546 return 0; |
| 547 } | 547 } |
| 548 | 548 |
| 549 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra
ngeBoundaryPoint& boundaryB, ExceptionState& es) | 549 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra
ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState) |
| 550 { | 550 { |
| 551 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun
daryB.container(), boundaryB.offset(), es); | 551 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun
daryB.container(), boundaryB.offset(), exceptionState); |
| 552 } | 552 } |
| 553 | 553 |
| 554 bool Range::boundaryPointsValid() const | 554 bool Range::boundaryPointsValid() const |
| 555 { | 555 { |
| 556 TrackExceptionState es; | 556 TrackExceptionState exceptionState; |
| 557 return m_start.container() && compareBoundaryPoints(m_start, m_end, es) <= 0
&& !es.hadException(); | 557 return m_start.container() && compareBoundaryPoints(m_start, m_end, exceptio
nState) <= 0 && !exceptionState.hadException(); |
| 558 } | 558 } |
| 559 | 559 |
| 560 void Range::deleteContents(ExceptionState& es) | 560 void Range::deleteContents(ExceptionState& exceptionState) |
| 561 { | 561 { |
| 562 checkDeleteExtract("deleteContents", es); | 562 checkDeleteExtract("deleteContents", exceptionState); |
| 563 if (es.hadException()) | 563 if (exceptionState.hadException()) |
| 564 return; | 564 return; |
| 565 | 565 |
| 566 processContents(DELETE_CONTENTS, es); | 566 processContents(DELETE_CONTENTS, exceptionState); |
| 567 } | 567 } |
| 568 | 568 |
| 569 bool Range::intersectsNode(Node* refNode, ExceptionState& es) | 569 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState) |
| 570 { | 570 { |
| 571 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode | 571 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode |
| 572 // Returns a bool if the node intersects the range. | 572 // Returns a bool if the node intersects the range. |
| 573 | 573 |
| 574 // Throw exception if the range is already detached. | 574 // Throw exception if the range is already detached. |
| 575 if (!m_start.container()) { | 575 if (!m_start.container()) { |
| 576 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("intersectsNode", "Range", "The range has no container. Perhaps 'detatch()' h
as been invoked on this object?")); | 576 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("intersectsNode", "Range", "The range has no container. Perhaps '
detatch()' has been invoked on this object?")); |
| 577 return false; | 577 return false; |
| 578 } | 578 } |
| 579 if (!refNode) { | 579 if (!refNode) { |
| 580 es.throwUninformativeAndGenericDOMException(NotFoundError); | 580 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 581 return false; | 581 return false; |
| 582 } | 582 } |
| 583 | 583 |
| 584 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ | 584 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument)
{ |
| 585 // Firefox doesn't throw an exception for these cases; it returns false. | 585 // Firefox doesn't throw an exception for these cases; it returns false. |
| 586 return false; | 586 return false; |
| 587 } | 587 } |
| 588 | 588 |
| 589 ContainerNode* parentNode = refNode->parentNode(); | 589 ContainerNode* parentNode = refNode->parentNode(); |
| 590 int nodeIndex = refNode->nodeIndex(); | 590 int nodeIndex = refNode->nodeIndex(); |
| 591 | 591 |
| 592 if (!parentNode) { | 592 if (!parentNode) { |
| 593 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R | 593 // if the node is the top document we should return NODE_BEFORE_AND_AFTE
R |
| 594 // but we throw to match firefox behavior | 594 // but we throw to match firefox behavior |
| 595 es.throwUninformativeAndGenericDOMException(NotFoundError); | 595 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 596 return false; | 596 return false; |
| 597 } | 597 } |
| 598 | 598 |
| 599 if (comparePoint(parentNode, nodeIndex, es) < 0 // starts before start | 599 if (comparePoint(parentNode, nodeIndex, exceptionState) < 0 // starts before
start |
| 600 && comparePoint(parentNode, nodeIndex + 1, es) < 0) { // ends before sta
rt | 600 && comparePoint(parentNode, nodeIndex + 1, exceptionState) < 0) { // end
s before start |
| 601 return false; | 601 return false; |
| 602 } | 602 } |
| 603 | 603 |
| 604 if (comparePoint(parentNode, nodeIndex, es) > 0 // starts after end | 604 if (comparePoint(parentNode, nodeIndex, exceptionState) > 0 // starts after
end |
| 605 && comparePoint(parentNode, nodeIndex + 1, es) > 0) { // ends after end | 605 && comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) { // end
s after end |
| 606 return false; | 606 return false; |
| 607 } | 607 } |
| 608 | 608 |
| 609 return true; // all other cases | 609 return true; // all other cases |
| 610 } | 610 } |
| 611 | 611 |
| 612 static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot) | 612 static inline Node* highestAncestorUnderCommonRoot(Node* node, Node* commonRoot) |
| 613 { | 613 { |
| 614 if (node == commonRoot) | 614 if (node == commonRoot) |
| 615 return 0; | 615 return 0; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 case Node::DOCUMENT_TYPE_NODE: | 659 case Node::DOCUMENT_TYPE_NODE: |
| 660 case Node::DOCUMENT_FRAGMENT_NODE: | 660 case Node::DOCUMENT_FRAGMENT_NODE: |
| 661 case Node::NOTATION_NODE: | 661 case Node::NOTATION_NODE: |
| 662 case Node::XPATH_NAMESPACE_NODE: | 662 case Node::XPATH_NAMESPACE_NODE: |
| 663 return node->childNodeCount(); | 663 return node->childNodeCount(); |
| 664 } | 664 } |
| 665 ASSERT_NOT_REACHED(); | 665 ASSERT_NOT_REACHED(); |
| 666 return 0; | 666 return 0; |
| 667 } | 667 } |
| 668 | 668 |
| 669 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
State& es) | 669 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
State& exceptionState) |
| 670 { | 670 { |
| 671 typedef Vector<RefPtr<Node> > NodeVector; | 671 typedef Vector<RefPtr<Node> > NodeVector; |
| 672 | 672 |
| 673 RefPtr<DocumentFragment> fragment; | 673 RefPtr<DocumentFragment> fragment; |
| 674 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | 674 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
| 675 fragment = DocumentFragment::create(*m_ownerDocument.get()); | 675 fragment = DocumentFragment::create(*m_ownerDocument.get()); |
| 676 | 676 |
| 677 if (collapsed(es)) | 677 if (collapsed(exceptionState)) |
| 678 return fragment.release(); | 678 return fragment.release(); |
| 679 if (es.hadException()) | 679 if (exceptionState.hadException()) |
| 680 return 0; | 680 return 0; |
| 681 | 681 |
| 682 RefPtr<Node> commonRoot = commonAncestorContainer(es); | 682 RefPtr<Node> commonRoot = commonAncestorContainer(exceptionState); |
| 683 if (es.hadException()) | 683 if (exceptionState.hadException()) |
| 684 return 0; | 684 return 0; |
| 685 ASSERT(commonRoot); | 685 ASSERT(commonRoot); |
| 686 | 686 |
| 687 if (m_start.container() == m_end.container()) { | 687 if (m_start.container() == m_end.container()) { |
| 688 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s
tart.offset(), m_end.offset(), es); | 688 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s
tart.offset(), m_end.offset(), exceptionState); |
| 689 return fragment; | 689 return fragment; |
| 690 } | 690 } |
| 691 | 691 |
| 692 // Since mutation observers can modify the range during the process, the bou
ndary points need to be saved. | 692 // Since mutation observers can modify the range during the process, the bou
ndary points need to be saved. |
| 693 RangeBoundaryPoint originalStart(m_start); | 693 RangeBoundaryPoint originalStart(m_start); |
| 694 RangeBoundaryPoint originalEnd(m_end); | 694 RangeBoundaryPoint originalEnd(m_end); |
| 695 | 695 |
| 696 // what is the highest node that partially selects the start / end of the ra
nge? | 696 // what is the highest node that partially selects the start / end of the ra
nge? |
| 697 RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(originalStart.con
tainer(), commonRoot.get()); | 697 RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(originalStart.con
tainer(), commonRoot.get()); |
| 698 RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(originalEnd.contain
er(), commonRoot.get()); | 698 RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(originalEnd.contain
er(), commonRoot.get()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 712 // in which case the last lot of nodes either goes from the first or last | 712 // in which case the last lot of nodes either goes from the first or last |
| 713 // child of commonRoot. | 713 // child of commonRoot. |
| 714 // | 714 // |
| 715 // These are deleted, cloned, or extracted (i.e. both) depending on action. | 715 // These are deleted, cloned, or extracted (i.e. both) depending on action. |
| 716 | 716 |
| 717 // Note that we are verifying that our common root hierarchy is still intact | 717 // Note that we are verifying that our common root hierarchy is still intact |
| 718 // after any DOM mutation event, at various stages below. See webkit bug 603
50. | 718 // after any DOM mutation event, at various stages below. See webkit bug 603
50. |
| 719 | 719 |
| 720 RefPtr<Node> leftContents; | 720 RefPtr<Node> leftContents; |
| 721 if (originalStart.container() != commonRoot && commonRoot->contains(original
Start.container())) { | 721 if (originalStart.container() != commonRoot && commonRoot->contains(original
Start.container())) { |
| 722 leftContents = processContentsBetweenOffsets(action, 0, originalStart.co
ntainer(), originalStart.offset(), lengthOfContentsInNode(originalStart.containe
r()), es); | 722 leftContents = processContentsBetweenOffsets(action, 0, originalStart.co
ntainer(), originalStart.offset(), lengthOfContentsInNode(originalStart.containe
r()), exceptionState); |
| 723 leftContents = processAncestorsAndTheirSiblings(action, originalStart.co
ntainer(), ProcessContentsForward, leftContents, commonRoot.get(), es); | 723 leftContents = processAncestorsAndTheirSiblings(action, originalStart.co
ntainer(), ProcessContentsForward, leftContents, commonRoot.get(), exceptionStat
e); |
| 724 } | 724 } |
| 725 | 725 |
| 726 RefPtr<Node> rightContents; | 726 RefPtr<Node> rightContents; |
| 727 if (m_end.container() != commonRoot && commonRoot->contains(originalEnd.cont
ainer())) { | 727 if (m_end.container() != commonRoot && commonRoot->contains(originalEnd.cont
ainer())) { |
| 728 rightContents = processContentsBetweenOffsets(action, 0, originalEnd.con
tainer(), 0, originalEnd.offset(), es); | 728 rightContents = processContentsBetweenOffsets(action, 0, originalEnd.con
tainer(), 0, originalEnd.offset(), exceptionState); |
| 729 rightContents = processAncestorsAndTheirSiblings(action, originalEnd.con
tainer(), ProcessContentsBackward, rightContents, commonRoot.get(), es); | 729 rightContents = processAncestorsAndTheirSiblings(action, originalEnd.con
tainer(), ProcessContentsBackward, rightContents, commonRoot.get(), exceptionSta
te); |
| 730 } | 730 } |
| 731 | 731 |
| 732 // delete all children of commonRoot between the start and end container | 732 // delete all children of commonRoot between the start and end container |
| 733 RefPtr<Node> processStart = childOfCommonRootBeforeOffset(originalStart.cont
ainer(), originalStart.offset(), commonRoot.get()); | 733 RefPtr<Node> processStart = childOfCommonRootBeforeOffset(originalStart.cont
ainer(), originalStart.offset(), commonRoot.get()); |
| 734 if (processStart && originalStart.container() != commonRoot) // processStart
contains nodes before m_start. | 734 if (processStart && originalStart.container() != commonRoot) // processStart
contains nodes before m_start. |
| 735 processStart = processStart->nextSibling(); | 735 processStart = processStart->nextSibling(); |
| 736 RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(originalEnd.containe
r(), originalEnd.offset(), commonRoot.get()); | 736 RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(originalEnd.containe
r(), originalEnd.offset(), commonRoot.get()); |
| 737 | 737 |
| 738 // Collapse the range, making sure that the result is not within a node that
was partially selected. | 738 // Collapse the range, making sure that the result is not within a node that
was partially selected. |
| 739 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 739 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
| 740 if (partialStart && commonRoot->contains(partialStart.get())) { | 740 if (partialStart && commonRoot->contains(partialStart.get())) { |
| 741 // FIXME: We should not continue if we have an earlier error. | 741 // FIXME: We should not continue if we have an earlier error. |
| 742 es.clearException(); | 742 exceptionState.clearException(); |
| 743 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1,
es); | 743 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1,
exceptionState); |
| 744 } else if (partialEnd && commonRoot->contains(partialEnd.get())) { | 744 } else if (partialEnd && commonRoot->contains(partialEnd.get())) { |
| 745 // FIXME: We should not continue if we have an earlier error. | 745 // FIXME: We should not continue if we have an earlier error. |
| 746 es.clearException(); | 746 exceptionState.clearException(); |
| 747 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), es); | 747 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), exceptio
nState); |
| 748 } | 748 } |
| 749 if (es.hadException()) | 749 if (exceptionState.hadException()) |
| 750 return 0; | 750 return 0; |
| 751 m_end = m_start; | 751 m_end = m_start; |
| 752 } | 752 } |
| 753 | 753 |
| 754 originalStart.clear(); | 754 originalStart.clear(); |
| 755 originalEnd.clear(); | 755 originalEnd.clear(); |
| 756 | 756 |
| 757 // Now add leftContents, stuff in between, and rightContents to the fragment | 757 // Now add leftContents, stuff in between, and rightContents to the fragment |
| 758 // (or just delete the stuff in between) | 758 // (or just delete the stuff in between) |
| 759 | 759 |
| 760 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents
) | 760 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents
) |
| 761 fragment->appendChild(leftContents, es); | 761 fragment->appendChild(leftContents, exceptionState); |
| 762 | 762 |
| 763 if (processStart) { | 763 if (processStart) { |
| 764 NodeVector nodes; | 764 NodeVector nodes; |
| 765 for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibl
ing()) | 765 for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibl
ing()) |
| 766 nodes.append(n); | 766 nodes.append(n); |
| 767 processNodes(action, nodes, commonRoot, fragment, es); | 767 processNodes(action, nodes, commonRoot, fragment, exceptionState); |
| 768 } | 768 } |
| 769 | 769 |
| 770 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContent
s) | 770 if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContent
s) |
| 771 fragment->appendChild(rightContents, es); | 771 fragment->appendChild(rightContents, exceptionState); |
| 772 | 772 |
| 773 return fragment.release(); | 773 return fragment.release(); |
| 774 } | 774 } |
| 775 | 775 |
| 776 static inline void deleteCharacterData(PassRefPtr<CharacterData> data, unsigned
startOffset, unsigned endOffset, ExceptionState& es) | 776 static inline void deleteCharacterData(PassRefPtr<CharacterData> data, unsigned
startOffset, unsigned endOffset, ExceptionState& exceptionState) |
| 777 { | 777 { |
| 778 if (data->length() - endOffset) | 778 if (data->length() - endOffset) |
| 779 data->deleteData(endOffset, data->length() - endOffset, es); | 779 data->deleteData(endOffset, data->length() - endOffset, exceptionState); |
| 780 if (startOffset) | 780 if (startOffset) |
| 781 data->deleteData(0, startOffset, es); | 781 data->deleteData(0, startOffset, exceptionState); |
| 782 } | 782 } |
| 783 | 783 |
| 784 PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRef
Ptr<DocumentFragment> fragment, | 784 PassRefPtr<Node> Range::processContentsBetweenOffsets(ActionType action, PassRef
Ptr<DocumentFragment> fragment, |
| 785 Node* container, unsigned startOffset, unsigned endOffset, ExceptionState& e
s) | 785 Node* container, unsigned startOffset, unsigned endOffset, ExceptionState& e
xceptionState) |
| 786 { | 786 { |
| 787 ASSERT(container); | 787 ASSERT(container); |
| 788 ASSERT(startOffset <= endOffset); | 788 ASSERT(startOffset <= endOffset); |
| 789 | 789 |
| 790 // This switch statement must be consistent with that of lengthOfContentsInN
ode. | 790 // This switch statement must be consistent with that of lengthOfContentsInN
ode. |
| 791 RefPtr<Node> result; | 791 RefPtr<Node> result; |
| 792 switch (container->nodeType()) { | 792 switch (container->nodeType()) { |
| 793 case Node::TEXT_NODE: | 793 case Node::TEXT_NODE: |
| 794 case Node::CDATA_SECTION_NODE: | 794 case Node::CDATA_SECTION_NODE: |
| 795 case Node::COMMENT_NODE: | 795 case Node::COMMENT_NODE: |
| 796 endOffset = std::min(endOffset, toCharacterData(container)->length()); | 796 endOffset = std::min(endOffset, toCharacterData(container)->length()); |
| 797 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | 797 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
| 798 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(contain
er->cloneNode(true)); | 798 RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(contain
er->cloneNode(true)); |
| 799 deleteCharacterData(c, startOffset, endOffset, es); | 799 deleteCharacterData(c, startOffset, endOffset, exceptionState); |
| 800 if (fragment) { | 800 if (fragment) { |
| 801 result = fragment; | 801 result = fragment; |
| 802 result->appendChild(c.release(), es); | 802 result->appendChild(c.release(), exceptionState); |
| 803 } else | 803 } else |
| 804 result = c.release(); | 804 result = c.release(); |
| 805 } | 805 } |
| 806 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) | 806 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) |
| 807 toCharacterData(container)->deleteData(startOffset, endOffset - star
tOffset, es); | 807 toCharacterData(container)->deleteData(startOffset, endOffset - star
tOffset, exceptionState); |
| 808 break; | 808 break; |
| 809 case Node::PROCESSING_INSTRUCTION_NODE: | 809 case Node::PROCESSING_INSTRUCTION_NODE: |
| 810 endOffset = std::min(endOffset, toProcessingInstruction(container)->data
().length()); | 810 endOffset = std::min(endOffset, toProcessingInstruction(container)->data
().length()); |
| 811 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | 811 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
| 812 RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInst
ruction>(container->cloneNode(true)); | 812 RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInst
ruction>(container->cloneNode(true)); |
| 813 c->setData(c->data().substring(startOffset, endOffset - startOffset)
); | 813 c->setData(c->data().substring(startOffset, endOffset - startOffset)
); |
| 814 if (fragment) { | 814 if (fragment) { |
| 815 result = fragment; | 815 result = fragment; |
| 816 result->appendChild(c.release(), es); | 816 result->appendChild(c.release(), exceptionState); |
| 817 } else | 817 } else |
| 818 result = c.release(); | 818 result = c.release(); |
| 819 } | 819 } |
| 820 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 820 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
| 821 ProcessingInstruction* pi = toProcessingInstruction(container); | 821 ProcessingInstruction* pi = toProcessingInstruction(container); |
| 822 String data(pi->data()); | 822 String data(pi->data()); |
| 823 data.remove(startOffset, endOffset - startOffset); | 823 data.remove(startOffset, endOffset - startOffset); |
| 824 pi->setData(data); | 824 pi->setData(data); |
| 825 } | 825 } |
| 826 break; | 826 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 840 result = container->cloneNode(false); | 840 result = container->cloneNode(false); |
| 841 } | 841 } |
| 842 | 842 |
| 843 Node* n = container->firstChild(); | 843 Node* n = container->firstChild(); |
| 844 Vector<RefPtr<Node> > nodes; | 844 Vector<RefPtr<Node> > nodes; |
| 845 for (unsigned i = startOffset; n && i; i--) | 845 for (unsigned i = startOffset; n && i; i--) |
| 846 n = n->nextSibling(); | 846 n = n->nextSibling(); |
| 847 for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibli
ng()) | 847 for (unsigned i = startOffset; n && i < endOffset; i++, n = n->nextSibli
ng()) |
| 848 nodes.append(n); | 848 nodes.append(n); |
| 849 | 849 |
| 850 processNodes(action, nodes, container, result, es); | 850 processNodes(action, nodes, container, result, exceptionState); |
| 851 break; | 851 break; |
| 852 } | 852 } |
| 853 | 853 |
| 854 return result.release(); | 854 return result.release(); |
| 855 } | 855 } |
| 856 | 856 |
| 857 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRe
fPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionState& es) | 857 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRe
fPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionState& exceptio
nState) |
| 858 { | 858 { |
| 859 for (unsigned i = 0; i < nodes.size(); i++) { | 859 for (unsigned i = 0; i < nodes.size(); i++) { |
| 860 switch (action) { | 860 switch (action) { |
| 861 case DELETE_CONTENTS: | 861 case DELETE_CONTENTS: |
| 862 oldContainer->removeChild(nodes[i].get(), es); | 862 oldContainer->removeChild(nodes[i].get(), exceptionState); |
| 863 break; | 863 break; |
| 864 case EXTRACT_CONTENTS: | 864 case EXTRACT_CONTENTS: |
| 865 newContainer->appendChild(nodes[i].release(), es); // will remove n
from its parent | 865 newContainer->appendChild(nodes[i].release(), exceptionState); // wi
ll remove n from its parent |
| 866 break; | 866 break; |
| 867 case CLONE_CONTENTS: | 867 case CLONE_CONTENTS: |
| 868 newContainer->appendChild(nodes[i]->cloneNode(true), es); | 868 newContainer->appendChild(nodes[i]->cloneNode(true), exceptionState)
; |
| 869 break; | 869 break; |
| 870 } | 870 } |
| 871 } | 871 } |
| 872 } | 872 } |
| 873 | 873 |
| 874 PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node
* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedCo
ntainer, Node* commonRoot, ExceptionState& es) | 874 PassRefPtr<Node> Range::processAncestorsAndTheirSiblings(ActionType action, Node
* container, ContentsProcessDirection direction, PassRefPtr<Node> passedClonedCo
ntainer, Node* commonRoot, ExceptionState& exceptionState) |
| 875 { | 875 { |
| 876 typedef Vector<RefPtr<Node> > NodeVector; | 876 typedef Vector<RefPtr<Node> > NodeVector; |
| 877 | 877 |
| 878 RefPtr<Node> clonedContainer = passedClonedContainer; | 878 RefPtr<Node> clonedContainer = passedClonedContainer; |
| 879 Vector<RefPtr<Node> > ancestors; | 879 Vector<RefPtr<Node> > ancestors; |
| 880 for (ContainerNode* n = container->parentNode(); n && n != commonRoot; n = n
->parentNode()) | 880 for (ContainerNode* n = container->parentNode(); n && n != commonRoot; n = n
->parentNode()) |
| 881 ancestors.append(n); | 881 ancestors.append(n); |
| 882 | 882 |
| 883 RefPtr<Node> firstChildInAncestorToProcess = direction == ProcessContentsFor
ward ? container->nextSibling() : container->previousSibling(); | 883 RefPtr<Node> firstChildInAncestorToProcess = direction == ProcessContentsFor
ward ? container->nextSibling() : container->previousSibling(); |
| 884 for (Vector<RefPtr<Node> >::const_iterator it = ancestors.begin(); it != anc
estors.end(); it++) { | 884 for (Vector<RefPtr<Node> >::const_iterator it = ancestors.begin(); it != anc
estors.end(); it++) { |
| 885 RefPtr<Node> ancestor = *it; | 885 RefPtr<Node> ancestor = *it; |
| 886 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | 886 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
| 887 if (RefPtr<Node> clonedAncestor = ancestor->cloneNode(false)) { // M
ight have been removed already during mutation event. | 887 if (RefPtr<Node> clonedAncestor = ancestor->cloneNode(false)) { // M
ight have been removed already during mutation event. |
| 888 clonedAncestor->appendChild(clonedContainer, es); | 888 clonedAncestor->appendChild(clonedContainer, exceptionState); |
| 889 clonedContainer = clonedAncestor; | 889 clonedContainer = clonedAncestor; |
| 890 } | 890 } |
| 891 } | 891 } |
| 892 | 892 |
| 893 // Copy siblings of an ancestor of start/end containers | 893 // Copy siblings of an ancestor of start/end containers |
| 894 // FIXME: This assertion may fail if DOM is modified during mutation eve
nt | 894 // FIXME: This assertion may fail if DOM is modified during mutation eve
nt |
| 895 // FIXME: Share code with Range::processNodes | 895 // FIXME: Share code with Range::processNodes |
| 896 ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->
parentNode() == ancestor); | 896 ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->
parentNode() == ancestor); |
| 897 | 897 |
| 898 NodeVector nodes; | 898 NodeVector nodes; |
| 899 for (Node* child = firstChildInAncestorToProcess.get(); child; | 899 for (Node* child = firstChildInAncestorToProcess.get(); child; |
| 900 child = (direction == ProcessContentsForward) ? child->nextSibling()
: child->previousSibling()) | 900 child = (direction == ProcessContentsForward) ? child->nextSibling()
: child->previousSibling()) |
| 901 nodes.append(child); | 901 nodes.append(child); |
| 902 | 902 |
| 903 for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); i
t++) { | 903 for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); i
t++) { |
| 904 Node* child = it->get(); | 904 Node* child = it->get(); |
| 905 switch (action) { | 905 switch (action) { |
| 906 case DELETE_CONTENTS: | 906 case DELETE_CONTENTS: |
| 907 ancestor->removeChild(child, es); | 907 ancestor->removeChild(child, exceptionState); |
| 908 break; | 908 break; |
| 909 case EXTRACT_CONTENTS: // will remove child from ancestor | 909 case EXTRACT_CONTENTS: // will remove child from ancestor |
| 910 if (direction == ProcessContentsForward) | 910 if (direction == ProcessContentsForward) |
| 911 clonedContainer->appendChild(child, es); | 911 clonedContainer->appendChild(child, exceptionState); |
| 912 else | 912 else |
| 913 clonedContainer->insertBefore(child, clonedContainer->firstC
hild(), es); | 913 clonedContainer->insertBefore(child, clonedContainer->firstC
hild(), exceptionState); |
| 914 break; | 914 break; |
| 915 case CLONE_CONTENTS: | 915 case CLONE_CONTENTS: |
| 916 if (direction == ProcessContentsForward) | 916 if (direction == ProcessContentsForward) |
| 917 clonedContainer->appendChild(child->cloneNode(true), es); | 917 clonedContainer->appendChild(child->cloneNode(true), excepti
onState); |
| 918 else | 918 else |
| 919 clonedContainer->insertBefore(child->cloneNode(true), cloned
Container->firstChild(), es); | 919 clonedContainer->insertBefore(child->cloneNode(true), cloned
Container->firstChild(), exceptionState); |
| 920 break; | 920 break; |
| 921 } | 921 } |
| 922 } | 922 } |
| 923 firstChildInAncestorToProcess = direction == ProcessContentsForward ? an
cestor->nextSibling() : ancestor->previousSibling(); | 923 firstChildInAncestorToProcess = direction == ProcessContentsForward ? an
cestor->nextSibling() : ancestor->previousSibling(); |
| 924 } | 924 } |
| 925 | 925 |
| 926 return clonedContainer.release(); | 926 return clonedContainer.release(); |
| 927 } | 927 } |
| 928 | 928 |
| 929 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionState& es) | 929 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionState& exceptionSta
te) |
| 930 { | 930 { |
| 931 checkDeleteExtract("extractContents", es); | 931 checkDeleteExtract("extractContents", exceptionState); |
| 932 if (es.hadException()) | 932 if (exceptionState.hadException()) |
| 933 return 0; | 933 return 0; |
| 934 | 934 |
| 935 return processContents(EXTRACT_CONTENTS, es); | 935 return processContents(EXTRACT_CONTENTS, exceptionState); |
| 936 } | 936 } |
| 937 | 937 |
| 938 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& es) | 938 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState
) |
| 939 { | 939 { |
| 940 if (!m_start.container()) { | 940 if (!m_start.container()) { |
| 941 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("cloneContents", "Range", "The range has no container. Perhaps 'detatch()' ha
s been invoked on this object?")); | 941 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("cloneContents", "Range", "The range has no container. Perhaps 'd
etatch()' has been invoked on this object?")); |
| 942 return 0; | 942 return 0; |
| 943 } | 943 } |
| 944 | 944 |
| 945 return processContents(CLONE_CONTENTS, es); | 945 return processContents(CLONE_CONTENTS, exceptionState); |
| 946 } | 946 } |
| 947 | 947 |
| 948 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& es) | 948 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta
te) |
| 949 { | 949 { |
| 950 RefPtr<Node> newNode = prpNewNode; | 950 RefPtr<Node> newNode = prpNewNode; |
| 951 | 951 |
| 952 if (!m_start.container()) { | 952 if (!m_start.container()) { |
| 953 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("insertNode", "Range", "The range has no container. Perhaps 'detatch()' has b
een invoked on this object?")); | 953 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("insertNode", "Range", "The range has no container. Perhaps 'deta
tch()' has been invoked on this object?")); |
| 954 return; | 954 return; |
| 955 } | 955 } |
| 956 | 956 |
| 957 if (!newNode) { | 957 if (!newNode) { |
| 958 es.throwUninformativeAndGenericDOMException(NotFoundError); | 958 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 959 return; | 959 return; |
| 960 } | 960 } |
| 961 | 961 |
| 962 // HierarchyRequestError: Raised if the container of the start of the Range
is of a type that | 962 // HierarchyRequestError: Raised if the container of the start of the Range
is of a type that |
| 963 // does not allow children of the type of newNode or if newNode is an ancest
or of the container. | 963 // does not allow children of the type of newNode or if newNode is an ancest
or of the container. |
| 964 | 964 |
| 965 // an extra one here - if a text node is going to split, it must have a pare
nt to insert into | 965 // an extra one here - if a text node is going to split, it must have a pare
nt to insert into |
| 966 bool startIsText = m_start.container()->isTextNode(); | 966 bool startIsText = m_start.container()->isTextNode(); |
| 967 if (startIsText && !m_start.container()->parentNode()) { | 967 if (startIsText && !m_start.container()->parentNode()) { |
| 968 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 968 exceptionState.throwUninformativeAndGenericDOMException(HierarchyRequest
Error); |
| 969 return; | 969 return; |
| 970 } | 970 } |
| 971 | 971 |
| 972 // In the case where the container is a text node, we check against the cont
ainer's parent, because | 972 // In the case where the container is a text node, we check against the cont
ainer's parent, because |
| 973 // text nodes get split up upon insertion. | 973 // text nodes get split up upon insertion. |
| 974 Node* checkAgainst; | 974 Node* checkAgainst; |
| 975 if (startIsText) | 975 if (startIsText) |
| 976 checkAgainst = m_start.container()->parentNode(); | 976 checkAgainst = m_start.container()->parentNode(); |
| 977 else | 977 else |
| 978 checkAgainst = m_start.container(); | 978 checkAgainst = m_start.container(); |
| 979 | 979 |
| 980 Node::NodeType newNodeType = newNode->nodeType(); | 980 Node::NodeType newNodeType = newNode->nodeType(); |
| 981 int numNewChildren; | 981 int numNewChildren; |
| 982 if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE && !newNode->isShadowRoot())
{ | 982 if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE && !newNode->isShadowRoot())
{ |
| 983 // check each child node, not the DocumentFragment itself | 983 // check each child node, not the DocumentFragment itself |
| 984 numNewChildren = 0; | 984 numNewChildren = 0; |
| 985 for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) { | 985 for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) { |
| 986 if (!checkAgainst->childTypeAllowed(c->nodeType())) { | 986 if (!checkAgainst->childTypeAllowed(c->nodeType())) { |
| 987 es.throwUninformativeAndGenericDOMException(HierarchyRequestErro
r); | 987 exceptionState.throwUninformativeAndGenericDOMException(Hierarch
yRequestError); |
| 988 return; | 988 return; |
| 989 } | 989 } |
| 990 ++numNewChildren; | 990 ++numNewChildren; |
| 991 } | 991 } |
| 992 } else { | 992 } else { |
| 993 numNewChildren = 1; | 993 numNewChildren = 1; |
| 994 if (!checkAgainst->childTypeAllowed(newNodeType)) { | 994 if (!checkAgainst->childTypeAllowed(newNodeType)) { |
| 995 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 995 exceptionState.throwUninformativeAndGenericDOMException(HierarchyReq
uestError); |
| 996 return; | 996 return; |
| 997 } | 997 } |
| 998 } | 998 } |
| 999 | 999 |
| 1000 for (Node* n = m_start.container(); n; n = n->parentNode()) { | 1000 for (Node* n = m_start.container(); n; n = n->parentNode()) { |
| 1001 if (n == newNode) { | 1001 if (n == newNode) { |
| 1002 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 1002 exceptionState.throwUninformativeAndGenericDOMException(HierarchyReq
uestError); |
| 1003 return; | 1003 return; |
| 1004 } | 1004 } |
| 1005 } | 1005 } |
| 1006 | 1006 |
| 1007 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, Sha
dowRoot or Document node. | 1007 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, Sha
dowRoot or Document node. |
| 1008 switch (newNodeType) { | 1008 switch (newNodeType) { |
| 1009 case Node::ATTRIBUTE_NODE: | 1009 case Node::ATTRIBUTE_NODE: |
| 1010 case Node::ENTITY_NODE: | 1010 case Node::ENTITY_NODE: |
| 1011 case Node::NOTATION_NODE: | 1011 case Node::NOTATION_NODE: |
| 1012 case Node::DOCUMENT_NODE: | 1012 case Node::DOCUMENT_NODE: |
| 1013 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1013 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeTypeE
rror); |
| 1014 return; | 1014 return; |
| 1015 default: | 1015 default: |
| 1016 if (newNode->isShadowRoot()) { | 1016 if (newNode->isShadowRoot()) { |
| 1017 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1017 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeT
ypeError); |
| 1018 return; | 1018 return; |
| 1019 } | 1019 } |
| 1020 break; | 1020 break; |
| 1021 } | 1021 } |
| 1022 | 1022 |
| 1023 EventQueueScope scope; | 1023 EventQueueScope scope; |
| 1024 bool collapsed = m_start == m_end; | 1024 bool collapsed = m_start == m_end; |
| 1025 RefPtr<Node> container; | 1025 RefPtr<Node> container; |
| 1026 if (startIsText) { | 1026 if (startIsText) { |
| 1027 container = m_start.container(); | 1027 container = m_start.container(); |
| 1028 RefPtr<Text> newText = toText(container)->splitText(m_start.offset(), es
); | 1028 RefPtr<Text> newText = toText(container)->splitText(m_start.offset(), ex
ceptionState); |
| 1029 if (es.hadException()) | 1029 if (exceptionState.hadException()) |
| 1030 return; | 1030 return; |
| 1031 | 1031 |
| 1032 container = m_start.container(); | 1032 container = m_start.container(); |
| 1033 container->parentNode()->insertBefore(newNode.release(), newText.get(),
es); | 1033 container->parentNode()->insertBefore(newNode.release(), newText.get(),
exceptionState); |
| 1034 if (es.hadException()) | 1034 if (exceptionState.hadException()) |
| 1035 return; | 1035 return; |
| 1036 | 1036 |
| 1037 if (collapsed) | 1037 if (collapsed) |
| 1038 m_end.setToBeforeChild(*newText); | 1038 m_end.setToBeforeChild(*newText); |
| 1039 } else { | 1039 } else { |
| 1040 RefPtr<Node> lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ?
newNode->lastChild() : newNode; | 1040 RefPtr<Node> lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ?
newNode->lastChild() : newNode; |
| 1041 if (lastChild && lastChild == m_start.childBefore()) { | 1041 if (lastChild && lastChild == m_start.childBefore()) { |
| 1042 // The insertion will do nothing, but we need to extend the range to
include | 1042 // The insertion will do nothing, but we need to extend the range to
include |
| 1043 // the inserted nodes. | 1043 // the inserted nodes. |
| 1044 Node* firstChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? n
ewNode->firstChild() : newNode.get(); | 1044 Node* firstChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? n
ewNode->firstChild() : newNode.get(); |
| 1045 ASSERT(firstChild); | 1045 ASSERT(firstChild); |
| 1046 m_start.setToBeforeChild(*firstChild); | 1046 m_start.setToBeforeChild(*firstChild); |
| 1047 return; | 1047 return; |
| 1048 } | 1048 } |
| 1049 | 1049 |
| 1050 container = m_start.container(); | 1050 container = m_start.container(); |
| 1051 container->insertBefore(newNode.release(), container->childNode(m_start.
offset()), es); | 1051 container->insertBefore(newNode.release(), container->childNode(m_start.
offset()), exceptionState); |
| 1052 if (es.hadException()) | 1052 if (exceptionState.hadException()) |
| 1053 return; | 1053 return; |
| 1054 | 1054 |
| 1055 // Note that m_start.offset() may have changed as a result of container-
>insertBefore, | 1055 // Note that m_start.offset() may have changed as a result of container-
>insertBefore, |
| 1056 // when the node we are inserting comes before the range in the same con
tainer. | 1056 // when the node we are inserting comes before the range in the same con
tainer. |
| 1057 if (collapsed && numNewChildren) | 1057 if (collapsed && numNewChildren) |
| 1058 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la
stChild.get()); | 1058 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la
stChild.get()); |
| 1059 } | 1059 } |
| 1060 } | 1060 } |
| 1061 | 1061 |
| 1062 String Range::toString(ExceptionState& es) const | 1062 String Range::toString(ExceptionState& exceptionState) const |
| 1063 { | 1063 { |
| 1064 if (!m_start.container()) { | 1064 if (!m_start.container()) { |
| 1065 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("toString", "Range", "The range has no container. Perhaps 'detatch()' has bee
n invoked on this object?")); | 1065 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("toString", "Range", "The range has no container. Perhaps 'detatc
h()' has been invoked on this object?")); |
| 1066 return String(); | 1066 return String(); |
| 1067 } | 1067 } |
| 1068 | 1068 |
| 1069 StringBuilder builder; | 1069 StringBuilder builder; |
| 1070 | 1070 |
| 1071 Node* pastLast = pastLastNode(); | 1071 Node* pastLast = pastLastNode(); |
| 1072 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { | 1072 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { |
| 1073 if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SEC
TION_NODE) { | 1073 if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SEC
TION_NODE) { |
| 1074 String data = toCharacterData(n)->data(); | 1074 String data = toCharacterData(n)->data(); |
| 1075 int length = data.length(); | 1075 int length = data.length(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1092 if (!m_start.container()) | 1092 if (!m_start.container()) |
| 1093 return String(); | 1093 return String(); |
| 1094 | 1094 |
| 1095 // We need to update layout, since plainText uses line boxes in the render t
ree. | 1095 // We need to update layout, since plainText uses line boxes in the render t
ree. |
| 1096 // FIXME: As with innerText, we'd like this to work even if there are no ren
der objects. | 1096 // FIXME: As with innerText, we'd like this to work even if there are no ren
der objects. |
| 1097 m_start.container()->document().updateLayout(); | 1097 m_start.container()->document().updateLayout(); |
| 1098 | 1098 |
| 1099 return plainText(this); | 1099 return plainText(this); |
| 1100 } | 1100 } |
| 1101 | 1101 |
| 1102 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku
p, ExceptionState& es) | 1102 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku
p, ExceptionState& exceptionState) |
| 1103 { | 1103 { |
| 1104 if (!m_start.container()) { | 1104 if (!m_start.container()) { |
| 1105 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("createContextualFragment", "Range", "The range has no container. Perhaps 'de
tatch()' has been invoked on this object?")); | 1105 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("createContextualFragment", "Range", "The range has no container.
Perhaps 'detatch()' has been invoked on this object?")); |
| 1106 return 0; | 1106 return 0; |
| 1107 } | 1107 } |
| 1108 | 1108 |
| 1109 Node* element = m_start.container()->isElementNode() ? m_start.container() :
m_start.container()->parentNode(); | 1109 Node* element = m_start.container()->isElementNode() ? m_start.container() :
m_start.container()->parentNode(); |
| 1110 if (!element || !element->isHTMLElement()) { | 1110 if (!element || !element->isHTMLElement()) { |
| 1111 es.throwDOMException(NotSupportedError, ExceptionMessages::failedToExecu
te("createContextualFragment", "Range", "The range's container must be an HTML e
lement.")); | 1111 exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::f
ailedToExecute("createContextualFragment", "Range", "The range's container must
be an HTML element.")); |
| 1112 return 0; | 1112 return 0; |
| 1113 } | 1113 } |
| 1114 | 1114 |
| 1115 RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup
, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, es); | 1115 RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup
, toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, excep
tionState); |
| 1116 if (!fragment) | 1116 if (!fragment) |
| 1117 return 0; | 1117 return 0; |
| 1118 | 1118 |
| 1119 return fragment.release(); | 1119 return fragment.release(); |
| 1120 } | 1120 } |
| 1121 | 1121 |
| 1122 | 1122 |
| 1123 void Range::detach(ExceptionState& es) | 1123 void Range::detach(ExceptionState& exceptionState) |
| 1124 { | 1124 { |
| 1125 // Check first to see if we've already detached: | 1125 // Check first to see if we've already detached: |
| 1126 if (!m_start.container()) { | 1126 if (!m_start.container()) { |
| 1127 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("detach", "Range", "The range has no container. Perhaps 'detatch()' has been
invoked on this object?")); | 1127 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("detach", "Range", "The range has no container. Perhaps 'detatch(
)' has been invoked on this object?")); |
| 1128 return; | 1128 return; |
| 1129 } | 1129 } |
| 1130 | 1130 |
| 1131 m_ownerDocument->detachRange(this); | 1131 m_ownerDocument->detachRange(this); |
| 1132 | 1132 |
| 1133 m_start.clear(); | 1133 m_start.clear(); |
| 1134 m_end.clear(); | 1134 m_end.clear(); |
| 1135 } | 1135 } |
| 1136 | 1136 |
| 1137 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& es) const | 1137 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat
e) const |
| 1138 { | 1138 { |
| 1139 switch (n->nodeType()) { | 1139 switch (n->nodeType()) { |
| 1140 case Node::DOCUMENT_TYPE_NODE: | 1140 case Node::DOCUMENT_TYPE_NODE: |
| 1141 case Node::ENTITY_NODE: | 1141 case Node::ENTITY_NODE: |
| 1142 case Node::NOTATION_NODE: | 1142 case Node::NOTATION_NODE: |
| 1143 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1143 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeT
ypeError); |
| 1144 return 0; | 1144 return 0; |
| 1145 case Node::CDATA_SECTION_NODE: | 1145 case Node::CDATA_SECTION_NODE: |
| 1146 case Node::COMMENT_NODE: | 1146 case Node::COMMENT_NODE: |
| 1147 case Node::TEXT_NODE: | 1147 case Node::TEXT_NODE: |
| 1148 if (static_cast<unsigned>(offset) > toCharacterData(n)->length()) | 1148 if (static_cast<unsigned>(offset) > toCharacterData(n)->length()) |
| 1149 es.throwUninformativeAndGenericDOMException(IndexSizeError); | 1149 exceptionState.throwUninformativeAndGenericDOMException(IndexSiz
eError); |
| 1150 return 0; | 1150 return 0; |
| 1151 case Node::PROCESSING_INSTRUCTION_NODE: | 1151 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1152 if (static_cast<unsigned>(offset) > toProcessingInstruction(n)->data
().length()) | 1152 if (static_cast<unsigned>(offset) > toProcessingInstruction(n)->data
().length()) |
| 1153 es.throwUninformativeAndGenericDOMException(IndexSizeError); | 1153 exceptionState.throwUninformativeAndGenericDOMException(IndexSiz
eError); |
| 1154 return 0; | 1154 return 0; |
| 1155 case Node::ATTRIBUTE_NODE: | 1155 case Node::ATTRIBUTE_NODE: |
| 1156 case Node::DOCUMENT_FRAGMENT_NODE: | 1156 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1157 case Node::DOCUMENT_NODE: | 1157 case Node::DOCUMENT_NODE: |
| 1158 case Node::ELEMENT_NODE: | 1158 case Node::ELEMENT_NODE: |
| 1159 case Node::XPATH_NAMESPACE_NODE: { | 1159 case Node::XPATH_NAMESPACE_NODE: { |
| 1160 if (!offset) | 1160 if (!offset) |
| 1161 return 0; | 1161 return 0; |
| 1162 Node* childBefore = n->childNode(offset - 1); | 1162 Node* childBefore = n->childNode(offset - 1); |
| 1163 if (!childBefore) | 1163 if (!childBefore) |
| 1164 es.throwUninformativeAndGenericDOMException(IndexSizeError); | 1164 exceptionState.throwUninformativeAndGenericDOMException(IndexSiz
eError); |
| 1165 return childBefore; | 1165 return childBefore; |
| 1166 } | 1166 } |
| 1167 } | 1167 } |
| 1168 ASSERT_NOT_REACHED(); | 1168 ASSERT_NOT_REACHED(); |
| 1169 return 0; | 1169 return 0; |
| 1170 } | 1170 } |
| 1171 | 1171 |
| 1172 void Range::checkNodeBA(Node* n, const String& methodName, ExceptionState& es) c
onst | 1172 void Range::checkNodeBA(Node* n, const String& methodName, ExceptionState& excep
tionState) const |
| 1173 { | 1173 { |
| 1174 if (!m_start.container()) { | 1174 if (!m_start.container()) { |
| 1175 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te(methodName, "Range", "The range has no container. Perhaps 'detatch()' has bee
n invoked on this object?")); | 1175 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute(methodName, "Range", "The range has no container. Perhaps 'detatc
h()' has been invoked on this object?")); |
| 1176 return; | 1176 return; |
| 1177 } | 1177 } |
| 1178 | 1178 |
| 1179 if (!n) { | 1179 if (!n) { |
| 1180 es.throwUninformativeAndGenericDOMException(NotFoundError); | 1180 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 1181 return; | 1181 return; |
| 1182 } | 1182 } |
| 1183 | 1183 |
| 1184 // InvalidNodeTypeError: Raised if the root container of refNode is not an | 1184 // InvalidNodeTypeError: Raised if the root container of refNode is not an |
| 1185 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha
dow DOM tree, | 1185 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha
dow DOM tree, |
| 1186 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity,
or Notation node. | 1186 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity,
or Notation node. |
| 1187 | 1187 |
| 1188 if (!n->parentNode()) { | 1188 if (!n->parentNode()) { |
| 1189 es.throwDOMException(InvalidNodeTypeError, ExceptionMessages::failedToEx
ecute(methodName, "Range", "the given Node has no parent.")); | 1189 exceptionState.throwDOMException(InvalidNodeTypeError, ExceptionMessages
::failedToExecute(methodName, "Range", "the given Node has no parent.")); |
| 1190 return; | 1190 return; |
| 1191 } | 1191 } |
| 1192 | 1192 |
| 1193 switch (n->nodeType()) { | 1193 switch (n->nodeType()) { |
| 1194 case Node::ATTRIBUTE_NODE: | 1194 case Node::ATTRIBUTE_NODE: |
| 1195 case Node::DOCUMENT_FRAGMENT_NODE: | 1195 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1196 case Node::DOCUMENT_NODE: | 1196 case Node::DOCUMENT_NODE: |
| 1197 case Node::ENTITY_NODE: | 1197 case Node::ENTITY_NODE: |
| 1198 case Node::NOTATION_NODE: | 1198 case Node::NOTATION_NODE: |
| 1199 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1199 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeT
ypeError); |
| 1200 return; | 1200 return; |
| 1201 case Node::CDATA_SECTION_NODE: | 1201 case Node::CDATA_SECTION_NODE: |
| 1202 case Node::COMMENT_NODE: | 1202 case Node::COMMENT_NODE: |
| 1203 case Node::DOCUMENT_TYPE_NODE: | 1203 case Node::DOCUMENT_TYPE_NODE: |
| 1204 case Node::ELEMENT_NODE: | 1204 case Node::ELEMENT_NODE: |
| 1205 case Node::PROCESSING_INSTRUCTION_NODE: | 1205 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1206 case Node::TEXT_NODE: | 1206 case Node::TEXT_NODE: |
| 1207 case Node::XPATH_NAMESPACE_NODE: | 1207 case Node::XPATH_NAMESPACE_NODE: |
| 1208 break; | 1208 break; |
| 1209 } | 1209 } |
| 1210 | 1210 |
| 1211 Node* root = n; | 1211 Node* root = n; |
| 1212 while (ContainerNode* parent = root->parentNode()) | 1212 while (ContainerNode* parent = root->parentNode()) |
| 1213 root = parent; | 1213 root = parent; |
| 1214 | 1214 |
| 1215 switch (root->nodeType()) { | 1215 switch (root->nodeType()) { |
| 1216 case Node::ATTRIBUTE_NODE: | 1216 case Node::ATTRIBUTE_NODE: |
| 1217 case Node::DOCUMENT_NODE: | 1217 case Node::DOCUMENT_NODE: |
| 1218 case Node::DOCUMENT_FRAGMENT_NODE: | 1218 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1219 case Node::ELEMENT_NODE: | 1219 case Node::ELEMENT_NODE: |
| 1220 break; | 1220 break; |
| 1221 case Node::CDATA_SECTION_NODE: | 1221 case Node::CDATA_SECTION_NODE: |
| 1222 case Node::COMMENT_NODE: | 1222 case Node::COMMENT_NODE: |
| 1223 case Node::DOCUMENT_TYPE_NODE: | 1223 case Node::DOCUMENT_TYPE_NODE: |
| 1224 case Node::ENTITY_NODE: | 1224 case Node::ENTITY_NODE: |
| 1225 case Node::NOTATION_NODE: | 1225 case Node::NOTATION_NODE: |
| 1226 case Node::PROCESSING_INSTRUCTION_NODE: | 1226 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1227 case Node::TEXT_NODE: | 1227 case Node::TEXT_NODE: |
| 1228 case Node::XPATH_NAMESPACE_NODE: | 1228 case Node::XPATH_NAMESPACE_NODE: |
| 1229 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1229 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeT
ypeError); |
| 1230 return; | 1230 return; |
| 1231 } | 1231 } |
| 1232 } | 1232 } |
| 1233 | 1233 |
| 1234 PassRefPtr<Range> Range::cloneRange(ExceptionState& es) const | 1234 PassRefPtr<Range> Range::cloneRange(ExceptionState& exceptionState) const |
| 1235 { | 1235 { |
| 1236 if (!m_start.container()) { | 1236 if (!m_start.container()) { |
| 1237 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("cloneRange", "Range", "The range has no container. Perhaps 'detatch()' has b
een invoked on this object?")); | 1237 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("cloneRange", "Range", "The range has no container. Perhaps 'deta
tch()' has been invoked on this object?")); |
| 1238 return 0; | 1238 return 0; |
| 1239 } | 1239 } |
| 1240 | 1240 |
| 1241 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of
fset(), m_end.container(), m_end.offset()); | 1241 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of
fset(), m_end.container(), m_end.offset()); |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 void Range::setStartAfter(Node* refNode, ExceptionState& es) | 1244 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState) |
| 1245 { | 1245 { |
| 1246 checkNodeBA(refNode, "setStartAfter", es); | 1246 checkNodeBA(refNode, "setStartAfter", exceptionState); |
| 1247 if (es.hadException()) | 1247 if (exceptionState.hadException()) |
| 1248 return; | 1248 return; |
| 1249 | 1249 |
| 1250 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, es); | 1250 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); |
| 1251 } | 1251 } |
| 1252 | 1252 |
| 1253 void Range::setEndBefore(Node* refNode, ExceptionState& es) | 1253 void Range::setEndBefore(Node* refNode, ExceptionState& exceptionState) |
| 1254 { | 1254 { |
| 1255 checkNodeBA(refNode, "setEndBefore", es); | 1255 checkNodeBA(refNode, "setEndBefore", exceptionState); |
| 1256 if (es.hadException()) | 1256 if (exceptionState.hadException()) |
| 1257 return; | 1257 return; |
| 1258 | 1258 |
| 1259 setEnd(refNode->parentNode(), refNode->nodeIndex(), es); | 1259 setEnd(refNode->parentNode(), refNode->nodeIndex(), exceptionState); |
| 1260 } | 1260 } |
| 1261 | 1261 |
| 1262 void Range::setEndAfter(Node* refNode, ExceptionState& es) | 1262 void Range::setEndAfter(Node* refNode, ExceptionState& exceptionState) |
| 1263 { | 1263 { |
| 1264 checkNodeBA(refNode, "setEndAfter", es); | 1264 checkNodeBA(refNode, "setEndAfter", exceptionState); |
| 1265 if (es.hadException()) | 1265 if (exceptionState.hadException()) |
| 1266 return; | 1266 return; |
| 1267 | 1267 |
| 1268 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, es); | 1268 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); |
| 1269 } | 1269 } |
| 1270 | 1270 |
| 1271 void Range::selectNode(Node* refNode, ExceptionState& es) | 1271 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) |
| 1272 { | 1272 { |
| 1273 if (!m_start.container()) { | 1273 if (!m_start.container()) { |
| 1274 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("selectNode", "Range", "The range has no container. Perhaps 'detatch()' has b
een invoked on this object?")); | 1274 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("selectNode", "Range", "The range has no container. Perhaps 'deta
tch()' has been invoked on this object?")); |
| 1275 return; | 1275 return; |
| 1276 } | 1276 } |
| 1277 | 1277 |
| 1278 if (!refNode) { | 1278 if (!refNode) { |
| 1279 es.throwUninformativeAndGenericDOMException(NotFoundError); | 1279 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 1280 return; | 1280 return; |
| 1281 } | 1281 } |
| 1282 | 1282 |
| 1283 if (!refNode->parentNode()) { | 1283 if (!refNode->parentNode()) { |
| 1284 es.throwDOMException(InvalidNodeTypeError, ExceptionMessages::failedToEx
ecute("selectNode", "Range", "the given Node has no parent.")); | 1284 exceptionState.throwDOMException(InvalidNodeTypeError, ExceptionMessages
::failedToExecute("selectNode", "Range", "the given Node has no parent.")); |
| 1285 return; | 1285 return; |
| 1286 } | 1286 } |
| 1287 | 1287 |
| 1288 // InvalidNodeTypeError: Raised if an ancestor of refNode is an Entity, Nota
tion or | 1288 // InvalidNodeTypeError: Raised if an ancestor of refNode is an Entity, Nota
tion or |
| 1289 // DocumentType node or if refNode is a Document, DocumentFragment, ShadowRo
ot, Attr, Entity, or Notation | 1289 // DocumentType node or if refNode is a Document, DocumentFragment, ShadowRo
ot, Attr, Entity, or Notation |
| 1290 // node. | 1290 // node. |
| 1291 for (ContainerNode* anc = refNode->parentNode(); anc; anc = anc->parentNode(
)) { | 1291 for (ContainerNode* anc = refNode->parentNode(); anc; anc = anc->parentNode(
)) { |
| 1292 switch (anc->nodeType()) { | 1292 switch (anc->nodeType()) { |
| 1293 case Node::ATTRIBUTE_NODE: | 1293 case Node::ATTRIBUTE_NODE: |
| 1294 case Node::CDATA_SECTION_NODE: | 1294 case Node::CDATA_SECTION_NODE: |
| 1295 case Node::COMMENT_NODE: | 1295 case Node::COMMENT_NODE: |
| 1296 case Node::DOCUMENT_FRAGMENT_NODE: | 1296 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1297 case Node::DOCUMENT_NODE: | 1297 case Node::DOCUMENT_NODE: |
| 1298 case Node::ELEMENT_NODE: | 1298 case Node::ELEMENT_NODE: |
| 1299 case Node::PROCESSING_INSTRUCTION_NODE: | 1299 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1300 case Node::TEXT_NODE: | 1300 case Node::TEXT_NODE: |
| 1301 case Node::XPATH_NAMESPACE_NODE: | 1301 case Node::XPATH_NAMESPACE_NODE: |
| 1302 break; | 1302 break; |
| 1303 case Node::DOCUMENT_TYPE_NODE: | 1303 case Node::DOCUMENT_TYPE_NODE: |
| 1304 case Node::ENTITY_NODE: | 1304 case Node::ENTITY_NODE: |
| 1305 case Node::NOTATION_NODE: | 1305 case Node::NOTATION_NODE: |
| 1306 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError
); | 1306 exceptionState.throwUninformativeAndGenericDOMException(InvalidN
odeTypeError); |
| 1307 return; | 1307 return; |
| 1308 } | 1308 } |
| 1309 } | 1309 } |
| 1310 | 1310 |
| 1311 switch (refNode->nodeType()) { | 1311 switch (refNode->nodeType()) { |
| 1312 case Node::CDATA_SECTION_NODE: | 1312 case Node::CDATA_SECTION_NODE: |
| 1313 case Node::COMMENT_NODE: | 1313 case Node::COMMENT_NODE: |
| 1314 case Node::DOCUMENT_TYPE_NODE: | 1314 case Node::DOCUMENT_TYPE_NODE: |
| 1315 case Node::ELEMENT_NODE: | 1315 case Node::ELEMENT_NODE: |
| 1316 case Node::PROCESSING_INSTRUCTION_NODE: | 1316 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1317 case Node::TEXT_NODE: | 1317 case Node::TEXT_NODE: |
| 1318 case Node::XPATH_NAMESPACE_NODE: | 1318 case Node::XPATH_NAMESPACE_NODE: |
| 1319 break; | 1319 break; |
| 1320 case Node::ATTRIBUTE_NODE: | 1320 case Node::ATTRIBUTE_NODE: |
| 1321 case Node::DOCUMENT_FRAGMENT_NODE: | 1321 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1322 case Node::DOCUMENT_NODE: | 1322 case Node::DOCUMENT_NODE: |
| 1323 case Node::ENTITY_NODE: | 1323 case Node::ENTITY_NODE: |
| 1324 case Node::NOTATION_NODE: | 1324 case Node::NOTATION_NODE: |
| 1325 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1325 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeT
ypeError); |
| 1326 return; | 1326 return; |
| 1327 } | 1327 } |
| 1328 | 1328 |
| 1329 if (m_ownerDocument != refNode->document()) | 1329 if (m_ownerDocument != refNode->document()) |
| 1330 setDocument(refNode->document()); | 1330 setDocument(refNode->document()); |
| 1331 | 1331 |
| 1332 setStartBefore(refNode); | 1332 setStartBefore(refNode); |
| 1333 setEndAfter(refNode); | 1333 setEndAfter(refNode); |
| 1334 } | 1334 } |
| 1335 | 1335 |
| 1336 void Range::selectNodeContents(Node* refNode, ExceptionState& es) | 1336 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) |
| 1337 { | 1337 { |
| 1338 if (!m_start.container()) { | 1338 if (!m_start.container()) { |
| 1339 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("selectNodeContents", "Range", "The range has no container. Perhaps 'detatch(
)' has been invoked on this object?")); | 1339 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("selectNodeContents", "Range", "The range has no container. Perha
ps 'detatch()' has been invoked on this object?")); |
| 1340 return; | 1340 return; |
| 1341 } | 1341 } |
| 1342 | 1342 |
| 1343 if (!refNode) { | 1343 if (!refNode) { |
| 1344 es.throwUninformativeAndGenericDOMException(NotFoundError); | 1344 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 1345 return; | 1345 return; |
| 1346 } | 1346 } |
| 1347 | 1347 |
| 1348 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an E
ntity, Notation | 1348 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an E
ntity, Notation |
| 1349 // or DocumentType node. | 1349 // or DocumentType node. |
| 1350 for (Node* n = refNode; n; n = n->parentNode()) { | 1350 for (Node* n = refNode; n; n = n->parentNode()) { |
| 1351 switch (n->nodeType()) { | 1351 switch (n->nodeType()) { |
| 1352 case Node::ATTRIBUTE_NODE: | 1352 case Node::ATTRIBUTE_NODE: |
| 1353 case Node::CDATA_SECTION_NODE: | 1353 case Node::CDATA_SECTION_NODE: |
| 1354 case Node::COMMENT_NODE: | 1354 case Node::COMMENT_NODE: |
| 1355 case Node::DOCUMENT_FRAGMENT_NODE: | 1355 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1356 case Node::DOCUMENT_NODE: | 1356 case Node::DOCUMENT_NODE: |
| 1357 case Node::ELEMENT_NODE: | 1357 case Node::ELEMENT_NODE: |
| 1358 case Node::PROCESSING_INSTRUCTION_NODE: | 1358 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1359 case Node::TEXT_NODE: | 1359 case Node::TEXT_NODE: |
| 1360 case Node::XPATH_NAMESPACE_NODE: | 1360 case Node::XPATH_NAMESPACE_NODE: |
| 1361 break; | 1361 break; |
| 1362 case Node::DOCUMENT_TYPE_NODE: | 1362 case Node::DOCUMENT_TYPE_NODE: |
| 1363 case Node::ENTITY_NODE: | 1363 case Node::ENTITY_NODE: |
| 1364 case Node::NOTATION_NODE: | 1364 case Node::NOTATION_NODE: |
| 1365 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError
); | 1365 exceptionState.throwUninformativeAndGenericDOMException(InvalidN
odeTypeError); |
| 1366 return; | 1366 return; |
| 1367 } | 1367 } |
| 1368 } | 1368 } |
| 1369 | 1369 |
| 1370 if (m_ownerDocument != refNode->document()) | 1370 if (m_ownerDocument != refNode->document()) |
| 1371 setDocument(refNode->document()); | 1371 setDocument(refNode->document()); |
| 1372 | 1372 |
| 1373 m_start.setToStartOfNode(refNode); | 1373 m_start.setToStartOfNode(refNode); |
| 1374 m_end.setToEndOfNode(refNode); | 1374 m_end.setToEndOfNode(refNode); |
| 1375 } | 1375 } |
| 1376 | 1376 |
| 1377 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& es) | 1377 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc
eptionState) |
| 1378 { | 1378 { |
| 1379 RefPtr<Node> newParent = passNewParent; | 1379 RefPtr<Node> newParent = passNewParent; |
| 1380 | 1380 |
| 1381 if (!m_start.container()) { | 1381 if (!m_start.container()) { |
| 1382 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("surroundContents", "Range", "The range has no container. Perhaps 'detatch()'
has been invoked on this object?")); | 1382 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("surroundContents", "Range", "The range has no container. Perhaps
'detatch()' has been invoked on this object?")); |
| 1383 return; | 1383 return; |
| 1384 } | 1384 } |
| 1385 | 1385 |
| 1386 if (!newParent) { | 1386 if (!newParent) { |
| 1387 es.throwUninformativeAndGenericDOMException(NotFoundError); | 1387 exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); |
| 1388 return; | 1388 return; |
| 1389 } | 1389 } |
| 1390 | 1390 |
| 1391 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No
tation, | 1391 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No
tation, |
| 1392 // Document, or DocumentFragment node. | 1392 // Document, or DocumentFragment node. |
| 1393 switch (newParent->nodeType()) { | 1393 switch (newParent->nodeType()) { |
| 1394 case Node::ATTRIBUTE_NODE: | 1394 case Node::ATTRIBUTE_NODE: |
| 1395 case Node::DOCUMENT_FRAGMENT_NODE: | 1395 case Node::DOCUMENT_FRAGMENT_NODE: |
| 1396 case Node::DOCUMENT_NODE: | 1396 case Node::DOCUMENT_NODE: |
| 1397 case Node::DOCUMENT_TYPE_NODE: | 1397 case Node::DOCUMENT_TYPE_NODE: |
| 1398 case Node::ENTITY_NODE: | 1398 case Node::ENTITY_NODE: |
| 1399 case Node::NOTATION_NODE: | 1399 case Node::NOTATION_NODE: |
| 1400 es.throwUninformativeAndGenericDOMException(InvalidNodeTypeError); | 1400 exceptionState.throwUninformativeAndGenericDOMException(InvalidNodeT
ypeError); |
| 1401 return; | 1401 return; |
| 1402 case Node::CDATA_SECTION_NODE: | 1402 case Node::CDATA_SECTION_NODE: |
| 1403 case Node::COMMENT_NODE: | 1403 case Node::COMMENT_NODE: |
| 1404 case Node::ELEMENT_NODE: | 1404 case Node::ELEMENT_NODE: |
| 1405 case Node::PROCESSING_INSTRUCTION_NODE: | 1405 case Node::PROCESSING_INSTRUCTION_NODE: |
| 1406 case Node::TEXT_NODE: | 1406 case Node::TEXT_NODE: |
| 1407 case Node::XPATH_NAMESPACE_NODE: | 1407 case Node::XPATH_NAMESPACE_NODE: |
| 1408 break; | 1408 break; |
| 1409 } | 1409 } |
| 1410 | 1410 |
| 1411 // Raise a HierarchyRequestError if m_start.container() doesn't accept child
ren like newParent. | 1411 // Raise a HierarchyRequestError if m_start.container() doesn't accept child
ren like newParent. |
| 1412 Node* parentOfNewParent = m_start.container(); | 1412 Node* parentOfNewParent = m_start.container(); |
| 1413 | 1413 |
| 1414 // If m_start.container() is a character data node, it will be split and it
will be its parent that will | 1414 // If m_start.container() is a character data node, it will be split and it
will be its parent that will |
| 1415 // need to accept newParent (or in the case of a comment, it logically "woul
d" be inserted into the parent, | 1415 // need to accept newParent (or in the case of a comment, it logically "woul
d" be inserted into the parent, |
| 1416 // although this will fail below for another reason). | 1416 // although this will fail below for another reason). |
| 1417 if (parentOfNewParent->isCharacterDataNode()) | 1417 if (parentOfNewParent->isCharacterDataNode()) |
| 1418 parentOfNewParent = parentOfNewParent->parentNode(); | 1418 parentOfNewParent = parentOfNewParent->parentNode(); |
| 1419 if (!parentOfNewParent || !parentOfNewParent->childTypeAllowed(newParent->no
deType())) { | 1419 if (!parentOfNewParent || !parentOfNewParent->childTypeAllowed(newParent->no
deType())) { |
| 1420 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 1420 exceptionState.throwUninformativeAndGenericDOMException(HierarchyRequest
Error); |
| 1421 return; | 1421 return; |
| 1422 } | 1422 } |
| 1423 | 1423 |
| 1424 if (newParent->contains(m_start.container())) { | 1424 if (newParent->contains(m_start.container())) { |
| 1425 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 1425 exceptionState.throwUninformativeAndGenericDOMException(HierarchyRequest
Error); |
| 1426 return; | 1426 return; |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 // FIXME: Do we need a check if the node would end up with a child node of a
type not | 1429 // FIXME: Do we need a check if the node would end up with a child node of a
type not |
| 1430 // allowed by the type of node? | 1430 // allowed by the type of node? |
| 1431 | 1431 |
| 1432 // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text
node. | 1432 // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-Text
node. |
| 1433 Node* startNonTextContainer = m_start.container(); | 1433 Node* startNonTextContainer = m_start.container(); |
| 1434 if (startNonTextContainer->nodeType() == Node::TEXT_NODE) | 1434 if (startNonTextContainer->nodeType() == Node::TEXT_NODE) |
| 1435 startNonTextContainer = startNonTextContainer->parentNode(); | 1435 startNonTextContainer = startNonTextContainer->parentNode(); |
| 1436 Node* endNonTextContainer = m_end.container(); | 1436 Node* endNonTextContainer = m_end.container(); |
| 1437 if (endNonTextContainer->nodeType() == Node::TEXT_NODE) | 1437 if (endNonTextContainer->nodeType() == Node::TEXT_NODE) |
| 1438 endNonTextContainer = endNonTextContainer->parentNode(); | 1438 endNonTextContainer = endNonTextContainer->parentNode(); |
| 1439 if (startNonTextContainer != endNonTextContainer) { | 1439 if (startNonTextContainer != endNonTextContainer) { |
| 1440 es.throwUninformativeAndGenericDOMException(InvalidStateError); | 1440 exceptionState.throwUninformativeAndGenericDOMException(InvalidStateErro
r); |
| 1441 return; | 1441 return; |
| 1442 } | 1442 } |
| 1443 | 1443 |
| 1444 while (Node* n = newParent->firstChild()) { | 1444 while (Node* n = newParent->firstChild()) { |
| 1445 toContainerNode(newParent)->removeChild(n, es); | 1445 toContainerNode(newParent)->removeChild(n, exceptionState); |
| 1446 if (es.hadException()) | 1446 if (exceptionState.hadException()) |
| 1447 return; | 1447 return; |
| 1448 } | 1448 } |
| 1449 RefPtr<DocumentFragment> fragment = extractContents(es); | 1449 RefPtr<DocumentFragment> fragment = extractContents(exceptionState); |
| 1450 if (es.hadException()) | 1450 if (exceptionState.hadException()) |
| 1451 return; | 1451 return; |
| 1452 insertNode(newParent, es); | 1452 insertNode(newParent, exceptionState); |
| 1453 if (es.hadException()) | 1453 if (exceptionState.hadException()) |
| 1454 return; | 1454 return; |
| 1455 newParent->appendChild(fragment.release(), es); | 1455 newParent->appendChild(fragment.release(), exceptionState); |
| 1456 if (es.hadException()) | 1456 if (exceptionState.hadException()) |
| 1457 return; | 1457 return; |
| 1458 selectNode(newParent.get(), es); | 1458 selectNode(newParent.get(), exceptionState); |
| 1459 } | 1459 } |
| 1460 | 1460 |
| 1461 void Range::setStartBefore(Node* refNode, ExceptionState& es) | 1461 void Range::setStartBefore(Node* refNode, ExceptionState& exceptionState) |
| 1462 { | 1462 { |
| 1463 checkNodeBA(refNode, "setStartBefore", es); | 1463 checkNodeBA(refNode, "setStartBefore", exceptionState); |
| 1464 if (es.hadException()) | 1464 if (exceptionState.hadException()) |
| 1465 return; | 1465 return; |
| 1466 | 1466 |
| 1467 setStart(refNode->parentNode(), refNode->nodeIndex(), es); | 1467 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState); |
| 1468 } | 1468 } |
| 1469 | 1469 |
| 1470 void Range::checkDeleteExtract(const String& methodName, ExceptionState& es) | 1470 void Range::checkDeleteExtract(const String& methodName, ExceptionState& excepti
onState) |
| 1471 { | 1471 { |
| 1472 if (!m_start.container()) { | 1472 if (!m_start.container()) { |
| 1473 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te(methodName, "Range", "The range has no container. Perhaps 'detatch()' has bee
n invoked on this object?")); | 1473 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute(methodName, "Range", "The range has no container. Perhaps 'detatc
h()' has been invoked on this object?")); |
| 1474 return; | 1474 return; |
| 1475 } | 1475 } |
| 1476 | 1476 |
| 1477 if (!commonAncestorContainer(es) || es.hadException()) | 1477 if (!commonAncestorContainer(exceptionState) || exceptionState.hadException(
)) |
| 1478 return; | 1478 return; |
| 1479 | 1479 |
| 1480 Node* pastLast = pastLastNode(); | 1480 Node* pastLast = pastLastNode(); |
| 1481 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { | 1481 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { |
| 1482 if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { | 1482 if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { |
| 1483 es.throwUninformativeAndGenericDOMException(HierarchyRequestError); | 1483 exceptionState.throwUninformativeAndGenericDOMException(HierarchyReq
uestError); |
| 1484 return; | 1484 return; |
| 1485 } | 1485 } |
| 1486 } | 1486 } |
| 1487 } | 1487 } |
| 1488 | 1488 |
| 1489 Node* Range::firstNode() const | 1489 Node* Range::firstNode() const |
| 1490 { | 1490 { |
| 1491 if (!m_start.container()) | 1491 if (!m_start.container()) |
| 1492 return 0; | 1492 return 0; |
| 1493 if (m_start.container()->offsetInCharacters()) | 1493 if (m_start.container()->offsetInCharacters()) |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1796 ASSERT(oldNode); | 1796 ASSERT(oldNode); |
| 1797 ASSERT(oldNode->document() == m_ownerDocument); | 1797 ASSERT(oldNode->document() == m_ownerDocument); |
| 1798 ASSERT(oldNode->parentNode()); | 1798 ASSERT(oldNode->parentNode()); |
| 1799 ASSERT(oldNode->isTextNode()); | 1799 ASSERT(oldNode->isTextNode()); |
| 1800 ASSERT(oldNode->nextSibling()); | 1800 ASSERT(oldNode->nextSibling()); |
| 1801 ASSERT(oldNode->nextSibling()->isTextNode()); | 1801 ASSERT(oldNode->nextSibling()->isTextNode()); |
| 1802 boundaryTextNodeSplit(m_start, oldNode); | 1802 boundaryTextNodeSplit(m_start, oldNode); |
| 1803 boundaryTextNodeSplit(m_end, oldNode); | 1803 boundaryTextNodeSplit(m_end, oldNode); |
| 1804 } | 1804 } |
| 1805 | 1805 |
| 1806 void Range::expand(const String& unit, ExceptionState& es) | 1806 void Range::expand(const String& unit, ExceptionState& exceptionState) |
| 1807 { | 1807 { |
| 1808 VisiblePosition start(startPosition()); | 1808 VisiblePosition start(startPosition()); |
| 1809 VisiblePosition end(endPosition()); | 1809 VisiblePosition end(endPosition()); |
| 1810 if (unit == "word") { | 1810 if (unit == "word") { |
| 1811 start = startOfWord(start); | 1811 start = startOfWord(start); |
| 1812 end = endOfWord(end); | 1812 end = endOfWord(end); |
| 1813 } else if (unit == "sentence") { | 1813 } else if (unit == "sentence") { |
| 1814 start = startOfSentence(start); | 1814 start = startOfSentence(start); |
| 1815 end = endOfSentence(end); | 1815 end = endOfSentence(end); |
| 1816 } else if (unit == "block") { | 1816 } else if (unit == "block") { |
| 1817 start = startOfParagraph(start); | 1817 start = startOfParagraph(start); |
| 1818 end = endOfParagraph(end); | 1818 end = endOfParagraph(end); |
| 1819 } else if (unit == "document") { | 1819 } else if (unit == "document") { |
| 1820 start = startOfDocument(start); | 1820 start = startOfDocument(start); |
| 1821 end = endOfDocument(end); | 1821 end = endOfDocument(end); |
| 1822 } else | 1822 } else |
| 1823 return; | 1823 return; |
| 1824 setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().comp
uteOffsetInContainerNode(), es); | 1824 setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().comp
uteOffsetInContainerNode(), exceptionState); |
| 1825 setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOff
setInContainerNode(), es); | 1825 setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOff
setInContainerNode(), exceptionState); |
| 1826 } | 1826 } |
| 1827 | 1827 |
| 1828 PassRefPtr<ClientRectList> Range::getClientRects() const | 1828 PassRefPtr<ClientRectList> Range::getClientRects() const |
| 1829 { | 1829 { |
| 1830 if (!m_start.container()) | 1830 if (!m_start.container()) |
| 1831 return ClientRectList::create(); | 1831 return ClientRectList::create(); |
| 1832 | 1832 |
| 1833 m_ownerDocument->updateLayoutIgnorePendingStylesheets(); | 1833 m_ownerDocument->updateLayoutIgnorePendingStylesheets(); |
| 1834 | 1834 |
| 1835 Vector<FloatQuad> quads; | 1835 Vector<FloatQuad> quads; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1907 | 1907 |
| 1908 void showTree(const WebCore::Range* range) | 1908 void showTree(const WebCore::Range* range) |
| 1909 { | 1909 { |
| 1910 if (range && range->boundaryPointsValid()) { | 1910 if (range && range->boundaryPointsValid()) { |
| 1911 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r
ange->endContainer(), "E"); | 1911 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r
ange->endContainer(), "E"); |
| 1912 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset
(), range->endOffset()); | 1912 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset
(), range->endOffset()); |
| 1913 } | 1913 } |
| 1914 } | 1914 } |
| 1915 | 1915 |
| 1916 #endif | 1916 #endif |
| OLD | NEW |