<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[266026] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/266026">266026</a></dd>
<dt>Author</dt> <dd>darin@apple.com</dd>
<dt>Date</dt> <dd>2020-08-22 09:11:58 -0700 (Sat, 22 Aug 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>Create documentOrder function, start refactoring to use it instead of Range::compare functions
https://bugs.webkit.org/show_bug.cgi?id=215551

Reviewed by Chris Dumez.

Source/WebCore:

* WebCore.xcodeproj/project.pbxproj: Make TextControlInnerElements.h Private so
we can use it from unit tests.

* accessibility/AccessibilityNodeObject.cpp:
(WebCore::AccessibilityNodeObject::text const): Tweak code slightly.

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::selectedTextRange const): Always use the native
text control's idea of the selected text range. There is no need to use the
document-based range with any of these native text controls. The check before would
almost always return true, except for unusual cases, particularly combo box, which
returns false for isARIATextControl. We may want to change isARIATextControl to
return true for combo box, but it's not necessary for this fix. Without this change,
a test involving a combo box was failing because changes caused
documentBasedSelectedTextRange to no longer accidentally do the right thing.

* dom/BoundaryPoint.h: Added != and documentOrder.

* dom/Document.h: Export allocation function and constructor  so we can allocate
in a unit test.

* dom/Node.cpp:
(WebCore::connectedInSameTreeScope): Renamed from areNodesConnectedInSameTreeScope.
(WebCore::Node::compareDocumentPosition): Updated for name change above.
(WebCore::depth): Changed to take a const& and to walk acrosss shadow host boundaries,
so this can be used in algorithms that are intended to work on the combined tree.
Has no effect when called on nodes that are not in a shadow tree.
(WebCore::commonInclusiveAncestorAndChildren): Refactored so this can be used by
callers that need to know the distinct ancestor children as well as the common
ancestor. Also revised it to work across shadow tree boundaries.
(WebCore::commonInclusiveAncestor): Updated to call commonInclusiveAncestorAndChildren.
(WebCore::isSiblingSubsequent): Added.
(WebCore::documentOrder): Added. Implemented using commonInclusiveAncestorAndChildren and
isSiblingSubsequent.
* dom/Node.h: Updated for above. Also added PartialOrdering class, a compatible
subset of C++20's std::partial_ordering, for return value for documentOrder.

* dom/Position.cpp:
(WebCore::Position::computeOffsetInContainerNode const): Removed clamping the
result to the length of the container node; not needed.
(WebCore::Position::previous const): Updated for name change.
(WebCore::Position::next const): Updated for name change.
(WebCore::Position::upstream const): Updated for name change.
(WebCore::Position::downstream const): Updated for name change.
(WebCore::commonInclusiveAncestor): Renamed from commonShadowIncludingAncestor
since this is now the same as the commonInclusiveAncestor that takes two nodes;
they now both take shadow trees into account.
(WebCore::makeContainerOffsetPosition): Added. Clearer way to construct
positions from containers and offsets. An alternative to makeDeprecatedLegacyPosition
for cases where we don't need the deprecated legacy behavior.
(WebCore::makeDeprecatedLegacyPosition): Renamed from createLegacyEditingPosition.
Adding the word "deprecated" to be clearer that this is not just "legacy" but also
something we are trying to get rid of. Changing from "create" to "make" because
this does not allocate memory on the heap.
(WebCore::documentOrder): Added. Still to do: more optimized implementation when
we can compare two positions without computing node offsets.

* dom/Position.h: Updated for above.
(WebCore::minOffsetForNode): Deleted.

* dom/RadioButtonGroups.cpp:
(WebCore::RadioButtonGroup::members const): Use documentOrder instead of
documentOrderComparator.

* dom/Range.cpp:
(WebCore::areRangesEqual): Rewrote to not use Position.
(WebCore::rangesOverlap): Updated for name change.
(WebCore::Range::expand): Rewrote to not use Range::start/endPosition.
(WebCore::operator<<): Deleted.

* dom/Range.h: Removed now-unused Range::start/endPosition, documentOrderComparator,
and TextStream operators.

* dom/RangeBoundaryPoint.h: Removed now-unused RangeBoundaryPoint::toPosition.
Added makeBoundaryPoint function to convert RangeBoundaryPoint into BoundaryPoint.

* dom/SimpleRange.cpp:
(WebCore::isOffsetBeforeChild): Added. For use by documentOrder.
(WebCore::documentOrder): Added.

* editing/TextIterator.cpp:
(WebCore::characterCount): Use documentOrder instead of
Range::compareBoundaryPoints.

* editing/VisiblePosition.cpp:
(WebCore::areVisiblePositionsInSameTreeScope): Updated for name change.

* editing/VisiblePosition.h: Use assignment insteed of calling clear,
to possibly prepare to get rid of Position::clear in the future.
Added a documentORder function that takes two visible positions.

* editing/cocoa/HTMLConverter.mm:
(HTMLConverterCaches::cacheAncestorsOfStartToBeConverted): Use
commonInclusiveAncestor instead of commonShadowIncludingAncestor.
* editing/markup.cpp:
(WebCore::serializePreservingVisualAppearanceInternal): Ditto.

* html/HTMLBodyElement.h: Export create function so it can used in unit tests.
* html/HTMLDivElement.h: Ditto.
* html/HTMLHtmlElement.h: Ditto.
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::create): Added so it can be used in unit tests.
* html/HTMLTextAreaElement.h: Ditto. Also export the innerTextElement function
so it can be used in unit tests.

* page/DOMSelection.cpp:
(WebCore::DOMSelection::addRange): Use makeDeprecatedLegacyPosition directly
rather than using Range::start/endPosition. This was the only place in WebCore
still using Range::start/endPosition and over time we would like to move from
makeDeprecatedLegacyPosition to makeContainerOffsetPosition, so it's good to
have it be explicit here rather than hidden inside the Range class.
(WebCore::DOMSelection::containsNode const): Added a check of containingShadowRoot.
This preserves the old behavior. Before, constructing the range resulted in
a collapsed range when the shadow tree was involved. This is a more direct way
to achieve the same result.

* page/Page.cpp:
(WebCore::replaceRanges): Use documentOrder instead of comparePositions.
Eventually we will delete comparePositions.

Source/WebKit:

* WebProcess/InjectedBundle/API/mac/WKDOMRange.mm:
(-[WKDOMRange rangeByExpandingToWordBoundaryByCharacters:inDirection:]):
Use makeDeprecatedLegacyPosition instead of Range::start/endPosition.
This was the only place in the WebKit framework still using
Range::start/endPosition and over time we would like to move from
makeDeprecatedLegacyPosition to makeContainerOffsetPosition, so it's good
to have it be explicit here rather than hidden inside the Range class.

Source/WebKitLegacy/ios:

* WebCoreSupport/WebVisiblePosition.mm:
(-[DOMRange startPosition]): Rewrote to not use Range::startPosition.
(-[DOMRange endPosition]): Rewrote to not use Range::endPosition.

Source/WebKitLegacy/mac:

* WebView/WebFrame.mm:
(-[WebFrame _smartInsertForString:replacingRange:beforeString:afterString:]):
Rewrite to use makeSimpleRange and makeContainerOffsetPosition. Simplifies
the null checks. Would love to remove the function but at this time it's
still used by Apple's Mail app (albeit in a peculiar way, always passing a
constant string).

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added DocumentOrder.cpp.
* TestWebKitAPI/Tests/WebCore/DocumentOrder.cpp: Added.
Relatively thorough test of three different documentOrder functions.
Could still use even more test cases involving different types of shadow trees.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityNodeObjectcpp">trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityRenderObjectcpp">trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp</a></li>
<li><a href="#trunkSourceWebCoredomBoundaryPointh">trunk/Source/WebCore/dom/BoundaryPoint.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumenth">trunk/Source/WebCore/dom/Document.h</a></li>
<li><a href="#trunkSourceWebCoredomNodecpp">trunk/Source/WebCore/dom/Node.cpp</a></li>
<li><a href="#trunkSourceWebCoredomNodeh">trunk/Source/WebCore/dom/Node.h</a></li>
<li><a href="#trunkSourceWebCoredomPositioncpp">trunk/Source/WebCore/dom/Position.cpp</a></li>
<li><a href="#trunkSourceWebCoredomPositionh">trunk/Source/WebCore/dom/Position.h</a></li>
<li><a href="#trunkSourceWebCoredomRadioButtonGroupscpp">trunk/Source/WebCore/dom/RadioButtonGroups.cpp</a></li>
<li><a href="#trunkSourceWebCoredomRangecpp">trunk/Source/WebCore/dom/Range.cpp</a></li>
<li><a href="#trunkSourceWebCoredomRangeh">trunk/Source/WebCore/dom/Range.h</a></li>
<li><a href="#trunkSourceWebCoredomRangeBoundaryPointh">trunk/Source/WebCore/dom/RangeBoundaryPoint.h</a></li>
<li><a href="#trunkSourceWebCoredomSimpleRangecpp">trunk/Source/WebCore/dom/SimpleRange.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingTextIteratorcpp">trunk/Source/WebCore/editing/TextIterator.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisiblePositioncpp">trunk/Source/WebCore/editing/VisiblePosition.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisiblePositionh">trunk/Source/WebCore/editing/VisiblePosition.h</a></li>
<li><a href="#trunkSourceWebCoreeditingcocoaHTMLConvertermm">trunk/Source/WebCore/editing/cocoa/HTMLConverter.mm</a></li>
<li><a href="#trunkSourceWebCoreeditingmarkupcpp">trunk/Source/WebCore/editing/markup.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLBodyElementh">trunk/Source/WebCore/html/HTMLBodyElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLDivElementh">trunk/Source/WebCore/html/HTMLDivElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLHtmlElementh">trunk/Source/WebCore/html/HTMLHtmlElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLTextAreaElementcpp">trunk/Source/WebCore/html/HTMLTextAreaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLTextAreaElementh">trunk/Source/WebCore/html/HTMLTextAreaElement.h</a></li>
<li><a href="#trunkSourceWebCorepageDOMSelectioncpp">trunk/Source/WebCore/page/DOMSelection.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePagecpp">trunk/Source/WebCore/page/Page.cpp</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitWebProcessInjectedBundleAPImacWKDOMRangemm">trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKDOMRange.mm</a></li>
<li><a href="#trunkSourceWebKitLegacyiosChangeLog">trunk/Source/WebKitLegacy/ios/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitLegacyiosWebCoreSupportWebVisiblePositionmm">trunk/Source/WebKitLegacy/ios/WebCoreSupport/WebVisiblePosition.mm</a></li>
<li><a href="#trunkSourceWebKitLegacymacChangeLog">trunk/Source/WebKitLegacy/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitLegacymacWebViewWebFramemm">trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreDocumentOrdercpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/DocumentOrder.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/ChangeLog      2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1,3 +1,130 @@
</span><ins>+2020-08-17  Darin Adler  <darin@apple.com>
+
+        Create documentOrder function, start refactoring to use it instead of Range::compare functions
+        https://bugs.webkit.org/show_bug.cgi?id=215551
+
+        Reviewed by Chris Dumez.
+
+        * WebCore.xcodeproj/project.pbxproj: Make TextControlInnerElements.h Private so
+        we can use it from unit tests.
+
+        * accessibility/AccessibilityNodeObject.cpp:
+        (WebCore::AccessibilityNodeObject::text const): Tweak code slightly.
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::selectedTextRange const): Always use the native
+        text control's idea of the selected text range. There is no need to use the
+        document-based range with any of these native text controls. The check before would
+        almost always return true, except for unusual cases, particularly combo box, which
+        returns false for isARIATextControl. We may want to change isARIATextControl to
+        return true for combo box, but it's not necessary for this fix. Without this change,
+        a test involving a combo box was failing because changes caused
+        documentBasedSelectedTextRange to no longer accidentally do the right thing.
+
+        * dom/BoundaryPoint.h: Added != and documentOrder.
+
+        * dom/Document.h: Export allocation function and constructor  so we can allocate
+        in a unit test.
+
+        * dom/Node.cpp:
+        (WebCore::connectedInSameTreeScope): Renamed from areNodesConnectedInSameTreeScope.
+        (WebCore::Node::compareDocumentPosition): Updated for name change above.
+        (WebCore::depth): Changed to take a const& and to walk acrosss shadow host boundaries,
+        so this can be used in algorithms that are intended to work on the combined tree.
+        Has no effect when called on nodes that are not in a shadow tree.
+        (WebCore::commonInclusiveAncestorAndChildren): Refactored so this can be used by
+        callers that need to know the distinct ancestor children as well as the common
+        ancestor. Also revised it to work across shadow tree boundaries.
+        (WebCore::commonInclusiveAncestor): Updated to call commonInclusiveAncestorAndChildren.
+        (WebCore::isSiblingSubsequent): Added.
+        (WebCore::documentOrder): Added. Implemented using commonInclusiveAncestorAndChildren and
+        isSiblingSubsequent.
+        * dom/Node.h: Updated for above. Also added PartialOrdering class, a compatible
+        subset of C++20's std::partial_ordering, for return value for documentOrder.
+
+        * dom/Position.cpp:
+        (WebCore::Position::computeOffsetInContainerNode const): Removed clamping the
+        result to the length of the container node; not needed.
+        (WebCore::Position::previous const): Updated for name change.
+        (WebCore::Position::next const): Updated for name change.
+        (WebCore::Position::upstream const): Updated for name change.
+        (WebCore::Position::downstream const): Updated for name change.
+        (WebCore::commonInclusiveAncestor): Renamed from commonShadowIncludingAncestor
+        since this is now the same as the commonInclusiveAncestor that takes two nodes;
+        they now both take shadow trees into account.
+        (WebCore::makeContainerOffsetPosition): Added. Clearer way to construct
+        positions from containers and offsets. An alternative to makeDeprecatedLegacyPosition
+        for cases where we don't need the deprecated legacy behavior.
+        (WebCore::makeDeprecatedLegacyPosition): Renamed from createLegacyEditingPosition.
+        Adding the word "deprecated" to be clearer that this is not just "legacy" but also
+        something we are trying to get rid of. Changing from "create" to "make" because
+        this does not allocate memory on the heap.
+        (WebCore::documentOrder): Added. Still to do: more optimized implementation when
+        we can compare two positions without computing node offsets.
+
+        * dom/Position.h: Updated for above.
+        (WebCore::minOffsetForNode): Deleted.
+
+        * dom/RadioButtonGroups.cpp:
+        (WebCore::RadioButtonGroup::members const): Use documentOrder instead of
+        documentOrderComparator.
+
+        * dom/Range.cpp:
+        (WebCore::areRangesEqual): Rewrote to not use Position.
+        (WebCore::rangesOverlap): Updated for name change.
+        (WebCore::Range::expand): Rewrote to not use Range::start/endPosition.
+        (WebCore::operator<<): Deleted.
+
+        * dom/Range.h: Removed now-unused Range::start/endPosition, documentOrderComparator,
+        and TextStream operators.
+
+        * dom/RangeBoundaryPoint.h: Removed now-unused RangeBoundaryPoint::toPosition.
+        Added makeBoundaryPoint function to convert RangeBoundaryPoint into BoundaryPoint.
+
+        * dom/SimpleRange.cpp:
+        (WebCore::isOffsetBeforeChild): Added. For use by documentOrder.
+        (WebCore::documentOrder): Added.
+
+        * editing/TextIterator.cpp:
+        (WebCore::characterCount): Use documentOrder instead of
+        Range::compareBoundaryPoints.
+
+        * editing/VisiblePosition.cpp:
+        (WebCore::areVisiblePositionsInSameTreeScope): Updated for name change.
+
+        * editing/VisiblePosition.h: Use assignment insteed of calling clear,
+        to possibly prepare to get rid of Position::clear in the future.
+        Added a documentORder function that takes two visible positions.
+
+        * editing/cocoa/HTMLConverter.mm:
+        (HTMLConverterCaches::cacheAncestorsOfStartToBeConverted): Use
+        commonInclusiveAncestor instead of commonShadowIncludingAncestor.
+        * editing/markup.cpp:
+        (WebCore::serializePreservingVisualAppearanceInternal): Ditto.
+
+        * html/HTMLBodyElement.h: Export create function so it can used in unit tests.
+        * html/HTMLDivElement.h: Ditto.
+        * html/HTMLHtmlElement.h: Ditto.
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::create): Added so it can be used in unit tests.
+        * html/HTMLTextAreaElement.h: Ditto. Also export the innerTextElement function
+        so it can be used in unit tests.
+
+        * page/DOMSelection.cpp:
+        (WebCore::DOMSelection::addRange): Use makeDeprecatedLegacyPosition directly
+        rather than using Range::start/endPosition. This was the only place in WebCore
+        still using Range::start/endPosition and over time we would like to move from
+        makeDeprecatedLegacyPosition to makeContainerOffsetPosition, so it's good to
+        have it be explicit here rather than hidden inside the Range class.
+        (WebCore::DOMSelection::containsNode const): Added a check of containingShadowRoot.
+        This preserves the old behavior. Before, constructing the range resulted in
+        a collapsed range when the shadow tree was involved. This is a more direct way
+        to achieve the same result.
+
+        * page/Page.cpp:
+        (WebCore::replaceRanges): Use documentOrder instead of comparePositions.
+        Eventually we will delete comparePositions.
+
</ins><span class="cx"> 2020-08-22  Philippe Normand  <pnormand@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [GTK][WPE] Compilation warnings with clang/gcc 10
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj   2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj      2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -405,7 +405,7 @@
</span><span class="cx">          141DC053164834B900371E5A /* LayoutRect.h in Headers */ = {isa = PBXBuildFile; fileRef = 141DC04D164834B900371E5A /* LayoutRect.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          141DC054164834B900371E5A /* LayoutSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 141DC04E164834B900371E5A /* LayoutSize.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          142011B70A003133008303F9 /* JSCSSStyleDeclaration.h in Headers */ = {isa = PBXBuildFile; fileRef = 142011B50A003133008303F9 /* JSCSSStyleDeclaration.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-               142B97CA13138943008BEF4B /* TextControlInnerElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 142B97C813138943008BEF4B /* TextControlInnerElements.h */; };
</del><ins>+                142B97CA13138943008BEF4B /* TextControlInnerElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 142B97C813138943008BEF4B /* TextControlInnerElements.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">           1432E8470C51493800B1500F /* GCController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1432E8460C51493800B1500F /* GCController.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          14476AA815DC4BB100305DB2 /* WritingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 14476AA715DC4BB100305DB2 /* WritingMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          1449E24C107D4A8400B5793F /* JSCallbackData.h in Headers */ = {isa = PBXBuildFile; fileRef = 1449E24A107D4A8400B5793F /* JSCallbackData.h */; };
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityNodeObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp   2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp      2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1940,17 +1940,15 @@
</span><span class="cx">     if (!isTextControl())
</span><span class="cx">         return String();
</span><span class="cx"> 
</span><del>-    Node* node = this->node();
-    if (!node)
</del><ins>+    auto node = this->node();
+    if (!is<Element>(node))
</ins><span class="cx">         return String();
</span><span class="cx"> 
</span><del>-    if (isNativeTextControl() && is<HTMLTextFormControlElement>(*node))
-        return downcast<HTMLTextFormControlElement>(*node).value();
</del><ins>+    auto& element = downcast<Element>(*node);
+    if (isNativeTextControl() && is<HTMLTextFormControlElement>(element))
+        return downcast<HTMLTextFormControlElement>(element).value();
</ins><span class="cx"> 
</span><del>-    if (!node->isElementNode())
-        return String();
-
-    return downcast<Element>(node)->innerText();
</del><ins>+    return element.innerText();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String AccessibilityNodeObject::stringValue() const
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityRenderObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp    2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1613,17 +1613,16 @@
</span><span class="cx"> PlainTextRange AccessibilityRenderObject::selectedTextRange() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isTextControl());
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (isPasswordField())
</span><span class="cx">         return PlainTextRange();
</span><del>-    
-    AccessibilityRole ariaRole = ariaRoleAttribute();
-    // Use the text control native range if it's a native object and it has no ARIA role (or has a text based ARIA role).
-    if (isNativeTextControl() && (ariaRole == AccessibilityRole::Unknown || isARIATextControl())) {
-        HTMLTextFormControlElement& textControl = downcast<RenderTextControl>(*m_renderer).textFormControlElement();
</del><ins>+
+    // Use the text control native range if it's a native object.
+    if (isNativeTextControl()) {
+        auto& textControl = downcast<RenderTextControl>(*m_renderer).textFormControlElement();
</ins><span class="cx">         return PlainTextRange(textControl.selectionStart(), textControl.selectionEnd() - textControl.selectionStart());
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     return documentBasedSelectedTextRange();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomBoundaryPointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/BoundaryPoint.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/BoundaryPoint.h 2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/BoundaryPoint.h    2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -39,6 +39,8 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> bool operator==(const BoundaryPoint&, const BoundaryPoint&);
</span><ins>+bool operator!=(const BoundaryPoint&, const BoundaryPoint&);
+WEBCORE_EXPORT PartialOrdering documentOrder(const BoundaryPoint&, const BoundaryPoint&);
</ins><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT Optional<BoundaryPoint> makeBoundaryPointBeforeNode(Node&);
</span><span class="cx"> WEBCORE_EXPORT Optional<BoundaryPoint> makeBoundaryPointAfterNode(Node&);
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.h      2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Document.h 2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -338,7 +338,7 @@
</span><span class="cx">     , public Supplementable<Document>
</span><span class="cx">     , public Logger::Observer
</span><span class="cx">     , public CanvasObserver {
</span><del>-    WTF_MAKE_ISO_ALLOCATED(Document);
</del><ins>+    WTF_MAKE_ISO_ALLOCATED_EXPORT(Document, WEBCORE_EXPORT);
</ins><span class="cx"> public:
</span><span class="cx">     static Ref<Document> create(const URL&);
</span><span class="cx">     static Ref<Document> createNonRenderedPlaceholder(Frame&, const URL&);
</span><span class="lines">@@ -1593,7 +1593,7 @@
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
</span><del>-    Document(Frame*, const URL&, DocumentClassFlags = DefaultDocumentClass, unsigned constructionFlags = 0);
</del><ins>+    WEBCORE_EXPORT Document(Frame*, const URL&, DocumentClassFlags = DefaultDocumentClass, unsigned constructionFlags = 0);
</ins><span class="cx"> 
</span><span class="cx">     void clearXMLVersion() { m_xmlVersion = String(); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.cpp        2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Node.cpp   2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -32,9 +32,6 @@
</span><span class="cx"> #include "CommonVM.h"
</span><span class="cx"> #include "ComposedTreeAncestorIterator.h"
</span><span class="cx"> #include "ContainerNodeAlgorithms.h"
</span><del>-#if PLATFORM(IOS_FAMILY)
-#include "ContentChangeObserver.h"
-#endif
</del><span class="cx"> #include "ContextMenuController.h"
</span><span class="cx"> #include "DOMWindow.h"
</span><span class="cx"> #include "DataTransfer.h"
</span><span class="lines">@@ -87,6 +84,10 @@
</span><span class="cx"> #include <wtf/text/StringBuilder.h>
</span><span class="cx"> #include <wtf/text/TextStream.h>
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS_FAMILY)
+#include "ContentChangeObserver.h"
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> WTF_MAKE_ISO_ALLOCATED_IMPL(Node);
</span><span class="lines">@@ -1621,14 +1622,13 @@
</span><span class="cx">     return Node::DOCUMENT_POSITION_DISCONNECTED | Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool areNodesConnectedInSameTreeScope(const Node* a, const Node* b)
</del><ins>+bool connectedInSameTreeScope(const Node* a, const Node* b)
</ins><span class="cx"> {
</span><del>-    if (!a || !b)
-        return false;
</del><span class="cx">     // Note that we avoid comparing Attr nodes here, since they return false from isConnected() all the time (which seems like a bug).
</span><del>-    return a->isConnected() == b->isConnected() && &a->treeScope() == &b->treeScope();
</del><ins>+    return a && b && a->isConnected() == b->isConnected() && &a->treeScope() == &b->treeScope();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Refactor this so it calls documentOrdering, except for any exotic inefficient things that are needed only here.
</ins><span class="cx"> unsigned short Node::compareDocumentPosition(Node& otherNode)
</span><span class="cx"> {
</span><span class="cx">     if (&otherNode == this)
</span><span class="lines">@@ -1674,7 +1674,7 @@
</span><span class="cx"> 
</span><span class="cx">     // If one node is in the document and the other is not, we must be disconnected.
</span><span class="cx">     // If the nodes have different owning documents, they must be disconnected.
</span><del>-    if (!areNodesConnectedInSameTreeScope(start1, start2))
</del><ins>+    if (!connectedInSameTreeScope(start1, start2))
</ins><span class="cx">         return compareDetachedElementsPosition(*this, otherNode);
</span><span class="cx"> 
</span><span class="cx">     // We need to find a common ancestor container, and then compare the indices of the two immediate children.
</span><span class="lines">@@ -2623,34 +2623,76 @@
</span><span class="cx">     return const_cast<void*>(static_cast<const void*>(node));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static size_t depth(Node& node)
</del><ins>+static size_t depth(const Node& node)
</ins><span class="cx"> {
</span><span class="cx">     size_t depth = 0;
</span><span class="cx">     auto ancestor = &node;
</span><del>-    while ((ancestor = ancestor->parentNode()))
</del><ins>+    while ((ancestor = ancestor->parentOrShadowHostNode()))
</ins><span class="cx">         ++depth;
</span><span class="cx">     return depth;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<Node> commonInclusiveAncestor(Node& a, Node& b)
</del><ins>+struct AncestorAndChildren {
+    const Node* commonAncestor;
+    const Node* distinctAncestorA;
+    const Node* distinctAncestorB;
+};
+static AncestorAndChildren commonInclusiveAncestorAndChildren(const Node& a, const Node& b)
</ins><span class="cx"> {
</span><span class="cx">     // This first check isn't needed for correctness, but it is cheap and likely to be
</span><span class="cx">     // common enough to be worth optimizing so we don't have to walk to the root.
</span><span class="cx">     if (&a == &b)
</span><del>-        return &a;
</del><ins>+        return { &a, nullptr, nullptr };
</ins><span class="cx">     auto [depthA, depthB] = std::make_tuple(depth(a), depth(b));
</span><del>-    auto [x, y, difference] = depthA > depthB
</del><ins>+    auto [x, y, difference] = depthA >= depthB
</ins><span class="cx">         ? std::make_tuple(&a, &b, depthA - depthB)
</span><span class="cx">         : std::make_tuple(&b, &a, depthB - depthA);
</span><del>-    for (decltype(difference) i = 0; i < difference; ++i)
-        x = x->parentNode();
</del><ins>+    decltype(x) distinctAncestorA = nullptr;
+    for (decltype(difference) i = 0; i < difference; ++i) {
+        distinctAncestorA = x;
+        x = x->parentOrShadowHostNode();
+    }
+    decltype(y) distinctAncestorB = nullptr;
</ins><span class="cx">     while (x != y) {
</span><del>-        x = x->parentNode();
-        y = y->parentNode();
</del><ins>+        distinctAncestorA = x;
+        distinctAncestorB = y;
+        x = x->parentOrShadowHostNode();
+        y = y->parentOrShadowHostNode();
</ins><span class="cx">     }
</span><del>-    return x;
</del><ins>+    if (depthA < depthB)
+        std::swap(distinctAncestorA, distinctAncestorB);
+    return { x, distinctAncestorA, distinctAncestorB };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RefPtr<Node> commonInclusiveAncestor(Node& a, Node& b)
+{
+    return const_cast<Node*>(commonInclusiveAncestorAndChildren(a, b).commonAncestor);
+}
+
+static bool isSiblingSubsequent(const Node& siblingA, const Node& siblingB)
+{
+    ASSERT(&siblingA != &siblingB);
+    for (auto sibling = &siblingA; sibling; sibling = sibling->nextSibling()) {
+        if (sibling == &siblingB)
+            return true;
+    }
+    return false;
+}
+
+PartialOrdering documentOrder(const Node& a, const Node& b)
+{
+    if (&a == &b)
+        return PartialOrdering::equivalent;
+    auto result = commonInclusiveAncestorAndChildren(a, b);
+    if (!result.commonAncestor)
+        return PartialOrdering::unordered;
+    if (!result.distinctAncestorA)
+        return PartialOrdering::less;
+    if (!result.distinctAncestorB)
+        return PartialOrdering::greater;
+    return isSiblingSubsequent(*result.distinctAncestorA, *result.distinctAncestorB) ? PartialOrdering::less : PartialOrdering::greater;
+}
+
</ins><span class="cx"> TextStream& operator<<(TextStream& ts, const Node& node)
</span><span class="cx"> {
</span><span class="cx">     ts << "node " << &node << " " << node.debugDescription();
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.h  2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Node.h     2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -670,8 +670,31 @@
</span><span class="cx">     std::unique_ptr<NodeRareData, NodeRareDataDeleter> m_rareData;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+bool connectedInSameTreeScope(const Node*, const Node*);
</ins><span class="cx"> WEBCORE_EXPORT RefPtr<Node> commonInclusiveAncestor(Node&, Node&);
</span><span class="cx"> 
</span><ins>+// Designed to be used the same way as C++20 std::partial_ordering class.
+// FIXME: Consider putting this in a separate header.
+// FIXME: Once we can require C++20, replace with std::partial_ordering.
+class PartialOrdering {
+public:
+    static const PartialOrdering less;
+    static const PartialOrdering equivalent;
+    static const PartialOrdering greater;
+    static const PartialOrdering unordered;
+
+    friend constexpr bool is_eq(PartialOrdering);
+    friend constexpr bool is_lt(PartialOrdering);
+    friend constexpr bool is_gt(PartialOrdering);
+
+private:
+    enum class Type : uint8_t { Less, Equivalent, Greater, Unordered };
+    constexpr PartialOrdering(Type type) : m_type { type } { }
+    Type m_type;
+};
+
+WEBCORE_EXPORT PartialOrdering documentOrder(const Node&, const Node&);
+
</ins><span class="cx"> #if ASSERT_ENABLED
</span><span class="cx"> 
</span><span class="cx"> inline void adopted(Node* node)
</span><span class="lines">@@ -785,8 +808,26 @@
</span><span class="cx">         moveTreeToNewScope(*this, *m_treeScope, newTreeScope);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool areNodesConnectedInSameTreeScope(const Node*, const Node*);
</del><ins>+inline constexpr PartialOrdering PartialOrdering::less(Type::Less);
+inline constexpr PartialOrdering PartialOrdering::equivalent(Type::Equivalent);
+inline constexpr PartialOrdering PartialOrdering::greater(Type::Greater);
+inline constexpr PartialOrdering PartialOrdering::unordered(Type::Unordered);
</ins><span class="cx"> 
</span><ins>+constexpr bool is_eq(PartialOrdering ordering)
+{
+    return ordering.m_type == PartialOrdering::Type::Equivalent;
+}
+
+constexpr bool is_lt(PartialOrdering ordering)
+{
+    return ordering.m_type == PartialOrdering::Type::Less;
+}
+
+constexpr bool is_gt(PartialOrdering ordering)
+{
+    return ordering.m_type == PartialOrdering::Type::Greater;
+}
+
</ins><span class="cx"> WTF::TextStream& operator<<(WTF::TextStream&, const Node&);
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomPositioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Position.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Position.cpp    2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Position.cpp       2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -208,7 +208,7 @@
</span><span class="cx">     case PositionIsAfterChildren:
</span><span class="cx">         return m_anchorNode->length();
</span><span class="cx">     case PositionIsOffsetInAnchor:
</span><del>-        return minOffsetForNode(m_anchorNode.get(), m_offset);
</del><ins>+        return m_offset;
</ins><span class="cx">     case PositionIsBeforeAnchor:
</span><span class="cx">         return m_anchorNode->computeNodeIndex();
</span><span class="cx">     case PositionIsAfterAnchor:
</span><span class="lines">@@ -355,11 +355,11 @@
</span><span class="cx">         //      Going from 1 to 0 is correct.
</span><span class="cx">         switch (moveType) {
</span><span class="cx">         case CodePoint:
</span><del>-            return createLegacyEditingPosition(node, offset - 1);
</del><ins>+            return makeDeprecatedLegacyPosition(node, offset - 1);
</ins><span class="cx">         case Character:
</span><del>-            return createLegacyEditingPosition(node, uncheckedPreviousOffset(node, offset));
</del><ins>+            return makeDeprecatedLegacyPosition(node, uncheckedPreviousOffset(node, offset));
</ins><span class="cx">         case BackwardDeletion:
</span><del>-            return createLegacyEditingPosition(node, uncheckedPreviousOffsetForBackwardDeletion(node, offset));
</del><ins>+            return makeDeprecatedLegacyPosition(node, uncheckedPreviousOffsetForBackwardDeletion(node, offset));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -374,7 +374,7 @@
</span><span class="cx">     if (previousSibling && positionBeforeOrAfterNodeIsCandidate(*previousSibling))
</span><span class="cx">         return positionAfterNode(previousSibling);
</span><span class="cx"> 
</span><del>-    return createLegacyEditingPosition(parent, node->computeNodeIndex());
</del><ins>+    return makeDeprecatedLegacyPosition(parent, node->computeNodeIndex());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Position Position::next(PositionMoveType moveType) const
</span><span class="lines">@@ -408,7 +408,7 @@
</span><span class="cx">         //      Going forward one character at a time is correct.
</span><span class="cx">         //   2) The new offset is a bogus offset like (<br>, 1), and there is no child.
</span><span class="cx">         //      Going from 0 to 1 is correct.
</span><del>-        return createLegacyEditingPosition(node, (moveType == Character) ? uncheckedNextOffset(node, offset) : offset + 1);
</del><ins>+        return makeDeprecatedLegacyPosition(node, (moveType == Character) ? uncheckedNextOffset(node, offset) : offset + 1);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ContainerNode* parent = node->parentNode();
</span><span class="lines">@@ -422,7 +422,7 @@
</span><span class="cx">     if (nextSibling && positionBeforeOrAfterNodeIsCandidate(*nextSibling))
</span><span class="cx">         return positionBeforeNode(nextSibling);
</span><span class="cx"> 
</span><del>-    return createLegacyEditingPosition(parent, node->computeNodeIndex() + 1);
</del><ins>+    return makeDeprecatedLegacyPosition(parent, node->computeNodeIndex() + 1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> int Position::uncheckedPreviousOffset(const Node* n, unsigned current)
</span><span class="lines">@@ -674,7 +674,7 @@
</span><span class="cx">     // iterate backward from there, looking for a qualified position
</span><span class="cx">     Node* boundary = enclosingVisualBoundary(startNode);
</span><span class="cx">     // FIXME: PositionIterator should respect Before and After positions.
</span><del>-    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(*m_anchorNode)) : *this;
</del><ins>+    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? makeDeprecatedLegacyPosition(m_anchorNode.get(), caretMaxOffset(*m_anchorNode)) : *this;
</ins><span class="cx">     PositionIterator currentPosition = lastVisible;
</span><span class="cx">     bool startEditable = startNode->hasEditableStyle();
</span><span class="cx">     Node* lastNode = startNode;
</span><span class="lines">@@ -740,7 +740,7 @@
</span><span class="cx">                 // render tree which can have a different length due to case transformation.
</span><span class="cx">                 // Until we resolve that, disable this so we can run the layout tests!
</span><span class="cx">                 //ASSERT(currentOffset >= renderer->caretMaxOffset());
</span><del>-                return createLegacyEditingPosition(&currentNode, renderer->caretMaxOffset());
</del><ins>+                return makeDeprecatedLegacyPosition(&currentNode, renderer->caretMaxOffset());
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             unsigned textOffset = currentPosition.offsetInLeafNode();
</span><span class="lines">@@ -776,7 +776,7 @@
</span><span class="cx">     // iterate forward from there, looking for a qualified position
</span><span class="cx">     Node* boundary = enclosingVisualBoundary(startNode);
</span><span class="cx">     // FIXME: PositionIterator should respect Before and After positions.
</span><del>-    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(*m_anchorNode)) : *this;
</del><ins>+    PositionIterator lastVisible = m_anchorType == PositionIsAfterAnchor ? makeDeprecatedLegacyPosition(m_anchorNode.get(), caretMaxOffset(*m_anchorNode)) : *this;
</ins><span class="cx">     PositionIterator currentPosition = lastVisible;
</span><span class="cx">     bool startEditable = startNode->hasEditableStyle();
</span><span class="cx">     Node* lastNode = startNode;
</span><span class="lines">@@ -843,7 +843,7 @@
</span><span class="cx"> 
</span><span class="cx">             if (&currentNode != startNode) {
</span><span class="cx">                 ASSERT(currentPosition.atStartOfNode());
</span><del>-                return createLegacyEditingPosition(&currentNode, textRenderer.caretMinOffset());
</del><ins>+                return makeDeprecatedLegacyPosition(&currentNode, textRenderer.caretMinOffset());
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             unsigned textOffset = currentPosition.offsetInLeafNode();
</span><span class="lines">@@ -1560,15 +1560,12 @@
</span><span class="cx">     return stream;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<Node> commonShadowIncludingAncestor(const Position& a, const Position& b)
</del><ins>+RefPtr<Node> commonInclusiveAncestor(const Position& a, const Position& b)
</ins><span class="cx"> {
</span><del>-    auto* commonScope = commonTreeScope(a.containerNode(), b.containerNode());
-    if (!commonScope)
</del><ins>+    auto nodeA = a.containerNode();
+    auto nodeB = b.containerNode();
+    if (!nodeA || !nodeB)
</ins><span class="cx">         return nullptr;
</span><del>-    auto* nodeA = commonScope->ancestorNodeInThisScope(a.containerNode());
-    ASSERT(nodeA);
-    auto* nodeB = commonScope->ancestorNodeInThisScope(b.containerNode());
-    ASSERT(nodeB);
</del><span class="cx">     return commonInclusiveAncestor(*nodeA, *nodeB);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1594,12 +1591,16 @@
</span><span class="cx">     return Position(ancestor, node->computeNodeIndex() + 1, Position::PositionIsOffsetInAnchor);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// FIXME: Rename to use make for the prefix verb instead of create.
-Position createLegacyEditingPosition(const BoundaryPoint& point)
</del><ins>+Position makeContainerOffsetPosition(const BoundaryPoint& point)
</ins><span class="cx"> {
</span><del>-    return createLegacyEditingPosition(point.container.ptr(), point.offset);
</del><ins>+    return makeContainerOffsetPosition(point.container.ptr(), point.offset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Position makeDeprecatedLegacyPosition(const BoundaryPoint& point)
+{
+    return makeDeprecatedLegacyPosition(point.container.ptr(), point.offset);
+}
+
</ins><span class="cx"> Optional<BoundaryPoint> makeBoundaryPoint(const Position& position)
</span><span class="cx"> {
</span><span class="cx">     if (position.isNull())
</span><span class="lines">@@ -1607,6 +1608,29 @@
</span><span class="cx">     return BoundaryPoint { *position.containerNode(), static_cast<unsigned>(position.computeOffsetInContainerNode()) };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PartialOrdering documentOrder(const Position& a, const Position& b)
+{
+    if (a.isNull() || b.isNull())
+        return a.isNull() && b.isNull() ? PartialOrdering::equivalent : PartialOrdering::unordered;
+
+    auto aContainer = a.containerNode();
+    auto bContainer = b.containerNode();
+
+    if (!aContainer || !bContainer) {
+        if (!commonInclusiveAncestor(*a.anchorNode(), *b.anchorNode()))
+            return PartialOrdering::unordered;
+        if (!aContainer && !bContainer && a.anchorType() == b.anchorType())
+            return PartialOrdering::equivalent;
+        if (bContainer)
+            return a.anchorType() == Position::PositionIsBeforeAnchor ? PartialOrdering::less : PartialOrdering::greater;
+        return b.anchorType() == Position::PositionIsBeforeAnchor ? PartialOrdering::greater : PartialOrdering::less;
+    }
+
+    // FIXME: Avoid computing node offset for cases where we don't need to.
+
+    return documentOrder(*makeBoundaryPoint(a), *makeBoundaryPoint(b));
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TREE_DEBUGGING)
</span></span></pre></div>
<a id="trunkSourceWebCoredomPositionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Position.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Position.h      2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Position.h 2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -201,7 +201,7 @@
</span><span class="cx">     // For creating legacy editing positions: (Anchor type will be determined from editingIgnoresContent(node))
</span><span class="cx">     enum class LegacyEditingPositionFlag { On };
</span><span class="cx">     WEBCORE_EXPORT Position(Node* anchorNode, unsigned offset, LegacyEditingPositionFlag);
</span><del>-    friend Position createLegacyEditingPosition(Node*, unsigned offset);
</del><ins>+    friend Position makeDeprecatedLegacyPosition(Node*, unsigned offset);
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT int offsetForPositionAfterAnchor() const;
</span><span class="cx">     
</span><span class="lines">@@ -221,15 +221,19 @@
</span><span class="cx"> 
</span><span class="cx"> bool operator==(const Position&, const Position&);
</span><span class="cx"> bool operator!=(const Position&, const Position&);
</span><ins>+
+WEBCORE_EXPORT PartialOrdering documentOrder(const Position&, const Position&);
</ins><span class="cx"> bool operator<(const Position&, const Position&);
</span><span class="cx"> bool operator>(const Position&, const Position&);
</span><span class="cx"> bool operator>=(const Position&, const Position&);
</span><span class="cx"> bool operator<=(const Position&, const Position&);
</span><span class="cx"> 
</span><del>-// FIXME: Consider renaming this to "make" instead of "create" since we normally use "create" for functions that allocate heap objects.
-Position createLegacyEditingPosition(Node*, unsigned offset);
-WEBCORE_EXPORT Position createLegacyEditingPosition(const BoundaryPoint&);
</del><ins>+Position makeContainerOffsetPosition(Node*, unsigned offset);
+WEBCORE_EXPORT Position makeContainerOffsetPosition(const BoundaryPoint&);
</ins><span class="cx"> 
</span><ins>+Position makeDeprecatedLegacyPosition(Node*, unsigned offset);
+WEBCORE_EXPORT Position makeDeprecatedLegacyPosition(const BoundaryPoint&);
+
</ins><span class="cx"> WEBCORE_EXPORT Optional<BoundaryPoint> makeBoundaryPoint(const Position&);
</span><span class="cx"> 
</span><span class="cx"> Position positionInParentBeforeNode(Node*);
</span><span class="lines">@@ -243,10 +247,9 @@
</span><span class="cx"> Position firstPositionInNode(Node* anchorNode);
</span><span class="cx"> Position lastPositionInNode(Node* anchorNode);
</span><span class="cx"> 
</span><del>-int minOffsetForNode(Node* anchorNode, unsigned offset);
</del><span class="cx"> bool offsetIsBeforeLastNodeOffset(unsigned offset, Node* anchorNode);
</span><span class="cx"> 
</span><del>-RefPtr<Node> commonShadowIncludingAncestor(const Position&, const Position&);
</del><ins>+RefPtr<Node> commonInclusiveAncestor(const Position&, const Position&);
</ins><span class="cx"> 
</span><span class="cx"> WTF::TextStream& operator<<(WTF::TextStream&, const Position&);
</span><span class="cx"> 
</span><span class="lines">@@ -259,15 +262,21 @@
</span><span class="cx"> 
</span><span class="cx"> // inlines
</span><span class="cx"> 
</span><del>-inline Position createLegacyEditingPosition(Node* node, unsigned offset)
</del><ins>+inline Position makeContainerOffsetPosition(Node* node, unsigned offset)
</ins><span class="cx"> {
</span><ins>+    return { node, offset, Position::PositionIsOffsetInAnchor };
+}
+
+inline Position makeDeprecatedLegacyPosition(Node* node, unsigned offset)
+{
</ins><span class="cx">     return { node, offset, Position::LegacyEditingPositionFlag::On };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Positions at the same document location with different anchoring will return false; that's unlike <= and >=.
+// FIXME: This ignores differences in m_isLegacyEditingPosition in a subtle way.
+// FIXME: For legacy editing positions, <div><img></div> [div, 0] != [img, 0] even though most of editing code will treat them as identical.
</ins><span class="cx"> inline bool operator==(const Position& a, const Position& b)
</span><span class="cx"> {
</span><del>-    // FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the
-    // editing code will treat them as identical.
</del><span class="cx">     return a.anchorNode() == b.anchorNode() && a.deprecatedEditingOffset() == b.deprecatedEditingOffset() && a.anchorType() == b.anchorType();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -328,17 +337,6 @@
</span><span class="cx">     return Position(anchorNode, Position::PositionIsAfterChildren);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline int minOffsetForNode(Node* anchorNode, unsigned offset)
-{
-    if (is<CharacterData>(*anchorNode))
-        return std::min(offset, downcast<CharacterData>(*anchorNode).length());
-
-    unsigned newOffset = 0;
-    for (Node* node = anchorNode->firstChild(); node && newOffset < offset; node = node->nextSibling())
-        newOffset++;
-    return newOffset;
-}
-
</del><span class="cx"> inline bool offsetIsBeforeLastNodeOffset(unsigned offset, Node* anchorNode)
</span><span class="cx"> {
</span><span class="cx">     if (is<CharacterData>(*anchorNode))
</span><span class="lines">@@ -350,6 +348,18 @@
</span><span class="cx">     return offset < currentOffset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Delete this after changing all callers to use the makeDeprecatedLegacyPosition name.
+inline Position createLegacyEditingPosition(Node* node, unsigned offset)
+{
+    return makeDeprecatedLegacyPosition(node, offset);
+}
+
+// FIXME: Delete this after changing all callers to use the makeDeprecatedLegacyPosition name.
+inline Position createLegacyEditingPosition(const BoundaryPoint& point)
+{
+    return makeDeprecatedLegacyPosition(point);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TREE_DEBUGGING)
</span></span></pre></div>
<a id="trunkSourceWebCoredomRadioButtonGroupscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/RadioButtonGroups.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/RadioButtonGroups.cpp   2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/RadioButtonGroups.cpp      2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -60,10 +60,10 @@
</span><span class="cx"> Vector<Ref<HTMLInputElement>> RadioButtonGroup::members() const
</span><span class="cx"> {
</span><span class="cx">     Vector<Ref<HTMLInputElement>> sortedMembers;
</span><del>-    for (auto& memeber : m_members)
-        sortedMembers.append(memeber);
</del><ins>+    for (auto& member : m_members)
+        sortedMembers.append(member);
</ins><span class="cx">     std::sort(sortedMembers.begin(), sortedMembers.end(), [](auto& a, auto& b) {
</span><del>-        return documentOrderComparator(a.ptr(), b.ptr());
</del><ins>+        return is_lt(documentOrder(a, b));
</ins><span class="cx">     });
</span><span class="cx">     return sortedMembers;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomRangecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Range.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Range.cpp       2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Range.cpp  2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1188,7 +1188,7 @@
</span><span class="cx">         return true;
</span><span class="cx">     if (!a || !b)
</span><span class="cx">         return false;
</span><del>-    return a->startPosition() == b->startPosition() && a->endPosition() == b->endPosition();
</del><ins>+    return &a->startContainer() == &b->startContainer() && a->startOffset() == b->startOffset() && &a->endContainer() == &b->endContainer() && a->endOffset() == b->endOffset();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool rangesOverlap(const Range* a, const Range* b)
</span><span class="lines">@@ -1199,7 +1199,7 @@
</span><span class="cx">     if (a == b)
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    if (!areNodesConnectedInSameTreeScope(a->commonAncestorContainer(), b->commonAncestorContainer()))
</del><ins>+    if (!connectedInSameTreeScope(a->commonAncestorContainer(), b->commonAncestorContainer()))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     short startToStart = a->compareBoundaryPoints(Range::START_TO_START, *b).releaseReturnValue();
</span><span class="lines">@@ -1387,8 +1387,8 @@
</span><span class="cx"> 
</span><span class="cx"> ExceptionOr<void> Range::expand(const String& unit)
</span><span class="cx"> {
</span><del>-    VisiblePosition start { startPosition() };
-    VisiblePosition end { endPosition() };
</del><ins>+    auto start = VisiblePosition { makeDeprecatedLegacyPosition(&startContainer(), startOffset()) };
+    auto end = VisiblePosition { makeDeprecatedLegacyPosition(&endContainer(), endOffset()) };
</ins><span class="cx">     if (unit == "word") {
</span><span class="cx">         start = startOfWord(start);
</span><span class="cx">         end = endOfWord(end);
</span><span class="lines">@@ -1544,16 +1544,6 @@
</span><span class="cx">     return createLiveRange(*range);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-WTF::TextStream& operator<<(WTF::TextStream& ts, const RangeBoundaryPoint& r)
-{
-    return ts << r.toPosition();
-}
-    
-WTF::TextStream& operator<<(WTF::TextStream& ts, const Range& r)
-{
-    return ts << "Range: " << "start: " << r.startPosition() << " end: " << r.endPosition();
-}
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TREE_DEBUGGING)
</span></span></pre></div>
<a id="trunkSourceWebCoredomRangeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Range.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Range.h 2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/Range.h    2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -93,9 +93,6 @@
</span><span class="cx">     WEBCORE_EXPORT ExceptionOr<void> surroundContents(Node&);
</span><span class="cx">     WEBCORE_EXPORT ExceptionOr<void> setStartBefore(Node&);
</span><span class="cx"> 
</span><del>-    Position startPosition() const { return m_start.toPosition(); }
-    Position endPosition() const { return m_end.toPosition(); }
-
</del><span class="cx">     WEBCORE_EXPORT Node* firstNode() const;
</span><span class="cx"> 
</span><span class="cx">     enum class BoundingRectBehavior : uint8_t {
</span><span class="lines">@@ -171,16 +168,6 @@
</span><span class="cx"> WEBCORE_EXPORT Ref<Range> createLiveRange(const SimpleRange&);
</span><span class="cx"> WEBCORE_EXPORT RefPtr<Range> createLiveRange(const Optional<SimpleRange>&);
</span><span class="cx"> 
</span><del>-bool documentOrderComparator(const Node*, const Node*);
-
-WTF::TextStream& operator<<(WTF::TextStream&, const RangeBoundaryPoint&);
-WTF::TextStream& operator<<(WTF::TextStream&, const Range&);
-
-inline bool documentOrderComparator(const Node* a, const Node* b)
-{
-    return Range::compareBoundaryPoints(const_cast<Node*>(a), 0, const_cast<Node*>(b), 0).releaseReturnValue() < 0;
-}
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TREE_DEBUGGING)
</span></span></pre></div>
<a id="trunkSourceWebCoredomRangeBoundaryPointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/RangeBoundaryPoint.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/RangeBoundaryPoint.h    2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/RangeBoundaryPoint.h       2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -25,8 +25,8 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include "Node.h"
-#include "Position.h"
</del><ins>+#include "BoundaryPoint.h"
+#include "CharacterData.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -34,8 +34,6 @@
</span><span class="cx"> public:
</span><span class="cx">     explicit RangeBoundaryPoint(Node* container);
</span><span class="cx"> 
</span><del>-    Position toPosition() const;
-
</del><span class="cx">     Node* container() const;
</span><span class="cx">     unsigned offset() const;
</span><span class="cx">     Node* childBefore() const;
</span><span class="lines">@@ -60,6 +58,8 @@
</span><span class="cx">     RefPtr<Node> m_childBeforeBoundary;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+BoundaryPoint makeBoundaryPoint(const RangeBoundaryPoint&);
+
</ins><span class="cx"> inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container)
</span><span class="cx">     : m_containerNode(container)
</span><span class="cx"> {
</span><span class="lines">@@ -85,12 +85,6 @@
</span><span class="cx">     m_offsetInContainer = m_childBeforeBoundary->computeNodeIndex() + 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline Position RangeBoundaryPoint::toPosition() const
-{
-    ensureOffsetIsValid();
-    return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer.value());
-}
-
</del><span class="cx"> inline unsigned RangeBoundaryPoint::offset() const
</span><span class="cx"> {
</span><span class="cx">     ensureOffsetIsValid();
</span><span class="lines">@@ -185,4 +179,9 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline BoundaryPoint makeBoundaryPoint(const RangeBoundaryPoint& point)
+{
+    return { *point.container(), point.offset() };
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomSimpleRangecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/SimpleRange.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/SimpleRange.cpp 2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/dom/SimpleRange.cpp    2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -66,6 +66,45 @@
</span><span class="cx">     return BoundaryPoint { *parent, node.computeNodeIndex() + 1 };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// FIXME: Create BoundaryPoint.cpp and move this there.
+static bool isOffsetBeforeChild(ContainerNode& container, unsigned offset, Node& child)
+{
+    if (!offset)
+        return true;
+    unsigned currentOffset = 0;
+    for (auto currentChild = container.firstChild(); currentChild && currentChild != &child; currentChild = currentChild->nextSibling()) {
+        if (offset <= ++currentOffset)
+            return true;
+    }
+    return false;
+}
+
+// FIXME: Create BoundaryPoint.cpp and move this there.
+PartialOrdering documentOrder(const BoundaryPoint& a, const BoundaryPoint& b)
+{
+    if (a.offset == b.offset)
+        return documentOrder(a.container, b.container);
+
+    if (a.container.ptr() == b.container.ptr())
+        return a.offset < b.offset ? PartialOrdering::less : PartialOrdering::greater;
+
+    for (auto ancestor = b.container.ptr(); ancestor; ) {
+        auto nextAncestor = ancestor->parentOrShadowHostNode();
+        if (nextAncestor == a.container.ptr())
+            return isOffsetBeforeChild(*nextAncestor, a.offset, *ancestor) ? PartialOrdering::less : PartialOrdering::greater;
+        ancestor = nextAncestor;
+    }
+
+    for (auto ancestor = a.container.ptr(); ancestor; ) {
+        auto nextAncestor = ancestor->parentOrShadowHostNode();
+        if (nextAncestor == b.container.ptr())
+            return isOffsetBeforeChild(*nextAncestor, b.offset, *ancestor) ? PartialOrdering::greater : PartialOrdering::less;
+        ancestor = nextAncestor;
+    }
+
+    return documentOrder(a.container, b.container);
+}
+
</ins><span class="cx"> Optional<SimpleRange> makeRangeSelectingNode(Node& node)
</span><span class="cx"> {
</span><span class="cx">     auto parent = node.parentNode();
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTextIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextIterator.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextIterator.cpp    2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/editing/TextIterator.cpp       2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1563,7 +1563,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_buffer.isEmpty()) {
</span><del>-            // Start gobbling chunks until we get to a suitable stopping point
</del><ins>+            // Start gobbling chunks until we get to a suitable stopping point.
</ins><span class="cx">             append(m_buffer, m_previousText.text());
</span><span class="cx">             m_previousText.reset();
</span><span class="cx">         }
</span><span class="lines">@@ -2090,10 +2090,10 @@
</span><span class="cx">     ASSERT(length);
</span><span class="cx">     ASSERT(m_options.contains(AtWordEnds));
</span><span class="cx"> 
</span><ins>+    // Start searching at the end of matched search, so that multiple word matches succeed.
</ins><span class="cx">     int endWord;
</span><del>-    // Start searching at the end of matched search, so that multiple word matches succeed.
</del><span class="cx">     findEndWordBoundary(StringView(m_buffer.data(), m_buffer.size()), start + length - 1, &endWord);
</span><del>-    return static_cast<size_t>(endWord) == (start + length);
</del><ins>+    return static_cast<size_t>(endWord) == start + length;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool SearchBuffer::isWordStartMatch(size_t start, size_t length) const
</span><span class="lines">@@ -2333,14 +2333,12 @@
</span><span class="cx"> 
</span><span class="cx"> uint64_t characterCount(const SimpleRange& range, TextIteratorBehavior behavior)
</span><span class="cx"> {
</span><del>-    auto comparisonResult = Range::compareBoundaryPoints(&range.startContainer(), range.startOffset(), &range.endContainer(), range.endOffset());
-    if (comparisonResult.hasException())
</del><ins>+    auto adjustedRange = range;
+    auto ordering = documentOrder(range.start, range.end);
+    if (is_gt(ordering))
+        std::swap(adjustedRange.start, adjustedRange.end);
+    else if (!is_lt(ordering))
</ins><span class="cx">         return 0;
</span><del>-
-    auto adjustedRange(range);
-    if (comparisonResult.releaseReturnValue() > 0)
-        std::swap(adjustedRange.start, adjustedRange.end);
-
</del><span class="cx">     uint64_t length = 0;
</span><span class="cx">     for (TextIterator it(adjustedRange, behavior); !it.atEnd(); it.advance())
</span><span class="cx">         length += it.text().length();
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisiblePositioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisiblePosition.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisiblePosition.cpp 2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/editing/VisiblePosition.cpp    2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -766,7 +766,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool areVisiblePositionsInSameTreeScope(const VisiblePosition& a, const VisiblePosition& b)
</span><span class="cx"> {
</span><del>-    return areNodesConnectedInSameTreeScope(a.deepEquivalent().anchorNode(), b.deepEquivalent().anchorNode());
</del><ins>+    return connectedInSameTreeScope(a.deepEquivalent().anchorNode(), b.deepEquivalent().anchorNode());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool VisiblePosition::equals(const VisiblePosition& other) const
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisiblePositionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisiblePosition.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisiblePosition.h   2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/editing/VisiblePosition.h      2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -54,7 +54,8 @@
</span><span class="cx">     VisiblePosition() : m_affinity(VP_DEFAULT_AFFINITY) { }
</span><span class="cx">     WEBCORE_EXPORT VisiblePosition(const Position&, EAffinity = VP_DEFAULT_AFFINITY);
</span><span class="cx"> 
</span><del>-    void clear() { m_deepPosition.clear(); }
</del><ins>+    // FIXME: Why doesn't this reset m_affinity?
+    void clear() { m_deepPosition = { }; }
</ins><span class="cx"> 
</span><span class="cx">     bool isNull() const { return m_deepPosition.isNull(); }
</span><span class="cx">     bool isNotNull() const { return m_deepPosition.isNotNull(); }
</span><span class="lines">@@ -119,6 +120,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool operator==(const VisiblePosition&, const VisiblePosition&);
</span><span class="cx"> bool operator!=(const VisiblePosition&, const VisiblePosition&);
</span><ins>+
+PartialOrdering documentOrder(const VisiblePosition&, const VisiblePosition&);
</ins><span class="cx"> bool operator<(const VisiblePosition&, const VisiblePosition&);
</span><span class="cx"> bool operator>(const VisiblePosition&, const VisiblePosition&);
</span><span class="cx"> bool operator<=(const VisiblePosition&, const VisiblePosition&);
</span><span class="lines">@@ -147,7 +150,7 @@
</span><span class="cx"> 
</span><span class="cx"> // inlines
</span><span class="cx"> 
</span><del>-// FIXME: This shouldn't ignore affinity.
</del><ins>+// FIXME: Is it correct and helpful for this to be ignoring affinity?
</ins><span class="cx"> inline bool operator==(const VisiblePosition& a, const VisiblePosition& b)
</span><span class="cx"> {
</span><span class="cx">     return a.deepEquivalent() == b.deepEquivalent();
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingcocoaHTMLConvertermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/cocoa/HTMLConverter.mm (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/HTMLConverter.mm      2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/editing/cocoa/HTMLConverter.mm 2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -2294,7 +2294,7 @@
</span><span class="cx"> 
</span><span class="cx"> Node* HTMLConverterCaches::cacheAncestorsOfStartToBeConverted(const Position& start, const Position& end)
</span><span class="cx"> {
</span><del>-    auto commonAncestor = commonShadowIncludingAncestor(start, end);
</del><ins>+    auto commonAncestor = commonInclusiveAncestor(start, end);
</ins><span class="cx">     Node* ancestor = start.containerNode();
</span><span class="cx"> 
</span><span class="cx">     while (ancestor) {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingmarkupcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/markup.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/markup.cpp  2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/editing/markup.cpp     2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -842,7 +842,7 @@
</span><span class="cx">     if (!comparePositions(start, end))
</span><span class="cx">         return emptyString();
</span><span class="cx"> 
</span><del>-    RefPtr<Node> commonAncestor = commonShadowIncludingAncestor(start, end);
</del><ins>+    auto commonAncestor = commonInclusiveAncestor(start, end);
</ins><span class="cx">     if (!commonAncestor)
</span><span class="cx">         return emptyString();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLBodyElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLBodyElement.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLBodyElement.h      2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/html/HTMLBodyElement.h 2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> class HTMLBodyElement final : public HTMLElement {
</span><span class="cx">     WTF_MAKE_ISO_ALLOCATED(HTMLBodyElement);
</span><span class="cx"> public:
</span><del>-    static Ref<HTMLBodyElement> create(Document&);
</del><ins>+    WEBCORE_EXPORT static Ref<HTMLBodyElement> create(Document&);
</ins><span class="cx">     static Ref<HTMLBodyElement> create(const QualifiedName&, Document&);
</span><span class="cx">     virtual ~HTMLBodyElement();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLDivElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLDivElement.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLDivElement.h       2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/html/HTMLDivElement.h  2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -29,7 +29,7 @@
</span><span class="cx"> class HTMLDivElement : public HTMLElement {
</span><span class="cx">     WTF_MAKE_ISO_ALLOCATED(HTMLDivElement);
</span><span class="cx"> public:
</span><del>-    static Ref<HTMLDivElement> create(Document&);
</del><ins>+    WEBCORE_EXPORT static Ref<HTMLDivElement> create(Document&);
</ins><span class="cx">     static Ref<HTMLDivElement> create(const QualifiedName&, Document&);
</span><span class="cx"> 
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLHtmlElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLHtmlElement.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLHtmlElement.h      2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/html/HTMLHtmlElement.h 2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> class HTMLHtmlElement final : public HTMLElement {
</span><span class="cx">     WTF_MAKE_ISO_ALLOCATED(HTMLHtmlElement);
</span><span class="cx"> public:
</span><del>-    static Ref<HTMLHtmlElement> create(Document&);
</del><ins>+    WEBCORE_EXPORT static Ref<HTMLHtmlElement> create(Document&);
</ins><span class="cx">     static Ref<HTMLHtmlElement> create(const QualifiedName&, Document&);
</span><span class="cx"> 
</span><span class="cx">     void insertedByParser();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLTextAreaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLTextAreaElement.cpp        2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.cpp   2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -103,6 +103,11 @@
</span><span class="cx">     return textArea;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Ref<HTMLTextAreaElement> HTMLTextAreaElement::create(Document& document)
+{
+    return create(textareaTag, document, nullptr);
+}
+
</ins><span class="cx"> void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot& root)
</span><span class="cx"> {
</span><span class="cx">     root.appendChild(TextControlInnerTextElement::create(document()));
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLTextAreaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.h (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLTextAreaElement.h  2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.h     2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> class HTMLTextAreaElement final : public HTMLTextFormControlElement {
</span><span class="cx">     WTF_MAKE_ISO_ALLOCATED(HTMLTextAreaElement);
</span><span class="cx"> public:
</span><ins>+    WEBCORE_EXPORT static Ref<HTMLTextAreaElement> create(Document&);
</ins><span class="cx">     static Ref<HTMLTextAreaElement> create(const QualifiedName&, Document&, HTMLFormElement*);
</span><span class="cx"> 
</span><span class="cx">     unsigned cols() const { return m_cols; }
</span><span class="lines">@@ -54,7 +55,7 @@
</span><span class="cx">     bool tooLong() const final;
</span><span class="cx">     bool isValidValue(const String&) const;
</span><span class="cx">     
</span><del>-    RefPtr<TextControlInnerTextElement> innerTextElement() const final;
</del><ins>+    WEBCORE_EXPORT RefPtr<TextControlInnerTextElement> innerTextElement() const final;
</ins><span class="cx">     RenderStyle createInnerTextStyle(const RenderStyle&) final;
</span><span class="cx">     void copyNonAttributePropertiesFromElement(const Element&) final;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageDOMSelectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/DOMSelection.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/DOMSelection.cpp       2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/page/DOMSelection.cpp  2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -336,15 +336,13 @@
</span><span class="cx">     Ref<Frame> protector(*frame);
</span><span class="cx"> 
</span><span class="cx">     auto& selection = frame->selection();
</span><del>-    if (selection.isNone()) {
</del><ins>+    auto selectedRange = selection.selection().toNormalizedRange();
+    if (!selectedRange || selectedRange->start.container->containingShadowRoot()) {
</ins><span class="cx">         selection.setSelection(makeSimpleRange(range));
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto normalizedRange = createLiveRange(selection.selection().toNormalizedRange());
-    if (!normalizedRange)
-        return;
-
</del><ins>+    auto normalizedRange = createLiveRange(selectedRange);
</ins><span class="cx">     auto result = range.compareBoundaryPoints(Range::START_TO_START, *normalizedRange);
</span><span class="cx">     if (!result.hasException() && result.releaseReturnValue() == -1) {
</span><span class="cx">         // We don't support discontiguous selection. We don't do anything if the two ranges don't intersect.
</span><span class="lines">@@ -353,7 +351,7 @@
</span><span class="cx">             result = range.compareBoundaryPoints(Range::END_TO_END, *normalizedRange);
</span><span class="cx">             if (!result.hasException() && result.releaseReturnValue() == -1) {
</span><span class="cx">                 // The ranges intersect.
</span><del>-                selection.moveTo(range.startPosition(), normalizedRange->endPosition(), DOWNSTREAM);
</del><ins>+                selection.moveTo(makeDeprecatedLegacyPosition(&range.startContainer(), range.startOffset()), makeDeprecatedLegacyPosition(&normalizedRange->endContainer(), normalizedRange->endOffset()), DOWNSTREAM);
</ins><span class="cx">             } else {
</span><span class="cx">                 // The new range contains the original range.
</span><span class="cx">                 selection.setSelection(makeSimpleRange(range));
</span><span class="lines">@@ -369,7 +367,7 @@
</span><span class="cx">                 selection.setSelection(makeSimpleRange(*normalizedRange));
</span><span class="cx">             } else {
</span><span class="cx">                 // The ranges intersect.
</span><del>-                selection.moveTo(normalizedRange->startPosition(), range.endPosition(), DOWNSTREAM);
</del><ins>+                selection.moveTo(makeDeprecatedLegacyPosition(&normalizedRange->startContainer(), normalizedRange->startOffset()), makeDeprecatedLegacyPosition(&range.endContainer(), range.endOffset()), DOWNSTREAM);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -404,7 +402,7 @@
</span><span class="cx"> 
</span><span class="cx">     Ref<Node> protectedNode(node);
</span><span class="cx">     auto selectedRange = selection.selection().toNormalizedRange();
</span><del>-    if (!selectedRange)
</del><ins>+    if (!selectedRange || selectedRange->start.container->containingShadowRoot())
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     ContainerNode* parentNode = node.parentNode();
</span></span></pre></div>
<a id="trunkSourceWebCorepagePagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.cpp (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.cpp       2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebCore/page/Page.cpp  2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -859,9 +859,10 @@
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         if (firstFrame == secondFrame) {
</span><del>-            // comparePositions is used here instead of Node::compareDocumentPosition because some editing roots may exist inside shadow roots.
-            return comparePositions({ firstNode.get(), Position::PositionIsBeforeChildren }, { secondNode.get(), Position::PositionIsBeforeChildren }) > 0;
</del><ins>+            // Use documentOrder instead of Node::compareDocumentPosition because some editing roots are inside shadow roots.
+            return is_gt(documentOrder(*firstNode, *secondNode));
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         return frameToTraversalIndexMap.get(firstFrame) > frameToTraversalIndexMap.get(secondFrame);
</span><span class="cx">     });
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebKit/ChangeLog       2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2020-08-17  Darin Adler  <darin@apple.com>
+
+        Create documentOrder function, start refactoring to use it instead of Range::compare functions
+        https://bugs.webkit.org/show_bug.cgi?id=215551
+
+        Reviewed by Chris Dumez.
+
+        * WebProcess/InjectedBundle/API/mac/WKDOMRange.mm:
+        (-[WKDOMRange rangeByExpandingToWordBoundaryByCharacters:inDirection:]):
+        Use makeDeprecatedLegacyPosition instead of Range::start/endPosition.
+        This was the only place in the WebKit framework still using
+        Range::start/endPosition and over time we would like to move from
+        makeDeprecatedLegacyPosition to makeContainerOffsetPosition, so it's good
+        to have it be explicit here rather than hidden inside the Range class.
+
</ins><span class="cx"> 2020-08-22  Philippe Normand  <pnormand@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [GTK][WPE] Compilation warnings with clang/gcc 10
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessInjectedBundleAPImacWKDOMRangemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKDOMRange.mm (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKDOMRange.mm      2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKDOMRange.mm 2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -134,7 +134,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (WKDOMRange *)rangeByExpandingToWordBoundaryByCharacters:(NSUInteger)characters inDirection:(WKDOMRangeDirection)direction
</span><span class="cx"> {
</span><del>-    auto newRange = rangeExpandedByCharactersInDirectionAtWordBoundary(direction == WKDOMRangeDirectionForward ?  _impl->endPosition() : _impl->startPosition(), characters, direction == WKDOMRangeDirectionForward ? WebCore::SelectionDirection::Forward : WebCore::SelectionDirection::Backward);
</del><ins>+    auto range = makeSimpleRange(*_impl);
+    auto newRange = rangeExpandedByCharactersInDirectionAtWordBoundary(makeDeprecatedLegacyPosition(direction == WKDOMRangeDirectionForward ? range.end : range.start), characters, direction == WKDOMRangeDirectionForward ? WebCore::SelectionDirection::Forward : WebCore::SelectionDirection::Backward);
</ins><span class="cx">     return [[[WKDOMRange alloc] _initWithImpl:createLiveRange(newRange).get()] autorelease];
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitLegacyiosChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKitLegacy/ios/ChangeLog (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKitLegacy/ios/ChangeLog  2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebKitLegacy/ios/ChangeLog     2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2020-08-17  Darin Adler  <darin@apple.com>
+
+        Create documentOrder function, start refactoring to use it instead of Range::compare functions
+        https://bugs.webkit.org/show_bug.cgi?id=215551
+
+        Reviewed by Chris Dumez.
+
+        * WebCoreSupport/WebVisiblePosition.mm:
+        (-[DOMRange startPosition]): Rewrote to not use Range::startPosition.
+        (-[DOMRange endPosition]): Rewrote to not use Range::endPosition.
+
</ins><span class="cx"> 2020-08-13  Tim Horton  <timothy_horton@apple.com>
</span><span class="cx"> 
</span><span class="cx">         macCatalyst: Granting location permission doesn't allow geolocation access
</span></span></pre></div>
<a id="trunkSourceWebKitLegacyiosWebCoreSupportWebVisiblePositionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKitLegacy/ios/WebCoreSupport/WebVisiblePosition.mm (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKitLegacy/ios/WebCoreSupport/WebVisiblePosition.mm       2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebKitLegacy/ios/WebCoreSupport/WebVisiblePosition.mm  2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -455,14 +455,14 @@
</span><span class="cx"> 
</span><span class="cx"> - (WebVisiblePosition *)startPosition
</span><span class="cx"> {
</span><del>-    Range *range = core(self);
-    return [WebVisiblePosition _wrapVisiblePosition:VisiblePosition(range->startPosition())];
</del><ins>+    auto& range = *core(self);
+    return [WebVisiblePosition _wrapVisiblePosition:makeDeprecatedLegacyPosition(&range.startContainer(), range.startOffset())];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (WebVisiblePosition *)endPosition
</span><span class="cx"> {
</span><del>-    Range *range = core(self);
-    return [WebVisiblePosition _wrapVisiblePosition:VisiblePosition(range->endPosition())];
</del><ins>+    auto& range = *core(self);
+    return [WebVisiblePosition _wrapVisiblePosition:makeDeprecatedLegacyPosition(&range.endContainer(), range.endOffset())];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (DOMRange *)enclosingWordRange
</span></span></pre></div>
<a id="trunkSourceWebKitLegacymacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKitLegacy/mac/ChangeLog  2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog     2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2020-08-17  Darin Adler  <darin@apple.com>
+
+        Create documentOrder function, start refactoring to use it instead of Range::compare functions
+        https://bugs.webkit.org/show_bug.cgi?id=215551
+
+        Reviewed by Chris Dumez.
+
+        * WebView/WebFrame.mm:
+        (-[WebFrame _smartInsertForString:replacingRange:beforeString:afterString:]):
+        Rewrite to use makeSimpleRange and makeContainerOffsetPosition. Simplifies
+        the null checks. Would love to remove the function but at this time it's
+        still used by Apple's Mail app (albeit in a peculiar way, always passing a
+        constant string).
+
</ins><span class="cx"> 2020-08-17  David Kilzer  <ddkilzer@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Clean up DragApplicationFlags after switch to OptionSet<>
</span></span></pre></div>
<a id="trunkSourceWebKitLegacymacWebViewWebFramemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm        2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm   2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1968,7 +1968,8 @@
</span><span class="cx">     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if !PLATFORM(IOS_FAMILY)
</del><ins>+#if PLATFORM(MAC)
+
</ins><span class="cx"> // Determines whether whitespace needs to be added around aString to preserve proper spacing and
</span><span class="cx"> // punctuation when it's inserted into the receiver's text over charRange. Returns by reference
</span><span class="cx"> // in beforeString and afterString any whitespace that should be added, unless either or both are
</span><span class="lines">@@ -1981,30 +1982,25 @@
</span><span class="cx">     if (afterString)
</span><span class="cx">         *afterString = nil;
</span><span class="cx">         
</span><del>-    // inspect destination
-    WebCore::Node *startContainer = core([rangeToReplace startContainer]);
-    WebCore::Node *endContainer = core([rangeToReplace endContainer]);
</del><ins>+    auto range = makeSimpleRange(core(rangeToReplace));
+    if (!range)
+        return;
</ins><span class="cx"> 
</span><del>-    WebCore::Position startPos(startContainer, [rangeToReplace startOffset], WebCore::Position::PositionIsOffsetInAnchor);
-    WebCore::Position endPos(endContainer, [rangeToReplace endOffset], WebCore::Position::PositionIsOffsetInAnchor);
</del><ins>+    auto start = WebCore::VisiblePosition { makeContainerOffsetPosition(range->start) };
+    auto end = WebCore::VisiblePosition { makeContainerOffsetPosition(range->end) };
</ins><span class="cx"> 
</span><del>-    WebCore::VisiblePosition startVisiblePos = WebCore::VisiblePosition(startPos, WebCore::VP_DEFAULT_AFFINITY);
-    WebCore::VisiblePosition endVisiblePos = WebCore::VisiblePosition(endPos, WebCore::VP_DEFAULT_AFFINITY);
</del><ins>+    bool addLeadingSpace = start.deepEquivalent().leadingWhitespacePosition(WebCore::VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(start);
+    if (addLeadingSpace) {
+        if (UChar previousCharacter = start.previous().characterAfter())
+            addLeadingSpace = !WebCore::isCharacterSmartReplaceExempt(previousCharacter, true);
+    }
</ins><span class="cx">     
</span><del>-    // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
-    if (startVisiblePos.isNull() || endVisiblePos.isNull())
-        return;
</del><ins>+    bool addTrailingSpace = end.deepEquivalent().trailingWhitespacePosition(WebCore::VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(end);
+    if (addTrailingSpace) {
+        if (UChar followingCharacter = end.characterAfter())
+            addTrailingSpace = !WebCore::isCharacterSmartReplaceExempt(followingCharacter, false);
+    }
</ins><span class="cx"> 
</span><del>-    bool addLeadingSpace = startPos.leadingWhitespacePosition(WebCore::VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
-    if (addLeadingSpace)
-        if (UChar previousChar = startVisiblePos.previous().characterAfter())
-            addLeadingSpace = !WebCore::isCharacterSmartReplaceExempt(previousChar, true);
-    
-    bool addTrailingSpace = endPos.trailingWhitespacePosition(WebCore::VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
-    if (addTrailingSpace)
-        if (UChar thisChar = endVisiblePos.characterAfter())
-            addTrailingSpace = !WebCore::isCharacterSmartReplaceExempt(thisChar, false);
-    
</del><span class="cx">     // inspect source
</span><span class="cx">     bool hasWhitespaceAtStart = false;
</span><span class="cx">     bool hasWhitespaceAtEnd = false;
</span><span class="lines">@@ -2019,7 +2015,7 @@
</span><span class="cx">             hasWhitespaceAtEnd = YES;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // issue the verdict
</span><span class="cx">     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
</span><span class="cx">         *beforeString = @" ";
</span><span class="lines">@@ -2026,8 +2022,9 @@
</span><span class="cx">     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
</span><span class="cx">         *afterString = @" ";
</span><span class="cx"> }
</span><del>-#endif // !PLATFORM(IOS_FAMILY)
</del><span class="cx"> 
</span><ins>+#endif // PLATFORM(MAC)
+
</ins><span class="cx"> - (NSMutableDictionary *)_cacheabilityDictionary
</span><span class="cx"> {
</span><span class="cx">     NSMutableDictionary *result = [NSMutableDictionary dictionary];
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Tools/ChangeLog       2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2020-08-17  Darin Adler  <darin@apple.com>
+
+        Create documentOrder function, start refactoring to use it instead of Range::compare functions
+        https://bugs.webkit.org/show_bug.cgi?id=215551
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added DocumentOrder.cpp.
+        * TestWebKitAPI/Tests/WebCore/DocumentOrder.cpp: Added.
+        Relatively thorough test of three different documentOrder functions.
+        Could still use even more test cases involving different types of shadow trees.
+
</ins><span class="cx"> 2020-08-22  Philippe Normand  <pnormand@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [GTK][WPE] Compilation warnings with clang/gcc 10
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (266025 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2020-08-22 14:33:25 UTC (rev 266025)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj   2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -805,6 +805,7 @@
</span><span class="cx">          937A6C8A24357C1700C3A6B0 /* KillWebProcessWithOpenConnection-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 937A6C8824357BF300C3A6B0 /* KillWebProcessWithOpenConnection-1.html */; };
</span><span class="cx">          937A6C8B24357C1700C3A6B0 /* KillWebProcessWithOpenConnection-2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 937A6C8924357BF300C3A6B0 /* KillWebProcessWithOpenConnection-2.html */; };
</span><span class="cx">          937B569E23CD23DB002AE640 /* IDBObjectStoreInfoUpgrade.sqlite3 in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93BCBC8123CC6EF500CA2221 /* IDBObjectStoreInfoUpgrade.sqlite3 */; };
</span><ins>+               93915A1724DB66C70019FF43 /* DocumentOrder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93915A1624DB66C70019FF43 /* DocumentOrder.cpp */; };
</ins><span class="cx">           9399BA0423711140008392BF /* IndexedDBInPageCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9399BA01237110AE008392BF /* IndexedDBInPageCache.mm */; };
</span><span class="cx">          9399BA052371114F008392BF /* IndexedDBInPageCache.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9399BA02237110BF008392BF /* IndexedDBInPageCache.html */; };
</span><span class="cx">          9399BA062371114F008392BF /* IndexedDBNotInPageCache.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9399BA03237110BF008392BF /* IndexedDBNotInPageCache.html */; };
</span><span class="lines">@@ -2116,7 +2117,6 @@
</span><span class="cx">          574F55D0204D471C002948C6 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
</span><span class="cx">          5751B289249D5B9900664C2A /* web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-pin-token-fake-pin-invalid-error-retry.html"; sourceTree = "<group>"; };
</span><span class="cx">          57537EE724BEA0190048DBA5 /* web-authentication-get-assertion-nfc-pin-disconnect.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-get-assertion-nfc-pin-disconnect.html"; sourceTree = "<group>"; };
</span><del>-               5758597D23A2527A00C74572 /* CtapPinTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapPinTest.h; sourceTree = "<group>"; };
</del><span class="cx">           5758597E23A2527A00C74572 /* CtapPinTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CtapPinTest.cpp; sourceTree = "<group>"; };
</span><span class="cx">          5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-retries-error.html"; sourceTree = "<group>"; };
</span><span class="cx">          57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexedDBStructuredCloneBackwardCompatibility.mm; sourceTree = "<group>"; };
</span><span class="lines">@@ -2381,6 +2381,7 @@
</span><span class="cx">          936F727F1CD7D9D00068A0FB /* large-video-with-audio.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "large-video-with-audio.mp4"; sourceTree = "<group>"; };
</span><span class="cx">          937A6C8824357BF300C3A6B0 /* KillWebProcessWithOpenConnection-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "KillWebProcessWithOpenConnection-1.html"; sourceTree = "<group>"; };
</span><span class="cx">          937A6C8924357BF300C3A6B0 /* KillWebProcessWithOpenConnection-2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "KillWebProcessWithOpenConnection-2.html"; sourceTree = "<group>"; };
</span><ins>+               93915A1624DB66C70019FF43 /* DocumentOrder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentOrder.cpp; sourceTree = "<group>"; };
</ins><span class="cx">           9399BA01237110AE008392BF /* IndexedDBInPageCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexedDBInPageCache.mm; sourceTree = "<group>"; };
</span><span class="cx">          9399BA02237110BF008392BF /* IndexedDBInPageCache.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = IndexedDBInPageCache.html; sourceTree = "<group>"; };
</span><span class="cx">          9399BA03237110BF008392BF /* IndexedDBNotInPageCache.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = IndexedDBNotInPageCache.html; sourceTree = "<group>"; };
</span><span class="lines">@@ -3440,12 +3441,12 @@
</span><span class="cx">                          44CF31FB24993F66009CB6CB /* ContextMenuAction.cpp */,
</span><span class="cx">                          CD5451E919E41F9D0016936F /* CSSParser.cpp */,
</span><span class="cx">                          5758597E23A2527A00C74572 /* CtapPinTest.cpp */,
</span><del>-                               5758597D23A2527A00C74572 /* CtapPinTest.h */,
</del><span class="cx">                           572B403321769A88000AD43E /* CtapRequestTest.cpp */,
</span><span class="cx">                          572B404321781B42000AD43E /* CtapResponseTest.cpp */,
</span><span class="cx">                          260BA5781B1D2E7B004FA07C /* DFACombiner.cpp */,
</span><span class="cx">                          260BA57A1B1D2EE2004FA07C /* DFAHelpers.h */,
</span><span class="cx">                          26F6E1EF1ADC749B00DE696B /* DFAMinimizer.cpp */,
</span><ins>+                               93915A1624DB66C70019FF43 /* DocumentOrder.cpp */,
</ins><span class="cx">                           3151180F1DB1ADD500176304 /* ExtendedColorTests.cpp */,
</span><span class="cx">                          579651E6216BFD53006EBFE5 /* FidoHidMessageTest.cpp */,
</span><span class="cx">                          572B40352176A029000AD43E /* FidoTestData.h */,
</span><span class="lines">@@ -5066,6 +5067,7 @@
</span><span class="cx">                          73BD731823A846500020F450 /* DisplayName.mm in Sources */,
</span><span class="cx">                          518EE51B20A78D0000E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm in Sources */,
</span><span class="cx">                          2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */,
</span><ins>+                               93915A1724DB66C70019FF43 /* DocumentOrder.cpp in Sources */,
</ins><span class="cx">                           7CCE7EEB1A411AE600447C4C /* DocumentStartUserScriptAlertCrash.cpp in Sources */,
</span><span class="cx">                          7CCE7EBB1A411A7E00447C4C /* DOMHTMLTableCellCellAbove.mm in Sources */,
</span><span class="cx">                          2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */,
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreDocumentOrdercpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/DocumentOrder.cpp (0 => 266026)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/DocumentOrder.cpp                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/DocumentOrder.cpp   2020-08-22 16:11:58 UTC (rev 266026)
</span><span class="lines">@@ -0,0 +1,455 @@
</span><ins>+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/BoundaryPoint.h>
+#include <WebCore/Document.h>
+#include <WebCore/HTMLBodyElement.h>
+#include <WebCore/HTMLDivElement.h>
+#include <WebCore/HTMLHtmlElement.h>
+#include <WebCore/HTMLTextAreaElement.h>
+#include <WebCore/Position.h>
+#include <WebCore/TextControlInnerElements.h>
+
+#define EXPECT_BOTH(a, b, forward, reversed) do { EXPECT_STREQ(string(documentOrder(a, b)), forward); EXPECT_STREQ(string(documentOrder(b, a)), reversed); } while (0)
+#define EXPECT_EQUIVALENT(a, b) EXPECT_BOTH(a, b, "equivalent", "equivalent")
+#define EXPECT_LESS(a, b) EXPECT_BOTH(a, b, "less", "greater")
+#define EXPECT_UNORDERED(a, b) EXPECT_BOTH(a, b, "unordered", "unordered")
+
+namespace TestWebKitAPI {
+
+using namespace WebCore;
+
+static Ref<Document> createDocument()
+{
+    HTMLNames::init();
+    auto document = Document::create(aboutBlankURL());
+    auto documentElement = HTMLHtmlElement::create(document);
+    document->appendChild(documentElement);
+    auto body = HTMLBodyElement::create(document);
+    documentElement->appendChild(body);
+    return document;
+}
+
+static BoundaryPoint makeBoundaryPoint(Node& node, unsigned offset)
+{
+    return { node, offset };
+}
+
+constexpr const char* string(PartialOrdering ordering)
+{
+    if (is_lt(ordering))
+        return "less";
+    if (is_gt(ordering))
+        return "greater";
+    if (is_eq(ordering))
+        return "equivalent";
+    return "unordered";
+}
+
+static PartialOrdering operator-(PartialOrdering ordering)
+{
+    if (is_lt(ordering))
+        return PartialOrdering::greater;
+    if (is_gt(ordering))
+        return PartialOrdering::less;
+    return ordering;
+}
+
+TEST(DocumentOrder, Node)
+{
+    HTMLNames::init();
+
+    auto document = createDocument();
+    auto& body = *document->body();
+
+    EXPECT_EQUIVALENT(document, document);
+
+    EXPECT_EQUIVALENT(body, body);
+    EXPECT_LESS(document, body);
+    EXPECT_LESS(document, body);
+
+    auto a = HTMLDivElement::create(document);
+    EXPECT_EQUIVALENT(a, a);
+    EXPECT_UNORDERED(body, a);
+    EXPECT_UNORDERED(a, body);
+
+    body.appendChild(a);
+    EXPECT_LESS(body, a);
+    EXPECT_LESS(body, a);
+    EXPECT_EQUIVALENT(a, a);
+
+    auto b = HTMLDivElement::create(document);
+    body.appendChild(b);
+    EXPECT_LESS(body, b);
+    EXPECT_LESS(body, b);
+    EXPECT_LESS(a, b);
+    EXPECT_LESS(a, b);
+
+    auto c = HTMLDivElement::create(document);
+    b->appendChild(c);
+    EXPECT_LESS(body, c);
+    EXPECT_LESS(body, c);
+    EXPECT_LESS(a, c);
+    EXPECT_LESS(b, c);
+    EXPECT_LESS(a, c);
+    EXPECT_LESS(b, c);
+
+    auto d = HTMLDivElement::create(document);
+    a->appendChild(d);
+    EXPECT_LESS(body, d);
+    EXPECT_LESS(body, d);
+    EXPECT_LESS(a, d);
+    EXPECT_LESS(d, b);
+    EXPECT_LESS(d, c);
+    EXPECT_LESS(a, d);
+    EXPECT_LESS(d, b);
+    EXPECT_LESS(d, c);
+
+    auto e = HTMLDivElement::create(document);
+    auto f = HTMLDivElement::create(document);
+    e->appendChild(f);
+    EXPECT_UNORDERED(body, f);
+    EXPECT_UNORDERED(f, body);
+
+    auto g = HTMLTextAreaElement::create(document);
+    c->appendChild(g);
+    EXPECT_LESS(body, g);
+
+    auto& h = *g->innerTextElement();
+    EXPECT_LESS(body, h);
+}
+
+TEST(DocumentOrder, BoundaryPointOffsetZero)
+{
+    auto document = createDocument();
+    auto& body = *document->body();
+
+    EXPECT_EQUIVALENT(makeBoundaryPoint(document, 0), makeBoundaryPoint(document, 0));
+
+    EXPECT_LESS(makeBoundaryPoint(document, 0), makeBoundaryPoint(body, 0));
+
+    auto a = HTMLDivElement::create(document);
+    EXPECT_EQUIVALENT(makeBoundaryPoint(a, 0), makeBoundaryPoint(a, 0));
+    EXPECT_UNORDERED(makeBoundaryPoint(body, 0), makeBoundaryPoint(a, 0));
+
+    body.appendChild(a);
+    EXPECT_EQUIVALENT(makeBoundaryPoint(a, 0), makeBoundaryPoint(a, 0));
+    EXPECT_LESS(makeBoundaryPoint(body, 0), makeBoundaryPoint(a, 0));
+
+    auto b = HTMLDivElement::create(document);
+    body.appendChild(b);
+    EXPECT_LESS(makeBoundaryPoint(body, 0), makeBoundaryPoint(b, 0));
+    EXPECT_LESS(makeBoundaryPoint(a, 0), makeBoundaryPoint(b, 0));
+
+    auto c = HTMLDivElement::create(document);
+    b->appendChild(c);
+    EXPECT_LESS(makeBoundaryPoint(body, 0), makeBoundaryPoint(c, 0));
+    EXPECT_LESS(makeBoundaryPoint(a, 0), makeBoundaryPoint(c, 0));
+    EXPECT_LESS(makeBoundaryPoint(b, 0), makeBoundaryPoint(c, 0));
+
+    auto d = HTMLDivElement::create(document);
+    a->appendChild(d);
+    EXPECT_LESS(makeBoundaryPoint(body, 0), makeBoundaryPoint(d, 0));
+    EXPECT_LESS(makeBoundaryPoint(a, 0), makeBoundaryPoint(d, 0));
+    EXPECT_LESS(makeBoundaryPoint(d, 0), makeBoundaryPoint(b, 0));
+    EXPECT_LESS(makeBoundaryPoint(d, 0), makeBoundaryPoint(c, 0));
+
+    auto e = HTMLDivElement::create(document);
+    auto f = HTMLDivElement::create(document);
+    e->appendChild(f);
+    EXPECT_UNORDERED(makeBoundaryPoint(body, 0), makeBoundaryPoint(f, 0));
+
+    auto g = HTMLTextAreaElement::create(document);
+    auto h = g->innerTextElement();
+    ASSERT_TRUE(h);
+    c->appendChild(g);
+    EXPECT_LESS(makeBoundaryPoint(body, 0), makeBoundaryPoint(g, 0));
+}
+
+TEST(DocumentOrder, BoundaryPointOffsets)
+{
+    auto document = createDocument();
+    auto& body = *document->body();
+
+    EXPECT_LESS(makeBoundaryPoint(document, 0), makeBoundaryPoint(document, 1));
+    EXPECT_LESS(makeBoundaryPoint(body, 0), makeBoundaryPoint(document, 1));
+
+    auto a = HTMLDivElement::create(document);
+    body.appendChild(a);
+    EXPECT_LESS(makeBoundaryPoint(a, 0), makeBoundaryPoint(body, 1));
+
+    auto b = HTMLDivElement::create(document);
+    body.appendChild(b);
+    EXPECT_LESS(makeBoundaryPoint(body, 1), makeBoundaryPoint(b, 0));
+    EXPECT_LESS(makeBoundaryPoint(b, 0), makeBoundaryPoint(body, 2));
+
+    auto c = HTMLDivElement::create(document);
+    b->appendChild(c);
+    EXPECT_LESS(makeBoundaryPoint(body, 1), makeBoundaryPoint(c, 0));
+    EXPECT_LESS(makeBoundaryPoint(c, 0), makeBoundaryPoint(body, 2));
+    EXPECT_LESS(makeBoundaryPoint(a, 1), makeBoundaryPoint(c, 0));
+    EXPECT_LESS(makeBoundaryPoint(c, 0), makeBoundaryPoint(b, 1));
+
+    auto d = HTMLDivElement::create(document);
+    a->appendChild(d);
+    EXPECT_LESS(makeBoundaryPoint(d, 0), makeBoundaryPoint(body, 1));
+    EXPECT_LESS(makeBoundaryPoint(d, 0), makeBoundaryPoint(a, 1));
+    EXPECT_LESS(makeBoundaryPoint(d, 0), makeBoundaryPoint(b, 1));
+    EXPECT_LESS(makeBoundaryPoint(d, 0), makeBoundaryPoint(c, 1));
+
+    auto e = HTMLDivElement::create(document);
+    auto f = HTMLDivElement::create(document);
+    e->appendChild(f);
+    EXPECT_UNORDERED(makeBoundaryPoint(body, 1), makeBoundaryPoint(f, 0));
+
+    auto g = HTMLTextAreaElement::create(document);
+    c->appendChild(g);
+    EXPECT_LESS(makeBoundaryPoint(body, 1), makeBoundaryPoint(g, 0));
+    EXPECT_LESS(makeBoundaryPoint(c, 0), makeBoundaryPoint(c, 1));
+    EXPECT_LESS(makeBoundaryPoint(c, 1), makeBoundaryPoint(c, 2));
+    EXPECT_LESS(makeBoundaryPoint(c, 0), makeBoundaryPoint(c, 2));
+    EXPECT_LESS(makeBoundaryPoint(c, 0), makeBoundaryPoint(g, 0));
+    EXPECT_LESS(makeBoundaryPoint(g, 0), makeBoundaryPoint(c, 1));
+    EXPECT_LESS(makeBoundaryPoint(g, 0), makeBoundaryPoint(c, 2));
+
+    auto& h = *g->innerTextElement();
+    EXPECT_LESS(makeBoundaryPoint(body, 1), makeBoundaryPoint(h, 0));
+    EXPECT_LESS(makeBoundaryPoint(c, 0), makeBoundaryPoint(h, 0));
+    EXPECT_LESS(makeBoundaryPoint(h, 0), makeBoundaryPoint(c, 1));
+    EXPECT_LESS(makeBoundaryPoint(h, 0), makeBoundaryPoint(c, 2));
+}
+
+static Vector<Position> allPositionTypes(Node* node, unsigned offset)
+{
+    Vector<Position> positions;
+    bool canContainRangeEndpoint = !node || node->canContainRangeEndPoint();
+    if (canContainRangeEndpoint)
+        positions.append(makeContainerOffsetPosition(node, offset));
+    if (!node && !offset) {
+        positions.append({ nullptr, Position::PositionIsBeforeAnchor });
+        positions.append({ nullptr, Position::PositionIsAfterAnchor });
+    } else {
+        if (canContainRangeEndpoint && !offset)
+            positions.append({ node, Position::PositionIsBeforeChildren });
+        if (canContainRangeEndpoint && offset == (node ? node->length() : 0))
+            positions.append({ node, Position::PositionIsAfterChildren });
+        if (node) {
+            if (offset) {
+                if (auto childBefore = node->traverseToChildAt(offset - 1))
+                    positions.append({ childBefore, Position::PositionIsAfterAnchor });
+            }
+            if (auto childAfter = node->traverseToChildAt(offset))
+                positions.append({ childAfter, Position::PositionIsBeforeAnchor });
+        }
+    }
+    return positions;
+}
+
+constexpr const char* typeStringSuffix(const Position& position)
+{
+    switch (position.anchorType()) {
+    case Position::PositionIsOffsetInAnchor:
+        return "";
+    case Position::PositionIsBeforeChildren:
+        return "[before-children]";
+    case Position::PositionIsAfterChildren:
+        return "[after-children]";
+    case Position::PositionIsBeforeAnchor:
+        return "[before]";
+    case Position::PositionIsAfterAnchor:
+        return "[after]";
+    }
+    return "[invalid]";
+}
+
+static String join(const Vector<String>& vector, ASCIILiteral separator)
+{
+    StringBuilder builder;
+    bool needSeparator = false;
+    for (auto& string : vector) {
+        if (needSeparator)
+            builder.append(separator);
+        builder.append(string);
+        needSeparator = true;
+    }
+    return builder.toString();
+}
+
+static CString allPositionTypeFailures(const Position& a, Node* nodeB, unsigned offsetB, PartialOrdering expectedResult)
+{
+    Vector<String> failures;
+    for (auto& b : allPositionTypes(nodeB, offsetB)) {
+        auto result = string(documentOrder(a, b));
+        if (strcmp(result, string(expectedResult)))
+            failures.append(makeString("order(b", typeStringSuffix(b), ")=", result, "<expected:", string(expectedResult), '>'));
+        result = string(documentOrder(b, a));
+        if (strcmp(result, string(-expectedResult)))
+            failures.append(makeString("order(b", typeStringSuffix(b), ")=", result, "<expected:", string(-expectedResult), '>'));
+    }
+    return join(failures, ", "_s).utf8();
+}
+
+static CString allPositionTypeFailures(Node* nodeA, unsigned offsetA, Node* nodeB, unsigned offsetB, PartialOrdering expectedResult)
+{
+    Vector<String> failures;
+    for (auto& a : allPositionTypes(nodeA, offsetA)) {
+        for (auto& b : allPositionTypes(nodeB, offsetB)) {
+            auto result = string(documentOrder(a, b));
+            if (strcmp(result, string(expectedResult)))
+                failures.append(makeString("order(a", typeStringSuffix(a), ",b", typeStringSuffix(b), ")=", result, "<expected:", string(expectedResult), '>'));
+            result = string(documentOrder(b, a));
+            if (strcmp(result, string(-expectedResult)))
+                failures.append(makeString("order(b", typeStringSuffix(b), ",a", typeStringSuffix(a), ")=", result, "<expected:", string(-expectedResult), '>'));
+        }
+    }
+    return join(failures, " | "_s).utf8();
+}
+
+static CString allPositionTypeFailures(Node& nodeA, unsigned offsetA, Node& nodeB, unsigned offsetB, PartialOrdering expectedResult)
+{
+    return allPositionTypeFailures(&nodeA, offsetA, &nodeB, offsetB, expectedResult);
+}
+
+static CString allPositionTypeFailures(Node* nodeA, unsigned offsetA, Node& nodeB, unsigned offsetB, PartialOrdering expectedResult)
+{
+    return allPositionTypeFailures(nodeA, offsetA, &nodeB, offsetB, expectedResult);
+}
+
+static CString allPositionTypeFailures(const Position& a, Node& nodeB, unsigned offsetB, PartialOrdering expectedResult)
+{
+    return allPositionTypeFailures(a, &nodeB, offsetB, expectedResult);
+}
+
+#define TEST_ALL_POSITION_TYPES(nodeA, offsetA, nodeB, offsetB, expectedResult) \
+    EXPECT_STREQ(allPositionTypeFailures(nodeA, offsetA, nodeB, offsetB, PartialOrdering::expectedResult).data(), "")
+#define TEST_ALL_POSITION_TYPES_B(positionA, nodeB, offsetB, expectedResult) \
+    EXPECT_STREQ(allPositionTypeFailures(positionA, nodeB, offsetB, PartialOrdering::expectedResult).data(), "")
+
+static Position makePositionBefore(Node& node)
+{
+    return { &node, Position::PositionIsBeforeAnchor };
+}
+
+static Position makePositionAfter(Node& node)
+{
+    return { &node, Position::PositionIsAfterAnchor };
+}
+
+TEST(DocumentOrder, Positions)
+{
+    auto document = createDocument();
+    auto& body = *document->body();
+
+    TEST_ALL_POSITION_TYPES(nullptr, 0, nullptr, 0, equivalent);
+    TEST_ALL_POSITION_TYPES(nullptr, 1, nullptr, 0, equivalent);
+    TEST_ALL_POSITION_TYPES(nullptr, 1, nullptr, 1, equivalent);
+
+    TEST_ALL_POSITION_TYPES(nullptr, 0, document, 0, unordered);
+    TEST_ALL_POSITION_TYPES(nullptr, 0, document, 1, unordered);
+
+    TEST_ALL_POSITION_TYPES(document, 0, document, 0, equivalent);
+    TEST_ALL_POSITION_TYPES(document, 0, document, 1, less);
+
+    TEST_ALL_POSITION_TYPES(document, 0, body, 0, less);
+    TEST_ALL_POSITION_TYPES(body, 0, document, 1, less);
+
+    auto a = HTMLDivElement::create(document);
+    body.appendChild(a);
+    TEST_ALL_POSITION_TYPES(body, 0, a, 0, less);
+    TEST_ALL_POSITION_TYPES(a, 0, body, 1, less);
+
+    auto b = HTMLDivElement::create(document);
+    body.appendChild(b);
+    TEST_ALL_POSITION_TYPES(body, 0, b, 0, less);
+    TEST_ALL_POSITION_TYPES(body, 1, b, 0, less);
+    TEST_ALL_POSITION_TYPES(b, 0, body, 2, less);
+
+    auto c = HTMLDivElement::create(document);
+    b->appendChild(c);
+    TEST_ALL_POSITION_TYPES(body, 0, c, 0, less);
+    TEST_ALL_POSITION_TYPES(body, 1, c, 0, less);
+    TEST_ALL_POSITION_TYPES(c, 0, body, 2, less);
+    TEST_ALL_POSITION_TYPES(a, 0, c, 0, less);
+    TEST_ALL_POSITION_TYPES(a, 1, c, 0, less);
+    TEST_ALL_POSITION_TYPES(b, 0, c, 0, less);
+    TEST_ALL_POSITION_TYPES(c, 0, b, 1, less);
+
+    auto d = HTMLDivElement::create(document);
+    a->appendChild(d);
+    TEST_ALL_POSITION_TYPES(body, 0, d, 0, less);
+    TEST_ALL_POSITION_TYPES(d, 0, body, 1, less);
+    TEST_ALL_POSITION_TYPES(a, 0, d, 0, less);
+    TEST_ALL_POSITION_TYPES(d, 0, a, 1, less);
+    TEST_ALL_POSITION_TYPES(d, 0, b, 0, less);
+    TEST_ALL_POSITION_TYPES(d, 0, b, 1, less);
+    TEST_ALL_POSITION_TYPES(d, 0, c, 0, less);
+    TEST_ALL_POSITION_TYPES(d, 0, c, 1, less);
+
+    auto e = HTMLDivElement::create(document);
+    EXPECT_UNORDERED(makePositionBefore(document), makePositionBefore(e));
+    EXPECT_UNORDERED(makePositionBefore(document), makePositionAfter(e));
+    EXPECT_UNORDERED(makePositionAfter(document), makePositionBefore(e));
+    EXPECT_UNORDERED(makePositionAfter(document), makePositionAfter(e));
+
+    auto f = HTMLDivElement::create(document);
+    e->appendChild(f);
+    TEST_ALL_POSITION_TYPES(body, 1, f, 0, unordered);
+
+    auto g = HTMLTextAreaElement::create(document);
+    c->appendChild(g);
+    TEST_ALL_POSITION_TYPES(body, 1, g, 0, less);
+    TEST_ALL_POSITION_TYPES(c, 0, c, 1, less);
+    TEST_ALL_POSITION_TYPES(c, 1, c, 2, less);
+    TEST_ALL_POSITION_TYPES(c, 0, c, 2, less);
+    TEST_ALL_POSITION_TYPES(c, 0, g, 0, less);
+    TEST_ALL_POSITION_TYPES(g, 0, c, 1, less);
+    TEST_ALL_POSITION_TYPES(g, 0, c, 2, less);
+
+    auto& h = *g->innerTextElement();
+    TEST_ALL_POSITION_TYPES(body, 1, h, 0, less);
+    TEST_ALL_POSITION_TYPES(c, 0, h, 0, less);
+    TEST_ALL_POSITION_TYPES(h, 0, c, 1, less);
+    TEST_ALL_POSITION_TYPES(h, 0, c, 2, less);
+
+    EXPECT_EQUIVALENT(makePositionBefore(document), makePositionBefore(document));
+    EXPECT_EQUIVALENT(makePositionAfter(document), makePositionAfter(document));
+    EXPECT_LESS(makePositionBefore(document), makePositionAfter(document));
+
+    TEST_ALL_POSITION_TYPES_B(makePositionBefore(document), document, 0, less);
+    TEST_ALL_POSITION_TYPES_B(makePositionBefore(document), body, 0, less);
+    TEST_ALL_POSITION_TYPES_B(makePositionBefore(document), document, 1, less);
+    TEST_ALL_POSITION_TYPES_B(makePositionBefore(document), body, 1, less);
+    TEST_ALL_POSITION_TYPES_B(makePositionBefore(document), h, 0, less);
+
+    TEST_ALL_POSITION_TYPES_B(makePositionAfter(document), document, 0, greater);
+    TEST_ALL_POSITION_TYPES_B(makePositionAfter(document), document, 1, greater);
+    TEST_ALL_POSITION_TYPES_B(makePositionAfter(document), body, 0, greater);
+    TEST_ALL_POSITION_TYPES_B(makePositionAfter(document), body, 1, greater);
+    TEST_ALL_POSITION_TYPES_B(makePositionAfter(document), h, 0, greater);
+}
+
+} // namespace TestWebKitAPI
</ins></span></pre>
</div>
</div>

</body>
</html>