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