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

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

Issue 2812733003: Let RangeboundaryPoint::container_node_ be reference. (Closed)
Patch Set: Created 3 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
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 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/Range.h ('k') | third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698