OLD | NEW |
1 /* | 1 /* |
2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) | 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) |
4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) | 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) |
5 * (C) 2001 Peter Kelly (pmk@post.com) | 5 * (C) 2001 Peter Kelly (pmk@post.com) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All |
| 7 * rights reserved. |
7 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
8 * | 9 * |
9 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 11 * modify it under the terms of the GNU Library General Public |
11 * License as published by the Free Software Foundation; either | 12 * License as published by the Free Software Foundation; either |
12 * version 2 of the License, or (at your option) any later version. | 13 * version 2 of the License, or (at your option) any later version. |
13 * | 14 * |
14 * This library is distributed in the hope that it will be useful, | 15 * This library is distributed in the hope that it will be useful, |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 inline Range::Range(Document& ownerDocument, | 69 inline Range::Range(Document& ownerDocument, |
69 Node* startContainer, | 70 Node* startContainer, |
70 int startOffset, | 71 int startOffset, |
71 Node* endContainer, | 72 Node* endContainer, |
72 int endOffset) | 73 int endOffset) |
73 : m_ownerDocument(&ownerDocument), | 74 : m_ownerDocument(&ownerDocument), |
74 m_start(m_ownerDocument), | 75 m_start(m_ownerDocument), |
75 m_end(m_ownerDocument) { | 76 m_end(m_ownerDocument) { |
76 m_ownerDocument->attachRange(this); | 77 m_ownerDocument->attachRange(this); |
77 | 78 |
78 // Simply setting the containers and offsets directly would not do any of the
checking | 79 // Simply setting the containers and offsets directly would not do any of the |
79 // that setStart and setEnd do, so we call those functions. | 80 // checking that setStart and setEnd do, so we call those functions. |
80 setStart(startContainer, startOffset); | 81 setStart(startContainer, startOffset); |
81 setEnd(endContainer, endOffset); | 82 setEnd(endContainer, endOffset); |
82 } | 83 } |
83 | 84 |
84 Range* Range::create(Document& ownerDocument, | 85 Range* Range::create(Document& ownerDocument, |
85 Node* startContainer, | 86 Node* startContainer, |
86 int startOffset, | 87 int startOffset, |
87 Node* endContainer, | 88 Node* endContainer, |
88 int endOffset) { | 89 int endOffset) { |
89 return new Range(ownerDocument, startContainer, startOffset, endContainer, | 90 return new Range(ownerDocument, startContainer, startOffset, endContainer, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 startRootContainer = startRootContainer->parentNode(); | 163 startRootContainer = startRootContainer->parentNode(); |
163 | 164 |
164 return startRootContainer != endRootContainer || | 165 return startRootContainer != endRootContainer || |
165 (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0); | 166 (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0); |
166 } | 167 } |
167 | 168 |
168 void Range::setStart(Node* refNode, | 169 void Range::setStart(Node* refNode, |
169 int offset, | 170 int offset, |
170 ExceptionState& exceptionState) { | 171 ExceptionState& exceptionState) { |
171 if (!refNode) { | 172 if (!refNode) { |
172 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 173 // FIXME: Generated bindings code never calls with null, and neither should |
| 174 // other callers! |
173 exceptionState.throwTypeError("The node provided is null."); | 175 exceptionState.throwTypeError("The node provided is null."); |
174 return; | 176 return; |
175 } | 177 } |
176 | 178 |
177 bool didMoveDocument = false; | 179 bool didMoveDocument = false; |
178 if (refNode->document() != m_ownerDocument) { | 180 if (refNode->document() != m_ownerDocument) { |
179 setDocument(refNode->document()); | 181 setDocument(refNode->document()); |
180 didMoveDocument = true; | 182 didMoveDocument = true; |
181 } | 183 } |
182 | 184 |
183 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); | 185 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); |
184 if (exceptionState.hadException()) | 186 if (exceptionState.hadException()) |
185 return; | 187 return; |
186 | 188 |
187 m_start.set(refNode, offset, childNode); | 189 m_start.set(refNode, offset, childNode); |
188 | 190 |
189 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 191 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
190 collapse(true); | 192 collapse(true); |
191 } | 193 } |
192 | 194 |
193 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { | 195 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { |
194 if (!refNode) { | 196 if (!refNode) { |
195 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 197 // FIXME: Generated bindings code never calls with null, and neither should |
| 198 // other callers! |
196 exceptionState.throwTypeError("The node provided is null."); | 199 exceptionState.throwTypeError("The node provided is null."); |
197 return; | 200 return; |
198 } | 201 } |
199 | 202 |
200 bool didMoveDocument = false; | 203 bool didMoveDocument = false; |
201 if (refNode->document() != m_ownerDocument) { | 204 if (refNode->document() != m_ownerDocument) { |
202 setDocument(refNode->document()); | 205 setDocument(refNode->document()); |
203 didMoveDocument = true; | 206 didMoveDocument = true; |
204 } | 207 } |
205 | 208 |
(...skipping 22 matching lines...) Expand all Loading... |
228 void Range::collapse(bool toStart) { | 231 void Range::collapse(bool toStart) { |
229 if (toStart) | 232 if (toStart) |
230 m_end = m_start; | 233 m_end = m_start; |
231 else | 234 else |
232 m_start = m_end; | 235 m_start = m_end; |
233 } | 236 } |
234 | 237 |
235 bool Range::isNodeFullyContained(Node& node) const { | 238 bool Range::isNodeFullyContained(Node& node) const { |
236 ContainerNode* parentNode = node.parentNode(); | 239 ContainerNode* parentNode = node.parentNode(); |
237 int nodeIndex = node.nodeIndex(); | 240 int nodeIndex = node.nodeIndex(); |
238 return isPointInRange( | 241 return isPointInRange(parentNode, nodeIndex, |
239 parentNode, nodeIndex, | 242 IGNORE_EXCEPTION) // starts in the middle of this |
240 IGNORE_EXCEPTION) // starts in the middle of this range, or on the
boundary points. | 243 // range, or on the boundary points. |
241 && | 244 && isPointInRange(parentNode, nodeIndex + 1, |
242 isPointInRange( | 245 IGNORE_EXCEPTION); // ends in the middle of this |
243 parentNode, nodeIndex + 1, | 246 // range, or on the boundary |
244 IGNORE_EXCEPTION); // ends in the middle of this range, or on the
boundary points. | 247 // points. |
245 } | 248 } |
246 | 249 |
247 bool Range::isPointInRange(Node* refNode, | 250 bool Range::isPointInRange(Node* refNode, |
248 int offset, | 251 int offset, |
249 ExceptionState& exceptionState) const { | 252 ExceptionState& exceptionState) const { |
250 if (!refNode) { | 253 if (!refNode) { |
251 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 254 // FIXME: Generated bindings code never calls with null, and neither should |
| 255 // other callers! |
252 exceptionState.throwTypeError("The node provided is null."); | 256 exceptionState.throwTypeError("The node provided is null."); |
253 return false; | 257 return false; |
254 } | 258 } |
255 | 259 |
256 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) { | 260 if (!refNode->inActiveDocument() || refNode->document() != m_ownerDocument) { |
257 return false; | 261 return false; |
258 } | 262 } |
259 | 263 |
260 checkNodeWOffset(refNode, offset, exceptionState); | 264 checkNodeWOffset(refNode, offset, exceptionState); |
261 if (exceptionState.hadException()) | 265 if (exceptionState.hadException()) |
262 return false; | 266 return false; |
263 | 267 |
264 return compareBoundaryPoints(refNode, offset, m_start.container(), | 268 return compareBoundaryPoints(refNode, offset, m_start.container(), |
265 m_start.offset(), exceptionState) >= 0 && | 269 m_start.offset(), exceptionState) >= 0 && |
266 !exceptionState.hadException() && | 270 !exceptionState.hadException() && |
267 compareBoundaryPoints(refNode, offset, m_end.container(), | 271 compareBoundaryPoints(refNode, offset, m_end.container(), |
268 m_end.offset(), exceptionState) <= 0 && | 272 m_end.offset(), exceptionState) <= 0 && |
269 !exceptionState.hadException(); | 273 !exceptionState.hadException(); |
270 } | 274 } |
271 | 275 |
272 short Range::comparePoint(Node* refNode, | 276 short Range::comparePoint(Node* refNode, |
273 int offset, | 277 int offset, |
274 ExceptionState& exceptionState) const { | 278 ExceptionState& exceptionState) const { |
275 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint | 279 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint |
276 // This method returns -1, 0 or 1 depending on if the point described by the | 280 // This method returns -1, 0 or 1 depending on if the point described by the |
277 // refNode node and an offset within the node is before, same as, or after the
range respectively. | 281 // refNode node and an offset within the node is before, same as, or after the |
| 282 // range respectively. |
278 | 283 |
279 if (!refNode->inActiveDocument()) { | 284 if (!refNode->inActiveDocument()) { |
280 exceptionState.throwDOMException( | 285 exceptionState.throwDOMException( |
281 WrongDocumentError, "The node provided is not in an active document."); | 286 WrongDocumentError, "The node provided is not in an active document."); |
282 return 0; | 287 return 0; |
283 } | 288 } |
284 | 289 |
285 if (refNode->document() != m_ownerDocument) { | 290 if (refNode->document() != m_ownerDocument) { |
286 exceptionState.throwDOMException( | 291 exceptionState.throwDOMException( |
287 WrongDocumentError, | 292 WrongDocumentError, |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 { | 402 { |
398 EventQueueScope eventQueueScope; | 403 EventQueueScope eventQueueScope; |
399 processContents(DELETE_CONTENTS, exceptionState); | 404 processContents(DELETE_CONTENTS, exceptionState); |
400 } | 405 } |
401 } | 406 } |
402 | 407 |
403 static bool nodeValidForIntersects(Node* refNode, | 408 static bool nodeValidForIntersects(Node* refNode, |
404 Document* expectedDocument, | 409 Document* expectedDocument, |
405 ExceptionState& exceptionState) { | 410 ExceptionState& exceptionState) { |
406 if (!refNode) { | 411 if (!refNode) { |
407 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 412 // FIXME: Generated bindings code never calls with null, and neither should |
| 413 // other callers! |
408 exceptionState.throwTypeError("The node provided is null."); | 414 exceptionState.throwTypeError("The node provided is null."); |
409 return false; | 415 return false; |
410 } | 416 } |
411 | 417 |
412 if (!refNode->inActiveDocument() || refNode->document() != expectedDocument) { | 418 if (!refNode->inActiveDocument() || refNode->document() != expectedDocument) { |
413 // Firefox doesn't throw an exception for these cases; it returns false. | 419 // Firefox doesn't throw an exception for these cases; it returns false. |
414 return false; | 420 return false; |
415 } | 421 } |
416 | 422 |
417 return true; | 423 return true; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 Node* commonRoot = commonAncestorContainer(); | 546 Node* commonRoot = commonAncestorContainer(); |
541 DCHECK(commonRoot); | 547 DCHECK(commonRoot); |
542 | 548 |
543 if (m_start.container() == m_end.container()) { | 549 if (m_start.container() == m_end.container()) { |
544 processContentsBetweenOffsets(action, fragment, m_start.container(), | 550 processContentsBetweenOffsets(action, fragment, m_start.container(), |
545 m_start.offset(), m_end.offset(), | 551 m_start.offset(), m_end.offset(), |
546 exceptionState); | 552 exceptionState); |
547 return fragment; | 553 return fragment; |
548 } | 554 } |
549 | 555 |
550 // Since mutation observers can modify the range during the process, the bound
ary points need to be saved. | 556 // Since mutation observers can modify the range during the process, the |
| 557 // boundary points need to be saved. |
551 RangeBoundaryPoint originalStart(m_start); | 558 RangeBoundaryPoint originalStart(m_start); |
552 RangeBoundaryPoint originalEnd(m_end); | 559 RangeBoundaryPoint originalEnd(m_end); |
553 | 560 |
554 // what is the highest node that partially selects the start / end of the rang
e? | 561 // what is the highest node that partially selects the start / end of the |
| 562 // range? |
555 Node* partialStart = | 563 Node* partialStart = |
556 highestAncestorUnderCommonRoot(originalStart.container(), commonRoot); | 564 highestAncestorUnderCommonRoot(originalStart.container(), commonRoot); |
557 Node* partialEnd = | 565 Node* partialEnd = |
558 highestAncestorUnderCommonRoot(originalEnd.container(), commonRoot); | 566 highestAncestorUnderCommonRoot(originalEnd.container(), commonRoot); |
559 | 567 |
560 // Start and end containers are different. | 568 // Start and end containers are different. |
561 // There are three possibilities here: | 569 // There are three possibilities here: |
562 // 1. Start container == commonRoot (End container must be a descendant) | 570 // 1. Start container == commonRoot (End container must be a descendant) |
563 // 2. End container == commonRoot (Start container must be a descendant) | 571 // 2. End container == commonRoot (Start container must be a descendant) |
564 // 3. Neither is commonRoot, they are both descendants | 572 // 3. Neither is commonRoot, they are both descendants |
565 // | 573 // |
566 // In case 3, we grab everything after the start (up until a direct child | 574 // In case 3, we grab everything after the start (up until a direct child |
567 // of commonRoot) into leftContents, and everything before the end (up until | 575 // of commonRoot) into leftContents, and everything before the end (up until |
568 // a direct child of commonRoot) into rightContents. Then we process all | 576 // a direct child of commonRoot) into rightContents. Then we process all |
569 // commonRoot children between leftContents and rightContents | 577 // commonRoot children between leftContents and rightContents |
570 // | 578 // |
571 // In case 1 or 2, we skip either processing of leftContents or rightContents, | 579 // In case 1 or 2, we skip either processing of leftContents or rightContents, |
572 // in which case the last lot of nodes either goes from the first or last | 580 // in which case the last lot of nodes either goes from the first or last |
573 // child of commonRoot. | 581 // child of commonRoot. |
574 // | 582 // |
575 // These are deleted, cloned, or extracted (i.e. both) depending on action. | 583 // These are deleted, cloned, or extracted (i.e. both) depending on action. |
576 | 584 |
577 // Note that we are verifying that our common root hierarchy is still intact | 585 // Note that we are verifying that our common root hierarchy is still intact |
578 // after any DOM mutation event, at various stages below. See webkit bug 60350
. | 586 // after any DOM mutation event, at various stages below. See webkit bug |
| 587 // 60350. |
579 | 588 |
580 Node* leftContents = nullptr; | 589 Node* leftContents = nullptr; |
581 if (originalStart.container() != commonRoot && | 590 if (originalStart.container() != commonRoot && |
582 commonRoot->contains(originalStart.container())) { | 591 commonRoot->contains(originalStart.container())) { |
583 leftContents = processContentsBetweenOffsets( | 592 leftContents = processContentsBetweenOffsets( |
584 action, nullptr, originalStart.container(), originalStart.offset(), | 593 action, nullptr, originalStart.container(), originalStart.offset(), |
585 originalStart.container()->lengthOfContents(), exceptionState); | 594 originalStart.container()->lengthOfContents(), exceptionState); |
586 leftContents = processAncestorsAndTheirSiblings( | 595 leftContents = processAncestorsAndTheirSiblings( |
587 action, originalStart.container(), ProcessContentsForward, leftContents, | 596 action, originalStart.container(), ProcessContentsForward, leftContents, |
588 commonRoot, exceptionState); | 597 commonRoot, exceptionState); |
(...skipping 13 matching lines...) Expand all Loading... |
602 // delete all children of commonRoot between the start and end container | 611 // delete all children of commonRoot between the start and end container |
603 Node* processStart = childOfCommonRootBeforeOffset( | 612 Node* processStart = childOfCommonRootBeforeOffset( |
604 originalStart.container(), originalStart.offset(), commonRoot); | 613 originalStart.container(), originalStart.offset(), commonRoot); |
605 if (processStart && | 614 if (processStart && |
606 originalStart.container() != | 615 originalStart.container() != |
607 commonRoot) // processStart contains nodes before m_start. | 616 commonRoot) // processStart contains nodes before m_start. |
608 processStart = processStart->nextSibling(); | 617 processStart = processStart->nextSibling(); |
609 Node* processEnd = childOfCommonRootBeforeOffset( | 618 Node* processEnd = childOfCommonRootBeforeOffset( |
610 originalEnd.container(), originalEnd.offset(), commonRoot); | 619 originalEnd.container(), originalEnd.offset(), commonRoot); |
611 | 620 |
612 // Collapse the range, making sure that the result is not within a node that w
as partially selected. | 621 // Collapse the range, making sure that the result is not within a node that |
| 622 // was partially selected. |
613 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { | 623 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { |
614 if (partialStart && commonRoot->contains(partialStart)) { | 624 if (partialStart && commonRoot->contains(partialStart)) { |
615 // FIXME: We should not continue if we have an earlier error. | 625 // FIXME: We should not continue if we have an earlier error. |
616 exceptionState.clearException(); | 626 exceptionState.clearException(); |
617 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, | 627 setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, |
618 exceptionState); | 628 exceptionState); |
619 } else if (partialEnd && commonRoot->contains(partialEnd)) { | 629 } else if (partialEnd && commonRoot->contains(partialEnd)) { |
620 // FIXME: We should not continue if we have an earlier error. | 630 // FIXME: We should not continue if we have an earlier error. |
621 exceptionState.clearException(); | 631 exceptionState.clearException(); |
622 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), | 632 setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 | 671 |
662 Node* Range::processContentsBetweenOffsets(ActionType action, | 672 Node* Range::processContentsBetweenOffsets(ActionType action, |
663 DocumentFragment* fragment, | 673 DocumentFragment* fragment, |
664 Node* container, | 674 Node* container, |
665 unsigned startOffset, | 675 unsigned startOffset, |
666 unsigned endOffset, | 676 unsigned endOffset, |
667 ExceptionState& exceptionState) { | 677 ExceptionState& exceptionState) { |
668 DCHECK(container); | 678 DCHECK(container); |
669 DCHECK_LE(startOffset, endOffset); | 679 DCHECK_LE(startOffset, endOffset); |
670 | 680 |
671 // This switch statement must be consistent with that of Node::lengthOfContent
s. | 681 // This switch statement must be consistent with that of |
| 682 // Node::lengthOfContents. |
672 Node* result = nullptr; | 683 Node* result = nullptr; |
673 switch (container->getNodeType()) { | 684 switch (container->getNodeType()) { |
674 case Node::kTextNode: | 685 case Node::kTextNode: |
675 case Node::kCdataSectionNode: | 686 case Node::kCdataSectionNode: |
676 case Node::kCommentNode: | 687 case Node::kCommentNode: |
677 case Node::kProcessingInstructionNode: | 688 case Node::kProcessingInstructionNode: |
678 endOffset = std::min(endOffset, toCharacterData(container)->length()); | 689 endOffset = std::min(endOffset, toCharacterData(container)->length()); |
679 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | 690 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
680 CharacterData* c = | 691 CharacterData* c = |
681 static_cast<CharacterData*>(container->cloneNode(true)); | 692 static_cast<CharacterData*>(container->cloneNode(true)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 if (runner == commonRoot) | 765 if (runner == commonRoot) |
755 break; | 766 break; |
756 ancestors.append(runner); | 767 ancestors.append(runner); |
757 } | 768 } |
758 | 769 |
759 Node* firstChildInAncestorToProcess = direction == ProcessContentsForward | 770 Node* firstChildInAncestorToProcess = direction == ProcessContentsForward |
760 ? container->nextSibling() | 771 ? container->nextSibling() |
761 : container->previousSibling(); | 772 : container->previousSibling(); |
762 for (const auto& ancestor : ancestors) { | 773 for (const auto& ancestor : ancestors) { |
763 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { | 774 if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
764 if (Node* clonedAncestor = ancestor->cloneNode( | 775 // Might have been removed already during mutation event. |
765 false)) { // Might have been removed already during mutation even
t. | 776 if (Node* clonedAncestor = ancestor->cloneNode(false)) { |
766 clonedAncestor->appendChild(clonedContainer, exceptionState); | 777 clonedAncestor->appendChild(clonedContainer, exceptionState); |
767 clonedContainer = clonedAncestor; | 778 clonedContainer = clonedAncestor; |
768 } | 779 } |
769 } | 780 } |
770 | 781 |
771 // Copy siblings of an ancestor of start/end containers | 782 // Copy siblings of an ancestor of start/end containers |
772 // FIXME: This assertion may fail if DOM is modified during mutation event | 783 // FIXME: This assertion may fail if DOM is modified during mutation event |
773 // FIXME: Share code with Range::processNodes | 784 // FIXME: Share code with Range::processNodes |
774 DCHECK(!firstChildInAncestorToProcess || | 785 DCHECK(!firstChildInAncestorToProcess || |
775 firstChildInAncestorToProcess->parentNode() == ancestor); | 786 firstChildInAncestorToProcess->parentNode() == ancestor); |
776 | 787 |
777 NodeVector nodes; | 788 NodeVector nodes; |
778 for (Node* child = firstChildInAncestorToProcess; child; | 789 for (Node* child = firstChildInAncestorToProcess; child; |
779 child = (direction == ProcessContentsForward) | 790 child = (direction == ProcessContentsForward) |
780 ? child->nextSibling() | 791 ? child->nextSibling() |
781 : child->previousSibling()) | 792 : child->previousSibling()) |
782 nodes.append(child); | 793 nodes.append(child); |
783 | 794 |
784 for (const auto& node : nodes) { | 795 for (const auto& node : nodes) { |
785 Node* child = node.get(); | 796 Node* child = node.get(); |
786 switch (action) { | 797 switch (action) { |
787 case DELETE_CONTENTS: | 798 case DELETE_CONTENTS: |
788 // Prior call of ancestor->removeChild() may cause a tree change due t
o DOMSubtreeModified event. | 799 // Prior call of ancestor->removeChild() may cause a tree change due |
789 // Therefore, we need to make sure |ancestor| is still |child|'s paren
t. | 800 // to DOMSubtreeModified event. Therefore, we need to make sure |
| 801 // |ancestor| is still |child|'s parent. |
790 if (ancestor == child->parentNode()) | 802 if (ancestor == child->parentNode()) |
791 ancestor->removeChild(child, exceptionState); | 803 ancestor->removeChild(child, exceptionState); |
792 break; | 804 break; |
793 case EXTRACT_CONTENTS: // will remove child from ancestor | 805 case EXTRACT_CONTENTS: // will remove child from ancestor |
794 if (direction == ProcessContentsForward) | 806 if (direction == ProcessContentsForward) |
795 clonedContainer->appendChild(child, exceptionState); | 807 clonedContainer->appendChild(child, exceptionState); |
796 else | 808 else |
797 clonedContainer->insertBefore(child, clonedContainer->firstChild(), | 809 clonedContainer->insertBefore(child, clonedContainer->firstChild(), |
798 exceptionState); | 810 exceptionState); |
799 break; | 811 break; |
(...skipping 23 matching lines...) Expand all Loading... |
823 | 835 |
824 return processContents(EXTRACT_CONTENTS, exceptionState); | 836 return processContents(EXTRACT_CONTENTS, exceptionState); |
825 } | 837 } |
826 | 838 |
827 DocumentFragment* Range::cloneContents(ExceptionState& exceptionState) { | 839 DocumentFragment* Range::cloneContents(ExceptionState& exceptionState) { |
828 return processContents(CLONE_CONTENTS, exceptionState); | 840 return processContents(CLONE_CONTENTS, exceptionState); |
829 } | 841 } |
830 | 842 |
831 void Range::insertNode(Node* newNode, ExceptionState& exceptionState) { | 843 void Range::insertNode(Node* newNode, ExceptionState& exceptionState) { |
832 if (!newNode) { | 844 if (!newNode) { |
833 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 845 // FIXME: Generated bindings code never calls with null, and neither should |
| 846 // other callers! |
834 exceptionState.throwTypeError("The node provided is null."); | 847 exceptionState.throwTypeError("The node provided is null."); |
835 return; | 848 return; |
836 } | 849 } |
837 | 850 |
838 // HierarchyRequestError: Raised if the container of the start of the Range is
of a type that | 851 // HierarchyRequestError: Raised if the container of the start of the Range is |
839 // does not allow children of the type of newNode or if newNode is an ancestor
of the container. | 852 // of a type that does not allow children of the type of newNode or if newNode |
| 853 // is an ancestor of the container. |
840 | 854 |
841 // an extra one here - if a text node is going to split, it must have a parent
to insert into | 855 // an extra one here - if a text node is going to split, it must have a parent |
| 856 // to insert into |
842 bool startIsText = m_start.container()->isTextNode(); | 857 bool startIsText = m_start.container()->isTextNode(); |
843 if (startIsText && !m_start.container()->parentNode()) { | 858 if (startIsText && !m_start.container()->parentNode()) { |
844 exceptionState.throwDOMException(HierarchyRequestError, | 859 exceptionState.throwDOMException(HierarchyRequestError, |
845 "This operation would split a text node, " | 860 "This operation would split a text node, " |
846 "but there's no parent into which to " | 861 "but there's no parent into which to " |
847 "insert."); | 862 "insert."); |
848 return; | 863 return; |
849 } | 864 } |
850 | 865 |
851 // In the case where the container is a text node, we check against the contai
ner's parent, because | 866 // In the case where the container is a text node, we check against the |
852 // text nodes get split up upon insertion. | 867 // container's parent, because text nodes get split up upon insertion. |
853 Node* checkAgainst; | 868 Node* checkAgainst; |
854 if (startIsText) | 869 if (startIsText) |
855 checkAgainst = m_start.container()->parentNode(); | 870 checkAgainst = m_start.container()->parentNode(); |
856 else | 871 else |
857 checkAgainst = m_start.container(); | 872 checkAgainst = m_start.container(); |
858 | 873 |
859 Node::NodeType newNodeType = newNode->getNodeType(); | 874 Node::NodeType newNodeType = newNode->getNodeType(); |
860 int numNewChildren; | 875 int numNewChildren; |
861 if (newNodeType == Node::kDocumentFragmentNode && !newNode->isShadowRoot()) { | 876 if (newNodeType == Node::kDocumentFragmentNode && !newNode->isShadowRoot()) { |
862 // check each child node, not the DocumentFragment itself | 877 // check each child node, not the DocumentFragment itself |
(...skipping 23 matching lines...) Expand all Loading... |
886 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*m_start.container())) { | 901 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*m_start.container())) { |
887 if (node == newNode) { | 902 if (node == newNode) { |
888 exceptionState.throwDOMException(HierarchyRequestError, | 903 exceptionState.throwDOMException(HierarchyRequestError, |
889 "The node to be inserted contains the " | 904 "The node to be inserted contains the " |
890 "insertion point; it may not be " | 905 "insertion point; it may not be " |
891 "inserted into itself."); | 906 "inserted into itself."); |
892 return; | 907 return; |
893 } | 908 } |
894 } | 909 } |
895 | 910 |
896 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, Shado
wRoot or Document node. | 911 // InvalidNodeTypeError: Raised if newNode is an Attr, Entity, Notation, |
| 912 // ShadowRoot or Document node. |
897 switch (newNodeType) { | 913 switch (newNodeType) { |
898 case Node::kAttributeNode: | 914 case Node::kAttributeNode: |
899 case Node::kDocumentNode: | 915 case Node::kDocumentNode: |
900 exceptionState.throwDOMException( | 916 exceptionState.throwDOMException( |
901 InvalidNodeTypeError, "The node to be inserted is a '" + | 917 InvalidNodeTypeError, "The node to be inserted is a '" + |
902 newNode->nodeName() + | 918 newNode->nodeName() + |
903 "' node, which may not be inserted here."); | 919 "' node, which may not be inserted here."); |
904 return; | 920 return; |
905 default: | 921 default: |
906 if (newNode->isShadowRoot()) { | 922 if (newNode->isShadowRoot()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 "but there's no parent into which to continue."); | 955 "but there's no parent into which to continue."); |
940 return; | 956 return; |
941 } | 957 } |
942 m_end.setToBeforeChild(*newText); | 958 m_end.setToBeforeChild(*newText); |
943 } | 959 } |
944 } else { | 960 } else { |
945 Node* lastChild = (newNodeType == Node::kDocumentFragmentNode) | 961 Node* lastChild = (newNodeType == Node::kDocumentFragmentNode) |
946 ? toDocumentFragment(newNode)->lastChild() | 962 ? toDocumentFragment(newNode)->lastChild() |
947 : newNode; | 963 : newNode; |
948 if (lastChild && lastChild == m_start.childBefore()) { | 964 if (lastChild && lastChild == m_start.childBefore()) { |
949 // The insertion will do nothing, but we need to extend the range to inclu
de | 965 // The insertion will do nothing, but we need to extend the range to |
950 // the inserted nodes. | 966 // include the inserted nodes. |
951 Node* firstChild = (newNodeType == Node::kDocumentFragmentNode) | 967 Node* firstChild = (newNodeType == Node::kDocumentFragmentNode) |
952 ? toDocumentFragment(newNode)->firstChild() | 968 ? toDocumentFragment(newNode)->firstChild() |
953 : newNode; | 969 : newNode; |
954 DCHECK(firstChild); | 970 DCHECK(firstChild); |
955 m_start.setToBeforeChild(*firstChild); | 971 m_start.setToBeforeChild(*firstChild); |
956 return; | 972 return; |
957 } | 973 } |
958 | 974 |
959 container = m_start.container(); | 975 container = m_start.container(); |
960 container->insertBefore( | 976 container->insertBefore( |
961 newNode, NodeTraversal::childAt(*container, m_start.offset()), | 977 newNode, NodeTraversal::childAt(*container, m_start.offset()), |
962 exceptionState); | 978 exceptionState); |
963 if (exceptionState.hadException()) | 979 if (exceptionState.hadException()) |
964 return; | 980 return; |
965 | 981 |
966 // Note that m_start.offset() may have changed as a result of container->ins
ertBefore, | 982 // Note that m_start.offset() may have changed as a result of |
967 // when the node we are inserting comes before the range in the same contain
er. | 983 // container->insertBefore, when the node we are inserting comes before the |
| 984 // range in the same container. |
968 if (collapsed && numNewChildren) | 985 if (collapsed && numNewChildren) |
969 m_end.set(m_start.container(), m_start.offset() + numNewChildren, | 986 m_end.set(m_start.container(), m_start.offset() + numNewChildren, |
970 lastChild); | 987 lastChild); |
971 } | 988 } |
972 } | 989 } |
973 | 990 |
974 String Range::toString() const { | 991 String Range::toString() const { |
975 StringBuilder builder; | 992 StringBuilder builder; |
976 | 993 |
977 Node* pastLast = pastLastNode(); | 994 Node* pastLast = pastLastNode(); |
978 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { | 995 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { |
979 Node::NodeType type = n->getNodeType(); | 996 Node::NodeType type = n->getNodeType(); |
980 if (type == Node::kTextNode || type == Node::kCdataSectionNode) { | 997 if (type == Node::kTextNode || type == Node::kCdataSectionNode) { |
981 String data = toCharacterData(n)->data(); | 998 String data = toCharacterData(n)->data(); |
982 int length = data.length(); | 999 int length = data.length(); |
983 int start = (n == m_start.container()) | 1000 int start = (n == m_start.container()) |
984 ? std::min(std::max(0, m_start.offset()), length) | 1001 ? std::min(std::max(0, m_start.offset()), length) |
985 : 0; | 1002 : 0; |
986 int end = (n == m_end.container()) | 1003 int end = (n == m_end.container()) |
987 ? std::min(std::max(start, m_end.offset()), length) | 1004 ? std::min(std::max(start, m_end.offset()), length) |
988 : length; | 1005 : length; |
989 builder.append(data, start, end - start); | 1006 builder.append(data, start, end - start); |
990 } | 1007 } |
991 } | 1008 } |
992 | 1009 |
993 return builder.toString(); | 1010 return builder.toString(); |
994 } | 1011 } |
995 | 1012 |
996 String Range::text() const { | 1013 String Range::text() const { |
997 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets n
eeds to be audited. | 1014 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
998 // see http://crbug.com/590369 for more details. | 1015 // needs to be audited. see http://crbug.com/590369 for more details. |
999 ownerDocument().updateStyleAndLayoutIgnorePendingStylesheets(); | 1016 ownerDocument().updateStyleAndLayoutIgnorePendingStylesheets(); |
1000 | 1017 |
1001 return plainText(EphemeralRange(this), | 1018 return plainText(EphemeralRange(this), |
1002 TextIteratorEmitsObjectReplacementCharacter); | 1019 TextIteratorEmitsObjectReplacementCharacter); |
1003 } | 1020 } |
1004 | 1021 |
1005 DocumentFragment* Range::createContextualFragment( | 1022 DocumentFragment* Range::createContextualFragment( |
1006 const String& markup, | 1023 const String& markup, |
1007 ExceptionState& exceptionState) { | 1024 ExceptionState& exceptionState) { |
1008 // Algorithm: http://domparsing.spec.whatwg.org/#extensions-to-the-range-inter
face | 1025 // Algorithm: |
| 1026 // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface |
1009 | 1027 |
1010 Node* node = m_start.container(); | 1028 Node* node = m_start.container(); |
1011 | 1029 |
1012 // Step 1. | 1030 // Step 1. |
1013 Element* element; | 1031 Element* element; |
1014 if (!m_start.offset() && | 1032 if (!m_start.offset() && |
1015 (node->isDocumentNode() || node->isDocumentFragment())) | 1033 (node->isDocumentNode() || node->isDocumentFragment())) |
1016 element = nullptr; | 1034 element = nullptr; |
1017 else if (node->isElementNode()) | 1035 else if (node->isElementNode()) |
1018 element = toElement(node); | 1036 element = toElement(node); |
1019 else | 1037 else |
1020 element = node->parentElement(); | 1038 element = node->parentElement(); |
1021 | 1039 |
1022 // Step 2. | 1040 // Step 2. |
1023 if (!element || isHTMLHtmlElement(element)) { | 1041 if (!element || isHTMLHtmlElement(element)) { |
1024 Document& document = node->document(); | 1042 Document& document = node->document(); |
1025 | 1043 |
1026 if (document.isSVGDocument()) { | 1044 if (document.isSVGDocument()) { |
1027 element = document.documentElement(); | 1045 element = document.documentElement(); |
1028 if (!element) | 1046 if (!element) |
1029 element = SVGSVGElement::create(document); | 1047 element = SVGSVGElement::create(document); |
1030 } else { | 1048 } else { |
1031 // Optimization over spec: try to reuse the existing <body> element, if it
is available. | 1049 // Optimization over spec: try to reuse the existing <body> element, if it |
| 1050 // is available. |
1032 element = document.body(); | 1051 element = document.body(); |
1033 if (!element) | 1052 if (!element) |
1034 element = HTMLBodyElement::create(document); | 1053 element = HTMLBodyElement::create(document); |
1035 } | 1054 } |
1036 } | 1055 } |
1037 | 1056 |
1038 // Steps 3, 4, 5. | 1057 // Steps 3, 4, 5. |
1039 return blink::createContextualFragment( | 1058 return blink::createContextualFragment( |
1040 markup, element, AllowScriptingContentAndDoNotMarkAlreadyStarted, | 1059 markup, element, AllowScriptingContentAndDoNotMarkAlreadyStarted, |
1041 exceptionState); | 1060 exceptionState); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 "There is no child at offset " + String::number(offset) + "."); | 1106 "There is no child at offset " + String::number(offset) + "."); |
1088 return childBefore; | 1107 return childBefore; |
1089 } | 1108 } |
1090 } | 1109 } |
1091 ASSERT_NOT_REACHED(); | 1110 ASSERT_NOT_REACHED(); |
1092 return nullptr; | 1111 return nullptr; |
1093 } | 1112 } |
1094 | 1113 |
1095 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const { | 1114 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const { |
1096 if (!n) { | 1115 if (!n) { |
1097 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 1116 // FIXME: Generated bindings code never calls with null, and neither should |
| 1117 // other callers! |
1098 exceptionState.throwTypeError("The node provided is null."); | 1118 exceptionState.throwTypeError("The node provided is null."); |
1099 return; | 1119 return; |
1100 } | 1120 } |
1101 | 1121 |
1102 // InvalidNodeTypeError: Raised if the root container of refNode is not an | 1122 // InvalidNodeTypeError: Raised if the root container of refNode is not an |
1103 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG shado
w DOM tree, | 1123 // Attr, Document, DocumentFragment or ShadowRoot node, or part of a SVG |
1104 // or if refNode is a Document, DocumentFragment, ShadowRoot, Attr, Entity, or
Notation node. | 1124 // shadow DOM tree, or if refNode is a Document, DocumentFragment, ShadowRoot, |
| 1125 // Attr, Entity, or Notation node. |
1105 | 1126 |
1106 if (!n->parentNode()) { | 1127 if (!n->parentNode()) { |
1107 exceptionState.throwDOMException(InvalidNodeTypeError, | 1128 exceptionState.throwDOMException(InvalidNodeTypeError, |
1108 "the given Node has no parent."); | 1129 "the given Node has no parent."); |
1109 return; | 1130 return; |
1110 } | 1131 } |
1111 | 1132 |
1112 switch (n->getNodeType()) { | 1133 switch (n->getNodeType()) { |
1113 case Node::kAttributeNode: | 1134 case Node::kAttributeNode: |
1114 case Node::kDocumentFragmentNode: | 1135 case Node::kDocumentFragmentNode: |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1172 void Range::setEndAfter(Node* refNode, ExceptionState& exceptionState) { | 1193 void Range::setEndAfter(Node* refNode, ExceptionState& exceptionState) { |
1173 checkNodeBA(refNode, exceptionState); | 1194 checkNodeBA(refNode, exceptionState); |
1174 if (exceptionState.hadException()) | 1195 if (exceptionState.hadException()) |
1175 return; | 1196 return; |
1176 | 1197 |
1177 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); | 1198 setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, exceptionState); |
1178 } | 1199 } |
1179 | 1200 |
1180 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) { | 1201 void Range::selectNode(Node* refNode, ExceptionState& exceptionState) { |
1181 if (!refNode) { | 1202 if (!refNode) { |
1182 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 1203 // FIXME: Generated bindings code never calls with null, and neither should |
| 1204 // other callers! |
1183 exceptionState.throwTypeError("The node provided is null."); | 1205 exceptionState.throwTypeError("The node provided is null."); |
1184 return; | 1206 return; |
1185 } | 1207 } |
1186 | 1208 |
1187 if (!refNode->parentNode()) { | 1209 if (!refNode->parentNode()) { |
1188 exceptionState.throwDOMException(InvalidNodeTypeError, | 1210 exceptionState.throwDOMException(InvalidNodeTypeError, |
1189 "the given Node has no parent."); | 1211 "the given Node has no parent."); |
1190 return; | 1212 return; |
1191 } | 1213 } |
1192 | 1214 |
(...skipping 16 matching lines...) Expand all Loading... |
1209 | 1231 |
1210 if (m_ownerDocument != refNode->document()) | 1232 if (m_ownerDocument != refNode->document()) |
1211 setDocument(refNode->document()); | 1233 setDocument(refNode->document()); |
1212 | 1234 |
1213 setStartBefore(refNode); | 1235 setStartBefore(refNode); |
1214 setEndAfter(refNode); | 1236 setEndAfter(refNode); |
1215 } | 1237 } |
1216 | 1238 |
1217 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) { | 1239 void Range::selectNodeContents(Node* refNode, ExceptionState& exceptionState) { |
1218 if (!refNode) { | 1240 if (!refNode) { |
1219 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 1241 // FIXME: Generated bindings code never calls with null, and neither should |
| 1242 // other callers! |
1220 exceptionState.throwTypeError("The node provided is null."); | 1243 exceptionState.throwTypeError("The node provided is null."); |
1221 return; | 1244 return; |
1222 } | 1245 } |
1223 | 1246 |
1224 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an Ent
ity, Notation | 1247 // InvalidNodeTypeError: Raised if refNode or an ancestor of refNode is an |
| 1248 // Entity, Notation |
1225 // or DocumentType node. | 1249 // or DocumentType node. |
1226 for (Node* n = refNode; n; n = n->parentNode()) { | 1250 for (Node* n = refNode; n; n = n->parentNode()) { |
1227 switch (n->getNodeType()) { | 1251 switch (n->getNodeType()) { |
1228 case Node::kAttributeNode: | 1252 case Node::kAttributeNode: |
1229 case Node::kCdataSectionNode: | 1253 case Node::kCdataSectionNode: |
1230 case Node::kCommentNode: | 1254 case Node::kCommentNode: |
1231 case Node::kDocumentFragmentNode: | 1255 case Node::kDocumentFragmentNode: |
1232 case Node::kDocumentNode: | 1256 case Node::kDocumentNode: |
1233 case Node::kElementNode: | 1257 case Node::kElementNode: |
1234 case Node::kProcessingInstructionNode: | 1258 case Node::kProcessingInstructionNode: |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 startBoundaryPoint.setToStartOfNode(*refNode); | 1298 startBoundaryPoint.setToStartOfNode(*refNode); |
1275 start = startBoundaryPoint.toPosition(); | 1299 start = startBoundaryPoint.toPosition(); |
1276 RangeBoundaryPoint endBoundaryPoint(refNode); | 1300 RangeBoundaryPoint endBoundaryPoint(refNode); |
1277 endBoundaryPoint.setToEndOfNode(*refNode); | 1301 endBoundaryPoint.setToEndOfNode(*refNode); |
1278 end = endBoundaryPoint.toPosition(); | 1302 end = endBoundaryPoint.toPosition(); |
1279 return true; | 1303 return true; |
1280 } | 1304 } |
1281 | 1305 |
1282 void Range::surroundContents(Node* newParent, ExceptionState& exceptionState) { | 1306 void Range::surroundContents(Node* newParent, ExceptionState& exceptionState) { |
1283 if (!newParent) { | 1307 if (!newParent) { |
1284 // FIXME: Generated bindings code never calls with null, and neither should
other callers! | 1308 // FIXME: Generated bindings code never calls with null, and neither should |
| 1309 // other callers! |
1285 exceptionState.throwTypeError("The node provided is null."); | 1310 exceptionState.throwTypeError("The node provided is null."); |
1286 return; | 1311 return; |
1287 } | 1312 } |
1288 | 1313 |
1289 // InvalidStateError: Raised if the Range partially selects a non-Text node. | 1314 // InvalidStateError: Raised if the Range partially selects a non-Text node. |
1290 Node* startNonTextContainer = m_start.container(); | 1315 Node* startNonTextContainer = m_start.container(); |
1291 if (startNonTextContainer->getNodeType() == Node::kTextNode) | 1316 if (startNonTextContainer->getNodeType() == Node::kTextNode) |
1292 startNonTextContainer = startNonTextContainer->parentNode(); | 1317 startNonTextContainer = startNonTextContainer->parentNode(); |
1293 Node* endNonTextContainer = m_end.container(); | 1318 Node* endNonTextContainer = m_end.container(); |
1294 if (endNonTextContainer->getNodeType() == Node::kTextNode) | 1319 if (endNonTextContainer->getNodeType() == Node::kTextNode) |
1295 endNonTextContainer = endNonTextContainer->parentNode(); | 1320 endNonTextContainer = endNonTextContainer->parentNode(); |
1296 if (startNonTextContainer != endNonTextContainer) { | 1321 if (startNonTextContainer != endNonTextContainer) { |
1297 exceptionState.throwDOMException( | 1322 exceptionState.throwDOMException( |
1298 InvalidStateError, "The Range has partially selected a non-Text node."); | 1323 InvalidStateError, "The Range has partially selected a non-Text node."); |
1299 return; | 1324 return; |
1300 } | 1325 } |
1301 | 1326 |
1302 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, Nota
tion, | 1327 // InvalidNodeTypeError: Raised if node is an Attr, Entity, DocumentType, |
| 1328 // Notation, |
1303 // Document, or DocumentFragment node. | 1329 // Document, or DocumentFragment node. |
1304 switch (newParent->getNodeType()) { | 1330 switch (newParent->getNodeType()) { |
1305 case Node::kAttributeNode: | 1331 case Node::kAttributeNode: |
1306 case Node::kDocumentFragmentNode: | 1332 case Node::kDocumentFragmentNode: |
1307 case Node::kDocumentNode: | 1333 case Node::kDocumentNode: |
1308 case Node::kDocumentTypeNode: | 1334 case Node::kDocumentTypeNode: |
1309 exceptionState.throwDOMException( | 1335 exceptionState.throwDOMException( |
1310 InvalidNodeTypeError, | 1336 InvalidNodeTypeError, |
1311 "The node provided is of type '" + newParent->nodeName() + "'."); | 1337 "The node provided is of type '" + newParent->nodeName() + "'."); |
1312 return; | 1338 return; |
1313 case Node::kCdataSectionNode: | 1339 case Node::kCdataSectionNode: |
1314 case Node::kCommentNode: | 1340 case Node::kCommentNode: |
1315 case Node::kElementNode: | 1341 case Node::kElementNode: |
1316 case Node::kProcessingInstructionNode: | 1342 case Node::kProcessingInstructionNode: |
1317 case Node::kTextNode: | 1343 case Node::kTextNode: |
1318 break; | 1344 break; |
1319 } | 1345 } |
1320 | 1346 |
1321 // Raise a HierarchyRequestError if m_start.container() doesn't accept childre
n like newParent. | 1347 // Raise a HierarchyRequestError if m_start.container() doesn't accept |
| 1348 // children like newParent. |
1322 Node* parentOfNewParent = m_start.container(); | 1349 Node* parentOfNewParent = m_start.container(); |
1323 | 1350 |
1324 // If m_start.container() is a character data node, it will be split and it wi
ll be its parent that will | 1351 // If m_start.container() is a character data node, it will be split and it |
1325 // need to accept newParent (or in the case of a comment, it logically "would"
be inserted into the parent, | 1352 // will be its parent that will need to accept newParent (or in the case of a |
1326 // although this will fail below for another reason). | 1353 // comment, it logically "would" be inserted into the parent, although this |
| 1354 // will fail below for another reason). |
1327 if (parentOfNewParent->isCharacterDataNode()) | 1355 if (parentOfNewParent->isCharacterDataNode()) |
1328 parentOfNewParent = parentOfNewParent->parentNode(); | 1356 parentOfNewParent = parentOfNewParent->parentNode(); |
1329 | 1357 |
1330 if (!parentOfNewParent) { | 1358 if (!parentOfNewParent) { |
1331 exceptionState.throwDOMException(HierarchyRequestError, | 1359 exceptionState.throwDOMException(HierarchyRequestError, |
1332 "The container node is a detached " | 1360 "The container node is a detached " |
1333 "character data node; no parent node is " | 1361 "character data node; no parent node is " |
1334 "available for insertion."); | 1362 "available for insertion."); |
1335 return; | 1363 return; |
1336 } | 1364 } |
1337 | 1365 |
1338 if (!parentOfNewParent->childTypeAllowed(newParent->getNodeType())) { | 1366 if (!parentOfNewParent->childTypeAllowed(newParent->getNodeType())) { |
1339 exceptionState.throwDOMException(HierarchyRequestError, | 1367 exceptionState.throwDOMException(HierarchyRequestError, |
1340 "The node provided is of type '" + | 1368 "The node provided is of type '" + |
1341 newParent->nodeName() + | 1369 newParent->nodeName() + |
1342 "', which may not be inserted here."); | 1370 "', which may not be inserted here."); |
1343 return; | 1371 return; |
1344 } | 1372 } |
1345 | 1373 |
1346 if (newParent->isShadowIncludingInclusiveAncestorOf(m_start.container())) { | 1374 if (newParent->isShadowIncludingInclusiveAncestorOf(m_start.container())) { |
1347 exceptionState.throwDOMException(HierarchyRequestError, | 1375 exceptionState.throwDOMException(HierarchyRequestError, |
1348 "The node provided contains the insertion " | 1376 "The node provided contains the insertion " |
1349 "point; it may not be inserted into " | 1377 "point; it may not be inserted into " |
1350 "itself."); | 1378 "itself."); |
1351 return; | 1379 return; |
1352 } | 1380 } |
1353 | 1381 |
1354 // FIXME: Do we need a check if the node would end up with a child node of a t
ype not | 1382 // FIXME: Do we need a check if the node would end up with a child node of a |
1355 // allowed by the type of node? | 1383 // type not allowed by the type of node? |
1356 | 1384 |
1357 while (Node* n = newParent->firstChild()) { | 1385 while (Node* n = newParent->firstChild()) { |
1358 toContainerNode(newParent)->removeChild(n, exceptionState); | 1386 toContainerNode(newParent)->removeChild(n, exceptionState); |
1359 if (exceptionState.hadException()) | 1387 if (exceptionState.hadException()) |
1360 return; | 1388 return; |
1361 } | 1389 } |
1362 DocumentFragment* fragment = extractContents(exceptionState); | 1390 DocumentFragment* fragment = extractContents(exceptionState); |
1363 if (exceptionState.hadException()) | 1391 if (exceptionState.hadException()) |
1364 return; | 1392 return; |
1365 insertNode(newParent, exceptionState); | 1393 insertNode(newParent, exceptionState); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1743 .data() | 1771 .data() |
1744 << "start offset: " << range->startOffset() | 1772 << "start offset: " << range->startOffset() |
1745 << ", end offset: " << range->endOffset(); | 1773 << ", end offset: " << range->endOffset(); |
1746 } else { | 1774 } else { |
1747 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " | 1775 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " |
1748 "invalid."; | 1776 "invalid."; |
1749 } | 1777 } |
1750 } | 1778 } |
1751 | 1779 |
1752 #endif | 1780 #endif |
OLD | NEW |