Skip to content

Commit 7cbafd3

Browse files
committed
fix(core): Address latest review feedback
- iOS: Add NSArray type check on path data in convertMultiClick to prevent runtime crash from unrecognized selector on non-array values (HIGH, Sentry bot). - Clear tap buffer when detection is disabled via updateOptions to prevent stale taps from causing false positives on re-enable (LOW, Sentry bot). - Move changelog entry from released 8.8.0 section to Unreleased (danger bot). - Add time window integration test to touchevents that varies timestamps between taps, verifying rageTapTimeWindow actually excludes old taps (sentry-warden).
1 parent 234b1c6 commit 7cbafd3

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- Expose screenshot masking options (`screenshot.maskAllText`, `screenshot.maskAllImages`, `screenshot.maskedViewClasses`, `screenshot.unmaskedViewClasses`) for error screenshots ([#6007](https://github.com/getsentry/sentry-react-native/pull/6007))
1414
- Warn Expo users at Metro startup when prebuilt native projects are missing Sentry configuration ([#5984](https://github.com/getsentry/sentry-react-native/pull/5984))
1515
- Add `Sentry.GlobalErrorBoundary` component (and `withGlobalErrorBoundary` HOC) that renders a fallback UI for fatal non-rendering JS errors routed through `ErrorUtils` in addition to the render-phase errors caught by `Sentry.ErrorBoundary`. Opt-in flags `includeNonFatalGlobalErrors` and `includeUnhandledRejections` extend the fallback to non-fatal errors and unhandled promise rejections respectively. ([#6023](https://github.com/getsentry/sentry-react-native/pull/6023))
16+
- Add rage tap detection — rapid consecutive taps on the same element emit `ui.multiClick` breadcrumbs and appear on the replay timeline with the rage click icon ([#5992](https://github.com/getsentry/sentry-react-native/pull/5992))
1617

1718
### Fixes
1819

@@ -39,7 +40,6 @@
3940
- Add `strictTraceContinuation` and `orgId` options for trace continuation validation ([#5829](https://github.com/getsentry/sentry-react-native/pull/5829))
4041
- Add `deeplinkIntegration` for automatic deep link breadcrumbs ([#5983](https://github.com/getsentry/sentry-react-native/pull/5983))
4142
- Name navigation spans using dispatched action payload when `useDispatchedActionData` is enabled ([#5982](https://github.com/getsentry/sentry-react-native/pull/5982))
42-
- Add rage tap detection — rapid consecutive taps on the same element emit `ui.multiClick` breadcrumbs and appear on the replay timeline with the rage click icon ([#5992](https://github.com/getsentry/sentry-react-native/pull/5992))
4343

4444
### Fixes
4545

packages/core/ios/RNSentryReplayBreadcrumbConverter.m

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,12 @@ - (instancetype _Nonnull)init
8585
return nil;
8686
}
8787

88-
NSMutableArray *path = [breadcrumb.data valueForKey:@"path"];
89-
NSString *message = [RNSentryReplayBreadcrumbConverter getTouchPathMessageFrom:path];
88+
id maybePath = [breadcrumb.data valueForKey:@"path"];
89+
if (![maybePath isKindOfClass:[NSArray class]]) {
90+
return nil;
91+
}
92+
93+
NSString *message = [RNSentryReplayBreadcrumbConverter getTouchPathMessageFrom:maybePath];
9094

9195
return [SentrySessionReplayHybridSDK createBreadcrumbwithTimestamp:breadcrumb.timestamp
9296
category:@"ui.multiClick"

packages/core/src/js/ragetap.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ export class RageTapDetector {
5050
public updateOptions(options: Partial<RageTapDetectorOptions>): void {
5151
if (options.enabled !== undefined) {
5252
this._enabled = options.enabled;
53+
if (!this._enabled) {
54+
this._recentTaps = [];
55+
}
5356
}
5457
if (options.threshold !== undefined) {
5558
this._threshold = options.threshold;

packages/core/test/touchevents.test.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,38 @@ describe('TouchEventBoundary._onTouchStart', () => {
419419
}),
420420
);
421421
});
422+
423+
it('does not trigger when taps are outside the time window', () => {
424+
const { defaultProps } = TouchEventBoundary;
425+
const boundary = new TouchEventBoundary(defaultProps);
426+
const nowMock = jest.spyOn(Date, 'now');
427+
428+
const event = {
429+
_targetInst: {
430+
elementType: { displayName: 'Button' },
431+
memoizedProps: { 'sentry-label': 'submit' },
432+
},
433+
};
434+
435+
nowMock.mockReturnValue(1000);
436+
// @ts-expect-error Calling private member
437+
boundary._onTouchStart(event);
438+
439+
nowMock.mockReturnValue(1500);
440+
// @ts-expect-error Calling private member
441+
boundary._onTouchStart(event);
442+
443+
// Third tap beyond 1000ms default window
444+
nowMock.mockReturnValue(2500);
445+
// @ts-expect-error Calling private member
446+
boundary._onTouchStart(event);
447+
448+
// Only touch breadcrumbs, no multiClick
449+
expect(addBreadcrumb).toHaveBeenCalledTimes(3);
450+
for (const call of addBreadcrumb.mock.calls) {
451+
expect(call[0].category).toBe('touch');
452+
}
453+
});
422454
});
423455

424456
describe('sentry-span-attributes', () => {

0 commit comments

Comments
 (0)