Remove live ranges from Editor.h and EditorClient.h
https://bugs.webkit.org/show_bug.cgi?id=214261

Reviewed by Sam Weinig.

Source/WebCore:

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::misspellingRange const): Update since
rangeForTextCheckingResult no longer returns a live range.
(WebCore::AccessibilityObject::rangeOfStringClosestToRangeInDirection const):
Update since rangeOfString no longer returns a live range.

* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(accessibilityTextOperationForParameterizedAttribute): Use makeSimpleRange.

* dom/Document.cpp:
(WebCore::acceptsEditingFocus): Use makeRangeSelectingNodeContents
since shouldBeginEditing no longer takes a live range.

* dom/Range.h: Exxported makeSimpleRange for use outside WebCore.

* dom/SimpleRange.cpp:
(WebCore::makeSimpleRange): Added. Takes two optional boundary points and
returns an optional range.
* dom/SimpleRange.h: Added the above.

* editing/AlternativeTextController.cpp:
(WebCore::AlternativeTextController::timerFired): Removed calls to
crateLiveRange since markAllMisspellingsAndBadGrammarInRanges no
longer takes live ranges.
(WebCore::AlternativeTextController::applyDictationAlternative):
Updates since shouldInsertText no longer takes a live range.

* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::mergeParagraphs): Updated since
shouldMoveRangeAfterDelete no longer takes live ranges.

* editing/Editor.cpp:
(WebCore::Editor::canDeleteRange const): Updated to not take a
live range.
(WebCore::Editor::deleteWithDirection): Updated since
addRangeToKillRing no longer takes a live range.
(WebCore::Editor::pasteAsPlainTextWithPasteboard): Updated since
shouldInsertText no longer takes a live range.
(WebCore::Editor::shouldInsertFragment): No longer take a live range.
(WebCore::Editor::replaceSelectionWithText): Updated since
selectedRange no longer returns a live range.
(WebCore::Editor::selectedRange): Do not return a live range.
(WebCore::Editor::shouldDeleteRange const): Do not take a live range.
(WebCore::Editor::shouldInsertText const): Ditto.
(WebCore::Editor::shouldApplyStyle): Ditto. Also take a const& to
the style instead of a non-const*.
(WebCore::Editor::applyStyleToSelection): Pass a style reference
and a non-live range.
(WebCore::Editor::applyParagraphStyleToSelection): Updated for
the change above.
(WebCore::Editor::insertTextWithoutSendingTextEvent): No need to
pass a live range any more.
(WebCore::Editor::insertLineBreak): Ditto.
(WebCore::Editor::insertParagraphSeparator): Ditto.
(WebCore::Editor::performCutOrCopy): Updated to not use live range.
(WebCore::Editor::performDelete): Ditto.
(WebCore::Editor::shouldEndEditing): Do not take a live range.
(WebCore::Editor::shouldBeginEditing): Ditto.
(WebCore::Editor::willWriteSelectionToPasteboard): Ditto.
(WebCore::Editor::selectComposition): Update since compositionRange
is not a live range.
(WebCore::Editor::markMisspellingsAfterTypingToWord): Update since
we don't need to pass live ranges to markAllMisspellingsAndBadGrammarInRanges.
(WebCore::Editor::markMisspellingsOrBadGrammar): Don't return a
live range in tthe out argument.
(WebCore::Editor::markMisspellings): Ditto.
(WebCore::Editor::markBadGrammar): Update for the above.
(WebCore::Editor::markAllMisspellingsAndBadGrammarInRanges): Do not
take live ranges for the arguments.
(WebCore::Editor::replaceRangeForSpellChecking): Do not take a live range.
(WebCore::Editor::markAndReplaceFor): Update since shouldInsertText does
not take a live range any more.
(WebCore::Editor::changeBackToReplacedString): Update to not use live
ranges as much.
(WebCore::Editor::markMisspellingsAndBadGrammar): Updae since
we don't need to pass live ranges to markAllMisspellingsAndBadGrammarInRanges.
(WebCore::Editor::rangeForPoint): Don't return a live range.
(WebCore::Editor::compositionRange const): Ditto.
(WebCore::Editor::transpose): Updated since we don't pass a live range.
(WebCore::Editor::firstRectForRange const): Don't take a live range.
(WebCore::Editor::shouldChangeSelection const): Updated since we don't
need to pass a live range.
(WebCore::Editor::findString): Ditto.
(WebCore::start): Added. Helper to make rangeOfString easier to read.
(WebCore::end): Ditto.
(WebCore::makeBoundaryPointAfterNodeContents): Ditto.
(WebCore::makeBoundaryPointAfterNode): Ditto.
(WebCore::collapseIfRootsDiffer): Ditto.
(WebCore::Editor::rangeOfString): Updated to not take or return a
live range and not use it internally either.
(WebCore::isFrameInRange): Don't take a live range.
(WebCore::Editor::countMatchesForText): Don't take or return live ranges.
(WebCore::Editor::contextRangeForCandidateRequest const): Don't return
a live range.
(WebCore::Editor::rangeForTextCheckingResult const): Ditto.
(WebCore::Editor::handleAcceptedCandidate): Update for the above.
(WebCore::Editor::adjustedSelectionRange): Don't return a live range.

* editing/Editor.h: Updated for all the chagnes above.

* editing/EditorCommand.cpp:
(WebCore::expandSelectionToGranularity): Updated to reduce the use of
live ranges.
(WebCore::unionRanges): Updated to no longer take or return a live
range. Still uses live ranges in the algorithm for now.
(WebCore::executeDeleteToMark): Updated since selectedRange no longer
returns a live range.
(WebCore::executeSelectToMark): Update to use the new unionRanges.

* editing/FrameSelection.cpp:
(WebCore::FrameSelection::shouldDeleteSelection const): Updated
since shouldDeleteRange no longer requires a live range.

* editing/cocoa/EditorCocoa.mm:
(WebCore::Editor::getPasteboardTypesAndDataForAttachment): Updated
for changes to use fewer live ranges.
(WebCore::Editor::writeSelectionToPasteboard): Ditto.
(WebCore::Editor::writeSelection): Ditto.
(WebCore::Editor::replaceSelectionWithAttributedString): Ditto.
* editing/gtk/EditorGtk.cpp:
(WebCore::Editor::pasteWithPasteboard): Ditto.
* editing/ios/EditorIOS.mm:
(WebCore::Editor::writeImageToPasteboard): Ditto.
(WebCore::Editor::pasteWithPasteboard): Ditto.
* editing/libwpe/EditorLibWPE.cpp:
(WebCore::createFragmentFromPasteboardData): Ditto.
(WebCore::Editor::pasteWithPasteboard): Ditto.
* editing/mac/EditorMac.mm:
(WebCore::Editor::pasteWithPasteboard): Ditto.
(WebCore::Editor::replaceNodeFromPasteboard): Ditto.
(WebCore::Editor::dataSelectionForPasteboard): Ditto.
* editing/win/EditorWin.cpp:
(WebCore::Editor::pasteWithPasteboard): Ditto.

* html/FTPDirectoryDocument.cpp:
(WebCore::FTPDirectoryDocumentParser::createTDForFilename):
Removed a WTFMove that messes up the return value optimization.
Noticed while fixing errors caused by live range changes.

* loader/EmptyClients.cpp: Updated for changes to EditorClient.

* page/ContextMenuController.cpp:
(WebCore::insertUnicodeCharacter): Updated to use fewer live ranges.
(WebCore::ContextMenuController::contextMenuItemSelected): DItto.
* page/DragController.cpp:
(WebCore::DragController::concludeEditDrag): Ditto.
(WebCore::DragController::startDrag): Ditto.

* page/EditorClient.h: Don't take or return live ranges.

* page/EventHandler.cpp:
(WebCore::EventHandler::sendContextMenuEventForKey): Simplified
since we don't need to use a live range.

* page/FocusController.cpp:
(WebCore::relinquishesEditingFocus): Changed argument type to be
more specific, and changed to not use a live range.
(WebCore::FocusController::setFocusedElement): Updated for the above.

* page/Frame.cpp:
(WebCore::Frame::rangeForPoint): Updated to not use live ranges.

* page/Page.cpp:
(WebCore::Page::findStringMatchingRanges): Updated to not use
live ranges as much.
(WebCore::Page::rangeOfString): Ditto.
(WebCore::Page::findMatchesForText): Ditto.

* testing/Internals.cpp:
(WebCore::Internals::rangeOfString): Updated since return value
of the Editor member function is no longer a live range.
(WebCore::Internals::countMatchesForText): Ditto.

Source/WebKit:

* UIProcess/mac/WKPrintingView.mm:
(-[WKPrintingView rectForPage:]): Use NSZeroRect.

* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::shouldDeleteRange): Updated for live
range changes and also removed gratuitous call to notImplemented
since the function is implemented.
(WebKit::WebEditorClient::shouldBeginEditing): Ditto.
(WebKit::WebEditorClient::shouldEndEditing): Ditto.
(WebKit::WebEditorClient::shouldInsertNode): Ditto.
(WebKit::WebEditorClient::shouldInsertText): Ditto.
(WebKit::WebEditorClient::shouldChangeSelectedRange): Ditto.
(WebKit::WebEditorClient::shouldApplyStyle): Ditto.
(WebKit::WebEditorClient::shouldMoveRangeAfterDelete): Ditto.
(WebKit::WebEditorClient::didBeginEditing): Ditto.
(WebKit::WebEditorClient::didEndEditing): Ditto.
(WebKit::WebEditorClient::willWriteSelectionToPasteboard): Ditto.
(WebKit::WebEditorClient::getClientPasteboardData): Ditto.
(WebKit::WebEditorClient::performTwoStepDrop): Ditto.
(WebKit::WebEditorClient::overflowScrollPositionChanged): Ditto.
(WebKit::WebEditorClient::subFrameScrollPositionChanged): Ditto.
(WebKit::WebEditorClient::setInputMethodState): Ditto.

* WebProcess/WebCoreSupport/WebEditorClient.h: Updated
for changes to EditorClient.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::getMarkedRangeAsync): Updated to reduce
the use of local values and live ranges.
(WebKit::WebPage::getSelectedRangeAsync): Ditto.
(WebKit::WebPage::characterIndexForPointAsync): Ditto.
(WebKit::WebPage::firstRectForCharacterRangeAsync): Ditto.
(WebKit::WebPage::setCompositionAsync): Ditto.
* WebProcess/WebPage/glib/WebPageGLib.cpp:
(WebKit::WebPage::getPlatformEditorState const): Ditto.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPlatformEditorState const): Ditto.
(WebKit::WebPage::selectWithGesture): Ditto.
(WebKit::WebPage::autocorrectionContext): Ditto.
(WebKit::focusedElementPositionInformation): Ditto.
(WebKit::WebPage::requestDocumentEditingContext): Ditto.

Source/WebKitLegacy/ios:

* WebCoreSupport/WebFrameIOS.mm:
(-[WebFrame closestCaretRectInMarkedTextRangeForPoint:]):
Updated since compositionRange is no longer a live range.

Source/WebKitLegacy/mac:

* DOM/DOMRange.mm:
(kit): Added an overload to convert to a live range so we don't have
to touch every call site.
* DOM/DOMRangeInternal.h: Added the above.

* WebCoreSupport/WebEditorClient.h: Updated for changes to EditorClient.

* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::shouldDeleteRange): Changed types to not use live ranges.
(WebEditorClient::shouldApplyStyle): Ditto.
(WebEditorClient::shouldMoveRangeAfterDelete): Ditto.
(WebEditorClient::shouldBeginEditing): Ditto.
(WebEditorClient::shouldEndEditing): Ditto.
(WebEditorClient::shouldInsertText): Ditto.
(WebEditorClient::shouldChangeSelectedRange): Ditto.
(WebEditorClient::willWriteSelectionToPasteboard): Ditto.
(WebEditorClient::getClientPasteboardData): Ditto.
(WebEditorClient::shouldInsertNode): Ditto.
(WebEditorClient::performTwoStepDrop): Ditto.

* WebView/WebFrame.mm:
(-[WebFrame _firstRectForDOMRange:]): Update to not use live range.
(-[WebFrame _scrollDOMRangeToVisible:]): Ditto.
(-[WebFrame _rangeByAlteringCurrentSelection:direction:granularity:]): Ditto.
(-[WebFrame _markDOMRange]): Ditto.
(-[WebFrame _selectionRangeForFirstPoint:secondPoint:]): Ditto.
(-[WebFrame _selectionRangeForPoint:]): Ditto.
(-[WebFrame selectedDOMRange]): Ditto.
(-[WebFrame elementRangeContainingCaretSelection]): Ditto.
(-[WebFrame wordRangeContainingCaretSelection]): Ditto.
(-[WebFrame rangeByMovingCurrentSelection:]): Ditto.
(-[WebFrame rangeByExtendingCurrentSelection:]): Ditto.
(-[WebFrame markedTextDOMRange]): Ditto.

* WebView/WebHTMLView.mm:
(-[WebHTMLView _selectedRange]): Update to not use live range.
(-[WebHTMLView firstRectForCharacterRange:]): Use NSZeroRect.
(-[WebHTMLView countMatchesForText:inDOMRange:options:limit:markMatches:]):
Update to not use live range.
* WebView/WebTextCompletionController.mm:
(-[WebTextCompletionController doCompletion]): Ditto.
* WebView/WebTextIterator.mm:
(-[WebTextIterator currentRange]): Ditto.
* WebView/WebView.mm:
(-[WebView textIteratorForRect:]): Ditto.
(-[WebView editableDOMRangeForPoint:]): Ditto.
(-[WebView selectedDOMRange]): Ditto.

Source/WebKitLegacy/win:

* DOMCoreClasses.cpp:
(DOMWindow::DOMWindow): Added ref for underlying WebCore::DOMWindow.
(DOMWindow::~DOMWindow): Added deref for underlying WebCore::DOMWindow.
(DOMRange::DOMRange): Added ref for underlying live range.
(DOMRange::~DOMRange): Added deref for underlying live range.
(DOMRange::createInstance): Added overload for creating a DOMRange from
a SimpleRange that creates the live range.
(DOMNamedNodeMap::DOMNamedNodeMap): Added ref for underlying live range.
(DOMNamedNodeMap::~DOMNamedNodeMap): Added deref for underlying live range.

* DOMCoreClasses.h: Added createInstance overload as described above.

* WebCoreSupport/WebEditorClient.cpp:
(WebEditorClient::shouldBeginEditing): Updated for changes to not use
live ranges. Also removed unnecessary notImplemented calls.
(WebEditorClient::shouldEndEditing): Ditto.
(WebEditorClient::discardedComposition): Ditto.
(WebEditorClient::canceledComposition): Ditto.
(WebEditorClient::didWriteSelectionToPasteboard): Ditto.
(WebEditorClient::willWriteSelectionToPasteboard): Ditto.
(WebEditorClient::getClientPasteboardData): Ditto.
(WebEditorClient::shouldDeleteRange): Ditto.
(WebEditorClient::shouldInsertNode): Ditto.
(WebEditorClient::shouldInsertText): Ditto.
(WebEditorClient::shouldChangeSelectedRange): Ditto.
(WebEditorClient::shouldApplyStyle): Ditto.
(WebEditorClient::didApplyStyle): Ditto.
(WebEditorClient::shouldMoveRangeAfterDelete): Ditto.

* WebCoreSupport/WebEditorClient.h: Updated for changes to
EditorClient.

* WebView.cpp:
(WebView::prepareCandidateWindow): Updated to not use live ranges.
(WebView::onIMERequestCharPosition): Ditto.
(WebView::compositionRangeForTesting): Ditto.
(WebView::firstRectForCharacterRangeForTesting): Ditto.
(WebView::selectedRangeForTesting): Ditto.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
Removed duplicate install of Ahem.ttf that was leading new versions
of Xcode to fail when trying to build this.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@264692 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/editing/AlternativeTextController.cpp b/Source/WebCore/editing/AlternativeTextController.cpp
index e2e894c..9ac2e9d 100644
--- a/Source/WebCore/editing/AlternativeTextController.cpp
+++ b/Source/WebCore/editing/AlternativeTextController.cpp
@@ -243,7 +243,7 @@
         VisiblePosition p = startOfWord(start, LeftWordIfOnBoundary);
         VisibleSelection adjacentWords = VisibleSelection(p, start);
         auto adjacentWordRange = adjacentWords.toNormalizedRange();
-        m_document.editor().markAllMisspellingsAndBadGrammarInRanges({ TextCheckingType::Spelling, TextCheckingType::Replacement, TextCheckingType::ShowCorrectionPanel }, createLiveRange(adjacentWordRange), createLiveRange(adjacentWordRange), nullptr);
+        m_document.editor().markAllMisspellingsAndBadGrammarInRanges({ TextCheckingType::Spelling, TextCheckingType::Replacement, TextCheckingType::ShowCorrectionPanel }, adjacentWordRange, adjacentWordRange, WTF::nullopt);
     }
         break;
     case AlternativeTextTypeReversion: {
@@ -653,7 +653,7 @@
 #if USE(DICTATION_ALTERNATIVES)
     auto& editor = m_document.editor();
     auto selection = editor.selectedRange();
-    if (!selection || !editor.shouldInsertText(alternativeString, selection.get(), EditorInsertAction::Pasted))
+    if (!selection || !editor.shouldInsertText(alternativeString, *selection, EditorInsertAction::Pasted))
         return;
     for (auto* marker : selection->startContainer().document().markers().markersInRange(*selection, DocumentMarker::DictationAlternatives))
         removeDictationAlternativesForMarker(*marker);
diff --git a/Source/WebCore/editing/DeleteSelectionCommand.cpp b/Source/WebCore/editing/DeleteSelectionCommand.cpp
index 112f97b..870c4db 100644
--- a/Source/WebCore/editing/DeleteSelectionCommand.cpp
+++ b/Source/WebCore/editing/DeleteSelectionCommand.cpp
@@ -749,9 +749,9 @@
     
     auto range = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), endOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent());
     auto rangeToBeReplaced = Range::create(document(), mergeDestination.deepEquivalent().parentAnchoredEquivalent(), mergeDestination.deepEquivalent().parentAnchoredEquivalent());
-    if (!document().editor().client()->shouldMoveRangeAfterDelete(range.ptr(), rangeToBeReplaced.ptr()))
+    if (!document().editor().client()->shouldMoveRangeAfterDelete(range, rangeToBeReplaced))
         return;
-    
+
     // moveParagraphs will insert placeholders if it removes blocks that would require their use, don't let block
     // removals that it does cause the insertion of *another* placeholder.
     bool needPlaceholder = m_needPlaceholder;
diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp
index db97d37..7b5e2ee 100644
--- a/Source/WebCore/editing/Editor.cpp
+++ b/Source/WebCore/editing/Editor.cpp
@@ -507,21 +507,18 @@
     return selection.isRange() && selection.rootEditableElement();
 }
 
-bool Editor::canDeleteRange(Range* range) const
+bool Editor::canDeleteRange(const SimpleRange& range) const
 {
-    Node& startContainer = range->startContainer();
-    Node& endContainer = range->endContainer();
-    
-    if (!startContainer.hasEditableStyle() || !endContainer.hasEditableStyle())
+    if (!range.start.container->hasEditableStyle() || !range.end.container->hasEditableStyle())
         return false;
 
-    if (range->collapsed()) {
-        VisiblePosition start(range->startPosition(), DOWNSTREAM);
-        VisiblePosition previous = start.previous();
+    if (range.collapsed()) {
         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
-        if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer.rootEditableElement())
+        auto previous = VisiblePosition { createLegacyEditingPosition(range.start), DOWNSTREAM }.previous();
+        if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != range.start.container->rootEditableElement())
             return false;
     }
+
     return true;
 }
 
@@ -558,7 +555,7 @@
             revealSelectionAfterEditingOperation();
         } else {
             if (shouldAddToKillRing)
-                addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
+                addRangeToKillRing(*selectedRange(), KillRingInsertionMode::AppendText);
             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
             // Implicitly calls revealSelectionAfterEditingOperation().
         }
@@ -627,7 +624,7 @@
 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard& pasteboard)
 {
     String text = readPlainTextFromPasteboard(pasteboard);
-    if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertAction::Pasted))
+    if (client() && client()->shouldInsertText(text, selectedRange(), EditorInsertAction::Pasted))
         pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
 }
 
@@ -652,7 +649,7 @@
     return client() && client()->smartInsertDeleteEnabled() && pasteboard.canSmartReplace();
 }
 
-bool Editor::shouldInsertFragment(DocumentFragment& fragment, Range* replacingDOMRange, EditorInsertAction givenAction)
+bool Editor::shouldInsertFragment(DocumentFragment& fragment, const Optional<SimpleRange>& replacingDOMRange, EditorInsertAction givenAction)
 {
     if (!client())
         return false;
@@ -661,7 +658,7 @@
     if (is<CharacterData>(child) && fragment.lastChild() == child)
         return client()->shouldInsertText(downcast<CharacterData>(*child).data(), replacingDOMRange, givenAction);
 
-    return client()->shouldInsertNode(&fragment, replacingDOMRange, givenAction);
+    return client()->shouldInsertNode(fragment, replacingDOMRange, givenAction);
 }
 
 void Editor::replaceSelectionWithFragment(DocumentFragment& fragment, SelectReplacement selectReplacement, SmartReplace smartReplace, MatchStyle matchStyle, EditAction editingAction, MailBlockquoteHandling mailBlockquoteHandling)
@@ -724,27 +721,21 @@
 
 void Editor::replaceSelectionWithText(const String& text, SelectReplacement selectReplacement, SmartReplace smartReplace, EditAction editingAction)
 {
-    RefPtr<Range> range = selectedRange();
+    auto range = selectedRange();
     if (!range)
         return;
 
-    replaceSelectionWithFragment(createFragmentFromText(*range, text), selectReplacement, smartReplace, MatchStyle::Yes, editingAction);
+    replaceSelectionWithFragment(createFragmentFromText(createLiveRange(*range), text), selectReplacement, smartReplace, MatchStyle::Yes, editingAction);
 }
 
-RefPtr<Range> Editor::selectedRange()
+Optional<SimpleRange> Editor::selectedRange()
 {
-    return createLiveRange(m_document.selection().selection().toNormalizedRange());
+    return m_document.selection().selection().toNormalizedRange();
 }
 
-bool Editor::shouldDeleteRange(Range* range) const
+bool Editor::shouldDeleteRange(const Optional<SimpleRange>& range) const
 {
-    if (!range || range->collapsed())
-        return false;
-    
-    if (!canDeleteRange(range))
-        return false;
-
-    return client() && client()->shouldDeleteRange(range);
+    return range && !range->collapsed() && canDeleteRange(*range) && client() && client()->shouldDeleteRange(*range);
 }
 
 bool Editor::tryDHTMLCopy()
@@ -763,7 +754,7 @@
     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Cut);
 }
 
-bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
+bool Editor::shouldInsertText(const String& text, const Optional<SimpleRange>& range, EditorInsertAction action) const
 {
     if (m_document.frame()->mainFrame().loader().shouldSuppressTextInputFromEditing() && action == EditorInsertAction::Typed)
         return false;
@@ -980,7 +971,7 @@
         dispatchInputEvent(*element, inputTypeName, inputEventData);
 }
     
-bool Editor::shouldApplyStyle(StyleProperties* style, Range* range)
+bool Editor::shouldApplyStyle(const StyleProperties& style, const SimpleRange& range)
 {   
     return client()->shouldApplyStyle(style, range);
 }
@@ -1011,7 +1002,7 @@
     if (!style || style->isEmpty() || !canEditRichly())
         return;
 
-    if (!client() || !client()->shouldApplyStyle(style, createLiveRange(m_document.selection().selection().toNormalizedRange()).get()))
+    if (!client() || !client()->shouldApplyStyle(*style, m_document.selection().selection().toNormalizedRange()))
         return;
     applyStyle(style, editingAction);
 }
@@ -1022,7 +1013,7 @@
         return;
 
     // FIXME: This is wrong for text decorations since m_mutableStyle is empty.
-    if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), createLiveRange(m_document.selection().selection().toNormalizedRange()).get()))
+    if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations(), m_document.selection().selection().toNormalizedRange()))
         return;
 
     applyStyle(WTFMove(style), editingAction, colorFilterMode);
@@ -1033,7 +1024,7 @@
     if (!style || style->isEmpty() || !canEditRichly())
         return;
     
-    if (client() && client()->shouldApplyStyle(style, createLiveRange(m_document.selection().selection().toNormalizedRange()).get()))
+    if (client() && client()->shouldApplyStyle(*style, m_document.selection().selection().toNormalizedRange()))
         applyParagraphStyle(style, editingAction);
 }
 
@@ -1273,7 +1264,7 @@
     if (!selection.isContentEditable())
         return false;
 
-    if (!shouldInsertText(text, createLiveRange(selection.toNormalizedRange()).get(), EditorInsertAction::Typed))
+    if (!shouldInsertText(text, selection.toNormalizedRange(), EditorInsertAction::Typed))
         return true;
 
     // FIXME: Should pass false to updateMarkersForWordsAffectedByEditing() to not remove markers if
@@ -1332,7 +1323,7 @@
     if (!canEdit())
         return false;
 
-    if (!shouldInsertText("\n", createLiveRange(m_document.selection().selection().toNormalizedRange()).get(), EditorInsertAction::Typed))
+    if (!shouldInsertText("\n"_s, m_document.selection().selection().toNormalizedRange(), EditorInsertAction::Typed))
         return true;
 
     VisiblePosition caret = m_document.selection().selection().visibleStart();
@@ -1352,7 +1343,7 @@
     if (!canEditRichly())
         return insertLineBreak();
     
-    if (!shouldInsertText("\n", createLiveRange(m_document.selection().selection().toNormalizedRange()).get(), EditorInsertAction::Typed))
+    if (!shouldInsertText("\n"_s, m_document.selection().selection().toNormalizedRange(), EditorInsertAction::Typed))
         return true;
 
     VisiblePosition caret = m_document.selection().selection().visibleStart();
@@ -1412,10 +1403,10 @@
 
 void Editor::performCutOrCopy(EditorActionSpecifier action)
 {
-    RefPtr<Range> selection = selectedRange();
-    willWriteSelectionToPasteboard(selection.get());
+    auto selection = selectedRange();
+    willWriteSelectionToPasteboard(selection);
     if (action == CutAction) {
-        if (!shouldDeleteRange(selection.get()))
+        if (!shouldDeleteRange(selection))
             return;
 
         updateMarkersForWordsAffectedByEditing(true);
@@ -1440,7 +1431,7 @@
             writeSelectionToPasteboard(*Pasteboard::createForCopyAndPaste());
 #else
             // FIXME: Delete after <http://webkit.org/b/177618> lands.
-            Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), *m_document.frame(), IncludeImageAltTextForDataTransfer);
+            Pasteboard::createForCopyAndPaste()->writeSelection(createLiveRange(*selection).get(), canSmartCopyOrDelete(), *m_document.frame(), IncludeImageAltTextForDataTransfer);
 #endif
         }
     }
@@ -1532,7 +1523,7 @@
         return;
     }
 
-    addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
+    addRangeToKillRing(*selectedRange(), KillRingInsertionMode::AppendText);
     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
 
     // clear the "start new kill ring sequence" setting, because it was set to true
@@ -1790,12 +1781,12 @@
 
 #endif
 
-bool Editor::shouldEndEditing(Range* range)
+bool Editor::shouldEndEditing(const SimpleRange& range)
 {
     return client() && client()->shouldEndEditing(range);
 }
 
-bool Editor::shouldBeginEditing(Range* range)
+bool Editor::shouldBeginEditing(const SimpleRange& range)
 {
     return client() && client()->shouldBeginEditing(range);
 }
@@ -1847,7 +1838,7 @@
         client()->didEndEditing();
 }
 
-void Editor::willWriteSelectionToPasteboard(Range* range)
+void Editor::willWriteSelectionToPasteboard(const Optional<SimpleRange>& range)
 {
     if (client())
         client()->willWriteSelectionToPasteboard(range);
@@ -1930,14 +1921,14 @@
 
 void Editor::selectComposition()
 {
-    RefPtr<Range> range = compositionRange();
+    auto range = compositionRange();
     if (!range)
         return;
     
     // The composition can start inside a composed character sequence, so we have to override checks.
     // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
     VisibleSelection selection;
-    selection.setWithoutValidation(range->startPosition(), range->endPosition());
+    selection.setWithoutValidation(createLegacyEditingPosition(range->start), createLegacyEditingPosition(range->end));
     m_document.selection().setSelection(selection, { });
 }
 
@@ -2491,9 +2482,9 @@
     if (!textCheckingOptions.contains(TextCheckingType::Spelling))
         return;
 
-    VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
+    auto adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
     auto adjacentWordRange = adjacentWords.toNormalizedRange();
-    markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, createLiveRange(adjacentWordRange), createLiveRange(adjacentWordRange), createLiveRange(adjacentWordRange));
+    markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWordRange, adjacentWordRange, adjacentWordRange);
 #else
 #if !USE(AUTOMATIC_TEXT_REPLACEMENT)
     UNUSED_PARAM(doReplacement);
@@ -2578,7 +2569,7 @@
         // full sentence as we can, respecting boundaries where spellchecking is disabled.
         fullSentenceRange->start.document().markers().removeMarkers(*fullSentenceRange, DocumentMarker::Grammar);
         spellCheckingRange->start.document().markers().removeMarkers(*spellCheckingRange, DocumentMarker::Spelling);
-        markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, createLiveRange(spellCheckingRange), createLiveRange(adjacentWordRange), createLiveRange(fullSentenceRange));
+        markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellCheckingRange, adjacentWordRange, fullSentenceRange);
         return;
     }
 
@@ -2586,8 +2577,7 @@
         return;
 
     // Check spelling of one word
-    RefPtr<Range> misspellingRange;
-    markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)), misspellingRange);
+    auto misspellingRange = markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)));
 
     // Autocorrect the misspelled word.
     if (!misspellingRange)
@@ -2605,7 +2595,7 @@
             m_document.selection().setSelection(newSelection);
         }
 
-        if (!m_document.editor().shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertAction::Typed))
+        if (!m_document.editor().shouldInsertText(autocorrectedString, misspellingRange, EditorInsertAction::Typed))
             return;
         m_document.editor().replaceSelectionWithText(autocorrectedString, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
 
@@ -2622,7 +2612,7 @@
 #endif
 }
     
-void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
+Optional<SimpleRange> Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling)
 {
 #if !PLATFORM(IOS_FAMILY)
     // This function is called with a selection already expanded to word boundaries.
@@ -2631,33 +2621,37 @@
     // This function is used only for as-you-type checking, so if that's off we do nothing. Note that
     // grammar checking can only be on if spell checking is also on.
     if (!isContinuousSpellCheckingEnabled())
-        return;
+        return WTF::nullopt;
     
     auto searchRange = selection.toNormalizedRange();
     if (!searchRange)
-        return;
+        return WTF::nullopt;
     
     // If we're not in an editable node, bail.
     Node& editableNode = searchRange->startContainer();
     if (!editableNode.hasEditableStyle())
-        return;
+        return WTF::nullopt;
 
     if (!isSpellCheckingEnabledFor(&editableNode))
-        return;
+        return WTF::nullopt;
 
     // Get the spell checker if it is available
     if (!client())
-        return;
+        return WTF::nullopt;
     
     TextCheckingHelper checker(*client(), *searchRange);
-    if (checkSpelling)
-        checker.markAllMisspellings(firstMisspellingRange);
-    else if (isGrammarCheckingEnabled())
+    if (checkSpelling) {
+        RefPtr<Range> firstMisspellingLiveRange;
+        checker.markAllMisspellings(firstMisspellingLiveRange);
+        return makeSimpleRange(firstMisspellingLiveRange);
+    }
+    if (isGrammarCheckingEnabled())
         checker.markAllBadGrammar();
+    return WTF::nullopt;
 #else
     UNUSED_PARAM(selection);
     UNUSED_PARAM(checkSpelling);
-    UNUSED_PARAM(firstMisspellingRange);
+    return WTF::nullopt;
 #endif // !PLATFORM(IOS_FAMILY)
 }
 
@@ -2680,18 +2674,17 @@
     return isSpellCheckingEnabledFor(m_document.selection().selection().start().deprecatedNode());
 }
 
-void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
+Optional<SimpleRange> Editor::markMisspellings(const VisibleSelection& selection)
 {
-    markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange);
+    return markMisspellingsOrBadGrammar(selection, true);
 }
     
 void Editor::markBadGrammar(const VisibleSelection& selection)
 {
-    RefPtr<Range> firstMisspellingRange;
-    markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange);
+    markMisspellingsOrBadGrammar(selection, false);
 }
 
-void Editor::markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType> textCheckingOptions, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange)
+void Editor::markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType> textCheckingOptions, const Optional<SimpleRange>& spellingRange, const Optional<SimpleRange>& automaticReplacementRange, const Optional<SimpleRange>& grammarRange)
 {
     if (platformDrivenTextCheckerEnabled())
         return;
@@ -2716,8 +2709,8 @@
     if (!isSpellCheckingEnabledFor(&editableNode))
         return;
 
-    auto rangeToCheck = shouldMarkGrammar ? grammarRange.releaseNonNull() : spellingRange.releaseNonNull();
-    TextCheckingParagraph paragraphToCheck(rangeToCheck.get());
+    auto& rangeToCheck = shouldMarkGrammar ? *grammarRange : *spellingRange;
+    TextCheckingParagraph paragraphToCheck(createLiveRange(rangeToCheck));
     if (paragraphToCheck.isEmpty())
         return;
 
@@ -2725,8 +2718,8 @@
 
     // In asynchronous mode, we intentionally check paragraph-wide sentence.
     const auto resolvedOptions = resolveTextCheckingTypeMask(editableNode, textCheckingOptions);
-    auto textReplacementRange = automaticReplacementRange ? makeRef(*automaticReplacementRange) : rangeToCheck.copyRef();
-    auto request = SpellCheckRequest::create(resolvedOptions, TextCheckingProcessIncremental, asynchronous ? makeRef(paragraphToCheck.paragraphRange()) : WTFMove(rangeToCheck), WTFMove(textReplacementRange), paragraphToCheck.paragraphRange());
+    auto& textReplacementRange = automaticReplacementRange ? *automaticReplacementRange : rangeToCheck;
+    auto request = SpellCheckRequest::create(resolvedOptions, TextCheckingProcessIncremental, asynchronous ? Ref<Range> { paragraphToCheck.paragraphRange() } : createLiveRange(rangeToCheck), createLiveRange(textReplacementRange), paragraphToCheck.paragraphRange());
     if (!request)
         return;
 
@@ -2759,9 +2752,9 @@
     return false;
 }
 
-void Editor::replaceRangeForSpellChecking(Range& rangeToReplace, const String& replacement)
+void Editor::replaceRangeForSpellChecking(const SimpleRange& rangeToReplace, const String& replacement)
 {
-    SpellingCorrectionCommand::create(rangeToReplace, replacement)->apply();
+    SpellingCorrectionCommand::create(createLiveRange(rangeToReplace), replacement)->apply();
 }
 
 static void correctSpellcheckingPreservingTextCheckingParagraph(TextCheckingParagraph& paragraph, Range& rangeToReplace, const String& replacement, CharacterRange resultCharacterRange)
@@ -2901,7 +2894,7 @@
                 restoreSelectionAfterChange = false;
                 if (canEditRichly())
                     CreateLinkCommand::create(document(), replacement)->apply();
-            } else if (canEdit() && shouldInsertText(replacement, rangeToReplace.ptr(), EditorInsertAction::Typed)) {
+            } else if (canEdit() && shouldInsertText(replacement, makeSimpleRange(rangeToReplace), EditorInsertAction::Typed)) {
                 correctSpellcheckingPreservingTextCheckingParagraph(paragraph, rangeToReplace, replacement, { resultLocation, resultLength });
 
                 if (AXObjectCache* cache = document().existingAXObjectCache()) {
@@ -2954,12 +2947,12 @@
     if (replacedString.isEmpty())
         return;
 
-    RefPtr<Range> selection = selectedRange();
-    if (!selection || !shouldInsertText(replacedString, selection.get(), EditorInsertAction::Pasted))
+    auto selection = selectedRange();
+    if (!selection || !shouldInsertText(replacedString, selection, EditorInsertAction::Pasted))
         return;
     
     m_alternativeTextController->recordAutocorrectionResponse(AutocorrectionResponse::Reverted, replacedString, *selection);
-    TextCheckingParagraph paragraph(*selection);
+    TextCheckingParagraph paragraph(createLiveRange(*selection));
     replaceSelectionWithText(replacedString, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
     auto changedRange = paragraph.subrange(CharacterRange(paragraph.checkingStart(), replacedString.length()));
     changedRange->startContainer().document().markers().addMarker(changedRange, DocumentMarker::Replacement, String());
@@ -2985,12 +2978,11 @@
         if (markGrammar && isGrammarCheckingEnabled())
             textCheckingOptions.add(TextCheckingType::Grammar);
         auto spellCheckingRange = spellingSelection.toNormalizedRange();
-        markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, createLiveRange(spellCheckingRange), createLiveRange(spellCheckingRange), createLiveRange(grammarSelection.toNormalizedRange()));
+        markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellCheckingRange, spellCheckingRange, grammarSelection.toNormalizedRange());
         return;
     }
 
-    RefPtr<Range> firstMisspellingRange;
-    markMisspellings(spellingSelection, firstMisspellingRange);
+    markMisspellings(spellingSelection);
     if (markGrammar)
         markBadGrammar(grammarSelection);
 }
@@ -3092,23 +3084,18 @@
     m_alternativeTextController->deletedAutocorrectionAtPosition(position, originalString);
 }
 
-RefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
+Optional<SimpleRange> Editor::rangeForPoint(const IntPoint& windowPoint)
 {
     auto document = m_document.frame()->documentAtPoint(windowPoint);
     if (!document)
-        return nullptr;
-    
+        return WTF::nullopt;
     auto frame = document->frame();
     if (!frame)
-        return nullptr;
-    
+        return WTF::nullopt;
     auto frameView = frame->view();
     if (!frameView)
-        return nullptr;
-
-    auto framePoint = frameView->windowToContents(windowPoint);
-    auto selection = VisibleSelection { frame->visiblePositionForPoint(framePoint) };
-    return createLiveRange(selection.toNormalizedRange());
+        return WTF::nullopt;
+    return VisibleSelection { frame->visiblePositionForPoint(frameView->windowToContents(windowPoint)) }.toNormalizedRange();
 }
 
 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
@@ -3135,17 +3122,16 @@
         revealSelectionAfterEditingOperation(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
 }
 
-RefPtr<Range> Editor::compositionRange() const
+Optional<SimpleRange> Editor::compositionRange() const
 {
     if (!m_compositionNode)
-        return nullptr;
+        return WTF::nullopt;
     unsigned length = m_compositionNode->length();
     unsigned start = std::min(m_compositionStart, length);
-    unsigned end = std::min(std::max(start, m_compositionEnd), length);
-    // FIXME: Why is this early return neeed?
+    unsigned end = std::clamp(m_compositionEnd, start, length);
     if (start >= end)
-        return nullptr;
-    return Range::create(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
+        return WTF::nullopt;
+    return { { { *m_compositionNode, start }, { *m_compositionNode, end } } };
 }
 
 bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const
@@ -3207,7 +3193,7 @@
     }
 
     // Insert the transposed characters.
-    if (!shouldInsertText(transposed, range.get(), EditorInsertAction::Typed))
+    if (!shouldInsertText(transposed, newSelection.firstRange(), EditorInsertAction::Typed))
         return;
     replaceSelectionWithText(transposed, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
 }
@@ -3366,13 +3352,13 @@
         rect.setHeight(0);
 }
 
-IntRect Editor::firstRectForRange(Range* range) const
+IntRect Editor::firstRectForRange(const SimpleRange& range) const
 {
-    range->ownerDocument().updateLayout();
+    range.start.document().updateLayout();
 
-    VisiblePosition startVisiblePosition(range->startPosition(), DOWNSTREAM);
+    VisiblePosition startVisiblePosition(createLegacyEditingPosition(range.start), DOWNSTREAM);
 
-    if (range->collapsed()) {
+    if (range.collapsed()) {
         // FIXME: Getting caret rect and removing caret width is a very roundabout way to get collapsed range location.
         // In particular, width adjustment doesn't work for rotated text.
         IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect();
@@ -3380,10 +3366,10 @@
         return startCaretRect;
     }
 
-    VisiblePosition endVisiblePosition(range->endPosition(), UPSTREAM);
+    VisiblePosition endVisiblePosition(createLegacyEditingPosition(range.end), UPSTREAM);
 
     if (inSameLine(startVisiblePosition, endVisiblePosition))
-        return enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(*range)));
+        return enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(range)));
 
     LayoutUnit extraWidthToEndOfLine;
     IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect(&extraWidthToEndOfLine);
@@ -3409,7 +3395,7 @@
     if (m_document.frame() && m_document.frame()->selectionChangeCallbacksDisabled())
         return true;
 #endif
-    return client() && client()->shouldChangeSelectedRange(createLiveRange(oldSelection.toNormalizedRange()).get(), createLiveRange(newSelection.toNormalizedRange()).get(), affinity, stillSelecting);
+    return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange(), newSelection.toNormalizedRange(), affinity, stillSelecting);
 }
 
 void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAction)
@@ -3496,7 +3482,7 @@
 
     VisibleSelection selection = m_document.selection().selection();
 
-    auto resultRange = rangeOfString(target, createLiveRange(selection.firstRange()).get(), options);
+    auto resultRange = rangeOfString(target, selection.firstRange(), options);
     if (!resultRange)
         return false;
 
@@ -3508,106 +3494,109 @@
     return true;
 }
 
-RefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
+template<typename T> static auto& start(T& range, FindOptions options)
+{
+    return options.contains(Backwards) ? range.end : range.start;
+}
+
+template<typename T> static auto& end(T& range, FindOptions options)
+{
+    return options.contains(Backwards) ? range.start : range.end;
+}
+
+static BoundaryPoint makeBoundaryPointAfterNodeContents(Node& node, FindOptions options)
+{
+    return options.contains(Backwards) ? makeBoundaryPointBeforeNodeContents(node) : makeBoundaryPointAfterNodeContents(node);
+}
+
+static Optional<BoundaryPoint> makeBoundaryPointAfterNode(Node& node, FindOptions options)
+{
+    return options.contains(Backwards) ? makeBoundaryPointBeforeNode(node) : makeBoundaryPointAfterNode(node);
+}
+
+static SimpleRange collapseIfRootsDiffer(SimpleRange&& range)
+{
+    // FIXME: This helps correct results in some cases involving shadow trees. But we can incorrectly find a string with middle characters in an input element and first and last characters outside it.
+    return &range.start.container->rootNode() == &range.end.container->rootNode()
+        ? WTFMove(range) : SimpleRange { range.start, range.start };
+}
+
+Optional<SimpleRange> Editor::rangeOfString(const String& target, const Optional<SimpleRange>& referenceRange, FindOptions options)
 {
     if (target.isEmpty())
-        return nullptr;
+        return WTF::nullopt;
 
     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
-    RefPtr<Range> searchRange(rangeOfContents(document()));
 
-    bool forward = !options.contains(Backwards);
     bool startInReferenceRange = referenceRange && options.contains(StartInSelection);
-    if (referenceRange) {
-        if (forward)
-            searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
-        else
-            searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
-    }
+    auto shadowTreeRoot = referenceRange ? referenceRange->startContainer().containingShadowRoot() : nullptr;
 
-    RefPtr<ShadowRoot> shadowTreeRoot = referenceRange ? referenceRange->startContainer().containingShadowRoot() : nullptr;
-    if (shadowTreeRoot) {
-        if (forward)
-            searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
-        else
-            searchRange->setStart(*shadowTreeRoot, 0);
-    }
+    auto searchRange = makeRangeSelectingNodeContents(document());
+    if (referenceRange)
+        start(searchRange, options) = startInReferenceRange ? start(*referenceRange, options) : end(*referenceRange, options);
+    if (shadowTreeRoot)
+        end(searchRange, options) = makeBoundaryPointAfterNodeContents(*shadowTreeRoot, options);
+    auto resultRange = collapseIfRootsDiffer(findPlainText(searchRange, target, options));
 
-    RefPtr<Range> resultRange = createLiveRange(findPlainText(*searchRange, target, options));
     // If we started in the reference range and the found range exactly matches the reference range, find again.
     // Build a selection with the found range to remove collapsed whitespace.
     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
-    if (startInReferenceRange && areRangesEqual(createLiveRange(VisibleSelection(*resultRange).toNormalizedRange()).get(), referenceRange)) {
-        searchRange = rangeOfContents(document());
-        if (forward)
-            searchRange->setStart(referenceRange->endPosition());
-        else
-            searchRange->setEnd(referenceRange->startPosition());
-
-        if (shadowTreeRoot) {
-            if (forward)
-                searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
-            else
-                searchRange->setStart(*shadowTreeRoot, 0);
-        }
-
-        resultRange = createLiveRange(findPlainText(*searchRange, target, options));
+    if (startInReferenceRange && VisibleSelection(resultRange).toNormalizedRange() == referenceRange) {
+        searchRange = makeRangeSelectingNodeContents(document());
+        start(searchRange, options) = end(*referenceRange, options);
+        if (shadowTreeRoot)
+            end(searchRange, options) = makeBoundaryPointAfterNodeContents(*shadowTreeRoot, options);
+        resultRange = collapseIfRootsDiffer(findPlainText(searchRange, target, options));
     }
 
     // If nothing was found in the shadow tree, search in main content following the shadow tree.
-    if (resultRange->collapsed() && shadowTreeRoot) {
-        searchRange = rangeOfContents(document());
-        if (shadowTreeRoot->shadowHost()) {
-            if (forward)
-                searchRange->setStartAfter(*shadowTreeRoot->shadowHost());
-            else
-                searchRange->setEndBefore(*shadowTreeRoot->shadowHost());
-        }
-
-        resultRange = createLiveRange(findPlainText(*searchRange, target, options));
+    if (resultRange.collapsed() && shadowTreeRoot) {
+        searchRange = makeRangeSelectingNodeContents(document());
+        if (auto host = shadowTreeRoot->shadowHost())
+            start(searchRange, options) = *makeBoundaryPointAfterNode(*host, options);
+        resultRange = collapseIfRootsDiffer(findPlainText(searchRange, target, options));
     }
 
     // If we didn't find anything and we're wrapping, search again in the entire document (this will
     // redundantly re-search the area already searched in some cases).
-    if (resultRange->collapsed() && options.contains(WrapAround)) {
-        resultRange = createLiveRange(findPlainText(rangeOfContents(document()), target, options));
+    if (resultRange.collapsed() && options.contains(WrapAround)) {
+        resultRange = collapseIfRootsDiffer(findPlainText(rangeOfContents(document()), target, options));
         // We used to return false here if we ended up with the same range that we started with
         // (e.g., the reference range was already the only instance of this text). But we decided that
         // this should be a success case instead, so we'll just fall through in that case.
     }
 
-    return resultRange->collapsed() ? nullptr : resultRange;
+    return resultRange.collapsed() ? WTF::nullopt : makeOptional(resultRange);
 }
 
-static bool isFrameInRange(Frame& frame, Range& range)
+static bool isFrameInRange(Frame& frame, const SimpleRange& range)
 {
     for (auto* ownerElement = frame.ownerElement(); ownerElement; ownerElement = ownerElement->document().ownerElement()) {
-        if (&ownerElement->document() == &range.ownerDocument()) {
-            auto result = range.intersectsNode(*ownerElement);
+        if (&ownerElement->document() == &range.start.document()) {
+            auto result = createLiveRange(range)->intersectsNode(*ownerElement);
             return !result.hasException() && result.releaseReturnValue();
         }
     }
     return false;
 }
 
-unsigned Editor::countMatchesForText(const String& target, Range* range, FindOptions options, unsigned limit, bool markMatches, Vector<RefPtr<Range>>* matches)
+unsigned Editor::countMatchesForText(const String& target, const Optional<SimpleRange>& range, FindOptions options, unsigned limit, bool markMatches, Vector<SimpleRange>* matches)
 {
     if (target.isEmpty())
         return 0;
 
-    RefPtr<Range> searchRange;
+    Optional<SimpleRange> searchRange;
     if (range) {
-        if (&range->ownerDocument() == &document())
-            searchRange = range;
+        if (&range->start.document() == &document())
+            searchRange = *range;
         else if (!isFrameInRange(*m_document.frame(), *range))
             return 0;
     }
     if (!searchRange)
-        searchRange = rangeOfContents(document());
+        searchRange = makeRangeSelectingNodeContents(document());
 
-    Node& originalEndContainer = searchRange->endContainer();
-    int originalEndOffset = searchRange->endOffset();
+    auto originalEnd = searchRange->end;
 
     unsigned matchCount = 0;
     do {
@@ -3616,8 +3605,8 @@
             if (!resultRange.start.container->isInShadowTree())
                 break;
 
-            searchRange->setStartAfter(*resultRange.start.container->shadowHost());
-            searchRange->setEnd(originalEndContainer, originalEndOffset);
+            searchRange->start = makeBoundaryPointAfterNodeContents(*resultRange.start.container->shadowHost());
+            searchRange->end = originalEnd;
             continue;
         }
 
@@ -3632,15 +3621,14 @@
         if (limit > 0 && matchCount >= limit)
             break;
 
-        // Set the new start for the search range to be the end of the previous
-        // result range. There is no need to use a VisiblePosition here,
-        // since findPlainText will use a TextIterator to go over the visible
-        // text nodes. 
-        searchRange->setStart(WTFMove(resultRange.end.container), resultRange.end.offset);
+        // Set the new start for the search range to be the end of the previous result range.
+        // There is no need to use VisiblePosition here: findPlainText will use TextIterator to go over visible text nodes.
+        searchRange->start = WTFMove(resultRange.end);
 
-        Node* shadowTreeRoot = searchRange->shadowRoot();
-        if (searchRange->collapsed() && shadowTreeRoot)
-            searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
+        if (searchRange->collapsed()) {
+            if (auto shadowTreeRoot = searchRange->start.container->containingShadowRoot())
+                searchRange->end = makeBoundaryPointAfterNodeContents(*shadowTreeRoot);
+        }
     } while (true);
 
     return matchCount;
@@ -3949,22 +3937,24 @@
     return plainText(*range);
 }
 
-RefPtr<Range> Editor::contextRangeForCandidateRequest() const
+Optional<SimpleRange> Editor::contextRangeForCandidateRequest() const
 {
-    const VisibleSelection& selection = m_document.selection().selection();
-    return makeRange(startOfParagraph(selection.visibleStart()), endOfParagraph(selection.visibleEnd()));
+    auto& selection = m_document.selection().selection();
+    auto start = makeBoundaryPoint(startOfParagraph(selection.visibleStart()));
+    auto end = makeBoundaryPoint(endOfParagraph(selection.visibleEnd()));
+    if (!start || !end)
+        return WTF::nullopt;
+    return { { *start, *end } };
 }
 
-RefPtr<Range> Editor::rangeForTextCheckingResult(const TextCheckingResult& result) const
+Optional<SimpleRange> Editor::rangeForTextCheckingResult(const TextCheckingResult& result) const
 {
     if (!result.range.length)
-        return nullptr;
-
-    RefPtr<Range> contextRange = contextRangeForCandidateRequest();
+        return WTF::nullopt;
+    auto contextRange = contextRangeForCandidateRequest();
     if (!contextRange)
-        return nullptr;
-
-    return createLiveRange(resolveCharacterRange(*contextRange, result.range));
+        return WTF::nullopt;
+    return resolveCharacterRange(*contextRange, result.range);
 }
 
 void Editor::scheduleEditorUIUpdate()
@@ -4234,8 +4224,8 @@
     m_isHandlingAcceptedCandidate = true;
 
     if (auto range = rangeForTextCheckingResult(acceptedCandidate)) {
-        if (shouldInsertText(acceptedCandidate.replacement, range.get(), EditorInsertAction::Typed))
-            ReplaceRangeWithTextCommand::create(range.get(), acceptedCandidate.replacement)->apply();
+        if (shouldInsertText(acceptedCandidate.replacement, range, EditorInsertAction::Typed))
+            ReplaceRangeWithTextCommand::create(createLiveRange(range), acceptedCandidate.replacement)->apply();
     } else
         insertText(acceptedCandidate.replacement, nullptr);
 
@@ -4267,16 +4257,16 @@
     m_document.selection().setShouldShowBlockCursor(m_overwriteModeEnabled);
 }
 
-RefPtr<Range> Editor::adjustedSelectionRange()
+Optional<SimpleRange> Editor::adjustedSelectionRange()
 {
-    // FIXME: Why do we need to adjust the selection to include the anchor tag it's in?
-    // Whoever wrote this code originally forgot to leave us a comment explaining the rationale.
-    RefPtr<Range> range = selectedRange();
-    Node* commonAncestor = range->commonAncestorContainer();
-    ASSERT(commonAncestor);
-    auto* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(commonAncestor), HTMLNames::aTag);
-    if (enclosingAnchor && comparePositions(firstPositionInOrBeforeNode(range->startPosition().anchorNode()), range->startPosition()) >= 0)
-        range->setStart(*enclosingAnchor, 0);
+    // FIXME: Why do we need to adjust the selection to include the anchor tag it's in? Whoever wrote this code originally forgot to leave us a comment explaining the rationale.
+    auto range = selectedRange();
+    if (range) {
+        if (auto enclosingAnchor = enclosingElementWithTag(firstPositionInNode(commonInclusiveAncestor(range->start.container, range->end.container).get()), HTMLNames::aTag)) {
+            if (comparePositions(firstPositionInOrBeforeNode(range->start.container.ptr()), createLegacyEditingPosition(range->start)) >= 0)
+                range->start = makeBoundaryPointBeforeNodeContents(*enclosingAnchor);
+        }
+    }
     return range;
 }
 
diff --git a/Source/WebCore/editing/Editor.h b/Source/WebCore/editing/Editor.h
index 111440c..a97cb42 100644
--- a/Source/WebCore/editing/Editor.h
+++ b/Source/WebCore/editing/Editor.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007, 2008, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -214,10 +214,10 @@
     WEBCORE_EXPORT void outdent();
     void transpose();
 
-    bool shouldInsertFragment(DocumentFragment&, Range*, EditorInsertAction);
-    bool shouldInsertText(const String&, Range*, EditorInsertAction) const;
-    WEBCORE_EXPORT bool shouldDeleteRange(Range*) const;
-    bool shouldApplyStyle(StyleProperties*, Range*);
+    bool shouldInsertFragment(DocumentFragment&, const Optional<SimpleRange>&, EditorInsertAction);
+    bool shouldInsertText(const String&, const Optional<SimpleRange>&, EditorInsertAction) const;
+    WEBCORE_EXPORT bool shouldDeleteRange(const Optional<SimpleRange>&) const;
+    bool shouldApplyStyle(const StyleProperties&, const SimpleRange&);
 
     void respondToChangedContents(const VisibleSelection& endingSelection);
 
@@ -323,16 +323,16 @@
     bool isSpellCheckingEnabledInFocusedNode() const;
     bool isSpellCheckingEnabledFor(Node*) const;
     WEBCORE_EXPORT void markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement);
-    void markMisspellings(const VisibleSelection&, RefPtr<Range>& firstMisspellingRange);
+    Optional<SimpleRange> markMisspellings(const VisibleSelection&); // Returns first mispelling range.
     void markBadGrammar(const VisibleSelection&);
     void markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection);
     void markAndReplaceFor(const SpellCheckRequest&, const Vector<TextCheckingResult>&);
-    WEBCORE_EXPORT void replaceRangeForSpellChecking(Range&, const String&);
+    WEBCORE_EXPORT void replaceRangeForSpellChecking(const SimpleRange&, const String&);
 
     bool isOverwriteModeEnabled() const { return m_overwriteModeEnabled; }
     WEBCORE_EXPORT void toggleOverwriteModeEnabled();
 
-    void markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType>, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange);
+    void markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType>, const Optional<SimpleRange>& spellingRange, const Optional<SimpleRange>& automaticReplacementRange, const Optional<SimpleRange>& grammarRange);
 #if PLATFORM(IOS_FAMILY)
     NO_RETURN_DUE_TO_ASSERT
 #endif
@@ -344,8 +344,8 @@
     void showSpellingGuessPanel();
     bool spellingPanelIsShowing();
 
-    bool shouldBeginEditing(Range*);
-    bool shouldEndEditing(Range*);
+    bool shouldBeginEditing(const SimpleRange&);
+    bool shouldEndEditing(const SimpleRange&);
 
     void clearUndoRedoOperations();
     bool canUndo() const;
@@ -357,7 +357,7 @@
 
     void didBeginEditing();
     void didEndEditing();
-    void willWriteSelectionToPasteboard(Range*);
+    void willWriteSelectionToPasteboard(const Optional<SimpleRange>&);
     void didWriteSelectionToPasteboard();
 
     void showFontPanel();
@@ -381,7 +381,7 @@
     WEBCORE_EXPORT void confirmComposition(const String&); // if no existing composition, replaces selection
     WEBCORE_EXPORT void cancelComposition();
     bool cancelCompositionIfSelectionIsInvalid();
-    WEBCORE_EXPORT RefPtr<Range> compositionRange() const;
+    WEBCORE_EXPORT Optional<SimpleRange> compositionRange() const;
     WEBCORE_EXPORT bool getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const;
 
     // getting international text input composition state (for use by InlineTextBox)
@@ -401,7 +401,7 @@
     WEBCORE_EXPORT void setIgnoreSelectionChanges(bool, RevealSelection shouldRevealExistingSelection = RevealSelection::Yes);
     bool ignoreSelectionChanges() const { return m_ignoreSelectionChanges; }
 
-    WEBCORE_EXPORT RefPtr<Range> rangeForPoint(const IntPoint& windowPoint);
+    WEBCORE_EXPORT Optional<SimpleRange> rangeForPoint(const IntPoint& windowPoint);
 
     void clear();
 
@@ -412,7 +412,7 @@
 
     EditingBehavior behavior() const;
 
-    RefPtr<Range> selectedRange();
+    Optional<SimpleRange> selectedRange();
 
 #if PLATFORM(IOS_FAMILY)
     WEBCORE_EXPORT void confirmMarkedText();
@@ -447,7 +447,7 @@
     String selectedTextForDataTransfer() const;
     WEBCORE_EXPORT bool findString(const String&, FindOptions);
 
-    WEBCORE_EXPORT RefPtr<Range> rangeOfString(const String&, Range*, FindOptions);
+    WEBCORE_EXPORT Optional<SimpleRange> rangeOfString(const String&, const Optional<SimpleRange>& searchRange, FindOptions);
 
     const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
     void setMark(const VisibleSelection&);
@@ -456,13 +456,13 @@
     WEBCORE_EXPORT void computeAndSetTypingStyle(StyleProperties& , EditAction = EditAction::Unspecified);
     WEBCORE_EXPORT void applyEditingStyleToBodyElement() const;
 
-    WEBCORE_EXPORT IntRect firstRectForRange(Range*) const;
+    WEBCORE_EXPORT IntRect firstRectForRange(const SimpleRange&) const;
 
     void selectionWillChange();
     void respondToChangedSelection(const VisibleSelection& oldSelection, OptionSet<FrameSelection::SetSelectionOption>);
     WEBCORE_EXPORT void updateEditorUINowIfScheduled();
     bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
-    WEBCORE_EXPORT unsigned countMatchesForText(const String&, Range*, FindOptions, unsigned limit, bool markMatches, Vector<RefPtr<Range>>*);
+    WEBCORE_EXPORT unsigned countMatchesForText(const String&, const Optional<SimpleRange>&, FindOptions, unsigned limit, bool markMatches, Vector<SimpleRange>*);
     bool markedTextMatchesAreHighlighted() const;
     WEBCORE_EXPORT void setMarkedTextMatchesAreHighlighted(bool);
 
@@ -546,8 +546,8 @@
 
     WEBCORE_EXPORT String stringForCandidateRequest() const;
     WEBCORE_EXPORT void handleAcceptedCandidate(TextCheckingResult);
-    WEBCORE_EXPORT RefPtr<Range> contextRangeForCandidateRequest() const;
-    RefPtr<Range> rangeForTextCheckingResult(const TextCheckingResult&) const;
+    WEBCORE_EXPORT Optional<SimpleRange> contextRangeForCandidateRequest() const;
+    Optional<SimpleRange> rangeForTextCheckingResult(const TextCheckingResult&) const;
     bool isHandlingAcceptedCandidate() const { return m_isHandlingAcceptedCandidate; }
 
     void setIsGettingDictionaryPopupInfo(bool b) { m_isGettingDictionaryPopupInfo = b; }
@@ -580,7 +580,7 @@
 private:
     Document& document() const { return m_document; }
 
-    bool canDeleteRange(Range*) const;
+    bool canDeleteRange(const SimpleRange&) const;
     bool canSmartReplaceWithPasteboard(Pasteboard&);
     void pasteAsPlainTextWithPasteboard(Pasteboard&);
     void pasteWithPasteboard(Pasteboard*, OptionSet<PasteOption>);
@@ -589,7 +589,7 @@
     void quoteFragmentForPasting(DocumentFragment&);
 
     void revealSelectionAfterEditingOperation(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
-    void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
+    Optional<SimpleRange> markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling);
     OptionSet<TextCheckingType> resolveTextCheckingTypeMask(const Node& rootEditableElement, OptionSet<TextCheckingType>);
 
     WEBCORE_EXPORT String selectedText(TextIteratorBehavior) const;
@@ -609,7 +609,7 @@
 
     bool unifiedTextCheckerEnabled() const;
 
-    RefPtr<Range> adjustedSelectionRange();
+    Optional<SimpleRange> adjustedSelectionRange();
 
 #if PLATFORM(COCOA)
     RefPtr<SharedBuffer> selectionInWebArchiveFormat();
diff --git a/Source/WebCore/editing/EditorCommand.cpp b/Source/WebCore/editing/EditorCommand.cpp
index d6ea426..440fcf6 100644
--- a/Source/WebCore/editing/EditorCommand.cpp
+++ b/Source/WebCore/editing/EditorCommand.cpp
@@ -176,15 +176,15 @@
 static bool expandSelectionToGranularity(Frame& frame, TextGranularity granularity)
 {
     VisibleSelection selection = frame.selection().selection();
+    auto oldRange = selection.toNormalizedRange();
     selection.expandUsingGranularity(granularity);
     auto newRange = selection.toNormalizedRange();
     if (!newRange || newRange->collapsed())
         return false;
-    auto oldRange = selection.toNormalizedRange();
     auto affinity = selection.affinity();
-    if (!frame.editor().client()->shouldChangeSelectedRange(createLiveRange(oldRange).get(), createLiveRange(newRange).get(), affinity, false))
+    if (!frame.editor().client()->shouldChangeSelectedRange(*oldRange, *newRange, affinity, false))
         return false;
-    frame.selection().setSelectedRange(createLiveRange(newRange).get(), affinity, FrameSelection::ShouldCloseTyping::Yes);
+    frame.selection().setSelectedRange(createLiveRange(*newRange).ptr(), affinity, FrameSelection::ShouldCloseTyping::Yes);
     return true;
 }
 
@@ -226,11 +226,11 @@
     return static_cast<unsigned>(Scrollbar::pageStep(height));
 }
 
-static RefPtr<Range> unionDOMRanges(Range& a, Range& b)
+static SimpleRange unionRanges(const SimpleRange& a, const SimpleRange& b)
 {
-    Range& start = a.compareBoundaryPoints(Range::START_TO_START, b).releaseReturnValue() <= 0 ? a : b;
-    Range& end = a.compareBoundaryPoints(Range::END_TO_END, b).releaseReturnValue() <= 0 ? b : a;
-    return Range::create(a.ownerDocument(), &start.startContainer(), start.startOffset(), &end.endContainer(), end.endOffset());
+    auto& start = createLiveRange(a)->compareBoundaryPoints(Range::START_TO_START, createLiveRange(b)).releaseReturnValue() <= 0 ? a : b;
+    auto& end = createLiveRange(a)->compareBoundaryPoints(Range::END_TO_END, createLiveRange(b)).releaseReturnValue() <= 0 ? b : a;
+    return { start.start, end.end };
 }
 
 // Execute command functions
@@ -354,7 +354,7 @@
     auto mark = frame.editor().mark().toNormalizedRange();
     auto& selection = frame.selection();
     if (mark && frame.editor().selectedRange()) {
-        bool selected = selection.setSelectedRange(unionDOMRanges(createLiveRange(*mark), *frame.editor().selectedRange()).get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes);
+        bool selected = selection.setSelectedRange(createLiveRange(unionRanges(*mark, *frame.editor().selectedRange())).ptr(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes);
         ASSERT(selected);
         if (!selected)
             return false;
@@ -1056,7 +1056,7 @@
         PAL::systemBeep();
         return false;
     }
-    frame.selection().setSelectedRange(unionDOMRanges(createLiveRange(*mark), *selection).get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes);
+    frame.selection().setSelectedRange(createLiveRange(unionRanges(*mark, *selection)).ptr(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes);
     return true;
 }
 
diff --git a/Source/WebCore/editing/FrameSelection.cpp b/Source/WebCore/editing/FrameSelection.cpp
index 1475fe5..52a67a8 100644
--- a/Source/WebCore/editing/FrameSelection.cpp
+++ b/Source/WebCore/editing/FrameSelection.cpp
@@ -2311,7 +2311,7 @@
     if (m_document->frame() && m_document->frame()->selectionChangeCallbacksDisabled())
         return true;
 #endif
-    return m_document->editor().client()->shouldDeleteRange(createLiveRange(selection.toNormalizedRange()).get());
+    return m_document->editor().client()->shouldDeleteRange(selection.toNormalizedRange());
 }
 
 FloatRect FrameSelection::selectionBounds(ClipToVisibleContent clipToVisibleContent) const
diff --git a/Source/WebCore/editing/cocoa/EditorCocoa.mm b/Source/WebCore/editing/cocoa/EditorCocoa.mm
index c5cbc3f..eefe8fd 100644
--- a/Source/WebCore/editing/cocoa/EditorCocoa.mm
+++ b/Source/WebCore/editing/cocoa/EditorCocoa.mm
@@ -88,14 +88,13 @@
 
 void Editor::getPasteboardTypesAndDataForAttachment(Element& element, Vector<String>& outTypes, Vector<RefPtr<SharedBuffer>>& outData)
 {
-    auto& document = element.document();
-    auto elementRange = Range::create(document, { &element, Position::PositionIsBeforeAnchor }, { &element, Position::PositionIsAfterAnchor });
-    client()->getClientPasteboardDataForRange(elementRange.ptr(), outTypes, outData);
+    auto elementRange = makeRangeSelectingNode(element);
+    client()->getClientPasteboardData(elementRange, outTypes, outData);
 
     outTypes.append(PasteboardCustomData::cocoaType());
-    outData.append(PasteboardCustomData { document.originIdentifierForPasteboard(), { } }.createSharedBuffer());
+    outData.append(PasteboardCustomData { element.document().originIdentifierForPasteboard(), { } }.createSharedBuffer());
 
-    if (auto archive = LegacyWebArchive::create(elementRange.ptr())) {
+    if (auto archive = LegacyWebArchive::create(createLiveRange(elementRange).get())) {
         if (auto webArchiveData = archive->rawDataRepresentation()) {
             outTypes.append(WebArchivePboardType);
             outData.append(SharedBuffer::create(webArchiveData.get()));
@@ -123,7 +122,7 @@
         content.dataInRTFDFormat = [string containsAttachments] ? dataInRTFDFormat(string.get()) : nullptr;
         content.dataInRTFFormat = dataInRTFFormat(string.get());
         content.dataInAttributedStringFormat = archivedDataForAttributedString(string.get());
-        client()->getClientPasteboardDataForRange(selectedRange().get(), content.clientTypes, content.clientData);
+        client()->getClientPasteboardData(selectedRange(), content.clientTypes, content.clientData);
     }
     content.dataInHTMLFormat = selectionInHTMLFormat();
     content.dataInStringFormat = stringSelectionForPasteboardWithImageAltText();
@@ -144,7 +143,7 @@
     webContent.dataInAttributedStringFormat = archivedDataForAttributedString(string.get());
     webContent.dataInHTMLFormat = selectionInHTMLFormat();
     webContent.dataInStringFormat = stringSelectionForPasteboardWithImageAltText();
-    client()->getClientPasteboardDataForRange(selectedRange().get(), webContent.clientTypes, webContent.clientData);
+    client()->getClientPasteboardData(selectedRange(), webContent.clientTypes, webContent.clientData);
 
     pasteboardWriterData.setWebContent(WTFMove(webContent));
 }
@@ -184,12 +183,12 @@
 
     if (m_document.selection().selection().isContentRichlyEditable()) {
         if (auto fragment = createFragmentAndAddResources(*m_document.frame(), attributedString)) {
-            if (shouldInsertFragment(*fragment, selectedRange().get(), EditorInsertAction::Pasted))
+            if (shouldInsertFragment(*fragment, selectedRange(), EditorInsertAction::Pasted))
                 pasteAsFragment(fragment.releaseNonNull(), false, false, mailBlockquoteHandling);
         }
     } else {
         String text = attributedString.string;
-        if (shouldInsertText(text, selectedRange().get(), EditorInsertAction::Pasted))
+        if (shouldInsertText(text, selectedRange(), EditorInsertAction::Pasted))
             pasteAsPlainText(text, false);
     }
 }
diff --git a/Source/WebCore/editing/gtk/EditorGtk.cpp b/Source/WebCore/editing/gtk/EditorGtk.cpp
index 99aa119..da7e941 100644
--- a/Source/WebCore/editing/gtk/EditorGtk.cpp
+++ b/Source/WebCore/editing/gtk/EditorGtk.cpp
@@ -50,17 +50,17 @@
 
 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption> options)
 {
-    RefPtr<Range> range = selectedRange();
+    auto range = selectedRange();
     if (!range)
         return;
 
     bool chosePlainText;
-    RefPtr<DocumentFragment> fragment = webContentFromPasteboard(*pasteboard, *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
+    auto fragment = webContentFromPasteboard(*pasteboard, *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
 
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
 
-    if (fragment && shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Pasted))
+    if (fragment && shouldInsertFragment(*fragment, *range, EditorInsertAction::Pasted))
         pasteAsFragment(fragment.releaseNonNull(), canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote);
 }
 
diff --git a/Source/WebCore/editing/ios/EditorIOS.mm b/Source/WebCore/editing/ios/EditorIOS.mm
index 312325f..6c25479 100644
--- a/Source/WebCore/editing/ios/EditorIOS.mm
+++ b/Source/WebCore/editing/ios/EditorIOS.mm
@@ -206,30 +206,26 @@
     pasteboardImage.resourceMIMEType = pasteboard.resourceMIMEType(cachedImage->response().mimeType());
     pasteboardImage.resourceData = cachedImage->resourceBuffer();
 
-    if (!pasteboard.isStatic()) {
-        Position beforeImagePosition(&imageElement, Position::PositionIsBeforeAnchor);
-        Position afterImagePosition(&imageElement, Position::PositionIsAfterAnchor);
-        auto imageRange = Range::create(imageElement.document(), beforeImagePosition, afterImagePosition);
-        client()->getClientPasteboardDataForRange(imageRange.ptr(), pasteboardImage.clientTypes, pasteboardImage.clientData);
-    }
+    if (!pasteboard.isStatic())
+        client()->getClientPasteboardData(makeRangeSelectingNode(imageElement), pasteboardImage.clientTypes, pasteboardImage.clientData);
 
     pasteboard.write(pasteboardImage);
 }
 
 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption> options)
 {
-    RefPtr<Range> range = selectedRange();
+    auto range = selectedRange();
     bool allowPlainText = options.contains(PasteOption::AllowPlainText);
     WebContentReader reader(*m_document.frame(), *range, allowPlainText);
     int numberOfPasteboardItems = client()->getPasteboardItemsCount();
     for (int i = 0; i < numberOfPasteboardItems; ++i) {
-        RefPtr<DocumentFragment> fragment = client()->documentFragmentFromDelegate(i);
+        auto fragment = client()->documentFragmentFromDelegate(i);
         if (!fragment)
             continue;
         reader.addFragment(fragment.releaseNonNull());
     }
 
-    RefPtr<DocumentFragment> fragment = reader.fragment;
+    auto fragment = WTFMove(reader.fragment);
     if (!fragment) {
         bool chosePlainTextIgnored;
         fragment = webContentFromPasteboard(*pasteboard, *range, allowPlainText, chosePlainTextIgnored);
@@ -238,7 +234,7 @@
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
 
-    if (fragment && shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Pasted))
+    if (fragment && shouldInsertFragment(*fragment, range, EditorInsertAction::Pasted))
         pasteAsFragment(fragment.releaseNonNull(), canSmartReplaceWithPasteboard(*pasteboard), false, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote);
 }
 
diff --git a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp
index 12fd6a4..0b7c262 100644
--- a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp
+++ b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp
@@ -37,7 +37,7 @@
 
 namespace WebCore {
 
-static RefPtr<DocumentFragment> createFragmentFromPasteboardData(Pasteboard& pasteboard, Frame& frame, Range& range, bool allowPlainText, bool& chosePlainText)
+static RefPtr<DocumentFragment> createFragmentFromPasteboardData(Pasteboard& pasteboard, Frame& frame, const SimpleRange& range, bool allowPlainText, bool& chosePlainText)
 {
     chosePlainText = false;
 
@@ -47,8 +47,7 @@
 
     if (types.contains("text/html;charset=utf-8") && frame.document()) {
         String markup = pasteboard.readString("text/html;charset=utf-8");
-        if (RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(*frame.document(), markup, emptyString(), DisallowScriptingAndPluginContent))
-            return fragment;
+        return createFragmentFromMarkup(*frame.document(), markup, emptyString(), DisallowScriptingAndPluginContent);
     }
 
     if (!allowPlainText)
@@ -56,8 +55,7 @@
 
     if (types.contains("text/plain;charset=utf-8")) {
         chosePlainText = true;
-        if (RefPtr<DocumentFragment> fragment = createFragmentFromText(range, pasteboard.readString("text/plain;charset=utf-8")))
-            return fragment;
+        return createFragmentFromText(createLiveRange(range).get(), pasteboard.readString("text/plain;charset=utf-8"));
     }
 
     return nullptr;
@@ -79,17 +77,17 @@
 
 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption> options)
 {
-    RefPtr<Range> range = selectedRange();
+    auto range = selectedRange();
     if (!range)
         return;
 
     bool chosePlainText;
-    RefPtr<DocumentFragment> fragment = createFragmentFromPasteboardData(*pasteboard, *m_document.frame(), *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
+    auto fragment = createFragmentFromPasteboardData(*pasteboard, *m_document.frame(), *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
 
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
 
-    if (fragment && shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Pasted))
+    if (fragment && shouldInsertFragment(*fragment, *range, EditorInsertAction::Pasted))
         pasteAsFragment(*fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote);
 }
 
diff --git a/Source/WebCore/editing/mac/EditorMac.mm b/Source/WebCore/editing/mac/EditorMac.mm
index 1cd8c39..ba31c18 100644
--- a/Source/WebCore/editing/mac/EditorMac.mm
+++ b/Source/WebCore/editing/mac/EditorMac.mm
@@ -80,7 +80,7 @@
 
 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption> options)
 {
-    RefPtr<Range> range = selectedRange();
+    auto range = selectedRange();
 
     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     // FIXME: How can this hard-coded pasteboard name be right, given that the passed-in pasteboard has a name?
@@ -93,7 +93,7 @@
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
 
-    if (fragment && shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Pasted))
+    if (fragment && shouldInsertFragment(*fragment, range, EditorInsertAction::Pasted))
         pasteAsFragment(fragment.releaseNonNull(), canSmartReplaceWithPasteboard(*pasteboard), false, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote );
 
     client()->setInsertionPasteboard(String());
@@ -159,7 +159,7 @@
     bool chosePlainText;
     if (auto fragment = webContentFromPasteboard(pasteboard, range, true, chosePlainText)) {
         maybeCopyNodeAttributesToFragment(*node, *fragment);
-        if (shouldInsertFragment(*fragment, createLiveRange(range).ptr(), EditorInsertAction::Pasted))
+        if (shouldInsertFragment(*fragment, range, EditorInsertAction::Pasted))
             pasteAsFragment(fragment.releaseNonNull(), canSmartReplaceWithPasteboard(pasteboard), false, MailBlockquoteHandling::IgnoreBlockquote);
     }
 
@@ -176,11 +176,9 @@
 
 RefPtr<SharedBuffer> Editor::dataSelectionForPasteboard(const String& pasteboardType)
 {
-    // FIXME: The interface to this function is awkward. We'd probably be better off with three separate functions.
-    // As of this writing, this is only used in WebKit2 to implement the method -[WKView writeSelectionToPasteboard:types:],
-    // which is only used to support OS X services.
+    // FIXME: The interface to this function is awkward. We'd probably be better off with three separate functions. As of this writing, this is only used in WebKit2 to implement the method -[WKView writeSelectionToPasteboard:types:], which is only used to support OS X services.
 
-    // FIXME: Does this function really need to use adjustedSelectionRange()? Because writeSelectionToPasteboard() just uses selectedRange().
+    // FIXME: Does this function really need to use adjustedSelectionRange()? Because writeSelectionToPasteboard() just uses selectedRange(). This is the only function in WebKit that uses adjustedSelectionRange.
     if (!canCopy())
         return nullptr;
 
diff --git a/Source/WebCore/editing/win/EditorWin.cpp b/Source/WebCore/editing/win/EditorWin.cpp
index c796bfa..93ddeaf 100644
--- a/Source/WebCore/editing/win/EditorWin.cpp
+++ b/Source/WebCore/editing/win/EditorWin.cpp
@@ -37,17 +37,17 @@
 
 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet<PasteOption> options)
 {
-    RefPtr<Range> range = selectedRange();
+    auto range = selectedRange();
     if (!range)
         return;
 
     bool chosePlainText;
-    RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(*m_document.frame(), *range, options.contains(PasteOption::AllowPlainText), chosePlainText);
+    auto fragment = pasteboard->documentFragment(*m_document.frame(), createLiveRange(*range), options.contains(PasteOption::AllowPlainText), chosePlainText);
 
     if (fragment && options.contains(PasteOption::AsQuotation))
         quoteFragmentForPasting(*fragment);
 
-    if (fragment && shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Pasted))
+    if (fragment && shouldInsertFragment(*fragment, *range, EditorInsertAction::Pasted))
         pasteAsFragment(fragment.releaseNonNull(), canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote);
 }