Skip to content

Commit 2c6cb27

Browse files
generatedunixname1608173377072046meta-codesync[bot]
authored andcommitted
Add null guard for changedTouches in ResponderTouchHistoryStore.recordTouchTrack (#56819)
Summary: Pull Request resolved: #56819 The native iOS touch system can occasionally dispatch touch events to JavaScript where `nativeEvent.changedTouches` is undefined due to inconsistencies between local and UIKit touch registries. This causes a TypeError crash in `ResponderTouchHistoryStore.recordTouchTrack` when it unconditionally calls `.forEach()` on `changedTouches`. The fix adds a defensive null check: if `changedTouches` is null/undefined, we log a DEV warning and bail out early from `recordTouchTrack`. Additionally, `nativeEvent.touches` accesses use optional chaining to prevent secondary crashes. Changelog: [iOS][Fixed] - Fix TypeError crash in ResponderTouchHistoryStore when changedTouches is undefined Reviewed By: fkgozali Differential Revision: D105023000 fbshipit-source-id: d3ade24e93f45614b094932e436f7190c8c0a985
1 parent fafcfcd commit 2c6cb27

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

packages/react-native/src/private/renderer/events/ResponderTouchHistoryStore.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,19 +221,28 @@ const ResponderTouchHistoryStore = {
221221
instrumentationCallback(topLevelType, nativeEvent);
222222
}
223223

224+
if (nativeEvent.changedTouches == null) {
225+
console.error(
226+
'Touch event "%s" received with no changedTouches. This is likely ' +
227+
'a bug in the native touch handling system.',
228+
topLevelType,
229+
);
230+
return;
231+
}
232+
224233
if (isMoveish(topLevelType)) {
225234
nativeEvent.changedTouches.forEach(recordTouchMove);
226235
} else if (isStartish(topLevelType)) {
227236
nativeEvent.changedTouches.forEach(recordTouchStart);
228-
touchHistory.numberActiveTouches = nativeEvent.touches.length;
237+
touchHistory.numberActiveTouches = nativeEvent.touches?.length ?? 0;
229238
if (touchHistory.numberActiveTouches === 1) {
230239
touchHistory.indexOfSingleActiveTouch =
231240
// $FlowFixMe[incompatible-type] might be null according to type
232241
nativeEvent.touches[0].identifier;
233242
}
234243
} else if (isEndish(topLevelType)) {
235244
nativeEvent.changedTouches.forEach(recordTouchEnd);
236-
touchHistory.numberActiveTouches = nativeEvent.touches.length;
245+
touchHistory.numberActiveTouches = nativeEvent.touches?.length ?? 0;
237246
if (touchHistory.numberActiveTouches === 1) {
238247
for (let i = 0; i < touchBank.length; i++) {
239248
const touchTrackToCheck = touchBank[i];

0 commit comments

Comments
 (0)