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

Side by Side Diff: third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp

Issue 2692093003: Rewrite DocumentMarkerController to use SynchronousMutationObserver (Closed)
Patch Set: Rebase on separate CL to add SetCharacterDataCommand Created 3 years, 10 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 * 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 "core/editing/commands/CompositeEditCommand.h" 26 #include "core/editing/commands/CompositeEditCommand.h"
27 27
28 #include <algorithm>
Xiaocheng 2017/02/22 01:49:23 No need to change include order.
rlanday 2017/02/22 02:01:10 git cl format did this, the linter will probably c
28 #include "bindings/core/v8/ExceptionState.h" 29 #include "bindings/core/v8/ExceptionState.h"
29 #include "core/HTMLNames.h" 30 #include "core/HTMLNames.h"
30 #include "core/dom/Document.h" 31 #include "core/dom/Document.h"
31 #include "core/dom/DocumentFragment.h" 32 #include "core/dom/DocumentFragment.h"
32 #include "core/dom/ElementTraversal.h" 33 #include "core/dom/ElementTraversal.h"
33 #include "core/dom/NodeTraversal.h" 34 #include "core/dom/NodeTraversal.h"
34 #include "core/dom/Range.h" 35 #include "core/dom/Range.h"
35 #include "core/dom/Text.h" 36 #include "core/dom/Text.h"
36 #include "core/editing/EditingUtilities.h" 37 #include "core/editing/EditingUtilities.h"
37 #include "core/editing/Editor.h" 38 #include "core/editing/Editor.h"
38 #include "core/editing/PlainTextRange.h" 39 #include "core/editing/PlainTextRange.h"
39 #include "core/editing/RelocatablePosition.h" 40 #include "core/editing/RelocatablePosition.h"
40 #include "core/editing/VisibleUnits.h" 41 #include "core/editing/VisibleUnits.h"
41 #include "core/editing/commands/AppendNodeCommand.h" 42 #include "core/editing/commands/AppendNodeCommand.h"
42 #include "core/editing/commands/ApplyStyleCommand.h" 43 #include "core/editing/commands/ApplyStyleCommand.h"
43 #include "core/editing/commands/DeleteFromTextNodeCommand.h" 44 #include "core/editing/commands/DeleteFromTextNodeCommand.h"
44 #include "core/editing/commands/DeleteSelectionCommand.h" 45 #include "core/editing/commands/DeleteSelectionCommand.h"
45 #include "core/editing/commands/InsertIntoTextNodeCommand.h" 46 #include "core/editing/commands/InsertIntoTextNodeCommand.h"
46 #include "core/editing/commands/InsertLineBreakCommand.h" 47 #include "core/editing/commands/InsertLineBreakCommand.h"
47 #include "core/editing/commands/InsertNodeBeforeCommand.h" 48 #include "core/editing/commands/InsertNodeBeforeCommand.h"
48 #include "core/editing/commands/InsertParagraphSeparatorCommand.h" 49 #include "core/editing/commands/InsertParagraphSeparatorCommand.h"
49 #include "core/editing/commands/MergeIdenticalElementsCommand.h" 50 #include "core/editing/commands/MergeIdenticalElementsCommand.h"
50 #include "core/editing/commands/RemoveCSSPropertyCommand.h" 51 #include "core/editing/commands/RemoveCSSPropertyCommand.h"
51 #include "core/editing/commands/RemoveNodeCommand.h" 52 #include "core/editing/commands/RemoveNodeCommand.h"
52 #include "core/editing/commands/RemoveNodePreservingChildrenCommand.h" 53 #include "core/editing/commands/RemoveNodePreservingChildrenCommand.h"
53 #include "core/editing/commands/ReplaceNodeWithSpanCommand.h" 54 #include "core/editing/commands/ReplaceNodeWithSpanCommand.h"
54 #include "core/editing/commands/ReplaceSelectionCommand.h" 55 #include "core/editing/commands/ReplaceSelectionCommand.h"
56 #include "core/editing/commands/SetCharacterDataCommand.h"
55 #include "core/editing/commands/SetNodeAttributeCommand.h" 57 #include "core/editing/commands/SetNodeAttributeCommand.h"
56 #include "core/editing/commands/SplitElementCommand.h" 58 #include "core/editing/commands/SplitElementCommand.h"
57 #include "core/editing/commands/SplitTextNodeCommand.h" 59 #include "core/editing/commands/SplitTextNodeCommand.h"
58 #include "core/editing/commands/SplitTextNodeContainingElementCommand.h" 60 #include "core/editing/commands/SplitTextNodeContainingElementCommand.h"
59 #include "core/editing/commands/WrapContentsInDummySpanCommand.h" 61 #include "core/editing/commands/WrapContentsInDummySpanCommand.h"
60 #include "core/editing/iterators/TextIterator.h" 62 #include "core/editing/iterators/TextIterator.h"
61 #include "core/editing/markers/DocumentMarkerController.h" 63 #include "core/editing/markers/DocumentMarkerController.h"
62 #include "core/editing/serializers/Serialization.h" 64 #include "core/editing/serializers/Serialization.h"
63 #include "core/editing/spellcheck/SpellChecker.h" 65 #include "core/editing/spellcheck/SpellChecker.h"
64 #include "core/events/ScopedEventQueue.h" 66 #include "core/events/ScopedEventQueue.h"
65 #include "core/frame/LocalFrame.h" 67 #include "core/frame/LocalFrame.h"
66 #include "core/html/HTMLBRElement.h" 68 #include "core/html/HTMLBRElement.h"
67 #include "core/html/HTMLDivElement.h" 69 #include "core/html/HTMLDivElement.h"
68 #include "core/html/HTMLElement.h" 70 #include "core/html/HTMLElement.h"
69 #include "core/html/HTMLLIElement.h" 71 #include "core/html/HTMLLIElement.h"
70 #include "core/html/HTMLQuoteElement.h" 72 #include "core/html/HTMLQuoteElement.h"
71 #include "core/html/HTMLSpanElement.h" 73 #include "core/html/HTMLSpanElement.h"
72 #include "core/layout/LayoutBlock.h" 74 #include "core/layout/LayoutBlock.h"
73 #include "core/layout/LayoutListItem.h" 75 #include "core/layout/LayoutListItem.h"
74 #include "core/layout/LayoutText.h" 76 #include "core/layout/LayoutText.h"
75 #include "core/layout/line/InlineTextBox.h" 77 #include "core/layout/line/InlineTextBox.h"
76 #include <algorithm>
77 78
78 namespace blink { 79 namespace blink {
79 80
80 using namespace HTMLNames; 81 using namespace HTMLNames;
81 82
82 CompositeEditCommand::CompositeEditCommand(Document& document) 83 CompositeEditCommand::CompositeEditCommand(Document& document)
83 : EditCommand(document) { 84 : EditCommand(document) {
84 setStartingSelection(document.frame() 85 setStartingSelection(document.frame()
85 ->selection() 86 ->selection()
86 .computeVisibleSelectionInDOMTreeDeprecated()); 87 .computeVisibleSelectionInDOMTreeDeprecated());
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 // DeleteFromTextNodeCommand is never aborted. 525 // DeleteFromTextNodeCommand is never aborted.
525 applyCommandToComposite( 526 applyCommandToComposite(
526 DeleteFromTextNodeCommand::create(node, offset, count), 527 DeleteFromTextNodeCommand::create(node, offset, count),
527 ASSERT_NO_EDITING_ABORT); 528 ASSERT_NO_EDITING_ABORT);
528 } 529 }
529 530
530 void CompositeEditCommand::replaceTextInNode(Text* node, 531 void CompositeEditCommand::replaceTextInNode(Text* node,
531 unsigned offset, 532 unsigned offset,
532 unsigned count, 533 unsigned count,
533 const String& replacementText) { 534 const String& replacementText) {
534 // DeleteFromTextNodeCommand and InsertIntoTextNodeCommand are never 535 // SetCharacterDataCommand is never aborted.
535 // aborted.
536 applyCommandToComposite( 536 applyCommandToComposite(
537 DeleteFromTextNodeCommand::create(node, offset, count), 537 SetCharacterDataCommand::create(node, offset, count, replacementText),
538 ASSERT_NO_EDITING_ABORT); 538 ASSERT_NO_EDITING_ABORT);
539 if (!replacementText.isEmpty())
540 applyCommandToComposite(
541 InsertIntoTextNodeCommand::create(node, offset, replacementText),
542 ASSERT_NO_EDITING_ABORT);
543 } 539 }
544 540
545 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) { 541 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) {
546 Position start = endingSelection().start(); 542 Position start = endingSelection().start();
547 Position end = endingSelection().end(); 543 Position end = endingSelection().end();
548 if (start.computeContainerNode() != end.computeContainerNode() || 544 if (start.computeContainerNode() != end.computeContainerNode() ||
549 !start.computeContainerNode()->isTextNode() || 545 !start.computeContainerNode()->isTextNode() ||
550 isTabHTMLSpanElementTextNode(start.computeContainerNode())) 546 isTabHTMLSpanElementTextNode(start.computeContainerNode()))
551 return Position(); 547 return Position();
552 548
553 Text* textNode = toText(start.computeContainerNode()); 549 Text* textNode = toText(start.computeContainerNode());
554 replaceTextInNode(textNode, start.offsetInContainerNode(), 550 replaceTextInNode(textNode, start.offsetInContainerNode(),
555 end.offsetInContainerNode() - start.offsetInContainerNode(), 551 end.offsetInContainerNode() - start.offsetInContainerNode(),
556 text); 552 text);
557 553
558 return Position(textNode, start.offsetInContainerNode() + text.length()); 554 return Position(textNode, start.offsetInContainerNode() + text.length());
559 } 555 }
560 556
561 static void copyMarkerTypesAndDescriptions(
562 const DocumentMarkerVector& markerPointers,
563 Vector<DocumentMarker::MarkerType>& types,
564 Vector<String>& descriptions) {
565 size_t arraySize = markerPointers.size();
566 types.reserveCapacity(arraySize);
567 descriptions.reserveCapacity(arraySize);
568 for (const auto& markerPointer : markerPointers) {
569 types.push_back(markerPointer->type());
570 descriptions.push_back(markerPointer->description());
571 }
572 }
573
574 void CompositeEditCommand::replaceTextInNodePreservingMarkers(
575 Text* node,
576 unsigned offset,
577 unsigned count,
578 const String& replacementText) {
579 DocumentMarkerController& markerController = document().markers();
580 Vector<DocumentMarker::MarkerType> types;
581 Vector<String> descriptions;
582 copyMarkerTypesAndDescriptions(
583 markerController.markersInRange(
584 EphemeralRange(Position(node, offset),
585 Position(node, offset + count)),
586 DocumentMarker::AllMarkers()),
587 types, descriptions);
588
589 replaceTextInNode(node, offset, count, replacementText);
590
591 // Re-adding markers requires a clean tree.
592 document().updateStyleAndLayout();
593
594 DocumentLifecycle::DisallowTransitionScope disallowTransition(
595 document().lifecycle());
596 Position startPosition(node, offset);
597 Position endPosition(node, offset + replacementText.length());
598 DCHECK_EQ(types.size(), descriptions.size());
599
600 for (size_t i = 0; i < types.size(); ++i)
601 markerController.addMarker(startPosition, endPosition, types[i],
602 descriptions[i]);
603 }
604
605 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) { 557 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) {
606 if (!isTabHTMLSpanElementTextNode(pos.anchorNode())) 558 if (!isTabHTMLSpanElementTextNode(pos.anchorNode()))
607 return pos; 559 return pos;
608 560
609 switch (pos.anchorType()) { 561 switch (pos.anchorType()) {
610 case PositionAnchorType::BeforeChildren: 562 case PositionAnchorType::BeforeChildren:
611 case PositionAnchorType::AfterChildren: 563 case PositionAnchorType::AfterChildren:
612 NOTREACHED(); 564 NOTREACHED();
613 return pos; 565 return pos;
614 case PositionAnchorType::OffsetInAnchor: 566 case PositionAnchorType::OffsetInAnchor:
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 !isWhitespace(toText(textNode->nextSibling())->data()[0]); 719 !isWhitespace(toText(textNode->nextSibling())->data()[0]);
768 const bool shouldEmitNBSPbeforeEnd = 720 const bool shouldEmitNBSPbeforeEnd =
769 (isEndOfParagraph(visibleDownstreamPos) || 721 (isEndOfParagraph(visibleDownstreamPos) ||
770 (unsigned)downstream == text.length()) && 722 (unsigned)downstream == text.length()) &&
771 !nextSiblingIsTextNode; 723 !nextSiblingIsTextNode;
772 String rebalancedString = stringWithRebalancedWhitespace( 724 String rebalancedString = stringWithRebalancedWhitespace(
773 string, isStartOfParagraph(visibleUpstreamPos) || !upstream, 725 string, isStartOfParagraph(visibleUpstreamPos) || !upstream,
774 shouldEmitNBSPbeforeEnd); 726 shouldEmitNBSPbeforeEnd);
775 727
776 if (string != rebalancedString) 728 if (string != rebalancedString)
777 replaceTextInNodePreservingMarkers(textNode, upstream, length, 729 replaceTextInNode(textNode, upstream, length, rebalancedString);
778 rebalancedString);
779 } 730 }
780 731
781 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit( 732 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(
782 Position& position) { 733 Position& position) {
783 if (!isRichlyEditablePosition(position)) 734 if (!isRichlyEditablePosition(position))
784 return; 735 return;
785 Node* node = position.anchorNode(); 736 Node* node = position.anchorNode();
786 if (!node || !node->isTextNode()) 737 if (!node || !node->isTextNode())
787 return; 738 return;
788 Text* textNode = toText(node); 739 Text* textNode = toText(node);
(...skipping 20 matching lines...) Expand all
809 } 760 }
810 761
811 void CompositeEditCommand:: 762 void CompositeEditCommand::
812 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded( 763 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(
813 const VisiblePosition& visiblePosition) { 764 const VisiblePosition& visiblePosition) {
814 if (!isCollapsibleWhitespace(characterAfter(visiblePosition))) 765 if (!isCollapsibleWhitespace(characterAfter(visiblePosition)))
815 return; 766 return;
816 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent()); 767 Position pos = mostForwardCaretPosition(visiblePosition.deepEquivalent());
817 if (!pos.computeContainerNode() || !pos.computeContainerNode()->isTextNode()) 768 if (!pos.computeContainerNode() || !pos.computeContainerNode()->isTextNode())
818 return; 769 return;
819 replaceTextInNodePreservingMarkers(toText(pos.computeContainerNode()), 770 replaceTextInNode(toText(pos.computeContainerNode()),
820 pos.offsetInContainerNode(), 1, 771 pos.offsetInContainerNode(), 1, nonBreakingSpaceString());
821 nonBreakingSpaceString());
822 } 772 }
823 773
824 void CompositeEditCommand::rebalanceWhitespace() { 774 void CompositeEditCommand::rebalanceWhitespace() {
825 VisibleSelection selection = endingSelection(); 775 VisibleSelection selection = endingSelection();
826 if (selection.isNone()) 776 if (selection.isNone())
827 return; 777 return;
828 778
829 rebalanceWhitespaceAt(selection.start()); 779 rebalanceWhitespaceAt(selection.start());
830 if (selection.isRange()) 780 if (selection.isRange())
831 rebalanceWhitespaceAt(selection.end()); 781 rebalanceWhitespaceAt(selection.end());
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 1922
1973 DEFINE_TRACE(CompositeEditCommand) { 1923 DEFINE_TRACE(CompositeEditCommand) {
1974 visitor->trace(m_commands); 1924 visitor->trace(m_commands);
1975 visitor->trace(m_startingSelection); 1925 visitor->trace(m_startingSelection);
1976 visitor->trace(m_endingSelection); 1926 visitor->trace(m_endingSelection);
1977 visitor->trace(m_undoStep); 1927 visitor->trace(m_undoStep);
1978 EditCommand::trace(visitor); 1928 EditCommand::trace(visitor);
1979 } 1929 }
1980 1930
1981 } // namespace blink 1931 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698