Skip to content

Commit 88b23f6

Browse files
committed
ref(replay): Avoid optional chaining
As this is transpiled to a rather verbose form.
1 parent 57b3ccb commit 88b23f6

11 files changed

+60
-39
lines changed

packages/browser/src/client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ export class BrowserClient extends BaseClient<BrowserClientOptions> {
9696
const breadcrumbIntegration = this.getIntegrationById(BREADCRUMB_INTEGRATION_ID) as Breadcrumbs | undefined;
9797
// We check for definedness of `addSentryBreadcrumb` in case users provided their own integration with id
9898
// "Breadcrumbs" that does not have this function.
99-
breadcrumbIntegration?.addSentryBreadcrumb?.(event);
99+
if (breadcrumbIntegration && breadcrumbIntegration.addSentryBreadcrumb) {
100+
breadcrumbIntegration.addSentryBreadcrumb(event);
101+
}
100102

101103
super.sendEvent(event, hint);
102104
}

packages/replay/src/coreHandlers/handleGlobalEvent.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ export function handleGlobalEventListener(replay: ReplayContainer): (event: Even
2121

2222
// Unless `captureExceptions` is enabled, we want to ignore errors coming from rrweb
2323
// As there can be a bunch of stuff going wrong in internals there, that we don't want to bubble up to users
24-
if (isRrwebError(event) && !replay.getOptions()._experiments?.captureExceptions) {
24+
if (isRrwebError(event) && !replay.getOptions()._experiments.captureExceptions) {
2525
__DEBUG_BUILD__ && logger.log('[Replay] Ignoring error from rrweb internals', event);
2626
return null;
2727
}
2828

2929
// Only tag transactions with replayId if not waiting for an error
3030
// @ts-ignore private
3131
if (!event.type || replay.recordingMode === 'session') {
32-
event.tags = { ...event.tags, replayId: replay.session?.id };
32+
event.tags = { ...event.tags, replayId: replay.getSessionId() };
3333
}
3434

3535
// Collect traceIds in _context regardless of `recordingMode` - if it's true,
@@ -44,12 +44,10 @@ export function handleGlobalEventListener(replay: ReplayContainer): (event: Even
4444
replay.getContext().errorIds.add(event.event_id as string);
4545
}
4646

47-
const exc = event.exception?.values?.[0];
48-
if (__DEBUG_BUILD__ && replay.getOptions()._experiments?.traceInternals) {
47+
const exc = getEventExceptionValues(event);
48+
if (__DEBUG_BUILD__ && replay.getOptions()._experiments.traceInternals) {
4949
addInternalBreadcrumb({
50-
message: `Tagging event (${event.event_id}) - ${event.message} - ${exc?.type || 'Unknown'}: ${
51-
exc?.value || 'n/a'
52-
}`,
50+
message: `Tagging event (${event.event_id}) - ${event.message} - ${exc.type}: ${exc.value}`,
5351
});
5452
}
5553

@@ -89,3 +87,11 @@ function addInternalBreadcrumb(arg: Parameters<typeof addBreadcrumb>[0]): void {
8987
...rest,
9088
});
9189
}
90+
91+
function getEventExceptionValues(event: Event): { type: string; value: string } {
92+
return {
93+
type: 'Unknown',
94+
value: 'n/a',
95+
...(event.exception && event.exception.values && event.exception.values[0]),
96+
};
97+
}

packages/replay/src/coreHandlers/handleXhr.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,15 @@ function handleXhr(handlerData: XhrHandlerData): ReplayPerformanceEntry | null {
5050
return null;
5151
}
5252

53+
const timestamp = handlerData.xhr.__sentry_xhr__
54+
? handlerData.xhr.__sentry_xhr__.startTimestamp || 0
55+
: handlerData.endTimestamp;
56+
5357
return {
5458
type: 'resource.xhr',
5559
name: url,
56-
start: (handlerData.xhr.__sentry_xhr__?.startTimestamp || 0) / 1000 || handlerData.endTimestamp / 1000.0,
57-
end: handlerData.endTimestamp / 1000.0,
60+
start: timestamp / 1000,
61+
end: handlerData.endTimestamp / 1000,
5862
data: {
5963
method,
6064
statusCode,

packages/replay/src/eventBuffer.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
9595
*/
9696
public _pendingEvents: RecordingEvent[] = [];
9797

98-
private _worker: null | Worker;
98+
private _worker: Worker;
9999
private _eventBufferItemLength: number = 0;
100100
private _id: number = 0;
101101

@@ -124,8 +124,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
124124
*/
125125
public destroy(): void {
126126
__DEBUG_BUILD__ && logger.log('[Replay] Destroying compression worker');
127-
this._worker?.terminate();
128-
this._worker = null;
127+
this._worker.terminate();
129128
}
130129

131130
/**
@@ -177,7 +176,7 @@ export class EventBufferCompressionWorker implements EventBuffer {
177176
}
178177

179178
// At this point, we'll always want to remove listener regardless of result status
180-
this._worker?.removeEventListener('message', listener);
179+
this._worker.removeEventListener('message', listener);
181180

182181
if (!data.success) {
183182
// TODO: Do some error handling, not sure what
@@ -200,8 +199,8 @@ export class EventBufferCompressionWorker implements EventBuffer {
200199

201200
// Note: we can't use `once` option because it's possible it needs to
202201
// listen to multiple messages
203-
this._worker?.addEventListener('message', listener);
204-
this._worker?.postMessage({ id, method, args: stringifiedArgs });
202+
this._worker.addEventListener('message', listener);
203+
this._worker.postMessage({ id, method, args: stringifiedArgs });
205204
});
206205
}
207206

packages/replay/src/replay.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ export class ReplayContainer implements ReplayContainerInterface {
231231
__DEBUG_BUILD__ && logger.log('[Replay] Stopping Replays');
232232
this._isEnabled = false;
233233
this._removeListeners();
234-
this._stopRecording?.();
235-
this.eventBuffer?.destroy();
234+
this._stopRecording && this._stopRecording();
235+
this.eventBuffer && this.eventBuffer.destroy();
236236
this.eventBuffer = null;
237237
} catch (err) {
238238
this._handleException(err);
@@ -277,7 +277,7 @@ export class ReplayContainer implements ReplayContainerInterface {
277277
*/
278278
public addUpdate(cb: AddUpdateCallback): void {
279279
// We need to always run `cb` (e.g. in the case of `this.recordingMode == 'error'`)
280-
const cbResult = cb?.();
280+
const cbResult = cb();
281281

282282
// If this option is turned on then we will only want to call `flush`
283283
// explicitly
@@ -334,6 +334,11 @@ export class ReplayContainer implements ReplayContainerInterface {
334334
return this._debouncedFlush.flush() as Promise<void>;
335335
}
336336

337+
/** Get the current sesion (=replay) ID */
338+
public getSessionId(): string | undefined {
339+
return this.session && this.session.id;
340+
}
341+
337342
/** A wrapper to conditionally capture exceptions. */
338343
private _handleException(error: unknown): void {
339344
__DEBUG_BUILD__ && logger.error('[Replay]', error);
@@ -362,8 +367,9 @@ export class ReplayContainer implements ReplayContainerInterface {
362367
this._setInitialState();
363368
}
364369

365-
if (session.id !== this.session?.id) {
366-
session.previousSessionId = this.session?.id;
370+
const currentSessionId = this.getSessionId();
371+
if (session.id !== currentSessionId) {
372+
session.previousSessionId = currentSessionId;
367373
}
368374

369375
this.session = session;
@@ -404,7 +410,9 @@ export class ReplayContainer implements ReplayContainerInterface {
404410
if (!this._hasInitializedCoreListeners) {
405411
// Listeners from core SDK //
406412
const scope = getCurrentHub().getScope();
407-
scope?.addScopeListener(this._handleCoreBreadcrumbListener('scope'));
413+
if (scope) {
414+
scope.addScopeListener(this._handleCoreBreadcrumbListener('scope'));
415+
}
408416
addInstrumentationHandler('dom', this._handleCoreBreadcrumbListener('dom'));
409417
addInstrumentationHandler('fetch', handleFetchSpanListener(this));
410418
addInstrumentationHandler('xhr', handleXhrSpanListener(this));
@@ -491,7 +499,7 @@ export class ReplayContainer implements ReplayContainerInterface {
491499
// of the previous session. Do not immediately flush in this case
492500
// to avoid capturing only the checkout and instead the replay will
493501
// be captured if they perform any follow-up actions.
494-
if (this.session?.previousSessionId) {
502+
if (this.session && this.session.previousSessionId) {
495503
return true;
496504
}
497505

@@ -706,7 +714,7 @@ export class ReplayContainer implements ReplayContainerInterface {
706714
* Returns true if session is not expired, false otherwise.
707715
*/
708716
private _checkAndHandleExpiredSession({ expiry = SESSION_IDLE_DURATION }: { expiry?: number } = {}): boolean | void {
709-
const oldSessionId = this.session?.id;
717+
const oldSessionId = this.getSessionId();
710718

711719
// Prevent starting a new session if the last user activity is older than
712720
// MAX_SESSION_LIFE. Otherwise non-user activity can trigger a new
@@ -723,7 +731,7 @@ export class ReplayContainer implements ReplayContainerInterface {
723731
this._loadSession({ expiry });
724732

725733
// Session was expired if session ids do not match
726-
const expired = oldSessionId !== this.session?.id;
734+
const expired = oldSessionId !== this.getSessionId();
727735

728736
if (!expired) {
729737
return true;
@@ -787,14 +795,14 @@ export class ReplayContainer implements ReplayContainerInterface {
787795
* Should never be called directly, only by `flush`
788796
*/
789797
private async _runFlush(): Promise<void> {
790-
if (!this.session) {
791-
__DEBUG_BUILD__ && logger.error('[Replay] No session found to flush.');
798+
if (!this.session || !this.eventBuffer) {
799+
__DEBUG_BUILD__ && logger.error('[Replay] No session or eventBuffer found to flush.');
792800
return;
793801
}
794802

795803
await this._addPerformanceEntries();
796804

797-
if (!this.eventBuffer?.pendingLength) {
805+
if (!this.eventBuffer.pendingLength) {
798806
return;
799807
}
800808

@@ -847,13 +855,13 @@ export class ReplayContainer implements ReplayContainerInterface {
847855
return;
848856
}
849857

850-
if (!this.session?.id) {
858+
if (!this.session) {
851859
__DEBUG_BUILD__ && logger.error('[Replay] No session found to flush.');
852860
return;
853861
}
854862

855863
// A flush is about to happen, cancel any queued flushes
856-
this._debouncedFlush?.cancel();
864+
this._debouncedFlush.cancel();
857865

858866
// this._flushLock acts as a lock so that future calls to `_flush()`
859867
// will be blocked until this promise resolves

packages/replay/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export interface ReplayPluginOptions extends SessionOptions {
118118
*
119119
* Default: undefined
120120
*/
121-
_experiments?: Partial<{
121+
_experiments: Partial<{
122122
captureExceptions: boolean;
123123
traceInternals: boolean;
124124
}>;
@@ -259,6 +259,7 @@ export interface ReplayContainer {
259259
triggerUserActivity(): void;
260260
addUpdate(cb: AddUpdateCallback): void;
261261
getOptions(): ReplayPluginOptions;
262+
getSessionId(): string | undefined;
262263
}
263264

264265
export interface ReplayPerformanceEntry {

packages/replay/src/util/addEvent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function addEvent(
3535
// Only record earliest event if a new session was created, otherwise it
3636
// shouldn't be relevant
3737
const earliestEvent = replay.getContext().earliestEvent;
38-
if (replay.session?.segmentId === 0 && (!earliestEvent || timestampInMs < earliestEvent)) {
38+
if (replay.session && replay.session.segmentId === 0 && (!earliestEvent || timestampInMs < earliestEvent)) {
3939
replay.getContext().earliestEvent = timestampInMs;
4040
}
4141

packages/replay/src/util/isRrwebError.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import type { Event } from '@sentry/types';
44
* Returns true if we think the given event is an error originating inside of rrweb.
55
*/
66
export function isRrwebError(event: Event): boolean {
7-
if (event.type || !event.exception?.values?.length) {
7+
if (event.type || !event.exception || !event.exception.values || !event.exception.values.length) {
88
return false;
99
}
1010

1111
// Check if any exception originates from rrweb
1212
return event.exception.values.some(exception => {
13-
if (!exception.stacktrace?.frames?.length) {
13+
if (!exception.stacktrace || !exception.stacktrace.frames || !exception.stacktrace.frames.length) {
1414
return false;
1515
}
1616

17-
return exception.stacktrace.frames.some(frame => frame.filename?.includes('/rrweb/src/'));
17+
return exception.stacktrace.frames.some(frame => frame.filename && frame.filename.includes('/rrweb/src/'));
1818
});
1919
}

packages/replay/src/util/isSessionExpired.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ export function isSessionExpired(session: Session, idleTimeout: number, targetTi
1111
isExpired(session.started, MAX_SESSION_LIFE, targetTime) ||
1212
// check that the idle timeout has not been exceeded (i.e. user has
1313
// performed an action within the last `idleTimeout` ms)
14-
isExpired(session?.lastActivity, idleTimeout, targetTime)
14+
isExpired(session.lastActivity, idleTimeout, targetTime)
1515
);
1616
}

packages/replay/src/util/sendReplayRequest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function sendReplayRequest({
3535
const client = hub.getClient();
3636
const scope = hub.getScope();
3737
const transport = client && client.getTransport();
38-
const dsn = client?.getDsn();
38+
const dsn = client && client.getDsn();
3939

4040
if (!client || !scope || !transport || !dsn || !session.sampled) {
4141
return;

packages/replay/src/util/shouldFilterRequest.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { ReplayContainer } from '../types';
77
*/
88
export function shouldFilterRequest(replay: ReplayContainer, url: string): boolean {
99
// If we enabled the `traceInternals` experiment, we want to trace everything
10-
if (__DEBUG_BUILD__ && replay.getOptions()._experiments?.traceInternals) {
10+
if (__DEBUG_BUILD__ && replay.getOptions()._experiments.traceInternals) {
1111
return false;
1212
}
1313

@@ -18,6 +18,7 @@ export function shouldFilterRequest(replay: ReplayContainer, url: string): boole
1818
* Checks wether a given URL belongs to the configured Sentry DSN.
1919
*/
2020
function _isSentryRequest(url: string): boolean {
21-
const dsn = getCurrentHub().getClient()?.getDsn();
21+
const client = getCurrentHub().getClient();
22+
const dsn = client && client.getDsn();
2223
return dsn ? url.includes(dsn.host) : false;
2324
}

0 commit comments

Comments
 (0)