Diff
Modified: trunk/LayoutTests/ChangeLog (278682 => 278683)
--- trunk/LayoutTests/ChangeLog 2021-06-09 23:44:40 UTC (rev 278682)
+++ trunk/LayoutTests/ChangeLog 2021-06-10 00:11:41 UTC (rev 278683)
@@ -1,3 +1,15 @@
+2021-06-09 Andres Gonzalez <[email protected]>
+
+ iOS - VoiceOver reads the old heading text when updated with heading.firstChild.data.
+ https://bugs.webkit.org/show_bug.cgi?id=226754
+
+ Reviewed by Chris Fleizach.
+
+ * accessibility/ios-simulator/heading-text-updates-expected.txt: Added.
+ * accessibility/ios-simulator/heading-text-updates.html: Added.
+ * accessibility/mac/heading-text-updates-expected.txt: Added.
+ * accessibility/mac/heading-text-updates.html: Added.
+
2021-06-09 Devin Rousso <[email protected]>
(r278618) media/modern-media-controls/overflow-support/chapters.html is timing out since introduction
Added: trunk/LayoutTests/accessibility/ios-simulator/heading-text-updates-expected.txt (0 => 278683)
--- trunk/LayoutTests/accessibility/ios-simulator/heading-text-updates-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/heading-text-updates-expected.txt 2021-06-10 00:11:41 UTC (rev 278683)
@@ -0,0 +1,75 @@
+This tests that changing the text in headings by four different DOM methods, results on the corresponding text being retrieved via the accessibility property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+h1
+AXValue: 1
+AXLabel: original text
+h2
+AXValue: 2
+AXLabel: original text
+h3
+AXValue: 3
+AXLabel: original text
+divheading
+AXValue: 2
+AXLabel: original text
+h1
+AXValue: 1
+AXLabel: innerHTML
+h2
+AXValue: 2
+AXLabel: innerHTML
+h3
+AXValue: 3
+AXLabel: innerHTML
+divheading
+AXValue: 2
+AXLabel: innerHTML
+h1
+AXValue: 1
+AXLabel: innerText
+h2
+AXValue: 2
+AXLabel: innerText
+h3
+AXValue: 3
+AXLabel: innerText
+divheading
+AXValue: 2
+AXLabel: innerText
+h1
+AXValue: 1
+AXLabel: textContent
+h2
+AXValue: 2
+AXLabel: textContent
+h3
+AXValue: 3
+AXLabel: textContent
+divheading
+AXValue: 2
+AXLabel: textContent
+h1
+AXValue: 1
+AXLabel: firstChild.data
+h2
+AXValue: 2
+AXLabel: firstChild.data
+h3
+AXValue: 3
+AXLabel: firstChild.data
+divheading
+AXValue: 2
+AXLabel: firstChild.data
+PASS successfullyParsed is true
+
+TEST COMPLETE
+firstChild.data
+
+firstChild.data
+
+firstChild.data
+
+firstChild.data
Added: trunk/LayoutTests/accessibility/ios-simulator/heading-text-updates.html (0 => 278683)
--- trunk/LayoutTests/accessibility/ios-simulator/heading-text-updates.html (rev 0)
+++ trunk/LayoutTests/accessibility/ios-simulator/heading-text-updates.html 2021-06-10 00:11:41 UTC (rev 278683)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+
+<h1 class="output" id="h1">original text</h1>
+<h2 class="output" id="h2">original text</h2>
+<h3 class="output" id="h3">original text</h3>
+<div role="heading" class="output" id="divheading">original text</div>
+
+<script>
+ description("This tests that changing the text in headings by four different DOM methods, results on the corresponding text being retrieved via the accessibility property.");
+
+ var ids = [ "h1", "h2", "h3", "divheading" ];
+
+ function setValue(value) {
+ [...document.querySelectorAll('.output')].forEach((node) => {
+ node[value] = `${value}`;
+ });
+ }
+
+ function setFirstChildData(value) {
+ [...document.querySelectorAll('.output')].forEach((node) => {
+ node.firstChild.data = ""
+ });
+ }
+
+ function checkAXLabels() {
+ ids.forEach((id) => {
+ debug(id);
+ axElement = accessibilityController.accessibleElementById(id);
+ debug(axElement.childAtIndex(0).stringValue);
+ debug(axElement.childAtIndex(0).description);
+ });
+ }
+
+ if (window.accessibilityController) {
+ // Log original text.
+ checkAXLabels();
+
+ setValue("innerHTML");
+ checkAXLabels();
+
+ setValue("innerText");
+ checkAXLabels();
+
+ setValue("textContent");
+ checkAXLabels();
+
+ setFirstChildData("firstChild.data");
+ checkAXLabels();
+ }
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/accessibility/mac/heading-text-updates-expected.txt (0 => 278683)
--- trunk/LayoutTests/accessibility/mac/heading-text-updates-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/mac/heading-text-updates-expected.txt 2021-06-10 00:11:41 UTC (rev 278683)
@@ -0,0 +1,75 @@
+This tests that changing the text in headings by four different DOM methods, results on the corresponding text being retrieved via the accessibility property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+h1
+AXValue: 1
+AXValue: original text
+h2
+AXValue: 2
+AXValue: original text
+h3
+AXValue: 3
+AXValue: original text
+divheading
+AXValue: 2
+AXValue: original text
+h1
+AXValue: 1
+AXValue: innerHTML
+h2
+AXValue: 2
+AXValue: innerHTML
+h3
+AXValue: 3
+AXValue: innerHTML
+divheading
+AXValue: 2
+AXValue: innerHTML
+h1
+AXValue: 1
+AXValue: innerText
+h2
+AXValue: 2
+AXValue: innerText
+h3
+AXValue: 3
+AXValue: innerText
+divheading
+AXValue: 2
+AXValue: innerText
+h1
+AXValue: 1
+AXValue: textContent
+h2
+AXValue: 2
+AXValue: textContent
+h3
+AXValue: 3
+AXValue: textContent
+divheading
+AXValue: 2
+AXValue: textContent
+h1
+AXValue: 1
+AXValue: firstChild.data
+h2
+AXValue: 2
+AXValue: firstChild.data
+h3
+AXValue: 3
+AXValue: firstChild.data
+divheading
+AXValue: 2
+AXValue: firstChild.data
+PASS successfullyParsed is true
+
+TEST COMPLETE
+firstChild.data
+
+firstChild.data
+
+firstChild.data
+
+firstChild.data
Added: trunk/LayoutTests/accessibility/mac/heading-text-updates.html (0 => 278683)
--- trunk/LayoutTests/accessibility/mac/heading-text-updates.html (rev 0)
+++ trunk/LayoutTests/accessibility/mac/heading-text-updates.html 2021-06-10 00:11:41 UTC (rev 278683)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+
+<h1 class="output" id="h1">original text</h1>
+<h2 class="output" id="h2">original text</h2>
+<h3 class="output" id="h3">original text</h3>
+<div role="heading" class="output" id="divheading">original text</div>
+
+<script>
+ description("This tests that changing the text in headings by four different DOM methods, results on the corresponding text being retrieved via the accessibility property.");
+
+ var ids = [ "h1", "h2", "h3", "divheading" ];
+
+ function setValue(value) {
+ [...document.querySelectorAll('.output')].forEach((node) => {
+ node[value] = `${value}`;
+ });
+ }
+
+ function setFirstChildData(value) {
+ [...document.querySelectorAll('.output')].forEach((node) => {
+ node.firstChild.data = ""
+ });
+ }
+
+ function checkAXLabels() {
+ ids.forEach((id) => {
+ debug(id);
+ axElement = accessibilityController.accessibleElementById(id);
+ debug(axElement.stringValue);
+ debug(axElement.childAtIndex(0).stringValue);
+ });
+ }
+
+ if (window.accessibilityController) {
+ // Log original text.
+ checkAXLabels();
+
+ setValue("innerHTML");
+ checkAXLabels();
+
+ setValue("innerText");
+ checkAXLabels();
+
+ setValue("textContent");
+ checkAXLabels();
+
+ setFirstChildData("firstChild.data");
+ checkAXLabels();
+ }
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (278682 => 278683)
--- trunk/Source/WebCore/ChangeLog 2021-06-09 23:44:40 UTC (rev 278682)
+++ trunk/Source/WebCore/ChangeLog 2021-06-10 00:11:41 UTC (rev 278683)
@@ -1,3 +1,27 @@
+2021-06-09 Andres Gonzalez <[email protected]>
+
+ iOS - VoiceOver reads the old heading text when updated with heading.firstChild.data.
+ https://bugs.webkit.org/show_bug.cgi?id=226754
+ rdar://44949563
+
+ Reviewed by Chris Fleizach.
+
+ Tests: accessibility/ios-simulator/heading-text-updates.html
+ accessibility/mac/heading-text-updates.html
+
+ The problem was caused by [WebAccessibilityObjectWrapper _accessibilityTraitsFromAncestors]
+ setting the value and label of static text inside headings. since this
+ method is called only on the initialization of the object, the label is
+ never updated when the text changes.
+ The solution is to move the logic to return the label and value of
+ static text inside headings to the accessibilityLabel and accessibilityValue
+ respectively.
+
+ * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+ (-[WebAccessibilityObjectWrapper _accessibilityTraitsFromAncestors]):
+ (-[WebAccessibilityObjectWrapper accessibilityLabel]):
+ (-[WebAccessibilityObjectWrapper accessibilityValue]):
+
2021-06-09 Eric Carlson <[email protected]>
Nullptr crash in MediaSource::updateBufferedIfNeeded
Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (278682 => 278683)
--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm 2021-06-09 23:44:40 UTC (rev 278682)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm 2021-06-10 00:11:41 UTC (rev 278683)
@@ -661,15 +661,15 @@
- (uint64_t)_accessibilityTraitsFromAncestors
{
uint64_t traits = 0;
- AccessibilityRole role = self.axBackingObject->roleValue();
-
+ auto* backingObject = self.axBackingObject;
+
// Trait information also needs to be gathered from the parents above the object.
- // The parentObject is needed instead of the unignoredParentObject, because a table might be ignored, but information still needs to be gathered from it.
- for (auto* parent = self.axBackingObject->parentObject(); parent != nil; parent = parent->parentObject()) {
+ // The parentObject is needed instead of the unignoredParentObject, because a table might be ignored, but information still needs to be gathered from it.
+ for (auto* parent = backingObject->parentObject(); parent; parent = parent->parentObject()) {
AccessibilityRole parentRole = parent->roleValue();
if (parentRole == AccessibilityRole::WebArea)
break;
-
+
switch (parentRole) {
case AccessibilityRole::Link:
case AccessibilityRole::WebCoreLink:
@@ -677,35 +677,20 @@
if (parent->isVisited())
traits |= [self _axVisitedTrait];
break;
- case AccessibilityRole::Heading: {
+ case AccessibilityRole::Heading:
traits |= [self _axHeaderTrait];
- // If this object has the header trait, we should set the value
- // to the heading level. If it was a static text element, we need to store
- // the value as the label, because the heading level needs to the value.
- AccessibilityObjectWrapper* wrapper = parent->wrapper();
- if (role == AccessibilityRole::StaticText) {
- // We should only set the text value as the label when there's no
- // alternate text on the heading parent.
- NSString *headingLabel = [wrapper baseAccessibilityDescription];
- if (![headingLabel length])
- [self setAccessibilityLabel:self.axBackingObject->stringValue()];
- else
- [self setAccessibilityLabel:headingLabel];
- }
- [self setAccessibilityValue:[wrapper accessibilityValue]];
break;
- }
default:
if ([self _accessibilityIsLandmarkRole:parentRole])
traits |= [self _axContainedByLandmarkTrait];
break;
}
-
+
// If this object has fieldset parent, we should add containedByFieldsetTrait to it.
if (parent->isFieldset())
traits |= [self _axContainedByFieldsetTrait];
}
-
+
return traits;
}
@@ -1189,35 +1174,56 @@
if (label)
return label;
+ auto* backingObject = self.axBackingObject;
+
// iOS doesn't distinguish between a title and description field,
// so concatentation will yield the best result.
- NSString *axTitle = self.axBackingObject->titleAttributeValue();
- NSString *axDescription = [self baseAccessibilityDescription];
+ NSString *axTitle = backingObject->titleAttributeValue();
+ NSString *axDescription = backingObject->descriptionAttributeValue();
NSString *landmarkDescription = [self ariaLandmarkRoleDescription];
NSString *interactiveVideoDescription = [self interactiveVideoDescription];
-
+
+ // If self is static text inside a heading, the label should be the string
+ // value of the static text object, except when the heading has alternative
+ // text, in which case, that alternative text is returned here.
+ // The reason is that the string value for static text inside a heading is
+ // used to convey the heading level instead.
+ if (backingObject->roleValue() == AccessibilityRole::StaticText
+ && self.accessibilityTraits & self._axHeaderTrait) {
+ auto* heading = Accessibility::findAncestor(*backingObject, false, [] (const auto& ancestor) {
+ return ancestor.roleValue() == AccessibilityRole::Heading;
+ });
+
+ if (heading) {
+ auto headingLabel = heading->descriptionAttributeValue();
+ if (!headingLabel.isEmpty())
+ return headingLabel;
+ return backingObject->stringValue();
+ }
+ }
+
// We should expose the value of the input type date or time through AXValue instead of AXTitle.
- if (self.axBackingObject->isInputTypePopupButton() && [axTitle isEqualToString:[self accessibilityValue]])
+ if (backingObject->isInputTypePopupButton() && [axTitle isEqualToString:[self accessibilityValue]])
axTitle = nil;
// Footer is not considered a landmark, but we want the role description.
- if (self.axBackingObject->roleValue() == AccessibilityRole::Footer)
+ if (backingObject->roleValue() == AccessibilityRole::Footer)
landmarkDescription = AXFooterRoleDescriptionText();
NSMutableString *result = [NSMutableString string];
- if (self.axBackingObject->roleValue() == AccessibilityRole::HorizontalRule)
+ if (backingObject->roleValue() == AccessibilityRole::HorizontalRule)
appendStringToResult(result, AXHorizontalRuleDescriptionText());
appendStringToResult(result, axTitle);
appendStringToResult(result, axDescription);
if ([self stringValueShouldBeUsedInLabel]) {
- NSString *valueLabel = self.axBackingObject->stringValue();
+ NSString *valueLabel = backingObject->stringValue();
valueLabel = [valueLabel stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
appendStringToResult(result, valueLabel);
}
appendStringToResult(result, landmarkDescription);
appendStringToResult(result, interactiveVideoDescription);
-
+
return [result length] ? result : nil;
}
@@ -1464,14 +1470,15 @@
{
if (![self _prepareAccessibilityCall])
return nil;
-
+
// check if the value was overridden
NSString *value = [super accessibilityValue];
if (value)
return value;
-
- if (self.axBackingObject->supportsCheckedState()) {
- switch (self.axBackingObject->checkboxOrRadioValue()) {
+
+ auto* backingObject = self.axBackingObject;
+ if (backingObject->supportsCheckedState()) {
+ switch (backingObject->checkboxOrRadioValue()) {
case AccessibilityButtonState::Off:
return [NSString stringWithFormat:@"%d", 0];
case AccessibilityButtonState::On:
@@ -1482,38 +1489,46 @@
ASSERT_NOT_REACHED();
return [NSString stringWithFormat:@"%d", 0];
}
-
- if (self.axBackingObject->isButton() && self.axBackingObject->isPressed())
+
+ if (backingObject->isButton() && backingObject->isPressed())
return [NSString stringWithFormat:@"%d", 1];
+ // If self has the header trait, value should be the heading level.
+ if (self.accessibilityTraits & self._axHeaderTrait) {
+ auto* heading = Accessibility::findAncestor(*backingObject, true, [] (const auto& ancestor) {
+ return ancestor.roleValue() == AccessibilityRole::Heading;
+ });
+ ASSERT(heading);
+
+ if (heading)
+ return [NSString stringWithFormat:@"%d", heading->headingLevel()];
+ }
+
// rdar://8131388 WebKit should expose the same info as UIKit for its password fields.
- if (self.axBackingObject->isPasswordField() && ![self _accessibilityIsStrongPasswordField]) {
- int passwordLength = self.axBackingObject->accessibilityPasswordFieldLength();
+ if (backingObject->isPasswordField() && ![self _accessibilityIsStrongPasswordField]) {
+ int passwordLength = backingObject->accessibilityPasswordFieldLength();
NSMutableString* string = [NSMutableString string];
for (int k = 0; k < passwordLength; ++k)
[string appendString:@"•"];
return string;
}
-
+
// A text control should return its text data as the axValue (per iPhone AX API).
if (![self stringValueShouldBeUsedInLabel])
- return self.axBackingObject->stringValue();
-
- if (self.axBackingObject->isRangeControl()) {
+ return backingObject->stringValue();
+
+ if (backingObject->isRangeControl()) {
// Prefer a valueDescription if provided by the author (through aria-valuetext).
- String valueDescription = self.axBackingObject->valueDescription();
+ String valueDescription = backingObject->valueDescription();
if (!valueDescription.isEmpty())
return valueDescription;
- return [NSString stringWithFormat:@"%.2f", self.axBackingObject->valueForRange()];
+ return [NSString stringWithFormat:@"%.2f", backingObject->valueForRange()];
}
- if (is<AccessibilityAttachment>(self.axBackingObject) && downcast<AccessibilityAttachment>(self.axBackingObject)->hasProgress())
- return [NSString stringWithFormat:@"%.2f", self.axBackingObject->valueForRange()];
-
- if (self.axBackingObject->isHeading())
- return [NSString stringWithFormat:@"%d", self.axBackingObject->headingLevel()];
-
+ if (is<AccessibilityAttachment>(backingObject) && downcast<AccessibilityAttachment>(backingObject)->hasProgress())
+ return [NSString stringWithFormat:@"%.2f", backingObject->valueForRange()];
+
return nil;
}