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 | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All |
7 * rights reserved. | 7 * rights reserved. |
8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 DISALLOW_COPY_AND_ASSIGN(RangeUpdateScope); | 108 DISALLOW_COPY_AND_ASSIGN(RangeUpdateScope); |
109 }; | 109 }; |
110 | 110 |
111 int RangeUpdateScope::scope_count_ = 0; | 111 int RangeUpdateScope::scope_count_ = 0; |
112 #if DCHECK_IS_ON() | 112 #if DCHECK_IS_ON() |
113 Range* RangeUpdateScope::current_range_; | 113 Range* RangeUpdateScope::current_range_; |
114 #endif | 114 #endif |
115 | 115 |
116 inline Range::Range(Document& owner_document) | 116 inline Range::Range(Document& owner_document) |
117 : owner_document_(&owner_document), | 117 : owner_document_(&owner_document), |
118 start_(owner_document_), | 118 start_(*owner_document_), |
119 end_(owner_document_) { | 119 end_(*owner_document_) { |
120 owner_document_->AttachRange(this); | 120 owner_document_->AttachRange(this); |
121 } | 121 } |
122 | 122 |
123 Range* Range::Create(Document& owner_document) { | 123 Range* Range::Create(Document& owner_document) { |
124 return new Range(owner_document); | 124 return new Range(owner_document); |
125 } | 125 } |
126 | 126 |
127 inline Range::Range(Document& owner_document, | 127 inline Range::Range(Document& owner_document, |
128 Node* start_container, | 128 Node* start_container, |
129 unsigned start_offset, | 129 unsigned start_offset, |
130 Node* end_container, | 130 Node* end_container, |
131 unsigned end_offset) | 131 unsigned end_offset) |
132 : owner_document_(&owner_document), | 132 : owner_document_(&owner_document), |
133 start_(owner_document_), | 133 start_(*owner_document_), |
134 end_(owner_document_) { | 134 end_(*owner_document_) { |
135 owner_document_->AttachRange(this); | 135 owner_document_->AttachRange(this); |
136 | 136 |
137 // Simply setting the containers and offsets directly would not do any of the | 137 // Simply setting the containers and offsets directly would not do any of the |
138 // checking that setStart and setEnd do, so we call those functions. | 138 // checking that setStart and setEnd do, so we call those functions. |
139 setStart(start_container, start_offset); | 139 setStart(start_container, start_offset); |
140 setEnd(end_container, end_offset); | 140 setEnd(end_container, end_offset); |
141 } | 141 } |
142 | 142 |
143 Range* Range::Create(Document& owner_document, | 143 Range* Range::Create(Document& owner_document, |
144 Node* start_container, | 144 Node* start_container, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 DCHECK_NE(owner_document_, document); | 188 DCHECK_NE(owner_document_, document); |
189 DCHECK(owner_document_); | 189 DCHECK(owner_document_); |
190 owner_document_->DetachRange(this); | 190 owner_document_->DetachRange(this); |
191 owner_document_ = &document; | 191 owner_document_ = &document; |
192 start_.SetToStartOfNode(document); | 192 start_.SetToStartOfNode(document); |
193 end_.SetToStartOfNode(document); | 193 end_.SetToStartOfNode(document); |
194 owner_document_->AttachRange(this); | 194 owner_document_->AttachRange(this); |
195 } | 195 } |
196 | 196 |
197 Node* Range::commonAncestorContainer() const { | 197 Node* Range::commonAncestorContainer() const { |
198 return commonAncestorContainer(start_.Container(), end_.Container()); | 198 return commonAncestorContainer(&start_.Container(), &end_.Container()); |
199 } | 199 } |
200 | 200 |
201 Node* Range::commonAncestorContainer(const Node* container_a, | 201 Node* Range::commonAncestorContainer(const Node* container_a, |
202 const Node* container_b) { | 202 const Node* container_b) { |
203 if (!container_a || !container_b) | 203 if (!container_a || !container_b) |
204 return nullptr; | 204 return nullptr; |
205 return container_a->CommonAncestor(*container_b, NodeTraversal::Parent); | 205 return container_a->CommonAncestor(*container_b, NodeTraversal::Parent); |
206 } | 206 } |
207 | 207 |
208 static inline bool CheckForDifferentRootContainer( | 208 static inline bool CheckForDifferentRootContainer( |
209 const RangeBoundaryPoint& start, | 209 const RangeBoundaryPoint& start, |
210 const RangeBoundaryPoint& end) { | 210 const RangeBoundaryPoint& end) { |
211 Node* end_root_container = end.Container(); | 211 Node* end_root_container = &end.Container(); |
212 while (end_root_container->parentNode()) | 212 while (end_root_container->parentNode()) |
213 end_root_container = end_root_container->parentNode(); | 213 end_root_container = end_root_container->parentNode(); |
214 Node* start_root_container = start.Container(); | 214 Node* start_root_container = &start.Container(); |
215 while (start_root_container->parentNode()) | 215 while (start_root_container->parentNode()) |
216 start_root_container = start_root_container->parentNode(); | 216 start_root_container = start_root_container->parentNode(); |
217 | 217 |
218 return start_root_container != end_root_container || | 218 return start_root_container != end_root_container || |
219 (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0); | 219 (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0); |
220 } | 220 } |
221 | 221 |
222 void Range::setStart(Node* ref_node, | 222 void Range::setStart(Node* ref_node, |
223 unsigned offset, | 223 unsigned offset, |
224 ExceptionState& exception_state) { | 224 ExceptionState& exception_state) { |
225 if (!ref_node) { | 225 if (!ref_node) { |
226 // FIXME: Generated bindings code never calls with null, and neither should | 226 // FIXME: Generated bindings code never calls with null, and neither should |
227 // other callers! | 227 // other callers! |
228 exception_state.ThrowTypeError("The node provided is null."); | 228 exception_state.ThrowTypeError("The node provided is null."); |
229 return; | 229 return; |
230 } | 230 } |
231 | 231 |
232 RangeUpdateScope scope(this); | 232 RangeUpdateScope scope(this); |
233 bool did_move_document = false; | 233 bool did_move_document = false; |
234 if (ref_node->GetDocument() != owner_document_) { | 234 if (ref_node->GetDocument() != owner_document_) { |
235 SetDocument(ref_node->GetDocument()); | 235 SetDocument(ref_node->GetDocument()); |
236 did_move_document = true; | 236 did_move_document = true; |
237 } | 237 } |
238 | 238 |
239 Node* child_node = CheckNodeWOffset(ref_node, offset, exception_state); | 239 Node* child_node = CheckNodeWOffset(ref_node, offset, exception_state); |
240 if (exception_state.HadException()) | 240 if (exception_state.HadException()) |
241 return; | 241 return; |
242 | 242 |
243 start_.Set(ref_node, offset, child_node); | 243 start_.Set(*ref_node, offset, child_node); |
244 | 244 |
245 if (did_move_document || CheckForDifferentRootContainer(start_, end_)) | 245 if (did_move_document || CheckForDifferentRootContainer(start_, end_)) |
246 collapse(true); | 246 collapse(true); |
247 } | 247 } |
248 | 248 |
249 void Range::setEnd(Node* ref_node, | 249 void Range::setEnd(Node* ref_node, |
250 unsigned offset, | 250 unsigned offset, |
251 ExceptionState& exception_state) { | 251 ExceptionState& exception_state) { |
252 if (!ref_node) { | 252 if (!ref_node) { |
253 // FIXME: Generated bindings code never calls with null, and neither should | 253 // FIXME: Generated bindings code never calls with null, and neither should |
254 // other callers! | 254 // other callers! |
255 exception_state.ThrowTypeError("The node provided is null."); | 255 exception_state.ThrowTypeError("The node provided is null."); |
256 return; | 256 return; |
257 } | 257 } |
258 | 258 |
259 RangeUpdateScope scope(this); | 259 RangeUpdateScope scope(this); |
260 bool did_move_document = false; | 260 bool did_move_document = false; |
261 if (ref_node->GetDocument() != owner_document_) { | 261 if (ref_node->GetDocument() != owner_document_) { |
262 SetDocument(ref_node->GetDocument()); | 262 SetDocument(ref_node->GetDocument()); |
263 did_move_document = true; | 263 did_move_document = true; |
264 } | 264 } |
265 | 265 |
266 Node* child_node = CheckNodeWOffset(ref_node, offset, exception_state); | 266 Node* child_node = CheckNodeWOffset(ref_node, offset, exception_state); |
267 if (exception_state.HadException()) | 267 if (exception_state.HadException()) |
268 return; | 268 return; |
269 | 269 |
270 end_.Set(ref_node, offset, child_node); | 270 end_.Set(*ref_node, offset, child_node); |
271 | 271 |
272 if (did_move_document || CheckForDifferentRootContainer(start_, end_)) | 272 if (did_move_document || CheckForDifferentRootContainer(start_, end_)) |
273 collapse(false); | 273 collapse(false); |
274 } | 274 } |
275 | 275 |
276 void Range::setStart(const Position& start, ExceptionState& exception_state) { | 276 void Range::setStart(const Position& start, ExceptionState& exception_state) { |
277 Position parent_anchored = start.ParentAnchoredEquivalent(); | 277 Position parent_anchored = start.ParentAnchoredEquivalent(); |
278 setStart(parent_anchored.ComputeContainerNode(), | 278 setStart(parent_anchored.ComputeContainerNode(), |
279 parent_anchored.OffsetInContainerNode(), exception_state); | 279 parent_anchored.OffsetInContainerNode(), exception_state); |
280 } | 280 } |
(...skipping 10 matching lines...) Expand all Loading... |
291 end_ = start_; | 291 end_ = start_; |
292 else | 292 else |
293 start_ = end_; | 293 start_ = end_; |
294 } | 294 } |
295 | 295 |
296 bool Range::HasSameRoot(const Node& node) const { | 296 bool Range::HasSameRoot(const Node& node) const { |
297 if (node.GetDocument() != owner_document_) | 297 if (node.GetDocument() != owner_document_) |
298 return false; | 298 return false; |
299 // commonAncestorContainer() is O(depth). We should avoid to call it in common | 299 // commonAncestorContainer() is O(depth). We should avoid to call it in common |
300 // cases. | 300 // cases. |
301 if (node.IsInTreeScope() && start_.Container()->IsInTreeScope() && | 301 if (node.IsInTreeScope() && start_.Container().IsInTreeScope() && |
302 &node.GetTreeScope() == &start_.Container()->GetTreeScope()) | 302 &node.GetTreeScope() == &start_.Container().GetTreeScope()) |
303 return true; | 303 return true; |
304 return node.CommonAncestor(*start_.Container(), NodeTraversal::Parent); | 304 return node.CommonAncestor(start_.Container(), NodeTraversal::Parent); |
305 } | 305 } |
306 | 306 |
307 bool Range::isPointInRange(Node* ref_node, | 307 bool Range::isPointInRange(Node* ref_node, |
308 unsigned offset, | 308 unsigned offset, |
309 ExceptionState& exception_state) const { | 309 ExceptionState& exception_state) const { |
310 if (!ref_node) { | 310 if (!ref_node) { |
311 // FIXME: Generated bindings code never calls with null, and neither should | 311 // FIXME: Generated bindings code never calls with null, and neither should |
312 // other callers! | 312 // other callers! |
313 exception_state.ThrowTypeError("The node provided is null."); | 313 exception_state.ThrowTypeError("The node provided is null."); |
314 return false; | 314 return false; |
315 } | 315 } |
316 if (!HasSameRoot(*ref_node)) | 316 if (!HasSameRoot(*ref_node)) |
317 return false; | 317 return false; |
318 | 318 |
319 CheckNodeWOffset(ref_node, offset, exception_state); | 319 CheckNodeWOffset(ref_node, offset, exception_state); |
320 if (exception_state.HadException()) | 320 if (exception_state.HadException()) |
321 return false; | 321 return false; |
322 | 322 |
323 return compareBoundaryPoints(ref_node, offset, start_.Container(), | 323 return compareBoundaryPoints(ref_node, offset, &start_.Container(), |
324 start_.Offset(), exception_state) >= 0 && | 324 start_.Offset(), exception_state) >= 0 && |
325 !exception_state.HadException() && | 325 !exception_state.HadException() && |
326 compareBoundaryPoints(ref_node, offset, end_.Container(), | 326 compareBoundaryPoints(ref_node, offset, &end_.Container(), |
327 end_.Offset(), exception_state) <= 0 && | 327 end_.Offset(), exception_state) <= 0 && |
328 !exception_state.HadException(); | 328 !exception_state.HadException(); |
329 } | 329 } |
330 | 330 |
331 short Range::comparePoint(Node* ref_node, | 331 short Range::comparePoint(Node* ref_node, |
332 unsigned offset, | 332 unsigned offset, |
333 ExceptionState& exception_state) const { | 333 ExceptionState& exception_state) const { |
334 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint | 334 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint |
335 // This method returns -1, 0 or 1 depending on if the point described by the | 335 // This method returns -1, 0 or 1 depending on if the point described by the |
336 // refNode node and an offset within the node is before, same as, or after the | 336 // refNode node and an offset within the node is before, same as, or after the |
337 // range respectively. | 337 // range respectively. |
338 | 338 |
339 if (!HasSameRoot(*ref_node)) { | 339 if (!HasSameRoot(*ref_node)) { |
340 exception_state.ThrowDOMException( | 340 exception_state.ThrowDOMException( |
341 kWrongDocumentError, | 341 kWrongDocumentError, |
342 "The node provided and the Range are not in the same tree."); | 342 "The node provided and the Range are not in the same tree."); |
343 return 0; | 343 return 0; |
344 } | 344 } |
345 | 345 |
346 CheckNodeWOffset(ref_node, offset, exception_state); | 346 CheckNodeWOffset(ref_node, offset, exception_state); |
347 if (exception_state.HadException()) | 347 if (exception_state.HadException()) |
348 return 0; | 348 return 0; |
349 | 349 |
350 // compare to start, and point comes before | 350 // compare to start, and point comes before |
351 if (compareBoundaryPoints(ref_node, offset, start_.Container(), | 351 if (compareBoundaryPoints(ref_node, offset, &start_.Container(), |
352 start_.Offset(), exception_state) < 0) | 352 start_.Offset(), exception_state) < 0) |
353 return -1; | 353 return -1; |
354 | 354 |
355 if (exception_state.HadException()) | 355 if (exception_state.HadException()) |
356 return 0; | 356 return 0; |
357 | 357 |
358 // compare to end, and point comes after | 358 // compare to end, and point comes after |
359 if (compareBoundaryPoints(ref_node, offset, end_.Container(), end_.Offset(), | 359 if (compareBoundaryPoints(ref_node, offset, &end_.Container(), end_.Offset(), |
360 exception_state) > 0 && | 360 exception_state) > 0 && |
361 !exception_state.HadException()) | 361 !exception_state.HadException()) |
362 return 1; | 362 return 1; |
363 | 363 |
364 // point is in the middle of this range, or on the boundary points | 364 // point is in the middle of this range, or on the boundary points |
365 return 0; | 365 return 0; |
366 } | 366 } |
367 | 367 |
368 short Range::compareBoundaryPoints(unsigned how, | 368 short Range::compareBoundaryPoints(unsigned how, |
369 const Range* source_range, | 369 const Range* source_range, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 exception_state.ThrowDOMException( | 428 exception_state.ThrowDOMException( |
429 kWrongDocumentError, "The two ranges are in separate documents."); | 429 kWrongDocumentError, "The two ranges are in separate documents."); |
430 return 0; | 430 return 0; |
431 } | 431 } |
432 return result; | 432 return result; |
433 } | 433 } |
434 | 434 |
435 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundary_a, | 435 short Range::compareBoundaryPoints(const RangeBoundaryPoint& boundary_a, |
436 const RangeBoundaryPoint& boundary_b, | 436 const RangeBoundaryPoint& boundary_b, |
437 ExceptionState& exception_state) { | 437 ExceptionState& exception_state) { |
438 return compareBoundaryPoints(boundary_a.Container(), boundary_a.Offset(), | 438 return compareBoundaryPoints(&boundary_a.Container(), boundary_a.Offset(), |
439 boundary_b.Container(), boundary_b.Offset(), | 439 &boundary_b.Container(), boundary_b.Offset(), |
440 exception_state); | 440 exception_state); |
441 } | 441 } |
442 | 442 |
443 bool Range::BoundaryPointsValid() const { | 443 bool Range::BoundaryPointsValid() const { |
444 DummyExceptionStateForTesting exception_state; | 444 DummyExceptionStateForTesting exception_state; |
445 return compareBoundaryPoints(start_, end_, exception_state) <= 0 && | 445 return compareBoundaryPoints(start_, end_, exception_state) <= 0 && |
446 !exception_state.HadException(); | 446 !exception_state.HadException(); |
447 } | 447 } |
448 | 448 |
449 void Range::deleteContents(ExceptionState& exception_state) { | 449 void Range::deleteContents(ExceptionState& exception_state) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) | 553 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
554 fragment = DocumentFragment::Create(*owner_document_.Get()); | 554 fragment = DocumentFragment::Create(*owner_document_.Get()); |
555 | 555 |
556 if (collapsed()) | 556 if (collapsed()) |
557 return fragment; | 557 return fragment; |
558 | 558 |
559 Node* common_root = commonAncestorContainer(); | 559 Node* common_root = commonAncestorContainer(); |
560 DCHECK(common_root); | 560 DCHECK(common_root); |
561 | 561 |
562 if (start_.Container() == end_.Container()) { | 562 if (start_.Container() == end_.Container()) { |
563 ProcessContentsBetweenOffsets(action, fragment, start_.Container(), | 563 ProcessContentsBetweenOffsets(action, fragment, &start_.Container(), |
564 start_.Offset(), end_.Offset(), | 564 start_.Offset(), end_.Offset(), |
565 exception_state); | 565 exception_state); |
566 return fragment; | 566 return fragment; |
567 } | 567 } |
568 | 568 |
569 // Since mutation observers can modify the range during the process, the | 569 // Since mutation observers can modify the range during the process, the |
570 // boundary points need to be saved. | 570 // boundary points need to be saved. |
571 const RangeBoundaryPoint original_start(start_); | 571 const RangeBoundaryPoint original_start(start_); |
572 const RangeBoundaryPoint original_end(end_); | 572 const RangeBoundaryPoint original_end(end_); |
573 | 573 |
574 // what is the highest node that partially selects the start / end of the | 574 // what is the highest node that partially selects the start / end of the |
575 // range? | 575 // range? |
576 Node* partial_start = | 576 Node* partial_start = |
577 HighestAncestorUnderCommonRoot(original_start.Container(), common_root); | 577 HighestAncestorUnderCommonRoot(&original_start.Container(), common_root); |
578 Node* partial_end = | 578 Node* partial_end = |
579 HighestAncestorUnderCommonRoot(original_end.Container(), common_root); | 579 HighestAncestorUnderCommonRoot(&original_end.Container(), common_root); |
580 | 580 |
581 // Start and end containers are different. | 581 // Start and end containers are different. |
582 // There are three possibilities here: | 582 // There are three possibilities here: |
583 // 1. Start container == commonRoot (End container must be a descendant) | 583 // 1. Start container == commonRoot (End container must be a descendant) |
584 // 2. End container == commonRoot (Start container must be a descendant) | 584 // 2. End container == commonRoot (Start container must be a descendant) |
585 // 3. Neither is commonRoot, they are both descendants | 585 // 3. Neither is commonRoot, they are both descendants |
586 // | 586 // |
587 // In case 3, we grab everything after the start (up until a direct child | 587 // In case 3, we grab everything after the start (up until a direct child |
588 // of commonRoot) into leftContents, and everything before the end (up until | 588 // of commonRoot) into leftContents, and everything before the end (up until |
589 // a direct child of commonRoot) into rightContents. Then we process all | 589 // a direct child of commonRoot) into rightContents. Then we process all |
590 // commonRoot children between leftContents and rightContents | 590 // commonRoot children between leftContents and rightContents |
591 // | 591 // |
592 // In case 1 or 2, we skip either processing of leftContents or rightContents, | 592 // In case 1 or 2, we skip either processing of leftContents or rightContents, |
593 // in which case the last lot of nodes either goes from the first or last | 593 // in which case the last lot of nodes either goes from the first or last |
594 // child of commonRoot. | 594 // child of commonRoot. |
595 // | 595 // |
596 // These are deleted, cloned, or extracted (i.e. both) depending on action. | 596 // These are deleted, cloned, or extracted (i.e. both) depending on action. |
597 | 597 |
598 // Note that we are verifying that our common root hierarchy is still intact | 598 // Note that we are verifying that our common root hierarchy is still intact |
599 // after any DOM mutation event, at various stages below. See webkit bug | 599 // after any DOM mutation event, at various stages below. See webkit bug |
600 // 60350. | 600 // 60350. |
601 | 601 |
602 Node* left_contents = nullptr; | 602 Node* left_contents = nullptr; |
603 if (original_start.Container() != common_root && | 603 if (original_start.Container() != common_root && |
604 common_root->contains(original_start.Container())) { | 604 common_root->contains(&original_start.Container())) { |
605 left_contents = ProcessContentsBetweenOffsets( | 605 left_contents = ProcessContentsBetweenOffsets( |
606 action, nullptr, original_start.Container(), original_start.Offset(), | 606 action, nullptr, &original_start.Container(), original_start.Offset(), |
607 LengthOfContents(original_start.Container()), exception_state); | 607 LengthOfContents(&original_start.Container()), exception_state); |
608 left_contents = ProcessAncestorsAndTheirSiblings( | 608 left_contents = ProcessAncestorsAndTheirSiblings( |
609 action, original_start.Container(), kProcessContentsForward, | 609 action, &original_start.Container(), kProcessContentsForward, |
610 left_contents, common_root, exception_state); | 610 left_contents, common_root, exception_state); |
611 } | 611 } |
612 | 612 |
613 Node* right_contents = nullptr; | 613 Node* right_contents = nullptr; |
614 if (end_.Container() != common_root && | 614 if (end_.Container() != common_root && |
615 common_root->contains(original_end.Container())) { | 615 common_root->contains(&original_end.Container())) { |
616 right_contents = ProcessContentsBetweenOffsets( | 616 right_contents = ProcessContentsBetweenOffsets( |
617 action, nullptr, original_end.Container(), 0, original_end.Offset(), | 617 action, nullptr, &original_end.Container(), 0, original_end.Offset(), |
618 exception_state); | 618 exception_state); |
619 right_contents = ProcessAncestorsAndTheirSiblings( | 619 right_contents = ProcessAncestorsAndTheirSiblings( |
620 action, original_end.Container(), kProcessContentsBackward, | 620 action, &original_end.Container(), kProcessContentsBackward, |
621 right_contents, common_root, exception_state); | 621 right_contents, common_root, exception_state); |
622 } | 622 } |
623 | 623 |
624 // delete all children of commonRoot between the start and end container | 624 // delete all children of commonRoot between the start and end container |
625 Node* process_start = ChildOfCommonRootBeforeOffset( | 625 Node* process_start = ChildOfCommonRootBeforeOffset( |
626 original_start.Container(), original_start.Offset(), common_root); | 626 &original_start.Container(), original_start.Offset(), common_root); |
627 if (process_start && | 627 if (process_start && |
628 original_start.Container() != | 628 original_start.Container() != |
629 common_root) // processStart contains nodes before m_start. | 629 common_root) // processStart contains nodes before m_start. |
630 process_start = process_start->nextSibling(); | 630 process_start = process_start->nextSibling(); |
631 Node* process_end = ChildOfCommonRootBeforeOffset( | 631 Node* process_end = ChildOfCommonRootBeforeOffset( |
632 original_end.Container(), original_end.Offset(), common_root); | 632 &original_end.Container(), original_end.Offset(), common_root); |
633 | 633 |
634 // Collapse the range, making sure that the result is not within a node that | 634 // Collapse the range, making sure that the result is not within a node that |
635 // was partially selected. | 635 // was partially selected. |
636 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 636 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
637 if (partial_start && common_root->contains(partial_start)) { | 637 if (partial_start && common_root->contains(partial_start)) { |
638 // FIXME: We should not continue if we have an earlier error. | 638 // FIXME: We should not continue if we have an earlier error. |
639 exception_state.ClearException(); | 639 exception_state.ClearException(); |
640 setStart(partial_start->parentNode(), partial_start->NodeIndex() + 1, | 640 setStart(partial_start->parentNode(), partial_start->NodeIndex() + 1, |
641 exception_state); | 641 exception_state); |
642 } else if (partial_end && common_root->contains(partial_end)) { | 642 } else if (partial_end && common_root->contains(partial_end)) { |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 exception_state.ThrowTypeError("The node provided is null."); | 859 exception_state.ThrowTypeError("The node provided is null."); |
860 return; | 860 return; |
861 } | 861 } |
862 | 862 |
863 // HierarchyRequestError: Raised if the container of the start of the Range is | 863 // HierarchyRequestError: Raised if the container of the start of the Range is |
864 // of a type that does not allow children of the type of newNode or if newNode | 864 // of a type that does not allow children of the type of newNode or if newNode |
865 // is an ancestor of the container. | 865 // is an ancestor of the container. |
866 | 866 |
867 // an extra one here - if a text node is going to split, it must have a parent | 867 // an extra one here - if a text node is going to split, it must have a parent |
868 // to insert into | 868 // to insert into |
869 bool start_is_text = start_.Container()->IsTextNode(); | 869 bool start_is_text = start_.Container().IsTextNode(); |
870 if (start_is_text && !start_.Container()->parentNode()) { | 870 if (start_is_text && !start_.Container().parentNode()) { |
871 exception_state.ThrowDOMException(kHierarchyRequestError, | 871 exception_state.ThrowDOMException(kHierarchyRequestError, |
872 "This operation would split a text node, " | 872 "This operation would split a text node, " |
873 "but there's no parent into which to " | 873 "but there's no parent into which to " |
874 "insert."); | 874 "insert."); |
875 return; | 875 return; |
876 } | 876 } |
877 | 877 |
878 // In the case where the container is a text node, we check against the | 878 // In the case where the container is a text node, we check against the |
879 // container's parent, because text nodes get split up upon insertion. | 879 // container's parent, because text nodes get split up upon insertion. |
880 Node* check_against; | 880 Node* check_against; |
881 if (start_is_text) | 881 if (start_is_text) |
882 check_against = start_.Container()->parentNode(); | 882 check_against = start_.Container().parentNode(); |
883 else | 883 else |
884 check_against = start_.Container(); | 884 check_against = &start_.Container(); |
885 | 885 |
886 Node::NodeType new_node_type = new_node->getNodeType(); | 886 Node::NodeType new_node_type = new_node->getNodeType(); |
887 int num_new_children; | 887 int num_new_children; |
888 if (new_node_type == Node::kDocumentFragmentNode && | 888 if (new_node_type == Node::kDocumentFragmentNode && |
889 !new_node->IsShadowRoot()) { | 889 !new_node->IsShadowRoot()) { |
890 // check each child node, not the DocumentFragment itself | 890 // check each child node, not the DocumentFragment itself |
891 num_new_children = 0; | 891 num_new_children = 0; |
892 for (Node* c = ToDocumentFragment(new_node)->FirstChild(); c; | 892 for (Node* c = ToDocumentFragment(new_node)->FirstChild(); c; |
893 c = c->nextSibling()) { | 893 c = c->nextSibling()) { |
894 if (!check_against->ChildTypeAllowed(c->getNodeType())) { | 894 if (!check_against->ChildTypeAllowed(c->getNodeType())) { |
895 exception_state.ThrowDOMException( | 895 exception_state.ThrowDOMException( |
896 kHierarchyRequestError, | 896 kHierarchyRequestError, |
897 "The node to be inserted contains a '" + c->nodeName() + | 897 "The node to be inserted contains a '" + c->nodeName() + |
898 "' node, which may not be inserted here."); | 898 "' node, which may not be inserted here."); |
899 return; | 899 return; |
900 } | 900 } |
901 ++num_new_children; | 901 ++num_new_children; |
902 } | 902 } |
903 } else { | 903 } else { |
904 num_new_children = 1; | 904 num_new_children = 1; |
905 if (!check_against->ChildTypeAllowed(new_node_type)) { | 905 if (!check_against->ChildTypeAllowed(new_node_type)) { |
906 exception_state.ThrowDOMException( | 906 exception_state.ThrowDOMException( |
907 kHierarchyRequestError, | 907 kHierarchyRequestError, |
908 "The node to be inserted is a '" + new_node->nodeName() + | 908 "The node to be inserted is a '" + new_node->nodeName() + |
909 "' node, which may not be inserted here."); | 909 "' node, which may not be inserted here."); |
910 return; | 910 return; |
911 } | 911 } |
912 } | 912 } |
913 | 913 |
914 for (Node& node : NodeTraversal::InclusiveAncestorsOf(*start_.Container())) { | 914 for (Node& node : NodeTraversal::InclusiveAncestorsOf(start_.Container())) { |
915 if (node == new_node) { | 915 if (node == new_node) { |
916 exception_state.ThrowDOMException(kHierarchyRequestError, | 916 exception_state.ThrowDOMException(kHierarchyRequestError, |
917 "The node to be inserted contains the " | 917 "The node to be inserted contains the " |
918 "insertion point; it may not be " | 918 "insertion point; it may not be " |
919 "inserted into itself."); | 919 "inserted into itself."); |
920 return; | 920 return; |
921 } | 921 } |
922 } | 922 } |
923 | 923 |
924 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, | 924 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, |
(...skipping 14 matching lines...) Expand all Loading... |
939 "here."); | 939 "here."); |
940 return; | 940 return; |
941 } | 941 } |
942 break; | 942 break; |
943 } | 943 } |
944 | 944 |
945 EventQueueScope scope; | 945 EventQueueScope scope; |
946 bool collapsed = start_ == end_; | 946 bool collapsed = start_ == end_; |
947 Node* container = nullptr; | 947 Node* container = nullptr; |
948 if (start_is_text) { | 948 if (start_is_text) { |
949 container = start_.Container(); | 949 container = &start_.Container(); |
950 Text* new_text = | 950 Text* new_text = |
951 ToText(container)->splitText(start_.Offset(), exception_state); | 951 ToText(container)->splitText(start_.Offset(), exception_state); |
952 if (exception_state.HadException()) | 952 if (exception_state.HadException()) |
953 return; | 953 return; |
954 | 954 |
955 container = start_.Container(); | 955 container = &start_.Container(); |
956 container->parentNode()->InsertBefore(new_node, new_text, exception_state); | 956 container->parentNode()->InsertBefore(new_node, new_text, exception_state); |
957 if (exception_state.HadException()) | 957 if (exception_state.HadException()) |
958 return; | 958 return; |
959 | 959 |
960 if (collapsed) { | 960 if (collapsed) { |
961 // Some types of events don't support EventQueueScope. Given | 961 // Some types of events don't support EventQueueScope. Given |
962 // circumstance may mutate the tree so newText->parentNode() may | 962 // circumstance may mutate the tree so newText->parentNode() may |
963 // become null. | 963 // become null. |
964 if (!new_text->parentNode()) { | 964 if (!new_text->parentNode()) { |
965 exception_state.ThrowDOMException( | 965 exception_state.ThrowDOMException( |
(...skipping 12 matching lines...) Expand all Loading... |
978 // The insertion will do nothing, but we need to extend the range to | 978 // The insertion will do nothing, but we need to extend the range to |
979 // include the inserted nodes. | 979 // include the inserted nodes. |
980 Node* first_child = (new_node_type == Node::kDocumentFragmentNode) | 980 Node* first_child = (new_node_type == Node::kDocumentFragmentNode) |
981 ? ToDocumentFragment(new_node)->FirstChild() | 981 ? ToDocumentFragment(new_node)->FirstChild() |
982 : new_node; | 982 : new_node; |
983 DCHECK(first_child); | 983 DCHECK(first_child); |
984 start_.SetToBeforeChild(*first_child); | 984 start_.SetToBeforeChild(*first_child); |
985 return; | 985 return; |
986 } | 986 } |
987 | 987 |
988 container = start_.Container(); | 988 container = &start_.Container(); |
989 Node* reference_node = NodeTraversal::ChildAt(*container, start_.Offset()); | 989 Node* reference_node = NodeTraversal::ChildAt(*container, start_.Offset()); |
990 // TODO(tkent): The following check must be unnecessary if we follow the | 990 // TODO(tkent): The following check must be unnecessary if we follow the |
991 // algorithm defined in the specification. | 991 // algorithm defined in the specification. |
992 // https://dom.spec.whatwg.org/#concept-range-insert | 992 // https://dom.spec.whatwg.org/#concept-range-insert |
993 if (new_node != reference_node) { | 993 if (new_node != reference_node) { |
994 container->insertBefore(new_node, reference_node, exception_state); | 994 container->insertBefore(new_node, reference_node, exception_state); |
995 if (exception_state.HadException()) | 995 if (exception_state.HadException()) |
996 return; | 996 return; |
997 } | 997 } |
998 | 998 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 .SetEmitsObjectReplacementCharacter(true) | 1033 .SetEmitsObjectReplacementCharacter(true) |
1034 .Build()); | 1034 .Build()); |
1035 } | 1035 } |
1036 | 1036 |
1037 DocumentFragment* Range::createContextualFragment( | 1037 DocumentFragment* Range::createContextualFragment( |
1038 const String& markup, | 1038 const String& markup, |
1039 ExceptionState& exception_state) { | 1039 ExceptionState& exception_state) { |
1040 // Algorithm: | 1040 // Algorithm: |
1041 // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface | 1041 // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface |
1042 | 1042 |
1043 Node* node = start_.Container(); | 1043 Node* node = &start_.Container(); |
1044 | 1044 |
1045 // Step 1. | 1045 // Step 1. |
1046 Element* element; | 1046 Element* element; |
1047 if (!start_.Offset() && | 1047 if (!start_.Offset() && |
1048 (node->IsDocumentNode() || node->IsDocumentFragment())) | 1048 (node->IsDocumentNode() || node->IsDocumentFragment())) |
1049 element = nullptr; | 1049 element = nullptr; |
1050 else if (node->IsElementNode()) | 1050 else if (node->IsElementNode()) |
1051 element = ToElement(node); | 1051 element = ToElement(node); |
1052 else | 1052 else |
1053 element = node->parentElement(); | 1053 element = node->parentElement(); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 case Node::kProcessingInstructionNode: | 1196 case Node::kProcessingInstructionNode: |
1197 case Node::kTextNode: | 1197 case Node::kTextNode: |
1198 exception_state.ThrowDOMException( | 1198 exception_state.ThrowDOMException( |
1199 kInvalidNodeTypeError, | 1199 kInvalidNodeTypeError, |
1200 "The node provided is of type '" + n->nodeName() + "'."); | 1200 "The node provided is of type '" + n->nodeName() + "'."); |
1201 return; | 1201 return; |
1202 } | 1202 } |
1203 } | 1203 } |
1204 | 1204 |
1205 Range* Range::cloneRange() const { | 1205 Range* Range::cloneRange() const { |
1206 return Range::Create(*owner_document_.Get(), start_.Container(), | 1206 return Range::Create(*owner_document_.Get(), &start_.Container(), |
1207 start_.Offset(), end_.Container(), end_.Offset()); | 1207 start_.Offset(), &end_.Container(), end_.Offset()); |
1208 } | 1208 } |
1209 | 1209 |
1210 void Range::setStartAfter(Node* ref_node, ExceptionState& exception_state) { | 1210 void Range::setStartAfter(Node* ref_node, ExceptionState& exception_state) { |
1211 CheckNodeBA(ref_node, exception_state); | 1211 CheckNodeBA(ref_node, exception_state); |
1212 if (exception_state.HadException()) | 1212 if (exception_state.HadException()) |
1213 return; | 1213 return; |
1214 | 1214 |
1215 setStart(ref_node->parentNode(), ref_node->NodeIndex() + 1, exception_state); | 1215 setStart(ref_node->parentNode(), ref_node->NodeIndex() + 1, exception_state); |
1216 } | 1216 } |
1217 | 1217 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 case Node::kDocumentNode: | 1320 case Node::kDocumentNode: |
1321 case Node::kElementNode: | 1321 case Node::kElementNode: |
1322 case Node::kProcessingInstructionNode: | 1322 case Node::kProcessingInstructionNode: |
1323 case Node::kTextNode: | 1323 case Node::kTextNode: |
1324 break; | 1324 break; |
1325 case Node::kDocumentTypeNode: | 1325 case Node::kDocumentTypeNode: |
1326 return false; | 1326 return false; |
1327 } | 1327 } |
1328 } | 1328 } |
1329 | 1329 |
1330 RangeBoundaryPoint start_boundary_point(ref_node); | 1330 RangeBoundaryPoint start_boundary_point(*ref_node); |
1331 start_boundary_point.SetToStartOfNode(*ref_node); | 1331 start_boundary_point.SetToStartOfNode(*ref_node); |
1332 start = start_boundary_point.ToPosition(); | 1332 start = start_boundary_point.ToPosition(); |
1333 RangeBoundaryPoint end_boundary_point(ref_node); | 1333 RangeBoundaryPoint end_boundary_point(*ref_node); |
1334 end_boundary_point.SetToEndOfNode(*ref_node); | 1334 end_boundary_point.SetToEndOfNode(*ref_node); |
1335 end = end_boundary_point.ToPosition(); | 1335 end = end_boundary_point.ToPosition(); |
1336 return true; | 1336 return true; |
1337 } | 1337 } |
1338 | 1338 |
1339 // https://dom.spec.whatwg.org/#dom-range-surroundcontents | 1339 // https://dom.spec.whatwg.org/#dom-range-surroundcontents |
1340 void Range::surroundContents(Node* new_parent, | 1340 void Range::surroundContents(Node* new_parent, |
1341 ExceptionState& exception_state) { | 1341 ExceptionState& exception_state) { |
1342 if (!new_parent) { | 1342 if (!new_parent) { |
1343 // FIXME: Generated bindings code never calls with null, and neither should | 1343 // FIXME: Generated bindings code never calls with null, and neither should |
1344 // other callers! | 1344 // other callers! |
1345 exception_state.ThrowTypeError("The node provided is null."); | 1345 exception_state.ThrowTypeError("The node provided is null."); |
1346 return; | 1346 return; |
1347 } | 1347 } |
1348 | 1348 |
1349 // 1. If a non-Text node is partially contained in the context object, then | 1349 // 1. If a non-Text node is partially contained in the context object, then |
1350 // throw an InvalidStateError. | 1350 // throw an InvalidStateError. |
1351 Node* start_non_text_container = start_.Container(); | 1351 Node* start_non_text_container = &start_.Container(); |
1352 if (start_non_text_container->getNodeType() == Node::kTextNode) | 1352 if (start_non_text_container->getNodeType() == Node::kTextNode) |
1353 start_non_text_container = start_non_text_container->parentNode(); | 1353 start_non_text_container = start_non_text_container->parentNode(); |
1354 Node* end_non_text_container = end_.Container(); | 1354 Node* end_non_text_container = &end_.Container(); |
1355 if (end_non_text_container->getNodeType() == Node::kTextNode) | 1355 if (end_non_text_container->getNodeType() == Node::kTextNode) |
1356 end_non_text_container = end_non_text_container->parentNode(); | 1356 end_non_text_container = end_non_text_container->parentNode(); |
1357 if (start_non_text_container != end_non_text_container) { | 1357 if (start_non_text_container != end_non_text_container) { |
1358 exception_state.ThrowDOMException( | 1358 exception_state.ThrowDOMException( |
1359 kInvalidStateError, | 1359 kInvalidStateError, |
1360 "The Range has partially selected a non-Text node."); | 1360 "The Range has partially selected a non-Text node."); |
1361 return; | 1361 return; |
1362 } | 1362 } |
1363 | 1363 |
1364 // 2. If newParent is a Document, DocumentType, or DocumentFragment node, then | 1364 // 2. If newParent is a Document, DocumentType, or DocumentFragment node, then |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1426 for (Node* n = FirstNode(); n != past_last; n = NodeTraversal::Next(*n)) { | 1426 for (Node* n = FirstNode(); n != past_last; n = NodeTraversal::Next(*n)) { |
1427 if (n->IsDocumentTypeNode()) { | 1427 if (n->IsDocumentTypeNode()) { |
1428 exception_state.ThrowDOMException(kHierarchyRequestError, | 1428 exception_state.ThrowDOMException(kHierarchyRequestError, |
1429 "The Range contains a doctype node."); | 1429 "The Range contains a doctype node."); |
1430 return; | 1430 return; |
1431 } | 1431 } |
1432 } | 1432 } |
1433 } | 1433 } |
1434 | 1434 |
1435 Node* Range::FirstNode() const { | 1435 Node* Range::FirstNode() const { |
1436 if (start_.Container()->IsCharacterDataNode()) | 1436 if (start_.Container().IsCharacterDataNode()) |
1437 return start_.Container(); | 1437 return &start_.Container(); |
1438 if (Node* child = | 1438 if (Node* child = NodeTraversal::ChildAt(start_.Container(), start_.Offset())) |
1439 NodeTraversal::ChildAt(*start_.Container(), start_.Offset())) | |
1440 return child; | 1439 return child; |
1441 if (!start_.Offset()) | 1440 if (!start_.Offset()) |
1442 return start_.Container(); | 1441 return &start_.Container(); |
1443 return NodeTraversal::NextSkippingChildren(*start_.Container()); | 1442 return NodeTraversal::NextSkippingChildren(start_.Container()); |
1444 } | 1443 } |
1445 | 1444 |
1446 Node* Range::PastLastNode() const { | 1445 Node* Range::PastLastNode() const { |
1447 if (end_.Container()->IsCharacterDataNode()) | 1446 if (end_.Container().IsCharacterDataNode()) |
1448 return NodeTraversal::NextSkippingChildren(*end_.Container()); | 1447 return NodeTraversal::NextSkippingChildren(end_.Container()); |
1449 if (Node* child = NodeTraversal::ChildAt(*end_.Container(), end_.Offset())) | 1448 if (Node* child = NodeTraversal::ChildAt(end_.Container(), end_.Offset())) |
1450 return child; | 1449 return child; |
1451 return NodeTraversal::NextSkippingChildren(*end_.Container()); | 1450 return NodeTraversal::NextSkippingChildren(end_.Container()); |
1452 } | 1451 } |
1453 | 1452 |
1454 IntRect Range::BoundingBox() const { | 1453 IntRect Range::BoundingBox() const { |
1455 IntRect result; | 1454 IntRect result; |
1456 Vector<IntRect> rects; | 1455 Vector<IntRect> rects; |
1457 TextRects(rects); | 1456 TextRects(rects); |
1458 for (const IntRect& rect : rects) | 1457 for (const IntRect& rect : rects) |
1459 result.Unite(rect); | 1458 result.Unite(rect); |
1460 return result; | 1459 return result; |
1461 } | 1460 } |
1462 | 1461 |
1463 void Range::TextRects(Vector<IntRect>& rects, bool use_selection_height) const { | 1462 void Range::TextRects(Vector<IntRect>& rects, bool use_selection_height) const { |
1464 Node* start_container = start_.Container(); | 1463 Node* start_container = &start_.Container(); |
1465 DCHECK(start_container); | 1464 DCHECK(start_container); |
1466 Node* end_container = end_.Container(); | 1465 Node* end_container = &end_.Container(); |
1467 DCHECK(end_container); | 1466 DCHECK(end_container); |
1468 | 1467 |
1469 Node* stop_node = PastLastNode(); | 1468 Node* stop_node = PastLastNode(); |
1470 for (Node* node = FirstNode(); node != stop_node; | 1469 for (Node* node = FirstNode(); node != stop_node; |
1471 node = NodeTraversal::Next(*node)) { | 1470 node = NodeTraversal::Next(*node)) { |
1472 LayoutObject* r = node->GetLayoutObject(); | 1471 LayoutObject* r = node->GetLayoutObject(); |
1473 if (!r || !r->IsText()) | 1472 if (!r || !r->IsText()) |
1474 continue; | 1473 continue; |
1475 LayoutText* layout_text = ToLayoutText(r); | 1474 LayoutText* layout_text = ToLayoutText(r); |
1476 unsigned start_offset = node == start_container ? start_.Offset() : 0; | 1475 unsigned start_offset = node == start_container ? start_.Offset() : 0; |
1477 unsigned end_offset = node == end_container | 1476 unsigned end_offset = node == end_container |
1478 ? end_.Offset() | 1477 ? end_.Offset() |
1479 : std::numeric_limits<unsigned>::max(); | 1478 : std::numeric_limits<unsigned>::max(); |
1480 layout_text->AbsoluteRectsForRange(rects, start_offset, end_offset, | 1479 layout_text->AbsoluteRectsForRange(rects, start_offset, end_offset, |
1481 use_selection_height); | 1480 use_selection_height); |
1482 } | 1481 } |
1483 } | 1482 } |
1484 | 1483 |
1485 void Range::TextQuads(Vector<FloatQuad>& quads, | 1484 void Range::TextQuads(Vector<FloatQuad>& quads, |
1486 bool use_selection_height) const { | 1485 bool use_selection_height) const { |
1487 Node* start_container = start_.Container(); | 1486 Node* start_container = &start_.Container(); |
1488 DCHECK(start_container); | 1487 DCHECK(start_container); |
1489 Node* end_container = end_.Container(); | 1488 Node* end_container = &end_.Container(); |
1490 DCHECK(end_container); | 1489 DCHECK(end_container); |
1491 | 1490 |
1492 Node* stop_node = PastLastNode(); | 1491 Node* stop_node = PastLastNode(); |
1493 for (Node* node = FirstNode(); node != stop_node; | 1492 for (Node* node = FirstNode(); node != stop_node; |
1494 node = NodeTraversal::Next(*node)) { | 1493 node = NodeTraversal::Next(*node)) { |
1495 LayoutObject* r = node->GetLayoutObject(); | 1494 LayoutObject* r = node->GetLayoutObject(); |
1496 if (!r || !r->IsText()) | 1495 if (!r || !r->IsText()) |
1497 continue; | 1496 continue; |
1498 LayoutText* layout_text = ToLayoutText(r); | 1497 LayoutText* layout_text = ToLayoutText(r); |
1499 unsigned start_offset = node == start_container ? start_.Offset() : 0; | 1498 unsigned start_offset = node == start_container ? start_.Offset() : 0; |
(...skipping 17 matching lines...) Expand all Loading... |
1517 static inline void BoundaryNodeChildrenWillBeRemoved( | 1516 static inline void BoundaryNodeChildrenWillBeRemoved( |
1518 RangeBoundaryPoint& boundary, | 1517 RangeBoundaryPoint& boundary, |
1519 ContainerNode& container) { | 1518 ContainerNode& container) { |
1520 for (Node* node_to_be_removed = container.FirstChild(); node_to_be_removed; | 1519 for (Node* node_to_be_removed = container.FirstChild(); node_to_be_removed; |
1521 node_to_be_removed = node_to_be_removed->nextSibling()) { | 1520 node_to_be_removed = node_to_be_removed->nextSibling()) { |
1522 if (boundary.ChildBefore() == node_to_be_removed) { | 1521 if (boundary.ChildBefore() == node_to_be_removed) { |
1523 boundary.SetToStartOfNode(container); | 1522 boundary.SetToStartOfNode(container); |
1524 return; | 1523 return; |
1525 } | 1524 } |
1526 | 1525 |
1527 for (Node* n = boundary.Container(); n; n = n->parentNode()) { | 1526 for (Node* n = &boundary.Container(); n; n = n->parentNode()) { |
1528 if (n == node_to_be_removed) { | 1527 if (n == node_to_be_removed) { |
1529 boundary.SetToStartOfNode(container); | 1528 boundary.SetToStartOfNode(container); |
1530 return; | 1529 return; |
1531 } | 1530 } |
1532 } | 1531 } |
1533 } | 1532 } |
1534 } | 1533 } |
1535 | 1534 |
1536 void Range::NodeChildrenWillBeRemoved(ContainerNode& container) { | 1535 void Range::NodeChildrenWillBeRemoved(ContainerNode& container) { |
1537 DCHECK_EQ(container.GetDocument(), owner_document_); | 1536 DCHECK_EQ(container.GetDocument(), owner_document_); |
1538 BoundaryNodeChildrenWillBeRemoved(start_, container); | 1537 BoundaryNodeChildrenWillBeRemoved(start_, container); |
1539 BoundaryNodeChildrenWillBeRemoved(end_, container); | 1538 BoundaryNodeChildrenWillBeRemoved(end_, container); |
1540 } | 1539 } |
1541 | 1540 |
1542 static inline void BoundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, | 1541 static inline void BoundaryNodeWillBeRemoved(RangeBoundaryPoint& boundary, |
1543 Node& node_to_be_removed) { | 1542 Node& node_to_be_removed) { |
1544 if (boundary.ChildBefore() == node_to_be_removed) { | 1543 if (boundary.ChildBefore() == node_to_be_removed) { |
1545 boundary.ChildBeforeWillBeRemoved(); | 1544 boundary.ChildBeforeWillBeRemoved(); |
1546 return; | 1545 return; |
1547 } | 1546 } |
1548 | 1547 |
1549 for (Node* n = boundary.Container(); n; n = n->parentNode()) { | 1548 for (Node* n = &boundary.Container(); n; n = n->parentNode()) { |
1550 if (n == node_to_be_removed) { | 1549 if (n == node_to_be_removed) { |
1551 boundary.SetToBeforeChild(node_to_be_removed); | 1550 boundary.SetToBeforeChild(node_to_be_removed); |
1552 return; | 1551 return; |
1553 } | 1552 } |
1554 } | 1553 } |
1555 } | 1554 } |
1556 | 1555 |
1557 void Range::NodeWillBeRemoved(Node& node) { | 1556 void Range::NodeWillBeRemoved(Node& node) { |
1558 DCHECK_EQ(node.GetDocument(), owner_document_); | 1557 DCHECK_EQ(node.GetDocument(), owner_document_); |
1559 DCHECK_NE(node, owner_document_.Get()); | 1558 DCHECK_NE(node, owner_document_.Get()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 void Range::DidRemoveText(Node* text, unsigned offset, unsigned length) { | 1604 void Range::DidRemoveText(Node* text, unsigned offset, unsigned length) { |
1606 DCHECK(text); | 1605 DCHECK(text); |
1607 DCHECK_EQ(text->GetDocument(), owner_document_); | 1606 DCHECK_EQ(text->GetDocument(), owner_document_); |
1608 BoundaryTextRemoved(start_, text, offset, length); | 1607 BoundaryTextRemoved(start_, text, offset, length); |
1609 BoundaryTextRemoved(end_, text, offset, length); | 1608 BoundaryTextRemoved(end_, text, offset, length); |
1610 } | 1609 } |
1611 | 1610 |
1612 static inline void BoundaryTextNodesMerged(RangeBoundaryPoint& boundary, | 1611 static inline void BoundaryTextNodesMerged(RangeBoundaryPoint& boundary, |
1613 const NodeWithIndex& old_node, | 1612 const NodeWithIndex& old_node, |
1614 unsigned offset) { | 1613 unsigned offset) { |
1615 if (boundary.Container() == old_node.GetNode()) | 1614 if (boundary.Container() == old_node.GetNode()) { |
1616 boundary.Set(old_node.GetNode().previousSibling(), | 1615 Node* const previous_sibling = old_node.GetNode().previousSibling(); |
1617 boundary.Offset() + offset, 0); | 1616 DCHECK(previous_sibling); |
1618 else if (boundary.Container() == old_node.GetNode().parentNode() && | 1617 boundary.Set(*previous_sibling, boundary.Offset() + offset, 0); |
1619 boundary.Offset() == static_cast<unsigned>(old_node.Index())) | 1618 } else if (boundary.Container() == old_node.GetNode().parentNode() && |
1620 boundary.Set(old_node.GetNode().previousSibling(), offset, 0); | 1619 boundary.Offset() == static_cast<unsigned>(old_node.Index())) { |
| 1620 Node* const previous_sibling = old_node.GetNode().previousSibling(); |
| 1621 DCHECK(previous_sibling); |
| 1622 boundary.Set(*previous_sibling, offset, 0); |
| 1623 } |
1621 } | 1624 } |
1622 | 1625 |
1623 void Range::DidMergeTextNodes(const NodeWithIndex& old_node, unsigned offset) { | 1626 void Range::DidMergeTextNodes(const NodeWithIndex& old_node, unsigned offset) { |
1624 DCHECK_EQ(old_node.GetNode().GetDocument(), owner_document_); | 1627 DCHECK_EQ(old_node.GetNode().GetDocument(), owner_document_); |
1625 DCHECK(old_node.GetNode().parentNode()); | 1628 DCHECK(old_node.GetNode().parentNode()); |
1626 DCHECK(old_node.GetNode().IsTextNode()); | 1629 DCHECK(old_node.GetNode().IsTextNode()); |
1627 DCHECK(old_node.GetNode().previousSibling()); | 1630 DCHECK(old_node.GetNode().previousSibling()); |
1628 DCHECK(old_node.GetNode().previousSibling()->IsTextNode()); | 1631 DCHECK(old_node.GetNode().previousSibling()->IsTextNode()); |
1629 BoundaryTextNodesMerged(start_, old_node, offset); | 1632 BoundaryTextNodesMerged(start_, old_node, offset); |
1630 BoundaryTextNodesMerged(end_, old_node, offset); | 1633 BoundaryTextNodesMerged(end_, old_node, offset); |
1631 } | 1634 } |
1632 | 1635 |
1633 void Range::UpdateOwnerDocumentIfNeeded() { | 1636 void Range::UpdateOwnerDocumentIfNeeded() { |
1634 DCHECK(start_.Container()); | 1637 Document& new_document = start_.Container().GetDocument(); |
1635 DCHECK(end_.Container()); | 1638 DCHECK_EQ(new_document, end_.Container().GetDocument()); |
1636 Document& new_document = start_.Container()->GetDocument(); | |
1637 DCHECK_EQ(new_document, end_.Container()->GetDocument()); | |
1638 if (new_document == owner_document_) | 1639 if (new_document == owner_document_) |
1639 return; | 1640 return; |
1640 owner_document_->DetachRange(this); | 1641 owner_document_->DetachRange(this); |
1641 owner_document_ = &new_document; | 1642 owner_document_ = &new_document; |
1642 owner_document_->AttachRange(this); | 1643 owner_document_->AttachRange(this); |
1643 } | 1644 } |
1644 | 1645 |
1645 static inline void BoundaryTextNodeSplit(RangeBoundaryPoint& boundary, | 1646 static inline void BoundaryTextNodeSplit(RangeBoundaryPoint& boundary, |
1646 const Text& old_node) { | 1647 const Text& old_node) { |
1647 Node* boundary_container = boundary.Container(); | |
1648 unsigned boundary_offset = boundary.Offset(); | 1648 unsigned boundary_offset = boundary.Offset(); |
1649 if (boundary.ChildBefore() == &old_node) | 1649 if (boundary.ChildBefore() == &old_node) { |
1650 boundary.Set(boundary_container, boundary_offset + 1, | 1650 boundary.Set(boundary.Container(), boundary_offset + 1, |
1651 old_node.nextSibling()); | 1651 old_node.nextSibling()); |
1652 else if (boundary.Container() == &old_node && | 1652 } else if (boundary.Container() == &old_node && |
1653 boundary_offset > old_node.length()) | 1653 boundary_offset > old_node.length()) { |
1654 boundary.Set(old_node.nextSibling(), boundary_offset - old_node.length(), | 1654 Node* const next_sibling = old_node.nextSibling(); |
1655 0); | 1655 DCHECK(next_sibling); |
| 1656 boundary.Set(*next_sibling, boundary_offset - old_node.length(), 0); |
| 1657 } |
1656 } | 1658 } |
1657 | 1659 |
1658 void Range::DidSplitTextNode(const Text& old_node) { | 1660 void Range::DidSplitTextNode(const Text& old_node) { |
1659 DCHECK_EQ(old_node.GetDocument(), owner_document_); | 1661 DCHECK_EQ(old_node.GetDocument(), owner_document_); |
1660 DCHECK(old_node.parentNode()); | 1662 DCHECK(old_node.parentNode()); |
1661 DCHECK(old_node.nextSibling()); | 1663 DCHECK(old_node.nextSibling()); |
1662 DCHECK(old_node.nextSibling()->IsTextNode()); | 1664 DCHECK(old_node.nextSibling()->IsTextNode()); |
1663 BoundaryTextNodeSplit(start_, old_node); | 1665 BoundaryTextNodeSplit(start_, old_node); |
1664 BoundaryTextNodeSplit(end_, old_node); | 1666 BoundaryTextNodeSplit(end_, old_node); |
1665 DCHECK(BoundaryPointsValid()); | 1667 DCHECK(BoundaryPointsValid()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1700 GetBorderAndTextQuads(quads); | 1702 GetBorderAndTextQuads(quads); |
1701 | 1703 |
1702 return ClientRectList::Create(quads); | 1704 return ClientRectList::Create(quads); |
1703 } | 1705 } |
1704 | 1706 |
1705 ClientRect* Range::getBoundingClientRect() const { | 1707 ClientRect* Range::getBoundingClientRect() const { |
1706 return ClientRect::Create(BoundingRect()); | 1708 return ClientRect::Create(BoundingRect()); |
1707 } | 1709 } |
1708 | 1710 |
1709 void Range::GetBorderAndTextQuads(Vector<FloatQuad>& quads) const { | 1711 void Range::GetBorderAndTextQuads(Vector<FloatQuad>& quads) const { |
1710 Node* start_container = start_.Container(); | 1712 Node* start_container = &start_.Container(); |
1711 Node* end_container = end_.Container(); | 1713 Node* end_container = &end_.Container(); |
1712 Node* stop_node = PastLastNode(); | 1714 Node* stop_node = PastLastNode(); |
1713 | 1715 |
1714 HeapHashSet<Member<Node>> node_set; | 1716 HeapHashSet<Member<Node>> node_set; |
1715 for (Node* node = FirstNode(); node != stop_node; | 1717 for (Node* node = FirstNode(); node != stop_node; |
1716 node = NodeTraversal::Next(*node)) { | 1718 node = NodeTraversal::Next(*node)) { |
1717 if (node->IsElementNode()) | 1719 if (node->IsElementNode()) |
1718 node_set.insert(node); | 1720 node_set.insert(node); |
1719 } | 1721 } |
1720 | 1722 |
1721 for (Node* node = FirstNode(); node != stop_node; | 1723 for (Node* node = FirstNode(); node != stop_node; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 .Data() | 1828 .Data() |
1827 << "start offset: " << range->startOffset() | 1829 << "start offset: " << range->startOffset() |
1828 << ", end offset: " << range->endOffset(); | 1830 << ", end offset: " << range->endOffset(); |
1829 } else { | 1831 } else { |
1830 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " | 1832 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " |
1831 "invalid."; | 1833 "invalid."; |
1832 } | 1834 } |
1833 } | 1835 } |
1834 | 1836 |
1835 #endif | 1837 #endif |
OLD | NEW |