Skip to content

Commit

Permalink
AX: AXObjectCache::updateIsolatedTree may cause the update of depende…
Browse files Browse the repository at this point in the history
…nt properties for the same object multiple times unnecessarily.

https://bugs.webkit.org/show_bug.cgi?id=267599
<rdar://problem/121065998>

Reviewed by Tyler Wilcock.

AXObjectCache::updateIsolatedTree calls AXIsolatedTree::updateDependentProperties twice unnecessarily in the following scenario:
1. The passed Vector of { object, notification } contains two LabelChanged notifications.
2. There is another notification in between the two label changes that causes an updateNode.
This patch fixes this problem and replaces the struct UpdatedFields that was being used before to prevent duplication of node updates with an OptionSet. This should be somewhat more efficient and less errorprone than the existing implementation.

* Source/WebCore/accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::updateIsolatedTree):

Canonical link: https://commits.webkit.org/273106@main
  • Loading branch information
AndresGonzalezApple committed Jan 17, 2024
1 parent 96d0ed7 commit f890a7c
Showing 1 changed file with 27 additions and 20 deletions.
47 changes: 27 additions & 20 deletions Source/WebCore/accessibility/AXObjectCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4167,16 +4167,33 @@ void AXObjectCache::updateIsolatedTree(const Vector<std::pair<RefPtr<Accessibili
return;
}

struct UpdatedFields {
bool children { false };
bool node { false };
bool dependentProperties { false };
enum class Field : uint8_t {
Children = 1 << 0,
DependentProperties = 1 << 1,
Node = 1 << 2,
};
HashMap<AXID, OptionSet<Field>> updatedObjects;
auto updateChildren = [&] (RefPtr<AccessibilityObject> axObject) {
auto updatedFields = updatedObjects.get(axObject->objectID());
if (!updatedFields.contains(Field::Children)) {
updatedFields.add(Field::Children);
updatedObjects.set(axObject->objectID(), updatedFields);
tree->queueNodeUpdate(*axObject, NodeUpdateOptions::childrenUpdate());
}
};
auto updateDependentProperties = [&] (RefPtr<AccessibilityObject> axObject) {
auto updatedFields = updatedObjects.get(axObject->objectID());
if (!updatedFields.contains(Field::DependentProperties)) {
updatedFields.add(Field::DependentProperties);
updatedObjects.set(axObject->objectID(), updatedFields);
tree->updateDependentProperties(*axObject);
}
};
HashMap<AXID, UpdatedFields> updatedObjects;
auto updateNode = [&] (RefPtr<AccessibilityObject> axObject) {
auto updatedFields = updatedObjects.get(axObject->objectID());
if (!updatedFields.node) {
updatedObjects.set(axObject->objectID(), UpdatedFields { updatedFields.children, true });
if (!updatedFields.contains(Field::Node)) {
updatedFields.add(Field::Node);
updatedObjects.set(axObject->objectID(), updatedFields);
tree->queueNodeUpdate(*axObject, NodeUpdateOptions::nodeUpdate());
}
};
Expand Down Expand Up @@ -4332,27 +4349,17 @@ void AXObjectCache::updateIsolatedTree(const Vector<std::pair<RefPtr<Accessibili
break;
case AXLabelChanged: {
updateNode(notification.first);

auto updatedFields = updatedObjects.get(notification.first->objectID());
if (!updatedFields.dependentProperties) {
updatedObjects.set(notification.first->objectID(), UpdatedFields { updatedFields.children, updatedFields.node, true });
tree->updateDependentProperties(*notification.first);
}
updateDependentProperties(notification.first);
break;
}
case AXLanguageChanged:
case AXRowCountChanged:
updateNode(notification.first);
FALLTHROUGH;
case AXRowCollapsed:
case AXRowExpanded: {
auto updatedFields = updatedObjects.get(notification.first->objectID());
if (!updatedFields.children) {
updatedObjects.set(notification.first->objectID(), UpdatedFields { true, updatedFields.node });
tree->queueNodeUpdate(*notification.first, NodeUpdateOptions::childrenUpdate());
}
case AXRowExpanded:
updateChildren(notification.first);
break;
}
default:
break;
}
Expand Down

0 comments on commit f890a7c

Please sign in to comment.