From 269e0595ec45286139def4209327adcaf6f4102c Mon Sep 17 00:00:00 2001 From: Autopilot Bot Date: Wed, 2 Sep 2026 16:43:16 -0700 Subject: [PATCH] Stop reading `buttons` back out of the pointer payload under construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: WARNING: Generated by Autopilot (alpha) — review carefully, verify the underlying claim before accepting. Agent: React Native Agent (Bugs) | Trajectory: https://www.internalfb.com/intern/devai/devmate/inspector/8e9d02d0-ad79-40df-b2c0-8dbc0f0c39d1/ | SC job: https://www.internalfb.com/intern/sandcastle/instance/54043196151461660/ --- `PointerEvent.createW3CPointerEvent` built its payload map, then read one field straight back out of that same half-built map to compute another field: ``` pointerEvent.putInt("buttons", getButtons(_eventName, pointerType, buttonState)) ... getPressure(pointerEvent.getInt("buttons"), _eventName) ``` Reading from a `WritableNativeMap` while still writing to it is not free and not safe: - `ReadableNativeMap.getInt` materialises the *whole* map across JNI (`importKeys` + `importValues`) and memoises the result in `keysStorage` / `localMapStorage`. Every subsequent `put*` on the same instance then leaves those caches stale, so a later Kotlin-side read of the map (`hasKey`, `toHashMap`) does not see `pressure`, `tangentialPressure`, `hitPathForEventListener` or the modifier keys. - It happens on the pointer-event hot path, once per pointer index per dispatch, purely to recover a value the caller already has in hand. Keep the value in a local and pass it to `getPressure` directly. The payload is byte-for-byte identical: `getInt` returns exactly the `Int` that `putInt` stored, so `getPressure` receives the same argument as before. Changelog: [Internal] Differential Revision: D118471070 --- .../java/com/facebook/react/uimanager/events/PointerEvent.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.kt index bf42c5ab73a9..2dedee48e841 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.kt @@ -204,13 +204,14 @@ internal class PointerEvent private constructor() : Event() { "button", getButtonChange(pointerType, eventState.lastButtonState, buttonState), ) - pointerEvent.putInt("buttons", getButtons(_eventName, pointerType, buttonState)) + val buttons = getButtons(_eventName, pointerType, buttonState) + pointerEvent.putInt("buttons", buttons) val pressure = if (isClickEvent) { 0.0 // click events need pressure=0 } else { - getPressure(pointerEvent.getInt("buttons"), _eventName) + getPressure(buttons, _eventName) } pointerEvent.putDouble("pressure", pressure)