@newrelic/browser-agent 1.250.0 → 1.251.1

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 (104) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/common/config/state/init.js +0 -2
  3. package/dist/cjs/common/config/state/originals.js +1 -2
  4. package/dist/cjs/common/constants/env.cdn.js +4 -8
  5. package/dist/cjs/common/constants/env.js +4 -8
  6. package/dist/cjs/common/constants/env.npm.js +4 -8
  7. package/dist/cjs/common/constants/runtime.js +13 -24
  8. package/dist/cjs/common/constants/shared-channel.js +2 -3
  9. package/dist/cjs/common/event-emitter/contextual-ee.js +2 -4
  10. package/dist/cjs/common/event-emitter/handle.js +1 -2
  11. package/dist/cjs/common/harvest/harvest-scheduler.js +4 -3
  12. package/dist/cjs/common/harvest/harvest.js +2 -2
  13. package/dist/cjs/common/harvest/types.js +1 -2
  14. package/dist/cjs/common/ids/bundle-id.js +1 -2
  15. package/dist/cjs/common/session/constants.js +7 -13
  16. package/dist/cjs/common/timer/interaction-timer.js +0 -1
  17. package/dist/cjs/common/timing/nav-timing.js +1 -2
  18. package/dist/cjs/common/util/feature-flags.js +1 -2
  19. package/dist/cjs/common/vitals/constants.js +2 -3
  20. package/dist/cjs/common/vitals/cumulative-layout-shift.js +1 -2
  21. package/dist/cjs/common/vitals/first-contentful-paint.js +1 -2
  22. package/dist/cjs/common/vitals/first-input-delay.js +1 -2
  23. package/dist/cjs/common/vitals/first-paint.js +1 -2
  24. package/dist/cjs/common/vitals/interaction-to-next-paint.js +1 -2
  25. package/dist/cjs/common/vitals/largest-contentful-paint.js +1 -2
  26. package/dist/cjs/common/vitals/long-task.js +1 -3
  27. package/dist/cjs/common/vitals/time-to-first-byte.js +1 -2
  28. package/dist/cjs/common/window/nreum.js +1 -2
  29. package/dist/cjs/common/wrap/wrap-function.js +2 -4
  30. package/dist/cjs/features/ajax/aggregate/index.js +0 -2
  31. package/dist/cjs/features/ajax/constants.js +1 -2
  32. package/dist/cjs/features/jserrors/aggregate/index.js +0 -1
  33. package/dist/cjs/features/jserrors/aggregate/string-hash-code.js +0 -1
  34. package/dist/cjs/features/jserrors/constants.js +1 -2
  35. package/dist/cjs/features/metrics/aggregate/index.js +1 -1
  36. package/dist/cjs/features/metrics/constants.js +5 -10
  37. package/dist/cjs/features/page_action/constants.js +1 -2
  38. package/dist/cjs/features/page_view_event/aggregate/index.js +2 -2
  39. package/dist/cjs/features/page_view_event/constants.js +1 -2
  40. package/dist/cjs/features/page_view_event/instrument/index.js +2 -2
  41. package/dist/cjs/features/page_view_timing/constants.js +1 -2
  42. package/dist/cjs/features/session_replay/aggregate/index.js +40 -27
  43. package/dist/cjs/features/session_replay/constants.js +8 -16
  44. package/dist/cjs/features/session_replay/instrument/index.js +11 -11
  45. package/dist/cjs/features/session_replay/shared/recorder-events.js +2 -0
  46. package/dist/cjs/features/session_replay/shared/recorder.js +51 -5
  47. package/dist/cjs/features/session_replay/shared/stylesheet-evaluator.js +99 -0
  48. package/dist/cjs/features/session_trace/aggregate/index.js +0 -2
  49. package/dist/cjs/features/session_trace/constants.js +8 -16
  50. package/dist/cjs/features/session_trace/instrument/index.js +2 -2
  51. package/dist/cjs/features/spa/aggregate/index.js +2 -2
  52. package/dist/cjs/features/spa/aggregate/interaction-node.js +0 -1
  53. package/dist/cjs/features/spa/constants.js +22 -44
  54. package/dist/cjs/features/spa/instrument/index.js +2 -2
  55. package/dist/cjs/features/utils/instrument-base.js +6 -7
  56. package/dist/cjs/features/utils/lazy-feature-loader.js +2 -2
  57. package/dist/cjs/loaders/agent-base.js +61 -15
  58. package/dist/cjs/loaders/agent.js +0 -38
  59. package/dist/cjs/loaders/api/api.js +7 -7
  60. package/dist/cjs/loaders/api/interaction-types.js +1 -2
  61. package/dist/cjs/loaders/features/features.js +3 -5
  62. package/dist/cjs/loaders/micro-agent.js +2 -2
  63. package/dist/esm/common/config/state/init.js +0 -2
  64. package/dist/esm/common/constants/env.cdn.js +1 -1
  65. package/dist/esm/common/constants/env.npm.js +1 -1
  66. package/dist/esm/common/harvest/harvest-scheduler.js +2 -1
  67. package/dist/esm/common/timer/interaction-timer.js +0 -1
  68. package/dist/esm/common/vitals/long-task.js +0 -1
  69. package/dist/esm/features/ajax/aggregate/index.js +0 -2
  70. package/dist/esm/features/jserrors/aggregate/index.js +0 -1
  71. package/dist/esm/features/jserrors/aggregate/string-hash-code.js +0 -1
  72. package/dist/esm/features/metrics/aggregate/index.js +1 -1
  73. package/dist/esm/features/session_replay/aggregate/index.js +29 -16
  74. package/dist/esm/features/session_replay/shared/recorder-events.js +2 -0
  75. package/dist/esm/features/session_replay/shared/recorder.js +51 -5
  76. package/dist/esm/features/session_replay/shared/stylesheet-evaluator.js +93 -0
  77. package/dist/esm/features/session_trace/aggregate/index.js +0 -2
  78. package/dist/esm/features/spa/aggregate/interaction-node.js +0 -1
  79. package/dist/esm/features/utils/instrument-base.js +0 -1
  80. package/dist/esm/loaders/agent-base.js +62 -15
  81. package/dist/esm/loaders/agent.js +0 -38
  82. package/dist/types/features/session_replay/aggregate/index.d.ts +8 -3
  83. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  84. package/dist/types/features/session_replay/shared/recorder-events.d.ts +2 -0
  85. package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -1
  86. package/dist/types/features/session_replay/shared/recorder.d.ts +14 -1
  87. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  88. package/dist/types/features/session_replay/shared/stylesheet-evaluator.d.ts +22 -0
  89. package/dist/types/features/session_replay/shared/stylesheet-evaluator.d.ts.map +1 -0
  90. package/dist/types/loaders/agent-base.d.ts +48 -12
  91. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  92. package/dist/types/loaders/agent.d.ts +0 -33
  93. package/dist/types/loaders/agent.d.ts.map +1 -1
  94. package/package.json +49 -49
  95. package/src/common/harvest/harvest-scheduler.js +1 -1
  96. package/src/common/ids/__mocks__/bundle-id.js +1 -1
  97. package/src/common/ids/__mocks__/unique-id.js +2 -2
  98. package/src/features/metrics/aggregate/index.js +1 -1
  99. package/src/features/session_replay/aggregate/index.js +29 -16
  100. package/src/features/session_replay/shared/recorder-events.js +2 -0
  101. package/src/features/session_replay/shared/recorder.js +51 -6
  102. package/src/features/session_replay/shared/stylesheet-evaluator.js +89 -0
  103. package/src/loaders/agent-base.js +59 -15
  104. package/src/loaders/agent.js +0 -38
@@ -17,8 +17,8 @@ var _aggregateBase = require("../../utils/aggregate-base");
17
17
  var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
18
18
  var _firstPaint = require("../../../common/vitals/first-paint");
19
19
  var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
20
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
20
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
21
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
22
22
  class Aggregate extends _aggregateBase.AggregateBase {
23
23
  static featureName = CONSTANTS.FEATURE_NAME;
24
24
  constructor(agentIdentifier, aggregator) {
@@ -5,5 +5,4 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.FEATURE_NAME = void 0;
7
7
  var _features = require("../../loaders/features/features");
8
- const FEATURE_NAME = _features.FEATURE_NAMES.pageViewEvent;
9
- exports.FEATURE_NAME = FEATURE_NAME;
8
+ const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.pageViewEvent;
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.Instrument = void 0;
7
7
  var _instrumentBase = require("../../utils/instrument-base");
8
8
  var CONSTANTS = _interopRequireWildcard(require("../constants"));
9
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
10
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
9
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
10
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
11
11
  class Instrument extends _instrumentBase.InstrumentBase {
12
12
  static featureName = CONSTANTS.FEATURE_NAME;
13
13
  constructor(agentIdentifier, aggregator) {
@@ -5,5 +5,4 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.FEATURE_NAME = void 0;
7
7
  var _features = require("../../loaders/features/features");
8
- const FEATURE_NAME = _features.FEATURE_NAMES.pageViewTiming;
9
- exports.FEATURE_NAME = FEATURE_NAME;
8
+ const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.pageViewTiming;
@@ -20,18 +20,18 @@ var _env = require("../../../common/constants/env.npm");
20
20
  var _now = require("../../../common/timing/now");
21
21
  var _constants3 = require("../../../common/session/constants");
22
22
  var _stringify = require("../../../common/util/stringify");
23
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
24
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /*
25
- * Copyright 2023 New Relic Corporation. All rights reserved.
26
- * SPDX-License-Identifier: Apache-2.0
27
- */ /**
28
- * @file Records, aggregates, and harvests session replay data.
29
- *
30
- * NOTE: This code is under development and dormant. It will not download to instrumented pages or record any data.
31
- * It is not production ready, and is not intended to be imported or implemented in any build of the browser agent until
32
- * functionality is validated and a full user experience is curated.
33
- */
34
- let gzipper, u8;
23
+ var _stylesheetEvaluator = require("../shared/stylesheet-evaluator");
24
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
25
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /*
26
+ * Copyright 2023 New Relic Corporation. All rights reserved.
27
+ * SPDX-License-Identifier: Apache-2.0
28
+ */ /**
29
+ * @file Records, aggregates, and harvests session replay data.
30
+ *
31
+ * NOTE: This code is under development and dormant. It will not download to instrumented pages or record any data.
32
+ * It is not production ready, and is not intended to be imported or implemented in any build of the browser agent until
33
+ * functionality is validated and a full user experience is curated.
34
+ */
35
35
  class Aggregate extends _aggregateBase.AggregateBase {
36
36
  static featureName = _constants.FEATURE_NAME;
37
37
  // pass the recorder into the aggregator
@@ -43,8 +43,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
43
43
  this.initialized = false;
44
44
  /** Set once the feature has been "aborted" to prevent other side-effects from continuing */
45
45
  this.blocked = false;
46
- /** can shut off efforts to compress the data */
47
- this.shouldCompress = true;
46
+ /** populated with the gzipper lib async */
47
+ this.gzipper = undefined;
48
+ /** populated with the u8 string lib async */
49
+ this.u8 = undefined;
48
50
  /** the mode to start in. Defaults to off */
49
51
  const {
50
52
  session
@@ -91,6 +93,11 @@ class Aggregate extends _aggregateBase.AggregateBase {
91
93
  getPayload: this.prepareHarvest.bind(this),
92
94
  raw: true
93
95
  }, this);
96
+ if (this.recorder?.getEvents().type === 'preloaded') {
97
+ this.prepUtils().then(() => {
98
+ this.scheduler.runHarvest();
99
+ });
100
+ }
94
101
  (0, _registerHandler.registerHandler)('recordReplay', () => {
95
102
  // if it has aborted or BCS returned bad entitlements, do not allow
96
103
  if (this.blocked || !this.entitled) return;
@@ -195,24 +202,29 @@ class Aggregate extends _aggregateBase.AggregateBase {
195
202
  // We only report (harvest) in FULL mode
196
203
  this.scheduler.startTimer(this.harvestTimeSeconds);
197
204
  }
205
+ await this.prepUtils();
206
+ if (!this.recorder.recording) this.recorder.startRecording();
207
+ this.syncWithSessionManager({
208
+ sessionReplayMode: this.mode
209
+ });
210
+ }
211
+ async prepUtils() {
198
212
  try {
199
213
  // Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
200
214
  const {
201
215
  gzipSync,
202
216
  strToU8
203
217
  } = await Promise.resolve().then(() => _interopRequireWildcard(require( /* webpackChunkName: "compressor" */'fflate')));
204
- gzipper = gzipSync;
205
- u8 = strToU8;
218
+ this.gzipper = gzipSync;
219
+ this.u8 = strToU8;
206
220
  } catch (err) {
207
221
  // compressor failed to load, but we can still record without compression as a last ditch effort
208
- this.shouldCompress = false;
209
222
  }
210
- if (!this.recorder.recording) this.recorder.startRecording();
211
- this.syncWithSessionManager({
212
- sessionReplayMode: this.mode
213
- });
214
223
  }
215
224
  prepareHarvest() {
225
+ let {
226
+ opts
227
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
216
228
  if (!this.recorder) return;
217
229
  const recorderEvents = this.recorder.getEvents();
218
230
  // get the event type and use that to trigger another harvest if needed
@@ -223,8 +235,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
223
235
  return;
224
236
  }
225
237
  let len = 0;
226
- if (this.shouldCompress) {
227
- payload.body = gzipper(u8("[".concat(payload.body.map(e => e.__serialized).join(','), "]")));
238
+ if (!!this.gzipper && !!this.u8) {
239
+ payload.body = this.gzipper(this.u8("[".concat(payload.body.map(e => e.__serialized).join(','), "]")));
228
240
  len = payload.body.length;
229
241
  this.scheduler.opts.gzip = true;
230
242
  } else {
@@ -250,7 +262,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
250
262
  sessionReplaySentFirstChunk: true
251
263
  });
252
264
  this.recorder.clearBuffer();
253
- if (recorderEvents.type === 'preloaded') this.scheduler.runHarvest();
265
+ if (recorderEvents.type === 'preloaded') this.scheduler.runHarvest(opts);
254
266
  return [payload];
255
267
  }
256
268
  getHarvestContents(recorderEvents) {
@@ -281,7 +293,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
281
293
  const relativeNow = (0, _now.now)();
282
294
  const firstEventTimestamp = events[0]?.timestamp; // from rrweb node
283
295
  const lastEventTimestamp = events[events.length - 1]?.timestamp; // from rrweb node
284
- const firstTimestamp = firstEventTimestamp || recorderEvents.cycleTimestamp;
296
+ const firstTimestamp = firstEventTimestamp || recorderEvents.cycleTimestamp; // from rrweb node || from when the harvest cycle started
285
297
  const lastTimestamp = lastEventTimestamp || agentOffset + relativeNow;
286
298
  return {
287
299
  qs: {
@@ -292,7 +304,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
292
304
  attributes: (0, _encode.obj)({
293
305
  // this section of attributes must be controllable and stay below the query param padding limit -- see QUERY_PARAM_PADDING
294
306
  // if not, data could be lost to truncation at time of sending, potentially breaking parsing / API behavior in NR1
295
- ...(this.shouldCompress && {
307
+ ...(!!this.gzipper && !!this.u8 && {
296
308
  content_encoding: 'gzip'
297
309
  }),
298
310
  'replay.firstTimestamp': firstTimestamp,
@@ -309,6 +321,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
309
321
  hasError: recorderEvents.hasError || false,
310
322
  isFirstChunk: agentRuntime.session.state.sessionReplaySentFirstChunk === false,
311
323
  decompressedBytes: recorderEvents.payloadBytesEstimation,
324
+ invalidStylesheetsDetected: _stylesheetEvaluator.stylesheetEvaluator.invalidStylesheetsDetected,
325
+ inlinedAllStylesheets: recorderEvents.inlinedAllStylesheets,
312
326
  'rrweb.version': _env.RRWEB_VERSION,
313
327
  // customer-defined data should go last so that if it exceeds the query param padding limit it will be truncated instead of important attrs
314
328
  ...(endUserId && {
@@ -317,7 +331,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
317
331
  // The Query Param is being arbitrarily limited in length here. It is also applied when estimating the size of the payload in getPayloadSize()
318
332
  }, _constants.QUERY_PARAM_PADDING).substring(1) // remove the leading '&'
319
333
  },
320
-
321
334
  body: events
322
335
  };
323
336
  }
@@ -6,11 +6,9 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.RRWEB_EVENT_TYPES = exports.QUERY_PARAM_PADDING = exports.MAX_PAYLOAD_SIZE = exports.IDEAL_PAYLOAD_SIZE = exports.FEATURE_NAME = exports.CHECKOUT_MS = exports.AVG_COMPRESSION = exports.ABORT_REASONS = void 0;
7
7
  var _constants = require("../../common/session/constants");
8
8
  var _features = require("../../loaders/features/features");
9
- const FEATURE_NAME = _features.FEATURE_NAMES.sessionReplay;
10
- exports.FEATURE_NAME = FEATURE_NAME;
11
- const AVG_COMPRESSION = 0.12;
12
- exports.AVG_COMPRESSION = AVG_COMPRESSION;
13
- const RRWEB_EVENT_TYPES = {
9
+ const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.sessionReplay;
10
+ const AVG_COMPRESSION = exports.AVG_COMPRESSION = 0.12;
11
+ const RRWEB_EVENT_TYPES = exports.RRWEB_EVENT_TYPES = {
14
12
  DomContentLoaded: 0,
15
13
  Load: 1,
16
14
  FullSnapshot: 2,
@@ -19,20 +17,16 @@ const RRWEB_EVENT_TYPES = {
19
17
  Custom: 5
20
18
  };
21
19
  /** Vortex caps payload sizes at 1MB */
22
- exports.RRWEB_EVENT_TYPES = RRWEB_EVENT_TYPES;
23
- const MAX_PAYLOAD_SIZE = 1000000;
20
+ const MAX_PAYLOAD_SIZE = exports.MAX_PAYLOAD_SIZE = 1000000;
24
21
  /** Unloading caps around 64kb */
25
- exports.MAX_PAYLOAD_SIZE = MAX_PAYLOAD_SIZE;
26
- const IDEAL_PAYLOAD_SIZE = 64000;
22
+ const IDEAL_PAYLOAD_SIZE = exports.IDEAL_PAYLOAD_SIZE = 64000;
27
23
  /** Interval between forcing new full snapshots -- 15 seconds in error mode (x2), 5 minutes in full mode */
28
- exports.IDEAL_PAYLOAD_SIZE = IDEAL_PAYLOAD_SIZE;
29
- const CHECKOUT_MS = {
24
+ const CHECKOUT_MS = exports.CHECKOUT_MS = {
30
25
  [_constants.MODE.ERROR]: 15000,
31
26
  [_constants.MODE.FULL]: 300000,
32
27
  [_constants.MODE.OFF]: 0
33
28
  };
34
- exports.CHECKOUT_MS = CHECKOUT_MS;
35
- const ABORT_REASONS = {
29
+ const ABORT_REASONS = exports.ABORT_REASONS = {
36
30
  RESET: {
37
31
  message: 'Session was reset',
38
32
  sm: 'Reset'
@@ -59,6 +53,4 @@ const ABORT_REASONS = {
59
53
  }
60
54
  };
61
55
  /** Reserved room for query param attrs */
62
- exports.ABORT_REASONS = ABORT_REASONS;
63
- const QUERY_PARAM_PADDING = 5000;
64
- exports.QUERY_PARAM_PADDING = QUERY_PARAM_PADDING;
56
+ const QUERY_PARAM_PADDING = exports.QUERY_PARAM_PADDING = 5000;
@@ -7,17 +7,17 @@ exports.Instrument = void 0;
7
7
  var _constants = require("../../../common/session/constants");
8
8
  var _instrumentBase = require("../../utils/instrument-base");
9
9
  var _constants2 = require("../constants");
10
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
11
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /*
12
- * Copyright 2023 New Relic Corporation. All rights reserved.
13
- * SPDX-License-Identifier: Apache-2.0
14
- */ /**
15
- * @file Primes the Session Replay feature for lazy loading.
16
- *
17
- * NOTE: This code is under development and dormant. It will not download to instrumented pages or record any data.
18
- * It is not production ready, and is not intended to be imported or implemented in any build of the browser agent until
19
- * functionality is validated and a full user experience is curated.
20
- */
10
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /*
12
+ * Copyright 2023 New Relic Corporation. All rights reserved.
13
+ * SPDX-License-Identifier: Apache-2.0
14
+ */ /**
15
+ * @file Primes the Session Replay feature for lazy loading.
16
+ *
17
+ * NOTE: This code is under development and dormant. It will not download to instrumented pages or record any data.
18
+ * It is not production ready, and is not intended to be imported or implemented in any build of the browser agent until
19
+ * functionality is validated and a full user experience is curated.
20
+ */
21
21
  class Instrument extends _instrumentBase.InstrumentBase {
22
22
  static featureName = _constants2.FEATURE_NAME;
23
23
  constructor(agentIdentifier, aggregator) {
@@ -23,6 +23,8 @@ class RecorderEvents {
23
23
  this.hasMeta = false;
24
24
  /** Payload metadata -- Should indicate that the payload being sent contains an error. Used for query/filter purposes in UI */
25
25
  this.hasError = false;
26
+ /** Payload metadata -- Denotes whether all stylesheet elements were able to be inlined */
27
+ this.inlinedAllStylesheets = true;
26
28
  }
27
29
  add(event) {
28
30
  this.events.push(event);
@@ -10,6 +10,10 @@ var _constants = require("../constants");
10
10
  var _config = require("../../../common/config/config");
11
11
  var _recorderEvents = require("./recorder-events");
12
12
  var _constants2 = require("../../../common/session/constants");
13
+ var _stylesheetEvaluator = require("./stylesheet-evaluator");
14
+ var _handle = require("../../../common/event-emitter/handle");
15
+ var _constants3 = require("../../metrics/constants");
16
+ var _features = require("../../../loaders/features/features");
13
17
  class Recorder {
14
18
  /** Each page mutation or event will be stored (raw) in this array. This array will be cleared on each harvest */
15
19
  #events = new _recorderEvents.RecorderEvents();
@@ -17,14 +21,21 @@ class Recorder {
17
21
  #backloggedEvents = new _recorderEvents.RecorderEvents();
18
22
  /** array of recorder events -- Will be filled only if forced harvest was triggered and harvester does not exist */
19
23
  #preloaded = [new _recorderEvents.RecorderEvents()];
24
+ /** flag that if true, blocks events from being "stored". Only set to true when a full snapshot has incomplete nodes (only stylesheets ATM) */
25
+ #fixing = false;
20
26
  constructor(parent) {
21
27
  /** True when actively recording, false when paused or stopped */
22
28
  this.recording = false;
29
+ /** The pointer to the current bucket holding rrweb events */
23
30
  this.currentBufferTarget = this.#events;
24
31
  /** Hold on to the last meta node, so that it can be re-inserted if the meta and snapshot nodes are broken up due to harvesting */
25
32
  this.lastMeta = false;
33
+ /** The parent class that instantiated the recorder */
26
34
  this.parent = parent;
27
-
35
+ /** Config to inform to inline stylesheet contents (true default) */
36
+ this.shouldInlineStylesheets = (0, _config.getConfigurationValue)(this.parent.agentIdentifier, 'session_replay.inline_stylesheet');
37
+ /** A flag that can be set to false by failing conversions to stop the fetching process */
38
+ this.shouldFix = this.shouldInlineStylesheets;
28
39
  /** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
29
40
  this.stopRecording = () => {/* no-op until set by rrweb initializer */};
30
41
  }
@@ -40,7 +51,8 @@ class Recorder {
40
51
  payloadBytesEstimation: this.#backloggedEvents.payloadBytesEstimation + this.#events.payloadBytesEstimation,
41
52
  hasError: this.#backloggedEvents.hasError || this.#events.hasError,
42
53
  hasMeta: this.#backloggedEvents.hasMeta || this.#events.hasMeta,
43
- hasSnapshot: this.#backloggedEvents.hasSnapshot || this.#events.hasSnapshot
54
+ hasSnapshot: this.#backloggedEvents.hasSnapshot || this.#events.hasSnapshot,
55
+ inlinedAllStylesheets: !!this.#backloggedEvents.events.length && this.#backloggedEvents.inlinedAllStylesheets || this.#events.inlinedAllStylesheets
44
56
  };
45
57
  }
46
58
 
@@ -68,7 +80,7 @@ class Recorder {
68
80
  // set up rrweb configurations for maximum privacy --
69
81
  // https://newrelic.atlassian.net/wiki/spaces/O11Y/pages/2792293280/2023+02+28+Browser+-+Session+Replay#Configuration-options
70
82
  const stop = (0, _rrweb.record)({
71
- emit: this.store.bind(this),
83
+ emit: this.audit.bind(this),
72
84
  blockClass: block_class,
73
85
  ignoreClass: ignore_class,
74
86
  maskTextClass: mask_text_class,
@@ -87,10 +99,44 @@ class Recorder {
87
99
  };
88
100
  }
89
101
 
102
+ /**
103
+ * audit - Checks if the event node payload is missing certain attributes
104
+ * will forward on to the "store" method if nothing needs async fixing
105
+ * @param {*} event - An RRWEB event node
106
+ * @param {*} isCheckout - Flag indicating if the payload was triggered as a checkout
107
+ */
108
+ audit(event, isCheckout) {
109
+ /** only run the audit if inline_stylesheets is configured as on (default behavior) */
110
+ if (this.shouldInlineStylesheets === false || !this.shouldFix) {
111
+ this.currentBufferTarget.inlinedAllStylesheets = false;
112
+ return this.store(event, isCheckout);
113
+ }
114
+ /** An count of stylesheet objects that were blocked from accessing contents via JS */
115
+ const incompletes = _stylesheetEvaluator.stylesheetEvaluator.evaluate();
116
+ /** Only stop ignoring data if already ignoring and a new valid snapshap is taking place (0 incompletes and we get a meta node for the snap) */
117
+ if (!incompletes && this.#fixing && event.type === _constants.RRWEB_EVENT_TYPES.Meta) this.#fixing = false;
118
+ if (incompletes) {
119
+ (0, _handle.handle)(_constants3.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css', incompletes], undefined, _features.FEATURE_NAMES.metrics, this.parent.ee);
120
+ /** wait for the evaluator to download/replace the incompletes' src code and then take a new snap */
121
+ _stylesheetEvaluator.stylesheetEvaluator.fix().then(failedToFix => {
122
+ if (failedToFix) {
123
+ this.currentBufferTarget.inlinedAllStylesheets = false;
124
+ this.shouldFix = false;
125
+ }
126
+ this.takeFullSnapshot();
127
+ });
128
+ /** Only start ignoring data if got a faulty snapshot */
129
+ if (event.type === _constants.RRWEB_EVENT_TYPES.FullSnapshot || event.type === _constants.RRWEB_EVENT_TYPES.Meta) this.#fixing = true;
130
+ }
131
+ /** Only store the data if not being "fixed" (full snapshots that have broken css) */
132
+ if (!this.#fixing) this.store(event, isCheckout);
133
+ }
134
+
90
135
  /** Store a payload in the buffer (this.#events). This should be the callback to the recording lib noticing a mutation */
91
136
  store(event, isCheckout) {
137
+ if (!event) return;
92
138
  event.__serialized = (0, _stringify.stringify)(event);
93
- if (!this.parent.scheduler) this.currentBufferTarget = this.#preloaded[this.#preloaded.length - 1];else this.currentBufferTarget = this.#events;
139
+ if (!this.parent.scheduler && this.#preloaded.length) this.currentBufferTarget = this.#preloaded[this.#preloaded.length - 1];else this.currentBufferTarget = this.#events;
94
140
  if (this.parent.blocked) return;
95
141
  const eventBytes = event.__serialized.length;
96
142
  /** The estimated size of the payload after compression */
@@ -148,7 +194,7 @@ class Recorder {
148
194
  * https://staging.onenr.io/037jbJWxbjy
149
195
  * */
150
196
  estimateCompression(data) {
151
- if (this.shouldCompress) return data * _constants.AVG_COMPRESSION;
197
+ if (!!this.parent.gzipper && !!this.parent.u8) return data * _constants.AVG_COMPRESSION;
152
198
  return data;
153
199
  }
154
200
  }
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.stylesheetEvaluator = void 0;
7
+ var _config = require("../../../common/config/config");
8
+ var _runtime = require("../../../common/constants/runtime");
9
+ class StylesheetEvaluator {
10
+ #evaluated = new WeakSet();
11
+ #fetchProms = [];
12
+ /**
13
+ * Flipped to true if stylesheets that cannot be natively inlined are detected by the stylesheetEvaluator class
14
+ * Used at harvest time to denote that all subsequent payloads are subject to this and customers should be advised to handle crossorigin decoration
15
+ * */
16
+ invalidStylesheetsDetected = false;
17
+ failedToFix = false;
18
+
19
+ /**
20
+ * this works by checking (only ever once) each cssRules obj in the style sheets array. The try/catch will catch an error if the cssRules obj blocks access, triggering the module to try to "fix" the asset`. Returns the count of incomplete assets discovered.
21
+ * @returns {Number}
22
+ */
23
+ evaluate() {
24
+ let incompletes = 0;
25
+ if (_runtime.isBrowserScope) {
26
+ for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
27
+ const ss = document.styleSheets[i];
28
+ if (!this.#evaluated.has(ss)) {
29
+ this.#evaluated.add(ss);
30
+ try {
31
+ // eslint-disable-next-line
32
+ const temp = ss.cssRules;
33
+ } catch (err) {
34
+ incompletes++;
35
+ this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i], ss.href));
36
+ }
37
+ }
38
+ }
39
+ }
40
+ if (incompletes) this.invalidStylesheetsDetected = true;
41
+ return incompletes;
42
+ }
43
+
44
+ /**
45
+ * Resolves promise once all stylesheets have been fetched and overridden
46
+ * @returns {Promise}
47
+ */
48
+ async fix() {
49
+ await Promise.all(this.#fetchProms);
50
+ this.#fetchProms = [];
51
+ const failedToFix = this.failedToFix;
52
+ this.failedToFix = false;
53
+ return failedToFix;
54
+ }
55
+
56
+ /**
57
+ * Fetches stylesheet contents and overrides the target getters
58
+ * @param {*} target - The stylesheet object target - ex. document.styleSheets[0]
59
+ * @param {*} href - The asset href to fetch
60
+ * @returns {Promise}
61
+ */
62
+ async #fetchAndOverride(target, href) {
63
+ try {
64
+ const stylesheetContents = await _config.originals.FETCH.bind(window)(href);
65
+ if (!stylesheetContents.ok) {
66
+ this.failedToFix = true;
67
+ return;
68
+ }
69
+ const stylesheetText = await stylesheetContents.text();
70
+ try {
71
+ const cssSheet = new CSSStyleSheet();
72
+ await cssSheet.replace(stylesheetText);
73
+ Object.defineProperty(target, 'cssRules', {
74
+ get() {
75
+ return cssSheet.cssRules;
76
+ }
77
+ });
78
+ Object.defineProperty(target, 'rules', {
79
+ get() {
80
+ return cssSheet.rules;
81
+ }
82
+ });
83
+ } catch (err) {
84
+ // cant make new dynamic stylesheets, browser likely doesn't support `.replace()`...
85
+ // this is appended in prep of forking rrweb
86
+ Object.defineProperty(target, 'cssText', {
87
+ get() {
88
+ return stylesheetText;
89
+ }
90
+ });
91
+ this.failedToFix = true;
92
+ }
93
+ } catch (err) {
94
+ // failed to fetch
95
+ this.failedToFix = true;
96
+ }
97
+ }
98
+ }
99
+ const stylesheetEvaluator = exports.stylesheetEvaluator = new StylesheetEvaluator();
@@ -251,7 +251,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
251
251
  }); // sends first stn harvest immediately
252
252
  startupBuffer.decide(true); // signal to ALLOW & process data in EE's buffer into internal nodes queued for next harvest
253
253
  }
254
-
255
254
  #onHarvestFinished(result) {
256
255
  if (result.sent && result.responseText && !this.ptid) {
257
256
  // continue interval harvest only if ptid was returned by server on the first
@@ -290,7 +289,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
290
289
  if (currentMode === _constants2.MODE.OFF && Object.keys(this.trace).length === 0) return;
291
290
  if (currentMode === _constants2.MODE.ERROR) return; // Trace in this mode should never be harvesting, even on unload
292
291
  }
293
-
294
292
  return this.takeSTNs(options.retry);
295
293
  }
296
294
 
@@ -5,19 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.START = exports.RESOURCE = exports.PUSH_STATE = exports.FN_START = exports.FN_END = exports.FEATURE_NAME = exports.END = exports.BST_RESOURCE = void 0;
7
7
  var _features = require("../../loaders/features/features");
8
- const FEATURE_NAME = _features.FEATURE_NAMES.sessionTrace;
9
- exports.FEATURE_NAME = FEATURE_NAME;
10
- const BST_RESOURCE = 'bstResource';
11
- exports.BST_RESOURCE = BST_RESOURCE;
12
- const RESOURCE = 'resource';
13
- exports.RESOURCE = RESOURCE;
14
- const START = '-start';
15
- exports.START = START;
16
- const END = '-end';
17
- exports.END = END;
18
- const FN_START = 'fn' + START;
19
- exports.FN_START = FN_START;
20
- const FN_END = 'fn' + END;
21
- exports.FN_END = FN_END;
22
- const PUSH_STATE = 'pushState';
23
- exports.PUSH_STATE = PUSH_STATE;
8
+ const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.sessionTrace;
9
+ const BST_RESOURCE = exports.BST_RESOURCE = 'bstResource';
10
+ const RESOURCE = exports.RESOURCE = 'resource';
11
+ const START = exports.START = '-start';
12
+ const END = exports.END = '-end';
13
+ const FN_START = exports.FN_START = 'fn' + START;
14
+ const FN_END = exports.FN_END = 'fn' + END;
15
+ const PUSH_STATE = exports.PUSH_STATE = 'pushState';
@@ -11,8 +11,8 @@ var _instrumentBase = require("../../utils/instrument-base");
11
11
  var CONSTANTS = _interopRequireWildcard(require("../constants"));
12
12
  var _features = require("../../../loaders/features/features");
13
13
  var _runtime = require("../../../common/constants/runtime");
14
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
15
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
16
  /*
17
17
  * Copyright 2020 New Relic Corporation. All rights reserved.
18
18
  * SPDX-License-Identifier: Apache-2.0
@@ -25,8 +25,8 @@ var _bundleId = require("../../../common/ids/bundle-id");
25
25
  var _runtime = require("../../../common/constants/runtime");
26
26
  var _handle = require("../../../common/event-emitter/handle");
27
27
  var _constants2 = require("../../metrics/constants");
28
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
29
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
28
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
29
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
30
30
  /*
31
31
  * Copyright 2020 New Relic Corporation. All rights reserved.
32
32
  * SPDX-License-Identifier: Apache-2.0
@@ -16,7 +16,6 @@ function InteractionNode(interaction, parent, type, timestamp) {
16
16
  value: interaction,
17
17
  writable: true // enumerable: false -- by default, which hides this prop from obj (iterations)
18
18
  });
19
-
20
19
  this.parent = parent;
21
20
  this.id = ++lastId;
22
21
  this.type = type;