Title: [286116] trunk
Revision
286116
Author
[email protected]
Date
2021-11-22 12:34:19 -0800 (Mon, 22 Nov 2021)

Log Message

AX: WebKit: need a method to get visible text and frame of an element on screen
https://bugs.webkit.org/show_bug.cgi?id=233336

Reviewed by Andres Gonzalez.

Source/WebCore:

Implement visibleCharacterRange for static text elements so that Books can determine the visible
content on a page.

Test: accessibility/visible-character-range.html

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::visibleCharacterRange const):
(WebCore::AccessibilityObject::unobscuredContentRect const):
* accessibility/AccessibilityObject.h:
* accessibility/AccessibilityObjectInterface.h:
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper accessibilityVisibleContentRect]):
(accessibleElementsForObjects):
(-[WebAccessibilityObjectWrapper accessibilityFindMatchingObjects:]):
(-[WebAccessibilityObjectWrapper positionForTextMarker:]):
(-[WebAccessibilityObjectWrapper textMarkerForPosition:]):
(-[WebAccessibilityObjectWrapper stringForRange:]):
(-[WebAccessibilityObjectWrapper frameForRange:]):
(-[WebAccessibilityObjectWrapper accessibilityMathRadicand]):
(-[WebAccessibilityObjectWrapper _convertToNSRange:]): Deleted.
(-[WebAccessibilityObjectWrapper _convertToDOMRange:]): Deleted.
* accessibility/isolatedtree/AXIsolatedObject.cpp:
(WebCore::AXIsolatedObject::visibleCharacterRange const):
(WebCore::AXIsolatedObject::unobscuredContentRect const):
* accessibility/isolatedtree/AXIsolatedObject.h:
* accessibility/mac/WebAccessibilityObjectWrapperBase.h:
* accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
(makeNSArray):
(-[WebAccessibilityObjectWrapperBase accessibilityVisibleCharacterRange]):
(makeNSRange):
(makeDOMRange):
(-[WebAccessibilityObjectWrapperBase baseUpdateBackingStore]):
(-[WebAccessibilityObjectWrapperBase lineRectsAndText]):
(convertToNSArray): Deleted.
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(-[WebAccessibilityObjectWrapper childrenVectorArray]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
(-[WebAccessibilityObjectWrapper _indexForTextMarker:]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
(-[WebAccessibilityObjectWrapper _convertToNSRange:]): Deleted.

LayoutTests:

* accessibility/ios-simulator/visible-character-range-expected.txt: Added.
* accessibility/visible-character-range-expected.txt: Added.
* accessibility/visible-character-range.html: Added.
* platform/ios/TestExpectations:
* platform/mac-wk1/TestExpectations:
* platform/win/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286115 => 286116)


--- trunk/LayoutTests/ChangeLog	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/LayoutTests/ChangeLog	2021-11-22 20:34:19 UTC (rev 286116)
@@ -1,3 +1,17 @@
+2021-11-22  Chris Fleizach  <[email protected]>
+
+        AX: WebKit: need a method to get visible text and frame of an element on screen
+        https://bugs.webkit.org/show_bug.cgi?id=233336
+
+        Reviewed by Andres Gonzalez.
+
+        * accessibility/ios-simulator/visible-character-range-expected.txt: Added.
+        * accessibility/visible-character-range-expected.txt: Added.
+        * accessibility/visible-character-range.html: Added.
+        * platform/ios/TestExpectations:
+        * platform/mac-wk1/TestExpectations:
+        * platform/win/TestExpectations:
+
 2021-11-22  Antti Koivisto  <[email protected]>
 
         [LFC][Integration] Remove dirOverride

Added: trunk/LayoutTests/accessibility/visible-character-range.html (0 => 286116)


--- trunk/LayoutTests/accessibility/visible-character-range.html	                        (rev 0)
+++ trunk/LayoutTests/accessibility/visible-character-range.html	2021-11-22 20:34:19 UTC (rev 286116)
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body id="body">
+
+<div id="group">
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+test test test test test test test test test test test test test test test test test test test test test test test test test test test test
+</div>
+
+<script>
+
+    description("This tests that visibleCharacterRange returns expected visible ranges while modifying obscured content.");
+
+    if (window.accessibilityController) {
+        var text = accessibilityController.accessibleElementById("group").childAtIndex(0);
+        debug("Visible range: " + text.stringDescriptionOfAttributeValue("AXVisibleCharacterRange"));
+
+        testRunner.setViewSize(500, 200);
+        debug("Visible range (500, 200): " + text.stringDescriptionOfAttributeValue("AXVisibleCharacterRange"));
+
+        document.body.scrollTop = 200;
+        testRunner.setViewSize(200, 500);
+        debug("Visible range, offset: 200 (200, 500): " + text.stringDescriptionOfAttributeValue("AXVisibleCharacterRange"));
+
+        document.getElementById("group").style.visibility = "hidden";
+    }
+
+</script>
+
+</body>
+</html>

Modified: trunk/LayoutTests/platform/ios/TestExpectations (286115 => 286116)


--- trunk/LayoutTests/platform/ios/TestExpectations	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2021-11-22 20:34:19 UTC (rev 286116)
@@ -2118,7 +2118,7 @@
 fast/dom/linkify-phone-numbers.html [ Pass ]
 
 accessibility/video-element-url-attribute.html [ Pass ]
-
+accessibility/visible-character-range.html [ Pass ]
 accessibility/ancestor-computation.html [ Pass ]
 
 # Enable "aria-current" tests for iOS.

Added: trunk/LayoutTests/platform/ios/accessibility/visible-character-range-expected.txt (0 => 286116)


--- trunk/LayoutTests/platform/ios/accessibility/visible-character-range-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/accessibility/visible-character-range-expected.txt	2021-11-22 20:34:19 UTC (rev 286116)
@@ -0,0 +1,12 @@
+This tests that visibleCharacterRange returns expected visible ranges while modifying obscured content.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Visible range: {0, 3900}
+Visible range (500, 200): {0, 270}
+Visible range, offset: 200 (200, 500): {0, 735}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/platform/mac/accessibility/visible-character-range-expected.txt (0 => 286116)


--- trunk/LayoutTests/platform/mac/accessibility/visible-character-range-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac/accessibility/visible-character-range-expected.txt	2021-11-22 20:34:19 UTC (rev 286116)
@@ -0,0 +1,12 @@
+This tests that visibleCharacterRange returns expected visible ranges while modifying obscured content.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Visible range: NSRange: {0, 4205}
+Visible range (500, 200): NSRange: {0, 360}
+Visible range, offset: 200 (200, 500): NSRange: {0, 690}
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (286115 => 286116)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2021-11-22 20:34:19 UTC (rev 286116)
@@ -601,6 +601,9 @@
 editing/spelling/spellcheck-async.html [ Failure ]
 editing/spelling/spelling-unified-emulation.html [ Failure ]
 
+# Skip due to lack of DumpRenderTree `AccessibilityUIElement::stringDescriptionOfAttributeValue` implementation.
+accessibility/visible-character-range.html [ Skip ]
+
 # <rdar://problem/26050923> The result is probably still a pass, but we don't have a way
 # to have platform specific results that are different between WK1 and WK2.
 accessibility/mac/document-attributes.html [ Failure ]

Modified: trunk/LayoutTests/platform/win/TestExpectations (286115 => 286116)


--- trunk/LayoutTests/platform/win/TestExpectations	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/LayoutTests/platform/win/TestExpectations	2021-11-22 20:34:19 UTC (rev 286116)
@@ -278,6 +278,7 @@
 accessibility/listbox-clear-selection.html [ Skip ]
 accessibility/embedded-image-description.html [ Skip ]
 accessibility/img-no-alt-not-ignored-with-title.html [ Skip ]
+accessibility/visible-character-range.html [ Skip ]
 
 # Need to implement AccessibilityUIElement::hasDocumentRoleAncestor(), AccessibilityUIElement::hasWebApplicationAncestor(),
 # AccessibilityUIElement::isInDescriptionListDetail(), AccessibilityUIElement::isInDescriptionListTerm(), and

Modified: trunk/Source/WebCore/ChangeLog (286115 => 286116)


--- trunk/Source/WebCore/ChangeLog	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/ChangeLog	2021-11-22 20:34:19 UTC (rev 286116)
@@ -1,3 +1,51 @@
+2021-11-22  Chris Fleizach  <[email protected]>
+
+        AX: WebKit: need a method to get visible text and frame of an element on screen
+        https://bugs.webkit.org/show_bug.cgi?id=233336
+
+        Reviewed by Andres Gonzalez.
+
+        Implement visibleCharacterRange for static text elements so that Books can determine the visible
+        content on a page.
+
+        Test: accessibility/visible-character-range.html
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::visibleCharacterRange const):
+        (WebCore::AccessibilityObject::unobscuredContentRect const):
+        * accessibility/AccessibilityObject.h:
+        * accessibility/AccessibilityObjectInterface.h:
+        * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+        (-[WebAccessibilityObjectWrapper accessibilityVisibleContentRect]):
+        (accessibleElementsForObjects):
+        (-[WebAccessibilityObjectWrapper accessibilityFindMatchingObjects:]):
+        (-[WebAccessibilityObjectWrapper positionForTextMarker:]):
+        (-[WebAccessibilityObjectWrapper textMarkerForPosition:]):
+        (-[WebAccessibilityObjectWrapper stringForRange:]):
+        (-[WebAccessibilityObjectWrapper frameForRange:]):
+        (-[WebAccessibilityObjectWrapper accessibilityMathRadicand]):
+        (-[WebAccessibilityObjectWrapper _convertToNSRange:]): Deleted.
+        (-[WebAccessibilityObjectWrapper _convertToDOMRange:]): Deleted.
+        * accessibility/isolatedtree/AXIsolatedObject.cpp:
+        (WebCore::AXIsolatedObject::visibleCharacterRange const):
+        (WebCore::AXIsolatedObject::unobscuredContentRect const):
+        * accessibility/isolatedtree/AXIsolatedObject.h:
+        * accessibility/mac/WebAccessibilityObjectWrapperBase.h:
+        * accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
+        (makeNSArray):
+        (-[WebAccessibilityObjectWrapperBase accessibilityVisibleCharacterRange]):
+        (makeNSRange):
+        (makeDOMRange):
+        (-[WebAccessibilityObjectWrapperBase baseUpdateBackingStore]):
+        (-[WebAccessibilityObjectWrapperBase lineRectsAndText]):
+        (convertToNSArray): Deleted.
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (-[WebAccessibilityObjectWrapper childrenVectorArray]):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
+        (-[WebAccessibilityObjectWrapper _indexForTextMarker:]):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+        (-[WebAccessibilityObjectWrapper _convertToNSRange:]): Deleted.
+
 2021-11-20  Simon Fraser  <[email protected]>
 
         Clarify the behavior of ScrollAnimator::scroll()

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (286115 => 286116)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2021-11-22 20:34:19 UTC (rev 286116)
@@ -704,6 +704,52 @@
     return AXObjectCache::rangeForNodeContents(*node);
 }
 
+std::optional<SimpleRange> AccessibilityObject::visibleCharacterRange() const
+{
+    auto range = elementRange();
+    if (!range)
+        return std::nullopt;
+
+    auto contentRect = unobscuredContentRect();
+    auto elementRect = snappedIntRect(this->elementRect());
+    if (!contentRect.intersects(elementRect))
+        return std::nullopt;
+
+    std::optional<BoundaryPoint> startBoundary = range->start;
+    std::optional<BoundaryPoint> endBoundary = range->end;
+
+    // Origin isn't contained in visible rect, start moving forward by line.
+    while (!contentRect.contains(elementRect.location())) {
+        auto nextLinePosition = nextLineEndPosition(VisiblePosition(makeContainerOffsetPosition(*startBoundary)));
+        std::optional<BoundaryPoint> testStartBoundary = makeBoundaryPoint(nextLinePosition);
+        if (!testStartBoundary || !contains(*range, *testStartBoundary))
+            break;
+        
+        startBoundary = testStartBoundary;
+        elementRect = boundsForRange(SimpleRange(*startBoundary, range->end));
+        if (elementRect.isEmpty())
+            break;
+    }
+
+    // End isn't contained in visible rect, start moving backwards by line.
+    while (!contentRect.contains(elementRect.location() + elementRect.size())) {
+        auto previousLinePosition = previousLineStartPosition(VisiblePosition(makeContainerOffsetPosition(*endBoundary)));
+        std::optional<BoundaryPoint> testEndBoundary = makeBoundaryPoint(previousLinePosition);
+        if (!testEndBoundary || !contains(*range, *testEndBoundary))
+            break;
+        
+        endBoundary = testEndBoundary;
+        elementRect = boundsForRange({ *startBoundary, *endBoundary });
+        if (elementRect.isEmpty())
+            break;
+    }
+
+    if (!startBoundary || !endBoundary)
+        return std::nullopt;
+    
+    return {{ *startBoundary, *endBoundary }};
+}
+
 std::optional<SimpleRange> AccessibilityObject::findTextRange(const Vector<String>& searchStrings, const SimpleRange& start, AccessibilitySearchTextDirection direction) const
 {
     std::optional<SimpleRange> found;
@@ -3182,6 +3228,14 @@
         scrollParent->scrollToMakeVisibleWithSubFocus(newSubfocus);
 }
 
+FloatRect AccessibilityObject::unobscuredContentRect() const
+{
+    auto document = this->document();
+    if (!document || !document->view())
+        return { };
+    return FloatRect(snappedIntRect(document->view()->unobscuredContentRect()));
+}
+
 void AccessibilityObject::scrollToGlobalPoint(const IntPoint& globalPoint) const
 {
     // Search up the parent chain and create a vector of all scrollable parent objects

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (286115 => 286116)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.h	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h	2021-11-22 20:34:19 UTC (rev 286116)
@@ -808,7 +808,7 @@
     void ariaElementsFromAttribute(AccessibilityChildrenVector&, const QualifiedName&) const;
     void ariaElementsReferencedByAttribute(AccessibilityChildrenVector&, const QualifiedName&) const;
     virtual bool exposesTitleUIElement() const { return true; }
-
+    FloatRect unobscuredContentRect() const override;
     AccessibilityObject* radioGroupAncestor() const;
 
     bool allowsTextRanges() const;
@@ -821,6 +821,7 @@
     std::optional<SimpleRange> rangeOfStringClosestToRangeInDirection(const SimpleRange&, AccessibilitySearchDirection, const Vector<String>&) const;
     std::optional<SimpleRange> selectionRange() const;
     std::optional<SimpleRange> findTextRange(const Vector<String>& searchStrings, const SimpleRange& start, AccessibilitySearchTextDirection) const;
+    std::optional<SimpleRange> visibleCharacterRange() const override;
 
 protected: // FIXME: Make the data members private.
     bool childrenInitialized() const { return m_childrenInitialized; }

Modified: trunk/Source/WebCore/accessibility/AccessibilityObjectInterface.h (286115 => 286116)


--- trunk/Source/WebCore/accessibility/AccessibilityObjectInterface.h	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/AccessibilityObjectInterface.h	2021-11-22 20:34:19 UTC (rev 286116)
@@ -988,6 +988,7 @@
     virtual void setIsExpanded(bool) = 0;
     virtual FloatRect relativeFrame() const = 0;
     virtual FloatRect convertFrameToSpace(const FloatRect&, AccessibilityConversionSpace) const = 0;
+    virtual FloatRect unobscuredContentRect() const = 0;
     virtual bool supportsCheckedState() const = 0;
     
     // In a multi-select list, many items can be selected but only one is active at a time.
@@ -997,6 +998,7 @@
     virtual bool hasItalicFont() const = 0;
     virtual bool hasMisspelling() const = 0;
     virtual std::optional<SimpleRange> misspellingRange(const SimpleRange& start, AccessibilitySearchDirection) const = 0;
+    virtual std::optional<SimpleRange> visibleCharacterRange() const = 0;
     virtual bool hasPlainText() const = 0;
     virtual bool hasSameFont(const AXCoreObject&) const = 0;
     virtual bool hasSameFontColor(const AXCoreObject&) const = 0;

Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (286115 => 286116)


--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm	2021-11-22 20:34:19 UTC (rev 286116)
@@ -52,6 +52,7 @@
 #import "SVGElementInlines.h"
 #import "SVGNames.h"
 #import "SelectionGeometry.h"
+#import "SimpleRange.h"
 #import "TextIterator.h"
 #import "WAKScrollView.h"
 #import "WAKWindow.h"
@@ -1694,12 +1695,7 @@
 {
     if (![self _prepareAccessibilityCall])
         return CGRectZero;
-    
-    auto document = self.axBackingObject->document();
-    if (!document || !document->view())
-        return CGRectZero;
-    auto rect = FloatRect(snappedIntRect(document->view()->unobscuredContentRect()));
-    return [self convertRectToSpace:rect space:AccessibilityConversionSpace::Screen];
+    return [self convertRectToSpace:self.axBackingObject->unobscuredContentRect() space:AccessibilityConversionSpace::Screen];
 }
 
 // The "center point" is where VoiceOver will "press" an object. This may not be the actual
@@ -1915,7 +1911,7 @@
         });
     }
 
-    return convertToNSArray(accessibleElements);
+    return makeNSArray(accessibleElements);
 }
 
 - (NSArray *)accessibilityDetailsElements
@@ -2104,7 +2100,7 @@
     AccessibilitySearchCriteria criteria = accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(parameters);
     AccessibilityObject::AccessibilityChildrenVector results;
     self.axBackingObject->findMatchingObjects(&criteria, results);
-    return convertToNSArray(results);
+    return makeNSArray(results);
 }
 
 - (void)accessibilityModifySelection:(TextGranularity)granularity increase:(BOOL)increase
@@ -2209,48 +2205,7 @@
     return range ? [self contentForSimpleRange:*range attributed:attributed] : nil;
 }
 
-// FIXME: No reason for this to be a method instead of a function.
-- (NSRange)_convertToNSRange:(const SimpleRange&)range
-{
-    auto& document = range.start.document();
-    auto* frame = document.frame();
-    if (!frame)
-        return NSMakeRange(NSNotFound, 0);
 
-    auto* rootEditableElement = frame->selection().selection().rootEditableElement();
-    auto* scope = rootEditableElement ? rootEditableElement : document.documentElement();
-    if (!scope)
-        return NSMakeRange(NSNotFound, 0);
-
-    // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
-    // that is not inside the current editable region. These checks ensure we don't produce
-    // potentially invalid data when responding to such requests.
-    if (!scope->contains(range.start.container.ptr()) || !scope->contains(range.end.container.ptr()))
-        return NSMakeRange(NSNotFound, 0);
-
-    return NSMakeRange(characterCount({ { *scope, 0 }, range.start }), characterCount(range));
-}
-
-- (std::optional<SimpleRange>)_convertToDOMRange:(NSRange)range
-{
-    if (range.location == NSNotFound)
-        return std::nullopt;
-
-    // our critical assumption is that we are only called by input methods that
-    // concentrate on a given area containing the selection
-    // We have to do this because of text fields and textareas. The DOM for those is not
-    // directly in the document DOM, so serialization is problematic. Our solution is
-    // to use the root editable element of the selection start as the positional base.
-    // That fits with AppKit's idea of an input context.
-    auto document = self.axBackingObject->document();
-    auto selectionRoot = document->frame()->selection().selection().rootEditableElement();
-    auto scope = selectionRoot ? selectionRoot : document->documentElement();
-    if (!scope)
-        return std::nullopt;
-
-    return resolveCharacterRange(makeRangeSelectingNodeContents(*scope), range);
-}
-
 // This method is intended to take a text marker representing a VisiblePosition and convert it
 // into a normalized location within the document.
 - (NSInteger)positionForTextMarker:(WebAccessibilityTextMarker *)marker
@@ -2267,7 +2222,7 @@
         auto range = cache->rangeForUnorderedCharacterOffsets(characterOffset, characterOffset);
         if (!range)
             return NSNotFound;
-        return [self _convertToNSRange:*range].location;
+        return makeNSRange(range).location;
     }
     return NSNotFound;
 }
@@ -2346,7 +2301,7 @@
     if (![self _prepareAccessibilityCall])
         return nil;
 
-    auto range = [self _convertToDOMRange:NSMakeRange(position, 0)];
+    auto range = makeDOMRange(self.axBackingObject->document(), NSMakeRange(position, 0));
     if (!range)
         return nil;
 
@@ -2414,7 +2369,7 @@
 {
     if (![self _prepareAccessibilityCall])
         return nil;
-    auto webRange = [self _convertToDOMRange:range];
+    auto webRange = makeDOMRange(self.axBackingObject->document(), range);
     if (!webRange)
         return nil;
     return self.axBackingObject->stringForRange(*webRange);
@@ -2600,6 +2555,17 @@
     return [self previousMarkerForCharacterOffset:start];
 }
 
+- (CGRect)frameForRange:(NSRange)range
+{
+    if (![self _prepareAccessibilityCall])
+        return CGRectZero;
+    auto webRange = makeDOMRange(self.axBackingObject->document(), range);
+    if (!webRange)
+        return CGRectZero;
+    auto rect = self.axBackingObject->boundsForRange(*webRange);
+    return [self convertRectToSpace:rect space:AccessibilityConversionSpace::Screen];
+}
+
 // This method is intended to return the bounds of a text marker range in screen coordinates.
 - (CGRect)frameForTextMarkers:(NSArray *)array
 {
@@ -2931,7 +2897,7 @@
         return nil;
 
     auto radicand = self.axBackingObject->mathRadicand();
-    return radicand ? convertToNSArray(*radicand) : nil;
+    return radicand ? makeNSArray(*radicand) : nil;
 }
 
 - (WebAccessibilityObjectWrapper *)accessibilityMathNumeratorObject

Modified: trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp (286115 => 286116)


--- trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp	2021-11-22 20:34:19 UTC (rev 286116)
@@ -992,6 +992,13 @@
         tree->applyPendingChanges();
 }
 
+std::optional<SimpleRange> AXIsolatedObject::visibleCharacterRange() const
+{
+    ASSERT(isMainThread());
+    auto* axObject = associatedAXObject();
+    return axObject ? axObject->visibleCharacterRange() : std::nullopt;
+}
+
 std::optional<SimpleRange> AXIsolatedObject::rangeForPlainTextRange(const PlainTextRange& axRange) const
 {
     ASSERT(isMainThread());
@@ -1470,6 +1477,15 @@
         object->setSelectedVisiblePositionRange(visiblePositionRange);
 }
 
+FloatRect AXIsolatedObject::unobscuredContentRect() const
+{
+    return Accessibility::retrieveValueFromMainThread<FloatRect>([this] () -> FloatRect {
+        if (auto* object = associatedAXObject())
+            return object->unobscuredContentRect();
+        return { };
+    });
+}
+
 std::optional<SimpleRange> AXIsolatedObject::elementRange() const
 {
     ASSERT(isMainThread());

Modified: trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h (286115 => 286116)


--- trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h	2021-11-22 20:34:19 UTC (rev 286116)
@@ -441,9 +441,11 @@
     AXCoreObject* accessibilityObjectForPosition(const VisiblePosition&) const override;
     int lineForPosition(const VisiblePosition&) const override;
     PlainTextRange plainTextRangeForVisiblePositionRange(const VisiblePositionRange&) const override;
+    std::optional<SimpleRange> visibleCharacterRange() const override;
     int index(const VisiblePosition&) const override;
     void lineBreaks(Vector<int>&) const override;
-
+    FloatRect unobscuredContentRect() const override;
+    
     // Attribute setters.
     void setARIAGrabbed(bool) override;
     void setIsExpanded(bool) override;

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.h (286115 => 286116)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.h	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.h	2021-11-22 20:34:19 UTC (rev 286116)
@@ -34,6 +34,7 @@
 
 namespace WebCore {
 struct AccessibilitySearchCriteria;
+class Document;
 class IntRect;
 class FloatPoint;
 class HTMLTextFormControlElement;
@@ -111,11 +112,15 @@
 - (NSArray *)accessibilityMathPostscriptPairs;
 - (NSArray *)accessibilityMathPrescriptPairs;
 
+- (NSRange)accessibilityVisibleCharacterRange;
+
 - (NSDictionary<NSString *, id> *)baseAccessibilityResolvedEditingStyles;
 
 extern WebCore::AccessibilitySearchCriteria accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(const NSDictionary *);
 
-extern NSArray *convertToNSArray(const WebCore::AXCoreObject::AccessibilityChildrenVector&);
+extern NSArray *makeNSArray(const WebCore::AXCoreObject::AccessibilityChildrenVector&);
+extern NSRange makeNSRange(std::optional<WebCore::SimpleRange>);
+extern std::optional<WebCore::SimpleRange> makeDOMRange(WebCore::Document*, NSRange);
 
 #if PLATFORM(IOS_FAMILY)
 - (id)_accessibilityWebDocumentView;

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm (286115 => 286116)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm	2021-11-22 20:34:19 UTC (rev 286116)
@@ -261,7 +261,7 @@
     }).autorelease();
 }
 
-NSArray *convertToNSArray(const WebCore::AXCoreObject::AccessibilityChildrenVector& children)
+NSArray *makeNSArray(const WebCore::AXCoreObject::AccessibilityChildrenVector& children)
 {
     return createNSArray(children, [] (const auto& child) -> id {
         auto wrapper = child->wrapper();
@@ -462,6 +462,27 @@
     return convertedPath.autorelease();
 }
 
+// Determine the visible range by checking intersection of unobscuredContentRect and a range of text by
+// advancing forward by line from top and backwards by line from the bottom, until we have a visible range.
+- (NSRange)accessibilityVisibleCharacterRange
+{
+    return Accessibility::retrieveValueFromMainThread<NSRange>([protectedSelf = retainPtr(self)] () -> NSRange {
+        auto backingObject = protectedSelf.get().baseUpdateBackingStore;
+        if (!backingObject)
+            return NSMakeRange(NSNotFound, 0);
+
+        auto elementRange = makeNSRange(backingObject->elementRange());
+        if (elementRange.location == NSNotFound)
+            return elementRange;
+        
+        auto visibleRange = makeNSRange(backingObject->visibleCharacterRange());
+        if (visibleRange.location == NSNotFound)
+            return visibleRange;
+
+        return NSMakeRange(visibleRange.location - elementRange.location, visibleRange.length);
+    });
+}
+
 - (id)_accessibilityWebDocumentView
 {
     ASSERT_NOT_REACHED();
@@ -623,6 +644,49 @@
     AXAttributeStringSetLanguage(attrString, node->renderer(), attrStringRange);
 }
 
+NSRange makeNSRange(std::optional<SimpleRange> range)
+{
+    if (!range)
+        return NSMakeRange(NSNotFound, 0);
+    
+    auto& document = range->start.document();
+    auto* frame = document.frame();
+    if (!frame)
+        return NSMakeRange(NSNotFound, 0);
+
+    auto* rootEditableElement = frame->selection().selection().rootEditableElement();
+    auto* scope = rootEditableElement ? rootEditableElement : document.documentElement();
+    if (!scope)
+        return NSMakeRange(NSNotFound, 0);
+
+    // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
+    // that is not inside the current editable region. These checks ensure we don't produce
+    // potentially invalid data when responding to such requests.
+    if (!scope->contains(range->start.container.ptr()) || !scope->contains(range->end.container.ptr()))
+        return NSMakeRange(NSNotFound, 0);
+
+    return NSMakeRange(characterCount({ { *scope, 0 }, range->start }), characterCount(*range));
+}
+
+std::optional<SimpleRange> makeDOMRange(Document* document, NSRange range)
+{
+    if (range.location == NSNotFound)
+        return std::nullopt;
+
+    // our critical assumption is that we are only called by input methods that
+    // concentrate on a given area containing the selection
+    // We have to do this because of text fields and textareas. The DOM for those is not
+    // directly in the document DOM, so serialization is problematic. Our solution is
+    // to use the root editable element of the selection start as the positional base.
+    // That fits with AppKit's idea of an input context.
+    auto selectionRoot = document->frame()->selection().selection().rootEditableElement();
+    auto scope = selectionRoot ? selectionRoot : document->documentElement();
+    if (!scope)
+        return std::nullopt;
+
+    return resolveCharacterRange(makeRangeSelectingNodeContents(*scope), range);
+}
+
 // Returns an array of strings and AXObject wrappers corresponding to the text
 // runs and replacement nodes included in the given range.
 - (NSArray *)contentForSimpleRange:(const SimpleRange&)range attributed:(BOOL)attributed
@@ -676,18 +740,26 @@
     return array.autorelease();
 }
 
-- (NSArray<NSDictionary *> *)lineRectsAndText
+- (WebCore::AXCoreObject*)baseUpdateBackingStore
 {
 #if PLATFORM(MAC)
     auto* backingObject = self.updateObjectBackingStore;
     if (!backingObject)
-        return nil;
+        return nullptr;
 #else
     if (![self _prepareAccessibilityCall])
-        return nil;
+        return nullptr;
     auto* backingObject = self.axBackingObject;
 #endif
+    return backingObject;
+}
 
+- (NSArray<NSDictionary *> *)lineRectsAndText
+{
+    auto backingObject = self.baseUpdateBackingStore;
+    if (!backingObject)
+        return nil;
+    
     auto range = backingObject->elementRange();
     if (!range)
         return nil;

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (286115 => 286116)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2021-11-22 20:34:19 UTC (rev 286116)
@@ -1795,7 +1795,7 @@
 
 - (NSArray<WebAccessibilityObjectWrapper *> *)childrenVectorArray
 {
-    return convertToNSArray(self.axBackingObject->children());
+    return makeNSArray(self.axBackingObject->children());
 }
 
 - (NSValue *)position
@@ -2203,7 +2203,7 @@
         if (backingObject->isTreeItem()) {
             AccessibilityObject::AccessibilityChildrenVector contentCopy;
             backingObject->ariaTreeItemContent(contentCopy);
-            return convertToNSArray(contentCopy);
+            return makeNSArray(contentCopy);
         }
 
         return self.childrenVectorArray;
@@ -2213,7 +2213,7 @@
         if (backingObject->canHaveSelectedChildren()) {
             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
             backingObject->selectedChildren(selectedChildrenCopy);
-            return convertToNSArray(selectedChildrenCopy);
+            return makeNSArray(selectedChildrenCopy);
         }
         return nil;
     }
@@ -2222,7 +2222,7 @@
         if (backingObject->isListBox()) {
             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
             backingObject->visibleChildren(visibleChildrenCopy);
-            return convertToNSArray(visibleChildrenCopy);
+            return makeNSArray(visibleChildrenCopy);
         }
 
         if (backingObject->isList())
@@ -2234,7 +2234,7 @@
 
     if (backingObject->isWebArea()) {
         if ([attributeName isEqualToString:@"AXLinkUIElements"])
-            return convertToNSArray(backingObject->documentLinks());
+            return makeNSArray(backingObject->documentLinks());
 
         if ([attributeName isEqualToString:@"AXLoaded"])
             return [NSNumber numberWithBool:backingObject->isLoaded()];
@@ -2267,10 +2267,6 @@
             PlainTextRange textRange = backingObject->selectedTextRange();
             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
         }
-        // TODO: Get actual visible range. <rdar://problem/4712101>
-        if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
-            return backingObject->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, backingObject->textLength())];
-
         if ([attributeName isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) {
             int lineNumber = backingObject->insertionPointLineNumber();
             return lineNumber >= 0 ? @(lineNumber) : nil;
@@ -2277,6 +2273,15 @@
         }
     }
 
+    if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
+        if (backingObject->isPasswordField())
+            return nil;
+        // TODO: Get actual visible range. <rdar://problem/4712101>
+        if (backingObject->isTextControl())
+            return [NSValue valueWithRange:NSMakeRange(0, backingObject->textLength())];
+        return [NSValue valueWithRange:[self accessibilityVisibleCharacterRange]];
+    }
+
     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
         URL url = ""
         if (url.isNull())
@@ -2380,7 +2385,7 @@
 
     if ([attributeName isEqualToString:NSAccessibilityImageOverlayElementsAttribute]) {
         auto imageOverlayElements = backingObject->imageOverlayElements();
-        return imageOverlayElements ? convertToNSArray(*imageOverlayElements) : nil;
+        return imageOverlayElements ? makeNSArray(*imageOverlayElements) : nil;
     }
 
     if ([attributeName isEqualToString:NSAccessibilityEmbeddedImageDescriptionAttribute])
@@ -2404,29 +2409,29 @@
         if (backingObject->isTabList()) {
             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
             backingObject->tabChildren(tabsChildren);
-            return convertToNSArray(tabsChildren);
+            return makeNSArray(tabsChildren);
         }
     }
 
     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute])
-        return convertToNSArray(backingObject->contents());
+        return makeNSArray(backingObject->contents());
 
     if (backingObject->isTable() && backingObject->isExposable()) {
         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
-            return convertToNSArray(backingObject->rows());
+            return makeNSArray(backingObject->rows());
 
         if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute])
-            return convertToNSArray(backingObject->visibleRows());
+            return makeNSArray(backingObject->visibleRows());
 
         // TODO: distinguish between visible and non-visible columns
         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute]
             || [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute])
-            return convertToNSArray(backingObject->columns());
+            return makeNSArray(backingObject->columns());
 
         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
             backingObject->selectedChildren(selectedChildrenCopy);
-            return convertToNSArray(selectedChildrenCopy);
+            return makeNSArray(selectedChildrenCopy);
         }
 
         // HTML tables don't support these attributes.
@@ -2435,7 +2440,7 @@
             return nil;
 
         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute])
-            return convertToNSArray(backingObject->columnHeaders());
+            return makeNSArray(backingObject->columnHeaders());
 
         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
             auto* headerContainer = backingObject->headerContainer();
@@ -2443,10 +2448,10 @@
         }
 
         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute])
-            return convertToNSArray(backingObject->rowHeaders());
+            return makeNSArray(backingObject->rowHeaders());
 
         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute])
-            return convertToNSArray(backingObject->cells());
+            return makeNSArray(backingObject->cells());
 
         if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
             return @(backingObject->columnCount());
@@ -2468,7 +2473,7 @@
         // rows attribute for a column is the list of all the elements in that column at each row
         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]
             || [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute])
-            return convertToNSArray(backingObject->children());
+            return makeNSArray(backingObject->children());
 
         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
             auto* header = backingObject->columnHeader();
@@ -2488,10 +2493,10 @@
         }
 
         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute])
-            return convertToNSArray(backingObject->columnHeaders());
+            return makeNSArray(backingObject->columnHeaders());
 
         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute])
-            return convertToNSArray(backingObject->rowHeaders());
+            return makeNSArray(backingObject->rowHeaders());
 
         if ([attributeName isEqualToString:NSAccessibilityARIAColumnIndexAttribute])
             return @(backingObject->axColumnIndex());
@@ -2504,12 +2509,12 @@
         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
             backingObject->selectedChildren(selectedChildrenCopy);
-            return convertToNSArray(selectedChildrenCopy);
+            return makeNSArray(selectedChildrenCopy);
         }
         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
             backingObject->ariaTreeRows(rowsCopy);
-            return convertToNSArray(rowsCopy);
+            return makeNSArray(rowsCopy);
         }
 
         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
@@ -2544,7 +2549,7 @@
     // The rows that are considered inside this row.
     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
         if (backingObject->isTreeItem() || backingObject->isARIATreeGridRow())
-            return convertToNSArray(backingObject->disclosedRows());
+            return makeNSArray(backingObject->disclosedRows());
     }
 
     // The row that contains this row. It should be the same as the first parent that is a treeitem.
@@ -2612,7 +2617,7 @@
     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
         backingObject->linkedUIElements(linkedUIElements);
-        return convertToNSArray(linkedUIElements);
+        return makeNSArray(linkedUIElements);
     }
 
     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
@@ -2685,7 +2690,7 @@
     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
         backingObject->ariaOwnsElements(ariaOwns);
-        return convertToNSArray(ariaOwns);
+        return makeNSArray(ariaOwns);
     }
 
     if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
@@ -2751,7 +2756,7 @@
 
         if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute]) {
             auto radicand = backingObject->mathRadicand();
-            return radicand ? convertToNSArray(*radicand) : nil;
+            return radicand ? makeNSArray(*radicand) : nil;
         }
 
         if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
@@ -2845,7 +2850,7 @@
     if ([attributeName isEqualToString:@"AXDetailsElements"]) {
         AccessibilityObject::AccessibilityChildrenVector details;
         backingObject->ariaDetailsElements(details);
-        return convertToNSArray(details);
+        return makeNSArray(details);
     }
 
     if ([attributeName isEqualToString:NSAccessibilityBrailleLabelAttribute])
@@ -2860,7 +2865,7 @@
     if ([attributeName isEqualToString:@"AXErrorMessageElements"]) {
         AccessibilityObject::AccessibilityChildrenVector errorMessages;
         backingObject->ariaErrorMessageElements(errorMessages);
-        return convertToNSArray(errorMessages);
+        return makeNSArray(errorMessages);
     }
 
     // Multi-selectable
@@ -2878,7 +2883,7 @@
     if ([attributeName isEqualToString:NSAccessibilityAriaControlsAttribute]) {
         AccessibilityObject::AccessibilityChildrenVector ariaControls;
         backingObject->ariaControlsElements(ariaControls);
-        return convertToNSArray(ariaControls);
+        return makeNSArray(ariaControls);
     }
 
     if ([attributeName isEqualToString:NSAccessibilityFocusableAncestorAttribute]) {
@@ -3428,22 +3433,6 @@
     });
 }
 
-// FIXME: No reason for this to be a method instead of a function; can get document from range.
-- (NSRange)_convertToNSRange:(const SimpleRange&)range
-{
-    ASSERT(isMainThread());
-    
-    auto document = self.axBackingObject->document();
-    if (!document)
-        return NSMakeRange(NSNotFound, 0);
-
-    auto documentElement = document->documentElement();
-    if (!documentElement)
-        return NSMakeRange(NSNotFound, 0);
-
-    return characterRange(makeBoundaryPointBeforeNodeContents(*documentElement), range);
-}
-
 - (NSInteger)_indexForTextMarker:(AXTextMarkerRef)marker
 {
     if (!marker)
@@ -3460,7 +3449,7 @@
             if (!range)
                 return NSNotFound;
 
-            return [protectedSelf _convertToNSRange:*range].location;
+            return makeNSRange(range).location;
         }
 
         return NSNotFound;
@@ -3835,8 +3824,8 @@
         AccessibilityObject::AccessibilityChildrenVector results;
         backingObject->findMatchingObjects(&criteria, results);
         if (widgetChildren)
-            return [widgetChildren arrayByAddingObjectsFromArray:convertToNSArray(results)];
-        return convertToNSArray(results);
+            return [widgetChildren arrayByAddingObjectsFromArray:makeNSArray(results)];
+        return makeNSArray(results);
     }
 
     // TextMarker attributes.

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm (286115 => 286116)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm	2021-11-22 20:01:09 UTC (rev 286115)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm	2021-11-22 20:34:19 UTC (rev 286116)
@@ -108,6 +108,7 @@
 - (id)_accessibilityListAncestor;
 - (id)_accessibilityPhotoDescription;
 - (NSArray *)accessibilityImageOverlayElements;
+- (NSRange)accessibilityVisibleCharacterRange;
 
 // TextMarker related
 - (NSArray *)textMarkerRange;
@@ -394,6 +395,9 @@
 
 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringDescriptionOfAttributeValue(JSStringRef attribute)
 {
+    if (JSStringIsEqualToUTF8CString(attribute, "AXVisibleCharacterRange"))
+        return [NSStringFromRange([m_element accessibilityVisibleCharacterRange]) createJSStringRef];
+
     return createJSString();
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to