Diff
Modified: trunk/LayoutTests/ChangeLog (292773 => 292774)
--- trunk/LayoutTests/ChangeLog 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/LayoutTests/ChangeLog 2022-04-12 17:02:46 UTC (rev 292774)
@@ -1,3 +1,16 @@
+2022-04-12 Tyler Wilcock <[email protected]>
+
+ AX: Incorrect role on dynamic lists
+ https://bugs.webkit.org/show_bug.cgi?id=238831
+
+ Reviewed by Andres Gonzalez.
+
+ * accessibility/list-with-dynamically-changing-content-expected.txt: Added.
+ * accessibility/list-with-dynamically-changing-content.html: Added.
+ * platform/ios/accessibility/list-with-dynamically-changing-content-expected.txt: Added.
+ * platform/ios/TestExpectations: Enable new test.
+ * platform/win/TestExpectations: Skip new test.
+
2022-04-11 Myles C. Maxfield <[email protected]>
Make fast/text/otsvg-canvas.html more robust
Added: trunk/LayoutTests/accessibility/list-with-dynamically-changing-content-expected.txt (0 => 292774)
--- trunk/LayoutTests/accessibility/list-with-dynamically-changing-content-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/list-with-dynamically-changing-content-expected.txt 2022-04-12 17:02:46 UTC (rev 292774)
@@ -0,0 +1,25 @@
+This test ensures that lists that are initially empty but gain children later become part of the AX tree with the proper role.
+
+#ul-list: AXRole: AXGroup
+#ul-list: childrenCount 0
+#aria-list: AXRole: AXGroup
+#aria-list: childrenCount 0
+
+Adding listitems to both lists.
+
+#ul-list: AXRole: AXList
+#ul-list: childrenCount 1
+#aria-list: AXRole: AXList
+#aria-list: childrenCount 1
+
+Clearing listitems from both lists.
+
+#ul-list: AXRole: AXGroup
+#ul-list: childrenCount 0
+#aria-list: AXRole: AXGroup
+#aria-list: childrenCount 0
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/accessibility/list-with-dynamically-changing-content.html (0 => 292774)
--- trunk/LayoutTests/accessibility/list-with-dynamically-changing-content.html (rev 0)
+++ trunk/LayoutTests/accessibility/list-with-dynamically-changing-content.html 2022-04-12 17:02:46 UTC (rev 292774)
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+
+<ul id="ul-list"></ul>
+<div id="aria-list" role="list"></div>
+
+<script>
+ var testOutput = "This test ensures that lists that are initially empty but gain children later become part of the AX tree with the proper role.\n\n";
+ var ulList, ariaList;
+
+ function verifyLists() {
+ testOutput += `#ul-list: ${ulList.role}\n`;
+ testOutput += `#ul-list: childrenCount ${ulList.childrenCount}\n`;
+ testOutput += `#aria-list: ${ariaList.role}\n`;
+ testOutput += `#aria-list: childrenCount ${ariaList.childrenCount}\n`;
+ }
+
+ async function waitForChildrenCount(count) {
+ await waitFor(() => {
+ return ulList.childrenCount === count && ariaList.childrenCount === count;
+ });
+ }
+
+ if (window.accessibilityController) {
+ window.jsTestIsAsync = true;
+ ulList = accessibilityController.accessibleElementById("ul-list");
+ ariaList = accessibilityController.accessibleElementById("aria-list");
+ verifyLists();
+
+ testOutput += `\nAdding listitems to both lists.\n\n`;
+ const li = document.createElement("li");
+ li.textContent = "A dynamic list item";
+ document.getElementById("ul-list").appendChild(li);
+
+ const ariaListItem = document.createElement("div");
+ ariaListItem.role = "listitem";
+ document.getElementById("aria-list").appendChild(ariaListItem);
+
+ setTimeout(async function() {
+ await waitForChildrenCount(1);
+ verifyLists();
+
+ document.getElementById("ul-list").removeChild(li);
+ document.getElementById("aria-list").removeChild(ariaListItem);
+ testOutput += `\nClearing listitems from both lists.\n\n`;
+ await waitForChildrenCount(0);
+ verifyLists();
+
+ debug(testOutput);
+ finishJSTest();
+ }, 0);
+ }
+</script>
+</body>
+</html>
+
Modified: trunk/LayoutTests/platform/ios/TestExpectations (292773 => 292774)
--- trunk/LayoutTests/platform/ios/TestExpectations 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/LayoutTests/platform/ios/TestExpectations 2022-04-12 17:02:46 UTC (rev 292774)
@@ -2097,6 +2097,7 @@
accessibility/aria-readonly-updates-after-dynamic-change.html [ Pass ]
accessibility/aria-required-updates-after-dynamic-change.html [ Pass ]
accessibility/display-contents-element-roles.html [ Pass ]
+accessibility/list-with-dynamically-changing-content.html [ Pass ]
accessibility/node-only-object-element-rect.html [ Pass ]
accessibility/video-element-url-attribute.html [ Pass ]
accessibility/visible-character-range-basic.html [ Pass ]
Added: trunk/LayoutTests/platform/ios/accessibility/list-with-dynamically-changing-content-expected.txt (0 => 292774)
--- trunk/LayoutTests/platform/ios/accessibility/list-with-dynamically-changing-content-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/ios/accessibility/list-with-dynamically-changing-content-expected.txt 2022-04-12 17:02:46 UTC (rev 292774)
@@ -0,0 +1,25 @@
+This test ensures that lists that are initially empty but gain children later become part of the AX tree with the proper role.
+
+#ul-list: Group
+#ul-list: childrenCount 0
+#aria-list: ApplicationGroup
+#aria-list: childrenCount 0
+
+Adding listitems to both lists.
+
+#ul-list: List
+#ul-list: childrenCount 1
+#aria-list: List
+#aria-list: childrenCount 1
+
+Clearing listitems from both lists.
+
+#ul-list: Group
+#ul-list: childrenCount 0
+#aria-list: ApplicationGroup
+#aria-list: childrenCount 0
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Modified: trunk/LayoutTests/platform/win/TestExpectations (292773 => 292774)
--- trunk/LayoutTests/platform/win/TestExpectations 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/LayoutTests/platform/win/TestExpectations 2022-04-12 17:02:46 UTC (rev 292774)
@@ -460,6 +460,9 @@
# TODO Accept header is handled by the browser
http/tests/misc/image-checks-for-accept.html [ Skip ]
+# Probably wrong role after adding children to list (AXGroup instead of AXList).
+accessibility/list-with-dynamically-changing-content.html [ Skip ]
+
# Need to implement AccessibilityUIElement::clearSelectedChildren()
accessibility/aria-listbox-clear-selection-crash.html [ Skip ]
accessibility/listbox-clear-selection.html [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (292773 => 292774)
--- trunk/Source/WebCore/ChangeLog 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/ChangeLog 2022-04-12 17:02:46 UTC (rev 292774)
@@ -1,3 +1,42 @@
+2022-04-12 Tyler Wilcock <[email protected]>
+
+ AX: Incorrect role on dynamic lists
+ https://bugs.webkit.org/show_bug.cgi?id=238831
+
+ Reviewed by Andres Gonzalez.
+
+ AccessibilityList objects cache their role after running
+ AccessibilityNodeObject::determineAccessibilityRole, but we never
+ recomputed it when necessary.
+
+ With this patch, when the children of a list changes, we also
+ re-compute its role, since a list's role is dependent on its children.
+
+ Test: accessibility/list-with-dynamically-changing-content.html
+
+ * accessibility/AXObjectCache.cpp:
+ (WebCore::AXObjectCache::handleChildrenChanged):
+ (WebCore::AXObjectCache::handleRoleChange):
+ (WebCore::AXObjectCache::handleAriaRoleChanged):
+ Renamed to handleRoleChange.
+ * accessibility/AXObjectCache.h:
+ (WebCore::AXObjectCache::handleRoleChange):
+ (WebCore::AXObjectCache::handleAriaRoleChanged):
+ Renamed to handleRoleChange.
+ * accessibility/AccessibilityNodeObject.cpp:
+ (WebCore::AccessibilityNodeObject::updateRole):
+ (WebCore::AccessibilityNodeObject::updateAccessibilityRole):
+ Renamed to updateRole.
+ * accessibility/AccessibilityNodeObject.h:
+ * accessibility/AccessibilityObject.h:
+ (WebCore::AccessibilityObject::updateRole):
+ (WebCore::AccessibilityObject::updateAccessibilityRole):
+ Renamed to updateRole.
+ * accessibility/AccessibilityRenderObject.cpp:
+ (WebCore::AccessibilityRenderObject::updateRoleAfterChildrenCreation):
+ * accessibility/AccessibilityTable.cpp:
+ (WebCore::AccessibilityTable::addChildren):
+
2022-04-12 Zan Dobersek <[email protected]>
[GTK][WPE] Move DMABuf-backed GraphicsContextGLANGLE functionality into a standalone derivation chain
Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (292773 => 292774)
--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp 2022-04-12 17:02:46 UTC (rev 292774)
@@ -1075,6 +1075,10 @@
updateIsolatedTree(object, AXChildrenChanged);
#endif
+ // The role of list objects is dependent on their children, so we'll need to re-compute it here.
+ if (is<AccessibilityList>(object))
+ object.updateRole();
+
postPlatformNotification(&object, AXChildrenChanged);
}
@@ -1792,21 +1796,15 @@
obj->handleActiveDescendantChanged();
}
-void AXObjectCache::handleAriaRoleChanged(Node* node)
+void AXObjectCache::handleRoleChange(AccessibilityObject* axObject)
{
stopCachingComputedObjectAttributes();
+ if (axObject->hasIgnoredValueChanged())
+ childrenChanged(axObject->parentObject());
- // Don't make an AX object unless it's needed
- if (auto* object = get(node)) {
- object->updateAccessibilityRole();
-
- if (object->hasIgnoredValueChanged())
- childrenChanged(object->parentObject());
-
#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
- updateIsolatedTree(object, AXObjectCache::AXAriaRoleChanged);
+ updateIsolatedTree(axObject, AXObjectCache::AXAriaRoleChanged);
#endif
- }
}
void AXObjectCache::deferAttributeChangeIfNeeded(const QualifiedName& attrName, Element* element)
@@ -1843,8 +1841,10 @@
if (!shouldProcessAttributeChange(attrName, element))
return;
- if (attrName == roleAttr)
- handleAriaRoleChanged(element);
+ if (attrName == roleAttr) {
+ if (auto* axObject = get(element))
+ axObject->updateRole();
+ }
else if (attrName == altAttr || attrName == titleAttr)
textChanged(element);
else if (attrName == disabledAttr)
Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (292773 => 292774)
--- trunk/Source/WebCore/accessibility/AXObjectCache.h 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h 2022-04-12 17:02:46 UTC (rev 292774)
@@ -186,6 +186,7 @@
void childrenChanged(RenderObject*, RenderObject* newChild = nullptr);
void childrenChanged(AccessibilityObject*);
void checkedStateChanged(Node*);
+ void handleRoleChange(AccessibilityObject*);
// Called when a node has just been attached, so we can make sure we have the right subclass of AccessibilityObject.
void updateCacheAfterNodeIsAttached(Node*);
void updateLoadingProgress(double);
@@ -467,7 +468,6 @@
// Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
void textChanged(Node*);
void handleActiveDescendantChanged(Node*);
- void handleAriaRoleChanged(Node*);
void handleAriaExpandedChange(Node*);
void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
void handleMenuListValueChanged(Element&);
@@ -602,7 +602,7 @@
inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
inline void AXObjectCache::handleModalChange(Element&) { }
inline void AXObjectCache::deferModalChange(Element*) { }
-inline void AXObjectCache::handleAriaRoleChanged(Node*) { }
+inline void AXObjectCache::handleRoleChange(AccessibilityObject*) { }
inline void AXObjectCache::deferAttributeChangeIfNeeded(const QualifiedName&, Element*) { }
inline void AXObjectCache::handleAttributeChange(const QualifiedName&, Element*) { }
inline bool AXObjectCache::shouldProcessAttributeChange(const QualifiedName&, Element*) { return false; }
Modified: trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp (292773 => 292774)
--- trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp 2022-04-12 17:02:46 UTC (rev 292774)
@@ -120,9 +120,14 @@
m_node = nullptr;
}
-void AccessibilityNodeObject::updateAccessibilityRole()
+void AccessibilityNodeObject::updateRole()
{
+ auto previousRole = m_role;
m_role = determineAccessibilityRole();
+ if (previousRole != m_role) {
+ if (auto* cache = axObjectCache())
+ cache->handleRoleChange(this);
+ }
}
AccessibilityObject* AccessibilityNodeObject::firstChild() const
Modified: trunk/Source/WebCore/accessibility/AccessibilityNodeObject.h (292773 => 292774)
--- trunk/Source/WebCore/accessibility/AccessibilityNodeObject.h 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/accessibility/AccessibilityNodeObject.h 2022-04-12 17:02:46 UTC (rev 292774)
@@ -133,7 +133,7 @@
AccessibilityObject* parentObject() const override;
AccessibilityObject* parentObjectIfExists() const override;
- void updateAccessibilityRole() override;
+ void updateRole() override;
void increment() override;
void decrement() override;
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (292773 => 292774)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.h 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h 2022-04-12 17:02:46 UTC (rev 292774)
@@ -508,7 +508,7 @@
void increment() override { }
void decrement() override { }
- virtual void updateAccessibilityRole() { }
+ virtual void updateRole() { }
const AccessibilityChildrenVector& children(bool updateChildrenIfNeeded = true) override;
virtual void addChildren() { }
enum class DescendIfIgnored : uint8_t { No, Yes };
Modified: trunk/Source/WebCore/accessibility/AccessibilityTable.cpp (292773 => 292774)
--- trunk/Source/WebCore/accessibility/AccessibilityTable.cpp 2022-04-12 16:03:50 UTC (rev 292773)
+++ trunk/Source/WebCore/accessibility/AccessibilityTable.cpp 2022-04-12 17:02:46 UTC (rev 292774)
@@ -429,7 +429,7 @@
// see bug: https://bugs.webkit.org/show_bug.cgi?id=147001
for (const auto& row : m_rows) {
for (const auto& cell : row->children())
- downcast<AccessibilityObject>(*cell).updateAccessibilityRole();
+ downcast<AccessibilityObject>(*cell).updateRole();
}
}