mixpanel-browser 2.76.0 → 2.77.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 (49) hide show
  1. package/.github/dependabot.yml +8 -0
  2. package/.github/workflows/integration-tests.yml +2 -2
  3. package/.github/workflows/unit-tests.yml +2 -2
  4. package/CHANGELOG.md +4 -0
  5. package/dist/async-modules/{mixpanel-recorder-bIS4LMGd.js → mixpanel-recorder-DLKbUIEE.js} +84 -10
  6. package/dist/async-modules/mixpanel-recorder-wIWnMDLA.min.js +2 -0
  7. package/dist/async-modules/mixpanel-recorder-wIWnMDLA.min.js.map +1 -0
  8. package/dist/async-modules/{mixpanel-targeting-VOeN7RWY.min.js → mixpanel-targeting-CTcftSJC.min.js} +2 -2
  9. package/dist/async-modules/{mixpanel-targeting-VOeN7RWY.min.js.map → mixpanel-targeting-CTcftSJC.min.js.map} +1 -1
  10. package/dist/async-modules/{mixpanel-targeting-BcAPS-Mz.js → mixpanel-targeting-CmVvUyFM.js} +1 -1
  11. package/dist/mixpanel-core.cjs.d.ts +2 -1
  12. package/dist/mixpanel-core.cjs.js +183 -52
  13. package/dist/mixpanel-recorder.js +84 -10
  14. package/dist/mixpanel-recorder.min.js +1 -1
  15. package/dist/mixpanel-recorder.min.js.map +1 -1
  16. package/dist/mixpanel-targeting.js +1 -1
  17. package/dist/mixpanel-targeting.min.js +1 -1
  18. package/dist/mixpanel-targeting.min.js.map +1 -1
  19. package/dist/mixpanel-with-async-modules.cjs.d.ts +2 -1
  20. package/dist/mixpanel-with-async-modules.cjs.js +185 -54
  21. package/dist/mixpanel-with-async-recorder.cjs.d.ts +2 -1
  22. package/dist/mixpanel-with-async-recorder.cjs.js +185 -54
  23. package/dist/mixpanel-with-recorder.d.ts +2 -1
  24. package/dist/mixpanel-with-recorder.js +272 -90
  25. package/dist/mixpanel-with-recorder.min.d.ts +2 -1
  26. package/dist/mixpanel-with-recorder.min.js +1 -1
  27. package/dist/mixpanel.amd.d.ts +2 -1
  28. package/dist/mixpanel.amd.js +272 -90
  29. package/dist/mixpanel.cjs.d.ts +2 -1
  30. package/dist/mixpanel.cjs.js +272 -90
  31. package/dist/mixpanel.globals.js +185 -54
  32. package/dist/mixpanel.min.js +190 -186
  33. package/dist/mixpanel.module.d.ts +2 -1
  34. package/dist/mixpanel.module.js +272 -90
  35. package/dist/mixpanel.umd.d.ts +2 -1
  36. package/dist/mixpanel.umd.js +272 -90
  37. package/dist/rrweb-bundled.js +61 -9
  38. package/dist/rrweb-compiled.js +56 -9
  39. package/package.json +6 -5
  40. package/src/config.js +1 -1
  41. package/src/index.d.ts +2 -1
  42. package/src/mixpanel-core.js +1 -1
  43. package/src/recorder/session-recording.js +5 -1
  44. package/src/recorder/utils.js +27 -1
  45. package/src/recorder-manager.js +110 -2
  46. package/testServer.js +14 -1
  47. package/dist/async-modules/mixpanel-recorder-hFoTniVR.min.js +0 -2
  48. package/dist/async-modules/mixpanel-recorder-hFoTniVR.min.js.map +0 -1
  49. /package/src/loaders/{loader-module-with-async-recorder.d.ts → loader-module-with-async-modules.d.ts} +0 -0
@@ -28,7 +28,7 @@
28
28
 
29
29
  var Config = {
30
30
  DEBUG: false,
31
- LIB_VERSION: '2.76.0'
31
+ LIB_VERSION: '2.77.0'
32
32
  };
33
33
 
34
34
  // Window global names for async modules
@@ -10736,13 +10736,7 @@
10736
10736
  };
10737
10737
  while(_this.mapRemoves.length){
10738
10738
  var removedNode = _this.mapRemoves.shift();
10739
- if (removedNode.nodeName === "IFRAME") {
10740
- try {
10741
- _this.iframeManager.removeIframe(removedNode);
10742
- } catch (e2) {}
10743
- } else {
10744
- _this.stylesheetManager.cleanupStylesheetsForRemovedNode(removedNode);
10745
- }
10739
+ _this.cleanupRemovedNode(removedNode);
10746
10740
  _this.mirror.removeNodeFromMap(removedNode);
10747
10741
  }
10748
10742
  for(var _iterator = _create_for_of_iterator_helper_loose(_this.movedSet), _step; !(_step = _iterator()).done;){
@@ -11062,6 +11056,20 @@
11062
11056
  }
11063
11057
  }
11064
11058
  });
11059
+ __publicField$1(this, "cleanupRemovedNode", function(node2) {
11060
+ if (node2.nodeName === "IFRAME") {
11061
+ try {
11062
+ _this.iframeManager.removeIframe(node2);
11063
+ } catch (e2) {}
11064
+ } else {
11065
+ try {
11066
+ _this.stylesheetManager.cleanupStylesheetsForRemovedNode(node2);
11067
+ } catch (e2) {}
11068
+ }
11069
+ node2.childNodes.forEach(function(child) {
11070
+ _this.cleanupRemovedNode(child);
11071
+ });
11072
+ });
11065
11073
  }
11066
11074
  var _proto = MutationBuffer.prototype;
11067
11075
  _proto.init = function init(options) {
@@ -13289,6 +13297,31 @@
13289
13297
  _proto.destroy = function destroy() {};
13290
13298
  return ProcessedNodeManager;
13291
13299
  }();
13300
+ function toOrigin(url) {
13301
+ try {
13302
+ var origin = new URL(url).origin;
13303
+ return origin !== "null" ? origin : null;
13304
+ } catch (e) {
13305
+ return null;
13306
+ }
13307
+ }
13308
+ function buildAllowedOriginSet(origins) {
13309
+ if (!Array.isArray(origins) || origins.length === 0) {
13310
+ throw new Error("[rrweb] allowedIframeOrigins must be a non-empty array of origin strings.");
13311
+ }
13312
+ var set = /* @__PURE__ */ new Set();
13313
+ for(var i2 = 0; i2 < origins.length; i2++){
13314
+ var entry = origins[i2];
13315
+ if (typeof entry !== "string") {
13316
+ throw new Error("[rrweb] allowedIframeOrigins[" + i2 + "] must be a string, got " + (typeof entry === "undefined" ? "undefined" : _type_of(entry)) + ".");
13317
+ }
13318
+ var origin = toOrigin(entry);
13319
+ if (origin) {
13320
+ set.add(origin);
13321
+ }
13322
+ }
13323
+ return Object.freeze(set);
13324
+ }
13292
13325
  var wrappedEmit;
13293
13326
  var takeFullSnapshot$1;
13294
13327
  var canvasManager;
@@ -13310,10 +13343,17 @@
13310
13343
  var mirror = createMirror$2();
13311
13344
  function record(options) {
13312
13345
  if (options === void 0) options = {};
13313
- var emit = options.emit, checkoutEveryNms = options.checkoutEveryNms, checkoutEveryNth = options.checkoutEveryNth, _options_blockClass = options.blockClass, blockClass = _options_blockClass === void 0 ? "rr-block" : _options_blockClass, _options_blockSelector = options.blockSelector, blockSelector = _options_blockSelector === void 0 ? null : _options_blockSelector, _options_ignoreClass = options.ignoreClass, ignoreClass = _options_ignoreClass === void 0 ? "rr-ignore" : _options_ignoreClass, _options_ignoreSelector = options.ignoreSelector, ignoreSelector = _options_ignoreSelector === void 0 ? null : _options_ignoreSelector, _options_maskTextClass = options.maskTextClass, maskTextClass = _options_maskTextClass === void 0 ? "rr-mask" : _options_maskTextClass, _options_maskTextSelector = options.maskTextSelector, maskTextSelector = _options_maskTextSelector === void 0 ? null : _options_maskTextSelector, _options_inlineStylesheet = options.inlineStylesheet, inlineStylesheet = _options_inlineStylesheet === void 0 ? true : _options_inlineStylesheet, maskAllInputs = options.maskAllInputs, _maskInputOptions = options.maskInputOptions, _slimDOMOptions = options.slimDOMOptions, maskInputFn = options.maskInputFn, maskTextFn = options.maskTextFn, hooks = options.hooks, packFn = options.packFn, _options_sampling = options.sampling, sampling = _options_sampling === void 0 ? {} : _options_sampling, _options_dataURLOptions = options.dataURLOptions, dataURLOptions = _options_dataURLOptions === void 0 ? {} : _options_dataURLOptions, mousemoveWait = options.mousemoveWait, _options_recordDOM = options.recordDOM, recordDOM = _options_recordDOM === void 0 ? true : _options_recordDOM, _options_recordCanvas = options.recordCanvas, recordCanvas = _options_recordCanvas === void 0 ? false : _options_recordCanvas, _options_recordCrossOriginIframes = options.recordCrossOriginIframes, recordCrossOriginIframes = _options_recordCrossOriginIframes === void 0 ? false : _options_recordCrossOriginIframes, _options_recordAfter = options.recordAfter, recordAfter = _options_recordAfter === void 0 ? options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load" : _options_recordAfter, _options_userTriggeredOnInput = options.userTriggeredOnInput, userTriggeredOnInput = _options_userTriggeredOnInput === void 0 ? false : _options_userTriggeredOnInput, _options_collectFonts = options.collectFonts, collectFonts = _options_collectFonts === void 0 ? false : _options_collectFonts, _options_inlineImages = options.inlineImages, inlineImages = _options_inlineImages === void 0 ? false : _options_inlineImages, plugins = options.plugins, _options_keepIframeSrcFn = options.keepIframeSrcFn, keepIframeSrcFn = _options_keepIframeSrcFn === void 0 ? function() {
13346
+ var emit = options.emit, checkoutEveryNms = options.checkoutEveryNms, checkoutEveryNth = options.checkoutEveryNth, _options_blockClass = options.blockClass, blockClass = _options_blockClass === void 0 ? "rr-block" : _options_blockClass, _options_blockSelector = options.blockSelector, blockSelector = _options_blockSelector === void 0 ? null : _options_blockSelector, _options_ignoreClass = options.ignoreClass, ignoreClass = _options_ignoreClass === void 0 ? "rr-ignore" : _options_ignoreClass, _options_ignoreSelector = options.ignoreSelector, ignoreSelector = _options_ignoreSelector === void 0 ? null : _options_ignoreSelector, _options_maskTextClass = options.maskTextClass, maskTextClass = _options_maskTextClass === void 0 ? "rr-mask" : _options_maskTextClass, _options_maskTextSelector = options.maskTextSelector, maskTextSelector = _options_maskTextSelector === void 0 ? null : _options_maskTextSelector, _options_inlineStylesheet = options.inlineStylesheet, inlineStylesheet = _options_inlineStylesheet === void 0 ? true : _options_inlineStylesheet, maskAllInputs = options.maskAllInputs, _maskInputOptions = options.maskInputOptions, _slimDOMOptions = options.slimDOMOptions, maskInputFn = options.maskInputFn, maskTextFn = options.maskTextFn, hooks = options.hooks, packFn = options.packFn, _options_sampling = options.sampling, sampling = _options_sampling === void 0 ? {} : _options_sampling, _options_dataURLOptions = options.dataURLOptions, dataURLOptions = _options_dataURLOptions === void 0 ? {} : _options_dataURLOptions, mousemoveWait = options.mousemoveWait, _options_recordDOM = options.recordDOM, recordDOM = _options_recordDOM === void 0 ? true : _options_recordDOM, _options_recordCanvas = options.recordCanvas, recordCanvas = _options_recordCanvas === void 0 ? false : _options_recordCanvas, _options_recordCrossOriginIframes = options.recordCrossOriginIframes, recordCrossOriginIframes = _options_recordCrossOriginIframes === void 0 ? false : _options_recordCrossOriginIframes, allowedIframeOrigins = options.allowedIframeOrigins, _options_recordAfter = options.recordAfter, recordAfter = _options_recordAfter === void 0 ? options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load" : _options_recordAfter, _options_userTriggeredOnInput = options.userTriggeredOnInput, userTriggeredOnInput = _options_userTriggeredOnInput === void 0 ? false : _options_userTriggeredOnInput, _options_collectFonts = options.collectFonts, collectFonts = _options_collectFonts === void 0 ? false : _options_collectFonts, _options_inlineImages = options.inlineImages, inlineImages = _options_inlineImages === void 0 ? false : _options_inlineImages, plugins = options.plugins, _options_keepIframeSrcFn = options.keepIframeSrcFn, keepIframeSrcFn = _options_keepIframeSrcFn === void 0 ? function() {
13314
13347
  return false;
13315
13348
  } : _options_keepIframeSrcFn, _options_ignoreCSSAttributes = options.ignoreCSSAttributes, ignoreCSSAttributes = _options_ignoreCSSAttributes === void 0 ? /* @__PURE__ */ new Set([]) : _options_ignoreCSSAttributes, errorHandler2 = options.errorHandler;
13316
13349
  registerErrorHandler(errorHandler2);
13350
+ var validatedOrigins;
13351
+ if (recordCrossOriginIframes && allowedIframeOrigins && allowedIframeOrigins.length > 0) {
13352
+ validatedOrigins = buildAllowedOriginSet(allowedIframeOrigins);
13353
+ if (validatedOrigins.size === 0) {
13354
+ validatedOrigins = void 0;
13355
+ }
13356
+ }
13317
13357
  var inEmittingFrame = recordCrossOriginIframes ? window.parent === window : true;
13318
13358
  var passEmitsToParent = false;
13319
13359
  if (!inEmittingFrame) {
@@ -13405,7 +13445,14 @@
13405
13445
  origin: window.location.origin,
13406
13446
  isCheckout: isCheckout
13407
13447
  };
13408
- window.parent.postMessage(message, "*");
13448
+ if (validatedOrigins) {
13449
+ for(var _iterator = _create_for_of_iterator_helper_loose(validatedOrigins), _step; !(_step = _iterator()).done;){
13450
+ var targetOrigin = _step.value;
13451
+ window.parent.postMessage(message, targetOrigin);
13452
+ }
13453
+ } else {
13454
+ window.parent.postMessage(message, "*");
13455
+ }
13409
13456
  }
13410
13457
  if (e2.type === EventType.FullSnapshot) {
13411
13458
  lastFullSnapshotEvent = e2;
@@ -21189,7 +21236,7 @@
21189
21236
  };
21190
21237
  }
21191
21238
 
21192
- var logger$7 = console_with_prefix('lock');
21239
+ var logger$8 = console_with_prefix('lock');
21193
21240
 
21194
21241
  /**
21195
21242
  * SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
@@ -21241,7 +21288,7 @@
21241
21288
 
21242
21289
  var delay = function(cb) {
21243
21290
  if (new Date().getTime() - startTime > timeoutMS) {
21244
- logger$7.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
21291
+ logger$8.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
21245
21292
  storage.removeItem(keyZ);
21246
21293
  storage.removeItem(keyY);
21247
21294
  loop();
@@ -21388,7 +21435,7 @@
21388
21435
  }, this));
21389
21436
  };
21390
21437
 
21391
- var logger$6 = console_with_prefix('batch');
21438
+ var logger$7 = console_with_prefix('batch');
21392
21439
 
21393
21440
  /**
21394
21441
  * RequestQueue: queue for batching API requests with localStorage backup for retries.
@@ -21417,7 +21464,7 @@
21417
21464
  timeoutMS: options.sharedLockTimeoutMS,
21418
21465
  });
21419
21466
  }
21420
- this.reportError = options.errorReporter || _.bind(logger$6.error, logger$6);
21467
+ this.reportError = options.errorReporter || _.bind(logger$7.error, logger$7);
21421
21468
 
21422
21469
  this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
21423
21470
 
@@ -21750,7 +21797,7 @@
21750
21797
  // maximum interval between request retries after exponential backoff
21751
21798
  var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
21752
21799
 
21753
- var logger$5 = console_with_prefix('batch');
21800
+ var logger$6 = console_with_prefix('batch');
21754
21801
 
21755
21802
  /**
21756
21803
  * RequestBatcher: manages the queueing, flushing, retry etc of requests of one
@@ -21878,7 +21925,7 @@
21878
21925
  */
21879
21926
  RequestBatcher.prototype.flush = function(options) {
21880
21927
  if (this.requestInProgress) {
21881
- logger$5.log('Flush: Request already in progress');
21928
+ logger$6.log('Flush: Request already in progress');
21882
21929
  return PromisePolyfill.resolve();
21883
21930
  }
21884
21931
 
@@ -22055,7 +22102,7 @@
22055
22102
  if (options.unloading) {
22056
22103
  requestOptions.transport = 'sendBeacon';
22057
22104
  }
22058
- logger$5.log('MIXPANEL REQUEST:', dataForRequest);
22105
+ logger$6.log('MIXPANEL REQUEST:', dataForRequest);
22059
22106
  return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
22060
22107
  }, this))
22061
22108
  .catch(_.bind(function(err) {
@@ -22068,7 +22115,7 @@
22068
22115
  * Log error to global logger and optional user-defined logger.
22069
22116
  */
22070
22117
  RequestBatcher.prototype.reportError = function(msg, err) {
22071
- logger$5.error.apply(logger$5.error, arguments);
22118
+ logger$6.error.apply(logger$6.error, arguments);
22072
22119
  if (this.errorReporter) {
22073
22120
  try {
22074
22121
  if (!(err instanceof Error)) {
@@ -22076,7 +22123,7 @@
22076
22123
  }
22077
22124
  this.errorReporter(msg, err);
22078
22125
  } catch(err) {
22079
- logger$5.error(err);
22126
+ logger$6.error(err);
22080
22127
  }
22081
22128
  }
22082
22129
  };
@@ -22093,6 +22140,29 @@
22093
22140
 
22094
22141
  var RECORD_ENQUEUE_THROTTLE_MS = 250;
22095
22142
 
22143
+ var validateAllowedOrigins = function(origins, logger) {
22144
+ if (!_.isArray(origins)) {
22145
+ if (origins) {
22146
+ logger.critical('record_allowed_iframe_origins must be an array of origin strings, cross-origin recording will be disabled.');
22147
+ }
22148
+ return [];
22149
+ }
22150
+ var valid = [];
22151
+ for (var i = 0; i < origins.length; i++) {
22152
+ try {
22153
+ var origin = new URL(origins[i]).origin;
22154
+ if (origin === 'null') {
22155
+ logger.critical(origins[i] + ' has an opaque origin. Skipping this entry.');
22156
+ continue;
22157
+ }
22158
+ valid.push(origin);
22159
+ } catch (e) {
22160
+ logger.critical(origins[i] + ' is not a valid origin URL. Skipping this entry.');
22161
+ }
22162
+ }
22163
+ return valid;
22164
+ };
22165
+
22096
22166
  // stateless utils
22097
22167
  // mostly from https://github.com/mixpanel/mixpanel-js/blob/989ada50f518edab47b9c4fd9535f9fbd5ec5fc0/src/autotrack-utils.js
22098
22168
 
@@ -22198,7 +22268,7 @@
22198
22268
 
22199
22269
  var MAX_DEPTH = 5;
22200
22270
 
22201
- var logger$4 = console_with_prefix('autocapture');
22271
+ var logger$5 = console_with_prefix('autocapture');
22202
22272
 
22203
22273
 
22204
22274
  function getClasses(el) {
@@ -22462,7 +22532,7 @@
22462
22532
  return false;
22463
22533
  }
22464
22534
  } catch (err) {
22465
- logger$4.critical('Error while checking element in allowElementCallback', err);
22535
+ logger$5.critical('Error while checking element in allowElementCallback', err);
22466
22536
  return false;
22467
22537
  }
22468
22538
  }
@@ -22479,7 +22549,7 @@
22479
22549
  return true;
22480
22550
  }
22481
22551
  } catch (err) {
22482
- logger$4.critical('Error while checking selector: ' + sel, err);
22552
+ logger$5.critical('Error while checking selector: ' + sel, err);
22483
22553
  }
22484
22554
  }
22485
22555
  return false;
@@ -22494,7 +22564,7 @@
22494
22564
  return true;
22495
22565
  }
22496
22566
  } catch (err) {
22497
- logger$4.critical('Error while checking element in blockElementCallback', err);
22567
+ logger$5.critical('Error while checking element in blockElementCallback', err);
22498
22568
  return true;
22499
22569
  }
22500
22570
  }
@@ -22508,7 +22578,7 @@
22508
22578
  return true;
22509
22579
  }
22510
22580
  } catch (err) {
22511
- logger$4.critical('Error while checking selector: ' + sel, err);
22581
+ logger$5.critical('Error while checking selector: ' + sel, err);
22512
22582
  }
22513
22583
  }
22514
22584
  }
@@ -23064,7 +23134,7 @@
23064
23134
  *
23065
23135
  */
23066
23136
 
23067
- var logger$3 = console_with_prefix('network-plugin');
23137
+ var logger$4 = console_with_prefix('network-plugin');
23068
23138
 
23069
23139
  /**
23070
23140
  * Get the time origin for converting performance timestamps to absolute timestamps.
@@ -23216,7 +23286,7 @@
23216
23286
  return str;
23217
23287
  }
23218
23288
  if (str.length > MAX_BODY_SIZE) {
23219
- logger$3.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
23289
+ logger$4.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
23220
23290
  return str.substring(0, MAX_BODY_SIZE) + '... [truncated]';
23221
23291
  }
23222
23292
  return str;
@@ -23230,7 +23300,7 @@
23230
23300
  */
23231
23301
  function initPerformanceObserver(cb, win, options) {
23232
23302
  if (!win.PerformanceObserver) {
23233
- logger$3.error('PerformanceObserver not supported');
23303
+ logger$4.error('PerformanceObserver not supported');
23234
23304
  return function() {
23235
23305
  //
23236
23306
  };
@@ -23383,7 +23453,7 @@
23383
23453
  attempt = 0;
23384
23454
  }
23385
23455
  if (attempt > 10) {
23386
- logger$3.error('Cannot find performance entry');
23456
+ logger$4.error('Cannot find performance entry');
23387
23457
  return Promise.resolve(null);
23388
23458
  }
23389
23459
  var urlPerformanceEntries = /** @type {PerformanceResourceTiming[]} */ (
@@ -23504,7 +23574,7 @@
23504
23574
  )
23505
23575
  .then(function(entry) {
23506
23576
  if (!entry) {
23507
- logger$3.error('Failed to get performance entry for XHR request to ' + req.url);
23577
+ logger$4.error('Failed to get performance entry for XHR request to ' + req.url);
23508
23578
  return;
23509
23579
  }
23510
23580
  /** @type {NetworkRequest} */
@@ -23524,7 +23594,7 @@
23524
23594
  cb({ requests: [request] });
23525
23595
  })
23526
23596
  .catch(function(e) {
23527
- logger$3.error('Error recording XHR request to ' + req.url + ': ' + String(e));
23597
+ logger$4.error('Error recording XHR request to ' + req.url + ': ' + String(e));
23528
23598
  });
23529
23599
  });
23530
23600
 
@@ -23616,7 +23686,7 @@
23616
23686
  })
23617
23687
  .then(function(entry) {
23618
23688
  if (!entry) {
23619
- logger$3.error('Failed to get performance entry for fetch request to ' + req.url);
23689
+ logger$4.error('Failed to get performance entry for fetch request to ' + req.url);
23620
23690
  return;
23621
23691
  }
23622
23692
  /** @type {NetworkRequest} */
@@ -23636,7 +23706,7 @@
23636
23706
  cb({ requests: [request] });
23637
23707
  })
23638
23708
  .catch(function (e) {
23639
- logger$3.error('Error recording fetch request to ' + req.url + ': ' + String(e));
23709
+ logger$4.error('Error recording fetch request to ' + req.url + ': ' + String(e));
23640
23710
  });
23641
23711
 
23642
23712
  return originalFetchPromise;
@@ -23709,7 +23779,7 @@
23709
23779
  */
23710
23780
 
23711
23781
 
23712
- var logger$2 = console_with_prefix('recorder');
23782
+ var logger$3 = console_with_prefix('recorder');
23713
23783
  var CompressionStream = win['CompressionStream'];
23714
23784
 
23715
23785
  var RECORDER_BATCHER_LIB_CONFIG = {
@@ -23889,14 +23959,14 @@
23889
23959
  }
23890
23960
 
23891
23961
  if (this._stopRecording !== null) {
23892
- logger$2.log('Recording already in progress, skipping startRecording.');
23962
+ logger$3.log('Recording already in progress, skipping startRecording.');
23893
23963
  return;
23894
23964
  }
23895
23965
 
23896
23966
  this.recordMaxMs = this.getConfig('record_max_ms');
23897
23967
  if (this.recordMaxMs > MAX_RECORDING_MS) {
23898
23968
  this.recordMaxMs = MAX_RECORDING_MS;
23899
- logger$2.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
23969
+ logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
23900
23970
  }
23901
23971
 
23902
23972
  if (!this.maxExpires) {
@@ -23960,6 +24030,8 @@
23960
24030
  );
23961
24031
  }
23962
24032
 
24033
+ var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$3);
24034
+
23963
24035
  try {
23964
24036
  this._stopRecording = this._rrwebRecord({
23965
24037
  'emit': function (ev) {
@@ -23994,6 +24066,8 @@
23994
24066
  'maskTextSelector': '*',
23995
24067
  'maskInputFn': this._getMaskFn(shouldMaskInput, privacyConfig),
23996
24068
  'maskTextFn': this._getMaskFn(shouldMaskText, privacyConfig),
24069
+ 'recordCrossOriginIframes': validatedOrigins.length > 0,
24070
+ 'allowedIframeOrigins': validatedOrigins,
23997
24071
  'recordCanvas': this.getConfig('record_canvas'),
23998
24072
  'sampling': {
23999
24073
  'canvas': 15
@@ -24218,14 +24292,14 @@
24218
24292
 
24219
24293
 
24220
24294
  SessionRecording.prototype.reportError = function(msg, err) {
24221
- logger$2.error.apply(logger$2.error, arguments);
24295
+ logger$3.error.apply(logger$3.error, arguments);
24222
24296
  try {
24223
24297
  if (!err && !(msg instanceof Error)) {
24224
24298
  msg = new Error(msg);
24225
24299
  }
24226
24300
  this.getConfig('error_reporter')(msg, err);
24227
24301
  } catch(err) {
24228
- logger$2.error(err);
24302
+ logger$3.error(err);
24229
24303
  }
24230
24304
  };
24231
24305
 
@@ -24254,7 +24328,7 @@
24254
24328
  var configValue = this.getConfig('record_min_ms');
24255
24329
 
24256
24330
  if (configValue > MAX_VALUE_FOR_MIN_RECORDING_MS) {
24257
- logger$2.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
24331
+ logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
24258
24332
  return MAX_VALUE_FOR_MIN_RECORDING_MS;
24259
24333
  }
24260
24334
 
@@ -24417,7 +24491,7 @@
24417
24491
  .catch(this.handleError.bind(this));
24418
24492
  };
24419
24493
 
24420
- var logger$1 = console_with_prefix('recorder');
24494
+ var logger$2 = console_with_prefix('recorder');
24421
24495
 
24422
24496
  /**
24423
24497
  * Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
@@ -24433,7 +24507,7 @@
24433
24507
  */
24434
24508
  this.recordingRegistry = new RecordingRegistry({
24435
24509
  mixpanelInstance: this.mixpanelInstance,
24436
- errorReporter: logger$1.error,
24510
+ errorReporter: logger$2.error,
24437
24511
  sharedLockStorage: sharedLockStorage
24438
24512
  });
24439
24513
  this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
@@ -24445,17 +24519,17 @@
24445
24519
  MixpanelRecorder.prototype.startRecording = function(options) {
24446
24520
  options = options || {};
24447
24521
  if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
24448
- logger$1.log('Recording already in progress, skipping startRecording.');
24522
+ logger$2.log('Recording already in progress, skipping startRecording.');
24449
24523
  return;
24450
24524
  }
24451
24525
 
24452
24526
  var onIdleTimeout = function () {
24453
- logger$1.log('Idle timeout reached, restarting recording.');
24527
+ logger$2.log('Idle timeout reached, restarting recording.');
24454
24528
  this.resetRecording();
24455
24529
  }.bind(this);
24456
24530
 
24457
24531
  var onMaxLengthReached = function () {
24458
- logger$1.log('Max recording length reached, stopping recording.');
24532
+ logger$2.log('Max recording length reached, stopping recording.');
24459
24533
  this.resetRecording();
24460
24534
  }.bind(this);
24461
24535
 
@@ -24525,7 +24599,7 @@
24525
24599
  } else if (startNewIfInactive) {
24526
24600
  return this.startRecording({shouldStopBatcher: false});
24527
24601
  } else {
24528
- logger$1.log('No resumable recording found.');
24602
+ logger$2.log('No resumable recording found.');
24529
24603
  return null;
24530
24604
  }
24531
24605
  }.bind(this));
@@ -24659,7 +24733,7 @@
24659
24733
  observer.observe(shadowRoot, this.observerConfig);
24660
24734
  this.shadowObservers.push(observer);
24661
24735
  } catch (e) {
24662
- logger$4.critical('Error while observing shadow root', e);
24736
+ logger$5.critical('Error while observing shadow root', e);
24663
24737
  }
24664
24738
  };
24665
24739
 
@@ -24670,7 +24744,7 @@
24670
24744
  }
24671
24745
 
24672
24746
  if (!weakSetSupported()) {
24673
- logger$4.critical('Shadow DOM observation unavailable: WeakSet not supported');
24747
+ logger$5.critical('Shadow DOM observation unavailable: WeakSet not supported');
24674
24748
  return;
24675
24749
  }
24676
24750
 
@@ -24686,7 +24760,7 @@
24686
24760
  try {
24687
24761
  this.shadowObservers[i].disconnect();
24688
24762
  } catch (e) {
24689
- logger$4.critical('Error while disconnecting shadow DOM observer', e);
24763
+ logger$5.critical('Error while disconnecting shadow DOM observer', e);
24690
24764
  }
24691
24765
  }
24692
24766
  this.shadowObservers = [];
@@ -24874,7 +24948,7 @@
24874
24948
 
24875
24949
  this.mutationObserver.observe(document.body || document.documentElement, MUTATION_OBSERVER_CONFIG);
24876
24950
  } catch (e) {
24877
- logger$4.critical('Error while setting up mutation observer', e);
24951
+ logger$5.critical('Error while setting up mutation observer', e);
24878
24952
  }
24879
24953
  }
24880
24954
 
@@ -24889,7 +24963,7 @@
24889
24963
  );
24890
24964
  this.shadowDOMObserver.start();
24891
24965
  } catch (e) {
24892
- logger$4.critical('Error while setting up shadow DOM observer', e);
24966
+ logger$5.critical('Error while setting up shadow DOM observer', e);
24893
24967
  this.shadowDOMObserver = null;
24894
24968
  }
24895
24969
  }
@@ -24916,7 +24990,7 @@
24916
24990
  try {
24917
24991
  listener.target.removeEventListener(listener.event, listener.handler, listener.options);
24918
24992
  } catch (e) {
24919
- logger$4.critical('Error while removing event listener', e);
24993
+ logger$5.critical('Error while removing event listener', e);
24920
24994
  }
24921
24995
  }
24922
24996
  this.eventListeners = [];
@@ -24925,7 +24999,7 @@
24925
24999
  try {
24926
25000
  this.mutationObserver.disconnect();
24927
25001
  } catch (e) {
24928
- logger$4.critical('Error while disconnecting mutation observer', e);
25002
+ logger$5.critical('Error while disconnecting mutation observer', e);
24929
25003
  }
24930
25004
  this.mutationObserver = null;
24931
25005
  }
@@ -24934,7 +25008,7 @@
24934
25008
  try {
24935
25009
  this.shadowDOMObserver.stop();
24936
25010
  } catch (e) {
24937
- logger$4.critical('Error while stopping shadow DOM observer', e);
25011
+ logger$5.critical('Error while stopping shadow DOM observer', e);
24938
25012
  }
24939
25013
  this.shadowDOMObserver = null;
24940
25014
  }
@@ -25012,7 +25086,7 @@
25012
25086
 
25013
25087
  Autocapture.prototype.init = function() {
25014
25088
  if (!minDOMApisSupported()) {
25015
- logger$4.critical('Autocapture unavailable: missing required DOM APIs');
25089
+ logger$5.critical('Autocapture unavailable: missing required DOM APIs');
25016
25090
  return;
25017
25091
  }
25018
25092
  this.initPageListeners();
@@ -25052,7 +25126,7 @@
25052
25126
  try {
25053
25127
  return !urlMatchesRegexList(currentUrl, allowUrlRegexes);
25054
25128
  } catch (err) {
25055
- logger$4.critical('Error while checking block URL regexes: ', err);
25129
+ logger$5.critical('Error while checking block URL regexes: ', err);
25056
25130
  return true;
25057
25131
  }
25058
25132
  }
@@ -25065,7 +25139,7 @@
25065
25139
  try {
25066
25140
  return urlMatchesRegexList(currentUrl, blockUrlRegexes);
25067
25141
  } catch (err) {
25068
- logger$4.critical('Error while checking block URL regexes: ', err);
25142
+ logger$5.critical('Error while checking block URL regexes: ', err);
25069
25143
  return true;
25070
25144
  }
25071
25145
  };
@@ -25203,7 +25277,7 @@
25203
25277
  return;
25204
25278
  }
25205
25279
 
25206
- logger$4.log('Initializing scroll depth tracking');
25280
+ logger$5.log('Initializing scroll depth tracking');
25207
25281
 
25208
25282
  this.maxScrollViewDepth = Math.max(document$1.documentElement.clientHeight, win.innerHeight || 0);
25209
25283
 
@@ -25229,7 +25303,7 @@
25229
25303
  if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
25230
25304
  return;
25231
25305
  }
25232
- logger$4.log('Initializing click tracking');
25306
+ logger$5.log('Initializing click tracking');
25233
25307
 
25234
25308
  this.listenerClick = function(ev) {
25235
25309
  if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
@@ -25248,7 +25322,7 @@
25248
25322
  return;
25249
25323
  }
25250
25324
 
25251
- logger$4.log('Initializing dead click tracking');
25325
+ logger$5.log('Initializing dead click tracking');
25252
25326
  if (!this._deadClickTracker) {
25253
25327
  this._deadClickTracker = new DeadClickTracker(function(deadClickEvent) {
25254
25328
  this.trackDomEvent(deadClickEvent, MP_EV_DEAD_CLICK);
@@ -25282,7 +25356,7 @@
25282
25356
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
25283
25357
  return;
25284
25358
  }
25285
- logger$4.log('Initializing input tracking');
25359
+ logger$5.log('Initializing input tracking');
25286
25360
 
25287
25361
  this.listenerChange = function(ev) {
25288
25362
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
@@ -25299,7 +25373,7 @@
25299
25373
  if (!this.pageviewTrackingConfig()) {
25300
25374
  return;
25301
25375
  }
25302
- logger$4.log('Initializing pageview tracking');
25376
+ logger$5.log('Initializing pageview tracking');
25303
25377
 
25304
25378
  var previousTrackedUrl = '';
25305
25379
  var tracked = false;
@@ -25334,7 +25408,7 @@
25334
25408
  }
25335
25409
  if (didPathChange) {
25336
25410
  this.lastScrollCheckpoint = 0;
25337
- logger$4.log('Path change: re-initializing scroll depth checkpoints');
25411
+ logger$5.log('Path change: re-initializing scroll depth checkpoints');
25338
25412
  }
25339
25413
  }
25340
25414
  }.bind(this));
@@ -25349,7 +25423,7 @@
25349
25423
  return;
25350
25424
  }
25351
25425
 
25352
- logger$4.log('Initializing rage click tracking');
25426
+ logger$5.log('Initializing rage click tracking');
25353
25427
  if (!this._rageClickTracker) {
25354
25428
  this._rageClickTracker = new RageClickTracker();
25355
25429
  }
@@ -25379,7 +25453,7 @@
25379
25453
  if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
25380
25454
  return;
25381
25455
  }
25382
- logger$4.log('Initializing scroll tracking');
25456
+ logger$5.log('Initializing scroll tracking');
25383
25457
  this.lastScrollCheckpoint = 0;
25384
25458
 
25385
25459
  var scrollTrackFunction = function() {
@@ -25416,7 +25490,7 @@
25416
25490
  }
25417
25491
  }
25418
25492
  } catch (err) {
25419
- logger$4.critical('Error while calculating scroll percentage', err);
25493
+ logger$5.critical('Error while calculating scroll percentage', err);
25420
25494
  }
25421
25495
  if (shouldTrack) {
25422
25496
  this.mp.track(MP_EV_SCROLL, props);
@@ -25434,7 +25508,7 @@
25434
25508
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
25435
25509
  return;
25436
25510
  }
25437
- logger$4.log('Initializing submit tracking');
25511
+ logger$5.log('Initializing submit tracking');
25438
25512
 
25439
25513
  this.listenerSubmit = function(ev) {
25440
25514
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
@@ -25456,7 +25530,7 @@
25456
25530
  return;
25457
25531
  }
25458
25532
 
25459
- logger$4.log('Initializing page visibility tracking.');
25533
+ logger$5.log('Initializing page visibility tracking.');
25460
25534
  this._initScrollDepthTracking();
25461
25535
  var previousTrackedUrl = _.info.currentUrl();
25462
25536
 
@@ -25541,7 +25615,7 @@
25541
25615
  return win[TARGETING_GLOBAL_NAME];
25542
25616
  };
25543
25617
 
25544
- var logger = console_with_prefix('flags');
25618
+ var logger$1 = console_with_prefix('flags');
25545
25619
  var FLAGS_CONFIG_KEY = 'flags';
25546
25620
 
25547
25621
  var CONFIG_CONTEXT = 'context';
@@ -25584,7 +25658,7 @@
25584
25658
 
25585
25659
  FeatureFlagManager.prototype.init = function() {
25586
25660
  if (!this.minApisSupported()) {
25587
- logger.critical('Feature Flags unavailable: missing minimum required APIs');
25661
+ logger$1.critical('Feature Flags unavailable: missing minimum required APIs');
25588
25662
  return;
25589
25663
  }
25590
25664
 
@@ -25619,7 +25693,7 @@
25619
25693
 
25620
25694
  FeatureFlagManager.prototype.updateContext = function(newContext, options) {
25621
25695
  if (!this.isSystemEnabled()) {
25622
- logger.critical('Feature Flags not enabled, cannot update context');
25696
+ logger$1.critical('Feature Flags not enabled, cannot update context');
25623
25697
  return Promise.resolve();
25624
25698
  }
25625
25699
 
@@ -25636,7 +25710,7 @@
25636
25710
 
25637
25711
  FeatureFlagManager.prototype.areFlagsReady = function() {
25638
25712
  if (!this.isSystemEnabled()) {
25639
- logger.error('Feature Flags not enabled');
25713
+ logger$1.error('Feature Flags not enabled');
25640
25714
  }
25641
25715
  return !!this.flags;
25642
25716
  };
@@ -25649,7 +25723,7 @@
25649
25723
  var distinctId = this.getMpProperty('distinct_id');
25650
25724
  var deviceId = this.getMpProperty('$device_id');
25651
25725
  var traceparent = generateTraceparent();
25652
- logger.log('Fetching flags for distinct ID: ' + distinctId);
25726
+ logger$1.log('Fetching flags for distinct ID: ' + distinctId);
25653
25727
 
25654
25728
  var context = _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT));
25655
25729
  var searchParams = new URLSearchParams();
@@ -25748,11 +25822,11 @@
25748
25822
  this._loadTargetingIfNeeded();
25749
25823
  }.bind(this)).catch(function(error) {
25750
25824
  this.markFetchComplete();
25751
- logger.error(error);
25825
+ logger$1.error(error);
25752
25826
  }.bind(this));
25753
25827
  }.bind(this)).catch(function(error) {
25754
25828
  this.markFetchComplete();
25755
- logger.error(error);
25829
+ logger$1.error(error);
25756
25830
  }.bind(this));
25757
25831
 
25758
25832
  return this.fetchPromise;
@@ -25760,7 +25834,7 @@
25760
25834
 
25761
25835
  FeatureFlagManager.prototype.markFetchComplete = function() {
25762
25836
  if (!this._fetchInProgressStartTime) {
25763
- logger.error('Fetch in progress started time not set, cannot mark fetch complete');
25837
+ logger$1.error('Fetch in progress started time not set, cannot mark fetch complete');
25764
25838
  return;
25765
25839
  }
25766
25840
  this._fetchStartTime = this._fetchInProgressStartTime;
@@ -25782,7 +25856,7 @@
25782
25856
 
25783
25857
  if (hasPropertyFilters) {
25784
25858
  this.getTargeting().then(function() {
25785
- logger.log('targeting loaded for property filter evaluation');
25859
+ logger$1.log('targeting loaded for property filter evaluation');
25786
25860
  });
25787
25861
  }
25788
25862
  };
@@ -25797,7 +25871,7 @@
25797
25871
  this.loadExtraBundle.bind(this),
25798
25872
  this.targetingSrc
25799
25873
  ).catch(function(error) {
25800
- logger.error('Failed to load targeting: ' + error);
25874
+ logger$1.error('Failed to load targeting: ' + error);
25801
25875
  }.bind(this));
25802
25876
  };
25803
25877
 
@@ -25851,7 +25925,7 @@
25851
25925
 
25852
25926
  // If no targeting library and event has property filters, skip it
25853
25927
  if (!targeting && pendingEvent['property_filters'] && !_.isEmptyObject(pendingEvent['property_filters'])) {
25854
- logger.warn('Skipping event check for "' + flagKey + '" - property filters require targeting library');
25928
+ logger$1.warn('Skipping event check for "' + flagKey + '" - property filters require targeting library');
25855
25929
  return;
25856
25930
  }
25857
25931
 
@@ -25874,7 +25948,7 @@
25874
25948
  }
25875
25949
 
25876
25950
  if (matchResult.error) {
25877
- logger.error('Error checking first-time event for flag "' + flagKey + '": ' + matchResult.error);
25951
+ logger$1.error('Error checking first-time event for flag "' + flagKey + '": ' + matchResult.error);
25878
25952
  return;
25879
25953
  }
25880
25954
 
@@ -25882,7 +25956,7 @@
25882
25956
  return;
25883
25957
  }
25884
25958
 
25885
- logger.log('First-time event matched for flag "' + flagKey + '": ' + eventName);
25959
+ logger$1.log('First-time event matched for flag "' + flagKey + '": ' + eventName);
25886
25960
 
25887
25961
  var newVariant = {
25888
25962
  'key': pendingEvent['pending_variant']['variant_key'],
@@ -25923,7 +25997,7 @@
25923
25997
  'first_time_event_hash': firstTimeEventHash
25924
25998
  };
25925
25999
 
25926
- logger.log('Recording first-time event for flag: ' + flagId);
26000
+ logger$1.log('Recording first-time event for flag: ' + flagId);
25927
26001
 
25928
26002
  // Fire-and-forget POST request
25929
26003
  this.fetch.call(win, url, {
@@ -25936,14 +26010,14 @@
25936
26010
  'body': JSON.stringify(payload)
25937
26011
  }).catch(function(error) {
25938
26012
  // Silent failure - cohort sync will catch up
25939
- logger.error('Failed to record first-time event for flag ' + flagId + ': ' + error);
26013
+ logger$1.error('Failed to record first-time event for flag ' + flagId + ': ' + error);
25940
26014
  });
25941
26015
  };
25942
26016
 
25943
26017
  FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
25944
26018
  if (!this.fetchPromise) {
25945
26019
  return new Promise(function(resolve) {
25946
- logger.critical('Feature Flags not initialized');
26020
+ logger$1.critical('Feature Flags not initialized');
25947
26021
  resolve(fallback);
25948
26022
  });
25949
26023
  }
@@ -25951,19 +26025,19 @@
25951
26025
  return this.fetchPromise.then(function() {
25952
26026
  return this.getVariantSync(featureName, fallback);
25953
26027
  }.bind(this)).catch(function(error) {
25954
- logger.error(error);
26028
+ logger$1.error(error);
25955
26029
  return fallback;
25956
26030
  });
25957
26031
  };
25958
26032
 
25959
26033
  FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
25960
26034
  if (!this.areFlagsReady()) {
25961
- logger.log('Flags not loaded yet');
26035
+ logger$1.log('Flags not loaded yet');
25962
26036
  return fallback;
25963
26037
  }
25964
26038
  var feature = this.flags.get(featureName);
25965
26039
  if (!feature) {
25966
- logger.log('No flag found: "' + featureName + '"');
26040
+ logger$1.log('No flag found: "' + featureName + '"');
25967
26041
  return fallback;
25968
26042
  }
25969
26043
  this.trackFeatureCheck(featureName, feature);
@@ -25974,14 +26048,14 @@
25974
26048
  return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
25975
26049
  return feature['value'];
25976
26050
  }).catch(function(error) {
25977
- logger.error(error);
26051
+ logger$1.error(error);
25978
26052
  return fallbackValue;
25979
26053
  });
25980
26054
  };
25981
26055
 
25982
26056
  // TODO remove deprecated method
25983
26057
  FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
25984
- logger.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
26058
+ logger$1.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
25985
26059
  return this.getVariantValue(featureName, fallbackValue);
25986
26060
  };
25987
26061
 
@@ -25993,7 +26067,7 @@
25993
26067
  return this.getVariantValue(featureName).then(function() {
25994
26068
  return this.isEnabledSync(featureName, fallbackValue);
25995
26069
  }.bind(this)).catch(function(error) {
25996
- logger.error(error);
26070
+ logger$1.error(error);
25997
26071
  return fallbackValue;
25998
26072
  });
25999
26073
  };
@@ -26002,7 +26076,7 @@
26002
26076
  fallbackValue = fallbackValue || false;
26003
26077
  var val = this.getVariantValueSync(featureName, fallbackValue);
26004
26078
  if (val !== true && val !== false) {
26005
- logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
26079
+ logger$1.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
26006
26080
  val = fallbackValue;
26007
26081
  }
26008
26082
  return val;
@@ -26064,6 +26138,12 @@
26064
26138
  /* eslint camelcase: "off" */
26065
26139
 
26066
26140
 
26141
+ var logger = console_with_prefix('recorder');
26142
+
26143
+ var IFRAME_HANDSHAKE_REQUEST = 'mp_iframe_handshake_request';
26144
+ var IFRAME_HANDSHAKE_RESPONSE = 'mp_iframe_handshake_response';
26145
+
26146
+
26067
26147
  /**
26068
26148
  * RecorderManager: manages session recording initialization, lifecycle and state
26069
26149
  * @constructor
@@ -26083,6 +26163,8 @@
26083
26163
  this.libBasePath = initOptions.libBasePath;
26084
26164
 
26085
26165
  this._recorder = null;
26166
+ this._parentReplayId = null;
26167
+ this._parentFrameRetryInterval = null;
26086
26168
  };
26087
26169
 
26088
26170
  RecorderManager.prototype.shouldLoadRecorder = function() {
@@ -26136,6 +26218,22 @@
26136
26218
  }, this));
26137
26219
  }, this);
26138
26220
 
26221
+ // Cross-origin iframe handling
26222
+ var allowedOrigins = validateAllowedOrigins(this.getMpConfig('record_allowed_iframe_origins'), logger);
26223
+ var isCrossOriginRecordingEnabled = allowedOrigins.length > 0;
26224
+
26225
+ if (isCrossOriginRecordingEnabled) {
26226
+ // listen for handshake requests from their own child iframes (including nested)
26227
+ this._setupParentFrameListener(allowedOrigins);
26228
+
26229
+ if (win.parent !== win) {
26230
+ // also wait for parent's replay ID
26231
+ this._setupChildFrameListener(allowedOrigins, loadRecorder);
26232
+ this._sendParentFrameRequestWithRetry(allowedOrigins);
26233
+ return PromisePolyfill.resolve();
26234
+ }
26235
+ }
26236
+
26139
26237
  /**
26140
26238
  * If the user is sampled or start_session_recording is called, we always load the recorder since it's guaranteed a recording should start.
26141
26239
  * Otherwise, if the recording registry has any records then it's likely there's a recording in progress or orphaned data that needs to be flushed.
@@ -26255,6 +26353,10 @@
26255
26353
  };
26256
26354
 
26257
26355
  RecorderManager.prototype.getSessionReplayId = function() {
26356
+ // Child iframe uses parent's replay ID
26357
+ if (this._parentReplayId) {
26358
+ return this._parentReplayId;
26359
+ }
26258
26360
  var replay_id = null;
26259
26361
  if (this._recorder) {
26260
26362
  replay_id = this._recorder['replayId'];
@@ -26267,6 +26369,86 @@
26267
26369
  return this._recorder;
26268
26370
  };
26269
26371
 
26372
+ RecorderManager.prototype._setupChildFrameListener = function(allowedOrigins, loadRecorder) {
26373
+ if (this._childFrameMessageHandler) {
26374
+ return;
26375
+ }
26376
+ var self = this;
26377
+ this._childFrameMessageHandler = function(event) {
26378
+ if (allowedOrigins.indexOf(event.origin) === -1) return;
26379
+ var data = event.data;
26380
+ if (data && data['type'] === IFRAME_HANDSHAKE_RESPONSE && data['token'] === self.getMpConfig('token') && data['replayId']) {
26381
+ self._parentReplayId = data['replayId'];
26382
+ if (data['distinctId']) {
26383
+ self.mixpanelInstance['identify'](data['distinctId']);
26384
+ }
26385
+ self._parentFrameRetryActive = false;
26386
+ win.removeEventListener('message', self._childFrameMessageHandler);
26387
+ self._childFrameMessageHandler = null;
26388
+ loadRecorder(true);
26389
+ }
26390
+ };
26391
+ win.addEventListener('message', this._childFrameMessageHandler);
26392
+ };
26393
+
26394
+ RecorderManager.prototype._sendParentFrameRequest = function(allowedOrigins) {
26395
+ var message = {};
26396
+ message['type'] = IFRAME_HANDSHAKE_REQUEST;
26397
+ message['token'] = this.getMpConfig('token');
26398
+ for (var i = 0; i < allowedOrigins.length; i++) {
26399
+ try {
26400
+ win.parent.postMessage(message, allowedOrigins[i]);
26401
+ } catch (e) {
26402
+ // origin mismatch - ignore
26403
+ }
26404
+ }
26405
+ };
26406
+
26407
+ RecorderManager.prototype._sendParentFrameRequestWithRetry = function(allowedOrigins) {
26408
+ var self = this;
26409
+ var maxRetries = 10;
26410
+ var retryCount = 0;
26411
+ var delay = 50;
26412
+ this._parentFrameRetryActive = true;
26413
+
26414
+ this._sendParentFrameRequest(allowedOrigins);
26415
+
26416
+ function scheduleRetry() {
26417
+ setTimeout(function() {
26418
+ if (!self._parentFrameRetryActive || self._parentReplayId || ++retryCount >= maxRetries) {
26419
+ return;
26420
+ }
26421
+ self._sendParentFrameRequest(allowedOrigins);
26422
+ delay *= 2;
26423
+ scheduleRetry();
26424
+ }, delay);
26425
+ }
26426
+ scheduleRetry();
26427
+ };
26428
+
26429
+ RecorderManager.prototype._setupParentFrameListener = function(allowedOrigins) {
26430
+ if (this._parentFrameMessageHandler) {
26431
+ return;
26432
+ }
26433
+ var self = this;
26434
+ this._parentFrameMessageHandler = function(event) {
26435
+ if (allowedOrigins.indexOf(event.origin) === -1) return;
26436
+ var data = event.data;
26437
+ if (data && data['type'] === IFRAME_HANDSHAKE_REQUEST && data['token'] === self.getMpConfig('token')) {
26438
+ var replayId = self.getSessionReplayId();
26439
+ if (replayId) {
26440
+ var response = {};
26441
+ response['type'] = IFRAME_HANDSHAKE_RESPONSE;
26442
+ response['token'] = self.getMpConfig('token');
26443
+ response['replayId'] = replayId;
26444
+ response['distinctId'] = self.getDistinctId();
26445
+ event.source.postMessage(response, event.origin);
26446
+ }
26447
+ }
26448
+ };
26449
+ win.addEventListener('message', this._parentFrameMessageHandler);
26450
+ };
26451
+
26270
26452
  safewrapClass(RecorderManager);
26271
26453
 
26272
26454
  /* eslint camelcase: "off" */
@@ -27641,7 +27823,6 @@
27641
27823
  /** @const */ var SETTING_FALLBACK = 'fallback';
27642
27824
  /** @const */ var SETTING_DISABLED = 'disabled';
27643
27825
 
27644
-
27645
27826
  /*
27646
27827
  * Dynamic... constants? Is that an oxymoron?
27647
27828
  */
@@ -27726,6 +27907,7 @@
27726
27907
  'batch_request_timeout_ms': 90000,
27727
27908
  'batch_autostart': true,
27728
27909
  'hooks': {},
27910
+ 'record_allowed_iframe_origins': [],
27729
27911
  'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
27730
27912
  'record_block_selector': 'img, video, audio',
27731
27913
  'record_canvas': false,