Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: Source/core/dom/Range.cpp

Issue 252783002: Make Range.detach() a no-op (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix some failures Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 22 matching lines...) Expand all
33 #include "core/dom/Node.h" 33 #include "core/dom/Node.h"
34 #include "core/dom/NodeTraversal.h" 34 #include "core/dom/NodeTraversal.h"
35 #include "core/dom/NodeWithIndex.h" 35 #include "core/dom/NodeWithIndex.h"
36 #include "core/dom/ProcessingInstruction.h" 36 #include "core/dom/ProcessingInstruction.h"
37 #include "core/events/ScopedEventQueue.h" 37 #include "core/events/ScopedEventQueue.h"
38 #include "core/dom/Text.h" 38 #include "core/dom/Text.h"
39 #include "core/editing/TextIterator.h" 39 #include "core/editing/TextIterator.h"
40 #include "core/editing/VisiblePosition.h" 40 #include "core/editing/VisiblePosition.h"
41 #include "core/editing/VisibleUnits.h" 41 #include "core/editing/VisibleUnits.h"
42 #include "core/editing/markup.h" 42 #include "core/editing/markup.h"
43 #include "core/frame/UseCounter.h"
43 #include "core/html/HTMLElement.h" 44 #include "core/html/HTMLElement.h"
44 #include "core/rendering/RenderBoxModelObject.h" 45 #include "core/rendering/RenderBoxModelObject.h"
45 #include "core/rendering/RenderText.h" 46 #include "core/rendering/RenderText.h"
46 #include "platform/geometry/FloatQuad.h" 47 #include "platform/geometry/FloatQuad.h"
47 #include "wtf/RefCountedLeakCounter.h" 48 #include "wtf/RefCountedLeakCounter.h"
48 #include "wtf/text/CString.h" 49 #include "wtf/text/CString.h"
49 #include "wtf/text/StringBuilder.h" 50 #include "wtf/text/StringBuilder.h"
50 #ifndef NDEBUG 51 #ifndef NDEBUG
51 #include <stdio.h> 52 #include <stdio.h>
52 #endif 53 #endif
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 { 119 {
119 ASSERT(m_ownerDocument != document); 120 ASSERT(m_ownerDocument != document);
120 ASSERT(m_ownerDocument); 121 ASSERT(m_ownerDocument);
121 m_ownerDocument->detachRange(this); 122 m_ownerDocument->detachRange(this);
122 m_ownerDocument = &document; 123 m_ownerDocument = &document;
123 m_start.setToStartOfNode(document); 124 m_start.setToStartOfNode(document);
124 m_end.setToStartOfNode(document); 125 m_end.setToStartOfNode(document);
125 m_ownerDocument->attachRange(this); 126 m_ownerDocument->attachRange(this);
126 } 127 }
127 128
128 Node* Range::startContainer(ExceptionState& exceptionState) const 129 Node* Range::commonAncestorContainer() const
129 { 130 {
130 if (!m_start.container()) {
131 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
132 return 0;
133 }
134
135 return m_start.container();
136 }
137
138 int Range::startOffset(ExceptionState& exceptionState) const
139 {
140 if (!m_start.container()) {
141 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
142 return 0;
143 }
144
145 return m_start.offset();
146 }
147
148 Node* Range::endContainer(ExceptionState& exceptionState) const
149 {
150 if (!m_start.container()) {
151 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
152 return 0;
153 }
154
155 return m_end.container();
156 }
157
158 int Range::endOffset(ExceptionState& exceptionState) const
159 {
160 if (!m_start.container()) {
161 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
162 return 0;
163 }
164
165 return m_end.offset();
166 }
167
168 Node* Range::commonAncestorContainer(ExceptionState& exceptionState) const
169 {
170 if (!m_start.container()) {
171 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
172 return 0;
173 }
174
175 return commonAncestorContainer(m_start.container(), m_end.container()); 131 return commonAncestorContainer(m_start.container(), m_end.container());
176 } 132 }
177 133
178 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB) 134 Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
179 { 135 {
180 for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) { 136 for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
181 for (Node* parentB = containerB; parentB; parentB = parentB->parentNode( )) { 137 for (Node* parentB = containerB; parentB; parentB = parentB->parentNode( )) {
182 if (parentA == parentB) 138 if (parentA == parentB)
183 return parentA; 139 return parentA;
184 } 140 }
185 } 141 }
186 return 0; 142 return 0;
187 } 143 }
188 144
189 bool Range::collapsed(ExceptionState& exceptionState) const
190 {
191 if (!m_start.container()) {
192 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
193 return 0;
194 }
195
196 return m_start == m_end;
197 }
198
199 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& star t, const RangeBoundaryPoint& end) 145 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& star t, const RangeBoundaryPoint& end)
200 { 146 {
201 Node* endRootContainer = end.container(); 147 Node* endRootContainer = end.container();
202 while (endRootContainer->parentNode()) 148 while (endRootContainer->parentNode())
203 endRootContainer = endRootContainer->parentNode(); 149 endRootContainer = endRootContainer->parentNode();
204 Node* startRootContainer = start.container(); 150 Node* startRootContainer = start.container();
205 while (startRootContainer->parentNode()) 151 while (startRootContainer->parentNode())
206 startRootContainer = startRootContainer->parentNode(); 152 startRootContainer = startRootContainer->parentNode();
207 153
208 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin ts(start, end, ASSERT_NO_EXCEPTION) > 0); 154 return startRootContainer != endRootContainer || (Range::compareBoundaryPoin ts(start, end, ASSERT_NO_EXCEPTION) > 0);
209 } 155 }
210 156
211 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep tionState) 157 void Range::setStart(PassRefPtr<Node> refNode, int offset, ExceptionState& excep tionState)
212 { 158 {
213 if (!m_start.container()) {
214 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
215 return;
216 }
217
218 if (!refNode) { 159 if (!refNode) {
219 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull."); 160 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull.");
220 return; 161 return;
221 } 162 }
222 163
223 bool didMoveDocument = false; 164 bool didMoveDocument = false;
224 if (refNode->document() != m_ownerDocument) { 165 if (refNode->document() != m_ownerDocument) {
225 setDocument(refNode->document()); 166 setDocument(refNode->document());
226 didMoveDocument = true; 167 didMoveDocument = true;
227 } 168 }
228 169
229 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); 170 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState);
230 if (exceptionState.hadException()) 171 if (exceptionState.hadException())
231 return; 172 return;
232 173
233 m_start.set(refNode, offset, childNode); 174 m_start.set(refNode, offset, childNode);
234 175
235 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) 176 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
236 collapse(true, exceptionState); 177 collapse(true);
237 } 178 }
238 179
239 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti onState) 180 void Range::setEnd(PassRefPtr<Node> refNode, int offset, ExceptionState& excepti onState)
240 { 181 {
241 if (!m_start.container()) {
242 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
243 return;
244 }
245
246 if (!refNode) { 182 if (!refNode) {
247 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull."); 183 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull.");
248 return; 184 return;
249 } 185 }
250 186
251 bool didMoveDocument = false; 187 bool didMoveDocument = false;
252 if (refNode->document() != m_ownerDocument) { 188 if (refNode->document() != m_ownerDocument) {
253 setDocument(refNode->document()); 189 setDocument(refNode->document());
254 didMoveDocument = true; 190 didMoveDocument = true;
255 } 191 }
256 192
257 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState); 193 Node* childNode = checkNodeWOffset(refNode.get(), offset, exceptionState);
258 if (exceptionState.hadException()) 194 if (exceptionState.hadException())
259 return; 195 return;
260 196
261 m_end.set(refNode, offset, childNode); 197 m_end.set(refNode, offset, childNode);
262 198
263 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) 199 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end))
264 collapse(false, exceptionState); 200 collapse(false);
265 } 201 }
266 202
267 void Range::setStart(const Position& start, ExceptionState& exceptionState) 203 void Range::setStart(const Position& start, ExceptionState& exceptionState)
268 { 204 {
269 Position parentAnchored = start.parentAnchoredEquivalent(); 205 Position parentAnchored = start.parentAnchoredEquivalent();
270 setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNod e(), exceptionState); 206 setStart(parentAnchored.containerNode(), parentAnchored.offsetInContainerNod e(), exceptionState);
271 } 207 }
272 208
273 void Range::setEnd(const Position& end, ExceptionState& exceptionState) 209 void Range::setEnd(const Position& end, ExceptionState& exceptionState)
274 { 210 {
275 Position parentAnchored = end.parentAnchoredEquivalent(); 211 Position parentAnchored = end.parentAnchoredEquivalent();
276 setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode( ), exceptionState); 212 setEnd(parentAnchored.containerNode(), parentAnchored.offsetInContainerNode( ), exceptionState);
277 } 213 }
278 214
279 void Range::collapse(bool toStart, ExceptionState& exceptionState) 215 void Range::collapse(bool toStart)
280 { 216 {
281 if (!m_start.container()) {
282 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
283 return;
284 }
285
286 if (toStart) 217 if (toStart)
287 m_end = m_start; 218 m_end = m_start;
288 else 219 else
289 m_start = m_end; 220 m_start = m_end;
290 } 221 }
291 222
292 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS tate) 223 bool Range::isPointInRange(Node* refNode, int offset, ExceptionState& exceptionS tate)
293 { 224 {
294 if (!m_start.container()) {
295 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
296 return false;
297 }
298
299 if (!refNode) { 225 if (!refNode) {
300 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null."); 226 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null.");
301 return false; 227 return false;
302 } 228 }
303 229
304 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) { 230 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) {
305 return false; 231 return false;
306 } 232 }
307 233
308 checkNodeWOffset(refNode, offset, exceptionState); 234 checkNodeWOffset(refNode, offset, exceptionState);
309 if (exceptionState.hadException()) 235 if (exceptionState.hadException())
310 return false; 236 return false;
311 237
312 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o ffset(), exceptionState) >= 0 && !exceptionState.hadException() 238 return compareBoundaryPoints(refNode, offset, m_start.container(), m_start.o ffset(), exceptionState) >= 0 && !exceptionState.hadException()
313 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse t(), exceptionState) <= 0 && !exceptionState.hadException(); 239 && compareBoundaryPoints(refNode, offset, m_end.container(), m_end.offse t(), exceptionState) <= 0 && !exceptionState.hadException();
314 } 240 }
315 241
316 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt ate) const 242 short Range::comparePoint(Node* refNode, int offset, ExceptionState& exceptionSt ate) const
317 { 243 {
318 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint 244 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint
319 // This method returns -1, 0 or 1 depending on if the point described by the 245 // This method returns -1, 0 or 1 depending on if the point described by the
320 // refNode node and an offset within the node is before, same as, or after t he range respectively. 246 // refNode node and an offset within the node is before, same as, or after t he range respectively.
321 247
322 if (!m_start.container()) {
323 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
324 return 0;
325 }
326
327 if (!refNode) { 248 if (!refNode) {
328 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null."); 249 exceptionState.throwDOMException(HierarchyRequestError, "The node provid ed was null.");
329 return 0; 250 return 0;
330 } 251 }
331 252
332 if (!refNode->inActiveDocument()) { 253 if (!refNode->inActiveDocument()) {
333 exceptionState.throwDOMException(WrongDocumentError, "The node provided is not in an active document."); 254 exceptionState.throwDOMException(WrongDocumentError, "The node provided is not in an active document.");
334 return 0; 255 return 0;
335 } 256 }
336 257
(...skipping 25 matching lines...) Expand all
362 { 283 {
363 // http://developer.mozilla.org/en/docs/DOM:range.compareNode 284 // http://developer.mozilla.org/en/docs/DOM:range.compareNode
364 // This method returns 0, 1, 2, or 3 based on if the node is before, after, 285 // This method returns 0, 1, 2, or 3 based on if the node is before, after,
365 // before and after(surrounds), or inside the range, respectively 286 // before and after(surrounds), or inside the range, respectively
366 287
367 if (!refNode) { 288 if (!refNode) {
368 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull."); 289 exceptionState.throwDOMException(NotFoundError, "The node provided was n ull.");
369 return NODE_BEFORE; 290 return NODE_BEFORE;
370 } 291 }
371 292
372 if (!m_start.container() && refNode->inActiveDocument()) { 293 if (!refNode->inActiveDocument()) {
373 exceptionState.throwDOMException(InvalidStateError, "This Range is detac hed, and the provided node is not.");
374 return NODE_BEFORE;
375 }
376
377 if (m_start.container() && !refNode->inActiveDocument()) {
378 // Firefox doesn't throw an exception for this case; it returns 0. 294 // Firefox doesn't throw an exception for this case; it returns 0.
379 return NODE_BEFORE; 295 return NODE_BEFORE;
380 } 296 }
381 297
382 if (refNode->document() != m_ownerDocument) { 298 if (refNode->document() != m_ownerDocument) {
383 // Firefox doesn't throw an exception for this case; it returns 0. 299 // Firefox doesn't throw an exception for this case; it returns 0.
384 return NODE_BEFORE; 300 return NODE_BEFORE;
385 } 301 }
386 302
387 ContainerNode* parentNode = refNode->parentNode(); 303 ContainerNode* parentNode = refNode->parentNode();
(...skipping 12 matching lines...) Expand all
400 return NODE_BEFORE; // ends before or in the range 316 return NODE_BEFORE; // ends before or in the range
401 } 317 }
402 // starts at or after the range start 318 // starts at or after the range start
403 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft er the range 319 if (comparePoint(parentNode, nodeIndex + 1, exceptionState) > 0) // ends aft er the range
404 return NODE_AFTER; 320 return NODE_AFTER;
405 return NODE_INSIDE; // ends inside the range 321 return NODE_INSIDE; // ends inside the range
406 } 322 }
407 323
408 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc eptionState& exceptionState) const 324 short Range::compareBoundaryPoints(CompareHow how, const Range* sourceRange, Exc eptionState& exceptionState) const
409 { 325 {
410 if (!m_start.container()) {
411 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
412 return 0;
413 }
414
415 if (!sourceRange) { 326 if (!sourceRange) {
416 exceptionState.throwDOMException(NotFoundError, "The source range provid ed was null."); 327 exceptionState.throwDOMException(NotFoundError, "The source range provid ed was null.");
417 return 0; 328 return 0;
418 } 329 }
419 330
420 Node* thisCont = commonAncestorContainer(exceptionState); 331 Node* thisCont = commonAncestorContainer();
421 if (exceptionState.hadException()) 332 Node* sourceCont = sourceRange->commonAncestorContainer();
422 return 0;
423 Node* sourceCont = sourceRange->commonAncestorContainer(exceptionState);
424 if (exceptionState.hadException())
425 return 0;
426
427 if (thisCont->document() != sourceCont->document()) { 333 if (thisCont->document() != sourceCont->document()) {
428 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.");
429 return 0; 335 return 0;
430 } 336 }
431 337
432 Node* thisTop = thisCont; 338 Node* thisTop = thisCont;
433 Node* sourceTop = sourceCont; 339 Node* sourceTop = sourceCont;
434 while (thisTop->parentNode()) 340 while (thisTop->parentNode())
435 thisTop = thisTop->parentNode(); 341 thisTop = thisTop->parentNode();
436 while (sourceTop->parentNode()) 342 while (sourceTop->parentNode())
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 } 455 }
550 456
551 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState) 457 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundaryA, const Ra ngeBoundaryPoint& boundaryB, ExceptionState& exceptionState)
552 { 458 {
553 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun daryB.container(), boundaryB.offset(), exceptionState); 459 return compareBoundaryPoints(boundaryA.container(), boundaryA.offset(), boun daryB.container(), boundaryB.offset(), exceptionState);
554 } 460 }
555 461
556 bool Range::boundaryPointsValid() const 462 bool Range::boundaryPointsValid() const
557 { 463 {
558 TrackExceptionState exceptionState; 464 TrackExceptionState exceptionState;
559 return m_start.container() && compareBoundaryPoints(m_start, m_end, exceptio nState) <= 0 && !exceptionState.hadException(); 465 return compareBoundaryPoints(m_start, m_end, exceptionState) <= 0 && !except ionState.hadException();
560 } 466 }
561 467
562 void Range::deleteContents(ExceptionState& exceptionState) 468 void Range::deleteContents(ExceptionState& exceptionState)
563 { 469 {
564 checkDeleteExtract(exceptionState); 470 checkDeleteExtract(exceptionState);
565 if (exceptionState.hadException()) 471 if (exceptionState.hadException())
566 return; 472 return;
567 473
568 processContents(DELETE_CONTENTS, exceptionState); 474 processContents(DELETE_CONTENTS, exceptionState);
569 } 475 }
570 476
571 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState) 477 bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState)
572 { 478 {
573 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode 479 // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode
574 // Returns a bool if the node intersects the range. 480 // Returns a bool if the node intersects the range.
575
576 // Throw exception if the range is already detached.
577 if (!m_start.container()) {
578 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
579 return false;
580 }
581 if (!refNode) { 481 if (!refNode) {
582 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 482 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
583 return false; 483 return false;
584 } 484 }
585 485
586 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) { 486 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) {
587 // Firefox doesn't throw an exception for these cases; it returns false. 487 // Firefox doesn't throw an exception for these cases; it returns false.
588 return false; 488 return false;
589 } 489 }
590 490
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 } 567 }
668 568
669 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception State& exceptionState) 569 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception State& exceptionState)
670 { 570 {
671 typedef Vector<RefPtr<Node> > NodeVector; 571 typedef Vector<RefPtr<Node> > NodeVector;
672 572
673 RefPtr<DocumentFragment> fragment; 573 RefPtr<DocumentFragment> fragment;
674 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) 574 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
675 fragment = DocumentFragment::create(*m_ownerDocument.get()); 575 fragment = DocumentFragment::create(*m_ownerDocument.get());
676 576
677 if (collapsed(exceptionState)) 577 if (collapsed())
678 return fragment.release(); 578 return fragment.release();
679 if (exceptionState.hadException())
680 return nullptr;
681 579
682 RefPtr<Node> commonRoot = commonAncestorContainer(exceptionState); 580 RefPtr<Node> commonRoot = commonAncestorContainer();
683 if (exceptionState.hadException())
684 return nullptr;
685 ASSERT(commonRoot); 581 ASSERT(commonRoot);
686 582
687 if (m_start.container() == m_end.container()) { 583 if (m_start.container() == m_end.container()) {
688 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s tart.offset(), m_end.offset(), exceptionState); 584 processContentsBetweenOffsets(action, fragment, m_start.container(), m_s tart.offset(), m_end.offset(), exceptionState);
689 return fragment; 585 return fragment;
690 } 586 }
691 587
692 // Since mutation observers can modify the range during the process, the bou ndary points need to be saved. 588 // Since mutation observers can modify the range during the process, the bou ndary points need to be saved.
693 RangeBoundaryPoint originalStart(m_start); 589 RangeBoundaryPoint originalStart(m_start);
694 RangeBoundaryPoint originalEnd(m_end); 590 RangeBoundaryPoint originalEnd(m_end);
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 { 826 {
931 checkDeleteExtract(exceptionState); 827 checkDeleteExtract(exceptionState);
932 if (exceptionState.hadException()) 828 if (exceptionState.hadException())
933 return nullptr; 829 return nullptr;
934 830
935 return processContents(EXTRACT_CONTENTS, exceptionState); 831 return processContents(EXTRACT_CONTENTS, exceptionState);
936 } 832 }
937 833
938 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState ) 834 PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionState& exceptionState )
939 { 835 {
940 if (!m_start.container()) {
941 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
942 return nullptr;
943 }
944
945 return processContents(CLONE_CONTENTS, exceptionState); 836 return processContents(CLONE_CONTENTS, exceptionState);
946 } 837 }
947 838
948 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta te) 839 void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionState& exceptionSta te)
949 { 840 {
950 RefPtr<Node> newNode = prpNewNode; 841 RefPtr<Node> newNode = prpNewNode;
951 842
952 if (!m_start.container()) {
953 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
954 return;
955 }
956
957 if (!newNode) { 843 if (!newNode) {
958 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 844 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
959 return; 845 return;
960 } 846 }
961 847
962 // HierarchyRequestError: Raised if the container of the start of the Range is of a type that 848 // 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. 849 // does not allow children of the type of newNode or if newNode is an ancest or of the container.
964 850
965 // an extra one here - if a text node is going to split, it must have a pare nt to insert into 851 // 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(); 852 bool startIsText = m_start.container()->isTextNode();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 if (exceptionState.hadException()) 936 if (exceptionState.hadException())
1051 return; 937 return;
1052 938
1053 // Note that m_start.offset() may have changed as a result of container- >insertBefore, 939 // Note that m_start.offset() may have changed as a result of container- >insertBefore,
1054 // when the node we are inserting comes before the range in the same con tainer. 940 // when the node we are inserting comes before the range in the same con tainer.
1055 if (collapsed && numNewChildren) 941 if (collapsed && numNewChildren)
1056 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la stChild.get()); 942 m_end.set(m_start.container(), m_start.offset() + numNewChildren, la stChild.get());
1057 } 943 }
1058 } 944 }
1059 945
1060 String Range::toString(ExceptionState& exceptionState) const 946 String Range::toString() const
1061 { 947 {
1062 if (!m_start.container()) {
1063 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1064 return String();
1065 }
1066
1067 StringBuilder builder; 948 StringBuilder builder;
1068 949
1069 Node* pastLast = pastLastNode(); 950 Node* pastLast = pastLastNode();
1070 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { 951 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) {
1071 if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SEC TION_NODE) { 952 if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SEC TION_NODE) {
1072 String data = toCharacterData(n)->data(); 953 String data = toCharacterData(n)->data();
1073 int length = data.length(); 954 int length = data.length();
1074 int start = (n == m_start.container()) ? min(max(0, m_start.offset() ), length) : 0; 955 int start = (n == m_start.container()) ? min(max(0, m_start.offset() ), length) : 0;
1075 int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length; 956 int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length;
1076 builder.append(data, start, end - start); 957 builder.append(data, start, end - start);
1077 } 958 }
1078 } 959 }
1079 960
1080 return builder.toString(); 961 return builder.toString();
1081 } 962 }
1082 963
1083 String Range::toHTML() const 964 String Range::toHTML() const
1084 { 965 {
1085 return createMarkup(this); 966 return createMarkup(this);
1086 } 967 }
1087 968
1088 String Range::text() const 969 String Range::text() const
1089 { 970 {
1090 if (!m_start.container())
1091 return String();
1092
1093 // We need to update layout, since plainText uses line boxes in the render t ree. 971 // We need to update layout, since plainText uses line boxes in the render t ree.
1094 // FIXME: As with innerText, we'd like this to work even if there are no ren der objects. 972 // FIXME: As with innerText, we'd like this to work even if there are no ren der objects.
1095 m_start.container()->document().updateLayout(); 973 m_start.container()->document().updateLayout();
1096 974
1097 return plainText(this); 975 return plainText(this);
1098 } 976 }
1099 977
1100 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku p, ExceptionState& exceptionState) 978 PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& marku p, ExceptionState& exceptionState)
1101 { 979 {
1102 if (!m_start.container()) {
1103 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1104 return nullptr;
1105 }
1106
1107 Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode(); 980 Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode();
1108 if (!element || !element->isHTMLElement()) { 981 if (!element || !element->isHTMLElement()) {
1109 exceptionState.throwDOMException(NotSupportedError, "The range's contain er must be an HTML element."); 982 exceptionState.throwDOMException(NotSupportedError, "The range's contain er must be an HTML element.");
1110 return nullptr; 983 return nullptr;
1111 } 984 }
1112 985
1113 RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup , toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, excep tionState); 986 RefPtr<DocumentFragment> fragment = WebCore::createContextualFragment(markup , toHTMLElement(element), AllowScriptingContentAndDoNotMarkAlreadyStarted, excep tionState);
1114 if (!fragment) 987 if (!fragment)
1115 return nullptr; 988 return nullptr;
1116 989
1117 return fragment.release(); 990 return fragment.release();
1118 } 991 }
1119 992
1120 993
1121 void Range::detach(ExceptionState& exceptionState) 994 void Range::detach()
1122 { 995 {
1123 // Check first to see if we've already detached: 996 // This is now a no-op as per the DOM specification.
1124 if (!m_start.container()) { 997 UseCounter::countDeprecation(ownerDocument(), UseCounter::RangeDetach);
Yuta Kitamura 2014/04/28 09:27:38 Why don't you use "DeprecateAs=" IDL attribute her
Inactive 2014/04/28 14:44:18 Done.
1125 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1126 return;
1127 }
1128
1129 m_ownerDocument->detachRange(this);
1130
1131 m_start.clear();
1132 m_end.clear();
1133 } 998 }
1134 999
1135 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat e) const 1000 Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionState& exceptionStat e) const
1136 { 1001 {
1137 switch (n->nodeType()) { 1002 switch (n->nodeType()) {
1138 case Node::DOCUMENT_TYPE_NODE: 1003 case Node::DOCUMENT_TYPE_NODE:
1139 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'."); 1004 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'.");
1140 return 0; 1005 return 0;
1141 case Node::CDATA_SECTION_NODE: 1006 case Node::CDATA_SECTION_NODE:
1142 case Node::COMMENT_NODE: 1007 case Node::COMMENT_NODE:
(...skipping 16 matching lines...) Expand all
1159 exceptionState.throwDOMException(IndexSizeError, "There is no ch ild at offset " + String::number(offset) + "."); 1024 exceptionState.throwDOMException(IndexSizeError, "There is no ch ild at offset " + String::number(offset) + ".");
1160 return childBefore; 1025 return childBefore;
1161 } 1026 }
1162 } 1027 }
1163 ASSERT_NOT_REACHED(); 1028 ASSERT_NOT_REACHED();
1164 return 0; 1029 return 0;
1165 } 1030 }
1166 1031
1167 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const 1032 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const
1168 { 1033 {
1169 if (!m_start.container()) {
1170 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1171 return;
1172 }
1173
1174 if (!n) { 1034 if (!n) {
1175 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1035 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1176 return; 1036 return;
1177 } 1037 }
1178 1038
1179 // InvalidNodeTypeError: Raised if the root container of refNode is not an 1039 // InvalidNodeTypeError: Raised if the root container of refNode is not an
1180 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha dow DOM tree, 1040 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG sha dow DOM tree,
1181 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation node. 1041 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or Notation node.
1182 1042
1183 if (!n->parentNode()) { 1043 if (!n->parentNode()) {
(...skipping 29 matching lines...) Expand all
1213 case Node::CDATA_SECTION_NODE: 1073 case Node::CDATA_SECTION_NODE:
1214 case Node::COMMENT_NODE: 1074 case Node::COMMENT_NODE:
1215 case Node::DOCUMENT_TYPE_NODE: 1075 case Node::DOCUMENT_TYPE_NODE:
1216 case Node::PROCESSING_INSTRUCTION_NODE: 1076 case Node::PROCESSING_INSTRUCTION_NODE:
1217 case Node::TEXT_NODE: 1077 case Node::TEXT_NODE:
1218 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'."); 1078 exceptionState.throwDOMException(InvalidNodeTypeError, "The node pro vided is of type '" + n->nodeName() + "'.");
1219 return; 1079 return;
1220 } 1080 }
1221 } 1081 }
1222 1082
1223 PassRefPtrWillBeRawPtr<Range> Range::cloneRange(ExceptionState& exceptionState) const 1083 PassRefPtrWillBeRawPtr<Range> Range::cloneRange() const
1224 { 1084 {
1225 if (!m_start.container()) {
1226 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1227 return nullptr;
1228 }
1229
1230 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of fset(), m_end.container(), m_end.offset()); 1085 return Range::create(*m_ownerDocument.get(), m_start.container(), m_start.of fset(), m_end.container(), m_end.offset());
1231 } 1086 }
1232 1087
1233 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState) 1088 void Range::setStartAfter(Node* refNode, ExceptionState& exceptionState)
1234 { 1089 {
1235 checkNodeBA(refNode, exceptionState); 1090 checkNodeBA(refNode, exceptionState);
1236 if (exceptionState.hadException()) 1091 if (exceptionState.hadException())
1237 return; 1092 return;
1238 1093
1239 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); 1094 setStart(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState);
(...skipping 12 matching lines...) Expand all
1252 { 1107 {
1253 checkNodeBA(refNode, exceptionState); 1108 checkNodeBA(refNode, exceptionState);
1254 if (exceptionState.hadException()) 1109 if (exceptionState.hadException())
1255 return; 1110 return;
1256 1111
1257 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); 1112 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState);
1258 } 1113 }
1259 1114
1260 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) 1115 void Range::selectNode(Node* refNode, ExceptionState& exceptionState)
1261 { 1116 {
1262 if (!m_start.container()) {
1263 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1264 return;
1265 }
1266
1267 if (!refNode) { 1117 if (!refNode) {
1268 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1118 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1269 return; 1119 return;
1270 } 1120 }
1271 1121
1272 if (!refNode->parentNode()) { 1122 if (!refNode->parentNode()) {
1273 exceptionState.throwDOMException(InvalidNodeTypeError, "the given Node h as no parent."); 1123 exceptionState.throwDOMException(InvalidNodeTypeError, "the given Node h as no parent.");
1274 return; 1124 return;
1275 } 1125 }
1276 1126
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 1161
1312 if (m_ownerDocument != refNode->document()) 1162 if (m_ownerDocument != refNode->document())
1313 setDocument(refNode->document()); 1163 setDocument(refNode->document());
1314 1164
1315 setStartBefore(refNode); 1165 setStartBefore(refNode);
1316 setEndAfter(refNode); 1166 setEndAfter(refNode);
1317 } 1167 }
1318 1168
1319 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) 1169 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState)
1320 { 1170 {
1321 if (!m_start.container()) {
1322 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1323 return;
1324 }
1325
1326 if (!refNode) { 1171 if (!refNode) {
1327 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1172 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1328 return; 1173 return;
1329 } 1174 }
1330 1175
1331 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an E ntity, Notation 1176 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an E ntity, Notation
1332 // or DocumentType node. 1177 // or DocumentType node.
1333 for (Node* n = refNode; n; n = n->parentNode()) { 1178 for (Node* n = refNode; n; n = n->parentNode()) {
1334 switch (n->nodeType()) { 1179 switch (n->nodeType()) {
1335 case Node::ATTRIBUTE_NODE: 1180 case Node::ATTRIBUTE_NODE:
(...skipping 14 matching lines...) Expand all
1350 if (m_ownerDocument != refNode->document()) 1195 if (m_ownerDocument != refNode->document())
1351 setDocument(refNode->document()); 1196 setDocument(refNode->document());
1352 1197
1353 m_start.setToStartOfNode(*refNode); 1198 m_start.setToStartOfNode(*refNode);
1354 m_end.setToEndOfNode(*refNode); 1199 m_end.setToEndOfNode(*refNode);
1355 } 1200 }
1356 1201
1357 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc eptionState) 1202 void Range::surroundContents(PassRefPtr<Node> passNewParent, ExceptionState& exc eptionState)
1358 { 1203 {
1359 RefPtr<Node> newParent = passNewParent; 1204 RefPtr<Node> newParent = passNewParent;
1360
1361 if (!m_start.container()) {
1362 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1363 return;
1364 }
1365
1366 if (!newParent) { 1205 if (!newParent) {
1367 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll."); 1206 exceptionState.throwDOMException(NotFoundError, "The node provided is nu ll.");
1368 return; 1207 return;
1369 } 1208 }
1370 1209
1371 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No tation, 1210 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, No tation,
1372 // Document, or DocumentFragment node. 1211 // Document, or DocumentFragment node.
1373 switch (newParent->nodeType()) { 1212 switch (newParent->nodeType()) {
1374 case Node::ATTRIBUTE_NODE: 1213 case Node::ATTRIBUTE_NODE:
1375 case Node::DOCUMENT_FRAGMENT_NODE: 1214 case Node::DOCUMENT_FRAGMENT_NODE:
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1445 { 1284 {
1446 checkNodeBA(refNode, exceptionState); 1285 checkNodeBA(refNode, exceptionState);
1447 if (exceptionState.hadException()) 1286 if (exceptionState.hadException())
1448 return; 1287 return;
1449 1288
1450 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState); 1289 setStart(refNode->parentNode(), refNode->nodeIndex(), exceptionState);
1451 } 1290 }
1452 1291
1453 void Range::checkDeleteExtract(ExceptionState& exceptionState) 1292 void Range::checkDeleteExtract(ExceptionState& exceptionState)
1454 { 1293 {
1455 if (!m_start.container()) {
1456 exceptionState.throwDOMException(InvalidStateError, "The range has no co ntainer. Perhaps 'detach()' has been invoked on this object?");
1457 return;
1458 }
1459
1460 ASSERT(boundaryPointsValid()); 1294 ASSERT(boundaryPointsValid());
1461 1295
1462 if (!commonAncestorContainer(exceptionState) || exceptionState.hadException( )) 1296 if (!commonAncestorContainer())
1463 return; 1297 return;
1464 1298
1465 Node* pastLast = pastLastNode(); 1299 Node* pastLast = pastLastNode();
1466 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { 1300 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) {
1467 if (n->isDocumentTypeNode()) { 1301 if (n->isDocumentTypeNode()) {
1468 exceptionState.throwDOMException(HierarchyRequestError, "The Range c ontains a doctype node."); 1302 exceptionState.throwDOMException(HierarchyRequestError, "The Range c ontains a doctype node.");
1469 return; 1303 return;
1470 } 1304 }
1471 } 1305 }
1472 } 1306 }
1473 1307
1474 Node* Range::firstNode() const 1308 Node* Range::firstNode() const
1475 { 1309 {
1476 if (!m_start.container())
1477 return 0;
1478 if (m_start.container()->offsetInCharacters()) 1310 if (m_start.container()->offsetInCharacters())
1479 return m_start.container(); 1311 return m_start.container();
1480 if (Node* child = m_start.container()->traverseToChildAt(m_start.offset())) 1312 if (Node* child = m_start.container()->traverseToChildAt(m_start.offset()))
1481 return child; 1313 return child;
1482 if (!m_start.offset()) 1314 if (!m_start.offset())
1483 return m_start.container(); 1315 return m_start.container();
1484 return NodeTraversal::nextSkippingChildren(*m_start.container()); 1316 return NodeTraversal::nextSkippingChildren(*m_start.container());
1485 } 1317 }
1486 1318
1487 ShadowRoot* Range::shadowRoot() const 1319 ShadowRoot* Range::shadowRoot() const
1488 { 1320 {
1489 return startContainer() ? startContainer()->containingShadowRoot() : 0; 1321 return startContainer() ? startContainer()->containingShadowRoot() : 0;
1490 } 1322 }
1491 1323
1492 Node* Range::pastLastNode() const 1324 Node* Range::pastLastNode() const
1493 { 1325 {
1494 if (!m_start.container() || !m_end.container())
1495 return 0;
1496 if (m_end.container()->offsetInCharacters()) 1326 if (m_end.container()->offsetInCharacters())
1497 return NodeTraversal::nextSkippingChildren(*m_end.container()); 1327 return NodeTraversal::nextSkippingChildren(*m_end.container());
1498 if (Node* child = m_end.container()->traverseToChildAt(m_end.offset())) 1328 if (Node* child = m_end.container()->traverseToChildAt(m_end.offset()))
1499 return child; 1329 return child;
1500 return NodeTraversal::nextSkippingChildren(*m_end.container()); 1330 return NodeTraversal::nextSkippingChildren(*m_end.container());
1501 } 1331 }
1502 1332
1503 IntRect Range::boundingBox() const 1333 IntRect Range::boundingBox() const
1504 { 1334 {
1505 IntRect result; 1335 IntRect result;
1506 Vector<IntRect> rects; 1336 Vector<IntRect> rects;
1507 textRects(rects); 1337 textRects(rects);
1508 const size_t n = rects.size(); 1338 const size_t n = rects.size();
1509 for (size_t i = 0; i < n; ++i) 1339 for (size_t i = 0; i < n; ++i)
1510 result.unite(rects[i]); 1340 result.unite(rects[i]);
1511 return result; 1341 return result;
1512 } 1342 }
1513 1343
1514 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFi xedPosition* inFixed) const 1344 void Range::textRects(Vector<IntRect>& rects, bool useSelectionHeight, RangeInFi xedPosition* inFixed) const
1515 { 1345 {
1516 Node* startContainer = m_start.container(); 1346 Node* startContainer = m_start.container();
1347 ASSERT(startContainer);
1517 Node* endContainer = m_end.container(); 1348 Node* endContainer = m_end.container();
1518 1349 ASSERT(endContainer);
1519 if (!startContainer || !endContainer) {
1520 if (inFixed)
1521 *inFixed = NotFixedPosition;
1522 return;
1523 }
1524 1350
1525 bool allFixed = true; 1351 bool allFixed = true;
1526 bool someFixed = false; 1352 bool someFixed = false;
1527 1353
1528 Node* stopNode = pastLastNode(); 1354 Node* stopNode = pastLastNode();
1529 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) { 1355 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) {
1530 RenderObject* r = node->renderer(); 1356 RenderObject* r = node->renderer();
1531 if (!r || !r->isText()) 1357 if (!r || !r->isText())
1532 continue; 1358 continue;
1533 RenderText* renderText = toRenderText(r); 1359 RenderText* renderText = toRenderText(r);
1534 int startOffset = node == startContainer ? m_start.offset() : 0; 1360 int startOffset = node == startContainer ? m_start.offset() : 0;
1535 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max(); 1361 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max();
1536 bool isFixed = false; 1362 bool isFixed = false;
1537 renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSele ctionHeight, &isFixed); 1363 renderText->absoluteRectsForRange(rects, startOffset, endOffset, useSele ctionHeight, &isFixed);
1538 allFixed &= isFixed; 1364 allFixed &= isFixed;
1539 someFixed |= isFixed; 1365 someFixed |= isFixed;
1540 } 1366 }
1541 1367
1542 if (inFixed) 1368 if (inFixed)
1543 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition); 1369 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition);
1544 } 1370 }
1545 1371
1546 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeIn FixedPosition* inFixed) const 1372 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight, RangeIn FixedPosition* inFixed) const
1547 { 1373 {
1548 Node* startContainer = m_start.container(); 1374 Node* startContainer = m_start.container();
1375 ASSERT(startContainer);
1549 Node* endContainer = m_end.container(); 1376 Node* endContainer = m_end.container();
1550 1377 ASSERT(endContainer);
1551 if (!startContainer || !endContainer) {
1552 if (inFixed)
1553 *inFixed = NotFixedPosition;
1554 return;
1555 }
1556 1378
1557 bool allFixed = true; 1379 bool allFixed = true;
1558 bool someFixed = false; 1380 bool someFixed = false;
1559 1381
1560 Node* stopNode = pastLastNode(); 1382 Node* stopNode = pastLastNode();
1561 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) { 1383 for (Node* node = firstNode(); node != stopNode; node = NodeTraversal::next( *node)) {
1562 RenderObject* r = node->renderer(); 1384 RenderObject* r = node->renderer();
1563 if (!r || !r->isText()) 1385 if (!r || !r->isText())
1564 continue; 1386 continue;
1565 RenderText* renderText = toRenderText(r); 1387 RenderText* renderText = toRenderText(r);
1566 int startOffset = node == startContainer ? m_start.offset() : 0; 1388 int startOffset = node == startContainer ? m_start.offset() : 0;
1567 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max(); 1389 int endOffset = node == endContainer ? m_end.offset() : numeric_limits<i nt>::max();
1568 bool isFixed = false; 1390 bool isFixed = false;
1569 renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSele ctionHeight, &isFixed); 1391 renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSele ctionHeight, &isFixed);
1570 allFixed &= isFixed; 1392 allFixed &= isFixed;
1571 someFixed |= isFixed; 1393 someFixed |= isFixed;
1572 } 1394 }
1573 1395
1574 if (inFixed) 1396 if (inFixed)
1575 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition); 1397 *inFixed = allFixed ? EntirelyFixedPosition : (someFixed ? PartiallyFixe dPosition : NotFixedPosition);
1576 } 1398 }
1577 1399
1578 #ifndef NDEBUG 1400 #ifndef NDEBUG
1579 void Range::formatForDebugger(char* buffer, unsigned length) const 1401 void Range::formatForDebugger(char* buffer, unsigned length) const
1580 { 1402 {
1581 StringBuilder result; 1403 StringBuilder result;
1582 String s;
1583 1404
1584 if (!m_start.container() || !m_end.container()) 1405 const int FormatBufferSize = 1024;
1585 result.appendLiteral("<empty>"); 1406 char s[FormatBufferSize];
1586 else { 1407 result.appendLiteral("from offset ");
1587 const int FormatBufferSize = 1024; 1408 result.appendNumber(m_start.offset());
1588 char s[FormatBufferSize]; 1409 result.appendLiteral(" of ");
1589 result.appendLiteral("from offset "); 1410 m_start.container()->formatForDebugger(s, FormatBufferSize);
1590 result.appendNumber(m_start.offset()); 1411 result.append(s);
1591 result.appendLiteral(" of "); 1412 result.appendLiteral(" to offset ");
1592 m_start.container()->formatForDebugger(s, FormatBufferSize); 1413 result.appendNumber(m_end.offset());
1593 result.append(s); 1414 result.appendLiteral(" of ");
1594 result.appendLiteral(" to offset "); 1415 m_end.container()->formatForDebugger(s, FormatBufferSize);
1595 result.appendNumber(m_end.offset()); 1416 result.append(s);
1596 result.appendLiteral(" of ");
1597 m_end.container()->formatForDebugger(s, FormatBufferSize);
1598 result.append(s);
1599 }
1600 1417
1601 strncpy(buffer, result.toString().utf8().data(), length - 1); 1418 strncpy(buffer, result.toString().utf8().data(), length - 1);
1602 } 1419 }
1603 #endif 1420 #endif
1604 1421
1605 bool areRangesEqual(const Range* a, const Range* b) 1422 bool areRangesEqual(const Range* a, const Range* b)
1606 { 1423 {
1607 if (a == b) 1424 if (a == b)
1608 return true; 1425 return true;
1609 if (!a || !b) 1426 if (!a || !b)
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 start = startOfDocument(start); 1602 start = startOfDocument(start);
1786 end = endOfDocument(end); 1603 end = endOfDocument(end);
1787 } else 1604 } else
1788 return; 1605 return;
1789 setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().comp uteOffsetInContainerNode(), exceptionState); 1606 setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().comp uteOffsetInContainerNode(), exceptionState);
1790 setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOff setInContainerNode(), exceptionState); 1607 setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOff setInContainerNode(), exceptionState);
1791 } 1608 }
1792 1609
1793 PassRefPtrWillBeRawPtr<ClientRectList> Range::getClientRects() const 1610 PassRefPtrWillBeRawPtr<ClientRectList> Range::getClientRects() const
1794 { 1611 {
1795 if (!m_start.container())
1796 return ClientRectList::create();
1797
1798 m_ownerDocument->updateLayoutIgnorePendingStylesheets(); 1612 m_ownerDocument->updateLayoutIgnorePendingStylesheets();
1799 1613
1800 Vector<FloatQuad> quads; 1614 Vector<FloatQuad> quads;
1801 getBorderAndTextQuads(quads); 1615 getBorderAndTextQuads(quads);
1802 1616
1803 return ClientRectList::create(quads); 1617 return ClientRectList::create(quads);
1804 } 1618 }
1805 1619
1806 PassRefPtrWillBeRawPtr<ClientRect> Range::getBoundingClientRect() const 1620 PassRefPtrWillBeRawPtr<ClientRect> Range::getBoundingClientRect() const
1807 { 1621 {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1842 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQu ads, renderText); 1656 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQu ads, renderText);
1843 1657
1844 quads.appendVector(textQuads); 1658 quads.appendVector(textQuads);
1845 } 1659 }
1846 } 1660 }
1847 } 1661 }
1848 } 1662 }
1849 1663
1850 FloatRect Range::boundingRect() const 1664 FloatRect Range::boundingRect() const
1851 { 1665 {
1852 if (!m_start.container())
1853 return FloatRect();
1854
1855 m_ownerDocument->updateLayoutIgnorePendingStylesheets(); 1666 m_ownerDocument->updateLayoutIgnorePendingStylesheets();
1856 1667
1857 Vector<FloatQuad> quads; 1668 Vector<FloatQuad> quads;
1858 getBorderAndTextQuads(quads); 1669 getBorderAndTextQuads(quads);
1859 if (quads.isEmpty()) 1670 if (quads.isEmpty())
1860 return FloatRect(); 1671 return FloatRect();
1861 1672
1862 FloatRect result; 1673 FloatRect result;
1863 for (size_t i = 0; i < quads.size(); ++i) 1674 for (size_t i = 0; i < quads.size(); ++i)
1864 result.unite(quads[i].boundingBox()); 1675 result.unite(quads[i].boundingBox());
(...skipping 11 matching lines...) Expand all
1876 1687
1877 void showTree(const WebCore::Range* range) 1688 void showTree(const WebCore::Range* range)
1878 { 1689 {
1879 if (range && range->boundaryPointsValid()) { 1690 if (range && range->boundaryPointsValid()) {
1880 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r ange->endContainer(), "E"); 1691 range->startContainer()->showTreeAndMark(range->startContainer(), "S", r ange->endContainer(), "E");
1881 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset (), range->endOffset()); 1692 fprintf(stderr, "start offset: %d, end offset: %d\n", range->startOffset (), range->endOffset());
1882 } 1693 }
1883 } 1694 }
1884 1695
1885 #endif 1696 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698