Replace more uses of live ranges with SimpleRange
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Apr 2020 15:05:00 +0000 (15:05 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Apr 2020 15:05:00 +0000 (15:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=211058

Reviewed by Antti Koivisto.

Source/WebCore:

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::textUnderElement const): Use SimpleRange.

* dom/BoundaryPoint.h: Moved makeBoundaryPointAfterNodeContents here so it
can be used more places.

* dom/Node.cpp:
(WebCore::commonInclusiveAncestor): Moved the commonAncestorContainer function
here from Range, decided to use the "inclusive ancestor" naming from the
DOM specification, and used RefPtr for the result since it's part of our modern
safer design to always use smart pointers for return values.
* dom/Node.h: Added commonInclusiveAncestor.

* dom/Position.cpp:
(WebCore::commonShadowIncludingAncestor): Call commonInclusiveAncestor.

* dom/Range.cpp:
(WebCore::Range::commonAncestorContainer): Deleted.
(WebCore::Range::isPointInRange): Call commonInclusiveAncestor.
(WebCore::Range::comparePoint const): Ditto.
(WebCore::Range::compareBoundaryPoints): Ditto.
(WebCore::Range::collectSelectionRectsWithoutUnionInteriorLines const): Ditto.
* dom/Range.h:
(WebCore::Range::commonAncestorContainer const): Call commonInclusiveAncestor.

* dom/SimpleRange.cpp:
(WebCore::makeBoundaryPointAfterNodeContents): Moved to BoundaryPoint.h.

* editing/AlternativeTextController.cpp:
(WebCore::AlternativeTextController::respondToUnappliedSpellCorrection): Use
SimpleRange instead of live range.
(WebCore::AlternativeTextController::respondToUnappliedEditing): Ditto.
(WebCore::AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand): Ditto.
(WebCore::AlternativeTextController::processMarkersOnTextToBeReplacedByResult): Ditto.

* editing/ChangeListTypeCommand.cpp:
(WebCore::listConversionTypeForSelection): use commonInclusiveAncestor.

* editing/Editing.cpp:
(WebCore::isNodeVisiblyContainedWithin): Take a SimpleRange argument.
* editing/Editing.h: Updated for the above.

* editing/Editor.cpp:
(WebCore::Editor::addRangeToKillRing): Take a SimpleRange argument.
(WebCore::Editor::shouldDetectTelephoneNumbers const): Made this const and
tweaked coding style a bit.
(WebCore::scanForTelephoneNumbers): Moved this, made it a non-member function,
renamed from scanRangeForTelephoneNumbers, use SimpleRange.
(WebCore::extendSelection): Added. Factored out some logic from the function below.
(WebCore::Editor::scanSelectionForTelephoneNumbers): Use SimpleRange. Removed
some unnecessary code that subtracts 1 and then adds 1 again.
* editing/Editor.h: Updated for the above.

* editing/TextManipulationController.cpp:
(WebCore::TextManipulationController::replace): Use commonInclusiveAncestor.

* editing/VisibleSelection.cpp:
(WebCore::makeSearchRange): Return a SimpleRange.
(WebCore::VisibleSelection::appendTrailingWhitespace): Use SimpleRange.

* editing/WebContentReader.h: Use SimpleRange instead of a live range.

* editing/cocoa/DataDetection.h: Use a struct, DetectedItem, for the return value
from the detection functions. Also changed DataDetectorTypes to an enum class so
it can be forward-declared instead of having to include this header.
* editing/cocoa/DataDetection.mm:
(WebCore::detectItem): Renamed from detectItemAtPositionWithRange. Return the
DetectedItem struct, with a SimpleRange rather than an out argument live range.
(WebCore::DataDetection::detectItemAroundHitTestResult): Ditto.
(WebCore::contains): Added a helper function for testing bits in the
DataDetectorType enum. Later we can make this better using OptionSet.
(WebCore::constructURLStringForResult): Refactored a bit, updated for the new
DataDetectorTypes enum class, and to use CFEqual instead of CFStringCompare.
(WebCore::DataDetection::detectContentInRange): Ditto.

* editing/cocoa/EditorCocoa.mm:
(WebCore::Editor::webContentFromPasteboard): Use SimpleRange.
* editing/cocoa/WebContentReaderCocoa.mm:
(WebCore::WebContentReader::readPlainText): Updated since context is SimpleRange.
* editing/gtk/EditorGtk.cpp:
(WebCore::createFragmentFromPasteboardData): Use SimpleRange.
(WebCore::Editor::webContentFromPasteboard): Use SimpleRange.
* editing/win/EditorWin.cpp:
(WebCore::Editor::webContentFromPasteboard): Use SimpleRange.
* editing/mac/EditorMac.mm:
(WebCore::Editor::replaceNodeFromPasteboard): Use SimpleRange.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::checkLoadCompleteForThisFrame): Use SimpleRange.
* page/EventHandler.cpp:
(WebCore::targetNodeForClickEvent): Use commonInclusiveAncestor. Also updated
to return a RefPtr.
(WebCore::EventHandler::handleMouseReleaseEvent): Updated for the above.

* page/Settings.yaml: Changed the default for DataDetectorTypes to be the empty
string rather than a named constant.
* page/SettingsBase.h: Forward-declare DataDetectorTypes instead of including
the DataDetection.h header.

* page/TextIndicator.cpp:
(WebCore::TextIndicator::createWithRange): Take a SimpleRange.
(WebCore::TextIndicator::createWithSelectionInFrame): Ditto.
(WebCore::hasNonInlineOrReplacedElements): Ditto.
(WebCore::selectionRects): Ditto. Also renamed from getSelectionRectsForRange.
(WebCore::styleContainsComplexBackground): Tweaked implementation.
(WebCore::estimatedTextColorsForRange): Take a SimpleRange.
(WebCore::absoluteBoundingRectForRange): Ditto.
(WebCore::estimatedBackgroundColorForRange): Ditto.
(WebCore::containsOnlyWhiteSpaceText): Ditto.
(WebCore::initializeIndicator): Ditto.
* page/TextIndicator.h: Updated for the above.

* page/mac/ServicesOverlayController.h: Use SimpleRange instead of a live
range for highlights.
* page/mac/ServicesOverlayController.mm:
(WebCore::ServicesOverlayController::Highlight::createForSelection): Take SimpleRange.
(WebCore::ServicesOverlayController::Highlight::createForTelephoneNumber): Ditto.
(WebCore::ServicesOverlayController::Highlight::Highlight): Ditto.
(WebCore::ServicesOverlayController::buildPhoneNumberHighlights): Ditto.
(WebCore::ServicesOverlayController::buildSelectionHighlight): Ditto.
(WebCore::ServicesOverlayController::telephoneNumberRangesForFocusedFrame): Ditto.
(WebCore::ServicesOverlayController::highlightsAreEquivalent): Ditto.
(WebCore::ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight): Ditto.
(WebCore::ServicesOverlayController::handleClick): Ditto.

* platform/ios/DragImageIOS.mm:
(WebCore::createDragImageForLink): Use SimpleRange.
(WebCore::createDragImageForSelection): Tweaked a bit.

Source/WebKit:

* Shared/API/Cocoa/WKDataDetectorTypesInternal.h:
(fromWKDataDetectorTypes): Updated since DataDetectorTypes
is now an enum class. Also got rid of special "none" and "all" values.

* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInRangeHandle.mm:
(-[WKWebProcessPlugInRangeHandle detectDataWithTypes:context:]): Updated
since DataDetection now takes a SimpleRange.

* WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
(WebKit::ViewGestureGeometryCollector::computeTextLegibilityScales):
Use SimpleRange.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::detectDataInAllFrames): Ditto.

* WebProcess/WebPage/WebPage.h: Removed unneeded include of DataDetection.h.

* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::performImmediateActionHitTestAtLocation): Use SimpleRange.

Source/WebKitLegacy/mac:

* DOM/DOM.mm:
(-[DOMNode getPreviewSnapshotImage:andRects:]): Use SimpleRange.
* WebCoreSupport/WebContextMenuClient.mm:
(WebContextMenuClient::imageForCurrentSharingServicePickerItem): Ditto.

* WebView/WebImmediateActionController.mm:
(-[WebImmediateActionController _animationControllerForDataDetectedText]):
Updated to use DetectedItem and SimpleRange.
(+[WebImmediateActionController _dictionaryPopupInfoForRange:inFrame:withLookupOptions:indicatorOptions:transition:]):
Ditto.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@260753 268f45cc-cd09-0410-ab3c-d52691b4dbfc

45 files changed:
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/dom/BoundaryPoint.h
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/Position.cpp
Source/WebCore/dom/Range.cpp
Source/WebCore/dom/Range.h
Source/WebCore/dom/SimpleRange.cpp
Source/WebCore/editing/AlternativeTextController.cpp
Source/WebCore/editing/ChangeListTypeCommand.cpp
Source/WebCore/editing/Editing.cpp
Source/WebCore/editing/Editing.h
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/editing/TextManipulationController.cpp
Source/WebCore/editing/VisibleSelection.cpp
Source/WebCore/editing/WebContentReader.h
Source/WebCore/editing/cocoa/DataDetection.h
Source/WebCore/editing/cocoa/DataDetection.mm
Source/WebCore/editing/cocoa/EditorCocoa.mm
Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm
Source/WebCore/editing/gtk/EditorGtk.cpp
Source/WebCore/editing/mac/EditorMac.mm
Source/WebCore/editing/win/EditorWin.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/Settings.yaml
Source/WebCore/page/SettingsBase.h
Source/WebCore/page/TextIndicator.cpp
Source/WebCore/page/TextIndicator.h
Source/WebCore/page/mac/ServicesOverlayController.h
Source/WebCore/page/mac/ServicesOverlayController.mm
Source/WebCore/platform/ios/DragImageIOS.mm
Source/WebKit/ChangeLog
Source/WebKit/Shared/API/Cocoa/WKDataDetectorTypesInternal.h
Source/WebKit/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInRangeHandle.mm
Source/WebKit/WebProcess/WebPage/ViewGestureGeometryCollector.cpp
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/DOM/DOM.mm
Source/WebKitLegacy/mac/WebCoreSupport/WebContextMenuClient.mm
Source/WebKitLegacy/mac/WebView/WebImmediateActionController.mm

index 4ddcc34..7574356 100644 (file)
@@ -1,3 +1,138 @@
+2020-04-26  Darin Adler  <darin@apple.com>
+
+        Replace more uses of live ranges with SimpleRange
+        https://bugs.webkit.org/show_bug.cgi?id=211058
+
+        Reviewed by Antti Koivisto.
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::textUnderElement const): Use SimpleRange.
+
+        * dom/BoundaryPoint.h: Moved makeBoundaryPointAfterNodeContents here so it
+        can be used more places.
+
+        * dom/Node.cpp:
+        (WebCore::commonInclusiveAncestor): Moved the commonAncestorContainer function
+        here from Range, decided to use the "inclusive ancestor" naming from the
+        DOM specification, and used RefPtr for the result since it's part of our modern
+        safer design to always use smart pointers for return values.
+        * dom/Node.h: Added commonInclusiveAncestor.
+
+        * dom/Position.cpp:
+        (WebCore::commonShadowIncludingAncestor): Call commonInclusiveAncestor.
+
+        * dom/Range.cpp:
+        (WebCore::Range::commonAncestorContainer): Deleted.
+        (WebCore::Range::isPointInRange): Call commonInclusiveAncestor.
+        (WebCore::Range::comparePoint const): Ditto.
+        (WebCore::Range::compareBoundaryPoints): Ditto.
+        (WebCore::Range::collectSelectionRectsWithoutUnionInteriorLines const): Ditto.
+        * dom/Range.h:
+        (WebCore::Range::commonAncestorContainer const): Call commonInclusiveAncestor.
+
+        * dom/SimpleRange.cpp:
+        (WebCore::makeBoundaryPointAfterNodeContents): Moved to BoundaryPoint.h.
+
+        * editing/AlternativeTextController.cpp:
+        (WebCore::AlternativeTextController::respondToUnappliedSpellCorrection): Use
+        SimpleRange instead of live range.
+        (WebCore::AlternativeTextController::respondToUnappliedEditing): Ditto.
+        (WebCore::AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand): Ditto.
+        (WebCore::AlternativeTextController::processMarkersOnTextToBeReplacedByResult): Ditto.
+
+        * editing/ChangeListTypeCommand.cpp:
+        (WebCore::listConversionTypeForSelection): use commonInclusiveAncestor.
+
+        * editing/Editing.cpp:
+        (WebCore::isNodeVisiblyContainedWithin): Take a SimpleRange argument.
+        * editing/Editing.h: Updated for the above.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::addRangeToKillRing): Take a SimpleRange argument.
+        (WebCore::Editor::shouldDetectTelephoneNumbers const): Made this const and
+        tweaked coding style a bit.
+        (WebCore::scanForTelephoneNumbers): Moved this, made it a non-member function,
+        renamed from scanRangeForTelephoneNumbers, use SimpleRange.
+        (WebCore::extendSelection): Added. Factored out some logic from the function below.
+        (WebCore::Editor::scanSelectionForTelephoneNumbers): Use SimpleRange. Removed
+        some unnecessary code that subtracts 1 and then adds 1 again.
+        * editing/Editor.h: Updated for the above.
+
+        * editing/TextManipulationController.cpp:
+        (WebCore::TextManipulationController::replace): Use commonInclusiveAncestor.
+
+        * editing/VisibleSelection.cpp:
+        (WebCore::makeSearchRange): Return a SimpleRange.
+        (WebCore::VisibleSelection::appendTrailingWhitespace): Use SimpleRange.
+
+        * editing/WebContentReader.h: Use SimpleRange instead of a live range.
+
+        * editing/cocoa/DataDetection.h: Use a struct, DetectedItem, for the return value
+        from the detection functions. Also changed DataDetectorTypes to an enum class so
+        it can be forward-declared instead of having to include this header.
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::detectItem): Renamed from detectItemAtPositionWithRange. Return the
+        DetectedItem struct, with a SimpleRange rather than an out argument live range.
+        (WebCore::DataDetection::detectItemAroundHitTestResult): Ditto.
+        (WebCore::contains): Added a helper function for testing bits in the
+        DataDetectorType enum. Later we can make this better using OptionSet.
+        (WebCore::constructURLStringForResult): Refactored a bit, updated for the new
+        DataDetectorTypes enum class, and to use CFEqual instead of CFStringCompare.
+        (WebCore::DataDetection::detectContentInRange): Ditto.
+
+        * editing/cocoa/EditorCocoa.mm:
+        (WebCore::Editor::webContentFromPasteboard): Use SimpleRange.
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::WebContentReader::readPlainText): Updated since context is SimpleRange.
+        * editing/gtk/EditorGtk.cpp:
+        (WebCore::createFragmentFromPasteboardData): Use SimpleRange.
+        (WebCore::Editor::webContentFromPasteboard): Use SimpleRange.
+        * editing/win/EditorWin.cpp:
+        (WebCore::Editor::webContentFromPasteboard): Use SimpleRange.
+        * editing/mac/EditorMac.mm:
+        (WebCore::Editor::replaceNodeFromPasteboard): Use SimpleRange.
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::checkLoadCompleteForThisFrame): Use SimpleRange.
+        * page/EventHandler.cpp:
+        (WebCore::targetNodeForClickEvent): Use commonInclusiveAncestor. Also updated
+        to return a RefPtr.
+        (WebCore::EventHandler::handleMouseReleaseEvent): Updated for the above.
+
+        * page/Settings.yaml: Changed the default for DataDetectorTypes to be the empty
+        string rather than a named constant.
+        * page/SettingsBase.h: Forward-declare DataDetectorTypes instead of including
+        the DataDetection.h header.
+
+        * page/TextIndicator.cpp:
+        (WebCore::TextIndicator::createWithRange): Take a SimpleRange.
+        (WebCore::TextIndicator::createWithSelectionInFrame): Ditto.
+        (WebCore::hasNonInlineOrReplacedElements): Ditto.
+        (WebCore::selectionRects): Ditto. Also renamed from getSelectionRectsForRange.
+        (WebCore::styleContainsComplexBackground): Tweaked implementation.
+        (WebCore::estimatedTextColorsForRange): Take a SimpleRange.
+        (WebCore::absoluteBoundingRectForRange): Ditto.
+        (WebCore::estimatedBackgroundColorForRange): Ditto.
+        (WebCore::containsOnlyWhiteSpaceText): Ditto.
+        (WebCore::initializeIndicator): Ditto.
+        * page/TextIndicator.h: Updated for the above.
+
+        * page/mac/ServicesOverlayController.h: Use SimpleRange instead of a live
+        range for highlights.
+        * page/mac/ServicesOverlayController.mm:
+        (WebCore::ServicesOverlayController::Highlight::createForSelection): Take SimpleRange.
+        (WebCore::ServicesOverlayController::Highlight::createForTelephoneNumber): Ditto.
+        (WebCore::ServicesOverlayController::Highlight::Highlight): Ditto.
+        (WebCore::ServicesOverlayController::buildPhoneNumberHighlights): Ditto.
+        (WebCore::ServicesOverlayController::buildSelectionHighlight): Ditto.
+        (WebCore::ServicesOverlayController::telephoneNumberRangesForFocusedFrame): Ditto.
+        (WebCore::ServicesOverlayController::highlightsAreEquivalent): Ditto.
+        (WebCore::ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight): Ditto.
+        (WebCore::ServicesOverlayController::handleClick): Ditto.
+
+        * platform/ios/DragImageIOS.mm:
+        (WebCore::createDragImageForLink): Use SimpleRange.
+        (WebCore::createDragImageForSelection): Tweaked a bit.
+
 2020-04-27  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK4] Make it possible to build with GTK4 without errors
index b347d79..02c7570 100644 (file)
@@ -633,10 +633,10 @@ String AccessibilityRenderObject::textUnderElement(AccessibilityTextUnderElement
         // If possible, use a text iterator to get the text, so that whitespace
         // is handled consistently.
         Document* nodeDocument = nullptr;
-        RefPtr<Range> textRange;
+        Optional<SimpleRange> textRange;
         if (Node* node = m_renderer->node()) {
             nodeDocument = &node->document();
-            textRange = rangeOfContents(*node);
+            textRange = makeRangeSelectingNodeContents(*node);
         } else {
             // For anonymous blocks, we work around not having a direct node to create a range from
             // defining one based in the two external positions defining the boundaries of the subtree.
@@ -650,7 +650,7 @@ String AccessibilityRenderObject::textUnderElement(AccessibilityTextUnderElement
                 Position endPosition = positionInParentAfterNode(lastChildRenderer->node());
 
                 nodeDocument = &firstNodeInBlock->document();
-                textRange = Range::create(*nodeDocument, startPosition, endPosition);
+                textRange = { { *makeBoundaryPoint(startPosition), *makeBoundaryPoint(endPosition) } };
             }
         }
 
index 5cbbfdc..4b22a31 100644 (file)
@@ -47,6 +47,7 @@ struct BoundaryPoint {
 bool operator==(const BoundaryPoint&, const BoundaryPoint&);
 
 BoundaryPoint makeBoundaryPointBeforeNodeContents(Node&);
+BoundaryPoint makeBoundaryPointAfterNodeContents(Node&);
 
 inline BoundaryPoint::BoundaryPoint(Ref<Node>&& container, unsigned offset)
     : container(WTFMove(container))
@@ -82,4 +83,9 @@ inline BoundaryPoint makeBoundaryPointBeforeNodeContents(Node& node)
     return { node, 0 };
 }
 
+inline BoundaryPoint makeBoundaryPointAfterNodeContents(Node& node)
+{
+    return { node, node.length() };
+}
+
 }
index 8e58d0e..78f7f55 100644 (file)
@@ -2612,6 +2612,17 @@ void* Node::opaqueRootSlow() const
     return const_cast<void*>(static_cast<const void*>(node));
 }
 
+RefPtr<Node> commonInclusiveAncestor(Node& a, Node& b)
+{
+    for (auto ancestorA = &a; ancestorA; ancestorA = ancestorA->parentNode()) {
+        for (auto ancestorB = &b; ancestorB; ancestorB = ancestorB->parentNode()) {
+            if (ancestorA == ancestorB)
+                return ancestorA;
+        }
+    }
+    return nullptr;
+}
+
 TextStream& operator<<(TextStream& ts, const Node& node)
 {
     ts << "node " << &node << " " << node.debugDescription();
index e2b3061..eaaa358 100644 (file)
@@ -670,6 +670,8 @@ private:
     std::unique_ptr<NodeRareData, NodeRareDataDeleter> m_rareData;
 };
 
+WEBCORE_EXPORT RefPtr<Node> commonInclusiveAncestor(Node&, Node&);
+
 #if ASSERT_ENABLED
 
 inline void adopted(Node* node)
index bcf6904..6745b19 100644 (file)
@@ -1570,7 +1570,7 @@ RefPtr<Node> commonShadowIncludingAncestor(const Position& a, const Position& b)
     ASSERT(nodeA);
     auto* nodeB = commonScope->ancestorNodeInThisScope(b.containerNode());
     ASSERT(nodeB);
-    return Range::commonAncestorContainer(nodeA, nodeB);
+    return commonInclusiveAncestor(*nodeA, *nodeB);
 }
 
 Position positionInParentBeforeNode(Node* node)
index 64a8aa8..d5bde0a 100644 (file)
@@ -143,17 +143,6 @@ void Range::setDocument(Document& document)
     m_ownerDocument->attachRange(*this);
 }
 
-Node* Range::commonAncestorContainer(Node* containerA, Node* containerB)
-{
-    for (Node* parentA = containerA; parentA; parentA = parentA->parentNode()) {
-        for (Node* parentB = containerB; parentB; parentB = parentB->parentNode()) {
-            if (parentA == parentB)
-                return parentA;
-        }
-    }
-    return nullptr;
-}
-
 static inline bool checkForDifferentRootContainer(const RangeBoundaryPoint& start, const RangeBoundaryPoint& end)
 {
     Node* endRootContainer = end.container();
@@ -239,7 +228,7 @@ ExceptionOr<bool> Range::isPointInRange(Node& refNode, unsigned offset)
     if (checkNodeResult.hasException()) {
         // DOM4 spec requires us to check whether refNode and start container have the same root first
         // but we do it in the reverse order to avoid O(n) operation here in common case.
-        if (!commonAncestorContainer(&refNode, &startContainer()))
+        if (!commonInclusiveAncestor(refNode, startContainer()))
             return false;
         return checkNodeResult.releaseException();
     }
@@ -263,7 +252,7 @@ ExceptionOr<short> Range::comparePoint(Node& refNode, unsigned offset) const
     if (checkNodeResult.hasException()) {
         // DOM4 spec requires us to check whether refNode and start container have the same root first
         // but we do it in the reverse order to avoid O(n) operation here in common case.
-        if (!refNode.isConnected() && !commonAncestorContainer(&refNode, &startContainer()))
+        if (!refNode.isConnected() && !commonInclusiveAncestor(refNode, startContainer()))
             return Exception { WrongDocumentError };
         return checkNodeResult.releaseException();
     }
@@ -421,19 +410,19 @@ ExceptionOr<short> Range::compareBoundaryPoints(Node* containerA, unsigned offse
 
     // case 4: containers A & B are siblings, or children of siblings
     // ### we need to do a traversal here instead
-    auto* commonAncestor = commonAncestorContainer(containerA, containerB);
+    auto commonAncestor = commonInclusiveAncestor(*containerA, *containerB);
     if (!commonAncestor)
         return Exception { WrongDocumentError };
     Node* childA = containerA;
     while (childA && childA->parentNode() != commonAncestor)
         childA = childA->parentNode();
     if (!childA)
-        childA = commonAncestor;
+        childA = commonAncestor.get();
     Node* childB = containerB;
     while (childB && childB->parentNode() != commonAncestor)
         childB = childB->parentNode();
     if (!childB)
-        childB = commonAncestor;
+        childB = commonAncestor.get();
 
     if (childA == childB)
         return 0; // A is equal to B
@@ -1290,10 +1279,10 @@ int Range::collectSelectionRectsWithoutUnionInteriorLines(Vector<SelectionRect>&
         }
     }
 
-    // The range could span over nodes with different writing modes.
+    // The range could span nodes with different writing modes.
     // If this is the case, we use the writing mode of the common ancestor.
     if (containsDifferentWritingModes) {
-        if (Node* ancestor = commonAncestorContainer(&startContainer, &endContainer))
+        if (auto ancestor = commonInclusiveAncestor(startContainer, endContainer))
             hasFlippedWritingMode = ancestor->renderer()->style().isFlippedBlocksWritingMode();
     }
 
index 82c3265..8a26ab5 100644 (file)
@@ -60,8 +60,7 @@ public:
     unsigned endOffset() const { return m_end.offset(); }
     bool collapsed() const { return m_start == m_end; }
 
-    Node* commonAncestorContainer() const { return commonAncestorContainer(&startContainer(), &endContainer()); }
-    WEBCORE_EXPORT static Node* commonAncestorContainer(Node* containerA, Node* containerB);
+    Node* commonAncestorContainer() const { return commonInclusiveAncestor(startContainer(), endContainer()).get(); }
     WEBCORE_EXPORT ExceptionOr<void> setStart(Ref<Node>&& container, unsigned offset);
     WEBCORE_EXPORT ExceptionOr<void> setEnd(Ref<Node>&& container, unsigned offset);
     WEBCORE_EXPORT void collapse(bool toStart);
index 9ab1360..9240c34 100644 (file)
@@ -64,11 +64,6 @@ Optional<SimpleRange> makeRangeSelectingNode(Node& node)
     return SimpleRange { { *parent, offset }, { *parent, offset + 1 } };
 }
 
-static BoundaryPoint makeBoundaryPointAfterNodeContents(Node& node)
-{
-    return { node, node.length() };
-}
-
 SimpleRange makeRangeSelectingNodeContents(Node& node)
 {
     return { makeBoundaryPointBeforeNodeContents(node), makeBoundaryPointAfterNodeContents(node) };
index 5af2c60..3bd658d 100644 (file)
@@ -217,18 +217,20 @@ bool AlternativeTextController::applyAutocorrectionBeforeTypingIfAppropriate()
 
 void AlternativeTextController::respondToUnappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
 {
-    if (AlternativeTextClient* client = alternativeTextClient())
+    if (auto client = alternativeTextClient())
         client->recordAutocorrectionResponse(AutocorrectionResponse::Reverted, corrected, correction);
 
     Ref<Frame> protector(m_frame);
     m_frame.document()->updateLayout();
-    m_frame.selection().setSelection(selectionOfCorrected, FrameSelection::defaultSetSelectionOptions() | FrameSelection::SpellCorrectionTriggered);
-    auto range = Range::create(*m_frame.document(), m_frame.selection().selection().start(), m_frame.selection().selection().end());
 
+    m_frame.selection().setSelection(selectionOfCorrected, FrameSelection::defaultSetSelectionOptions() | FrameSelection::SpellCorrectionTriggered);
+    auto range = m_frame.selection().selection().firstRange();
+    if (!range)
+        return;
     auto& markers = m_frame.document()->markers();
-    markers.removeMarkers(range, OptionSet<DocumentMarker::MarkerType> { DocumentMarker::Spelling, DocumentMarker::Autocorrected }, DocumentMarkerController::RemovePartiallyOverlappingMarker);
-    markers.addMarker(range, DocumentMarker::Replacement);
-    markers.addMarker(range, DocumentMarker::SpellCheckingExemption);
+    markers.removeMarkers(*range, OptionSet<DocumentMarker::MarkerType> { DocumentMarker::Spelling, DocumentMarker::Autocorrected }, DocumentMarkerController::RemovePartiallyOverlappingMarker);
+    markers.addMarker(*range, DocumentMarker::Replacement);
+    markers.addMarker(*range, DocumentMarker::SpellCheckingExemption);
 }
 
 void AlternativeTextController::timerFired()
@@ -395,10 +397,12 @@ void AlternativeTextController::respondToUnappliedEditing(EditCommandComposition
 {
     if (!command->wasCreateLinkCommand())
         return;
-    auto range = Range::create(*m_frame.document(), command->startingSelection().start(), command->startingSelection().end());
+    auto range = command->startingSelection().firstRange();
+    if (!range)
+        return;
     auto& markers = m_frame.document()->markers();
-    markers.addMarker(range, DocumentMarker::Replacement);
-    markers.addMarker(range, DocumentMarker::SpellCheckingExemption);
+    markers.addMarker(*range, DocumentMarker::Replacement);
+    markers.addMarker(*range, DocumentMarker::SpellCheckingExemption);
 }
 
 EditorClient* AlternativeTextController::editorClient()
@@ -471,7 +475,7 @@ void AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionA
     if (endOfSelection == precedingCharacterPosition)
         return;
 
-    auto precedingCharacterRange = Range::create(*m_frame.document(), precedingCharacterPosition, endOfSelection);
+    auto precedingCharacterRange = SimpleRange { *makeBoundaryPoint(precedingCharacterPosition), *makeBoundaryPoint(endOfSelection) };
     String string = plainText(precedingCharacterRange);
     if (string.isEmpty() || !deprecatedIsEditingWhitespace(string[string.length() - 1]))
         return;
@@ -484,25 +488,25 @@ void AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionA
 
 bool AlternativeTextController::processMarkersOnTextToBeReplacedByResult(const TextCheckingResult& result, Range& rangeWithAlternative, const String& stringToBeReplaced)
 {
-    DocumentMarkerController& markerController = m_frame.document()->markers();
-    if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::Replacement)) {
+    auto& markers = m_frame.document()->markers();
+    if (markers.hasMarkers(rangeWithAlternative, DocumentMarker::Replacement)) {
         if (result.type == TextCheckingType::Correction)
             recordSpellcheckerResponseForModifiedCorrection(rangeWithAlternative, stringToBeReplaced, result.replacement);
         return false;
     }
 
-    if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::RejectedCorrection))
+    if (markers.hasMarkers(rangeWithAlternative, DocumentMarker::RejectedCorrection))
         return false;
 
-    if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::AcceptedCandidate))
+    if (markers.hasMarkers(rangeWithAlternative, DocumentMarker::AcceptedCandidate))
         return false;
 
     Position beginningOfRange = rangeWithAlternative.startPosition();
     Position precedingCharacterPosition = beginningOfRange.previous();
-    auto precedingCharacterRange = Range::create(*m_frame.document(), precedingCharacterPosition, beginningOfRange);
 
-    Vector<RenderedDocumentMarker*> markers = markerController.markersInRange(precedingCharacterRange, DocumentMarker::DeletedAutocorrection);
-    for (const auto* marker : markers) {
+    auto precedingCharacterRange = SimpleRange { *makeBoundaryPoint(precedingCharacterPosition), *makeBoundaryPoint(beginningOfRange) };
+
+    for (auto& marker : markers.markersInRange(precedingCharacterRange, DocumentMarker::DeletedAutocorrection)) {
         if (marker->description() == stringToBeReplaced)
             return false;
     }
index d8a8703..019a426 100644 (file)
@@ -40,8 +40,13 @@ namespace WebCore {
 
 static Optional<std::pair<ChangeListTypeCommand::Type, Ref<HTMLElement>>> listConversionTypeForSelection(const VisibleSelection& selection)
 {
+    auto startNode = selection.start().containerNode();
+    auto endNode = selection.end().containerNode();
+    if (!startNode || !endNode)
+        return { };
+    auto commonAncestor = commonInclusiveAncestor(*startNode, *endNode);
+
     RefPtr<HTMLElement> listToReplace;
-    auto commonAncestor = makeRefPtr(Range::commonAncestorContainer(selection.start().containerNode(), selection.end().containerNode()));
     if (is<HTMLUListElement>(commonAncestor) || is<HTMLOListElement>(commonAncestor))
         listToReplace = downcast<HTMLElement>(commonAncestor.get());
     else
index 3b029ea..5ae7ab2 100644 (file)
@@ -1140,19 +1140,22 @@ static bool isVisiblyAdjacent(const Position& first, const Position& second)
 
 // Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range.
 // Call this function to determine whether a node is visibly fit inside selectedRange
-bool isNodeVisiblyContainedWithin(Node& node, const Range& range)
+bool isNodeVisiblyContainedWithin(Node& node, const SimpleRange& range)
 {
     // If the node is inside the range, then it surely is contained within.
-    auto comparisonResult = range.compareNode(node);
+    auto comparisonResult = createLiveRange(range)->compareNode(node);
     if (!comparisonResult.hasException() && comparisonResult.releaseReturnValue() == Range::NODE_INSIDE)
         return true;
 
-    bool startIsVisuallySame = visiblePositionBeforeNode(node) == range.startPosition();
-    if (startIsVisuallySame && comparePositions(positionInParentAfterNode(&node), range.endPosition()) < 0)
+    auto startPosition = createLegacyEditingPosition(range.start);
+    auto endPosition = createLegacyEditingPosition(range.end);
+
+    bool startIsVisuallySame = visiblePositionBeforeNode(node) == startPosition;
+    if (startIsVisuallySame && comparePositions(positionInParentAfterNode(&node), endPosition) < 0)
         return true;
 
-    bool endIsVisuallySame = visiblePositionAfterNode(node) == range.endPosition();
-    if (endIsVisuallySame && comparePositions(range.startPosition(), positionInParentBeforeNode(&node)) < 0)
+    bool endIsVisuallySame = visiblePositionAfterNode(node) == endPosition;
+    if (endIsVisuallySame && comparePositions(startPosition, positionInParentBeforeNode(&node)) < 0)
         return true;
 
     return startIsVisuallySame && endIsVisuallySame;
index c052646..7f3ac62 100644 (file)
@@ -37,7 +37,6 @@ class HTMLElement;
 class HTMLImageElement;
 class HTMLSpanElement;
 class HTMLTextFormControlElement;
-class Range;
 class RenderBlock;
 class VisiblePosition;
 class VisibleSelection;
@@ -101,7 +100,7 @@ bool isNodeRendered(const Node&);
 bool isRenderedAsNonInlineTableImageOrHR(const Node*);
 bool isNonTableCellHTMLBlockElement(const Node*);
 
-bool isNodeVisiblyContainedWithin(Node&, const Range&);
+bool isNodeVisiblyContainedWithin(Node&, const SimpleRange&);
 
 bool areIdenticalElements(const Node&, const Node&);
 
index 1c83fd0..2b10606 100644 (file)
@@ -3211,7 +3211,7 @@ void Editor::transpose()
     replaceSelectionWithText(transposed, SelectReplacement::No, SmartReplace::No, EditAction::Insert);
 }
 
-void Editor::addRangeToKillRing(const Range& range, KillRingInsertionMode mode)
+void Editor::addRangeToKillRing(const SimpleRange& range, KillRingInsertionMode mode)
 {
     addTextToKillRing(plainText(range), mode);
 }
@@ -3685,99 +3685,74 @@ void Editor::respondToChangedSelection(const VisibleSelection&, OptionSet<FrameS
     scheduleEditorUIUpdate();
 }
 
-#if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC)
 
-bool Editor::shouldDetectTelephoneNumbers()
+bool Editor::shouldDetectTelephoneNumbers() const
 {
-    if (!m_frame.document())
-        return false;
-    return document().isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
+    return m_frame.document() && document().isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
 }
 
-void Editor::scanSelectionForTelephoneNumbers()
+static Vector<SimpleRange> scanForTelephoneNumbers(const SimpleRange& range)
 {
-    if (!shouldDetectTelephoneNumbers() || !client())
-        return;
-
-    m_detectedTelephoneNumberRanges.clear();
-
-    Vector<RefPtr<Range>> markedRanges;
-
-    FrameSelection& frameSelection = m_frame.selection();
-    if (!frameSelection.isRange()) {
-        if (auto* page = m_frame.page())
-            page->servicesOverlayController().selectedTelephoneNumberRangesChanged();
-        return;
+    // Don't scan for phone numbers inside editable regions.
+    auto& startNode = range.startContainer();
+    if (startNode.hasEditableStyle())
+        return { };
+    auto text = plainText(range);
+    Vector<SimpleRange> result;
+    unsigned length = text.length();
+    unsigned scannerPosition = 0;
+    int relativeStartPosition = 0;
+    int relativeEndPosition = 0;
+    auto characters = StringView { text }.upconvertedCharacters();
+    while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
+        ASSERT(scannerPosition + relativeEndPosition <= length);
+        result.append(resolveCharacterRange(range, CharacterRange(scannerPosition + relativeStartPosition, relativeEndPosition - relativeStartPosition)));
+        scannerPosition += relativeEndPosition;
     }
-    auto selectedRange = createLiveRange(frameSelection.selection().toNormalizedRange());
-
-    // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
-    static const int charactersToExtend = 15;
-    const VisibleSelection& visibleSelection = frameSelection.selection();
-    Position start = visibleSelection.start();
-    Position end = visibleSelection.end();
-    for (int i = 0; i < charactersToExtend; ++i) {
+    return result;
+}
+
+static SimpleRange extendSelection(const SimpleRange& range, unsigned charactersToExtend)
+{
+    auto start = createLegacyEditingPosition(range.start);
+    auto end = createLegacyEditingPosition(range.end);
+    for (unsigned i = 0; i < charactersToExtend; ++i) {
         start = start.previous(Character);
         end = end.next(Character);
     }
+    return { *makeBoundaryPoint(start), *makeBoundaryPoint(end)};
+}
 
-    FrameSelection extendedSelection;
-    extendedSelection.setStart(start);
-    extendedSelection.setEnd(end);
-    auto extendedRange = extendedSelection.selection().toNormalizedRange();
-
-    if (!extendedRange) {
-        if (auto* page = m_frame.page())
-            page->servicesOverlayController().selectedTelephoneNumberRangesChanged();
+void Editor::scanSelectionForTelephoneNumbers()
+{
+    // FIXME: Why is it helpful here to check client for null?
+    if (!shouldDetectTelephoneNumbers() || !client())
         return;
-    }
 
-    scanRangeForTelephoneNumbers(createLiveRange(*extendedRange), plainText(*extendedRange), markedRanges);
+    m_detectedTelephoneNumberRanges.clear();
 
-    // Only consider ranges with a detected telephone number if they overlap with the actual selection range.
-    for (auto& range : markedRanges) {
-        if (rangesOverlap(range.get(), selectedRange.get()))
-            m_detectedTelephoneNumberRanges.append(range);
+    auto& selection = m_frame.selection();
+    if (selection.isRange()) {
+        if (auto selectedRange = selection.selection().firstRange()) {
+            // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
+            constexpr unsigned charactersToExtend = 15;
+            auto selectedLiveRange = createLiveRange(*selectedRange);
+            for (auto& range : scanForTelephoneNumbers(extendSelection(*selectedRange, charactersToExtend))) {
+                // FIXME: Why do we do this unconditionally and the code below this only when it overlaps the selection?
+                document().markers().addMarker(range, DocumentMarker::TelephoneNumber);
+
+                // Only consider ranges with a detected telephone number if they overlap with the actual selection range.
+                if (rangesOverlap(createLiveRange(range).ptr(), selectedLiveRange.ptr()))
+                    m_detectedTelephoneNumberRanges.append(range);
+            }
+        }
     }
 
     if (auto* page = m_frame.page())
         page->servicesOverlayController().selectedTelephoneNumberRangesChanged();
 }
 
-void Editor::scanRangeForTelephoneNumbers(Range& range, const StringView& stringView, Vector<RefPtr<Range>>& markedRanges)
-{
-    // Don't scan for phone numbers inside editable regions.
-    Node& startNode = range.startContainer();
-    if (startNode.hasEditableStyle())
-        return;
-
-    // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
-    // relative to the scannerPosition
-    unsigned length = stringView.length();
-    unsigned scannerPosition = 0;
-    int relativeStartPosition = 0;
-    int relativeEndPosition = 0;
-
-    auto characters = stringView.upconvertedCharacters();
-
-    while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
-        // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
-        // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So subtract 1 to get the same
-        // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
-        // to the old parser).
-        --relativeEndPosition;
-
-        ASSERT(scannerPosition + relativeEndPosition < length);
-
-        auto subrange = resolveCharacterRange(range, CharacterRange(scannerPosition + relativeStartPosition, relativeEndPosition - relativeStartPosition + 1));
-
-        markedRanges.append(createLiveRange(subrange));
-        range.ownerDocument().markers().addMarker(subrange, DocumentMarker::TelephoneNumber);
-
-        scannerPosition += relativeEndPosition + 1;
-    }
-}
-
 #endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
 
 void Editor::updateEditorUINowIfScheduled()
index ad9eda2..23f5de1 100644 (file)
@@ -417,7 +417,7 @@ public:
 #endif
     
     enum class KillRingInsertionMode { PrependText, AppendText };
-    void addRangeToKillRing(const Range&, KillRingInsertionMode);
+    void addRangeToKillRing(const SimpleRange&, KillRingInsertionMode);
     void addTextToKillRing(const String&, KillRingInsertionMode);
     void setStartNewKillRingSequence(bool);
 
@@ -506,7 +506,7 @@ public:
     WEBCORE_EXPORT void toggleAutomaticSpellingCorrection();
 #endif
 
-    RefPtr<DocumentFragment> webContentFromPasteboard(Pasteboard&, Range& context, bool allowPlainText, bool& chosePlainText);
+    RefPtr<DocumentFragment> webContentFromPasteboard(Pasteboard&, const SimpleRange& context, bool allowPlainText, bool& chosePlainText);
 
     WEBCORE_EXPORT const Font* fontForSelection(bool& hasMultipleFonts) const;
     WEBCORE_EXPORT static const RenderStyle* styleForSelectionStart(Frame* , Node *&nodeToRemove);
@@ -516,12 +516,13 @@ public:
     WEBCORE_EXPORT String stringSelectionForPasteboard();
     String stringSelectionForPasteboardWithImageAltText();
     void takeFindStringFromSelection();
-#if !PLATFORM(IOS_FAMILY)
+    WEBCORE_EXPORT void replaceSelectionWithAttributedString(NSAttributedString *, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
+#endif
+
+#if PLATFORM(MAC)
     WEBCORE_EXPORT void readSelectionFromPasteboard(const String& pasteboardName);
     WEBCORE_EXPORT void replaceNodeFromPasteboard(Node*, const String& pasteboardName);
     WEBCORE_EXPORT RefPtr<SharedBuffer> dataSelectionForPasteboard(const String& pasteboardName);
-#endif // !PLATFORM(IOS_FAMILY)
-    WEBCORE_EXPORT void replaceSelectionWithAttributedString(NSAttributedString *, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
 #endif
 
     bool canCopyExcludingStandaloneImages() const;
@@ -532,9 +533,9 @@ public:
     void writeSelection(PasteboardWriterData&);
 #endif
 
-#if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC)
     void scanSelectionForTelephoneNumbers();
-    const Vector<RefPtr<Range>>& detectedTelephoneNumberRanges() const { return m_detectedTelephoneNumberRanges; }
+    const Vector<SimpleRange>& detectedTelephoneNumberRanges() const { return m_detectedTelephoneNumberRanges; }
 #endif
 
     WEBCORE_EXPORT String stringForCandidateRequest() const;
@@ -648,12 +649,11 @@ private:
     bool m_editorUIUpdateTimerWasTriggeredByDictation { false };
     bool m_isHandlingAcceptedCandidate { false };
 
-#if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
-    bool shouldDetectTelephoneNumbers();
-    void scanRangeForTelephoneNumbers(Range&, const StringView&, Vector<RefPtr<Range>>& markedRanges);
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC)
+    bool shouldDetectTelephoneNumbers() const;
 
     Timer m_telephoneNumberDetectionUpdateTimer;
-    Vector<RefPtr<Range>> m_detectedTelephoneNumberRanges;
+    Vector<SimpleRange> m_detectedTelephoneNumberRanges;
 #endif
 
     bool m_isGettingDictionaryPopupInfo { false };
index 7e534f2..7e444d0 100644 (file)
@@ -596,7 +596,7 @@ auto TextManipulationController::replace(const ManipulationItemData& item, const
             if (!commonAncestor)
                 commonAncestor = parent;
             else if (!parent->isDescendantOf(commonAncestor.get())) {
-                commonAncestor = Range::commonAncestorContainer(commonAncestor.get(), parent.get());
+                commonAncestor = commonInclusiveAncestor(*commonAncestor, *parent);
                 ASSERT(commonAncestor);
             }
         }
index 3cafc3a..bda4b1e 100644 (file)
@@ -202,26 +202,16 @@ bool VisibleSelection::expandUsingGranularity(TextGranularity granularity)
     return true;
 }
 
-static RefPtr<Range> makeSearchRange(const Position& position)
+static Optional<SimpleRange> makeSearchRange(const Position& position)
 {
-    auto* node = position.deprecatedNode();
-    if (!node)
-        return nullptr;
-    auto* boundary = deprecatedEnclosingBlockFlowElement(node);
-    if (!boundary)
-        return nullptr;
-
-    auto searchRange = Range::create(node->document());
-
-    auto result = searchRange->selectNodeContents(*boundary);
-    if (result.hasException())
-        return nullptr;
-    Position start { position.parentAnchoredEquivalent() };
-    result = searchRange->setStart(*start.containerNode(), start.offsetInContainerNode());
-    if (result.hasException())
-        return nullptr;
-
-    return searchRange;
+    auto node = position.deprecatedNode();
+    auto scope = deprecatedEnclosingBlockFlowElement(node);
+    if (!scope)
+        return { };
+    auto start = makeBoundaryPoint(position.parentAnchoredEquivalent());
+    if (!start)
+        return { };
+    return { { WTFMove(*start), makeBoundaryPointAfterNodeContents(*scope) } };
 }
 
 bool VisibleSelection::isAll(EditingBoundaryCrossingRule rule) const
@@ -231,7 +221,7 @@ bool VisibleSelection::isAll(EditingBoundaryCrossingRule rule) const
 
 void VisibleSelection::appendTrailingWhitespace()
 {
-    RefPtr<Range> searchRange = makeSearchRange(m_end);
+    auto searchRange = makeSearchRange(m_end);
     if (!searchRange)
         return;
 
index 683e244..54541f0 100644 (file)
 #include "DocumentFragment.h"
 #include "Frame.h"
 #include "Pasteboard.h"
-#include "Range.h"
+#include "SimpleRange.h"
 #include "markup.h"
 
 namespace WebCore {
 
 class ArchiveResource;
-class Blob;
 
 class FrameWebContentReader : public PasteboardWebContentReader {
 public:
@@ -52,13 +51,13 @@ protected:
 
 class WebContentReader final : public FrameWebContentReader {
 public:
-    Range& context;
+    const SimpleRange context;
     const bool allowPlainText;
 
     RefPtr<DocumentFragment> fragment;
     bool madeFragmentFromPlainText;
 
-    WebContentReader(Frame& frame, Range& context, bool allowPlainText)
+    WebContentReader(Frame& frame, const SimpleRange& context, bool allowPlainText)
         : FrameWebContentReader(frame)
         , context(context)
         , allowPlainText(allowPlainText)
index 1d112dc..39bbb1f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-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
@@ -27,9 +27,9 @@
 
 #if ENABLE(DATA_DETECTION)
 
-#import <wtf/RefPtr.h>
+#import "FloatRect.h"
+#import "SimpleRange.h"
 #import <wtf/RetainPtr.h>
-#import <wtf/text/WTFString.h>
 
 OBJC_CLASS DDActionContext;
 OBJC_CLASS NSArray;
@@ -37,30 +37,31 @@ OBJC_CLASS NSDictionary;
 
 namespace WebCore {
 
-class Document;
-class Element;
-class FloatRect;
 class HitTestResult;
-class Range;
 
-enum DataDetectorTypes {
-    DataDetectorTypeNone = 0,
-    DataDetectorTypePhoneNumber = 1 << 0,
-    DataDetectorTypeLink = 1 << 1,
-    DataDetectorTypeAddress = 1 << 2,
-    DataDetectorTypeCalendarEvent = 1 << 3,
-    DataDetectorTypeTrackingNumber = 1 << 4,
-    DataDetectorTypeFlightNumber = 1 << 5,
-    DataDetectorTypeLookupSuggestion = 1 << 6,
-    DataDetectorTypeAll = ULONG_MAX
+// FIXME: Would be better to use an OptionSet and uint8_t.
+enum class DataDetectorTypes : uint32_t {
+    PhoneNumber = 1 << 0,
+    Link = 1 << 1,
+    Address = 1 << 2,
+    CalendarEvent = 1 << 3,
+    TrackingNumber = 1 << 4,
+    FlightNumber = 1 << 5,
+    LookupSuggestion = 1 << 6,
+};
+
+struct DetectedItem {
+    RetainPtr<DDActionContext> actionContext;
+    FloatRect boundingBox;
+    SimpleRange range;
 };
 
 class DataDetection {
 public:
 #if PLATFORM(MAC)
-    WEBCORE_EXPORT static RetainPtr<DDActionContext> detectItemAroundHitTestResult(const HitTestResult&, FloatRect& detectedDataBoundingBox, RefPtr<Range>& detectedDataRange);
+    WEBCORE_EXPORT static Optional<DetectedItem> detectItemAroundHitTestResult(const HitTestResult&);
 #endif
-    WEBCORE_EXPORT static NSArray *detectContentInRange(RefPtr<Range>& contextRange, DataDetectorTypes, NSDictionary *context);
+    WEBCORE_EXPORT static NSArray *detectContentInRange(const SimpleRange&, DataDetectorTypes, NSDictionary *context);
     WEBCORE_EXPORT static void removeDataDetectedLinksInDocument(Document&);
 #if PLATFORM(IOS_FAMILY)
     WEBCORE_EXPORT static bool canBePresentedByDataDetectors(const URL&);
@@ -77,4 +78,3 @@ public:
 } // namespace WebCore
 
 #endif
-
index 439c033..4729ef8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2017 Apple, Inc.  All rights reserved.
+ * Copyright (C) 2014-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
@@ -38,7 +38,6 @@
 #import "HTMLNames.h"
 #import "HTMLTextFormControlElement.h"
 #import "HitTestResult.h"
-#import "Node.h"
 #import "NodeList.h"
 #import "NodeTraversal.h"
 #import "Range.h"
@@ -56,8 +55,7 @@
 #import "DataDetectorsCoreSoftLink.h"
 
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
-template <>
-struct WTF::CFTypeTrait<DDResultRef> {
+template<> struct WTF::CFTypeTrait<DDResultRef> {
     static inline CFTypeID typeID(void) { return DDResultGetCFTypeID(); }
 };
 #endif
@@ -68,25 +66,24 @@ using namespace HTMLNames;
 
 #if PLATFORM(MAC)
 
-static RetainPtr<DDActionContext> detectItemAtPositionWithRange(VisiblePosition position, RefPtr<Range> contextRange, FloatRect& detectedDataBoundingBox, RefPtr<Range>& detectedDataRange)
+static Optional<DetectedItem> detectItem(const VisiblePosition& position, const SimpleRange& contextRange)
 {
-    auto start = contextRange->startPosition();
-    if (start.isNull() || position.isNull())
-        return nil;
-    String fullPlainTextString = plainText(*contextRange);
-    CFIndex hitLocation = characterCount({ *makeBoundaryPoint(start), *makeBoundaryPoint(position) });
+    if (position.isNull())
+        return { };
+    String fullPlainTextString = plainText(contextRange);
+    CFIndex hitLocation = characterCount({ contextRange.start, *makeBoundaryPoint(position) });
 
     auto scanner = adoptCF(DDScannerCreate(DDScannerTypeStandard, 0, nullptr));
     auto scanQuery = adoptCF(DDScanQueryCreateFromString(kCFAllocatorDefault, fullPlainTextString.createCFString().get(), CFRangeMake(0, fullPlainTextString.length())));
 
     if (!DDScannerScanQuery(scanner.get(), scanQuery.get()))
-        return nil;
+        return { };
 
     auto results = adoptCF(DDScannerCopyResultsWithOptions(scanner.get(), DDScannerCopyResultsOptionsNoOverlap));
 
     // Find the DDResultRef that intersects the hitTestResult's VisiblePosition.
     DDResultRef mainResult = nullptr;
-    RefPtr<Range> mainResultRange;
+    Optional<SimpleRange> mainResultRange;
     CFIndex resultCount = CFArrayGetCount(results.get());
     for (CFIndex i = 0; i < resultCount; i++) {
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
@@ -97,39 +94,40 @@ static RetainPtr<DDActionContext> detectItemAtPositionWithRange(VisiblePosition
         CFRange resultRangeInContext = DDResultGetRange(result);
         if (hitLocation >= resultRangeInContext.location && (hitLocation - resultRangeInContext.location) < resultRangeInContext.length) {
             mainResult = result;
-            mainResultRange = createLiveRange(resolveCharacterRange(*contextRange, resultRangeInContext));
+            mainResultRange = resolveCharacterRange(contextRange, resultRangeInContext);
             break;
         }
     }
 
     if (!mainResult)
-        return nil;
+        return { };
 
-    auto view = mainResultRange->ownerDocument().view();
+    auto view = mainResultRange->start.document().view();
     if (!view)
-        return nil;
+        return { };
 
     auto actionContext = adoptNS([allocDDActionContextInstance() init]);
     [actionContext setAllResults:@[ (__bridge id)mainResult ]];
     [actionContext setMainResult:mainResult];
 
-    detectedDataBoundingBox = view->contentsToWindow(enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(*mainResultRange))));
-    detectedDataRange = mainResultRange;
-
-    return actionContext;
+    return { {
+        WTFMove(actionContext),
+        view->contentsToWindow(enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(*mainResultRange)))),
+        *mainResultRange,
+    } };
 }
 
-RetainPtr<DDActionContext> DataDetection::detectItemAroundHitTestResult(const HitTestResult& hitTestResult, FloatRect& detectedDataBoundingBox, RefPtr<Range>& detectedDataRange)
+Optional<DetectedItem> DataDetection::detectItemAroundHitTestResult(const HitTestResult& hitTestResult)
 {
     if (!DataDetectorsLibrary())
-        return nullptr;
+        return { };
 
     Node* node = hitTestResult.innerNonSharedNode();
     if (!node)
-        return nullptr;
+        return { };
     auto renderer = node->renderer();
     if (!renderer)
-        return nullptr;
+        return { };
 
     VisiblePosition position;
     RefPtr<Range> contextRange;
@@ -140,27 +138,26 @@ RetainPtr<DDActionContext> DataDetection::detectItemAroundHitTestResult(const Hi
             position = firstPositionInOrBeforeNode(node);
 
         contextRange = rangeExpandedAroundPositionByCharacters(position, 250);
-        if (!contextRange)
-            return nullptr;
     } else {
         Frame* frame = node->document().frame();
         if (!frame)
-            return nullptr;
+            return { };
 
         IntPoint framePoint = hitTestResult.roundedPointInInnerNodeFrame();
         if (!frame->rangeForPoint(framePoint))
-            return nullptr;
+            return { };
 
-        VisiblePosition position = frame->visiblePositionForPoint(framePoint);
+        position = frame->visiblePositionForPoint(framePoint);
         if (position.isNull())
-            return nullptr;
+            return { };
 
         contextRange = enclosingTextUnitOfGranularity(position, LineGranularity, DirectionForward);
-        if (!contextRange)
-            return nullptr;
     }
 
-    return detectItemAtPositionWithRange(position, contextRange, detectedDataBoundingBox, detectedDataRange);
+    if (!contextRange)
+        return { };
+
+    return detectItem(position, *contextRange);
 }
 
 #endif // PLATFORM(MAC)
@@ -223,25 +220,30 @@ static BOOL resultIsURL(DDResultRef result)
     return [urlTypes containsObject:(NSString *)softLink_DataDetectorsCore_DDResultGetType(result)];
 }
 
+// Poor man's OptionSet.
+static bool contains(DataDetectorTypes types, DataDetectorTypes singleType)
+{
+    return static_cast<uint32_t>(types) & static_cast<uint32_t>(singleType);
+}
+
 static NSString *constructURLStringForResult(DDResultRef currentResult, NSString *resultIdentifier, NSDate *referenceDate, NSTimeZone *referenceTimeZone, DataDetectorTypes detectionTypes)
 {
     if (!softLink_DataDetectorsCore_DDResultHasProperties(currentResult, DDResultPropertyPassiveDisplay))
         return nil;
-    
-    DDURLifierPhoneNumberDetectionTypes phoneTypes = (detectionTypes & DataDetectorTypePhoneNumber) ? DDURLifierPhoneNumberDetectionRegular : DDURLifierPhoneNumberDetectionNone;
-    DDResultCategory category = softLink_DataDetectorsCore_DDResultGetCategory(currentResult);
-    CFStringRef type = softLink_DataDetectorsCore_DDResultGetType(currentResult);
-    
-    if (((detectionTypes & DataDetectorTypeAddress) && (DDResultCategoryAddress == category))
-        || ((detectionTypes & DataDetectorTypeTrackingNumber) && (CFStringCompare(get_DataDetectorsCore_DDBinderTrackingNumberKey(), type, 0) == kCFCompareEqualTo))
-        || ((detectionTypes & DataDetectorTypeFlightNumber) && (CFStringCompare(get_DataDetectorsCore_DDBinderFlightInformationKey(), type, 0) == kCFCompareEqualTo))
-        || ((detectionTypes & DataDetectorTypeLookupSuggestion) && (CFStringCompare(get_DataDetectorsCore_DDBinderParsecSourceKey(), type, 0) == kCFCompareEqualTo))
-        || ((detectionTypes & DataDetectorTypePhoneNumber) && (DDResultCategoryPhoneNumber == category))
-        || ((detectionTypes & DataDetectorTypeLink) && resultIsURL(currentResult))) {
-        
+
+    auto phoneTypes = contains(detectionTypes, DataDetectorTypes::PhoneNumber) ? DDURLifierPhoneNumberDetectionRegular : DDURLifierPhoneNumberDetectionNone;
+    auto category = softLink_DataDetectorsCore_DDResultGetCategory(currentResult);
+    auto type = softLink_DataDetectorsCore_DDResultGetType(currentResult);
+
+    if ((contains(detectionTypes, DataDetectorTypes::Address) && DDResultCategoryAddress == category)
+        || (contains(detectionTypes, DataDetectorTypes::TrackingNumber) && CFEqual(get_DataDetectorsCore_DDBinderTrackingNumberKey(), type))
+        || (contains(detectionTypes, DataDetectorTypes::FlightNumber) && CFEqual(get_DataDetectorsCore_DDBinderFlightInformationKey(), type))
+        || (contains(detectionTypes, DataDetectorTypes::LookupSuggestion) && CFEqual(get_DataDetectorsCore_DDBinderParsecSourceKey(), type))
+        || (contains(detectionTypes, DataDetectorTypes::PhoneNumber) && DDResultCategoryPhoneNumber == category)
+        || (contains(detectionTypes, DataDetectorTypes::Link) && resultIsURL(currentResult))) {
         return softLink_DataDetectorsCore_DDURLStringForResult(currentResult, resultIdentifier, phoneTypes, referenceDate, referenceTimeZone);
     }
-    if ((detectionTypes & DataDetectorTypeCalendarEvent) && (DDResultCategoryCalendarEvent == category)) {
+    if (contains(detectionTypes, DataDetectorTypes::CalendarEvent) && DDResultCategoryCalendarEvent == category) {
         if (!softLink_DataDetectorsCore_DDResultIsPastDate(currentResult, (CFDateRef)referenceDate, (CFTimeZoneRef)referenceTimeZone))
             return softLink_DataDetectorsCore_DDURLStringForResult(currentResult, resultIdentifier, phoneTypes, referenceDate, referenceTimeZone);
     }
@@ -443,28 +445,24 @@ void DataDetection::removeDataDetectedLinksInDocument(Document& document)
         removeResultLinksFromAnchor(anchor.get());
 }
 
-NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDetectorTypes types, NSDictionary *context)
+NSArray *DataDetection::detectContentInRange(const SimpleRange& contextRange, DataDetectorTypes types, NSDictionary *context)
 {
-    if (!contextRange)
-        return nil;
-
-    RetainPtr<DDScannerRef> scanner = adoptCF(softLink_DataDetectorsCore_DDScannerCreate(DDScannerTypeStandard, 0, nullptr));
-    RetainPtr<DDScanQueryRef> scanQuery = adoptCF(softLink_DataDetectorsCore_DDScanQueryCreate(NULL));
-    buildQuery(scanQuery.get(), *contextRange);
+    auto scanner = adoptCF(softLink_DataDetectorsCore_DDScannerCreate(DDScannerTypeStandard, 0, nullptr));
+    auto scanQuery = adoptCF(softLink_DataDetectorsCore_DDScanQueryCreate(NULL));
+    buildQuery(scanQuery.get(), contextRange);
     
-    if (types & DataDetectorTypeLookupSuggestion)
+    if (contains(types, DataDetectorTypes::LookupSuggestion))
         softLink_DataDetectorsCore_DDScannerEnableOptionalSource(scanner.get(), DDScannerSourceSpotlight, true);
 
     // FIXME: we should add a timeout to this call to make sure it doesn't take too much time.
     if (!softLink_DataDetectorsCore_DDScannerScanQuery(scanner.get(), scanQuery.get()))
         return nil;
 
-    RetainPtr<CFArrayRef> scannerResults = adoptCF(softLink_DataDetectorsCore_DDScannerCopyResultsWithOptions(scanner.get(), get_DataDetectorsCore_DDScannerCopyResultsOptionsForPassiveUse() | DDScannerCopyResultsOptionsCoalesceSignatures));
+    auto scannerResults = adoptCF(softLink_DataDetectorsCore_DDScannerCopyResultsWithOptions(scanner.get(), get_DataDetectorsCore_DDScannerCopyResultsOptionsForPassiveUse() | DDScannerCopyResultsOptionsCoalesceSignatures));
     if (!scannerResults)
         return nil;
 
-    CFIndex resultCount = CFArrayGetCount(scannerResults.get());
-    if (!resultCount)
+    if (!CFArrayGetCount(scannerResults.get()))
         return nil;
 
     Vector<RetainPtr<DDResultRef>> allResults;
@@ -476,7 +474,7 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
     for (id resultObject in (NSArray *)scannerResults.get()) {
         DDResultRef result = (DDResultRef)resultObject;
         NSIndexPath *indexPath = [NSIndexPath indexPathWithIndex:currentTopLevelIndex];
-        if (CFStringCompare(softLink_DataDetectorsCore_DDResultGetType(result), get_DataDetectorsCore_DDBinderSignatureBlockKey(), 0) == kCFCompareEqualTo) {
+        if (CFEqual(softLink_DataDetectorsCore_DDResultGetType(result), get_DataDetectorsCore_DDBinderSignatureBlockKey())) {
             NSArray *subresults = (NSArray *)softLink_DataDetectorsCore_DDResultGetSubResults(result);
             
             for (NSUInteger subResultIndex = 0 ; subResultIndex < [subresults count] ; subResultIndex++) {
@@ -491,7 +489,7 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
     }
 
     Vector<Vector<SimpleRange>> allResultRanges;
-    TextIterator iterator(*contextRange);
+    TextIterator iterator(contextRange);
     CFIndex iteratorCount = 0;
 
     // Iterate through the array of the expanded results to create a vector of Range objects that indicate
@@ -536,16 +534,15 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
 
     auto tz = adoptCF(CFTimeZoneCopyDefault());
     NSDate *referenceDate = [context objectForKey:getkDataDetectorsReferenceDateKey()] ?: [NSDate date];
-    Text* lastTextNodeToUpdate = nullptr;
+    RefPtr<Text> lastTextNodeToUpdate;
     String lastNodeContent;
-    size_t contentOffset = 0;
+    unsigned contentOffset = 0;
     DDQueryOffset lastModifiedQueryOffset = { -1, 0 };
-    
+
     // For each result add the link.
     // Since there could be multiple results in the same text node, the node is only modified when
     // we are about to process a different text node.
-    resultCount = allResults.size();
-    
+    CFIndex resultCount = allResults.size();
     for (CFIndex resultIndex = 0; resultIndex < resultCount; ++resultIndex) {
         DDResultRef coreResult = allResults[resultIndex].get();
         DDQueryRange queryRange = softLink_DataDetectorsCore_DDResultGetQueryRangeForURLification(coreResult);
@@ -578,7 +575,7 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
             ASSERT(resultRanges.size() == rangeBoundaries.size());
             resultRanges.shrink(0); // Keep capacity as we are going to repopulate the Vector right away with the same number of items.
             for (auto& rangeBoundary : rangeBoundaries)
-                resultRanges.uncheckedAppend(Range::create(*rangeBoundary.first.document(), rangeBoundary.first, rangeBoundary.second));
+                resultRanges.uncheckedAppend({ *makeBoundaryPoint(rangeBoundary.first), *makeBoundaryPoint(rangeBoundary.second) });
         }
         
         lastModifiedQueryOffset = queryRange.end;
@@ -612,7 +609,7 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
 
             // Create the actual anchor node and insert it before the current node.
             textNodeData = currentTextNode.data().substring(range.start.offset, range.end.offset - range.start.offset);
-            Ref<Text> newTextNode = Text::create(document, textNodeData);
+            auto newTextNode = Text::create(document, textNodeData);
             parentNode->insertBefore(newTextNode.copyRef(), &currentTextNode);
             
             Ref<HTMLAnchorElement> anchorElement = HTMLAnchorElement::create(document);
@@ -659,13 +656,13 @@ NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDe
 
     if (lastTextNodeToUpdate)
         lastTextNodeToUpdate->setData(lastNodeContent);
-    
+
     return [getDDScannerResultClass() resultsFromCoreResults:scannerResults.get()];
 }
 
 #else
 
-NSArray *DataDetection::detectContentInRange(RefPtr<Range>&, DataDetectorTypes, NSDictionary *)
+NSArray *DataDetection::detectContentInRange(const SimpleRange&, DataDetectorTypes, NSDictionary *)
 {
     return nil;
 }
index 722f848..7fe30e0 100644 (file)
@@ -225,7 +225,7 @@ RefPtr<SharedBuffer> Editor::dataInRTFFormat(NSAttributedString *string)
 
 // FIXME: Should give this function a name that makes it clear it adds resources to the document loader as a side effect.
 // Or refactor so it does not do that.
-RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, Range& context, bool allowPlainText, bool& chosePlainText)
+RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText)
 {
     WebContentReader reader(m_frame, context, allowPlainText);
     pasteboard.read(reader);
index bbfbc68..d794784 100644 (file)
@@ -675,7 +675,7 @@ bool WebContentReader::readPlainText(const String& text)
     if (!allowPlainText)
         return false;
 
-    addFragment(createFragmentFromText(context, [text precomposedStringWithCanonicalMapping]));
+    addFragment(createFragmentFromText(createLiveRange(context), [text precomposedStringWithCanonicalMapping]));
 
     madeFragmentFromPlainText = true;
     return true;
index 706e826..e9dfdfc 100644 (file)
@@ -50,7 +50,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;
 
@@ -81,7 +81,7 @@ static RefPtr<DocumentFragment> createFragmentFromPasteboardData(Pasteboard& pas
 
     if (selection.hasText()) {
         chosePlainText = true;
-        return createFragmentFromText(range, selection.text());
+        return createFragmentFromText(createLiveRange(range), selection.text());
     }
 
     return nullptr;
@@ -152,7 +152,7 @@ void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
     pasteboard.write(pasteboardContent);
 }
 
-RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, Range& context, bool allowPlainText, bool& chosePlainText)
+RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText)
 {
     return createFragmentFromPasteboardData(pasteboard, m_frame, context, allowPlainText, chosePlainText);
 }
index fd2fcbe..931a230 100644 (file)
@@ -140,8 +140,9 @@ void Editor::replaceNodeFromPasteboard(Node* node, const String& pasteboardName)
         return;
 
     Ref<Frame> protector(m_frame);
-    auto range = Range::create(node->document(), Position(node, Position::PositionIsBeforeAnchor), Position(node, Position::PositionIsAfterAnchor));
-    m_frame.selection().setSelection(VisibleSelection(range.get()), FrameSelection::DoNotSetFocus);
+
+    auto range = makeRangeSelectingNodeContents(*node);
+    m_frame.selection().setSelection(VisibleSelection(range), FrameSelection::DoNotSetFocus);
 
     Pasteboard pasteboard(pasteboardName);
 
@@ -156,9 +157,9 @@ void Editor::replaceNodeFromPasteboard(Node* node, const String& pasteboardName)
     ALLOW_DEPRECATED_DECLARATIONS_END
 
     bool chosePlainText;
-    if (RefPtr<DocumentFragment> fragment = webContentFromPasteboard(pasteboard, range.get(), true, chosePlainText)) {
+    if (auto fragment = webContentFromPasteboard(pasteboard, range, true, chosePlainText)) {
         maybeCopyNodeAttributesToFragment(*node, *fragment);
-        if (shouldInsertFragment(*fragment, range.ptr(), EditorInsertAction::Pasted))
+        if (shouldInsertFragment(*fragment, createLiveRange(range).ptr(), EditorInsertAction::Pasted))
             pasteAsFragment(fragment.releaseNonNull(), canSmartReplaceWithPasteboard(pasteboard), false, MailBlockquoteHandling::IgnoreBlockquote);
     }
 
index 0964ccb..5e8687f 100644 (file)
@@ -66,7 +66,7 @@ static RefPtr<DocumentFragment> createFragmentFromPlatformData(PlatformDragData&
     return nullptr;
 }
 
-RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, Range&, bool /*allowPlainText*/, bool& /*chosePlainText*/)
+RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange&, bool /*allowPlainText*/, bool& /*chosePlainText*/)
 {
     if (COMPtr<IDataObject> platformDragData = pasteboard.dataObject())
         return createFragmentFromPlatformData(*platformDragData, m_frame);
index 5c1ca3e..8b05f83 100644 (file)
@@ -2598,14 +2598,12 @@ void FrameLoader::checkLoadCompleteForThisFrame()
             } else {
                 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "checkLoadCompleteForThisFrame: Finished frame load");
 #if ENABLE(DATA_DETECTION)
-                auto* document = m_frame.document();
-                if (m_frame.settings().dataDetectorTypes() != DataDetectorTypeNone && document) {
-                    if (auto* documentElement = document->documentElement()) {
-                        RefPtr<Range> documentRange = makeRange(firstPositionInNode(documentElement), lastPositionInNode(documentElement));
-                        m_frame.setDataDetectionResults(DataDetection::detectContentInRange(documentRange, m_frame.settings().dataDetectorTypes(), m_client->dataDetectionContext()));
-                        if (m_frame.isMainFrame())
-                            m_client->dispatchDidFinishDataDetection(m_frame.dataDetectionResults());
-                    }
+                auto document = m_frame.document();
+                auto types = m_frame.settings().dataDetectorTypes();
+                if (document && static_cast<uint32_t>(types)) {
+                    m_frame.setDataDetectionResults(DataDetection::detectContentInRange(makeRangeSelectingNodeContents(*document), types, m_client->dataDetectionContext()));
+                    if (m_frame.isMainFrame())
+                        m_client->dispatchDidFinishDataDetection(m_frame.dataDetectionResults());
                 }
 #endif
                 m_client->dispatchDidFinishLoad();
index b32fcad..d67549b 100644 (file)
@@ -2066,7 +2066,7 @@ void EventHandler::invalidateClick()
     m_clickNode = nullptr;
 }
 
-static Node* targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNode)
+static RefPtr<Node> targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNode)
 {
     if (!mousePressNode || !mouseReleaseNode)
         return nullptr;
@@ -2076,17 +2076,18 @@ static Node* targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNod
 
     // If mousePressNode and mouseReleaseNode differ, we should fire the event at their common ancestor if there is one.
     if (&mousePressNode->document() == &mouseReleaseNode->document()) {
-        if (auto* commonAncestor = Range::commonAncestorContainer(mousePressNode, mouseReleaseNode))
+        if (auto commonAncestor = commonInclusiveAncestor(*mousePressNode, *mouseReleaseNode))
             return commonAncestor;
     }
 
-    Element* mouseReleaseShadowHost = mouseReleaseNode->shadowHost();
+    auto mouseReleaseShadowHost = mouseReleaseNode->shadowHost();
     if (mouseReleaseShadowHost && mouseReleaseShadowHost == mousePressNode->shadowHost()) {
         // We want to dispatch the click to the shadow tree host element to give listeners the illusion that the
         // shadom tree is a single element. For example, we want to give the illusion that <input type="range">
         // is a single element even though it is a composition of multiple shadom tree elements.
         return mouseReleaseShadowHost;
     }
+
     return nullptr;
 }
 
@@ -2159,8 +2160,8 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& platformMou
 
     bool contextMenuEvent = platformMouseEvent.button() == RightButton;
 
-    Node* nodeToClick = targetNodeForClickEvent(m_clickNode.get(), mouseEvent.targetNode());
-    bool swallowClickEvent = m_clickCount > 0 && !contextMenuEvent && nodeToClick && !dispatchMouseEvent(eventNames().clickEvent, nodeToClick, true, m_clickCount, platformMouseEvent, true);
+    auto nodeToClick = targetNodeForClickEvent(m_clickNode.get(), mouseEvent.targetNode());
+    bool swallowClickEvent = m_clickCount > 0 && !contextMenuEvent && nodeToClick && !dispatchMouseEvent(eventNames().clickEvent, nodeToClick.get(), true, m_clickCount, platformMouseEvent, true);
 
     if (m_resizeLayer) {
         m_resizeLayer->setInResizeMode(false);
index a8676d9..0b49ad7 100644 (file)
@@ -541,7 +541,7 @@ useImageDocumentForSubframePDF:
   initial: false
 dataDetectorTypes:
   type: DataDetectorTypes
-  initial: DataDetectorTypeNone
+  initial: 
   conditional: DATA_DETECTION
 
 # Allow SourceBuffers to store up to 304MB each, enough for approximately five minutes
index adf8dba..af2249d 100644 (file)
 #include <wtf/text/AtomString.h>
 #include <wtf/text/AtomStringHash.h>
 
-#if ENABLE(DATA_DETECTION)
-#include "DataDetection.h"
-#endif
-
 namespace WebCore {
 
 class FontGenericFamilies;
 class Page;
 
+enum class DataDetectorTypes : uint32_t;
+
 enum EditableLinkBehavior {
     EditableLinkDefaultBehavior,
     EditableLinkAlwaysLive,
index b121d9d..2d6ce80 100644 (file)
@@ -52,7 +52,7 @@
 
 namespace WebCore {
 
-static bool initializeIndicator(TextIndicatorData&, Frame&, const Range&, FloatSize margin, bool indicatesCurrentSelection);
+static bool initializeIndicator(TextIndicatorData&, Frame&, const SimpleRange&, FloatSize margin, bool indicatesCurrentSelection);
 
 TextIndicator::TextIndicator(const TextIndicatorData& data)
     : m_data(data)
@@ -66,31 +66,27 @@ Ref<TextIndicator> TextIndicator::create(const TextIndicatorData& data)
     return adoptRef(*new TextIndicator(data));
 }
 
-RefPtr<TextIndicator> TextIndicator::createWithRange(const Range& range, TextIndicatorOptions options, TextIndicatorPresentationTransition presentationTransition, FloatSize margin)
+RefPtr<TextIndicator> TextIndicator::createWithRange(const SimpleRange& range, TextIndicatorOptions options, TextIndicatorPresentationTransition presentationTransition, FloatSize margin)
 {
-    Frame* frame = range.startContainer().document().frame();
-
+    auto frame = makeRefPtr(range.startContainer().document().frame());
     if (!frame)
         return nullptr;
 
-    Ref<Frame> protector(*frame);
+    bool indicatesCurrentSelection = range == frame->selection().selection().toNormalizedRange();
 
-    VisibleSelection oldSelection = frame->selection().selection();
     OptionSet<TemporarySelectionOption> temporarySelectionOptions;
     temporarySelectionOptions.add(TemporarySelectionOption::DoNotSetFocus);
 #if PLATFORM(IOS_FAMILY)
     temporarySelectionOptions.add(TemporarySelectionOption::IgnoreSelectionChanges);
     temporarySelectionOptions.add(TemporarySelectionOption::EnableAppearanceUpdates);
 #endif
-    TemporarySelectionChange selectionChange(*frame, { SimpleRange { range } }, temporarySelectionOptions);
+    TemporarySelectionChange selectionChange(*frame, { range }, temporarySelectionOptions);
 
     TextIndicatorData data;
 
     data.presentationTransition = presentationTransition;
     data.options = options;
 
-    bool indicatesCurrentSelection = areRangesEqual(&range, createLiveRange(oldSelection.toNormalizedRange()).get());
-
     if (!initializeIndicator(data, *frame, range, margin, indicatesCurrentSelection))
         return nullptr;
 
@@ -108,25 +104,19 @@ RefPtr<TextIndicator> TextIndicator::createWithSelectionInFrame(Frame& frame, Te
     data.presentationTransition = presentationTransition;
     data.options = options;
 
-    if (!initializeIndicator(data, frame, createLiveRange(*range), margin, true))
+    if (!initializeIndicator(data, frame, *range, margin, true))
         return nullptr;
 
     return TextIndicator::create(data);
 }
 
-static bool hasNonInlineOrReplacedElements(const Range& range)
+static bool hasNonInlineOrReplacedElements(const SimpleRange& range)
 {
-    Node* stopNode = range.pastLastNode();
-    for (Node* node = range.firstNode(); node != stopNode; node = NodeTraversal::next(*node)) {
-        if (!node)
-            continue;
-        RenderObject* renderer = node->renderer();
-        if (!renderer)
-            continue;
-        if ((!renderer->isInline() || renderer->isReplaced()) && range.intersectsNode(*node).releaseReturnValue())
+    for (auto& node : intersectingNodes(range)) {
+        auto renderer = node.renderer();
+        if (renderer && (!renderer->isInline() || renderer->isReplaced()))
             return true;
     }
-
     return false;
 }
 
@@ -184,59 +174,49 @@ static bool takeSnapshots(TextIndicatorData& data, Frame& frame, IntRect snapsho
 
 #if PLATFORM(IOS_FAMILY)
 
-static void getSelectionRectsForRange(Vector<FloatRect>& resultingRects, const Range& range)
+static Vector<FloatRect> selectionRects(const SimpleRange& range)
 {
-    Vector<SelectionRect> selectionRectsForRange;
-    Vector<FloatRect> selectionRectsForRangeInBoundingRectCoordinates;
-    range.collectSelectionRects(selectionRectsForRange);
-    for (auto selectionRect : selectionRectsForRange)
-        resultingRects.append(selectionRect.rect());
+    Vector<SelectionRect> selectionRects;
+    createLiveRange(range)->collectSelectionRects(selectionRects);
+    Vector<FloatRect> rects;
+    for (auto& selectionRect : selectionRects)
+        rects.append(selectionRect.rect());
+    return rects;
 }
 
 #endif
 
 static bool styleContainsComplexBackground(const RenderStyle& style)
 {
-    if (style.hasBlendMode())
-        return true;
-
-    if (style.hasBackgroundImage())
-        return true;
-
-    if (style.hasBackdropFilter())
-        return true;
-
-    return false;
+    return style.hasBlendMode() || style.hasBackgroundImage() || style.hasBackdropFilter();
 }
 
-static HashSet<Color> estimatedTextColorsForRange(const Range& range)
+static HashSet<Color> estimatedTextColorsForRange(const SimpleRange& range)
 {
     HashSet<Color> colors;
     for (TextIterator iterator(range); !iterator.atEnd(); iterator.advance()) {
-        auto* node = iterator.node();
-        if (!is<Text>(node) || !is<RenderText>(node->renderer()))
-            continue;
-
-        colors.add(node->renderer()->style().color());
+        auto renderer = iterator.node()->renderer();
+        if (is<RenderText>(renderer))
+            colors.add(renderer->style().color());
     }
     return colors;
 }
-    
-static FloatRect absoluteBoundingRectForRange(const Range& range)
+
+static FloatRect absoluteBoundingRectForRange(const SimpleRange& range)
 {
-    return range.absoluteBoundingRect({
+    return createLiveRange(range)->absoluteBoundingRect({
         Range::BoundingRectBehavior::RespectClipping,
         Range::BoundingRectBehavior::UseVisibleBounds,
         Range::BoundingRectBehavior::IgnoreTinyRects,
     });
 }
 
-static Color estimatedBackgroundColorForRange(const Range& range, const Frame& frame)
+static Color estimatedBackgroundColorForRange(const SimpleRange& range, const Frame& frame)
 {
     auto estimatedBackgroundColor = frame.view() ? frame.view()->documentBackgroundColor() : Color::transparent;
 
     RenderElement* renderer = nullptr;
-    auto commonAncestor = range.commonAncestorContainer();
+    auto commonAncestor = commonInclusiveAncestor(range.start.container, range.end.container);
     while (commonAncestor) {
         if (is<RenderElement>(commonAncestor->renderer())) {
             renderer = downcast<RenderElement>(commonAncestor->renderer());
@@ -291,17 +271,16 @@ static bool hasAnyIllegibleColors(TextIndicatorData& data, const Color& backgrou
     return !hasOnlyLegibleTextColors || textColors.isEmpty();
 }
 
-static bool containsOnlyWhiteSpaceText(const Range& range)
+static bool containsOnlyWhiteSpaceText(const SimpleRange& range)
 {
-    auto* stop = range.pastLastNode();
-    for (auto* node = range.firstNode(); node && node != stop; node = NodeTraversal::next(*node)) {
-        if (!is<RenderText>(node->renderer()))
+    for (auto& node : intersectingNodes(range)) {
+        if (!is<RenderText>(node.renderer()))
             return false;
     }
     return plainTextReplacingNoBreakSpace(range).stripWhiteSpace().isEmpty();
 }
 
-static bool initializeIndicator(TextIndicatorData& data, Frame& frame, const Range& range, FloatSize margin, bool indicatesCurrentSelection)
+static bool initializeIndicator(TextIndicatorData& data, Frame& frame, const SimpleRange& range, FloatSize margin, bool indicatesCurrentSelection)
 {
     if (auto* document = frame.document())
         document->updateLayoutIgnorePendingStylesheets();
@@ -312,20 +291,17 @@ static bool initializeIndicator(TextIndicatorData& data, Frame& frame, const Ran
         treatRangeAsComplexDueToIllegibleTextColors = hasAnyIllegibleColors(data, data.estimatedBackgroundColor, estimatedTextColorsForRange(range));
     }
 
-    Vector<FloatRect> textRects;
-
     // FIXME (138888): Ideally we wouldn't remove the margin in this case, but we need to
     // ensure that the indicator and indicator-with-highlight overlap precisely, and
     // we can't add a margin to the indicator-with-highlight.
     if (indicatesCurrentSelection && !(data.options & TextIndicatorOptionIncludeMarginIfRangeMatchesSelection))
         margin = FloatSize();
 
-    FrameSelection::TextRectangleHeight textRectHeight = (data.options & TextIndicatorOptionTightlyFitContent) ? FrameSelection::TextRectangleHeight::TextHeight : FrameSelection::TextRectangleHeight::SelectionHeight;
+    Vector<FloatRect> textRects;
 
     bool useBoundingRectAndPaintAllContentForComplexRanges = data.options & TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges;
     if (useBoundingRectAndPaintAllContentForComplexRanges && containsOnlyWhiteSpaceText(range)) {
-        auto commonAncestorContainer = makeRefPtr(range.commonAncestorContainer());
-        if (auto* containerRenderer = commonAncestorContainer->renderer()) {
+        if (auto* containerRenderer = commonInclusiveAncestor(range.start.container, range.end.container)->renderer()) {
             data.options |= TextIndicatorOptionPaintAllContent;
             textRects.append(containerRenderer->absoluteBoundingBoxRect());
         }
@@ -333,15 +309,15 @@ static bool initializeIndicator(TextIndicatorData& data, Frame& frame, const Ran
         data.options |= TextIndicatorOptionPaintAllContent;
 #if PLATFORM(IOS_FAMILY)
     else if (data.options & TextIndicatorOptionUseSelectionRectForSizing)
-        getSelectionRectsForRange(textRects, range);
+        textRects = selectionRects(range);
 #endif
     else {
-        Vector<IntRect> absoluteTextRects;
-        range.absoluteTextRects(absoluteTextRects, textRectHeight == FrameSelection::TextRectangleHeight::SelectionHeight, Range::BoundingRectBehavior::RespectClipping);
-
-        textRects.reserveInitialCapacity(absoluteTextRects.size());
-        for (auto& rect : absoluteTextRects)
-            textRects.uncheckedAppend(rect);
+        auto textRectHeight = (data.options & TextIndicatorOptionTightlyFitContent) ? FrameSelection::TextRectangleHeight::TextHeight : FrameSelection::TextRectangleHeight::SelectionHeight;
+        Vector<IntRect> intRects;
+        createLiveRange(range)->absoluteTextRects(intRects, textRectHeight == FrameSelection::TextRectangleHeight::SelectionHeight, Range::BoundingRectBehavior::RespectClipping);
+        textRects.reserveInitialCapacity(intRects.size());
+        for (auto& intRect : intRects)
+            textRects.uncheckedAppend(intRect);
     }
 
     if (textRects.isEmpty())
index 6f30884..41173af 100644 (file)
@@ -34,7 +34,8 @@ namespace WebCore {
 
 class Frame;
 class GraphicsContext;
-class Range;
+
+struct SimpleRange;
 
 // FIXME: Move PresentationTransition to TextIndicatorWindow, because it's about presentation.
 enum class TextIndicatorPresentationTransition : uint8_t {
@@ -123,7 +124,7 @@ public:
 
     WEBCORE_EXPORT static Ref<TextIndicator> create(const TextIndicatorData&);
     WEBCORE_EXPORT static RefPtr<TextIndicator> createWithSelectionInFrame(Frame&, TextIndicatorOptions, TextIndicatorPresentationTransition, FloatSize margin = FloatSize(defaultHorizontalMargin, defaultVerticalMargin));
-    WEBCORE_EXPORT static RefPtr<TextIndicator> createWithRange(const Range&, TextIndicatorOptions, TextIndicatorPresentationTransition, FloatSize margin = FloatSize(defaultHorizontalMargin, defaultVerticalMargin));
+    WEBCORE_EXPORT static RefPtr<TextIndicator> createWithRange(const SimpleRange&, TextIndicatorOptions, TextIndicatorPresentationTransition, FloatSize margin = FloatSize(defaultHorizontalMargin, defaultVerticalMargin));
 
     WEBCORE_EXPORT ~TextIndicator();
 
index f4e4b5e..f5082fd 100644 (file)
@@ -55,14 +55,14 @@ private:
     class Highlight : public RefCounted<Highlight>, private GraphicsLayerClient {
         WTF_MAKE_NONCOPYABLE(Highlight);
     public:
-        static Ref<Highlight> createForSelection(ServicesOverlayController&, RetainPtr<DDHighlightRef>, Ref<Range>&&);
-        static Ref<Highlight> createForTelephoneNumber(ServicesOverlayController&, RetainPtr<DDHighlightRef>, Ref<Range>&&);
+        static Ref<Highlight> createForSelection(ServicesOverlayController&, RetainPtr<DDHighlightRef>&&, SimpleRange&&);
+        static Ref<Highlight> createForTelephoneNumber(ServicesOverlayController&, RetainPtr<DDHighlightRef>&&, SimpleRange&&);
         ~Highlight();
 
         void invalidate();
 
         DDHighlightRef ddHighlight() const { return m_ddHighlight.get(); }
-        Range& range() const { return m_range.get(); }
+        const SimpleRange& range() const { return m_range; }
         GraphicsLayer& layer() const { return m_graphicsLayer.get(); }
 
         enum {
@@ -78,7 +78,7 @@ private:
         void setDDHighlight(DDHighlightRef);
 
     private:
-        Highlight(ServicesOverlayController&, Type, RetainPtr<DDHighlightRef>, Ref<Range>&&);
+        Highlight(ServicesOverlayController&, Type, RetainPtr<DDHighlightRef>&&, SimpleRange&&);
 
         // GraphicsLayerClient
         void notifyFlushRequired(const GraphicsLayer*) override;
@@ -89,7 +89,7 @@ private:
 
         ServicesOverlayController* m_controller;
         RetainPtr<DDHighlightRef> m_ddHighlight;
-        Ref<Range> m_range;
+        SimpleRange m_range;
         Ref<GraphicsLayer> m_graphicsLayer;
         Type m_type;
     };
@@ -126,9 +126,9 @@ private:
     Seconds remainingTimeUntilHighlightShouldBeShown(Highlight*) const;
     void determineActiveHighlightTimerFired();
 
-    static bool highlightsAreEquivalent(const Highlight* a, const Highlight* b);
+    static bool highlightsAreEquivalent(const Highlight*, const Highlight*);
 
-    Vector<RefPtr<Range>> telephoneNumberRangesForFocusedFrame();
+    Vector<SimpleRange> telephoneNumberRangesForFocusedFrame();
 
     void didCreateHighlight(Highlight*);
     void willDestroyHighlight(Highlight*);
index cdcba2e..2efc41e 100644 (file)
@@ -55,17 +55,17 @@ const float highlightFadeAnimationDuration = 0.3;
 
 namespace WebCore {
 
-Ref<ServicesOverlayController::Highlight> ServicesOverlayController::Highlight::createForSelection(ServicesOverlayController& controller, RetainPtr<DDHighlightRef> ddHighlight, Ref<Range>&& range)
+Ref<ServicesOverlayController::Highlight> ServicesOverlayController::Highlight::createForSelection(ServicesOverlayController& controller, RetainPtr<DDHighlightRef>&& ddHighlight, SimpleRange&& range)
 {
-    return adoptRef(*new Highlight(controller, Highlight::SelectionType, ddHighlight, WTFMove(range)));
+    return adoptRef(*new Highlight(controller, Highlight::SelectionType, WTFMove(ddHighlight), WTFMove(range)));
 }
 
-Ref<ServicesOverlayController::Highlight> ServicesOverlayController::Highlight::createForTelephoneNumber(ServicesOverlayController& controller, RetainPtr<DDHighlightRef> ddHighlight, Ref<Range>&& range)
+Ref<ServicesOverlayController::Highlight> ServicesOverlayController::Highlight::createForTelephoneNumber(ServicesOverlayController& controller, RetainPtr<DDHighlightRef>&& ddHighlight, SimpleRange&& range)
 {
-    return adoptRef(*new Highlight(controller, Highlight::TelephoneNumberType, ddHighlight, WTFMove(range)));
+    return adoptRef(*new Highlight(controller, Highlight::TelephoneNumberType, WTFMove(ddHighlight), WTFMove(range)));
 }
 
-ServicesOverlayController::Highlight::Highlight(ServicesOverlayController& controller, Type type, RetainPtr<DDHighlightRef> ddHighlight, Ref<WebCore::Range>&& range)
+ServicesOverlayController::Highlight::Highlight(ServicesOverlayController& controller, Type type, RetainPtr<DDHighlightRef>&& ddHighlight, SimpleRange&& range)
     : m_controller(&controller)
     , m_range(WTFMove(range))
     , m_graphicsLayer(GraphicsLayer::create(controller.page().chrome().client().graphicsLayerFactory(), *this))
@@ -474,7 +474,7 @@ void ServicesOverlayController::removeAllPotentialHighlightsOfType(Highlight::Ty
 
 void ServicesOverlayController::buildPhoneNumberHighlights()
 {
-    Vector<RefPtr<Range>> phoneNumberRanges;
+    Vector<SimpleRange> phoneNumberRanges;
     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
         phoneNumberRanges.appendVector(frame->editor().detectedTelephoneNumberRanges());
 
@@ -492,26 +492,25 @@ void ServicesOverlayController::buildPhoneNumberHighlights()
 
     for (auto& range : phoneNumberRanges) {
         // FIXME: This makes a big rect if the range extends from the end of one line to the start of the next. Handle that case better?
-        auto rect = enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(*range)));
+        auto rect = enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(range)));
 
         // Convert to the main document's coordinate space.
         // FIXME: It's a little crazy to call contentsToWindow and then windowToContents in order to get the right coordinate space.
         // We should consider adding conversion functions to ScrollView for contentsToDocument(). Right now, contentsToRootView() is
         // not equivalent to what we need when you have a topContentInset or a header banner.
-        auto* viewForRange = range->ownerDocument().view();
+        auto* viewForRange = range.start.document().view();
         if (!viewForRange)
             continue;
 
         rect.setLocation(mainFrameView.windowToContents(viewForRange->contentsToWindow(rect.location())));
 
         CGRect cgRect = rect;
-        
 #if HAVE(DD_HIGHLIGHT_CREATE_WITH_SCALE)
-        RetainPtr<DDHighlightRef> ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleScaleAndDirection(nullptr, &cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightStyleBubbleStandard | DDHighlightStyleStandardIconArrow, YES, NSWritingDirectionNatural, NO, YES, 0));
+        auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleScaleAndDirection(nullptr, &cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightStyleBubbleStandard | DDHighlightStyleStandardIconArrow, YES, NSWritingDirectionNatural, NO, YES, 0));
 #else
-        RetainPtr<DDHighlightRef> ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightStyleBubbleStandard | DDHighlightStyleStandardIconArrow, YES, NSWritingDirectionNatural, NO, YES));
+        auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightStyleBubbleStandard | DDHighlightStyleStandardIconArrow, YES, NSWritingDirectionNatural, NO, YES));
 #endif
-        newPotentialHighlights.add(Highlight::createForTelephoneNumber(*this, ddHighlight, range.releaseNonNull()));
+        newPotentialHighlights.add(Highlight::createForTelephoneNumber(*this, WTFMove(ddHighlight), WTFMove(range)));
     }
 
     replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::TelephoneNumberType);
@@ -544,17 +543,17 @@ void ServicesOverlayController::buildSelectionHighlight()
         for (auto& rect : m_currentSelectionRects) {
             IntRect currentRect = snappedIntRect(rect);
             currentRect.setLocation(mainFrameView->windowToContents(viewForRange->contentsToWindow(currentRect.location())));
-            cgRects.append((CGRect)currentRect);
+            cgRects.append(currentRect);
         }
 
         if (!cgRects.isEmpty()) {
             CGRect visibleRect = mainFrameView->visibleContentRect();
 #if HAVE(DD_HIGHLIGHT_CREATE_WITH_SCALE)
-            RetainPtr<DDHighlightRef> ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleScaleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightStyleBubbleNone | DDHighlightStyleStandardIconArrow | DDHighlightStyleButtonShowAlways, YES, NSWritingDirectionNatural, NO, YES, 0));
+            auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleScaleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightStyleBubbleNone | DDHighlightStyleStandardIconArrow | DDHighlightStyleButtonShowAlways, YES, NSWritingDirectionNatural, NO, YES, 0));
 #else
-            RetainPtr<DDHighlightRef> ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightStyleBubbleNone | DDHighlightStyleStandardIconArrow | DDHighlightStyleButtonShowAlways, YES, NSWritingDirectionNatural, NO, YES));
+            auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightStyleBubbleNone | DDHighlightStyleStandardIconArrow | DDHighlightStyleButtonShowAlways, YES, NSWritingDirectionNatural, NO, YES));
 #endif
-            newPotentialHighlights.add(Highlight::createForSelection(*this, ddHighlight, createLiveRange(*selectionRange)));
+            newPotentialHighlights.add(Highlight::createForSelection(*this, WTFMove(ddHighlight), WTFMove(*selectionRange)));
         }
     }
 
@@ -607,7 +606,7 @@ void ServicesOverlayController::createOverlayIfNeeded()
     m_page.pageOverlayController().installPageOverlay(WTFMove(overlay), PageOverlay::FadeMode::DoNotFade);
 }
 
-Vector<RefPtr<Range>> ServicesOverlayController::telephoneNumberRangesForFocusedFrame()
+Vector<SimpleRange> ServicesOverlayController::telephoneNumberRangesForFocusedFrame()
 {
     return m_page.focusController().focusedOrMainFrame().editor().detectedTelephoneNumberRanges();
 }
@@ -618,7 +617,7 @@ bool ServicesOverlayController::highlightsAreEquivalent(const Highlight* a, cons
         return true;
     if (!a || !b)
         return false;
-    return a->type() == b->type() && areRangesEqual(&a->range(), &b->range());
+    return a->type() == b->type() && a->range() == b->range();
 }
 
 ServicesOverlayController::Highlight* ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight(Highlight& selectionHighlight)
@@ -631,7 +630,7 @@ ServicesOverlayController::Highlight* ServicesOverlayController::findTelephoneNu
         return nullptr;
 
     for (auto& highlight : m_potentialHighlights) {
-        if (highlight->type() == Highlight::TelephoneNumberType && highlight->range().contains(createLiveRange(*selectionRange)))
+        if (highlight->type() == Highlight::TelephoneNumberType && createLiveRange(highlight->range())->contains(createLiveRange(*selectionRange)))
             return highlight.get();
     }
 
@@ -787,11 +786,11 @@ void ServicesOverlayController::handleClick(const IntPoint& clickPoint, Highligh
         Vector<String> selectedTelephoneNumbers;
         selectedTelephoneNumbers.reserveCapacity(telephoneNumberRanges.size());
         for (auto& range : telephoneNumberRanges)
-            selectedTelephoneNumbers.append(range->text());
+            selectedTelephoneNumbers.append(plainText(range));
 
         m_page.chrome().client().handleSelectionServiceClick(m_page.focusController().focusedOrMainFrame().selection(), selectedTelephoneNumbers, windowPoint);
     } else if (highlight.type() == Highlight::TelephoneNumberType)
-        m_page.chrome().client().handleTelephoneNumberClick(highlight.range().text(), windowPoint);
+        m_page.chrome().client().handleTelephoneNumberClick(plainText(highlight.range()), windowPoint);
 }
 
 Frame& ServicesOverlayController::mainFrame() const
index 5027990..21f6884 100644 (file)
@@ -40,6 +40,7 @@
 #import "NotImplemented.h"
 #import "Page.h"
 #import "Range.h"
+#import "SimpleRange.h"
 #import "StringTruncator.h"
 #import "TextIndicator.h"
 #import "TextRun.h"
@@ -135,8 +136,8 @@ DragImageRef createDragImageForLink(Element& linkElement, URL& url, const String
 
     CGRect imageRect = CGRectMake(0, 0, textWidth + 2 * dragImagePadding, textHeight + 2 * dragImagePadding);
 
-    RetainPtr<UIGraphicsImageRenderer> render = adoptNS([PAL::allocUIGraphicsImageRendererInstance() initWithSize:imageRect.size]);
-    UIImage *image = [render.get() imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
+    auto renderer = adoptNS([PAL::allocUIGraphicsImageRendererInstance() initWithSize:imageRect.size]);
+    auto image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
         GraphicsContext context(rendererContext.CGContext);
         context.translate(0, CGRectGetHeight(imageRect));
         context.scale({ 1, -1 });
@@ -146,8 +147,7 @@ DragImageRef createDragImageForLink(Element& linkElement, URL& url, const String
             urlFontCascade.get().drawText(context, TextRun(truncatedBottomString), FloatPoint(dragImagePadding, 40 + dragImagePadding));
     }];
 
-    auto linkRange = rangeOfContents(linkElement);
-    if (auto textIndicator = TextIndicator::createWithRange(linkRange, defaultLinkIndicatorOptions, TextIndicatorPresentationTransition::None, FloatSize()))
+    if (auto textIndicator = TextIndicator::createWithRange(makeRangeSelectingNodeContents(linkElement), defaultLinkIndicatorOptions, TextIndicatorPresentationTransition::None, FloatSize()))
         indicatorData = textIndicator->data();
 
     return image.CGImage;
@@ -191,17 +191,15 @@ DragImageRef createDragImageForSelection(Frame& frame, TextIndicatorData& indica
         imageRect.scale(1 / page->deviceScaleFactor());
 
 
-    RetainPtr<UIGraphicsImageRenderer> render = adoptNS([PAL::allocUIGraphicsImageRendererInstance() initWithSize:imageRect.size()]);
-    UIImage *finalImage = [render.get() imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
+    auto renderer = adoptNS([PAL::allocUIGraphicsImageRendererInstance() initWithSize:imageRect.size()]);
+    return [renderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
         GraphicsContext context(rendererContext.CGContext);
         // FIXME: The context flip here should not be necessary, and suggests that somewhere else in the regular
         // drag initiation flow, we unnecessarily flip the graphics context.
         context.translate(0, imageRect.height());
         context.scale({ 1, -1 });
         context.drawImage(*image, imageRect);
-    }];
-
-    return finalImage.CGImage;
+    }].CGImage;
 }
 
 DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
index 181d955..ed9515d 100644 (file)
@@ -1,3 +1,29 @@
+2020-04-26  Darin Adler  <darin@apple.com>
+
+        Replace more uses of live ranges with SimpleRange
+        https://bugs.webkit.org/show_bug.cgi?id=211058
+
+        Reviewed by Antti Koivisto.
+
+        * Shared/API/Cocoa/WKDataDetectorTypesInternal.h:
+        (fromWKDataDetectorTypes): Updated since DataDetectorTypes
+        is now an enum class. Also got rid of special "none" and "all" values.
+
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInRangeHandle.mm:
+        (-[WKWebProcessPlugInRangeHandle detectDataWithTypes:context:]): Updated
+        since DataDetection now takes a SimpleRange.
+
+        * WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
+        (WebKit::ViewGestureGeometryCollector::computeTextLegibilityScales):
+        Use SimpleRange.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::detectDataInAllFrames): Ditto.
+
+        * WebProcess/WebPage/WebPage.h: Removed unneeded include of DataDetection.h.
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::performImmediateActionHitTestAtLocation): Use SimpleRange.
+
 2020-04-27  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK4] Make it possible to build with GTK4 without errors
index 3e8f02e..4b8c5c5 100644 (file)
 
 static inline WebCore::DataDetectorTypes fromWKDataDetectorTypes(uint64_t types)
 {
-    if (static_cast<WKDataDetectorTypes>(types) == WKDataDetectorTypeNone)
-        return WebCore::DataDetectorTypeNone;
-    if (static_cast<WKDataDetectorTypes>(types) == WKDataDetectorTypeAll)
-        return WebCore::DataDetectorTypeAll;
-
-    uint32_t value = WebCore::DataDetectorTypeNone;
+    uint32_t value = 0;
     if (types & WKDataDetectorTypePhoneNumber)
-        value |= WebCore::DataDetectorTypePhoneNumber;
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::PhoneNumber);
     if (types & WKDataDetectorTypeLink)
-        value |= WebCore::DataDetectorTypeLink;
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::Link);
     if (types & WKDataDetectorTypeAddress)
-        value |= WebCore::DataDetectorTypeAddress;
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::Address);
     if (types & WKDataDetectorTypeCalendarEvent)
-        value |= WebCore::DataDetectorTypeCalendarEvent;
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::CalendarEvent);
     if (types & WKDataDetectorTypeTrackingNumber)
-        value |= WebCore::DataDetectorTypeTrackingNumber;
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::TrackingNumber);
     if (types & WKDataDetectorTypeFlightNumber)
-        value |= WebCore::DataDetectorTypeFlightNumber;
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::FlightNumber);
     if (types & WKDataDetectorTypeLookupSuggestion)
-        value |= WebCore::DataDetectorTypeLookupSuggestion;
-
+        value |= static_cast<uint32_t>(WebCore::DataDetectorTypes::LookupSuggestion);
     return static_cast<WebCore::DataDetectorTypes>(value);
 }
 
index c8de688..07676a0 100644 (file)
 }
 
 #if TARGET_OS_IPHONE
+
 - (NSArray *)detectDataWithTypes:(WKDataDetectorTypes)types context:(NSDictionary *)context
 {
 #if ENABLE(DATA_DETECTION)
-    RefPtr<WebCore::Range> coreRange = &_rangeHandle->coreRange();
-    return WebCore::DataDetection::detectContentInRange(coreRange, fromWKDataDetectorTypes(types), context);
+    return WebCore::DataDetection::detectContentInRange(_rangeHandle->coreRange(), fromWKDataDetectorTypes(types), context);
 #else
     return nil;
 #endif
 }
+
 #endif
 
 - (WebKit::InjectedBundleRangeHandle&)_rangeHandle
index b0e6522..e160cea 100644 (file)
@@ -156,13 +156,12 @@ Optional<std::pair<double, double>> ViewGestureGeometryCollector::computeTextLeg
 
     document->updateLayoutIgnorePendingStylesheets();
 
-    auto documentRange = Range::create(*document, {{ document->documentElement(), Position::PositionIsBeforeAnchor }}, {{ document->documentElement(), Position::PositionIsAfterAnchor }});
     HashSet<Node*> allTextNodes;
     HashMap<unsigned, unsigned> fontSizeToCountMap;
     unsigned numberOfIterations = 0;
     unsigned totalSampledTextLength = 0;
 
-    for (TextIterator documentTextIterator { documentRange.get(), TextIteratorEntersTextControls }; !documentTextIterator.atEnd(); documentTextIterator.advance()) {
+    for (TextIterator documentTextIterator { makeRangeSelectingNodeContents(*document), TextIteratorEntersTextControls }; !documentTextIterator.atEnd(); documentTextIterator.advance()) {
         if (++numberOfIterations >= maximumNumberOfTextRunsToConsider)
             break;
 
index 45634c6..9356537 100644 (file)
@@ -3731,9 +3731,7 @@ void WebPage::detectDataInAllFrames(uint64_t types, CompletionHandler<void(const
         auto document = makeRefPtr(frame->document());
         if (!document)
             continue;
-
-        RefPtr<Range> range = Range::create(*document, Position { document.get(), Position::PositionIsBeforeChildren }, Position { document.get(), Position::PositionIsAfterChildren });
-        frame->setDataDetectionResults(DataDetection::detectContentInRange(range, dataDetectorTypes, m_dataDetectionContext.get()));
+        frame->setDataDetectionResults(DataDetection::detectContentInRange(makeRangeSelectingNodeContents(*document), dataDetectorTypes, m_dataDetectionContext.get()));
     }
     completionHandler({ m_page->mainFrame().dataDetectionResults() });
 }
index 4f11a53..5b547da 100644 (file)
@@ -129,10 +129,6 @@ typedef struct _AtkObject AtkObject;
 #include <WebCore/PlatformTouchEvent.h>
 #endif
 
-#if ENABLE(DATA_DETECTION)
-#include <WebCore/DataDetection.h>
-#endif
-
 #if ENABLE(MAC_GESTURE_EVENTS)
 #include <WebKitAdditions/PlatformGestureEventMac.h>
 #endif
index 073fc1e..89cc90f 100644 (file)
@@ -857,7 +857,7 @@ void WebPage::performImmediateActionHitTestAtLocation(WebCore::FloatPoint locati
     URL absoluteLinkURL = hitTestResult.absoluteLinkURL();
     Element* URLElement = hitTestResult.URLElement();
     if (!absoluteLinkURL.isEmpty() && URLElement)
-        immediateActionResult.linkTextIndicator = TextIndicator::createWithRange(rangeOfContents(*URLElement), TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges, TextIndicatorPresentationTransition::FadeIn);
+        immediateActionResult.linkTextIndicator = TextIndicator::createWithRange(makeRangeSelectingNodeContents(*URLElement), TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges, TextIndicatorPresentationTransition::FadeIn);
 
     auto lookupResult = lookupTextAtLocation(locationInViewCoordinates);
     if (auto* lookupRange = std::get<RefPtr<Range>>(lookupResult).get()) {
@@ -895,12 +895,11 @@ void WebPage::performImmediateActionHitTestAtLocation(WebCore::FloatPoint locati
 
     // FIXME: Avoid scanning if we will just throw away the result (e.g. we're over a link).
     if (!pageOverlayDidOverrideDataDetectors && hitTestResult.innerNode() && (hitTestResult.innerNode()->isTextNode() || hitTestResult.isOverTextInsideFormControlElement())) {
-        FloatRect detectedDataBoundingBox;
-        RefPtr<Range> detectedDataRange;
-        immediateActionResult.detectedDataActionContext = DataDetection::detectItemAroundHitTestResult(hitTestResult, detectedDataBoundingBox, detectedDataRange);
-        if (immediateActionResult.detectedDataActionContext && detectedDataRange) {
-            immediateActionResult.detectedDataBoundingBox = detectedDataBoundingBox;
-            immediateActionResult.detectedDataTextIndicator = TextIndicator::createWithRange(*detectedDataRange, TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges, TextIndicatorPresentationTransition::FadeIn);
+        if (auto result = DataDetection::detectItemAroundHitTestResult(hitTestResult)) {
+            immediateActionResult.detectedDataActionContext = WTFMove(result->actionContext);
+            immediateActionResult.detectedDataBoundingBox = result->boundingBox;
+            immediateActionResult.detectedDataTextIndicator = TextIndicator::createWithRange(result->range,
+                TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges, TextIndicatorPresentationTransition::FadeIn);
         }
     }
 
index 9ffe429..0ebe435 100644 (file)
@@ -1,3 +1,21 @@
+2020-04-26  Darin Adler  <darin@apple.com>
+
+        Replace more uses of live ranges with SimpleRange
+        https://bugs.webkit.org/show_bug.cgi?id=211058
+
+        Reviewed by Antti Koivisto.
+
+        * DOM/DOM.mm:
+        (-[DOMNode getPreviewSnapshotImage:andRects:]): Use SimpleRange.
+        * WebCoreSupport/WebContextMenuClient.mm:
+        (WebContextMenuClient::imageForCurrentSharingServicePickerItem): Ditto.
+
+        * WebView/WebImmediateActionController.mm:
+        (-[WebImmediateActionController _animationControllerForDataDetectedText]):
+        Updated to use DetectedItem and SimpleRange.
+        (+[WebImmediateActionController _dictionaryPopupInfoForRange:inFrame:withLookupOptions:indicatorOptions:transition:]):
+        Ditto.
+
 2020-04-27  Rob Buis  <rbuis@igalia.com>
 
         Make loadURLIntoChildFrame private and non-exported
index df0b520..5f060b0 100644 (file)
@@ -523,10 +523,8 @@ id <DOMEventTarget> kit(EventTarget* target)
 
     auto& node = *core(self);
 
-    auto range = rangeOfContents(node);
-
     const float margin = 4 / node.document().page()->pageScaleFactor();
-    auto textIndicator = TextIndicator::createWithRange(range, TextIndicatorOptionTightlyFitContent |
+    auto textIndicator = TextIndicator::createWithRange(makeRangeSelectingNodeContents(node), TextIndicatorOptionTightlyFitContent |
         TextIndicatorOptionRespectTextColor |
         TextIndicatorOptionPaintBackgrounds |
         TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges |
index 806da0b..256e689 100644 (file)
@@ -148,6 +148,7 @@ bool WebContextMenuClient::clientFloatRectForNode(Node& node, FloatRect& rect) c
 }
 
 #if ENABLE(SERVICE_CONTROLS)
+
 void WebContextMenuClient::sharingServicePickerWillBeDestroyed(WebSharingServicePickerController &)
 {
     m_sharingServicePickerController = nil;
@@ -183,15 +184,15 @@ WebCore::FloatRect WebContextMenuClient::screenRectForCurrentSharingServicePicke
 
 RetainPtr<NSImage> WebContextMenuClient::imageForCurrentSharingServicePickerItem(WebSharingServicePickerController &)
 {
-    Page* page = [m_webView page];
+    auto page = [m_webView page];
     if (!page)
         return nil;
 
-    Node* node = page->contextMenuController().context().hitTestResult().innerNode();
+    auto node = makeRefPtr(page->contextMenuController().context().hitTestResult().innerNode());
     if (!node)
         return nil;
 
-    FrameView* frameView = node->document().view();
+    auto frameView = makeRefPtr(node->document().view());
     if (!frameView) {
         // This method shouldn't be called in cases where the controlled node isn't in a rendered view.
         ASSERT_NOT_REACHED();
@@ -203,15 +204,14 @@ RetainPtr<NSImage> WebContextMenuClient::imageForCurrentSharingServicePickerItem
         return nil;
 
     // This is effectively a snapshot, and will be painted in an unaccelerated fashion in line with FrameSnapshotting.
-    std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(rect.size(), RenderingMode::Unaccelerated);
+    auto buffer = ImageBuffer::create(rect.size(), RenderingMode::Unaccelerated);
     if (!buffer)
         return nil;
 
-    VisibleSelection oldSelection = frameView->frame().selection().selection();
-    auto range = Range::create(node->document(), Position(node, Position::PositionIsBeforeAnchor), Position(node, Position::PositionIsAfterAnchor));
-    frameView->frame().selection().setSelection(VisibleSelection(range.get()), FrameSelection::DoNotSetFocus);
+    auto oldSelection = frameView->frame().selection().selection();
+    frameView->frame().selection().setSelection(*makeRangeSelectingNode(*node), FrameSelection::DoNotSetFocus);
 
-    OptionSet<PaintBehavior> oldPaintBehavior = frameView->paintBehavior();
+    auto oldPaintBehavior = frameView->paintBehavior();
     frameView->setPaintBehavior(PaintBehavior::SelectionOnly);
 
     buffer->context().translate(-toFloatSize(rect.location()));
@@ -220,12 +220,13 @@ RetainPtr<NSImage> WebContextMenuClient::imageForCurrentSharingServicePickerItem
     frameView->frame().selection().setSelection(oldSelection);
     frameView->setPaintBehavior(oldPaintBehavior);
 
-    RefPtr<Image> image = ImageBuffer::sinkIntoImage(WTFMove(buffer));
+    auto image = ImageBuffer::sinkIntoImage(WTFMove(buffer));
     if (!image)
         return nil;
 
     return image->snapshotNSImage();
 }
+
 #endif
 
 NSMenu *WebContextMenuClient::contextMenuForEvent(NSEvent *event, NSView *view, bool& isServicesMenu)
index b55d155..ea11b73 100644 (file)
@@ -411,35 +411,37 @@ static WebCore::IntRect elementBoundingBoxInWindowCoordinatesFromNode(WebCore::N
     if (!DataDetectorsLibrary())
         return nil;
 
-    RefPtr<WebCore::Range> detectedDataRange;
-    WebCore::FloatRect detectedDataBoundingBox;
-    RetainPtr<DDActionContext> actionContext;
+    Optional<WebCore::DetectedItem> detectedItem;
 
     if ([[_webView UIDelegate] respondsToSelector:@selector(_webView:actionContextForHitTestResult:range:)]) {
-        RetainPtr<WebElementDictionary> hitTestDictionary = adoptNS([[WebElementDictionary alloc] initWithHitTestResult:_hitTestResult]);
-
         DOMRange *customDataDetectorsRange;
-        actionContext = [(id)[_webView UIDelegate] _webView:_webView actionContextForHitTestResult:hitTestDictionary.get() range:&customDataDetectorsRange];
-
-        if (actionContext && customDataDetectorsRange)
-            detectedDataRange = core(customDataDetectorsRange);
+        auto actionContext = [(id)[_webView UIDelegate] _webView:_webView
+            actionContextForHitTestResult:adoptNS([[WebElementDictionary alloc] initWithHitTestResult:_hitTestResult]).get()
+            range:&customDataDetectorsRange];
+        if (actionContext && customDataDetectorsRange) {
+            detectedItem = { {
+                actionContext,
+                { }, // FIXME: Seems like an empty rect isn't really OK.
+                *core(customDataDetectorsRange)
+            } };
+        }
     }
 
     // If the client didn't give us an action context, try to scan around the hit point.
-    if (!actionContext || !detectedDataRange)
-        actionContext = WebCore::DataDetection::detectItemAroundHitTestResult(_hitTestResult, detectedDataBoundingBox, detectedDataRange);
+    if (!detectedItem)
+        detectedItem = WebCore::DataDetection::detectItemAroundHitTestResult(_hitTestResult);
 
-    if (!actionContext || !detectedDataRange)
+    if (!detectedItem)
         return nil;
 
-    [actionContext setAltMode:YES];
-    [actionContext setImmediate:YES];
-    if (![[getDDActionsManagerClass() sharedManager] hasActionsForResult:[actionContext mainResult] actionContext:actionContext.get()])
+    [detectedItem->actionContext setAltMode:YES];
+    [detectedItem->actionContext setImmediate:YES];
+    if (![[getDDActionsManagerClass() sharedManager] hasActionsForResult:[detectedItem->actionContext mainResult] actionContext:detectedItem->actionContext.get()])
         return nil;
 
-    auto indicator = WebCore::TextIndicator::createWithRange(*detectedDataRange, WebCore::TextIndicatorOptionDefault, WebCore::TextIndicatorPresentationTransition::FadeIn);
+    auto indicator = WebCore::TextIndicator::createWithRange(createLiveRange(detectedItem->range), WebCore::TextIndicatorOptionDefault, WebCore::TextIndicatorPresentationTransition::FadeIn);
 
-    _currentActionContext = [actionContext contextForView:_webView altMode:YES interactionStartedHandler:^() {
+    _currentActionContext = [detectedItem->actionContext contextForView:_webView altMode:YES interactionStartedHandler:^() {
     } interactionChangedHandler:^() {
         if (indicator)
             [_webView _setTextIndicator:*indicator withLifetime:WebCore::TextIndicatorWindowLifetime::Permanent];
@@ -447,7 +449,7 @@ static WebCore::IntRect elementBoundingBoxInWindowCoordinatesFromNode(WebCore::N
         [_webView _clearTextIndicatorWithAnimation:WebCore::TextIndicatorWindowDismissalAnimation::FadeOut];
     }];
 
-    [_currentActionContext setHighlightFrame:[_webView.window convertRectToScreen:detectedDataBoundingBox]];
+    [_currentActionContext setHighlightFrame:[_webView.window convertRectToScreen:detectedItem->boundingBox]];
 
     NSArray *menuItems = [[getDDActionsManagerClass() sharedManager] menuItemsForResult:[_currentActionContext mainResult] actionContext:_currentActionContext.get()];
     if (menuItems.count != 1)
@@ -536,7 +538,7 @@ static WebCore::IntRect elementBoundingBoxInWindowCoordinatesFromNode(WebCore::N
 
     popupInfo.attributedString = scaledAttributedString.get();
 
-    if (auto textIndicator = WebCore::TextIndicator::createWithRange(createLiveRange(range), indicatorOptions, presentationTransition))
+    if (auto textIndicator = WebCore::TextIndicator::createWithRange(range, indicatorOptions, presentationTransition))
         popupInfo.textIndicator = textIndicator->data();
 
     editor.setIsGettingDictionaryPopupInfo(false);