<!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>[214112] 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/214112">214112</a></dd>
<dt>Author</dt> <dd>n_wang@apple.com</dd>
<dt>Date</dt> <dd>2017-03-17 12:48:36 -0700 (Fri, 17 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>AX: VoiceOver no longer works corectly with editable text in the web
https://bugs.webkit.org/show_bug.cgi?id=169801

Reviewed by Chris Fleizach.

Source/WebCore:

The issue is that since we are entering text controls when getting the text marker,
the end text marker of the input tag might associate to the placeholder div instead of 
the input tag itself. 
Fixed the issue by checking the shadow elements using shadowHost() instead of isShadowRoot().
Also, only enter text controls when navigating by characters/indexes, so that both Mac and
iOS will get the correct text marker ranges for shadow host elements.

Tests: accessibility/ios-simulator/element-text-range-for-text-control.html
       accessibility/mac/text-markers-for-input-with-placeholder.html

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::traverseToOffsetInRange):
(WebCore::AXObjectCache::startOrEndCharacterOffsetForRange):
(WebCore::AXObjectCache::characterOffsetForIndex):
* accessibility/AXObjectCache.h:

LayoutTests:

* accessibility/ios-simulator/element-text-range-for-text-control-expected.txt: Added.
* accessibility/ios-simulator/element-text-range-for-text-control.html: Added.
* accessibility/mac/text-markers-for-input-with-placeholder-expected.txt: Added.
* accessibility/mac/text-markers-for-input-with-placeholder.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCachecpp">trunk/Source/WebCore/accessibility/AXObjectCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCacheh">trunk/Source/WebCore/accessibility/AXObjectCache.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilityiossimulatorelementtextrangefortextcontrolexpectedtxt">trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilityiossimulatorelementtextrangefortextcontrolhtml">trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control.html</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkersforinputwithplaceholderexpectedtxt">trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkersforinputwithplaceholderhtml">trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (214111 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-17 19:30:43 UTC (rev 214111)
+++ trunk/LayoutTests/ChangeLog        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-03-17  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: VoiceOver no longer works corectly with editable text in the web
+        https://bugs.webkit.org/show_bug.cgi?id=169801
+
+        Reviewed by Chris Fleizach.
+
+        * accessibility/ios-simulator/element-text-range-for-text-control-expected.txt: Added.
+        * accessibility/ios-simulator/element-text-range-for-text-control.html: Added.
+        * accessibility/mac/text-markers-for-input-with-placeholder-expected.txt: Added.
+        * accessibility/mac/text-markers-for-input-with-placeholder.html: Added.
+
</ins><span class="cx"> 2017-03-17  Dave Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Initial letter does not paginate properly.
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilityiossimulatorelementtextrangefortextcontrolexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control-expected.txt (0 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control-expected.txt                                (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control-expected.txt        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+
+This test ensures that elementTextRange is valid for text controls
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS input.elementTextPosition != -1 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilityiossimulatorelementtextrangefortextcontrolhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control.html (0 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control.html                                (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/element-text-range-for-text-control.html        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+var successfullyParsed = false;
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body id=&quot;body&quot;&gt;
+
+&lt;input id=&quot;input&quot; type='text'&gt;
+
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+
+&lt;script&gt;
+
+    description(&quot;This test ensures that elementTextRange is valid for text controls&quot;);
+
+    if (window.accessibilityController) {
+
+        var input = accessibilityController.accessibleElementById(&quot;input&quot;);
+        shouldBeTrue(&quot;input.elementTextPosition != -1&quot;);
+    }
+
+    successfullyParsed = true;
+&lt;/script&gt;
+
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkersforinputwithplaceholderexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder-expected.txt (0 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder-expected.txt                                (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder-expected.txt        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+
+This tests that start and end text markers of an input element with placeholder are valid.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS input.isEqual(startObject) is true
+PASS input.isEqual(endObject) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkersforinputwithplaceholderhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder.html (0 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder.html                                (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-markers-for-input-with-placeholder.html        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body id=&quot;body&quot;&gt;
+
+&lt;input id=&quot;input&quot; type='text' placeholder='text'&gt;
+
+&lt;div role=&quot;group&quot; id=&quot;console&quot;&gt;&lt;/div&gt;
+
+&lt;script&gt;
+
+    description(&quot;This tests that start and end text markers of an input element with placeholder are valid.&quot;);
+
+    // Test contenteditable with newlines.
+    var input = accessibilityController.accessibleElementById(&quot;input&quot;);
+    var textMarkerRange = input.textMarkerRangeForElement(input);
+    var startMarker = input.endTextMarkerForTextMarkerRange(textMarkerRange);
+    var endMarker = input.endTextMarkerForTextMarkerRange(textMarkerRange);
+    
+    // make sure the associated object of endMarker is the input object
+    var startObject = input.accessibilityElementForTextMarker(startMarker);
+    var endObject = input.accessibilityElementForTextMarker(endMarker);
+    shouldBeTrue(&quot;input.isEqual(startObject)&quot;);
+    shouldBeTrue(&quot;input.isEqual(endObject)&quot;);
+
+&lt;/script&gt;
+
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214111 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-17 19:30:43 UTC (rev 214111)
+++ trunk/Source/WebCore/ChangeLog        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2017-03-17  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: VoiceOver no longer works corectly with editable text in the web
+        https://bugs.webkit.org/show_bug.cgi?id=169801
+
+        Reviewed by Chris Fleizach.
+
+        The issue is that since we are entering text controls when getting the text marker,
+        the end text marker of the input tag might associate to the placeholder div instead of 
+        the input tag itself. 
+        Fixed the issue by checking the shadow elements using shadowHost() instead of isShadowRoot().
+        Also, only enter text controls when navigating by characters/indexes, so that both Mac and
+        iOS will get the correct text marker ranges for shadow host elements.
+
+        Tests: accessibility/ios-simulator/element-text-range-for-text-control.html
+               accessibility/mac/text-markers-for-input-with-placeholder.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::traverseToOffsetInRange):
+        (WebCore::AXObjectCache::startOrEndCharacterOffsetForRange):
+        (WebCore::AXObjectCache::characterOffsetForIndex):
+        * accessibility/AXObjectCache.h:
+
</ins><span class="cx"> 2017-03-17  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WK1] Support animated transitions when performing a data interaction operation
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (214111 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2017-03-17 19:30:43 UTC (rev 214111)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -1555,6 +1555,7 @@
</span><span class="cx">     
</span><span class="cx">     bool toNodeEnd = option &amp; TraverseOptionToNodeEnd;
</span><span class="cx">     bool validateOffset = option &amp; TraverseOptionValidateOffset;
</span><ins>+    bool doNotEnterTextControls = option &amp; TraverseOptionDoNotEnterTextControls;
</ins><span class="cx">     
</span><span class="cx">     int offsetInCharacter = 0;
</span><span class="cx">     int cumulativeOffset = 0;
</span><span class="lines">@@ -1564,7 +1565,7 @@
</span><span class="cx">     bool finished = false;
</span><span class="cx">     int lastStartOffset = 0;
</span><span class="cx">     
</span><del>-    TextIterator iterator(range.get(), TextIteratorEntersTextControls);
</del><ins>+    TextIterator iterator(range.get(), doNotEnterTextControls ? TextIteratorDefaultBehavior : TextIteratorEntersTextControls);
</ins><span class="cx">     
</span><span class="cx">     // When the range has zero length, there might be replaced node or brTag that we need to increment the characterOffset.
</span><span class="cx">     if (iterator.atEnd()) {
</span><span class="lines">@@ -1617,11 +1618,13 @@
</span><span class="cx">                     if (childNode &amp;&amp; childNode-&gt;renderer() &amp;&amp; childNode-&gt;renderer()-&gt;isBR()) {
</span><span class="cx">                         currentNode = childNode;
</span><span class="cx">                         hasReplacedNodeOrBR = true;
</span><del>-                    } else if (currentNode-&gt;isShadowRoot()) {
</del><ins>+                    } else if (Element *shadowHost = currentNode-&gt;shadowHost()) {
</ins><span class="cx">                         // Since we are entering text controls, we should set the currentNode
</span><span class="cx">                         // to be the shadow host when there's no content.
</span><del>-                        currentNode = currentNode-&gt;shadowHost();
-                        continue;
</del><ins>+                        if (nodeIsTextControl(shadowHost)) {
+                            currentNode = currentNode-&gt;shadowHost();
+                            continue;
+                        }
</ins><span class="cx">                     } else if (currentNode != previousNode) {
</span><span class="cx">                         // We should set the start offset and length for the current node in case this is the last iteration.
</span><span class="cx">                         lastStartOffset = 1;
</span><span class="lines">@@ -1837,7 +1840,7 @@
</span><span class="cx">     this-&gt;setNodeInUse(domNode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CharacterOffset AXObjectCache::startOrEndCharacterOffsetForRange(RefPtr&lt;Range&gt; range, bool isStart)
</del><ins>+CharacterOffset AXObjectCache::startOrEndCharacterOffsetForRange(RefPtr&lt;Range&gt; range, bool isStart, bool enterTextControls)
</ins><span class="cx"> {
</span><span class="cx">     if (!range)
</span><span class="cx">         return CharacterOffset();
</span><span class="lines">@@ -1865,7 +1868,10 @@
</span><span class="cx">         offset += nodeStartOffset.offset;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    return traverseToOffsetInRange(WTFMove(copyRange), offset, isStart ? TraverseOptionDefault : TraverseOptionToNodeEnd, stayWithinRange);
</del><ins>+    TraverseOption options = isStart ? TraverseOptionDefault : TraverseOptionToNodeEnd;
+    if (!enterTextControls)
+        options = static_cast&lt;TraverseOption&gt;(options | TraverseOptionDoNotEnterTextControls);
+    return traverseToOffsetInRange(WTFMove(copyRange), offset, options, stayWithinRange);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AXObjectCache::startOrEndTextMarkerDataForRange(TextMarkerData&amp; textMarkerData, RefPtr&lt;Range&gt; range, bool isStart)
</span><span class="lines">@@ -2616,8 +2622,8 @@
</span><span class="cx">         return CharacterOffset();
</span><span class="cx">     
</span><span class="cx">     RefPtr&lt;Range&gt; range = obj-&gt;elementRange();
</span><del>-    CharacterOffset start = startOrEndCharacterOffsetForRange(range, true);
-    CharacterOffset end = startOrEndCharacterOffsetForRange(range, false);
</del><ins>+    CharacterOffset start = startOrEndCharacterOffsetForRange(range, true, true);
+    CharacterOffset end = startOrEndCharacterOffsetForRange(range, false, true);
</ins><span class="cx">     CharacterOffset result = start;
</span><span class="cx">     for (int i = 0; i &lt; index; i++) {
</span><span class="cx">         result = nextCharacterOffset(result, false);
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (214111 => 214112)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.h        2017-03-17 19:30:43 UTC (rev 214111)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h        2017-03-17 19:48:36 UTC (rev 214112)
</span><span class="lines">@@ -222,7 +222,7 @@
</span><span class="cx">     CharacterOffset nextCharacterOffset(const CharacterOffset&amp;, bool ignoreNextNodeStart = true);
</span><span class="cx">     CharacterOffset previousCharacterOffset(const CharacterOffset&amp;, bool ignorePreviousNodeEnd = true);
</span><span class="cx">     void startOrEndTextMarkerDataForRange(TextMarkerData&amp;, RefPtr&lt;Range&gt;, bool);
</span><del>-    CharacterOffset startOrEndCharacterOffsetForRange(RefPtr&lt;Range&gt;, bool);
</del><ins>+    CharacterOffset startOrEndCharacterOffsetForRange(RefPtr&lt;Range&gt;, bool, bool enterTextControls = false);
</ins><span class="cx">     AccessibilityObject* accessibilityObjectForTextMarkerData(TextMarkerData&amp;);
</span><span class="cx">     RefPtr&lt;Range&gt; rangeForUnorderedCharacterOffsets(const CharacterOffset&amp;, const CharacterOffset&amp;);
</span><span class="cx">     static RefPtr&lt;Range&gt; rangeForNodeContents(Node*);
</span><span class="lines">@@ -351,7 +351,7 @@
</span><span class="cx">     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
</span><span class="cx">     
</span><span class="cx">     // CharacterOffset functions.
</span><del>-    enum TraverseOption { TraverseOptionDefault = 1 &lt;&lt; 0, TraverseOptionToNodeEnd = 1 &lt;&lt; 1, TraverseOptionIncludeStart = 1 &lt;&lt; 2, TraverseOptionValidateOffset = 1 &lt;&lt; 3 };
</del><ins>+    enum TraverseOption { TraverseOptionDefault = 1 &lt;&lt; 0, TraverseOptionToNodeEnd = 1 &lt;&lt; 1, TraverseOptionIncludeStart = 1 &lt;&lt; 2, TraverseOptionValidateOffset = 1 &lt;&lt; 3, TraverseOptionDoNotEnterTextControls = 1 &lt;&lt; 4 };
</ins><span class="cx">     Node* nextNode(Node*) const;
</span><span class="cx">     Node* previousNode(Node*) const;
</span><span class="cx">     CharacterOffset traverseToOffsetInRange(RefPtr&lt;Range&gt;, int, TraverseOption = TraverseOptionDefault, bool stayWithinRange = false);
</span></span></pre>
</div>
</div>

</body>
</html>