macOS IM: per-keydown command queue for Zhuyin TCIM
Source/WebKit/UIProcess/mac/WebViewImpl.h
WebKit on macOS routes keyboard events through NSTextInputClient's handleEventByInputMethod:, which dispatches asynchronously to system input methods over XPC. A prior fix (297270@main) introduced m_interpretKeyEventHoldingTank to enforce DOM event ordering: keydown must reach the web process before any compositionstart/update events the IM emits. All keyboard events were serialized through that tank — but the Traditional Chinese Zhuyin IM uses its XPC queue depth as a liveness signal, and the empty queue stalled its main thread. The fix makes keydowns bypass the tank, feeding the IM continuously, while keyups remain serialized through a Deque so the front slot always corresponds to the keydown the IM is currently processing.
Significance
This replaces a flat holding tank with a per-keydown Deque that allows multiple keydowns to be simultaneously in-flight to the IM — a meaningful concurrency-model change to a security-sensitive input pipeline.
Audit directions
-
Deque ordering invariant. "The front is always the keydown the IM is currently processing" is an assumption about IM thread serialization, not enforced by WebKit code. A misbehaving or attacker-installed input method that fires
doCommandBySelector:,insertText:, orsetMarkedText:callbacks out of order could corrupt the front-of-deque association and misroute commands from one keystroke into another's queue. -
Mixed prepend/append population of the same Deque.
collectKeyboardLayoutCommandsForEventusesprependwhile the IM path usesappend. The dual-path population is worth examining for interleaving cases where the synchronous prepend lands in the same Deque while an asynchronous IM completion handler is consuming the front. -
Released-keyup synchronous re-entrancy. The released-keyup path dispatches
handleEventByInputMethod:directly with an inline completion that never drains the Deque. If a released keyup's completion fires synchronously (a valid Cocoa behavior), the next keydown's completion could fire while the keyup's inline block is still on the stack — the tank-drain logic may not account for this re-entrancy. -
WeakPtr-to-CheckedPtr dereferences in async completion lambdas. A teardown-during-composition UAF surface that existed before is now exercised by more concurrent code paths.