Stop using live ranges in functions that return range of the selection
https://bugs.webkit.org/show_bug.cgi?id=210396
Reviewed by Sam Weinig.
Source/WebCore:
- Added makeRangeSelectingNode, to create a range that selects a node
and all its descendants.
- Improved intersectingNodes so it can now easily be used in a while loop
style as well as the range-for loop style. Also made it more robust
against tree changes while iterating; it will now always stop at the
end of the document.
- Changed functions that work with selection to get a SimpleRange, and
then either do all the work without a live range, or call createLiveRange
right where it's needed, making it clearer when we can delete that
call later as we cut down live ranges even more.
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::selectionRange const): Return a SimpleRange
instead of a live range.
(WebCore::AccessibilityObject::findTextRanges const): Use createLiveRange
on the result of selectionRange since this still mostly uses live ranges.
* accessibility/AccessibilityObject.h: Updated for the above.
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::documentBasedSelectedTextRange const):
Updated to create a live range only in the one place we need to call a
Range class member function.
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper textMarkerRangeForSelection]):
Use createLiveRange here.
* dom/SimpleRange.cpp:
(WebCore::makeRangeSelectingNode): Added. For use when we need to make
a range that selects a node, not just the node's contents.
(WebCore::firstIntersectingNode): Renamed from IntersectingNodeRange::first
since this is now used in the iterator class, not the range class. Also
letting it be a non-member function so we can tweak it without touching
the haeder file.
(WebCore::nodePastLastIntersectingNode): Ditto.
(WebCore::IntersectingNodeIterator::IntersectingNodeIterator): Changed
this constructor to take a SimpleRange. To add the advanceSkippingChildren
feature, had to build the termination condition into the iterator rather
than basing it on the value of the sentinel.
(WebCore::IntersectingNodeIterator::advance): Added. Contains the logic
from the ++ operator, so it can be called in a more straightforward way
when this is being used with a while loop rather than a range-for loop.
(WebCore::IntersectingNodeIterator::advanceSkippingChildren): Added.
* dom/SimpleRange.h: Updated for the changes to IntersectingNodeIterator
and IntersectingNodeRange.
* editing/AlternativeTextController.cpp:
(WebCore::AlternativeTextController::timerFired): Use createLiveRange.
* editing/CompositeEditCommand.cpp:
(WebCore::CompositeEditCommand::targetRanges const): Use WTFMove in
a place where the old code was copying instead.
* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss):
Use intersectingNodes to make the function's logic easier to understand.
* editing/Editing.cpp:
(WebCore::visibleImageElementsInRangeWithNonLoadedImages): Changed
the argument type to SimpleRange.
* editing/Editing.h: Updated for the change above.
* editing/EditingStyle.cpp:
(WebCore::EditingStyle::styleAtSelectionStart): Use createLiveRange.
* editing/Editor.cpp:
(WebCore::Editor::selectedRange): Use createLiveRange.
(WebCore::Editor::applyStyleToSelection): Ditto.
(WebCore::Editor::applyParagraphStyleToSelection): Ditto.
(WebCore::Editor::insertTextWithoutSendingTextEvent): Ditto.
(WebCore::Editor::insertLineBreak): Ditto.
(WebCore::Editor::insertParagraphSeparator): Ditto.
(WebCore::Editor::ignoreSpelling): Remove use of live range.
(WebCore::Editor::learnSpelling): Ditto.
(WebCore::Editor::misspelledWordAtCaretOrRange const): Ditto.
(WebCore::Editor::isSelectionUngrammatical): Ditto.
(WebCore::Editor::guessesForMisspelledOrUngrammatical): Ditto.
(WebCore::Editor::markMisspellingsAfterTypingToWord): Use createLiveRange.
(WebCore::Editor::markMisspellingsOrBadGrammar): Ditto.
(WebCore::Editor::markMisspellingsAndBadGrammar): Ditto.
(WebCore::Editor::rangeForPoint): Ditto.
(WebCore::Editor::insertTextPlaceholder): Ditto.
(WebCore::Editor::shouldChangeSelection const): Ditto.
(WebCore::Editor::findString): Ditto.
(WebCore::Editor::rangeOfString): Ditto.
(WebCore::Editor::scanSelectionForTelephoneNumbers): Ditto.
(WebCore::Editor::editorUIUpdateTimerFired): Remove use of live range.
(WebCore::candidateRangeForSelection): Deleted.
(WebCore::Editor::stringForCandidateRequest const): Use createLiveRange
and merged in the logic from candidateRangeForSelection.
(WebCore::Editor::fontForSelection const): Remove use of live range.
* editing/EditorCommand.cpp:
(WebCore::expandSelectionToGranularity): Use createLiveRange.
(WebCore::executeDeleteToMark): Ditto.
(WebCore::executeSelectToMark): Ditto.
(WebCore::valueFormatBlock): Ditto.
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::respondToNodeModification): Use createLiveRange.
(WebCore::FrameSelection::shouldDeleteSelection const): Ditto.
(WebCore::FrameSelection::getClippedVisibleTextRectangles const): Do the work
without a live range.
(WebCore::FrameSelection::expandSelectionToElementContainingCaretSelection): Ditto.
(WebCore::FrameSelection::elementRangeContainingCaretSelection const): Changed
to return a SimpleRange rather than a live range. Also removed redundant checks
and renamed locals to streamline the function.
(WebCore::FrameSelection::wordRangeContainingCaretSelection): Return a
SimpleRange instead of a live range.
(WebCore::FrameSelection::rangeByMovingCurrentSelection const): Ditto.
(WebCore::FrameSelection::rangeByExtendingCurrentSelection const): Ditto.
(WebCore::FrameSelection::rangeByAlteringCurrentSelection const): Ditto.
* editing/FrameSelection.h: Removed the toNormalizedRange function, since the
VisibleSelection class has a comment claiming most callers should not call it.
Updated forthe other changes above.
* editing/InsertListCommand.cpp:
(WebCore::InsertListCommand::doApply): Use createLiveRange.
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplacementFragment::ReplacementFragment): Ditto.
* editing/TextCheckingHelper.cpp:
(WebCore::TextCheckingHelper::TextCheckingHelper): Remove use of live range,
changing the type of m_range to SimpleRange.
(WebCore::TextCheckingHelper::findFirstMisspellingOrBadGrammar): Reduce use
of live range.
(WebCore::TextCheckingHelper::findFirstGrammarDetail const): Use createLiveRange.
(WebCore::TextCheckingHelper::findFirstBadGrammar const): Ditto.
(WebCore::TextCheckingHelper::isUngrammatical const): Remove use of live range.
(WebCore::TextCheckingHelper::guessesForMisspelledOrUngrammaticalRange const):
Use createLiveRange.
(WebCore::TextCheckingHelper::unifiedTextCheckerEnabled const): Updated for
different interface to get the document for a SimpleRange.
* editing/TextCheckingHelper.h: Change constructor to take a SimpleRange.
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::deleteKeyPressed): Use createLiveRange.
(WebCore::TypingCommand::forwardDeleteKeyPressed): Ditto.
* editing/VisibleSelection.cpp:
(WebCore::VisibleSelection::firstRange const): Return a SimpleRange.
(WebCore::VisibleSelection::toNormalizedRange const): Ditto.
* editing/VisibleSelection.h: Updated for the above.
* editing/cocoa/DictionaryLookup.mm: Removed an uneeded check of the
selection range against null. Code already guards against null endpoints.
* editing/cocoa/EditorCocoa.mm:
(WebCore::selectionAsAttributedString): Added. Uses the attributedString
function with it's new argument and return value types. There's no longer
a special function for the selection in the HTMLConverter header, so we
put it here instead.
(WebCore::Editor::writeSelectionToPasteboard): Updated to use the function
above and to deal with RetainPtr.
(WebCore::Editor::writeSelection): Ditto.
* editing/cocoa/HTMLConverter.h: Removed attributedStringFromSelection and
attributedStringBetweenStartAndEnd. Renamed attributedStringFromRange to
just attributedString and renamed editingAttributedStringFromRange to
just editingAttributedString. Also renamed IncludeImagesInAttributedString
to just IncludeImages.
* editing/cocoa/HTMLConverter.mm:
(HTMLConverter::HTMLConverter): Use a SimpleRange rther than two Position
arguments to the constructor.
(HTMLConverter::convert): Use RetainPtr for the return value and the
optional out argument.
(WebCore::attributedStringFromSelection): Deleted.
(WebCore::attributedStringBetweenStartAndEnd): Deleted.
(WebCore::attributedString): Renamed the version that takes a range and
made it take a SimpleRange, not a live range.
(WebCore::editingAttributedString): Ditto.
* editing/mac/EditorMac.mm:
(WebCore::Editor::dataSelectionForPasteboard): Updated for changes to
attributedString.
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent const):
Changed to not use live ranges any more.
* page/ContextMenuController.cpp:
(WebCore::ContextMenuController::contextMenuItemSelected):
Use createLiveRange.
* page/DOMSelection.cpp:
(WebCore::DOMSelection::getRangeAt): Use createLiveRange.
(WebCore::DOMSelection::addRange): Use Ditto.
(WebCore::DOMSelection::deleteFromDocument): Ditto.
* page/DragController.cpp:
(WebCore::setSelectionToDragCaret): Removed in/out argument that was
used to update a range that was never looked at afterward.
(WebCore::DragController::concludeEditDrag): Use createLiveRange.
(WebCore::DragController::draggableElement const): Ditto.
(WebCore::DragController::startDrag): Ditto.
* page/EventHandler.cpp:
(WebCore::EventHandler::dispatchMouseEvent): Use createLiveRange.
(WebCore::EventHandler::sendContextMenuEventForKey): Ditto.
(WebCore::EventHandler::didStartDrag): Remove use of live range.
* page/Page.cpp:
(WebCore::Page::findStringMatchingRanges): Use createLiveRange.
* page/TextIndicator.cpp:
(WebCore::TextIndicator::createWithRange): Ditto.
(WebCore::TextIndicator::createWithSelectionInFrame): Ditto.
* page/mac/ServicesOverlayController.mm:
(WebCore::ServicesOverlayController::buildSelectionHighlight):
Use createLiveRange.
(WebCore::ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight):
Use createLiveRange.
* rendering/HitTestResult.cpp:
(WebCore::HitTestResult::selectedText const): Remove use of
live range.
Source/WebKit:
* WebProcess/WebCoreSupport/gtk/WebEditorClientGtk.cpp:
(WebKit::WebEditorClient::updateGlobalSelection): Remove use of live range.
* WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
(WebKit::WebPage::dictionaryPopupInfoForRange): Updated for changes
to attributedString functions.
(WebKit::WebPage::getContentsAsAttributedString): Ditto.
* WebProcess/WebPage/FindController.cpp:
(WebKit::FindController::updateFindUIAfterPageScroll): Use createLiveRange.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::getSelectedRangeAsync): Ditto.
(WebKit::WebPage::currentSelectionAsRange): Ditto.
* WebProcess/WebPage/WebPage.h: Change m_rangeForDropSnapshot
to use a SimpleRange instead of a live range.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::plainTextForContext): Overloaded for SimpleRange and
Optional<SimpleRange> as needed by code below.
(WebKit::plainTextForDisplay): Ditto.
(WebKit::WebPage::getPlatformEditorState const): Use createLiveRange.
(WebKit::WebPage::getSelectionContext): Remove use of live range.
(WebKit::WebPage::didConcludeDrop): Ditto.
(WebKit::WebPage::didConcludeEditDrag): Use createLiveRange.
(WebKit::WebPage::computeAndSendEditDragSnapshot): Ditto.
(WebKit::WebPage::startAutoscrollAtPosition): Remove use of
live range.
(WebKit::WebPage::requestEvasionRectsAboveSelection): Use
createLiveRange.
(WebKit::WebPage::requestDictationContext): Remove use of live range.
(WebKit::WebPage::replaceSelectedText): Use createLiveRange.
(WebKit::WebPage::applyAutocorrectionInternal): Ditto.
(WebKit::WebPage::autocorrectionContext): Remove use of live range.
(WebKit::WebPage::requestDocumentEditingContext): Use createLiveRange.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::getPlatformEditorState const): Remove use of
live range.
(WebKit::WebPage::attributedSubstringForCharacterRangeAsync):
Updated for change to HTMLConverter functions.
(WebKit::WebPage::handleSelectionServiceClick): Ditto.
(WebKit::WebPage::performImmediateActionHitTestAtLocation):
Remove use of live range.
Source/WebKitLegacy/ios:
* WebCoreSupport/WebFrameIOS.mm:
(-[WebFrame selectionRectsForCoreRange:]): Changed argument type to
not require a live range. Internally, use createLiveRange and also
use a range-for loop.
(-[WebFrame selectionRectsForRange:]): Remove use of live range.
(-[WebFrame selectionRects]): Ditto.
Source/WebKitLegacy/mac:
* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::handleRequestedCandidates): Remove use of live range.
* WebCoreSupport/WebSelectionServiceController.mm:
(WebSelectionServiceController::handleSelectionServiceClick): Ditto.
* WebView/WebFrame.mm:
(-[WebFrame _rangeByAlteringCurrentSelection:direction:granularity:]):
Use createLiveRange.
(-[WebFrame _convertToNSRange:]): Changed to take SimpleRange.
(-[WebFrame _convertDOMRangeToNSRange:]): Updated for the above.
(-[WebFrame _markDOMRange]): Use createLiveRange.
(-[WebFrame _selectionRangeForFirstPoint:secondPoint:]): Ditto.
(-[WebFrame _selectionRangeForPoint:]): Ditto.
(-[WebFrame _selectedNSRange]): Remove use of live range.
(-[WebFrame selectedDOMRange]): Use crateLiveRange.
(-[WebFrame elementRangeContainingCaretSelection]): Ditto.
(-[WebFrame expandSelectionToWordContainingCaretSelection]): Tweaked
coding style a little.
(-[WebFrame expandSelectionToStartOfWordContainingCaretSelection]): Ditto.
(-[WebFrame wordRangeContainingCaretSelection]): Use createLiveRange.
(-[WebFrame rangeByMovingCurrentSelection:]): Ditto.
(-[WebFrame rangeByExtendingCurrentSelection:]): Ditto.
(-[WebFrame _replaceSelectionWithText:selectReplacement:smartReplace:matchStyle:]):
Use createLiveRange.
(-[WebFrame _replaceSelectionWithText:selectReplacement:smartReplace:]): Ditto.
(-[WebFrame _documentFragmentForText:]): Ditto.
* WebView/WebFrameInternal.h: Updated for changes above.
* WebView/WebHTMLRepresentation.mm:
(-[WebHTMLRepresentation attributedStringFrom:startOffset:to:endOffset:]):
Remove use of live range.
* WebView/WebHTMLView.mm:
(-[WebHTMLView _selectedRange]): Use createLiveRange.
(-[WebHTMLView _lookUpInDictionaryFromMenu:]): Remove use of live range.
(-[WebHTMLView markedRange]): Updated for change to _convertToNSRange.
(-[WebHTMLView attributedSubstringFromRange:]): Ditto.
(-[WebHTMLView _attributedStringFromDOMRange:]): Updated for changes to
HTMLConverter.
(-[WebHTMLView _legacyAttributedStringFrom:offset:to:offset:]): Remove
use of live range.
(-[WebHTMLView attributedString]): Ditto.
(-[WebHTMLView selectedAttributedString]): Ditto.
* WebView/WebImmediateActionController.h: Updated method to take a
SimpleRange instead of a live range.
* WebView/WebImmediateActionController.mm:
(+[WebImmediateActionController _dictionaryPopupInfoForRange:inFrame:withLookupOptions:indicatorOptions:transition:]):
Remove use of live range.
* WebView/WebTextCompletionController.mm:
(-[WebTextCompletionController doCompletion]): Use createLiveRange.
* WebView/WebView.mm:
(-[WebView _didConcludeEditDrag]): Ditto.
Source/WebKitLegacy/win:
* WebView.cpp:
(WebView::prepareCandidateWindow): Updated since toNormalizedRange
returns a SimpleRange.
(WebView::onIMERequestCharPosition): Ditto.
(WebView::onIMERequestReconvertString): Ditto.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@260725 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/editing/DeleteSelectionCommand.cpp b/Source/WebCore/editing/DeleteSelectionCommand.cpp
index 68d1506..ca56f30 100644
--- a/Source/WebCore/editing/DeleteSelectionCommand.cpp
+++ b/Source/WebCore/editing/DeleteSelectionCommand.cpp
@@ -503,19 +503,23 @@
void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss()
{
- RefPtr<Range> range = m_selectionToDelete.toNormalizedRange();
- RefPtr<Node> node = range ? range->firstNode() : nullptr;
- while (node && node != range->pastLastNode()) {
- RefPtr<Node> nextNode = NodeTraversal::next(*node);
- if ((is<HTMLStyleElement>(*node) && !downcast<HTMLStyleElement>(*node).hasAttributeWithoutSynchronization(scopedAttr)) || is<HTMLLinkElement>(*node)) {
- nextNode = NodeTraversal::nextSkippingChildren(*node);
- RefPtr<ContainerNode> rootEditableElement = node->rootEditableElement();
- if (rootEditableElement) {
- removeNode(*node);
- appendNode(*node, *rootEditableElement);
+ auto range = m_selectionToDelete.toNormalizedRange();
+ if (!range)
+ return;
+ auto nodes = intersectingNodes(*range).begin();
+ while (nodes) {
+ auto node = makeRef(*nodes);
+ auto shouldMove = is<HTMLLinkElement>(node)
+ || (is<HTMLStyleElement>(node) && !downcast<HTMLStyleElement>(node.get()).hasAttributeWithoutSynchronization(scopedAttr));
+ if (!shouldMove)
+ nodes.advance();
+ else {
+ nodes.advanceSkippingChildren();
+ if (auto rootEditableElement = makeRefPtr(node->rootEditableElement())) {
+ removeNode(node.get());
+ appendNode(node.get(), *rootEditableElement);
}
}
- node = nextNode;
}
}