@amplitude/session-replay-browser 1.47.0-sr-trc-debug-log.4 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +203 -0
  2. package/lib/cjs/beacon-transport.d.ts +2 -0
  3. package/lib/cjs/beacon-transport.d.ts.map +1 -1
  4. package/lib/cjs/beacon-transport.js +39 -1
  5. package/lib/cjs/beacon-transport.js.map +1 -1
  6. package/lib/cjs/config/joined-config.d.ts +1 -6
  7. package/lib/cjs/config/joined-config.d.ts.map +1 -1
  8. package/lib/cjs/config/joined-config.js +23 -64
  9. package/lib/cjs/config/joined-config.js.map +1 -1
  10. package/lib/cjs/config/local-config.d.ts +4 -6
  11. package/lib/cjs/config/local-config.d.ts.map +1 -1
  12. package/lib/cjs/config/local-config.js +3 -19
  13. package/lib/cjs/config/local-config.js.map +1 -1
  14. package/lib/cjs/config/types.d.ts +74 -19
  15. package/lib/cjs/config/types.d.ts.map +1 -1
  16. package/lib/cjs/config/types.js.map +1 -1
  17. package/lib/cjs/index.d.ts +1 -0
  18. package/lib/cjs/index.d.ts.map +1 -1
  19. package/lib/cjs/index.js.map +1 -1
  20. package/lib/cjs/plugins/url-tracking-plugin.d.ts +0 -13
  21. package/lib/cjs/plugins/url-tracking-plugin.d.ts.map +1 -1
  22. package/lib/cjs/plugins/url-tracking-plugin.js +2 -6
  23. package/lib/cjs/plugins/url-tracking-plugin.js.map +1 -1
  24. package/lib/cjs/session-replay.d.ts +0 -33
  25. package/lib/cjs/session-replay.d.ts.map +1 -1
  26. package/lib/cjs/session-replay.js +40 -339
  27. package/lib/cjs/session-replay.js.map +1 -1
  28. package/lib/cjs/targeting/targeting-manager.d.ts +1 -4
  29. package/lib/cjs/targeting/targeting-manager.d.ts.map +1 -1
  30. package/lib/cjs/targeting/targeting-manager.js +10 -56
  31. package/lib/cjs/targeting/targeting-manager.js.map +1 -1
  32. package/lib/cjs/track-destination.d.ts +5 -1
  33. package/lib/cjs/track-destination.d.ts.map +1 -1
  34. package/lib/cjs/track-destination.js +212 -55
  35. package/lib/cjs/track-destination.js.map +1 -1
  36. package/lib/cjs/version.d.ts +1 -1
  37. package/lib/cjs/version.d.ts.map +1 -1
  38. package/lib/cjs/version.js +1 -1
  39. package/lib/cjs/version.js.map +1 -1
  40. package/lib/cjs/worker/index.js +1 -1
  41. package/lib/esm/beacon-transport.d.ts +2 -0
  42. package/lib/esm/beacon-transport.d.ts.map +1 -1
  43. package/lib/esm/beacon-transport.js +39 -1
  44. package/lib/esm/beacon-transport.js.map +1 -1
  45. package/lib/esm/config/joined-config.d.ts +1 -6
  46. package/lib/esm/config/joined-config.d.ts.map +1 -1
  47. package/lib/esm/config/joined-config.js +23 -64
  48. package/lib/esm/config/joined-config.js.map +1 -1
  49. package/lib/esm/config/local-config.d.ts +4 -6
  50. package/lib/esm/config/local-config.d.ts.map +1 -1
  51. package/lib/esm/config/local-config.js +4 -20
  52. package/lib/esm/config/local-config.js.map +1 -1
  53. package/lib/esm/config/types.d.ts +74 -19
  54. package/lib/esm/config/types.d.ts.map +1 -1
  55. package/lib/esm/config/types.js.map +1 -1
  56. package/lib/esm/index.d.ts +1 -0
  57. package/lib/esm/index.d.ts.map +1 -1
  58. package/lib/esm/index.js.map +1 -1
  59. package/lib/esm/plugins/url-tracking-plugin.d.ts +0 -13
  60. package/lib/esm/plugins/url-tracking-plugin.d.ts.map +1 -1
  61. package/lib/esm/plugins/url-tracking-plugin.js +2 -6
  62. package/lib/esm/plugins/url-tracking-plugin.js.map +1 -1
  63. package/lib/esm/session-replay.d.ts +0 -33
  64. package/lib/esm/session-replay.d.ts.map +1 -1
  65. package/lib/esm/session-replay.js +40 -339
  66. package/lib/esm/session-replay.js.map +1 -1
  67. package/lib/esm/targeting/targeting-manager.d.ts +1 -4
  68. package/lib/esm/targeting/targeting-manager.d.ts.map +1 -1
  69. package/lib/esm/targeting/targeting-manager.js +10 -56
  70. package/lib/esm/targeting/targeting-manager.js.map +1 -1
  71. package/lib/esm/track-destination.d.ts +5 -1
  72. package/lib/esm/track-destination.d.ts.map +1 -1
  73. package/lib/esm/track-destination.js +212 -55
  74. package/lib/esm/track-destination.js.map +1 -1
  75. package/lib/esm/version.d.ts +1 -1
  76. package/lib/esm/version.d.ts.map +1 -1
  77. package/lib/esm/version.js +1 -1
  78. package/lib/esm/version.js.map +1 -1
  79. package/lib/esm/worker/index.js +1 -1
  80. package/lib/scripts/index-min.js +1 -1
  81. package/lib/scripts/index-min.js.gz +0 -0
  82. package/lib/scripts/index-min.js.map +1 -1
  83. package/lib/scripts/observers-min.js +1 -1
  84. package/lib/scripts/observers-min.js.gz +0 -0
  85. package/lib/scripts/session-replay-browser-min.js +1 -1
  86. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  87. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  88. package/lib/scripts/targeting-min.js +1 -1
  89. package/lib/scripts/targeting-min.js.gz +0 -0
  90. package/lib/scripts/worker-min.js +1 -1
  91. package/lib/scripts/worker-min.js.gz +0 -0
  92. package/package.json +4 -4
  93. package/lib/cjs/diagnostics.d.ts +0 -50
  94. package/lib/cjs/diagnostics.d.ts.map +0 -1
  95. package/lib/cjs/diagnostics.js +0 -67
  96. package/lib/cjs/diagnostics.js.map +0 -1
  97. package/lib/esm/diagnostics.d.ts +0 -50
  98. package/lib/esm/diagnostics.d.ts.map +0 -1
  99. package/lib/esm/diagnostics.js +0 -64
  100. package/lib/esm/diagnostics.js.map +0 -1
@@ -17,7 +17,6 @@ var identifiers_1 = require("./identifiers");
17
17
  var logger_1 = require("./logger");
18
18
  var replay_start_time_store_1 = require("./replay-start-time-store");
19
19
  var targeting_manager_1 = require("./targeting/targeting-manager");
20
- var diagnostics_1 = require("./diagnostics");
21
20
  var sampling_1 = require("./sampling");
22
21
  var version_1 = require("./version");
23
22
  var url_tracking_plugin_1 = require("./plugins/url-tracking-plugin");
@@ -29,10 +28,6 @@ var SessionReplay = /** @class */ (function () {
29
28
  this.recordCancelCallback = null;
30
29
  this.eventCount = 0;
31
30
  this.sessionTargetingMatch = false;
32
- // Session for which the one-per-session TRC diagnostic event was already emitted. The
33
- // diagnostics client caps in-memory events, so per-call signals go through counters and only
34
- // a single rich snapshot event is recorded per session.
35
- this.trcDiagnosticSessionId = undefined;
36
31
  // Public on purpose. `pageLeaveFns` is iterated by `pageLeaveListener`,
37
32
  // `rrwebEventManager` is dereferenced in `asyncSetSessionId` to drop the beacon buffer
38
33
  // at a session boundary, and `sessionStartTime` drives `isBelowMinSessionDuration()`.
@@ -55,9 +50,6 @@ var SessionReplay = /** @class */ (function () {
55
50
  this.recordEventsPendingShouldLogMetadata = null;
56
51
  /** Cleanup for URL change listener used to re-evaluate targeting on SPA route changes */
57
52
  this.urlChangeCleanup = null;
58
- // Ensures the url_poll.first_tick diagnostic event is emitted at most once per listener setup
59
- // (the per-tick counter still increments every tick; only the rich event is one-shot).
60
- this.urlPollFirstTickRecorded = false;
61
53
  this.crossOriginIframeCoordinator = null;
62
54
  this.crossOriginParentSignalCleanup = null;
63
55
  /** Monotonic counter to ignore stale URL-change targeting results */
@@ -126,23 +118,12 @@ var SessionReplay = /** @class */ (function () {
126
118
  if (forceRestart === void 0) { forceRestart = false; }
127
119
  if (forceTargetingReevaluation === void 0) { forceTargetingReevaluation = false; }
128
120
  return tslib_1.__awaiter(_this, void 0, void 0, function () {
129
- var targetingConfig, shouldReEvaluate, urlChangeEvaluationId, eventForTargeting, pageUrl, pageForTargeting, evalStart, targetingMatch, evalDurationMs, trigger;
130
- var _a, _b, _c, _d, _e, _f, _g;
131
- return tslib_1.__generator(this, function (_h) {
132
- switch (_h.label) {
121
+ var targetingConfig, shouldReEvaluate, urlChangeEvaluationId, eventForTargeting, pageUrl, pageForTargeting, targetingMatch;
122
+ var _a, _b, _c, _d, _e, _f;
123
+ return tslib_1.__generator(this, function (_g) {
124
+ switch (_g.label) {
133
125
  case 0:
134
- // What triggered this evaluation (init vs SPA URL change vs analytics event) — shows in
135
- // DataDog how often re-evaluation actually runs.
136
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalTrigger(isInit ? 'init' : forceTargetingReevaluation ? 'urlchange' : 'event'));
137
126
  if (!this.identifiers || !this.identifiers.sessionId || !this.config) {
138
- // Q4: eval can't run because a prerequisite is missing — record exactly which one.
139
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalMissingPrereq);
140
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.evalMissingPrereq, {
141
- hasIdentifiers: !!this.identifiers,
142
- hasSessionId: !!((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId),
143
- hasConfig: !!this.config,
144
- hasDeviceId: !!this.getDeviceId(),
145
- });
146
127
  if (this.identifiers && !this.identifiers.sessionId) {
147
128
  this.loggerProvider.log('Session ID has not been set yet, cannot evaluate targeting for Session Replay.');
148
129
  }
@@ -153,7 +134,6 @@ var SessionReplay = /** @class */ (function () {
153
134
  }
154
135
  // Handle cases where there's no targeting config
155
136
  if (!this.config.targetingConfig) {
156
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalNoConfig);
157
137
  if (isInit) {
158
138
  this.loggerProvider.log('Targeting config has not been set yet, cannot evaluate targeting.');
159
139
  }
@@ -173,20 +153,8 @@ var SessionReplay = /** @class */ (function () {
173
153
  Object.values(analytics_core_1.SpecialEventType).includes(eventForTargeting.event_type)) {
174
154
  eventForTargeting = undefined;
175
155
  }
176
- pageUrl = (_f = (_c = (_b = targetingParams.page) === null || _b === void 0 ? void 0 : _b.url) !== null && _c !== void 0 ? _c : (_e = (_d = (0, analytics_core_1.getGlobalScope)()) === null || _d === void 0 ? void 0 : _d.location) === null || _e === void 0 ? void 0 : _e.href) !== null && _f !== void 0 ? _f : '';
177
- pageForTargeting = (_g = targetingParams.page) !== null && _g !== void 0 ? _g : (pageUrl !== '' ? { url: pageUrl } : undefined);
178
- // Record the targeting trigger event
179
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.targetingTrigger, {
180
- sessionId: this.identifiers.sessionId,
181
- deviceId: this.getDeviceId(),
182
- targetingConfig: this.config.targetingConfig,
183
- targetingParams: {
184
- userProperties: targetingParams.userProperties,
185
- event: eventForTargeting,
186
- page: pageForTargeting,
187
- },
188
- });
189
- evalStart = Date.now();
156
+ pageUrl = (_e = (_b = (_a = targetingParams.page) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : (_d = (_c = (0, analytics_core_1.getGlobalScope)()) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : '';
157
+ pageForTargeting = (_f = targetingParams.page) !== null && _f !== void 0 ? _f : (pageUrl !== '' ? { url: pageUrl } : undefined);
190
158
  return [4 /*yield*/, (0, targeting_manager_1.evaluateTargetingAndStore)({
191
159
  sessionId: this.identifiers.sessionId,
192
160
  targetingConfig: targetingConfig,
@@ -198,76 +166,38 @@ var SessionReplay = /** @class */ (function () {
198
166
  page: pageForTargeting,
199
167
  },
200
168
  urlChange: forceTargetingReevaluation,
201
- diagnosticsClient: this.config.diagnosticsClient,
202
- deviceId: this.getDeviceId(),
203
169
  })];
204
170
  case 1:
205
- targetingMatch = _h.sent();
206
- evalDurationMs = Date.now() - evalStart;
207
- trigger = isInit ? 'init' : forceTargetingReevaluation ? 'urlchange' : 'event';
208
- // Evaluation latency — surfaces the slow-network residual gap (SR-4234) in DataDog as
209
- // sdk.diagnostics.sr.trc.eval.duration_ms.{avg,max,...}.
210
- this.recordDiagnosticHistogram(diagnostics_1.SrDiagnostic.evalDurationMs, evalDurationMs);
171
+ targetingMatch = _g.sent();
211
172
  if (forceTargetingReevaluation &&
212
173
  urlChangeEvaluationId !== undefined &&
213
174
  urlChangeEvaluationId !== this.latestUrlChangeTargetingEvaluationId) {
214
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalStaleDiscarded);
215
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.evalStaleDiscarded, {
216
- sessionId: this.identifiers.sessionId,
217
- pageUrl: pageForTargeting === null || pageForTargeting === void 0 ? void 0 : pageForTargeting.url,
218
- evaluationId: urlChangeEvaluationId,
219
- latestEvaluationId: this.latestUrlChangeTargetingEvaluationId,
220
- evalDurationMs: evalDurationMs,
221
- });
222
175
  this.loggerProvider.debug("Ignoring stale URL-change targeting result #".concat(urlChangeEvaluationId, "; latest is #").concat(this.latestUrlChangeTargetingEvaluationId, "."));
223
176
  return [2 /*return*/];
224
177
  }
225
- // Per-evaluation outcome (distinct from the per-session sr.gate.* gate counters).
226
- this.incrementDiagnostic(targetingMatch ? diagnostics_1.SrDiagnostic.evalMatch : diagnostics_1.SrDiagnostic.evalNoMatch);
227
178
  // Keep targeting match monotonic within a session: once true, always true.
228
179
  // This avoids races where an older in-flight evaluation resolves false after
229
180
  // a newer evaluation already resolved true.
230
181
  this.sessionTargetingMatch = this.sessionTargetingMatch || targetingMatch;
231
- // Q5: record ALL evaluation params (→ DataDog Logs) so a single evaluation can be fully
232
- // reconstructed by URL, identifiers, inputs, outcome, trigger and latency. userProperties
233
- // values are intentionally reduced to keys to avoid logging PII.
234
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.evalEvent, {
235
- // sessionId + deviceId are stamped by recordDiagnosticEvent.
236
- trigger: trigger,
237
- matched: targetingMatch,
238
- sessionTargetingMatch: this.sessionTargetingMatch,
239
- pageUrl: pageForTargeting === null || pageForTargeting === void 0 ? void 0 : pageForTargeting.url,
240
- hasDeviceId: !!this.getDeviceId(),
241
- hasEvent: !!eventForTargeting,
242
- eventType: eventForTargeting === null || eventForTargeting === void 0 ? void 0 : eventForTargeting.event_type,
243
- userPropertyKeys: targetingParams.userProperties ? Object.keys(targetingParams.userProperties) : [],
244
- evalDurationMs: evalDurationMs,
245
- });
246
182
  this.loggerProvider.debug(JSON.stringify({
247
183
  name: 'targeted replay capture config',
248
184
  sessionTargetingMatch: this.sessionTargetingMatch,
249
185
  event: eventForTargeting,
250
186
  targetingParams: targetingParams,
251
187
  }, null, 2));
252
- return [3 /*break*/, 3];
188
+ _g.label = 2;
253
189
  case 2:
254
- if (targetingConfig && this.sessionTargetingMatch) {
255
- // Already matched earlier this session — recording continues without re-evaluation.
256
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalSkippedAlreadyMatched);
257
- }
258
- _h.label = 3;
259
- case 3:
260
- if (!isInit) return [3 /*break*/, 4];
190
+ if (!isInit) return [3 /*break*/, 3];
261
191
  void this.initialize(true);
262
- return [3 /*break*/, 6];
263
- case 4:
264
- if (!(forceRestart || !this.recordCancelCallback)) return [3 /*break*/, 6];
192
+ return [3 /*break*/, 5];
193
+ case 3:
194
+ if (!(forceRestart || !this.recordCancelCallback)) return [3 /*break*/, 5];
265
195
  this.loggerProvider.log('Recording events for session due to forceRestart or no ongoing recording.');
266
196
  return [4 /*yield*/, this.recordEvents()];
267
- case 5:
268
- _h.sent();
269
- _h.label = 6;
270
- case 6: return [2 /*return*/];
197
+ case 4:
198
+ _g.sent();
199
+ _g.label = 5;
200
+ case 5: return [2 /*return*/];
271
201
  }
272
202
  });
273
203
  });
@@ -343,31 +273,17 @@ var SessionReplay = /** @class */ (function () {
343
273
  */
344
274
  SessionReplay.prototype.setupUrlChangeListener = function () {
345
275
  var _this = this;
346
- var _a, _b, _c, _d, _e, _f;
276
+ var _a, _b;
347
277
  // If init() runs multiple times, remove the previous URL-change subscription first
348
278
  // so we don't leak callbacks and trigger duplicate targeting evaluations.
349
279
  (_a = this.urlChangeCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
350
280
  var globalScope = (0, analytics_core_1.getGlobalScope)();
351
281
  if (!(globalScope === null || globalScope === void 0 ? void 0 : globalScope.location)) {
352
- // No window/location (SSR, worker, or pre-render) — the listener can't attach, so TRC will
353
- // never re-evaluate on navigation. Surface it rather than failing silently.
354
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.urlListenerSkipped);
355
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlListenerSkipped, { reason: 'no_global_scope' });
356
- this.loggerProvider.debug('URL-change listener not attached: no global scope/location.');
357
282
  return;
358
283
  }
359
284
  var hasTargeting = !!((_b = this.config) === null || _b === void 0 ? void 0 : _b.targetingConfig);
360
285
  var onUrlChange = function (href) {
361
286
  _this.currentPageUrl = href;
362
- // Team-visible signal that an SPA navigation was detected at all (covers the "is the SDK
363
- // even seeing route changes in this framework?" question — counter + a log with the href
364
- // and whether it triggered a targeting re-eval).
365
- _this.incrementDiagnostic(diagnostics_1.SrDiagnostic.urlChange);
366
- _this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlChangeEvent, {
367
- href: href,
368
- hasTargeting: hasTargeting,
369
- alreadyMatched: _this.sessionTargetingMatch,
370
- });
371
287
  if (hasTargeting) {
372
288
  var evaluationId = ++_this.latestUrlChangeTargetingEvaluationId;
373
289
  void _this.evaluateTargetingAndCapture({
@@ -378,39 +294,7 @@ var SessionReplay = /** @class */ (function () {
378
294
  _this.loggerProvider.debug("Queued URL-change targeting re-evaluation #".concat(evaluationId, " for ").concat(href, "."));
379
295
  }
380
296
  };
381
- // Pass the polling options so targeting re-evaluation also respects `enableUrlChangePolling`.
382
- // Without this, the targeting listener only sees history.pushState/replaceState + popstate +
383
- // hashchange — so SPA navigations that bypass the history API never re-evaluate TRC and
384
- // recording never starts on the new URL (enableUrlChangePolling previously only affected the
385
- // rrweb URL-tracking plugin, which runs only once recording is already active).
386
- var enablePolling = (_d = (_c = this.config) === null || _c === void 0 ? void 0 : _c.enableUrlChangePolling) !== null && _d !== void 0 ? _d : false;
387
- this.urlPollFirstTickRecorded = false;
388
- var unsubscribe = (0, url_tracking_plugin_1.subscribeToUrlChanges)(globalScope, onUrlChange, {
389
- enablePolling: enablePolling,
390
- pollingInterval: (_e = this.config) === null || _e === void 0 ? void 0 : _e.urlChangePollingInterval,
391
- // Mirror each poll tick to the console (Debug level) so we can confirm polling is firing.
392
- log: this.loggerProvider.debug.bind(this.loggerProvider),
393
- // Prove in DataDog that polling actually FIRES (not just that it was scheduled). Per-tick is a
394
- // cheap aggregated counter; the rich event is emitted once (with href) to avoid flooding the
395
- // diagnostics endpoint with one capture POST per second.
396
- onPoll: function (href, changed) {
397
- _this.incrementDiagnostic(diagnostics_1.SrDiagnostic.urlPollTick);
398
- if (!_this.urlPollFirstTickRecorded) {
399
- _this.urlPollFirstTickRecorded = true;
400
- // pollingInterval is already on url_listener.attached, so it's omitted here.
401
- _this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlPollFirstTick, { href: href, changed: changed });
402
- }
403
- },
404
- });
405
- // Confirm the listener is actually live, and under what settings — if recording never starts on
406
- // navigation, this tells us whether the listener existed and whether polling (the fallback for
407
- // SPAs that bypass the History API) was on.
408
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlListenerAttached, {
409
- hasTargeting: hasTargeting,
410
- enablePolling: enablePolling,
411
- pollingInterval: (_f = this.config) === null || _f === void 0 ? void 0 : _f.urlChangePollingInterval,
412
- });
413
- this.loggerProvider.debug("URL-change listener attached (polling: ".concat(String(enablePolling), ")."));
297
+ var unsubscribe = url_tracking_plugin_1.subscribeToUrlChanges(globalScope, onUrlChange);
414
298
  this.urlChangeCleanup = function () {
415
299
  unsubscribe();
416
300
  _this.urlChangeCleanup = null;
@@ -439,34 +323,14 @@ var SessionReplay = /** @class */ (function () {
439
323
  var currentUrl = (_b = (_a = (0, analytics_core_1.getGlobalScope)()) === null || _a === void 0 ? void 0 : _a.location) === null || _b === void 0 ? void 0 : _b.href;
440
324
  return currentUrl != null ? { url: currentUrl } : undefined;
441
325
  };
442
- /**
443
- * Best-effort navigation type from the Navigation Timing API: 'reload' | 'navigate' |
444
- * 'back_forward' | 'prerender'. Surfaced in the init diagnostic so a page refresh ('reload')
445
- * is distinguishable from a fresh load ('navigate') — neither changes the session id, so this
446
- * is the only way to tell them apart. Returns undefined when the API is unavailable.
447
- */
448
- SessionReplay.prototype.getNavigationType = function () {
449
- try {
450
- var globalScope = (0, analytics_core_1.getGlobalScope)();
451
- var performance_1 = globalScope && globalScope.performance;
452
- if (!performance_1 || typeof performance_1.getEntriesByType !== 'function') {
453
- return undefined;
454
- }
455
- var navEntries = performance_1.getEntriesByType('navigation');
456
- return navEntries.length > 0 ? navEntries[0].type : undefined;
457
- }
458
- catch (_a) {
459
- return undefined;
460
- }
461
- };
462
326
  SessionReplay.prototype._init = function (apiKey, options) {
463
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
327
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
464
328
  return tslib_1.__awaiter(this, void 0, void 0, function () {
465
- var now, _u, _v, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, compressionWorkerScript, trackDestinationWorkerScript, globalScope, _w, compressionScript, trackDestinationScript, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError, onFullSnapshotProcessed, pending_2, pending_1, pending_1_1, _x, event_1, sessionId, messenger, needsUrlTracking;
466
- var e_2, _y;
329
+ var now, _q, _r, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, compressionWorkerScript, trackDestinationWorkerScript, globalScope, _s, compressionScript, trackDestinationScript, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError, onFullSnapshotProcessed, pending_2, pending_1, pending_1_1, _t, event_1, sessionId, messenger, needsUrlTracking;
330
+ var e_2, _u;
467
331
  var _this = this;
468
- return tslib_1.__generator(this, function (_z) {
469
- switch (_z.label) {
332
+ return tslib_1.__generator(this, function (_v) {
333
+ switch (_v.label) {
470
334
  case 0:
471
335
  // Re-init should always tear down any previous URL-change subscription, even when the
472
336
  // next config has no targeting config and we don't subscribe again.
@@ -482,13 +346,13 @@ var SessionReplay = /** @class */ (function () {
482
346
  options.sessionId !== undefined
483
347
  ? (_b = (0, replay_start_time_store_1.getOrInitReplayStartTime)(apiKey, options.sessionId, now, this.loggerProvider)) !== null && _b !== void 0 ? _b : now
484
348
  : now;
485
- _u = this;
349
+ _q = this;
486
350
  return [4 /*yield*/, (0, joined_config_1.createSessionReplayJoinedConfigGenerator)(apiKey, options)];
487
351
  case 1:
488
- _u.joinedConfigGenerator = _z.sent();
352
+ _q.joinedConfigGenerator = _v.sent();
489
353
  return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig()];
490
354
  case 2:
491
- _v = _z.sent(), joinedConfig = _v.joinedConfig, localConfig = _v.localConfig, remoteConfig = _v.remoteConfig;
355
+ _r = _v.sent(), joinedConfig = _r.joinedConfig, localConfig = _r.localConfig, remoteConfig = _r.remoteConfig;
492
356
  this.config = joinedConfig;
493
357
  this.setMetadata(options.sessionId, joinedConfig, localConfig, remoteConfig, (_c = options.version) === null || _c === void 0 ? void 0 : _c.version, version_1.VERSION, (_d = options.version) === null || _d === void 0 ? void 0 : _d.type);
494
358
  this.pageLeaveFns = [];
@@ -512,12 +376,12 @@ var SessionReplay = /** @class */ (function () {
512
376
  if (!(this.config.useWebWorker && globalScope && globalScope.Worker)) return [3 /*break*/, 4];
513
377
  return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('./worker')); })];
514
378
  case 3:
515
- _w = _z.sent(), compressionScript = _w.compressionScript, trackDestinationScript = _w.trackDestinationScript;
379
+ _s = _v.sent(), compressionScript = _s.compressionScript, trackDestinationScript = _s.trackDestinationScript;
516
380
  compressionWorkerScript = compressionScript;
517
381
  trackDestinationWorkerScript = trackDestinationScript;
518
- _z.label = 4;
382
+ _v.label = 4;
519
383
  case 4:
520
- _z.trys.push([4, 6, , 7]);
384
+ _v.trys.push([4, 6, , 7]);
521
385
  return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
522
386
  config: this.config,
523
387
  type: 'replay',
@@ -529,21 +393,21 @@ var SessionReplay = /** @class */ (function () {
529
393
  shouldSend: function () { return !_this.isBelowMinSessionDuration(); },
530
394
  })];
531
395
  case 5:
532
- rrwebEventManager = _z.sent();
396
+ rrwebEventManager = _v.sent();
533
397
  this.rrwebEventManager = rrwebEventManager;
534
398
  managers.push({ name: 'replay', manager: rrwebEventManager });
535
399
  return [3 /*break*/, 7];
536
400
  case 6:
537
- error_1 = _z.sent();
401
+ error_1 = _v.sent();
538
402
  typedError = error_1;
539
403
  this.loggerProvider.warn("Error occurred while creating replay events manager: ".concat(typedError.toString()));
540
404
  return [3 /*break*/, 7];
541
405
  case 7:
542
406
  if (!((_j = this.config.interactionConfig) === null || _j === void 0 ? void 0 : _j.enabled)) return [3 /*break*/, 11];
543
407
  payloadBatcher = this.config.interactionConfig.batch ? click_1.clickBatcher : click_1.clickNonBatcher;
544
- _z.label = 8;
408
+ _v.label = 8;
545
409
  case 8:
546
- _z.trys.push([8, 10, , 11]);
410
+ _v.trys.push([8, 10, , 11]);
547
411
  return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
548
412
  config: this.config,
549
413
  type: 'interaction',
@@ -555,11 +419,11 @@ var SessionReplay = /** @class */ (function () {
555
419
  trackDestinationWorkerScript: trackDestinationWorkerScript,
556
420
  })];
557
421
  case 9:
558
- interactionEventManager = _z.sent();
422
+ interactionEventManager = _v.sent();
559
423
  managers.push({ name: 'interaction', manager: interactionEventManager });
560
424
  return [3 /*break*/, 11];
561
425
  case 10:
562
- error_2 = _z.sent();
426
+ error_2 = _v.sent();
563
427
  typedError = error_2;
564
428
  this.loggerProvider.warn("Error occurred while creating interaction events manager: ".concat(typedError.toString()));
565
429
  return [3 /*break*/, 11];
@@ -577,14 +441,14 @@ var SessionReplay = /** @class */ (function () {
577
441
  pending_2 = this.pendingEmitEvents.splice(0);
578
442
  try {
579
443
  for (pending_1 = tslib_1.__values(pending_2), pending_1_1 = pending_1.next(); !pending_1_1.done; pending_1_1 = pending_1.next()) {
580
- _x = pending_1_1.value, event_1 = _x.event, sessionId = _x.sessionId;
444
+ _t = pending_1_1.value, event_1 = _t.event, sessionId = _t.sessionId;
581
445
  this.eventCompressor.enqueueEvent(event_1, sessionId);
582
446
  }
583
447
  }
584
448
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
585
449
  finally {
586
450
  try {
587
- if (pending_1_1 && !pending_1_1.done && (_y = pending_1.return)) _y.call(pending_1);
451
+ if (pending_1_1 && !pending_1_1.done && (_u = pending_1.return)) _u.call(pending_1);
588
452
  }
589
453
  finally { if (e_2) throw e_2.error; }
590
454
  }
@@ -621,7 +485,7 @@ var SessionReplay = /** @class */ (function () {
621
485
  ], false);
622
486
  return [4 /*yield*/, this.initializeNetworkObservers()];
623
487
  case 12:
624
- _z.sent();
488
+ _v.sent();
625
489
  // Enable background capture when this page is opened by the Amplitude app
626
490
  // (window.opener exists). Uses the shared messenger singleton so that if
627
491
  // autocapture is also loaded, both share a single messenger and script load.
@@ -632,42 +496,10 @@ var SessionReplay = /** @class */ (function () {
632
496
  }
633
497
  this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
634
498
  this.teardownEventListeners(false);
635
- // Q1 "did init happen?": its presence in DataDog proves init() ran to completion for this
636
- // session; the props show whether the prerequisites (session/device id, config) were present.
637
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.init);
638
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.init, {
639
- // sessionId is always stamped by recordDiagnosticEvent, so no separate hasSessionId here.
640
- hasDeviceId: !!this.getDeviceId(),
641
- captureEnabled: this.config.captureEnabled,
642
- hasTargetingConfig: !!this.config.targetingConfig,
643
- sampleRate: this.config.sampleRate,
644
- optOut: this.shouldOptOut(),
645
- currentUrl: (_m = this.getCurrentPageForTargeting()) === null || _m === void 0 ? void 0 : _m.url,
646
- // 'reload' tells a page refresh apart from a fresh load ('navigate') or back/forward
647
- // ('back_forward'). New tabs and refreshes keep the same session id, so this is the only
648
- // way to distinguish a refresh from a brand-new init within a session.
649
- navigationType: this.getNavigationType(),
650
- // sdkVersion is the session-replay-browser version; `version` carries the integration
651
- // (`{ type: 'plugin'|'standalone', version }`) so DataDog shows the actual plugin version too.
652
- sdkVersion: version_1.VERSION,
653
- version: this.config.version,
654
- });
655
499
  return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options.userProperties, page: this.getCurrentPageForTargeting() }, true)];
656
500
  case 13:
657
- _z.sent();
658
- needsUrlTracking = this.config.targetingConfig || ((_q = (_p = (_o = this.config.privacyConfig) === null || _o === void 0 ? void 0 : _o.urlMaskLevels) === null || _p === void 0 ? void 0 : _p.length) !== null && _q !== void 0 ? _q : 0) > 0;
659
- // Record whether we even attempt to wire up the URL-change listener, and the inputs behind that
660
- // decision. If `needsUrlTracking` is false the listener is never attached, so SPA navigations are
661
- // invisible to TRC — this is the first thing to check when "TRC is on but never re-evaluates".
662
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlListenerSetup, {
663
- needsUrlTracking: !!needsUrlTracking,
664
- hasTargetingConfig: !!this.config.targetingConfig,
665
- urlMaskLevels: (_t = (_s = (_r = this.config.privacyConfig) === null || _r === void 0 ? void 0 : _r.urlMaskLevels) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0,
666
- // config always defaults this to a boolean (see local-config), so no `?? false` needed here.
667
- enableUrlChangePolling: this.config.enableUrlChangePolling,
668
- urlChangePollingInterval: this.config.urlChangePollingInterval,
669
- });
670
- this.loggerProvider.debug("URL-change listener needed: ".concat(String(!!needsUrlTracking), "."));
501
+ _v.sent();
502
+ needsUrlTracking = this.config.targetingConfig || ((_p = (_o = (_m = this.config.privacyConfig) === null || _m === void 0 ? void 0 : _m.urlMaskLevels) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : 0) > 0;
671
503
  if (needsUrlTracking) {
672
504
  this.setupUrlChangeListener();
673
505
  }
@@ -707,18 +539,6 @@ var SessionReplay = /** @class */ (function () {
707
539
  this.sendEvents(previousSessionId);
708
540
  }
709
541
  isSessionChange = previousSessionId !== sessionId;
710
- // A real session transition (not the first set): recording stops/restarts and targeting is
711
- // re-evaluated here, so session churn (timeout, multi-tab custom ids, explicit setSessionId)
712
- // is a prime suspect for "sometimes records, sometimes not". recordDiagnosticEvent ships to
713
- // DataDog AND mirrors to loggerProvider.debug. New tabs / refreshes keep the same id and won't
714
- // hit this — use the init diagnostic's navigationType for those.
715
- if (isSessionChange && previousSessionId !== undefined) {
716
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.sessionChanged, {
717
- from: previousSessionId,
718
- to: sessionId,
719
- deviceIdChanged: deviceId !== undefined && deviceId !== currentDeviceId,
720
- });
721
- }
722
542
  // Drop any beacon-buffered events from the previous session BEFORE installing the
723
543
  // new identifiers / start time. Otherwise the page-leave beacon path could attribute
724
544
  // old-session events to the new session id, and the gate (using the new start time)
@@ -815,9 +635,6 @@ var SessionReplay = /** @class */ (function () {
815
635
  // Cross-session leak is prevented in asyncSetSessionId, which drops the buffer
816
636
  // at the session transition. The page-leave path also gates independently.
817
637
  this.suppressedSendCount++;
818
- // gap #1: recording but events held back by min_session_duration — another "recording yet
819
- // no replay in Amplitude" cause.
820
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.sendSuppressedMinDuration);
821
638
  return;
822
639
  }
823
640
  // On the first send-after-pass for the session, emit a custom rrweb event so the
@@ -874,120 +691,17 @@ var SessionReplay = /** @class */ (function () {
874
691
  }
875
692
  return identityStoreOptOut !== undefined ? identityStoreOptOut : (_b = this.config) === null || _b === void 0 ? void 0 : _b.optOut;
876
693
  };
877
- /**
878
- * Increment a diagnostics counter so the team can see the distribution of recording decisions
879
- * across a customer's sessions (e.g. lots of sr.gate.trc_no_match => rule isn't matching).
880
- * Ships via the analytics SDK's DiagnosticsClient. No-op when there's no client or diagnostics
881
- * isn't sampled in; never throws — diagnostics must never interfere with recording.
882
- */
883
- SessionReplay.prototype.incrementDiagnostic = function (counter) {
884
- var _a, _b;
885
- try {
886
- // Mirror to the console (Debug level) so the full set of diagnostics is visible in the
887
- // browser, not only in DataDog — helps debugging when a customer can't share a repro env.
888
- this.loggerProvider.debug("[SR diagnostics] ".concat(counter));
889
- (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.diagnosticsClient) === null || _b === void 0 ? void 0 : _b.increment(counter);
890
- }
891
- catch (_c) {
892
- // swallow — diagnostics is best-effort
893
- }
894
- };
895
- /**
896
- * Record a diagnostics histogram value (min/max/avg/count in DataDog). Same best-effort, never-
897
- * throws contract as incrementDiagnostic. Use for latencies/sizes, not per-call counts.
898
- */
899
- SessionReplay.prototype.recordDiagnosticHistogram = function (name, value) {
900
- var _a, _b;
901
- try {
902
- // Mirror to the console (Debug level) — see incrementDiagnostic.
903
- this.loggerProvider.debug("[SR diagnostics] ".concat(name, "=").concat(value));
904
- // The only caller runs inside evaluateTargetingAndCapture's `this.config` guard, so the
905
- // `config == null` arm of this optional chain is unreachable here (kept as defensive parity
906
- // with recordDiagnosticEvent). The diagnosticsClient-absent arm IS exercised by no-client tests.
907
- /* istanbul ignore next */
908
- (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.diagnosticsClient) === null || _b === void 0 ? void 0 : _b.recordHistogram(name, value);
909
- }
910
- catch (_c) {
911
- // swallow — diagnostics is best-effort
912
- }
913
- };
914
- /**
915
- * Record a diagnostics EVENT with properties. Events are forwarded to DataDog Logs, so the
916
- * properties become queryable fields (e.g. @matched, @pageUrl). Use sparingly vs counters: the
917
- * client caps in-memory events (~10 per save interval), so this is for context-rich signals at
918
- * meaningful decision points, not per-call tallies. Best-effort, never throws.
919
- */
920
- SessionReplay.prototype.recordDiagnosticEvent = function (name, properties) {
921
- var _a, _b, _c, _d, _e, _f;
922
- try {
923
- var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
924
- var deviceId = this.getDeviceId();
925
- // Always stamp sessionId, deviceId and srId so every diagnostics event (→ DataDog Logs) can
926
- // be correlated to a single session/device — and to the actual replay, since the Session
927
- // Replay ID is `${deviceId}/${sessionId}`. Caller props override if they pass their own.
928
- var enriched = tslib_1.__assign({ sessionId: sessionId, deviceId: deviceId, srId: deviceId != null && sessionId != null ? "".concat(deviceId, "/").concat(sessionId) : undefined }, properties);
929
- // Mirror to the console (Debug level) so the full event + props are visible in the browser,
930
- // not only in DataDog — see incrementDiagnostic.
931
- this.loggerProvider.debug("[SR diagnostics] ".concat(name, " ").concat(JSON.stringify(enriched)));
932
- (_c = (_b = this.config) === null || _b === void 0 ? void 0 : _b.diagnosticsClient) === null || _c === void 0 ? void 0 : _c.recordEvent(name, enriched);
933
- // Flush immediately so the event ships now rather than on the client's ~5-min timer (and so
934
- // short sessions that never reach the timer aren't lost). NOTE: this sends one capture POST
935
- // per event — higher request volume; revisit/gate before production.
936
- void ((_f = (_e = (_d = this.config) === null || _d === void 0 ? void 0 : _d.diagnosticsClient) === null || _e === void 0 ? void 0 : _e._flush) === null || _f === void 0 ? void 0 : _f.call(_e));
937
- }
938
- catch (_g) {
939
- // swallow — diagnostics is best-effort
940
- }
941
- };
942
- /**
943
- * Emit a single rich TRC decision snapshot per session to diagnostics — surfaced even when
944
- * nothing records (the exact case customers can't reproduce locally).
945
- */
946
- SessionReplay.prototype.recordTrcDecisionDiagnostic = function (shouldRecord) {
947
- var _a, _b;
948
- var config = this.config;
949
- // Every caller is past getShouldRecord's `!this.identifiers`/`!this.config` guard, so both are
950
- // defined here; the `?.` arms below are unreachable defensive narrowing and excluded from
951
- // coverage. The reachable guards (no diagnosticsClient, undefined/duplicate sessionId) are tested.
952
- /* istanbul ignore next */
953
- if (!config) {
954
- return;
955
- }
956
- /* istanbul ignore next */
957
- var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
958
- // Once past this guard, config.diagnosticsClient is truthy, so the fields below read config
959
- // directly rather than re-asserting with `?.` on every access.
960
- if (!config.diagnosticsClient || sessionId === undefined || sessionId === this.trcDiagnosticSessionId) {
961
- return;
962
- }
963
- this.trcDiagnosticSessionId = sessionId;
964
- // Goes through recordDiagnosticEvent so it carries sessionId + deviceId like every other event.
965
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.decision, {
966
- shouldRecord: shouldRecord,
967
- captureEnabled: config.captureEnabled,
968
- hasTargetingConfig: !!config.targetingConfig,
969
- sessionTargetingMatch: this.sessionTargetingMatch,
970
- sampleRate: config.sampleRate,
971
- pageUrl: (_b = this.getCurrentPageForTargeting()) === null || _b === void 0 ? void 0 : _b.url,
972
- sdkVersion: version_1.VERSION,
973
- });
974
- };
975
694
  SessionReplay.prototype.getShouldRecord = function () {
976
695
  if (!this.identifiers || !this.config || !this.identifiers.sessionId) {
977
696
  this.loggerProvider.warn("Session is not being recorded due to lack of config, please call sessionReplay.init.");
978
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateNoIdentifiers);
979
697
  return false;
980
698
  }
981
699
  if (!this.config.captureEnabled) {
982
700
  this.loggerProvider.log("Session ".concat(this.identifiers.sessionId, " not being captured due to capture being disabled for project or because the remote config could not be fetched."));
983
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateCaptureDisabled);
984
- this.recordTrcDecisionDiagnostic(false);
985
701
  return false;
986
702
  }
987
703
  if (this.shouldOptOut()) {
988
704
  this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to optOut config."));
989
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateOptOut);
990
- this.recordTrcDecisionDiagnostic(false);
991
705
  return false;
992
706
  }
993
707
  var shouldRecord = false;
@@ -1001,14 +715,12 @@ var SessionReplay = /** @class */ (function () {
1001
715
  this.loggerProvider.log(message);
1002
716
  shouldRecord = false;
1003
717
  matched = false;
1004
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateTrcNoMatch);
1005
718
  }
1006
719
  else {
1007
720
  message = "Capturing replays for session ".concat(this.identifiers.sessionId, " due to matching targeting conditions.");
1008
721
  this.loggerProvider.log(message);
1009
722
  shouldRecord = true;
1010
723
  matched = true;
1011
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateTrcMatch);
1012
724
  }
1013
725
  }
1014
726
  else {
@@ -1018,12 +730,10 @@ var SessionReplay = /** @class */ (function () {
1018
730
  this.loggerProvider.log(message);
1019
731
  shouldRecord = false;
1020
732
  matched = false;
1021
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateSampleOut);
1022
733
  }
1023
734
  else {
1024
735
  shouldRecord = true;
1025
736
  matched = true;
1026
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateSampleIn);
1027
737
  }
1028
738
  }
1029
739
  // Only send custom rrweb event for targeting decision when the decision changes
@@ -1036,7 +746,6 @@ var SessionReplay = /** @class */ (function () {
1036
746
  });
1037
747
  this.lastShouldRecordDecision = shouldRecord;
1038
748
  }
1039
- this.recordTrcDecisionDiagnostic(shouldRecord);
1040
749
  return shouldRecord;
1041
750
  };
1042
751
  SessionReplay.prototype.getBlockSelectors = function () {
@@ -1201,9 +910,6 @@ var SessionReplay = /** @class */ (function () {
1201
910
  recordFunction = _o.sent();
1202
911
  // May be undefined if cannot import rrweb-record
1203
912
  if (!recordFunction) {
1204
- // gap #1: gate said record, but rrweb couldn't load → no replay despite shouldRecord=true.
1205
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.recordNoRecordFn);
1206
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.recordNoRecordFn, {});
1207
913
  return [2 /*return*/];
1208
914
  }
1209
915
  return [4 /*yield*/, this.initializeNetworkObservers()];
@@ -1234,11 +940,6 @@ var SessionReplay = /** @class */ (function () {
1234
940
  : {};
1235
941
  ugcFilterRules = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && interactionConfig.ugcFilterRules ? interactionConfig.ugcFilterRules : [];
1236
942
  this.loggerProvider.log("Session Replay capture beginning for ".concat(sessionId, "."));
1237
- // gap #1: rrweb is actually starting. Closes the "gate said yes but no replay" blind spot,
1238
- // and its srId is the id the replay uploads under (compare with analytics events to catch the
1239
- // device-id mismatch that breaks stitching).
1240
- this.incrementDiagnostic(diagnostics_1.SrDiagnostic.recordStarted);
1241
- this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.recordStarted, {});
1242
943
  _o.label = 3;
1243
944
  case 3:
1244
945
  _o.trys.push([3, 5, , 6]);