<!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>[196352] 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/196352">196352</a></dd>
<dt>Author</dt> <dd>n_wang@apple.com</dd>
<dt>Date</dt> <dd>2016-02-09 18:33:04 -0800 (Tue, 09 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>AX: Implement word related text marker functions using TextIterator
https://bugs.webkit.org/show_bug.cgi?id=153939
&lt;rdar://problem/24269605&gt;

Reviewed by Chris Fleizach.

Source/WebCore:

Using CharacterOffset to implement word related text marker calls. Reused
logic from previousBoundary and nextBoundary in VisibleUnits class.

Test: accessibility/mac/text-marker-word-nav.html

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::traverseToOffsetInRange):
(WebCore::AXObjectCache::rangeForNodeContents):
(WebCore::isReplacedNodeOrBR):
(WebCore::characterOffsetsInOrder):
(WebCore::resetNodeAndOffsetForReplacedNode):
(WebCore::setRangeStartOrEndWithCharacterOffset):
(WebCore::AXObjectCache::rangeForUnorderedCharacterOffsets):
(WebCore::AXObjectCache::setTextMarkerDataWithCharacterOffset):
(WebCore::AXObjectCache::startOrEndCharacterOffsetForRange):
(WebCore::AXObjectCache::startOrEndTextMarkerDataForRange):
(WebCore::AXObjectCache::characterOffsetForNodeAndOffset):
(WebCore::AXObjectCache::textMarkerDataForCharacterOffset):
(WebCore::AXObjectCache::previousNode):
(WebCore::AXObjectCache::visiblePositionFromCharacterOffset):
(WebCore::AXObjectCache::characterOffsetFromVisiblePosition):
(WebCore::AXObjectCache::textMarkerDataForVisiblePosition):
(WebCore::AXObjectCache::nextCharacterOffset):
(WebCore::AXObjectCache::previousCharacterOffset):
(WebCore::startWordBoundary):
(WebCore::endWordBoundary):
(WebCore::AXObjectCache::startCharacterOffsetOfWord):
(WebCore::AXObjectCache::endCharacterOffsetOfWord):
(WebCore::AXObjectCache::previousWordStartCharacterOffset):
(WebCore::AXObjectCache::nextWordEndCharacterOffset):
(WebCore::AXObjectCache::leftWordRange):
(WebCore::AXObjectCache::rightWordRange):
(WebCore::characterForCharacterOffset):
(WebCore::AXObjectCache::characterAfter):
(WebCore::AXObjectCache::characterBefore):
(WebCore::parentEditingBoundary):
(WebCore::AXObjectCache::nextWordBoundary):
(WebCore::AXObjectCache::previousWordBoundary):
(WebCore::AXObjectCache::rootAXEditableElement):
* accessibility/AXObjectCache.h:
(WebCore::AXObjectCache::removeNodeForUse):
(WebCore::AXObjectCache::isNodeInUse):
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(-[WebAccessibilityObjectWrapper previousTextMarkerForNode:offset:]):
(-[WebAccessibilityObjectWrapper textMarkerForNode:offset:ignoreStart:]):
(-[WebAccessibilityObjectWrapper textMarkerForNode:offset:]):
(textMarkerForCharacterOffset):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
* editing/VisibleUnits.cpp:
(WebCore::rightWordPosition):
(WebCore::prepend):
(WebCore::appendRepeatedCharacter):
(WebCore::suffixLengthForRange):
(WebCore::prefixLengthForRange):
(WebCore::backwardSearchForBoundaryWithTextIterator):
(WebCore::forwardSearchForBoundaryWithTextIterator):
(WebCore::previousBoundary):
(WebCore::nextBoundary):
* editing/VisibleUnits.h:

Tools:

* DumpRenderTree/AccessibilityUIElement.cpp:
(endTextMarkerCallback):
(leftWordTextMarkerRangeForTextMarkerCallback):
(rightWordTextMarkerRangeForTextMarkerCallback):
(previousWordStartTextMarkerForTextMarkerCallback):
(nextWordEndTextMarkerForTextMarkerCallback):
(setSelectedVisibleTextRangeCallback):
(AccessibilityUIElement::setSelectedVisibleTextRange):
(AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
(AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(AccessibilityUIElement::getJSClass):
* DumpRenderTree/AccessibilityUIElement.h:
* DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
(AccessibilityUIElement::setSelectedVisibleTextRange):
(AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
(AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
* DumpRenderTree/mac/AccessibilityUIElementMac.mm:
(AccessibilityUIElement::setSelectedVisibleTextRange):
(AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
(AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(AccessibilityUIElement::supportedActions):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
(WTR::AccessibilityUIElement::setBoolAttributeValue):
(WTR::AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::endTextMarker):
(WTR::AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::mathPostscriptsDescription):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::AccessibilityUIElement::endTextMarker):
(WTR::AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(WTR::_convertMathMultiscriptPairsToString):

LayoutTests:

* accessibility/mac/text-marker-word-nav-expected.txt: Added.
* accessibility/mac/text-marker-word-nav.html: Added.
* accessibility/text-marker/text-marker-previous-next-expected.txt:
* accessibility/text-marker/text-marker-previous-next.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnextexpectedtxt">trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnexthtml">trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html</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>
<li><a href="#trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm">trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitscpp">trunk/Source/WebCore/editing/VisibleUnits.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitsh">trunk/Source/WebCore/editing/VisibleUnits.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreeAccessibilityUIElementcpp">trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp</a></li>
<li><a href="#trunkToolsDumpRenderTreeAccessibilityUIElementh">trunk/Tools/DumpRenderTree/AccessibilityUIElement.h</a></li>
<li><a href="#trunkToolsDumpRenderTreeiosAccessibilityUIElementIOSmm">trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm</a></li>
<li><a href="#trunkToolsDumpRenderTreemacAccessibilityUIElementMacmm">trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementh">trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleBindingsAccessibilityUIElementidl">trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleiosAccessibilityUIElementIOSmm">trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundlemacAccessibilityUIElementMacmm">trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerwordnavexpectedtxt">trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerwordnavhtml">trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/LayoutTests/ChangeLog        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-02-09  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: Implement word related text marker functions using TextIterator
+        https://bugs.webkit.org/show_bug.cgi?id=153939
+        &lt;rdar://problem/24269605&gt;
+
+        Reviewed by Chris Fleizach.
+
+        * accessibility/mac/text-marker-word-nav-expected.txt: Added.
+        * accessibility/mac/text-marker-word-nav.html: Added.
+        * accessibility/text-marker/text-marker-previous-next-expected.txt:
+        * accessibility/text-marker/text-marker-previous-next.html:
+
</ins><span class="cx"> 2016-02-09  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Mark perf/adding-radio-buttons.html as flaky on ios-simulator
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerwordnavexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt (0 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt                                (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+word1 test
+Thisislongword I'll try. Test Contenteditable is working.
+c d
+can't select
+巧克力是食物吗?
+كيف حالك؟
+both   spaces
+line breaks
+some
+text
+test audio file
+This tests that word navigation is working correctly.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Current character is: w
+Left word is: word1
+Right word is: word1
+Pre word start to next word end: word1
+
+Current character is: T
+Left word is: Thisislongword
+Right word is: Thisislongword
+Pre word start to next word end: Thisislongword
+
+Current character is:  
+Left word is:  
+Right word is: I'll
+Pre word start to next word end:  I'll
+
+Current character is:  
+Left word is:  
+Right word is: try
+Pre word start to next word end:  try
+
+Current character is: e
+Left word is: editable
+Right word is: editable
+Pre word start to next word end: editable
+
+Current character is:  
+Left word is:  
+Right word is: [ATTACHMENT]
+Pre word start to next word end:  [ATTACHMENT]
+
+Current character is: [ATTACHMENT]
+Left word is: [ATTACHMENT]
+Right word is: d
+Pre word start to next word end: [ATTACHMENT]d
+
+Current character is: c
+Left word is: can't
+Right word is: can't
+Pre word start to next word end: can't
+
+Current character is: 克
+Left word is: 巧克力
+Right word is: 巧克力
+Pre word start to next word end: 巧克力
+
+Current character is: 力
+Left word is: 巧克力
+Right word is: 是
+Pre word start to next word end: 巧克力是
+
+Current character is: 是
+Left word is: 是
+Right word is: 食物
+Pre word start to next word end: 是食物
+
+Current character is: ف
+Left word is: كيف
+Right word is:  
+Pre word start to next word end: كيف 
+
+Current character is:  
+Left word is:  
+Right word is: حالك
+Pre word start to next word end:  حالك
+
+Current character is: h
+Left word is: both
+Right word is:    
+Pre word start to next word end: both   
+
+Current character is: s
+Left word is: spaces
+Right word is: 'line break'
+Pre word start to next word end: spaces'line break'
+
+Current character is: e
+Left word is: some
+Right word is: 'line break'
+Pre word start to next word end: some'line break'
+
+Current character is: 'line break'
+Left word is: 'line break'
+Right word is: text
+Pre word start to next word end: 'line break'text
+
+Current character is:  
+Left word is:  
+Right word is: [ATTACHMENT]
+Pre word start to next word end:  [ATTACHMENT]
+
+Current character is: [ATTACHMENT]
+Left word is: [ATTACHMENT]
+Right word is: file
+Pre word start to next word end: [ATTACHMENT]file
+
+Current character is: f
+Left word is: file
+Right word is: file
+Pre word start to next word end: file
+
+Test going forward.
+End word: file
+
+Test going backwards.
+Start word: word1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerwordnavhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html (0 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html                                (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -0,0 +1,195 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;meta charset=&quot;utf-8&quot;&gt; 
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;style&gt;
+.userselect { user-select: none; -webkit-user-select: none; }
+&lt;/style&gt;
+&lt;body id=&quot;body&quot;&gt;
+
+&lt;div id=&quot;text&quot; tabindex=&quot;0&quot;&gt;word1 test&lt;/div&gt;
+&lt;span id=&quot;span&quot;&gt;Thisis&lt;/span&gt;longword I&lt;span&gt;'ll try.&lt;/span&gt;
+Test Content&lt;span id=&quot;target&quot; contenteditable=&quot;true&quot;&gt;editable is working.&lt;/span&gt;
+
+&lt;div id=&quot;text2&quot;&gt;
+c &lt;img src=&quot;#&quot; aria-label=&quot;blah&quot; style=&quot;background-color: #aaaaaa; width: 100px; height: 100px;&quot;&gt;d
+&lt;/div&gt;
+
+&lt;div class=&quot;userselect&quot; id=&quot;text3&quot;&gt;can't select&lt;/div&gt;
+
+&lt;div id=&quot;text4&quot;&gt;
+巧克力是食物吗?
+&lt;/div&gt;
+&lt;div id=&quot;text4a&quot;&gt;
+كيف حالك؟
+&lt;/div&gt;
+
+&lt;pre id=&quot;text5&quot;&gt;
+both   spaces
+line breaks
+&lt;/pre&gt;
+
+&lt;div id=&quot;text6&quot;&gt;
+some&lt;br&gt;text
+&lt;/div&gt;
+
+&lt;div id=&quot;text7&quot;&gt;
+test audio &lt;audio controls&gt;&lt;source src=&quot;test.mp3&quot; type=&quot;audio/mpeg&quot;&gt;&lt;/audio&gt;file
+&lt;/div&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 tests that word navigation is working correctly.&quot;);
+    
+    if (window.accessibilityController) {
+        
+        var text = accessibilityController.accessibleElementById(&quot;text&quot;);
+        // Get the actual text node.
+        text = text.childAtIndex(0);
+        
+        // Check that we can get the word range. Land at &quot;w&quot; in &quot;word1 test&quot;.
+        var textMarkerRange = text.textMarkerRangeForElement(text);
+        var startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+        var currentMarker = advanceAndVerify(startMarker, 1, text);
+        
+        // Check the case with span
+        // At &quot;T&quot; in &quot;Thisis&quot;, should return the word as &quot;Thisislongword&quot;.
+        currentMarker = advanceAndVerify(currentMarker, 10, text);
+        // At &quot; &quot; before &quot;I&quot;, the word should be &quot;I'll&quot;.
+        currentMarker = advanceAndVerify(currentMarker, 14, text);
+        // At &quot; &quot; before &quot;try&quot;, the word should excludes &quot;.&quot;
+        currentMarker = advanceAndVerify(currentMarker, 5, text);
+        
+        // Check the case with contenteditable
+        // At &quot;e&quot; in &quot;editable&quot;, the word should NOT include &quot;Content&quot; before it.
+        currentMarker = advanceAndVerify(currentMarker, 17, text);
+        
+        // Check the case with replaced node, the replaced node should be considered a word.
+        var text2 = accessibilityController.accessibleElementById(&quot;text2&quot;);
+        textMarkerRange = text2.textMarkerRangeForElement(text2);
+        currentMarker = text2.startTextMarkerForTextMarkerRange(textMarkerRange);
+        currentMarker = advanceAndVerify(currentMarker, 2, text2);
+        currentMarker = advanceAndVerify(currentMarker, 1, text2);
+        
+        // Check user-select:none is also working.
+        var text3 = accessibilityController.accessibleElementById(&quot;text3&quot;);
+        textMarkerRange = text3.textMarkerRangeForElement(text3);
+        currentMarker = text3.startTextMarkerForTextMarkerRange(textMarkerRange);
+        currentMarker = advanceAndVerify(currentMarker, 1, text3);
+        
+        // Check multi-language, Chinese here.
+        var text4 = accessibilityController.accessibleElementById(&quot;text4&quot;);
+        textMarkerRange = text4.textMarkerRangeForElement(text4);
+        currentMarker = text4.startTextMarkerForTextMarkerRange(textMarkerRange);
+        currentMarker = advanceAndVerify(currentMarker, 2, text4);
+        currentMarker = advanceAndVerify(currentMarker, 1, text4);
+        currentMarker = advanceAndVerify(currentMarker, 1, text4);
+        // And Arabic
+        var text4a = accessibilityController.accessibleElementById(&quot;text4a&quot;);
+        textMarkerRange = text4a.textMarkerRangeForElement(text4a);
+        currentMarker = text4a.startTextMarkerForTextMarkerRange(textMarkerRange);
+        currentMarker = advanceAndVerify(currentMarker, 3, text4a);
+        currentMarker = advanceAndVerify(currentMarker, 1, text4a);
+        
+        // Check text in pre tag with line breaks.
+        var text5 = accessibilityController.accessibleElementById(&quot;text5&quot;);
+        textMarkerRange = text5.textMarkerRangeForElement(text5);
+        currentMarker = text5.startTextMarkerForTextMarkerRange(textMarkerRange);
+        // At &quot;h&quot; in &quot;both&quot;, right word should be &quot;   &quot;.
+        currentMarker = advanceAndVerify(currentMarker, 4, text5);
+        // At the end of first line, right word should be new line.
+        currentMarker = advanceAndVerify(currentMarker, 9, text5);
+        
+        // Check text with br tag in it.
+        var text6 = accessibilityController.accessibleElementById(&quot;text6&quot;);
+        textMarkerRange = text6.textMarkerRangeForElement(text6);
+        currentMarker = text6.startTextMarkerForTextMarkerRange(textMarkerRange);
+        currentMarker = advanceAndVerify(currentMarker, 4, text6);
+        currentMarker = advanceAndVerify(currentMarker, 1, text6);
+        
+        // Check &lt;audio&gt; element.
+        var text7 = accessibilityController.accessibleElementById(&quot;text7&quot;);
+        textMarkerRange = text7.textMarkerRangeForElement(text7);
+        currentMarker = text7.startTextMarkerForTextMarkerRange(textMarkerRange);
+        currentMarker = advanceAndVerify(currentMarker, 11, text7);
+        currentMarker = advanceAndVerify(currentMarker, 1, text7);
+        currentMarker = advanceAndVerify(currentMarker, 1, text7);
+        
+        // Check the word marker runs from start to end, and backwards.
+        // Make sure it won't hang.
+        verifyDocument(text);
+        
+        function advanceAndVerify(currentMarker, offset, obj) {
+            var previousMarker;
+            for (var i = 0; i &lt; offset; i++) {
+                previousMarker = currentMarker;
+                currentMarker = obj.nextTextMarker(previousMarker);
+            }
+            verifyWordRangeForTextMarker(previousMarker, currentMarker, obj);
+            return currentMarker;
+        }
+        
+        function replaceAttachmentInString(str) {
+            var newline = '\n';
+            str =  str.replace(String.fromCharCode(65532), &quot;[ATTACHMENT]&quot;);
+            str = str.replace(newline, &quot;'line break'&quot;);
+            return str;
+        }
+        
+        function verifyWordRangeForTextMarker(preMarker, textMarker, obj) {
+            var markerRange = obj.textMarkerRangeForMarkers(preMarker, textMarker);
+            var currentCharacter = replaceAttachmentInString(obj.stringForTextMarkerRange(markerRange));
+            debug(&quot;Current character is: &quot; + currentCharacter);
+            
+            var previousWordRange = obj.leftWordTextMarkerRangeForTextMarker(textMarker);
+            var nextWordRange = obj.rightWordTextMarkerRangeForTextMarker(textMarker);
+            var preWord = replaceAttachmentInString(obj.stringForTextMarkerRange(previousWordRange));
+            var nextWord = replaceAttachmentInString(obj.stringForTextMarkerRange(nextWordRange));
+            debug(&quot;Left word is: &quot; + preWord);
+            debug(&quot;Right word is: &quot; + nextWord);
+            
+            var preWordStart = obj.previousWordStartTextMarkerForTextMarker(textMarker);
+            var nextWordEnd = obj.nextWordEndTextMarkerForTextMarker(textMarker);
+            var preAndNextWordRange = obj.textMarkerRangeForMarkers(preWordStart, nextWordEnd);
+            var preAndNextWord = replaceAttachmentInString(obj.stringForTextMarkerRange(preAndNextWordRange));
+            debug(&quot;Pre word start to next word end: &quot; + preAndNextWord + &quot;\n&quot;);
+        }
+        
+        function verifyDocument(obj) {
+            var start = obj.startTextMarker;
+            
+            // Going forward.
+            debug(&quot;Test going forward.&quot;);
+            var current = start;
+            var endWord = &quot;file&quot;;
+            var currWord = &quot;&quot;;
+            while(currWord != endWord) {
+                var nextWordRange = obj.rightWordTextMarkerRangeForTextMarker(current);
+                currWord = obj.stringForTextMarkerRange(nextWordRange);
+                current = obj.nextWordEndTextMarkerForTextMarker(current);
+            }
+            debug(&quot;End word: &quot; + replaceAttachmentInString(currWord));
+            
+            // Going backwards.
+            debug(&quot;\nTest going backwards.&quot;);
+            var startWord = &quot;word1&quot;;
+            currWord = &quot;&quot;; 
+            while(currWord != startWord) {
+                var previousWordRange = obj.leftWordTextMarkerRangeForTextMarker(current);
+                currWord = obj.stringForTextMarkerRange(previousWordRange);
+                current = obj.previousWordStartTextMarkerForTextMarker(current);
+            }
+            debug(&quot;Start word: &quot; + replaceAttachmentInString(currWord));
+        }
+    }
+
+&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 class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnextexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -12,9 +12,9 @@
</span><span class="cx"> PASS text.textMarkerRangeLength(textMarkerRange) is 4
</span><span class="cx"> PASS text.accessibilityElementForTextMarker(startMarker).isEqual(text) is true
</span><span class="cx"> PASS text.accessibilityElementForTextMarker(endMarker).isEqual(text) is true
</span><del>-PASS text.stringForTextMarkerRange(markerRange) is ''
</del><ins>+PASS text.stringForTextMarkerRange(markerRange) is newline
</ins><span class="cx"> PASS text.stringForTextMarkerRange(markerRange) is 't'
</span><del>-PASS text.stringForTextMarkerRange(markerRange) is ''
</del><ins>+PASS text.stringForTextMarkerRange(markerRange) is newline
</ins><span class="cx"> PASS text.stringForTextMarkerRange(markerRange) is 't'
</span><span class="cx"> PASS text2.textMarkerRangeLength(textMarkerRange2) is 5
</span><span class="cx"> Object string for range: c [ATTACHMENT] d
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnexthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -50,7 +50,8 @@
</span><span class="cx">             currentMarker = text.nextTextMarker(currentMarker);
</span><span class="cx">         }
</span><span class="cx">         markerRange = text.textMarkerRangeForMarkers(previousMarker, currentMarker);
</span><del>-        shouldBe(&quot;text.stringForTextMarkerRange(markerRange)&quot;, &quot;''&quot;);
</del><ins>+        var newline = '\n';
+        shouldBe(&quot;text.stringForTextMarkerRange(markerRange)&quot;, &quot;newline&quot;);
</ins><span class="cx">         
</span><span class="cx">         // Advance one more character, it will lande at &quot;t&quot; in &quot;text1&quot;.
</span><span class="cx">         previousMarker = currentMarker;
</span><span class="lines">@@ -62,7 +63,7 @@
</span><span class="cx">         previousMarker = text.previousTextMarker(previousMarker);
</span><span class="cx">         currentMarker = text.previousTextMarker(currentMarker);
</span><span class="cx">         markerRange = text.textMarkerRangeForMarkers(previousMarker, currentMarker);
</span><del>-        shouldBe(&quot;text.stringForTextMarkerRange(markerRange)&quot;, &quot;''&quot;);
</del><ins>+        shouldBe(&quot;text.stringForTextMarkerRange(markerRange)&quot;, &quot;newline&quot;);
</ins><span class="cx">         
</span><span class="cx">         // Traverse backwards one more character, it will land at the last character of &quot;text&quot;.
</span><span class="cx">         previousMarker = text.previousTextMarker(previousMarker);
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Source/WebCore/ChangeLog        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -1,3 +1,71 @@
</span><ins>+2016-02-09  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: Implement word related text marker functions using TextIterator
+        https://bugs.webkit.org/show_bug.cgi?id=153939
+        &lt;rdar://problem/24269605&gt;
+
+        Reviewed by Chris Fleizach.
+
+        Using CharacterOffset to implement word related text marker calls. Reused
+        logic from previousBoundary and nextBoundary in VisibleUnits class.
+
+        Test: accessibility/mac/text-marker-word-nav.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::traverseToOffsetInRange):
+        (WebCore::AXObjectCache::rangeForNodeContents):
+        (WebCore::isReplacedNodeOrBR):
+        (WebCore::characterOffsetsInOrder):
+        (WebCore::resetNodeAndOffsetForReplacedNode):
+        (WebCore::setRangeStartOrEndWithCharacterOffset):
+        (WebCore::AXObjectCache::rangeForUnorderedCharacterOffsets):
+        (WebCore::AXObjectCache::setTextMarkerDataWithCharacterOffset):
+        (WebCore::AXObjectCache::startOrEndCharacterOffsetForRange):
+        (WebCore::AXObjectCache::startOrEndTextMarkerDataForRange):
+        (WebCore::AXObjectCache::characterOffsetForNodeAndOffset):
+        (WebCore::AXObjectCache::textMarkerDataForCharacterOffset):
+        (WebCore::AXObjectCache::previousNode):
+        (WebCore::AXObjectCache::visiblePositionFromCharacterOffset):
+        (WebCore::AXObjectCache::characterOffsetFromVisiblePosition):
+        (WebCore::AXObjectCache::textMarkerDataForVisiblePosition):
+        (WebCore::AXObjectCache::nextCharacterOffset):
+        (WebCore::AXObjectCache::previousCharacterOffset):
+        (WebCore::startWordBoundary):
+        (WebCore::endWordBoundary):
+        (WebCore::AXObjectCache::startCharacterOffsetOfWord):
+        (WebCore::AXObjectCache::endCharacterOffsetOfWord):
+        (WebCore::AXObjectCache::previousWordStartCharacterOffset):
+        (WebCore::AXObjectCache::nextWordEndCharacterOffset):
+        (WebCore::AXObjectCache::leftWordRange):
+        (WebCore::AXObjectCache::rightWordRange):
+        (WebCore::characterForCharacterOffset):
+        (WebCore::AXObjectCache::characterAfter):
+        (WebCore::AXObjectCache::characterBefore):
+        (WebCore::parentEditingBoundary):
+        (WebCore::AXObjectCache::nextWordBoundary):
+        (WebCore::AXObjectCache::previousWordBoundary):
+        (WebCore::AXObjectCache::rootAXEditableElement):
+        * accessibility/AXObjectCache.h:
+        (WebCore::AXObjectCache::removeNodeForUse):
+        (WebCore::AXObjectCache::isNodeInUse):
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (-[WebAccessibilityObjectWrapper previousTextMarkerForNode:offset:]):
+        (-[WebAccessibilityObjectWrapper textMarkerForNode:offset:ignoreStart:]):
+        (-[WebAccessibilityObjectWrapper textMarkerForNode:offset:]):
+        (textMarkerForCharacterOffset):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+        * editing/VisibleUnits.cpp:
+        (WebCore::rightWordPosition):
+        (WebCore::prepend):
+        (WebCore::appendRepeatedCharacter):
+        (WebCore::suffixLengthForRange):
+        (WebCore::prefixLengthForRange):
+        (WebCore::backwardSearchForBoundaryWithTextIterator):
+        (WebCore::forwardSearchForBoundaryWithTextIterator):
+        (WebCore::previousBoundary):
+        (WebCore::nextBoundary):
+        * editing/VisibleUnits.h:
+
</ins><span class="cx"> 2016-02-09  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSP: Extract helper classes into their own files
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -81,6 +81,7 @@
</span><span class="cx"> #include &quot;RenderTableRow.h&quot;
</span><span class="cx"> #include &quot;RenderView.h&quot;
</span><span class="cx"> #include &quot;ScrollView.h&quot;
</span><ins>+#include &quot;TextBoundaries.h&quot;
</ins><span class="cx"> #include &quot;TextIterator.h&quot;
</span><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -1470,6 +1471,7 @@
</span><span class="cx">     
</span><span class="cx">     for (; !iterator.atEnd(); iterator.advance()) {
</span><span class="cx">         int currentLength = iterator.text().length();
</span><ins>+        bool hasReplacedNodeOrBR = false;
</ins><span class="cx">         
</span><span class="cx">         Node&amp; node = iterator.range()-&gt;startContainer();
</span><span class="cx">         currentNode = &amp;node;
</span><span class="lines">@@ -1482,17 +1484,28 @@
</span><span class="cx">                 offsetSoFar++;
</span><span class="cx">                 currentLength++;
</span><span class="cx">                 currentNode = childNode;
</span><ins>+                hasReplacedNodeOrBR = true;
</ins><span class="cx">             } else
</span><span class="cx">                 continue;
</span><span class="cx">         } else {
</span><span class="cx">             // Ignore space, new line, tag node.
</span><del>-            if (currentLength == 1 &amp;&amp; isSpaceOrNewline(iterator.text()[0]))
-                continue;
</del><ins>+            if (currentLength == 1) {
+                if (isSpaceOrNewline(iterator.text()[0])) {
+                    // If the node has BR tag, we want to set the currentNode to it.
+                    int subOffset = iterator.range()-&gt;startOffset();
+                    Node* childNode = node.traverseToChildAt(subOffset);
+                    if (childNode &amp;&amp; childNode-&gt;renderer() &amp;&amp; childNode-&gt;renderer()-&gt;isBR()) {
+                        currentNode = childNode;
+                        hasReplacedNodeOrBR = true;
+                    } else
+                        continue;
+                }
+            }
</ins><span class="cx">             offsetSoFar += currentLength;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         lastLength = currentLength;
</span><del>-        lastStartOffset = iterator.range()-&gt;startOffset();
</del><ins>+        lastStartOffset = hasReplacedNodeOrBR ? 0 : iterator.range()-&gt;startOffset();
</ins><span class="cx">         
</span><span class="cx">         // Break early if we have advanced enough characters.
</span><span class="cx">         if (!toNodeEnd &amp;&amp; offsetSoFar &gt;= offset) {
</span><span class="lines">@@ -1546,6 +1559,11 @@
</span><span class="cx">     range-&gt;selectNodeContents(node, ec);
</span><span class="cx">     return ec ? nullptr : range;
</span><span class="cx"> }
</span><ins>+    
+static bool isReplacedNodeOrBR(Node* node)
+{
+    return node &amp;&amp; (AccessibilityObject::replacedNodeNeedsCharacter(node) || node-&gt;hasTagName(brTag));
+}
</ins><span class="cx"> 
</span><span class="cx"> static bool characterOffsetsInOrder(const CharacterOffset&amp; characterOffset1, const CharacterOffset&amp; characterOffset2)
</span><span class="cx"> {
</span><span class="lines">@@ -1555,8 +1573,18 @@
</span><span class="cx">     if (characterOffset1.node == characterOffset2.node)
</span><span class="cx">         return characterOffset1.offset &lt;= characterOffset2.offset;
</span><span class="cx">     
</span><del>-    RefPtr&lt;Range&gt; range1 = AXObjectCache::rangeForNodeContents(characterOffset1.node);
-    RefPtr&lt;Range&gt; range2 = AXObjectCache::rangeForNodeContents(characterOffset2.node);
</del><ins>+    Node* node1 = characterOffset1.node;
+    Node* node2 = characterOffset2.node;
+    if (!node1-&gt;offsetInCharacters() &amp;&amp; !isReplacedNodeOrBR(node1))
+        node1 = node1-&gt;traverseToChildAt(characterOffset1.offset);
+    if (!node2-&gt;offsetInCharacters() &amp;&amp; !isReplacedNodeOrBR(node2))
+        node2 = node2-&gt;traverseToChildAt(characterOffset2.offset);
+    
+    if (!node1 || !node2)
+        return false;
+    
+    RefPtr&lt;Range&gt; range1 = AXObjectCache::rangeForNodeContents(node1);
+    RefPtr&lt;Range&gt; range2 = AXObjectCache::rangeForNodeContents(node2);
</ins><span class="cx">     return range1-&gt;compareBoundaryPoints(Range::START_TO_START, range2.get(), IGNORE_EXCEPTION) &lt;= 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1572,9 +1600,26 @@
</span><span class="cx">     return replacedNode-&gt;parentNode();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool isReplacedNodeOrBR(Node* node)
</del><ins>+static void setRangeStartOrEndWithCharacterOffset(RefPtr&lt;Range&gt; range, CharacterOffset&amp; characterOffset, bool isStart, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    return AccessibilityObject::replacedNodeNeedsCharacter(node) || node-&gt;hasTagName(brTag);
</del><ins>+    if (!range) {
+        ec = RangeError;
+        return;
+    }
+    if (characterOffset.isNull()) {
+        ec = TypeError;
+        return;
+    }
+    
+    int offset = characterOffset.startIndex + characterOffset.offset;
+    Node* node = characterOffset.node;
+    if (isReplacedNodeOrBR(node))
+        node = resetNodeAndOffsetForReplacedNode(node, offset, characterOffset.offset);
+    
+    if (isStart)
+        range-&gt;setStart(node, offset, ec);
+    else
+        range-&gt;setEnd(node, offset, ec);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;Range&gt; AXObjectCache::rangeForUnorderedCharacterOffsets(const CharacterOffset&amp; characterOffset1, const CharacterOffset&amp; characterOffset2)
</span><span class="lines">@@ -1586,34 +1631,11 @@
</span><span class="cx">     CharacterOffset startCharacterOffset = alreadyInOrder ? characterOffset1 : characterOffset2;
</span><span class="cx">     CharacterOffset endCharacterOffset = alreadyInOrder ? characterOffset2 : characterOffset1;
</span><span class="cx">     
</span><del>-    int startOffset = startCharacterOffset.startIndex + startCharacterOffset.offset;
-    int endOffset = endCharacterOffset.startIndex + endCharacterOffset.offset;
-    Node* startNode = startCharacterOffset.node;
-    Node* endNode = endCharacterOffset.node;
-    
-    // Consider the case when the replaced node is at the start/end of the range.
-    bool startNodeIsReplacedOrBR = isReplacedNodeOrBR(startNode);
-    bool endNodeIsReplacedOrBR = isReplacedNodeOrBR(endNode);
-    if (startNodeIsReplacedOrBR || endNodeIsReplacedOrBR) {
-        // endOffset can be out of bounds sometimes if the node is a replaced node or has brTag and it has no children.
-        if (startNode == endNode &amp;&amp; !startNode-&gt;hasChildNodes()) {
-            RefPtr&lt;Range&gt; nodeRange = AXObjectCache::rangeForNodeContents(startNode);
-            int nodeLength = TextIterator::rangeLength(nodeRange.get());
-            if (endCharacterOffset.offset &gt; nodeLength)
-                endOffset = endCharacterOffset.startIndex + nodeLength;
-        } else {
-            if (startNodeIsReplacedOrBR)
-                startNode = resetNodeAndOffsetForReplacedNode(startNode, startOffset, startCharacterOffset.offset);
-            if (endNodeIsReplacedOrBR)
-                endNode = resetNodeAndOffsetForReplacedNode(startNode, endOffset, startCharacterOffset.offset);
-        }
-    }
-    
</del><span class="cx">     RefPtr&lt;Range&gt; result = Range::create(m_document);
</span><del>-    ExceptionCode ecStart = 0, ecEnd = 0;
-    result-&gt;setStart(startNode, startOffset, ecStart);
-    result-&gt;setEnd(endNode, endOffset, ecEnd);
-    if (ecStart || ecEnd)
</del><ins>+    ExceptionCode ec = 0;
+    setRangeStartOrEndWithCharacterOffset(result, startCharacterOffset, true, ec);
+    setRangeStartOrEndWithCharacterOffset(result, endCharacterOffset, false, ec);
+    if (ec)
</ins><span class="cx">         return nullptr;
</span><span class="cx">     
</span><span class="cx">     return result;
</span><span class="lines">@@ -1635,7 +1657,7 @@
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     // Convert to visible position.
</span><del>-    VisiblePosition visiblePosition = visiblePositionFromCharacterOffset(obj.get(), characterOffset);
</del><ins>+    VisiblePosition visiblePosition = visiblePositionFromCharacterOffset(characterOffset);
</ins><span class="cx">     int vpOffset = 0;
</span><span class="cx">     if (!visiblePosition.isNull()) {
</span><span class="cx">         Position deepPos = visiblePosition.deepEquivalent();
</span><span class="lines">@@ -1652,53 +1674,64 @@
</span><span class="cx">     this-&gt;setNodeInUse(domNode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void AXObjectCache::startOrEndTextMarkerDataForRange(TextMarkerData&amp; textMarkerData, RefPtr&lt;Range&gt; range, bool isStart)
</del><ins>+CharacterOffset AXObjectCache::startOrEndCharacterOffsetForRange(RefPtr&lt;Range&gt; range, bool isStart)
</ins><span class="cx"> {
</span><del>-    memset(&amp;textMarkerData, 0, sizeof(TextMarkerData));
-    
</del><span class="cx">     if (!range)
</span><del>-        return;
</del><ins>+        return CharacterOffset();
</ins><span class="cx">     
</span><span class="cx">     // If it's end text marker, we want to go to the end of the range, and stay within the range.
</span><span class="cx">     bool stayWithinRange = !isStart;
</span><span class="cx">     
</span><ins>+    RefPtr&lt;Range&gt; copyRange = range;
</ins><span class="cx">     // Change the start of the range, so the character offset starts from node beginning.
</span><span class="cx">     int offset = 0;
</span><del>-    Node* node = &amp;range-&gt;startContainer();
</del><ins>+    Node* node = &amp;copyRange-&gt;startContainer();
</ins><span class="cx">     if (node-&gt;offsetInCharacters()) {
</span><ins>+        copyRange = Range::create(range-&gt;ownerDocument(), &amp;range-&gt;startContainer(), range-&gt;startOffset(), &amp;range-&gt;endContainer(), range-&gt;endOffset());
</ins><span class="cx">         CharacterOffset nodeStartOffset = traverseToOffsetInRange(rangeForNodeContents(node), 0, false);
</span><del>-        offset = std::max(range-&gt;startOffset() - nodeStartOffset.startIndex, 0);
-        range-&gt;setStart(node, nodeStartOffset.startIndex);
</del><ins>+        offset = std::max(copyRange-&gt;startOffset() - nodeStartOffset.startIndex, 0);
+        copyRange-&gt;setStart(node, nodeStartOffset.startIndex);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    CharacterOffset characterOffset = traverseToOffsetInRange(range, offset, !isStart, stayWithinRange);
-    setTextMarkerDataWithCharacterOffset(textMarkerData, characterOffset);
</del><ins>+    return traverseToOffsetInRange(copyRange, offset, !isStart, stayWithinRange);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void AXObjectCache::textMarkerDataForCharacterOffset(TextMarkerData&amp; textMarkerData, Node&amp; node, int offset, bool toNodeEnd)
</del><ins>+void AXObjectCache::startOrEndTextMarkerDataForRange(TextMarkerData&amp; textMarkerData, RefPtr&lt;Range&gt; range, bool isStart)
</ins><span class="cx"> {
</span><span class="cx">     memset(&amp;textMarkerData, 0, sizeof(TextMarkerData));
</span><span class="cx">     
</span><ins>+    CharacterOffset characterOffset = startOrEndCharacterOffsetForRange(range, isStart);
+    if (characterOffset.isNull())
+        return;
+    
+    setTextMarkerDataWithCharacterOffset(textMarkerData, characterOffset);
+}
+
+CharacterOffset AXObjectCache::characterOffsetForNodeAndOffset(Node&amp; node, int offset, bool toNodeEnd, bool ignoreStart)
+{
</ins><span class="cx">     Node* domNode = &amp;node;
</span><span class="cx">     if (!domNode)
</span><del>-        return;
</del><ins>+        return CharacterOffset();
</ins><span class="cx">     
</span><del>-    // If offset &lt;= 0, means we want to go to the previous node.
-    if (offset &lt;= 0 &amp;&amp; !toNodeEnd) {
</del><ins>+    // ignoreStart is used to determine if we should go to previous node or
+    // stay in current node when offset is 0.
+    if (!toNodeEnd &amp;&amp; (offset &lt; 0 || (!offset &amp;&amp; ignoreStart))) {
</ins><span class="cx">         // Set the offset to the amount of characters we need to go backwards.
</span><del>-        offset = - offset + 1;
-        while (offset &gt; 0 &amp;&amp; textMarkerData.characterOffset &lt;= offset) {
-            offset -= textMarkerData.characterOffset;
</del><ins>+        offset = - offset;
+        CharacterOffset charOffset = CharacterOffset();
+        while (offset &gt;= 0 &amp;&amp; charOffset.offset &lt;= offset) {
+            offset -= charOffset.offset;
</ins><span class="cx">             domNode = previousNode(domNode);
</span><span class="cx">             if (domNode) {
</span><del>-                textMarkerDataForCharacterOffset(textMarkerData, *domNode, 0, true);
-                offset--;
</del><ins>+                charOffset = characterOffsetForNodeAndOffset(*domNode, 0, true);
</ins><span class="cx">             } else
</span><del>-                return;
</del><ins>+                return CharacterOffset();
+            if (!offset)
+                break;
</ins><span class="cx">         }
</span><span class="cx">         if (offset &gt; 0)
</span><del>-            textMarkerDataForCharacterOffset(textMarkerData, *domNode, offset, false);
-        return;
</del><ins>+            charOffset = characterOffsetForNodeAndOffset(*charOffset.node, charOffset.offset - offset, false);
+        return charOffset;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     RefPtr&lt;Range&gt; range = rangeForNodeContents(domNode);
</span><span class="lines">@@ -1709,11 +1742,19 @@
</span><span class="cx">     while (!characterOffset.isNull() &amp;&amp; characterOffset.remaining() &amp;&amp; !toNodeEnd) {
</span><span class="cx">         domNode = nextNode(domNode);
</span><span class="cx">         if (!domNode)
</span><del>-            return;
</del><ins>+            return CharacterOffset();
</ins><span class="cx">         range = rangeForNodeContents(domNode);
</span><span class="cx">         characterOffset = traverseToOffsetInRange(range, characterOffset.remaining(), toNodeEnd);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    return characterOffset;
+}
+
+void AXObjectCache::textMarkerDataForCharacterOffset(TextMarkerData&amp; textMarkerData, Node&amp; node, int offset, bool toNodeEnd, bool ignoreStart)
+{
+    memset(&amp;textMarkerData, 0, sizeof(TextMarkerData));
+    
+    CharacterOffset characterOffset = characterOffsetForNodeAndOffset(node, offset, toNodeEnd, ignoreStart);
</ins><span class="cx">     setTextMarkerDataWithCharacterOffset(textMarkerData, characterOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1737,8 +1778,12 @@
</span><span class="cx">     return NodeTraversal::previousSkippingChildren(*node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-VisiblePosition AXObjectCache::visiblePositionFromCharacterOffset(AccessibilityObject* obj, const CharacterOffset&amp; characterOffset)
</del><ins>+VisiblePosition AXObjectCache::visiblePositionFromCharacterOffset(const CharacterOffset&amp; characterOffset)
</ins><span class="cx"> {
</span><ins>+    if (characterOffset.isNull())
+        return VisiblePosition();
+    
+    RefPtr&lt;AccessibilityObject&gt; obj = this-&gt;getOrCreate(characterOffset.node);
</ins><span class="cx">     if (!obj)
</span><span class="cx">         return VisiblePosition();
</span><span class="cx">     
</span><span class="lines">@@ -1752,13 +1797,20 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CharacterOffset AXObjectCache::characterOffsetFromVisiblePosition(AccessibilityObject* obj, const VisiblePosition&amp; visiblePos)
</del><ins>+CharacterOffset AXObjectCache::characterOffsetFromVisiblePosition(const VisiblePosition&amp; visiblePos)
</ins><span class="cx"> {
</span><ins>+    if (visiblePos.isNull())
+        return CharacterOffset();
+    
+    Position deepPos = visiblePos.deepEquivalent();
+    Node* domNode = deepPos.deprecatedNode();
+    ASSERT(domNode);
+    
+    RefPtr&lt;AccessibilityObject&gt; obj = this-&gt;getOrCreate(domNode);
</ins><span class="cx">     if (!obj)
</span><del>-        return 0;
</del><ins>+        return CharacterOffset();
</ins><span class="cx">     
</span><span class="cx">     // Use nextVisiblePosition to calculate how many characters we need to traverse to the current position.
</span><del>-    Position deepPos = visiblePos.deepEquivalent();
</del><span class="cx">     VisiblePositionRange vpRange = obj-&gt;visiblePositionRange();
</span><span class="cx">     VisiblePosition vp = vpRange.start;
</span><span class="cx">     int characterOffset = 0;
</span><span class="lines">@@ -1816,13 +1868,256 @@
</span><span class="cx">     textMarkerData.affinity = visiblePos.affinity();
</span><span class="cx">     
</span><span class="cx">     // convert to character offset
</span><del>-    CharacterOffset characterOffset = characterOffsetFromVisiblePosition(obj.get(), visiblePos);
</del><ins>+    CharacterOffset characterOffset = characterOffsetFromVisiblePosition(visiblePos);
</ins><span class="cx">     textMarkerData.characterOffset = characterOffset.offset;
</span><span class="cx">     textMarkerData.characterStartIndex = characterOffset.startIndex;
</span><span class="cx">     
</span><span class="cx">     cache-&gt;setNodeInUse(domNode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CharacterOffset AXObjectCache::nextCharacterOffset(const CharacterOffset&amp; characterOffset)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset + 1);
+}
+
+CharacterOffset AXObjectCache::previousCharacterOffset(const CharacterOffset&amp; characterOffset)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset - 1, false, false);
+}
+
+static unsigned startWordBoundary(StringView text, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool&amp; needMoreContext)
+{
+    ASSERT(offset);
+    if (mayHaveMoreContext &amp;&amp; !startOfLastWordBoundaryContext(text.substring(0, offset))) {
+        needMoreContext = true;
+        return 0;
+    }
+    needMoreContext = false;
+    int start, end;
+    U16_BACK_1(text, 0, offset);
+    findWordBoundary(text, offset, &amp;start, &amp;end);
+    return start;
+}
+
+static unsigned endWordBoundary(StringView text, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool&amp; needMoreContext)
+{
+    ASSERT(offset &lt;= text.length());
+    if (mayHaveMoreContext &amp;&amp; endOfFirstWordBoundaryContext(text.substring(offset)) == text.length() - offset) {
+        needMoreContext = true;
+        return text.length();
+    }
+    needMoreContext = false;
+    int end;
+    findEndWordBoundary(text, offset, &amp;end);
+    return end;
+}
+
+CharacterOffset AXObjectCache::startCharacterOffsetOfWord(const CharacterOffset&amp; characterOffset, EWordSide side)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    CharacterOffset c = characterOffset;
+    if (side == RightWordIfOnBoundary) {
+        // FIXME: need to remove this when isEndOfParagraph is implemented for CharacterOffset.
+        VisiblePosition vp = visiblePositionFromCharacterOffset(c);
+        if (isEndOfParagraph(vp))
+            return c;
+        
+        c = nextCharacterOffset(characterOffset);
+        if (c.isNull())
+            return characterOffset;
+    }
+    
+    return previousWordBoundary(c, startWordBoundary);
+}
+
+CharacterOffset AXObjectCache::endCharacterOffsetOfWord(const CharacterOffset&amp; characterOffset, EWordSide side)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    CharacterOffset c = characterOffset;
+    if (side == LeftWordIfOnBoundary) {
+        // FIXME: need to remove this when isStartOfParagraph is implemented for CharacterOffset.
+        VisiblePosition vp = visiblePositionFromCharacterOffset(c);
+        if (isStartOfParagraph(vp))
+            return c;
+        
+        c = previousCharacterOffset(characterOffset);
+        if (c.isNull())
+            return characterOffset;
+    }
+    
+    return nextWordBoundary(c, endWordBoundary);
+}
+
+CharacterOffset AXObjectCache::previousWordStartCharacterOffset(const CharacterOffset&amp; characterOffset)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    CharacterOffset previousOffset = previousCharacterOffset(characterOffset);
+    if (previousOffset.isNull())
+        return CharacterOffset();
+    
+    return startCharacterOffsetOfWord(previousOffset, RightWordIfOnBoundary);
+}
+
+CharacterOffset AXObjectCache::nextWordEndCharacterOffset(const CharacterOffset&amp; characterOffset)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    CharacterOffset nextOffset = nextCharacterOffset(characterOffset);
+    if (nextOffset.isNull())
+        return CharacterOffset();
+    
+    return endCharacterOffsetOfWord(nextOffset, LeftWordIfOnBoundary);
+}
+
+RefPtr&lt;Range&gt; AXObjectCache::leftWordRange(const CharacterOffset&amp; characterOffset)
+{
+    CharacterOffset start = previousWordStartCharacterOffset(characterOffset);
+    CharacterOffset end = endCharacterOffsetOfWord(start);
+    return rangeForUnorderedCharacterOffsets(start, end);
+}
+
+RefPtr&lt;Range&gt; AXObjectCache::rightWordRange(const CharacterOffset&amp; characterOffset)
+{
+    CharacterOffset start = startCharacterOffsetOfWord(characterOffset);
+    CharacterOffset end = nextWordEndCharacterOffset(start);
+    return rangeForUnorderedCharacterOffsets(start, end);
+}
+
+static UChar32 characterForCharacterOffset(const CharacterOffset&amp; characterOffset)
+{
+    if (characterOffset.isNull() || !characterOffset.node-&gt;isTextNode())
+        return 0;
+    
+    UChar32 ch = 0;
+    unsigned offset = characterOffset.startIndex + characterOffset.offset;
+    if (offset &lt; characterOffset.node-&gt;textContent().length())
+        U16_NEXT(characterOffset.node-&gt;textContent(), offset, characterOffset.node-&gt;textContent().length(), ch);
+    return ch;
+}
+
+UChar32 AXObjectCache::characterAfter(const CharacterOffset&amp; characterOffset)
+{
+    return characterForCharacterOffset(nextCharacterOffset(characterOffset));
+}
+
+UChar32 AXObjectCache::characterBefore(const CharacterOffset&amp; characterOffset)
+{
+    return characterForCharacterOffset(characterOffset);
+}
+    
+static Node* parentEditingBoundary(Node* node)
+{
+    if (!node)
+        return nullptr;
+    
+    Node* documentElement = node-&gt;document().documentElement();
+    if (!documentElement)
+        return nullptr;
+    
+    Node* boundary = node;
+    while (boundary != documentElement &amp;&amp; boundary-&gt;nonShadowBoundaryParentNode() &amp;&amp; node-&gt;hasEditableStyle() == boundary-&gt;parentNode()-&gt;hasEditableStyle())
+        boundary = boundary-&gt;nonShadowBoundaryParentNode();
+    
+    return boundary;
+}
+
+CharacterOffset AXObjectCache::nextWordBoundary(CharacterOffset&amp; characterOffset, BoundarySearchFunction searchFunction)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    Node* boundary = parentEditingBoundary(characterOffset.node);
+    if (!boundary)
+        return CharacterOffset();
+    
+    RefPtr&lt;Range&gt; searchRange = rangeForNodeContents(boundary);
+    Vector&lt;UChar, 1024&gt; string;
+    unsigned prefixLength = 0;
+    
+    ExceptionCode ec = 0;
+    if (requiresContextForWordBoundary(characterAfter(characterOffset))) {
+        RefPtr&lt;Range&gt; backwardsScanRange(boundary-&gt;document().createRange());
+        setRangeStartOrEndWithCharacterOffset(backwardsScanRange, characterOffset, false, ec);
+        prefixLength = prefixLengthForRange(backwardsScanRange, string);
+    }
+    
+    setRangeStartOrEndWithCharacterOffset(searchRange, characterOffset, true, ec);
+    CharacterOffset end = startOrEndCharacterOffsetForRange(searchRange, false);
+    
+    ASSERT(!ec);
+    if (ec)
+        return CharacterOffset();
+    
+    TextIterator it(searchRange.get(), TextIteratorEmitsObjectReplacementCharacters);
+    unsigned next = forwardSearchForBoundaryWithTextIterator(it, string, prefixLength, searchFunction);
+    
+    if (it.atEnd() &amp;&amp; next == string.size())
+        return end;
+    if (next &gt; prefixLength)
+        return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset + next - prefixLength);
+    
+    return characterOffset;
+}
+
+CharacterOffset AXObjectCache::previousWordBoundary(CharacterOffset&amp; characterOffset, BoundarySearchFunction searchFunction)
+{
+    if (characterOffset.isNull())
+        return CharacterOffset();
+    
+    Node* boundary = parentEditingBoundary(characterOffset.node);
+    if (!boundary)
+        return CharacterOffset();
+    
+    RefPtr&lt;Range&gt; searchRange = rangeForNodeContents(boundary);
+    Vector&lt;UChar, 1024&gt; string;
+    unsigned suffixLength = 0;
+    
+    ExceptionCode ec = 0;
+    if (requiresContextForWordBoundary(characterBefore(characterOffset))) {
+        RefPtr&lt;Range&gt; forwardsScanRange(boundary-&gt;document().createRange());
+        forwardsScanRange-&gt;setEndAfter(boundary, ec);
+        setRangeStartOrEndWithCharacterOffset(forwardsScanRange, characterOffset, true, ec);
+        suffixLength = suffixLengthForRange(forwardsScanRange, string);
+    }
+    
+    setRangeStartOrEndWithCharacterOffset(searchRange, characterOffset, false, ec);
+    CharacterOffset start = startOrEndCharacterOffsetForRange(searchRange, true);
+    
+    ASSERT(!ec);
+    if (ec)
+        return CharacterOffset();
+    
+    SimplifiedBackwardsTextIterator it(*searchRange);
+    unsigned next = backwardSearchForBoundaryWithTextIterator(it, string, suffixLength, searchFunction);
+    
+    if (!next)
+        return it.atEnd() ? start : characterOffset;
+    
+    Node&amp; node = it.atEnd() ? searchRange-&gt;startContainer() : it.range()-&gt;startContainer();
+    if ((node.isTextNode() &amp;&amp; static_cast&lt;int&gt;(next) &lt;= node.maxCharacterOffset()) || (node.renderer() &amp;&amp; node.renderer()-&gt;isBR() &amp;&amp; !next)) {
+        // The next variable contains a usable index into a text node
+        if (&amp;node == characterOffset.node)
+            next -= characterOffset.startIndex;
+        return characterOffsetForNodeAndOffset(node, next, false);
+    }
+    
+    int characterCount = characterOffset.offset - (string.size() - suffixLength - next);
+    return characterOffsetForNodeAndOffset(*characterOffset.node, characterCount, false, false);
+}
+
</ins><span class="cx"> const Element* AXObjectCache::rootAXEditableElement(const Node* node)
</span><span class="cx"> {
</span><span class="cx">     const Element* result = node-&gt;rootEditableElement();
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.h        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;AccessibilityObject.h&quot;
</span><span class="cx"> #include &quot;Range.h&quot;
</span><span class="cx"> #include &quot;Timer.h&quot;
</span><ins>+#include &quot;VisibleUnits.h&quot;
</ins><span class="cx"> #include &lt;limits.h&gt;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="lines">@@ -186,12 +187,20 @@
</span><span class="cx">     void textMarkerDataForVisiblePosition(TextMarkerData&amp;, const VisiblePosition&amp;);
</span><span class="cx">     VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&amp;);
</span><span class="cx">     CharacterOffset characterOffsetForTextMarkerData(TextMarkerData&amp;);
</span><del>-    void textMarkerDataForCharacterOffset(TextMarkerData&amp;, Node&amp;, int, bool toNodeEnd = false);
</del><ins>+    void textMarkerDataForCharacterOffset(TextMarkerData&amp;, Node&amp;, int, bool toNodeEnd = false, bool ignoreStart = true);
</ins><span class="cx">     void startOrEndTextMarkerDataForRange(TextMarkerData&amp;, RefPtr&lt;Range&gt;, bool);
</span><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="cx">     static int lengthForRange(Range*);
</span><ins>+    
+    // Word boundary
+    CharacterOffset startCharacterOffsetOfWord(const CharacterOffset&amp;, EWordSide = RightWordIfOnBoundary);
+    CharacterOffset endCharacterOffsetOfWord(const CharacterOffset&amp;, EWordSide = RightWordIfOnBoundary);
+    CharacterOffset nextWordEndCharacterOffset(const CharacterOffset&amp;);
+    CharacterOffset previousWordStartCharacterOffset(const CharacterOffset&amp;);
+    RefPtr&lt;Range&gt; leftWordRange(const CharacterOffset&amp;);
+    RefPtr&lt;Range&gt; rightWordRange(const CharacterOffset&amp;);
</ins><span class="cx"> 
</span><span class="cx">     enum AXNotification {
</span><span class="cx">         AXActiveDescendantChanged,
</span><span class="lines">@@ -283,12 +292,21 @@
</span><span class="cx">     void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
</span><span class="cx">     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
</span><span class="cx">     
</span><ins>+    // CharacterOffset functions.
</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, bool, bool stayWithinRange = false);
</span><del>-    VisiblePosition visiblePositionFromCharacterOffset(AccessibilityObject*, const CharacterOffset&amp;);
-    CharacterOffset characterOffsetFromVisiblePosition(AccessibilityObject*, const VisiblePosition&amp;);
</del><ins>+    VisiblePosition visiblePositionFromCharacterOffset(const CharacterOffset&amp;);
+    CharacterOffset characterOffsetFromVisiblePosition(const VisiblePosition&amp;);
</ins><span class="cx">     void setTextMarkerDataWithCharacterOffset(TextMarkerData&amp;, const CharacterOffset&amp;);
</span><ins>+    UChar32 characterAfter(const CharacterOffset&amp;);
+    UChar32 characterBefore(const CharacterOffset&amp;);
+    CharacterOffset startOrEndCharacterOffsetForRange(RefPtr&lt;Range&gt;, bool);
+    CharacterOffset characterOffsetForNodeAndOffset(Node&amp;, int, bool toNodeEnd = false, bool ignoreStart = true);
+    CharacterOffset nextCharacterOffset(const CharacterOffset&amp;);
+    CharacterOffset previousCharacterOffset(const CharacterOffset&amp;);
+    CharacterOffset previousWordBoundary(CharacterOffset&amp;, BoundarySearchFunction);
+    CharacterOffset nextWordBoundary(CharacterOffset&amp;, BoundarySearchFunction);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     AccessibilityObject* rootWebArea();
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -858,12 +858,17 @@
</span><span class="cx">     return textMarker;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (id)textMarkerForNode:(Node&amp;)node offset:(int)offset ignoreStart:(BOOL)ignoreStart
+{
+    return textMarkerForCharacterOffset(m_object-&gt;axObjectCache(), node, offset, false, ignoreStart);
+}
+
</ins><span class="cx"> - (id)textMarkerForNode:(Node&amp;)node offset:(int)offset
</span><span class="cx"> {
</span><del>-    return textMarkerForCharacterOffset(m_object-&gt;axObjectCache(), node, offset);
</del><ins>+    return [self textMarkerForNode:node offset:offset ignoreStart:YES];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static id textMarkerForCharacterOffset(AXObjectCache* cache, Node&amp; node, int offset, bool toNodeEnd = false)
</del><ins>+static id textMarkerForCharacterOffset(AXObjectCache* cache, Node&amp; node, int offset, bool toNodeEnd, bool ignoreStart)
</ins><span class="cx"> {
</span><span class="cx">     if (!cache)
</span><span class="cx">         return nil;
</span><span class="lines">@@ -873,7 +878,7 @@
</span><span class="cx">         return nil;
</span><span class="cx">     
</span><span class="cx">     TextMarkerData textMarkerData;
</span><del>-    cache-&gt;textMarkerDataForCharacterOffset(textMarkerData, node, offset, toNodeEnd);
</del><ins>+    cache-&gt;textMarkerDataForCharacterOffset(textMarkerData, node, offset, toNodeEnd, ignoreStart);
</ins><span class="cx">     if (!textMarkerData.axID &amp;&amp; !textMarkerData.ignored)
</span><span class="cx">         return nil;
</span><span class="cx">     
</span><span class="lines">@@ -4070,15 +4075,21 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if ([attribute isEqualToString:@&quot;AXLeftWordTextMarkerRangeForTextMarker&quot;]) {
</span><del>-        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
-        VisiblePositionRange vpRange = m_object-&gt;positionOfLeftWord(visiblePos);
-        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
</del><ins>+        AXObjectCache* cache = m_object-&gt;axObjectCache();
+        if (!cache)
+            return nil;
+        CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
+        RefPtr&lt;Range&gt; range = cache-&gt;leftWordRange(characterOffset);
+        return [self textMarkerRangeFromRange:range];
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if ([attribute isEqualToString:@&quot;AXRightWordTextMarkerRangeForTextMarker&quot;]) {
</span><del>-        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
-        VisiblePositionRange vpRange = m_object-&gt;positionOfRightWord(visiblePos);
-        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
</del><ins>+        AXObjectCache* cache = m_object-&gt;axObjectCache();
+        if (!cache)
+            return nil;
+        CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
+        RefPtr&lt;Range&gt; range = cache-&gt;rightWordRange(characterOffset);
+        return [self textMarkerRangeFromRange:range];
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if ([attribute isEqualToString:@&quot;AXLeftLineTextMarkerRangeForTextMarker&quot;]) {
</span><span class="lines">@@ -4106,13 +4117,21 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if ([attribute isEqualToString:@&quot;AXNextWordEndTextMarkerForTextMarker&quot;]) {
</span><del>-        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
-        return [self textMarkerForVisiblePosition:m_object-&gt;nextWordEnd(visiblePos)];
</del><ins>+        AXObjectCache* cache = m_object-&gt;axObjectCache();
+        if (!cache)
+            return nil;
+        CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
+        CharacterOffset nextEnd = cache-&gt;nextWordEndCharacterOffset(characterOffset);
+        return [self textMarkerForNode:*nextEnd.node offset:nextEnd.offset];
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if ([attribute isEqualToString:@&quot;AXPreviousWordStartTextMarkerForTextMarker&quot;]) {
</span><del>-        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
-        return [self textMarkerForVisiblePosition:m_object-&gt;previousWordStart(visiblePos)];
</del><ins>+        AXObjectCache* cache = m_object-&gt;axObjectCache();
+        if (!cache)
+            return nil;
+        CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
+        CharacterOffset previousStart = cache-&gt;previousWordStartCharacterOffset(characterOffset);
+        return [self textMarkerForNode:*previousStart.node offset:previousStart.offset ignoreStart:NO];
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if ([attribute isEqualToString:@&quot;AXNextLineEndTextMarkerForTextMarker&quot;]) {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.cpp (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.cpp        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Source/WebCore/editing/VisibleUnits.cpp        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -439,10 +439,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
-
-typedef unsigned (*BoundarySearchFunction)(StringView, unsigned offset, BoundarySearchContextAvailability, bool&amp; needMoreContext);
-
</del><span class="cx"> static void prepend(Vector&lt;UChar, 1024&gt;&amp; buffer, StringView string)
</span><span class="cx"> {
</span><span class="cx">     unsigned oldSize = buffer.size();
</span><span class="lines">@@ -470,6 +466,99 @@
</span><span class="cx">         buffer[oldSize + i] = character;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned suffixLengthForRange(RefPtr&lt;Range&gt; forwardsScanRange, Vector&lt;UChar, 1024&gt;&amp; string)
+{
+    unsigned suffixLength = 0;
+    TextIterator forwardsIterator(forwardsScanRange.get());
+    while (!forwardsIterator.atEnd()) {
+        StringView text = forwardsIterator.text();
+        unsigned i = endOfFirstWordBoundaryContext(text);
+        append(string, text.substring(0, i));
+        suffixLength += i;
+        if (i &lt; text.length())
+            break;
+        forwardsIterator.advance();
+    }
+    return suffixLength;
+}
+
+unsigned prefixLengthForRange(RefPtr&lt;Range&gt; backwardsScanRange, Vector&lt;UChar, 1024&gt;&amp; string)
+{
+    unsigned prefixLength = 0;
+    SimplifiedBackwardsTextIterator backwardsIterator(*backwardsScanRange);
+    while (!backwardsIterator.atEnd()) {
+        StringView text = backwardsIterator.text();
+        int i = startOfLastWordBoundaryContext(text);
+        prepend(string, text.substring(i));
+        prefixLength += text.length() - i;
+        if (i &gt; 0)
+            break;
+        backwardsIterator.advance();
+    }
+    return prefixLength;
+}
+
+unsigned backwardSearchForBoundaryWithTextIterator(SimplifiedBackwardsTextIterator&amp; it, Vector&lt;UChar, 1024&gt;&amp; string, unsigned suffixLength, BoundarySearchFunction searchFunction)
+{
+    unsigned next = 0;
+    bool needMoreContext = false;
+    while (!it.atEnd()) {
+        bool inTextSecurityMode = it.node() &amp;&amp; it.node()-&gt;renderer() &amp;&amp; it.node()-&gt;renderer()-&gt;style().textSecurity() != TSNONE;
+        // iterate to get chunks until the searchFunction returns a non-zero value.
+        if (!inTextSecurityMode)
+            prepend(string, it.text());
+        else {
+            // Treat bullets used in the text security mode as regular characters when looking for boundaries
+            prependRepeatedCharacter(string, 'x', it.text().length());
+        }
+        if (string.size() &gt; suffixLength) {
+            next = searchFunction(StringView(string.data(), string.size()), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
+            if (next &gt; 1) // FIXME: This is a work around for https://webkit.org/b/115070. We need to provide more contexts in general case.
+                break;
+        }
+        it.advance();
+    }
+    if (needMoreContext &amp;&amp; string.size() &gt; suffixLength) {
+        // The last search returned the beginning of the buffer and asked for more context,
+        // but there is no earlier text. Force a search with what's available.
+        next = searchFunction(StringView(string.data(), string.size()), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
+        ASSERT(!needMoreContext);
+    }
+    
+    return next;
+}
+
+unsigned forwardSearchForBoundaryWithTextIterator(TextIterator&amp; it, Vector&lt;UChar, 1024&gt;&amp; string, unsigned prefixLength, BoundarySearchFunction searchFunction)
+{
+    unsigned next = 0;
+    bool needMoreContext = false;
+    while (!it.atEnd()) {
+        bool inTextSecurityMode = it.node() &amp;&amp; it.node()-&gt;renderer() &amp;&amp; it.node()-&gt;renderer()-&gt;style().textSecurity() != TSNONE;
+        // Keep asking the iterator for chunks until the search function
+        // returns an end value not equal to the length of the string passed to it.
+        if (!inTextSecurityMode)
+            append(string, it.text());
+        else {
+            // Treat bullets used in the text security mode as regular characters when looking for boundaries
+            appendRepeatedCharacter(string, 'x', it.text().length());
+        }
+        if (string.size() &gt; prefixLength) {
+            next = searchFunction(StringView(string.data(), string.size()), prefixLength, MayHaveMoreContext, needMoreContext);
+            if (next != string.size())
+                break;
+        }
+        it.advance();
+    }
+    if (needMoreContext &amp;&amp; string.size() &gt; prefixLength) {
+        // The last search returned the end of the buffer and asked for more context,
+        // but there is no further text. Force a search with what's available.
+        next = searchFunction(StringView(string.data(), string.size()), prefixLength, DontHaveMoreContext, needMoreContext);
+        ASSERT(!needMoreContext);
+    }
+    
+    return next;
+}
+
</ins><span class="cx"> static VisiblePosition previousBoundary(const VisiblePosition&amp; c, BoundarySearchFunction searchFunction)
</span><span class="cx"> {
</span><span class="cx">     Position pos = c.deepEquivalent();
</span><span class="lines">@@ -490,16 +579,7 @@
</span><span class="cx">         RefPtr&lt;Range&gt; forwardsScanRange(boundaryDocument.createRange());
</span><span class="cx">         forwardsScanRange-&gt;setEndAfter(boundary, ec);
</span><span class="cx">         forwardsScanRange-&gt;setStart(end.deprecatedNode(), end.deprecatedEditingOffset(), ec);
</span><del>-        TextIterator forwardsIterator(forwardsScanRange.get());
-        while (!forwardsIterator.atEnd()) {
-            StringView text = forwardsIterator.text();
-            unsigned i = endOfFirstWordBoundaryContext(text);
-            append(string, text.substring(0, i));
-            suffixLength += i;
-            if (i &lt; text.length())
-                break;
-            forwardsIterator.advance();
-        }
</del><ins>+        suffixLength = suffixLengthForRange(forwardsScanRange, string);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     searchRange-&gt;setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), ec);
</span><span class="lines">@@ -510,30 +590,7 @@
</span><span class="cx">         return VisiblePosition();
</span><span class="cx"> 
</span><span class="cx">     SimplifiedBackwardsTextIterator it(*searchRange);
</span><del>-    unsigned next = 0;
-    bool needMoreContext = false;
-    while (!it.atEnd()) {
-        bool inTextSecurityMode = it.node() &amp;&amp; it.node()-&gt;renderer() &amp;&amp; it.node()-&gt;renderer()-&gt;style().textSecurity() != TSNONE;
-        // iterate to get chunks until the searchFunction returns a non-zero value.
-        if (!inTextSecurityMode) 
-            prepend(string, it.text());
-        else {
-            // Treat bullets used in the text security mode as regular characters when looking for boundaries
-            prependRepeatedCharacter(string, 'x', it.text().length());
-        }
-        if (string.size() &gt; suffixLength) {
-            next = searchFunction(StringView(string.data(), string.size()), string.size() - suffixLength, MayHaveMoreContext, needMoreContext);
-            if (next &gt; 1) // FIXME: This is a work around for https://webkit.org/b/115070. We need to provide more contexts in general case.
-                break;
-        }
-        it.advance();
-    }
-    if (needMoreContext &amp;&amp; string.size() &gt; suffixLength) {
-        // The last search returned the beginning of the buffer and asked for more context,
-        // but there is no earlier text. Force a search with what's available.
-        next = searchFunction(StringView(string.data(), string.size()), string.size() - suffixLength, DontHaveMoreContext, needMoreContext);
-        ASSERT(!needMoreContext);
-    }
</del><ins>+    unsigned next = backwardSearchForBoundaryWithTextIterator(it, string, suffixLength, searchFunction);
</ins><span class="cx"> 
</span><span class="cx">     if (!next)
</span><span class="cx">         return VisiblePosition(it.atEnd() ? searchRange-&gt;startPosition() : pos, DOWNSTREAM);
</span><span class="lines">@@ -568,46 +625,13 @@
</span><span class="cx">     if (requiresContextForWordBoundary(c.characterAfter())) {
</span><span class="cx">         RefPtr&lt;Range&gt; backwardsScanRange(boundaryDocument.createRange());
</span><span class="cx">         backwardsScanRange-&gt;setEnd(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
</span><del>-        SimplifiedBackwardsTextIterator backwardsIterator(*backwardsScanRange);
-        while (!backwardsIterator.atEnd()) {
-            StringView text = backwardsIterator.text();
-            int i = startOfLastWordBoundaryContext(text);
-            prepend(string, text.substring(i));
-            prefixLength += text.length() - i;
-            if (i &gt; 0)
-                break;
-            backwardsIterator.advance();
-        }
</del><ins>+        prefixLength = prefixLengthForRange(backwardsScanRange, string);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     searchRange-&gt;selectNodeContents(boundary, IGNORE_EXCEPTION);
</span><span class="cx">     searchRange-&gt;setStart(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
</span><span class="cx">     TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
</span><del>-    unsigned next = 0;
-    bool needMoreContext = false;
-    while (!it.atEnd()) {
-        bool inTextSecurityMode = it.node() &amp;&amp; it.node()-&gt;renderer() &amp;&amp; it.node()-&gt;renderer()-&gt;style().textSecurity() != TSNONE;
-        // Keep asking the iterator for chunks until the search function
-        // returns an end value not equal to the length of the string passed to it.
-        if (!inTextSecurityMode)
-            append(string, it.text());
-        else {
-            // Treat bullets used in the text security mode as regular characters when looking for boundaries
-            appendRepeatedCharacter(string, 'x', it.text().length());
-        }
-        if (string.size() &gt; prefixLength) {
-            next = searchFunction(StringView(string.data(), string.size()), prefixLength, MayHaveMoreContext, needMoreContext);
-            if (next != string.size())
-                break;
-        }
-        it.advance();
-    }
-    if (needMoreContext &amp;&amp; string.size() &gt; prefixLength) {
-        // The last search returned the end of the buffer and asked for more context,
-        // but there is no further text. Force a search with what's available.
-        next = searchFunction(StringView(string.data(), string.size()), prefixLength, DontHaveMoreContext, needMoreContext);
-        ASSERT(!needMoreContext);
-    }
</del><ins>+    unsigned next = forwardSearchForBoundaryWithTextIterator(it, string, prefixLength, searchFunction);
</ins><span class="cx">     
</span><span class="cx">     if (it.atEnd() &amp;&amp; next == string.size())
</span><span class="cx">         pos = searchRange-&gt;endPosition();
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.h (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.h        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Source/WebCore/editing/VisibleUnits.h        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx"> 
</span><span class="cx"> class Node;
</span><span class="cx"> class VisiblePosition;
</span><ins>+class SimplifiedBackwardsTextIterator;
+class TextIterator;
</ins><span class="cx"> 
</span><span class="cx"> enum EWordSide { RightWordIfOnBoundary = false, LeftWordIfOnBoundary = true };
</span><span class="cx"> 
</span><span class="lines">@@ -107,6 +109,14 @@
</span><span class="cx"> WEBCORE_EXPORT void charactersAroundPosition(const VisiblePosition&amp;, UChar32&amp; oneAfter, UChar32&amp; oneBefore, UChar32&amp; twoBefore);
</span><span class="cx"> WEBCORE_EXPORT PassRefPtr&lt;Range&gt; rangeExpandedAroundPositionByCharacters(const VisiblePosition&amp;, int numberOfCharactersToExpand);
</span><span class="cx"> 
</span><ins>+// helper function
+enum BoundarySearchContextAvailability { DontHaveMoreContext, MayHaveMoreContext };
+typedef unsigned (*BoundarySearchFunction)(StringView, unsigned offset, BoundarySearchContextAvailability, bool&amp; needMoreContext);
+unsigned suffixLengthForRange(RefPtr&lt;Range&gt;, Vector&lt;UChar, 1024&gt;&amp;);
+unsigned prefixLengthForRange(RefPtr&lt;Range&gt;, Vector&lt;UChar, 1024&gt;&amp;);
+unsigned backwardSearchForBoundaryWithTextIterator(SimplifiedBackwardsTextIterator&amp;, Vector&lt;UChar, 1024&gt;&amp;, unsigned, BoundarySearchFunction);
+unsigned forwardSearchForBoundaryWithTextIterator(TextIterator&amp;, Vector&lt;UChar, 1024&gt;&amp;, unsigned, BoundarySearchFunction);
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // VisibleUnits_h
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/ChangeLog        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2016-02-09  Nan Wang  &lt;n_wang@apple.com&gt;
+
+        AX: Implement word related text marker functions using TextIterator
+        https://bugs.webkit.org/show_bug.cgi?id=153939
+        &lt;rdar://problem/24269605&gt;
+
+        Reviewed by Chris Fleizach.
+
+        * DumpRenderTree/AccessibilityUIElement.cpp:
+        (endTextMarkerCallback):
+        (leftWordTextMarkerRangeForTextMarkerCallback):
+        (rightWordTextMarkerRangeForTextMarkerCallback):
+        (previousWordStartTextMarkerForTextMarkerCallback):
+        (nextWordEndTextMarkerForTextMarkerCallback):
+        (setSelectedVisibleTextRangeCallback):
+        (AccessibilityUIElement::setSelectedVisibleTextRange):
+        (AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
+        (AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+        (AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+        (AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+        (AccessibilityUIElement::getJSClass):
+        * DumpRenderTree/AccessibilityUIElement.h:
+        * DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
+        (AccessibilityUIElement::setSelectedVisibleTextRange):
+        (AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
+        (AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+        (AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+        (AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+        * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
+        (AccessibilityUIElement::setSelectedVisibleTextRange):
+        (AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
+        (AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+        (AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+        (AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+        (AccessibilityUIElement::supportedActions):
+        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
+        (WTR::AccessibilityUIElement::setBoolAttributeValue):
+        (WTR::AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
+        (WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+        (WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+        (WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+        * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+        * WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
+        (WTR::AccessibilityUIElement::endTextMarker):
+        (WTR::AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
+        (WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+        (WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+        (WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+        (WTR::AccessibilityUIElement::mathPostscriptsDescription):
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+        (WTR::AccessibilityUIElement::endTextMarker):
+        (WTR::AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker):
+        (WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+        (WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+        (WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+        (WTR::_convertMathMultiscriptPairsToString):
+
</ins><span class="cx"> 2016-02-09  Csaba Osztrogonác  &lt;ossy@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Remove eail related cruft after r195725
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeAccessibilityUIElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -974,6 +974,42 @@
</span><span class="cx">     return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)-&gt;endTextMarker());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static JSValueRef leftWordTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    AccessibilityTextMarker* marker = nullptr;
+    if (argumentCount == 1)
+        marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+    
+    return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)-&gt;leftWordTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef rightWordTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    AccessibilityTextMarker* marker = nullptr;
+    if (argumentCount == 1)
+        marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+    
+    return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)-&gt;rightWordTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef previousWordStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    AccessibilityTextMarker* marker = nullptr;
+    if (argumentCount == 1)
+        marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+    
+    return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)-&gt;previousWordStartTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef nextWordEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    AccessibilityTextMarker* marker = nullptr;
+    if (argumentCount == 1)
+        marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+    
+    return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)-&gt;nextWordEndTextMarkerForTextMarker(marker));
+}
+
</ins><span class="cx"> static JSValueRef setSelectedVisibleTextRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
</span><span class="cx"> {
</span><span class="cx">     AccessibilityUIElement* uiElement = toAXElement(thisObject);
</span><span class="lines">@@ -1564,6 +1600,26 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AccessibilityTextMarkerRange AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> // Destruction
</span><span class="lines">@@ -1744,6 +1800,10 @@
</span><span class="cx">         { &quot;nextTextMarker&quot;, nextTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx">         { &quot;previousTextMarker&quot;, previousTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx">         { &quot;stringForTextMarkerRange&quot;, stringForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><ins>+        { &quot;leftWordTextMarkerRangeForTextMarker&quot;, leftWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { &quot;rightWordTextMarkerRangeForTextMarker&quot;, rightWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { &quot;previousWordStartTextMarkerForTextMarker&quot;, previousWordStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { &quot;nextWordEndTextMarkerForTextMarker&quot;, nextWordEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</ins><span class="cx">         { &quot;setSelectedChild&quot;, setSelectedChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx">         { &quot;setSelectedChildAtIndex&quot;, setSelectedChildAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx">         { &quot;removeSelectionAtIndex&quot;, removeSelectionAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeAccessibilityUIElementh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.h (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.h        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.h        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -260,6 +260,10 @@
</span><span class="cx">     AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker*);
</span><span class="cx">     AccessibilityTextMarker startTextMarker();
</span><span class="cx">     AccessibilityTextMarker endTextMarker();
</span><ins>+    AccessibilityTextMarkerRange leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+    AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+    AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+    AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*);
</ins><span class="cx">     AccessibilityTextMarkerRange selectedTextMarkerRange();
</span><span class="cx">     void resetSelectedTextMarkerRange();
</span><span class="cx">     bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*);
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeiosAccessibilityUIElementIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -550,6 +550,26 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AccessibilityTextMarkerRange AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+    return nullptr;
+}
+
</ins><span class="cx"> #endif // SUPPORTS_AX_TEXTMARKERS &amp;&amp; PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx"> #pragma mark Unused
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacAccessibilityUIElementMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -1846,6 +1846,46 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AccessibilityTextMarkerRange AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id textMarkerRange = [m_element accessibilityAttributeValue:@&quot;AXLeftWordTextMarkerRangeForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarkerRange(textMarkerRange);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id textMarkerRange = [m_element accessibilityAttributeValue:@&quot;AXRightWordTextMarkerRangeForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarkerRange(textMarkerRange);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id previousTextMarker = [m_element accessibilityAttributeValue:@&quot;AXPreviousWordStartTextMarkerForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarker(previousTextMarker);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id nextTextMarker = [m_element accessibilityAttributeValue:@&quot;AXNextWordEndTextMarkerForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarker(nextTextMarker);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
</ins><span class="cx"> #endif // SUPPORTS_AX_TEXTMARKERS &amp;&amp; PLATFORM(MAC)
</span><span class="cx"> 
</span><span class="cx"> JSStringRef AccessibilityUIElement::supportedActions()
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -244,5 +244,12 @@
</span><span class="cx"> void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if (!PLATFORM(MAC) &amp;&amp; !PLATFORM(IOS)) || !HAVE(ACCESSIBILITY)
+PassRefPtr&lt;AccessibilityTextMarkerRange&gt; AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr&lt;AccessibilityTextMarkerRange&gt; AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr&lt;AccessibilityTextMarker&gt; AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr&lt;AccessibilityTextMarker&gt; AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+#endif
+
</ins><span class="cx"> } // namespace WTR
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -251,6 +251,10 @@
</span><span class="cx">     PassRefPtr&lt;AccessibilityTextMarker&gt; startTextMarker();
</span><span class="cx">     PassRefPtr&lt;AccessibilityTextMarker&gt; endTextMarker();
</span><span class="cx">     bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*);
</span><ins>+    PassRefPtr&lt;AccessibilityTextMarkerRange&gt; leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+    PassRefPtr&lt;AccessibilityTextMarkerRange&gt; rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+    PassRefPtr&lt;AccessibilityTextMarker&gt; previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+    PassRefPtr&lt;AccessibilityTextMarker&gt; nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*);
</ins><span class="cx"> 
</span><span class="cx">     // Returns an ordered list of supported actions for an element.
</span><span class="cx">     JSRetainPtr&lt;JSStringRef&gt; supportedActions() const;
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleBindingsAccessibilityUIElementidl"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -201,6 +201,10 @@
</span><span class="cx">     readonly attribute AccessibilityTextMarker startTextMarker;
</span><span class="cx">     readonly attribute AccessibilityTextMarker endTextMarker;
</span><span class="cx">     boolean setSelectedVisibleTextRange(AccessibilityTextMarkerRange range);
</span><ins>+    AccessibilityTextMarkerRange leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker);
+    AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker);
+    AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker textMarker);
+    AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker textMarker);
</ins><span class="cx"> 
</span><span class="cx">     // Returns an ordered list of supported actions for an element.
</span><span class="cx">     readonly attribute DOMString supportedActions;
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleiosAccessibilityUIElementIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -1096,6 +1096,26 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PassRefPtr&lt;AccessibilityTextMarkerRange&gt; AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    return nullptr;
+}
+
+PassRefPtr&lt;AccessibilityTextMarkerRange&gt; AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    return nullptr;
+}
+
+PassRefPtr&lt;AccessibilityTextMarker&gt; AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    return nullptr;
+}
+
+PassRefPtr&lt;AccessibilityTextMarker&gt; AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    return nullptr;
+}
+
</ins><span class="cx"> JSRetainPtr&lt;JSStringRef&gt; AccessibilityUIElement::mathPostscriptsDescription() const
</span><span class="cx"> {
</span><span class="cx">     return 0;
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundlemacAccessibilityUIElementMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm (196351 => 196352)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm        2016-02-10 02:29:38 UTC (rev 196351)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm        2016-02-10 02:33:04 UTC (rev 196352)
</span><span class="lines">@@ -1873,6 +1873,46 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PassRefPtr&lt;AccessibilityTextMarkerRange&gt; AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id textMarkerRange = [m_element accessibilityAttributeValue:@&quot;AXLeftWordTextMarkerRangeForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarkerRange::create(textMarkerRange);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
+PassRefPtr&lt;AccessibilityTextMarkerRange&gt; AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id textMarkerRange = [m_element accessibilityAttributeValue:@&quot;AXRightWordTextMarkerRangeForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarkerRange::create(textMarkerRange);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
+PassRefPtr&lt;AccessibilityTextMarker&gt; AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id previousWordStartMarker = [m_element accessibilityAttributeValue:@&quot;AXPreviousWordStartTextMarkerForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarker::create(previousWordStartMarker);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
+PassRefPtr&lt;AccessibilityTextMarker&gt; AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+    BEGIN_AX_OBJC_EXCEPTIONS
+    id nextWordEndMarker = [m_element accessibilityAttributeValue:@&quot;AXNextWordEndTextMarkerForTextMarker&quot; forParameter:(id)textMarker-&gt;platformTextMarker()];
+    return AccessibilityTextMarker::create(nextWordEndMarker);
+    END_AX_OBJC_EXCEPTIONS
+    
+    return nullptr;
+}
+
</ins><span class="cx"> static NSString *_convertMathMultiscriptPairsToString(NSArray *pairs)
</span><span class="cx"> {
</span><span class="cx">     __block NSMutableString *result = [NSMutableString string];
</span></span></pre>
</div>
</div>

</body>
</html>