Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 88d4f079e156bef26125130bb5d852cd76ee887c
https://github.com/WebKit/WebKit/commit/88d4f079e156bef26125130bb5d852cd76ee887c
Author: Tyler Wilcock <[email protected]>
Date: 2026-06-26 (Fri, 26 Jun 2026)
Changed paths:
A
LayoutTests/accessibility/mac/layout-complete-notifications-coalesce-expected.txt
A LayoutTests/accessibility/mac/layout-complete-notifications-coalesce.html
M Source/WebCore/accessibility/AXObjectCache.cpp
M Source/WebCore/accessibility/AXObjectCache.h
Log Message:
-----------
AX: Coalesce repeated LayoutComplete notifications for the same object within
the same runloop cycle
https://bugs.webkit.org/show_bug.cgi?id=317950
rdar://180704127
Reviewed by Dominic Mazzoni.
AXObjectCache defers accessibility notifications in m_notificationsToPost and
flushes them from a zero-delay timer (m_notificationPostTimer) once control
returns to the run loop. When JavaScript forces synchronous layout in a loop
without yielding to the run loop -- for example by repeatedly reading a
layout-dependent property like clientWidth inside a MutationObserver callback --
the flush timer never fires, yet each completed layout still posts a
LayoutComplete notification via LocalFrameView::didLayout ->
AXObjectCache::onLayoutComplete. These redundant, duplicate LayoutComplete
notifications accumulate in m_notificationsToPost without bound until the Vector
overflows and CrashOnOverflow deliberately terminates the WebContent process
(observed at ~23 million entries, ~1.66 GB).
Fix this two ways:
1. Coalesce LayoutComplete notifications. Every pending LayoutComplete for a
given object collapses to a single meaningful notification once flushed, so
track
the objects that already have a pending LayoutComplete in a companion
HashSet<AXID> (m_pendingLayoutCompleteObjectIDs) and skip the append when one is
already queued. The set is cleared in lockstep with draining
m_notificationsToPost
in notificationPostTimerFired. This eliminates the unbounded duplicate growth
while preserving existing notification semantics and ordering.
2. Add a hard-cap backstop. Route all appends to m_notificationsToPost through a
new enqueueNotificationToPost() helper that refuses to grow the queue past a
fixed
maximum, asserting via AX_ASSERT_NOT_REACHED() and dropping the notification.
With
the coalescing above, the cap is never reached for LayoutComplete; if it is ever
hit by another notification type, that is a signal the type is being posted in
an
unbounded loop and needs its own coalescing strategy. The assert is debug-only,
so
release builds degrade gracefully (dropping notifications) rather than
overflowing
and crashing.
*
LayoutTests/accessibility/mac/layout-complete-notifications-coalesce-expected.txt:
Added.
* LayoutTests/accessibility/mac/layout-complete-notifications-coalesce.html:
Added.
* Source/WebCore/accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::notificationPostTimerFired):
(WebCore::AXObjectCache::enqueueNotificationToPost):
(WebCore::AXObjectCache::postNotification):
(WebCore::AXObjectCache::postARIANotifyNotification):
(WebCore::AXObjectCache::postLiveRegionNotification):
* Source/WebCore/accessibility/AXObjectCache.h:
Canonical link: https://commits.webkit.org/315950@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications