| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "core/editing/CompositeEditCommand.h" | 27 #include "core/editing/commands/CompositeEditCommand.h" |
| 28 | 28 |
| 29 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 29 #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
| 30 #include "core/HTMLNames.h" | 30 #include "core/HTMLNames.h" |
| 31 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
| 32 #include "core/dom/DocumentFragment.h" | 32 #include "core/dom/DocumentFragment.h" |
| 33 #include "core/dom/ElementTraversal.h" | 33 #include "core/dom/ElementTraversal.h" |
| 34 #include "core/dom/NodeTraversal.h" | 34 #include "core/dom/NodeTraversal.h" |
| 35 #include "core/dom/Range.h" | 35 #include "core/dom/Range.h" |
| 36 #include "core/dom/Text.h" | 36 #include "core/dom/Text.h" |
| 37 #include "core/editing/AppendNodeCommand.h" | |
| 38 #include "core/editing/ApplyStyleCommand.h" | |
| 39 #include "core/editing/DeleteFromTextNodeCommand.h" | |
| 40 #include "core/editing/DeleteSelectionCommand.h" | |
| 41 #include "core/editing/EditingUtilities.h" | 37 #include "core/editing/EditingUtilities.h" |
| 42 #include "core/editing/Editor.h" | 38 #include "core/editing/Editor.h" |
| 43 #include "core/editing/InsertIntoTextNodeCommand.h" | |
| 44 #include "core/editing/InsertLineBreakCommand.h" | |
| 45 #include "core/editing/InsertNodeBeforeCommand.h" | |
| 46 #include "core/editing/InsertParagraphSeparatorCommand.h" | |
| 47 #include "core/editing/MergeIdenticalElementsCommand.h" | |
| 48 #include "core/editing/PlainTextRange.h" | 39 #include "core/editing/PlainTextRange.h" |
| 49 #include "core/editing/RemoveCSSPropertyCommand.h" | |
| 50 #include "core/editing/RemoveNodeCommand.h" | |
| 51 #include "core/editing/RemoveNodePreservingChildrenCommand.h" | |
| 52 #include "core/editing/ReplaceNodeWithSpanCommand.h" | |
| 53 #include "core/editing/ReplaceSelectionCommand.h" | |
| 54 #include "core/editing/SetNodeAttributeCommand.h" | |
| 55 #include "core/editing/SplitElementCommand.h" | |
| 56 #include "core/editing/SplitTextNodeCommand.h" | |
| 57 #include "core/editing/SplitTextNodeContainingElementCommand.h" | |
| 58 #include "core/editing/VisibleUnits.h" | 40 #include "core/editing/VisibleUnits.h" |
| 59 #include "core/editing/WrapContentsInDummySpanCommand.h" | 41 #include "core/editing/commands/AppendNodeCommand.h" |
| 42 #include "core/editing/commands/ApplyStyleCommand.h" |
| 43 #include "core/editing/commands/DeleteFromTextNodeCommand.h" |
| 44 #include "core/editing/commands/DeleteSelectionCommand.h" |
| 45 #include "core/editing/commands/InsertIntoTextNodeCommand.h" |
| 46 #include "core/editing/commands/InsertLineBreakCommand.h" |
| 47 #include "core/editing/commands/InsertNodeBeforeCommand.h" |
| 48 #include "core/editing/commands/InsertParagraphSeparatorCommand.h" |
| 49 #include "core/editing/commands/MergeIdenticalElementsCommand.h" |
| 50 #include "core/editing/commands/RemoveCSSPropertyCommand.h" |
| 51 #include "core/editing/commands/RemoveNodeCommand.h" |
| 52 #include "core/editing/commands/RemoveNodePreservingChildrenCommand.h" |
| 53 #include "core/editing/commands/ReplaceNodeWithSpanCommand.h" |
| 54 #include "core/editing/commands/ReplaceSelectionCommand.h" |
| 55 #include "core/editing/commands/SetNodeAttributeCommand.h" |
| 56 #include "core/editing/commands/SplitElementCommand.h" |
| 57 #include "core/editing/commands/SplitTextNodeCommand.h" |
| 58 #include "core/editing/commands/SplitTextNodeContainingElementCommand.h" |
| 59 #include "core/editing/commands/WrapContentsInDummySpanCommand.h" |
| 60 #include "core/editing/iterators/TextIterator.h" | 60 #include "core/editing/iterators/TextIterator.h" |
| 61 #include "core/editing/markers/DocumentMarkerController.h" | 61 #include "core/editing/markers/DocumentMarkerController.h" |
| 62 #include "core/editing/serializers/Serialization.h" | 62 #include "core/editing/serializers/Serialization.h" |
| 63 #include "core/editing/spellcheck/SpellChecker.h" | 63 #include "core/editing/spellcheck/SpellChecker.h" |
| 64 #include "core/events/ScopedEventQueue.h" | 64 #include "core/events/ScopedEventQueue.h" |
| 65 #include "core/frame/LocalFrame.h" | 65 #include "core/frame/LocalFrame.h" |
| 66 #include "core/html/HTMLBRElement.h" | 66 #include "core/html/HTMLBRElement.h" |
| 67 #include "core/html/HTMLDivElement.h" | 67 #include "core/html/HTMLDivElement.h" |
| 68 #include "core/html/HTMLElement.h" | 68 #include "core/html/HTMLElement.h" |
| 69 #include "core/html/HTMLLIElement.h" | 69 #include "core/html/HTMLLIElement.h" |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 } | 313 } |
| 314 | 314 |
| 315 void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild) | 315 void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild) |
| 316 { | 316 { |
| 317 ASSERT(insertChild); | 317 ASSERT(insertChild); |
| 318 ASSERT(refChild); | 318 ASSERT(refChild); |
| 319 ASSERT(!isHTMLBodyElement(*refChild)); | 319 ASSERT(!isHTMLBodyElement(*refChild)); |
| 320 ContainerNode* parent = refChild->parentNode(); | 320 ContainerNode* parent = refChild->parentNode(); |
| 321 ASSERT(parent); | 321 ASSERT(parent); |
| 322 ASSERT(!parent->isShadowRoot()); | 322 ASSERT(!parent->isShadowRoot()); |
| 323 if (parent->lastChild() == refChild) | 323 if (parent->lastChild() == refChild) { |
| 324 appendNode(insertChild, parent); | 324 appendNode(insertChild, parent); |
| 325 else { | 325 } else { |
| 326 ASSERT(refChild->nextSibling()); | 326 ASSERT(refChild->nextSibling()); |
| 327 insertNodeBefore(insertChild, refChild->nextSibling()); | 327 insertNodeBefore(insertChild, refChild->nextSibling()); |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 | 330 |
| 331 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild
, const Position& editingPosition) | 331 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild
, const Position& editingPosition) |
| 332 { | 332 { |
| 333 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); | 333 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); |
| 334 // For editing positions like [table, 0], insert before the table, | 334 // For editing positions like [table, 0], insert before the table, |
| 335 // likewise for replaced elements, brs, etc. | 335 // likewise for replaced elements, brs, etc. |
| 336 Position p = editingPosition.parentAnchoredEquivalent(); | 336 Position p = editingPosition.parentAnchoredEquivalent(); |
| 337 Node* refChild = p.anchorNode(); | 337 Node* refChild = p.anchorNode(); |
| 338 int offset = p.offsetInContainerNode(); | 338 int offset = p.offsetInContainerNode(); |
| 339 | 339 |
| 340 if (canHaveChildrenForEditing(refChild)) { | 340 if (canHaveChildrenForEditing(refChild)) { |
| 341 Node* child = refChild->firstChild(); | 341 Node* child = refChild->firstChild(); |
| 342 for (int i = 0; child && i < offset; i++) | 342 for (int i = 0; child && i < offset; i++) |
| 343 child = child->nextSibling(); | 343 child = child->nextSibling(); |
| 344 if (child) | 344 if (child) |
| 345 insertNodeBefore(insertChild, child); | 345 insertNodeBefore(insertChild, child); |
| 346 else | 346 else |
| 347 appendNode(insertChild, toContainerNode(refChild)); | 347 appendNode(insertChild, toContainerNode(refChild)); |
| 348 } else if (caretMinOffset(refChild) >= offset) | 348 } else if (caretMinOffset(refChild) >= offset) { |
| 349 insertNodeBefore(insertChild, refChild); | 349 insertNodeBefore(insertChild, refChild); |
| 350 else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { | 350 } else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { |
| 351 splitTextNode(toText(refChild), offset); | 351 splitTextNode(toText(refChild), offset); |
| 352 | 352 |
| 353 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild | 353 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild |
| 354 if (!refChild->inDocument()) | 354 if (!refChild->inDocument()) |
| 355 return; | 355 return; |
| 356 insertNodeBefore(insertChild, refChild); | 356 insertNodeBefore(insertChild, refChild); |
| 357 } else | 357 } else { |
| 358 insertNodeAfter(insertChild, refChild); | 358 insertNodeAfter(insertChild, refChild); |
| 359 } |
| 359 } | 360 } |
| 360 | 361 |
| 361 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent) | 362 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent) |
| 362 { | 363 { |
| 363 // When cloneParagraphUnderNewElement() clones the fallback content | 364 // When cloneParagraphUnderNewElement() clones the fallback content |
| 364 // of an OBJECT element, the ASSERT below may fire since the return | 365 // of an OBJECT element, the ASSERT below may fire since the return |
| 365 // value of canHaveChildrenForEditing is not reliable until the layout | 366 // value of canHaveChildrenForEditing is not reliable until the layout |
| 366 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. | 367 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. |
| 367 ASSERT(canHaveChildrenForEditing(parent.get()) | 368 ASSERT(canHaveChildrenForEditing(parent.get()) |
| 368 || (parent->isElementNode() && toElement(parent.get())->tagQName() == ob
jectTag)); | 369 || (parent->isElementNode() && toElement(parent.get())->tagQName() == ob
jectTag)); |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 | 668 |
| 668 int length = downstream - upstream; | 669 int length = downstream - upstream; |
| 669 if (!length) | 670 if (!length) |
| 670 return; | 671 return; |
| 671 | 672 |
| 672 VisiblePosition visibleUpstreamPos(Position(textNode, upstream)); | 673 VisiblePosition visibleUpstreamPos(Position(textNode, upstream)); |
| 673 VisiblePosition visibleDownstreamPos(Position(textNode, downstream)); | 674 VisiblePosition visibleDownstreamPos(Position(textNode, downstream)); |
| 674 | 675 |
| 675 String string = text.substring(upstream, length); | 676 String string = text.substring(upstream, length); |
| 676 String rebalancedString = stringWithRebalancedWhitespace(string, | 677 String rebalancedString = stringWithRebalancedWhitespace(string, |
| 677 // FIXME: Because of the problem mentioned at the top of this function, we m
ust also use nbsps at the start/end of the string because | 678 // FIXME: Because of the problem mentioned at the top of this function, |
| 678 // this function doesn't get all surrounding whitespace, just the whitespace
in the current text node. | 679 // we must also use nbsps at the start/end of the string because this |
| 679 isStartOfParagraph(
visibleUpstreamPos) || upstream == 0, | 680 // function doesn't get all surrounding whitespace, just the whitespace |
| 680 isEndOfParagraph(vi
sibleDownstreamPos) || (unsigned)downstream == text.length()); | 681 // in the current text node. |
| 682 isStartOfParagraph(visibleUpstreamPos) || upstream == 0, |
| 683 isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.l
ength()); |
| 681 | 684 |
| 682 if (string != rebalancedString) | 685 if (string != rebalancedString) |
| 683 replaceTextInNodePreservingMarkers(textNode.release(), upstream, length,
rebalancedString); | 686 replaceTextInNodePreservingMarkers(textNode.release(), upstream, length,
rebalancedString); |
| 684 } | 687 } |
| 685 | 688 |
| 686 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio
n) | 689 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio
n) |
| 687 { | 690 { |
| 688 Node* node = position.anchorNode(); | 691 Node* node = position.anchorNode(); |
| 689 if (!node || !node->isTextNode()) | 692 if (!node || !node->isTextNode()) |
| 690 return; | 693 return; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 return; | 765 return; |
| 763 | 766 |
| 764 unsigned removed = 0; | 767 unsigned removed = 0; |
| 765 InlineTextBox* prevBox = nullptr; | 768 InlineTextBox* prevBox = nullptr; |
| 766 String str; | 769 String str; |
| 767 | 770 |
| 768 // This loop structure works to process all gaps preceding a box, | 771 // This loop structure works to process all gaps preceding a box, |
| 769 // and also will look at the gap after the last box. | 772 // and also will look at the gap after the last box. |
| 770 while (prevBox || box) { | 773 while (prevBox || box) { |
| 771 unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0; | 774 unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0; |
| 772 if (end < gapStart) | 775 if (end < gapStart) { |
| 773 // No more chance for any intersections | 776 // No more chance for any intersections |
| 774 break; | 777 break; |
| 778 } |
| 775 | 779 |
| 776 unsigned gapEnd = box ? box->start() : length; | 780 unsigned gapEnd = box ? box->start() : length; |
| 777 bool indicesIntersect = start <= gapEnd && end >= gapStart; | 781 bool indicesIntersect = start <= gapEnd && end >= gapStart; |
| 778 int gapLen = gapEnd - gapStart; | 782 int gapLen = gapEnd - gapStart; |
| 779 if (indicesIntersect && gapLen > 0) { | 783 if (indicesIntersect && gapLen > 0) { |
| 780 gapStart = std::max(gapStart, start); | 784 gapStart = std::max(gapStart, start); |
| 781 if (str.isNull()) | 785 if (str.isNull()) |
| 782 str = textNode->data().substring(start, end - start); | 786 str = textNode->data().substring(start, end - start); |
| 783 // remove text in the gap | 787 // remove text in the gap |
| 784 str.remove(gapStart - start - removed, gapLen); | 788 str.remove(gapStart - start - removed, gapLen); |
| 785 removed += gapLen; | 789 removed += gapLen; |
| 786 } | 790 } |
| 787 | 791 |
| 788 prevBox = box; | 792 prevBox = box; |
| 789 if (box) { | 793 if (box) { |
| 790 if (++sortedTextBoxesPosition < sortedTextBoxes.size()) | 794 if (++sortedTextBoxesPosition < sortedTextBoxes.size()) |
| 791 box = sortedTextBoxes[sortedTextBoxesPosition]; | 795 box = sortedTextBoxes[sortedTextBoxesPosition]; |
| 792 else | 796 else |
| 793 box = 0; | 797 box = 0; |
| 794 } | 798 } |
| 795 } | 799 } |
| 796 | 800 |
| 797 if (!str.isNull()) { | 801 if (!str.isNull()) { |
| 798 // Replace the text between start and end with our pruned version. | 802 // Replace the text between start and end with our pruned version. |
| 799 if (!str.isEmpty()) | 803 if (!str.isEmpty()) { |
| 800 replaceTextInNode(textNode, start, end - start, str); | 804 replaceTextInNode(textNode, start, end - start, str); |
| 801 else { | 805 } else { |
| 802 // Assert that we are not going to delete all of the text in the nod
e. | 806 // Assert that we are not going to delete all of the text in the nod
e. |
| 803 // If we were, that should have been done above with the call to | 807 // If we were, that should have been done above with the call to |
| 804 // removeNode and return. | 808 // removeNode and return. |
| 805 ASSERT(start > 0 || end - start < textNode->length()); | 809 ASSERT(start > 0 || end - start < textNode->length()); |
| 806 deleteTextFromNode(textNode, start, end - start); | 810 deleteTextFromNode(textNode, start, end - start); |
| 807 } | 811 } |
| 808 } | 812 } |
| 809 } | 813 } |
| 810 | 814 |
| 811 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) | 815 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 // div or an li), remove it during the move (the list removal code | 1100 // div or an li), remove it during the move (the list removal code |
| 1097 // expects this behavior). | 1101 // expects this behavior). |
| 1098 } else if (isBlock(node)) { | 1102 } else if (isBlock(node)) { |
| 1099 // If caret position after deletion and destination position coincid
es, | 1103 // If caret position after deletion and destination position coincid
es, |
| 1100 // node should not be removed. | 1104 // node should not be removed. |
| 1101 if (!rendersInDifferentPosition(position, destination.deepEquivalent
())) { | 1105 if (!rendersInDifferentPosition(position, destination.deepEquivalent
())) { |
| 1102 prune(node, destinationNode); | 1106 prune(node, destinationNode); |
| 1103 return; | 1107 return; |
| 1104 } | 1108 } |
| 1105 removeNodeAndPruneAncestors(node, destinationNode); | 1109 removeNodeAndPruneAncestors(node, destinationNode); |
| 1106 } | 1110 } else if (lineBreakExistsAtPosition(position)) { |
| 1107 else if (lineBreakExistsAtPosition(position)) { | |
| 1108 // There is a preserved '\n' at caretAfterDelete. | 1111 // There is a preserved '\n' at caretAfterDelete. |
| 1109 // We can safely assume this is a text node. | 1112 // We can safely assume this is a text node. |
| 1110 Text* textNode = toText(node); | 1113 Text* textNode = toText(node); |
| 1111 if (textNode->length() == 1) | 1114 if (textNode->length() == 1) |
| 1112 removeNodeAndPruneAncestors(node, destinationNode); | 1115 removeNodeAndPruneAncestors(node, destinationNode); |
| 1113 else | 1116 else |
| 1114 deleteTextFromNode(textNode, position.computeOffsetInContainerNo
de(), 1); | 1117 deleteTextFromNode(textNode, position.computeOffsetInContainerNo
de(), 1); |
| 1115 } | 1118 } |
| 1116 } | 1119 } |
| 1117 } | 1120 } |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 } | 1502 } |
| 1500 | 1503 |
| 1501 DEFINE_TRACE(CompositeEditCommand) | 1504 DEFINE_TRACE(CompositeEditCommand) |
| 1502 { | 1505 { |
| 1503 visitor->trace(m_commands); | 1506 visitor->trace(m_commands); |
| 1504 visitor->trace(m_composition); | 1507 visitor->trace(m_composition); |
| 1505 EditCommand::trace(visitor); | 1508 EditCommand::trace(visitor); |
| 1506 } | 1509 } |
| 1507 | 1510 |
| 1508 } // namespace blink | 1511 } // namespace blink |
| OLD | NEW |