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
@@ -31,7 +31,7 @@
31
31
 
32
32
  var Config = {
33
33
  DEBUG: false,
34
- LIB_VERSION: '2.76.0'
34
+ LIB_VERSION: '2.77.0'
35
35
  };
36
36
 
37
37
  // Window global names for async modules
@@ -10739,13 +10739,7 @@
10739
10739
  };
10740
10740
  while(_this.mapRemoves.length){
10741
10741
  var removedNode = _this.mapRemoves.shift();
10742
- if (removedNode.nodeName === "IFRAME") {
10743
- try {
10744
- _this.iframeManager.removeIframe(removedNode);
10745
- } catch (e2) {}
10746
- } else {
10747
- _this.stylesheetManager.cleanupStylesheetsForRemovedNode(removedNode);
10748
- }
10742
+ _this.cleanupRemovedNode(removedNode);
10749
10743
  _this.mirror.removeNodeFromMap(removedNode);
10750
10744
  }
10751
10745
  for(var _iterator = _create_for_of_iterator_helper_loose(_this.movedSet), _step; !(_step = _iterator()).done;){
@@ -11065,6 +11059,20 @@
11065
11059
  }
11066
11060
  }
11067
11061
  });
11062
+ __publicField$1(this, "cleanupRemovedNode", function(node2) {
11063
+ if (node2.nodeName === "IFRAME") {
11064
+ try {
11065
+ _this.iframeManager.removeIframe(node2);
11066
+ } catch (e2) {}
11067
+ } else {
11068
+ try {
11069
+ _this.stylesheetManager.cleanupStylesheetsForRemovedNode(node2);
11070
+ } catch (e2) {}
11071
+ }
11072
+ node2.childNodes.forEach(function(child) {
11073
+ _this.cleanupRemovedNode(child);
11074
+ });
11075
+ });
11068
11076
  }
11069
11077
  var _proto = MutationBuffer.prototype;
11070
11078
  _proto.init = function init(options) {
@@ -13292,6 +13300,31 @@
13292
13300
  _proto.destroy = function destroy() {};
13293
13301
  return ProcessedNodeManager;
13294
13302
  }();
13303
+ function toOrigin(url) {
13304
+ try {
13305
+ var origin = new URL(url).origin;
13306
+ return origin !== "null" ? origin : null;
13307
+ } catch (e) {
13308
+ return null;
13309
+ }
13310
+ }
13311
+ function buildAllowedOriginSet(origins) {
13312
+ if (!Array.isArray(origins) || origins.length === 0) {
13313
+ throw new Error("[rrweb] allowedIframeOrigins must be a non-empty array of origin strings.");
13314
+ }
13315
+ var set = /* @__PURE__ */ new Set();
13316
+ for(var i2 = 0; i2 < origins.length; i2++){
13317
+ var entry = origins[i2];
13318
+ if (typeof entry !== "string") {
13319
+ throw new Error("[rrweb] allowedIframeOrigins[" + i2 + "] must be a string, got " + (typeof entry === "undefined" ? "undefined" : _type_of(entry)) + ".");
13320
+ }
13321
+ var origin = toOrigin(entry);
13322
+ if (origin) {
13323
+ set.add(origin);
13324
+ }
13325
+ }
13326
+ return Object.freeze(set);
13327
+ }
13295
13328
  var wrappedEmit;
13296
13329
  var takeFullSnapshot$1;
13297
13330
  var canvasManager;
@@ -13313,10 +13346,17 @@
13313
13346
  var mirror = createMirror$2();
13314
13347
  function record(options) {
13315
13348
  if (options === void 0) options = {};
13316
- 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() {
13349
+ 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() {
13317
13350
  return false;
13318
13351
  } : _options_keepIframeSrcFn, _options_ignoreCSSAttributes = options.ignoreCSSAttributes, ignoreCSSAttributes = _options_ignoreCSSAttributes === void 0 ? /* @__PURE__ */ new Set([]) : _options_ignoreCSSAttributes, errorHandler2 = options.errorHandler;
13319
13352
  registerErrorHandler(errorHandler2);
13353
+ var validatedOrigins;
13354
+ if (recordCrossOriginIframes && allowedIframeOrigins && allowedIframeOrigins.length > 0) {
13355
+ validatedOrigins = buildAllowedOriginSet(allowedIframeOrigins);
13356
+ if (validatedOrigins.size === 0) {
13357
+ validatedOrigins = void 0;
13358
+ }
13359
+ }
13320
13360
  var inEmittingFrame = recordCrossOriginIframes ? window.parent === window : true;
13321
13361
  var passEmitsToParent = false;
13322
13362
  if (!inEmittingFrame) {
@@ -13408,7 +13448,14 @@
13408
13448
  origin: window.location.origin,
13409
13449
  isCheckout: isCheckout
13410
13450
  };
13411
- window.parent.postMessage(message, "*");
13451
+ if (validatedOrigins) {
13452
+ for(var _iterator = _create_for_of_iterator_helper_loose(validatedOrigins), _step; !(_step = _iterator()).done;){
13453
+ var targetOrigin = _step.value;
13454
+ window.parent.postMessage(message, targetOrigin);
13455
+ }
13456
+ } else {
13457
+ window.parent.postMessage(message, "*");
13458
+ }
13412
13459
  }
13413
13460
  if (e2.type === EventType.FullSnapshot) {
13414
13461
  lastFullSnapshotEvent = e2;
@@ -21192,7 +21239,7 @@
21192
21239
  };
21193
21240
  }
21194
21241
 
21195
- var logger$7 = console_with_prefix('lock');
21242
+ var logger$8 = console_with_prefix('lock');
21196
21243
 
21197
21244
  /**
21198
21245
  * SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
@@ -21244,7 +21291,7 @@
21244
21291
 
21245
21292
  var delay = function(cb) {
21246
21293
  if (new Date().getTime() - startTime > timeoutMS) {
21247
- logger$7.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
21294
+ logger$8.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
21248
21295
  storage.removeItem(keyZ);
21249
21296
  storage.removeItem(keyY);
21250
21297
  loop();
@@ -21391,7 +21438,7 @@
21391
21438
  }, this));
21392
21439
  };
21393
21440
 
21394
- var logger$6 = console_with_prefix('batch');
21441
+ var logger$7 = console_with_prefix('batch');
21395
21442
 
21396
21443
  /**
21397
21444
  * RequestQueue: queue for batching API requests with localStorage backup for retries.
@@ -21420,7 +21467,7 @@
21420
21467
  timeoutMS: options.sharedLockTimeoutMS,
21421
21468
  });
21422
21469
  }
21423
- this.reportError = options.errorReporter || _.bind(logger$6.error, logger$6);
21470
+ this.reportError = options.errorReporter || _.bind(logger$7.error, logger$7);
21424
21471
 
21425
21472
  this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
21426
21473
 
@@ -21753,7 +21800,7 @@
21753
21800
  // maximum interval between request retries after exponential backoff
21754
21801
  var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
21755
21802
 
21756
- var logger$5 = console_with_prefix('batch');
21803
+ var logger$6 = console_with_prefix('batch');
21757
21804
 
21758
21805
  /**
21759
21806
  * RequestBatcher: manages the queueing, flushing, retry etc of requests of one
@@ -21881,7 +21928,7 @@
21881
21928
  */
21882
21929
  RequestBatcher.prototype.flush = function(options) {
21883
21930
  if (this.requestInProgress) {
21884
- logger$5.log('Flush: Request already in progress');
21931
+ logger$6.log('Flush: Request already in progress');
21885
21932
  return PromisePolyfill.resolve();
21886
21933
  }
21887
21934
 
@@ -22058,7 +22105,7 @@
22058
22105
  if (options.unloading) {
22059
22106
  requestOptions.transport = 'sendBeacon';
22060
22107
  }
22061
- logger$5.log('MIXPANEL REQUEST:', dataForRequest);
22108
+ logger$6.log('MIXPANEL REQUEST:', dataForRequest);
22062
22109
  return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
22063
22110
  }, this))
22064
22111
  .catch(_.bind(function(err) {
@@ -22071,7 +22118,7 @@
22071
22118
  * Log error to global logger and optional user-defined logger.
22072
22119
  */
22073
22120
  RequestBatcher.prototype.reportError = function(msg, err) {
22074
- logger$5.error.apply(logger$5.error, arguments);
22121
+ logger$6.error.apply(logger$6.error, arguments);
22075
22122
  if (this.errorReporter) {
22076
22123
  try {
22077
22124
  if (!(err instanceof Error)) {
@@ -22079,7 +22126,7 @@
22079
22126
  }
22080
22127
  this.errorReporter(msg, err);
22081
22128
  } catch(err) {
22082
- logger$5.error(err);
22129
+ logger$6.error(err);
22083
22130
  }
22084
22131
  }
22085
22132
  };
@@ -22096,6 +22143,29 @@
22096
22143
 
22097
22144
  var RECORD_ENQUEUE_THROTTLE_MS = 250;
22098
22145
 
22146
+ var validateAllowedOrigins = function(origins, logger) {
22147
+ if (!_.isArray(origins)) {
22148
+ if (origins) {
22149
+ logger.critical('record_allowed_iframe_origins must be an array of origin strings, cross-origin recording will be disabled.');
22150
+ }
22151
+ return [];
22152
+ }
22153
+ var valid = [];
22154
+ for (var i = 0; i < origins.length; i++) {
22155
+ try {
22156
+ var origin = new URL(origins[i]).origin;
22157
+ if (origin === 'null') {
22158
+ logger.critical(origins[i] + ' has an opaque origin. Skipping this entry.');
22159
+ continue;
22160
+ }
22161
+ valid.push(origin);
22162
+ } catch (e) {
22163
+ logger.critical(origins[i] + ' is not a valid origin URL. Skipping this entry.');
22164
+ }
22165
+ }
22166
+ return valid;
22167
+ };
22168
+
22099
22169
  // stateless utils
22100
22170
  // mostly from https://github.com/mixpanel/mixpanel-js/blob/989ada50f518edab47b9c4fd9535f9fbd5ec5fc0/src/autotrack-utils.js
22101
22171
 
@@ -22201,7 +22271,7 @@
22201
22271
 
22202
22272
  var MAX_DEPTH = 5;
22203
22273
 
22204
- var logger$4 = console_with_prefix('autocapture');
22274
+ var logger$5 = console_with_prefix('autocapture');
22205
22275
 
22206
22276
 
22207
22277
  function getClasses(el) {
@@ -22465,7 +22535,7 @@
22465
22535
  return false;
22466
22536
  }
22467
22537
  } catch (err) {
22468
- logger$4.critical('Error while checking element in allowElementCallback', err);
22538
+ logger$5.critical('Error while checking element in allowElementCallback', err);
22469
22539
  return false;
22470
22540
  }
22471
22541
  }
@@ -22482,7 +22552,7 @@
22482
22552
  return true;
22483
22553
  }
22484
22554
  } catch (err) {
22485
- logger$4.critical('Error while checking selector: ' + sel, err);
22555
+ logger$5.critical('Error while checking selector: ' + sel, err);
22486
22556
  }
22487
22557
  }
22488
22558
  return false;
@@ -22497,7 +22567,7 @@
22497
22567
  return true;
22498
22568
  }
22499
22569
  } catch (err) {
22500
- logger$4.critical('Error while checking element in blockElementCallback', err);
22570
+ logger$5.critical('Error while checking element in blockElementCallback', err);
22501
22571
  return true;
22502
22572
  }
22503
22573
  }
@@ -22511,7 +22581,7 @@
22511
22581
  return true;
22512
22582
  }
22513
22583
  } catch (err) {
22514
- logger$4.critical('Error while checking selector: ' + sel, err);
22584
+ logger$5.critical('Error while checking selector: ' + sel, err);
22515
22585
  }
22516
22586
  }
22517
22587
  }
@@ -23067,7 +23137,7 @@
23067
23137
  *
23068
23138
  */
23069
23139
 
23070
- var logger$3 = console_with_prefix('network-plugin');
23140
+ var logger$4 = console_with_prefix('network-plugin');
23071
23141
 
23072
23142
  /**
23073
23143
  * Get the time origin for converting performance timestamps to absolute timestamps.
@@ -23219,7 +23289,7 @@
23219
23289
  return str;
23220
23290
  }
23221
23291
  if (str.length > MAX_BODY_SIZE) {
23222
- logger$3.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
23292
+ logger$4.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
23223
23293
  return str.substring(0, MAX_BODY_SIZE) + '... [truncated]';
23224
23294
  }
23225
23295
  return str;
@@ -23233,7 +23303,7 @@
23233
23303
  */
23234
23304
  function initPerformanceObserver(cb, win, options) {
23235
23305
  if (!win.PerformanceObserver) {
23236
- logger$3.error('PerformanceObserver not supported');
23306
+ logger$4.error('PerformanceObserver not supported');
23237
23307
  return function() {
23238
23308
  //
23239
23309
  };
@@ -23386,7 +23456,7 @@
23386
23456
  attempt = 0;
23387
23457
  }
23388
23458
  if (attempt > 10) {
23389
- logger$3.error('Cannot find performance entry');
23459
+ logger$4.error('Cannot find performance entry');
23390
23460
  return Promise.resolve(null);
23391
23461
  }
23392
23462
  var urlPerformanceEntries = /** @type {PerformanceResourceTiming[]} */ (
@@ -23507,7 +23577,7 @@
23507
23577
  )
23508
23578
  .then(function(entry) {
23509
23579
  if (!entry) {
23510
- logger$3.error('Failed to get performance entry for XHR request to ' + req.url);
23580
+ logger$4.error('Failed to get performance entry for XHR request to ' + req.url);
23511
23581
  return;
23512
23582
  }
23513
23583
  /** @type {NetworkRequest} */
@@ -23527,7 +23597,7 @@
23527
23597
  cb({ requests: [request] });
23528
23598
  })
23529
23599
  .catch(function(e) {
23530
- logger$3.error('Error recording XHR request to ' + req.url + ': ' + String(e));
23600
+ logger$4.error('Error recording XHR request to ' + req.url + ': ' + String(e));
23531
23601
  });
23532
23602
  });
23533
23603
 
@@ -23619,7 +23689,7 @@
23619
23689
  })
23620
23690
  .then(function(entry) {
23621
23691
  if (!entry) {
23622
- logger$3.error('Failed to get performance entry for fetch request to ' + req.url);
23692
+ logger$4.error('Failed to get performance entry for fetch request to ' + req.url);
23623
23693
  return;
23624
23694
  }
23625
23695
  /** @type {NetworkRequest} */
@@ -23639,7 +23709,7 @@
23639
23709
  cb({ requests: [request] });
23640
23710
  })
23641
23711
  .catch(function (e) {
23642
- logger$3.error('Error recording fetch request to ' + req.url + ': ' + String(e));
23712
+ logger$4.error('Error recording fetch request to ' + req.url + ': ' + String(e));
23643
23713
  });
23644
23714
 
23645
23715
  return originalFetchPromise;
@@ -23712,7 +23782,7 @@
23712
23782
  */
23713
23783
 
23714
23784
 
23715
- var logger$2 = console_with_prefix('recorder');
23785
+ var logger$3 = console_with_prefix('recorder');
23716
23786
  var CompressionStream = win['CompressionStream'];
23717
23787
 
23718
23788
  var RECORDER_BATCHER_LIB_CONFIG = {
@@ -23892,14 +23962,14 @@
23892
23962
  }
23893
23963
 
23894
23964
  if (this._stopRecording !== null) {
23895
- logger$2.log('Recording already in progress, skipping startRecording.');
23965
+ logger$3.log('Recording already in progress, skipping startRecording.');
23896
23966
  return;
23897
23967
  }
23898
23968
 
23899
23969
  this.recordMaxMs = this.getConfig('record_max_ms');
23900
23970
  if (this.recordMaxMs > MAX_RECORDING_MS) {
23901
23971
  this.recordMaxMs = MAX_RECORDING_MS;
23902
- logger$2.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
23972
+ logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
23903
23973
  }
23904
23974
 
23905
23975
  if (!this.maxExpires) {
@@ -23963,6 +24033,8 @@
23963
24033
  );
23964
24034
  }
23965
24035
 
24036
+ var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$3);
24037
+
23966
24038
  try {
23967
24039
  this._stopRecording = this._rrwebRecord({
23968
24040
  'emit': function (ev) {
@@ -23997,6 +24069,8 @@
23997
24069
  'maskTextSelector': '*',
23998
24070
  'maskInputFn': this._getMaskFn(shouldMaskInput, privacyConfig),
23999
24071
  'maskTextFn': this._getMaskFn(shouldMaskText, privacyConfig),
24072
+ 'recordCrossOriginIframes': validatedOrigins.length > 0,
24073
+ 'allowedIframeOrigins': validatedOrigins,
24000
24074
  'recordCanvas': this.getConfig('record_canvas'),
24001
24075
  'sampling': {
24002
24076
  'canvas': 15
@@ -24221,14 +24295,14 @@
24221
24295
 
24222
24296
 
24223
24297
  SessionRecording.prototype.reportError = function(msg, err) {
24224
- logger$2.error.apply(logger$2.error, arguments);
24298
+ logger$3.error.apply(logger$3.error, arguments);
24225
24299
  try {
24226
24300
  if (!err && !(msg instanceof Error)) {
24227
24301
  msg = new Error(msg);
24228
24302
  }
24229
24303
  this.getConfig('error_reporter')(msg, err);
24230
24304
  } catch(err) {
24231
- logger$2.error(err);
24305
+ logger$3.error(err);
24232
24306
  }
24233
24307
  };
24234
24308
 
@@ -24257,7 +24331,7 @@
24257
24331
  var configValue = this.getConfig('record_min_ms');
24258
24332
 
24259
24333
  if (configValue > MAX_VALUE_FOR_MIN_RECORDING_MS) {
24260
- logger$2.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
24334
+ logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
24261
24335
  return MAX_VALUE_FOR_MIN_RECORDING_MS;
24262
24336
  }
24263
24337
 
@@ -24420,7 +24494,7 @@
24420
24494
  .catch(this.handleError.bind(this));
24421
24495
  };
24422
24496
 
24423
- var logger$1 = console_with_prefix('recorder');
24497
+ var logger$2 = console_with_prefix('recorder');
24424
24498
 
24425
24499
  /**
24426
24500
  * Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
@@ -24436,7 +24510,7 @@
24436
24510
  */
24437
24511
  this.recordingRegistry = new RecordingRegistry({
24438
24512
  mixpanelInstance: this.mixpanelInstance,
24439
- errorReporter: logger$1.error,
24513
+ errorReporter: logger$2.error,
24440
24514
  sharedLockStorage: sharedLockStorage
24441
24515
  });
24442
24516
  this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
@@ -24448,17 +24522,17 @@
24448
24522
  MixpanelRecorder.prototype.startRecording = function(options) {
24449
24523
  options = options || {};
24450
24524
  if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
24451
- logger$1.log('Recording already in progress, skipping startRecording.');
24525
+ logger$2.log('Recording already in progress, skipping startRecording.');
24452
24526
  return;
24453
24527
  }
24454
24528
 
24455
24529
  var onIdleTimeout = function () {
24456
- logger$1.log('Idle timeout reached, restarting recording.');
24530
+ logger$2.log('Idle timeout reached, restarting recording.');
24457
24531
  this.resetRecording();
24458
24532
  }.bind(this);
24459
24533
 
24460
24534
  var onMaxLengthReached = function () {
24461
- logger$1.log('Max recording length reached, stopping recording.');
24535
+ logger$2.log('Max recording length reached, stopping recording.');
24462
24536
  this.resetRecording();
24463
24537
  }.bind(this);
24464
24538
 
@@ -24528,7 +24602,7 @@
24528
24602
  } else if (startNewIfInactive) {
24529
24603
  return this.startRecording({shouldStopBatcher: false});
24530
24604
  } else {
24531
- logger$1.log('No resumable recording found.');
24605
+ logger$2.log('No resumable recording found.');
24532
24606
  return null;
24533
24607
  }
24534
24608
  }.bind(this));
@@ -25193,7 +25267,7 @@
25193
25267
  observer.observe(shadowRoot, this.observerConfig);
25194
25268
  this.shadowObservers.push(observer);
25195
25269
  } catch (e) {
25196
- logger$4.critical('Error while observing shadow root', e);
25270
+ logger$5.critical('Error while observing shadow root', e);
25197
25271
  }
25198
25272
  };
25199
25273
 
@@ -25204,7 +25278,7 @@
25204
25278
  }
25205
25279
 
25206
25280
  if (!weakSetSupported()) {
25207
- logger$4.critical('Shadow DOM observation unavailable: WeakSet not supported');
25281
+ logger$5.critical('Shadow DOM observation unavailable: WeakSet not supported');
25208
25282
  return;
25209
25283
  }
25210
25284
 
@@ -25220,7 +25294,7 @@
25220
25294
  try {
25221
25295
  this.shadowObservers[i].disconnect();
25222
25296
  } catch (e) {
25223
- logger$4.critical('Error while disconnecting shadow DOM observer', e);
25297
+ logger$5.critical('Error while disconnecting shadow DOM observer', e);
25224
25298
  }
25225
25299
  }
25226
25300
  this.shadowObservers = [];
@@ -25408,7 +25482,7 @@
25408
25482
 
25409
25483
  this.mutationObserver.observe(document.body || document.documentElement, MUTATION_OBSERVER_CONFIG);
25410
25484
  } catch (e) {
25411
- logger$4.critical('Error while setting up mutation observer', e);
25485
+ logger$5.critical('Error while setting up mutation observer', e);
25412
25486
  }
25413
25487
  }
25414
25488
 
@@ -25423,7 +25497,7 @@
25423
25497
  );
25424
25498
  this.shadowDOMObserver.start();
25425
25499
  } catch (e) {
25426
- logger$4.critical('Error while setting up shadow DOM observer', e);
25500
+ logger$5.critical('Error while setting up shadow DOM observer', e);
25427
25501
  this.shadowDOMObserver = null;
25428
25502
  }
25429
25503
  }
@@ -25450,7 +25524,7 @@
25450
25524
  try {
25451
25525
  listener.target.removeEventListener(listener.event, listener.handler, listener.options);
25452
25526
  } catch (e) {
25453
- logger$4.critical('Error while removing event listener', e);
25527
+ logger$5.critical('Error while removing event listener', e);
25454
25528
  }
25455
25529
  }
25456
25530
  this.eventListeners = [];
@@ -25459,7 +25533,7 @@
25459
25533
  try {
25460
25534
  this.mutationObserver.disconnect();
25461
25535
  } catch (e) {
25462
- logger$4.critical('Error while disconnecting mutation observer', e);
25536
+ logger$5.critical('Error while disconnecting mutation observer', e);
25463
25537
  }
25464
25538
  this.mutationObserver = null;
25465
25539
  }
@@ -25468,7 +25542,7 @@
25468
25542
  try {
25469
25543
  this.shadowDOMObserver.stop();
25470
25544
  } catch (e) {
25471
- logger$4.critical('Error while stopping shadow DOM observer', e);
25545
+ logger$5.critical('Error while stopping shadow DOM observer', e);
25472
25546
  }
25473
25547
  this.shadowDOMObserver = null;
25474
25548
  }
@@ -25546,7 +25620,7 @@
25546
25620
 
25547
25621
  Autocapture.prototype.init = function() {
25548
25622
  if (!minDOMApisSupported()) {
25549
- logger$4.critical('Autocapture unavailable: missing required DOM APIs');
25623
+ logger$5.critical('Autocapture unavailable: missing required DOM APIs');
25550
25624
  return;
25551
25625
  }
25552
25626
  this.initPageListeners();
@@ -25586,7 +25660,7 @@
25586
25660
  try {
25587
25661
  return !urlMatchesRegexList(currentUrl, allowUrlRegexes);
25588
25662
  } catch (err) {
25589
- logger$4.critical('Error while checking block URL regexes: ', err);
25663
+ logger$5.critical('Error while checking block URL regexes: ', err);
25590
25664
  return true;
25591
25665
  }
25592
25666
  }
@@ -25599,7 +25673,7 @@
25599
25673
  try {
25600
25674
  return urlMatchesRegexList(currentUrl, blockUrlRegexes);
25601
25675
  } catch (err) {
25602
- logger$4.critical('Error while checking block URL regexes: ', err);
25676
+ logger$5.critical('Error while checking block URL regexes: ', err);
25603
25677
  return true;
25604
25678
  }
25605
25679
  };
@@ -25737,7 +25811,7 @@
25737
25811
  return;
25738
25812
  }
25739
25813
 
25740
- logger$4.log('Initializing scroll depth tracking');
25814
+ logger$5.log('Initializing scroll depth tracking');
25741
25815
 
25742
25816
  this.maxScrollViewDepth = Math.max(document$1.documentElement.clientHeight, win.innerHeight || 0);
25743
25817
 
@@ -25763,7 +25837,7 @@
25763
25837
  if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
25764
25838
  return;
25765
25839
  }
25766
- logger$4.log('Initializing click tracking');
25840
+ logger$5.log('Initializing click tracking');
25767
25841
 
25768
25842
  this.listenerClick = function(ev) {
25769
25843
  if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
@@ -25782,7 +25856,7 @@
25782
25856
  return;
25783
25857
  }
25784
25858
 
25785
- logger$4.log('Initializing dead click tracking');
25859
+ logger$5.log('Initializing dead click tracking');
25786
25860
  if (!this._deadClickTracker) {
25787
25861
  this._deadClickTracker = new DeadClickTracker(function(deadClickEvent) {
25788
25862
  this.trackDomEvent(deadClickEvent, MP_EV_DEAD_CLICK);
@@ -25816,7 +25890,7 @@
25816
25890
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
25817
25891
  return;
25818
25892
  }
25819
- logger$4.log('Initializing input tracking');
25893
+ logger$5.log('Initializing input tracking');
25820
25894
 
25821
25895
  this.listenerChange = function(ev) {
25822
25896
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
@@ -25833,7 +25907,7 @@
25833
25907
  if (!this.pageviewTrackingConfig()) {
25834
25908
  return;
25835
25909
  }
25836
- logger$4.log('Initializing pageview tracking');
25910
+ logger$5.log('Initializing pageview tracking');
25837
25911
 
25838
25912
  var previousTrackedUrl = '';
25839
25913
  var tracked = false;
@@ -25868,7 +25942,7 @@
25868
25942
  }
25869
25943
  if (didPathChange) {
25870
25944
  this.lastScrollCheckpoint = 0;
25871
- logger$4.log('Path change: re-initializing scroll depth checkpoints');
25945
+ logger$5.log('Path change: re-initializing scroll depth checkpoints');
25872
25946
  }
25873
25947
  }
25874
25948
  }.bind(this));
@@ -25883,7 +25957,7 @@
25883
25957
  return;
25884
25958
  }
25885
25959
 
25886
- logger$4.log('Initializing rage click tracking');
25960
+ logger$5.log('Initializing rage click tracking');
25887
25961
  if (!this._rageClickTracker) {
25888
25962
  this._rageClickTracker = new RageClickTracker();
25889
25963
  }
@@ -25913,7 +25987,7 @@
25913
25987
  if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
25914
25988
  return;
25915
25989
  }
25916
- logger$4.log('Initializing scroll tracking');
25990
+ logger$5.log('Initializing scroll tracking');
25917
25991
  this.lastScrollCheckpoint = 0;
25918
25992
 
25919
25993
  var scrollTrackFunction = function() {
@@ -25950,7 +26024,7 @@
25950
26024
  }
25951
26025
  }
25952
26026
  } catch (err) {
25953
- logger$4.critical('Error while calculating scroll percentage', err);
26027
+ logger$5.critical('Error while calculating scroll percentage', err);
25954
26028
  }
25955
26029
  if (shouldTrack) {
25956
26030
  this.mp.track(MP_EV_SCROLL, props);
@@ -25968,7 +26042,7 @@
25968
26042
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
25969
26043
  return;
25970
26044
  }
25971
- logger$4.log('Initializing submit tracking');
26045
+ logger$5.log('Initializing submit tracking');
25972
26046
 
25973
26047
  this.listenerSubmit = function(ev) {
25974
26048
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
@@ -25990,7 +26064,7 @@
25990
26064
  return;
25991
26065
  }
25992
26066
 
25993
- logger$4.log('Initializing page visibility tracking.');
26067
+ logger$5.log('Initializing page visibility tracking.');
25994
26068
  this._initScrollDepthTracking();
25995
26069
  var previousTrackedUrl = _.info.currentUrl();
25996
26070
 
@@ -26075,7 +26149,7 @@
26075
26149
  return win[TARGETING_GLOBAL_NAME];
26076
26150
  };
26077
26151
 
26078
- var logger = console_with_prefix('flags');
26152
+ var logger$1 = console_with_prefix('flags');
26079
26153
  var FLAGS_CONFIG_KEY = 'flags';
26080
26154
 
26081
26155
  var CONFIG_CONTEXT = 'context';
@@ -26118,7 +26192,7 @@
26118
26192
 
26119
26193
  FeatureFlagManager.prototype.init = function() {
26120
26194
  if (!this.minApisSupported()) {
26121
- logger.critical('Feature Flags unavailable: missing minimum required APIs');
26195
+ logger$1.critical('Feature Flags unavailable: missing minimum required APIs');
26122
26196
  return;
26123
26197
  }
26124
26198
 
@@ -26153,7 +26227,7 @@
26153
26227
 
26154
26228
  FeatureFlagManager.prototype.updateContext = function(newContext, options) {
26155
26229
  if (!this.isSystemEnabled()) {
26156
- logger.critical('Feature Flags not enabled, cannot update context');
26230
+ logger$1.critical('Feature Flags not enabled, cannot update context');
26157
26231
  return Promise.resolve();
26158
26232
  }
26159
26233
 
@@ -26170,7 +26244,7 @@
26170
26244
 
26171
26245
  FeatureFlagManager.prototype.areFlagsReady = function() {
26172
26246
  if (!this.isSystemEnabled()) {
26173
- logger.error('Feature Flags not enabled');
26247
+ logger$1.error('Feature Flags not enabled');
26174
26248
  }
26175
26249
  return !!this.flags;
26176
26250
  };
@@ -26183,7 +26257,7 @@
26183
26257
  var distinctId = this.getMpProperty('distinct_id');
26184
26258
  var deviceId = this.getMpProperty('$device_id');
26185
26259
  var traceparent = generateTraceparent();
26186
- logger.log('Fetching flags for distinct ID: ' + distinctId);
26260
+ logger$1.log('Fetching flags for distinct ID: ' + distinctId);
26187
26261
 
26188
26262
  var context = _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT));
26189
26263
  var searchParams = new URLSearchParams();
@@ -26282,11 +26356,11 @@
26282
26356
  this._loadTargetingIfNeeded();
26283
26357
  }.bind(this)).catch(function(error) {
26284
26358
  this.markFetchComplete();
26285
- logger.error(error);
26359
+ logger$1.error(error);
26286
26360
  }.bind(this));
26287
26361
  }.bind(this)).catch(function(error) {
26288
26362
  this.markFetchComplete();
26289
- logger.error(error);
26363
+ logger$1.error(error);
26290
26364
  }.bind(this));
26291
26365
 
26292
26366
  return this.fetchPromise;
@@ -26294,7 +26368,7 @@
26294
26368
 
26295
26369
  FeatureFlagManager.prototype.markFetchComplete = function() {
26296
26370
  if (!this._fetchInProgressStartTime) {
26297
- logger.error('Fetch in progress started time not set, cannot mark fetch complete');
26371
+ logger$1.error('Fetch in progress started time not set, cannot mark fetch complete');
26298
26372
  return;
26299
26373
  }
26300
26374
  this._fetchStartTime = this._fetchInProgressStartTime;
@@ -26316,7 +26390,7 @@
26316
26390
 
26317
26391
  if (hasPropertyFilters) {
26318
26392
  this.getTargeting().then(function() {
26319
- logger.log('targeting loaded for property filter evaluation');
26393
+ logger$1.log('targeting loaded for property filter evaluation');
26320
26394
  });
26321
26395
  }
26322
26396
  };
@@ -26331,7 +26405,7 @@
26331
26405
  this.loadExtraBundle.bind(this),
26332
26406
  this.targetingSrc
26333
26407
  ).catch(function(error) {
26334
- logger.error('Failed to load targeting: ' + error);
26408
+ logger$1.error('Failed to load targeting: ' + error);
26335
26409
  }.bind(this));
26336
26410
  };
26337
26411
 
@@ -26385,7 +26459,7 @@
26385
26459
 
26386
26460
  // If no targeting library and event has property filters, skip it
26387
26461
  if (!targeting && pendingEvent['property_filters'] && !_.isEmptyObject(pendingEvent['property_filters'])) {
26388
- logger.warn('Skipping event check for "' + flagKey + '" - property filters require targeting library');
26462
+ logger$1.warn('Skipping event check for "' + flagKey + '" - property filters require targeting library');
26389
26463
  return;
26390
26464
  }
26391
26465
 
@@ -26408,7 +26482,7 @@
26408
26482
  }
26409
26483
 
26410
26484
  if (matchResult.error) {
26411
- logger.error('Error checking first-time event for flag "' + flagKey + '": ' + matchResult.error);
26485
+ logger$1.error('Error checking first-time event for flag "' + flagKey + '": ' + matchResult.error);
26412
26486
  return;
26413
26487
  }
26414
26488
 
@@ -26416,7 +26490,7 @@
26416
26490
  return;
26417
26491
  }
26418
26492
 
26419
- logger.log('First-time event matched for flag "' + flagKey + '": ' + eventName);
26493
+ logger$1.log('First-time event matched for flag "' + flagKey + '": ' + eventName);
26420
26494
 
26421
26495
  var newVariant = {
26422
26496
  'key': pendingEvent['pending_variant']['variant_key'],
@@ -26457,7 +26531,7 @@
26457
26531
  'first_time_event_hash': firstTimeEventHash
26458
26532
  };
26459
26533
 
26460
- logger.log('Recording first-time event for flag: ' + flagId);
26534
+ logger$1.log('Recording first-time event for flag: ' + flagId);
26461
26535
 
26462
26536
  // Fire-and-forget POST request
26463
26537
  this.fetch.call(win, url, {
@@ -26470,14 +26544,14 @@
26470
26544
  'body': JSON.stringify(payload)
26471
26545
  }).catch(function(error) {
26472
26546
  // Silent failure - cohort sync will catch up
26473
- logger.error('Failed to record first-time event for flag ' + flagId + ': ' + error);
26547
+ logger$1.error('Failed to record first-time event for flag ' + flagId + ': ' + error);
26474
26548
  });
26475
26549
  };
26476
26550
 
26477
26551
  FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
26478
26552
  if (!this.fetchPromise) {
26479
26553
  return new Promise(function(resolve) {
26480
- logger.critical('Feature Flags not initialized');
26554
+ logger$1.critical('Feature Flags not initialized');
26481
26555
  resolve(fallback);
26482
26556
  });
26483
26557
  }
@@ -26485,19 +26559,19 @@
26485
26559
  return this.fetchPromise.then(function() {
26486
26560
  return this.getVariantSync(featureName, fallback);
26487
26561
  }.bind(this)).catch(function(error) {
26488
- logger.error(error);
26562
+ logger$1.error(error);
26489
26563
  return fallback;
26490
26564
  });
26491
26565
  };
26492
26566
 
26493
26567
  FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
26494
26568
  if (!this.areFlagsReady()) {
26495
- logger.log('Flags not loaded yet');
26569
+ logger$1.log('Flags not loaded yet');
26496
26570
  return fallback;
26497
26571
  }
26498
26572
  var feature = this.flags.get(featureName);
26499
26573
  if (!feature) {
26500
- logger.log('No flag found: "' + featureName + '"');
26574
+ logger$1.log('No flag found: "' + featureName + '"');
26501
26575
  return fallback;
26502
26576
  }
26503
26577
  this.trackFeatureCheck(featureName, feature);
@@ -26508,14 +26582,14 @@
26508
26582
  return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
26509
26583
  return feature['value'];
26510
26584
  }).catch(function(error) {
26511
- logger.error(error);
26585
+ logger$1.error(error);
26512
26586
  return fallbackValue;
26513
26587
  });
26514
26588
  };
26515
26589
 
26516
26590
  // TODO remove deprecated method
26517
26591
  FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
26518
- logger.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
26592
+ 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.');
26519
26593
  return this.getVariantValue(featureName, fallbackValue);
26520
26594
  };
26521
26595
 
@@ -26527,7 +26601,7 @@
26527
26601
  return this.getVariantValue(featureName).then(function() {
26528
26602
  return this.isEnabledSync(featureName, fallbackValue);
26529
26603
  }.bind(this)).catch(function(error) {
26530
- logger.error(error);
26604
+ logger$1.error(error);
26531
26605
  return fallbackValue;
26532
26606
  });
26533
26607
  };
@@ -26536,7 +26610,7 @@
26536
26610
  fallbackValue = fallbackValue || false;
26537
26611
  var val = this.getVariantValueSync(featureName, fallbackValue);
26538
26612
  if (val !== true && val !== false) {
26539
- logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
26613
+ logger$1.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
26540
26614
  val = fallbackValue;
26541
26615
  }
26542
26616
  return val;
@@ -26598,6 +26672,12 @@
26598
26672
  /* eslint camelcase: "off" */
26599
26673
 
26600
26674
 
26675
+ var logger = console_with_prefix('recorder');
26676
+
26677
+ var IFRAME_HANDSHAKE_REQUEST = 'mp_iframe_handshake_request';
26678
+ var IFRAME_HANDSHAKE_RESPONSE = 'mp_iframe_handshake_response';
26679
+
26680
+
26601
26681
  /**
26602
26682
  * RecorderManager: manages session recording initialization, lifecycle and state
26603
26683
  * @constructor
@@ -26617,6 +26697,8 @@
26617
26697
  this.libBasePath = initOptions.libBasePath;
26618
26698
 
26619
26699
  this._recorder = null;
26700
+ this._parentReplayId = null;
26701
+ this._parentFrameRetryInterval = null;
26620
26702
  };
26621
26703
 
26622
26704
  RecorderManager.prototype.shouldLoadRecorder = function() {
@@ -26670,6 +26752,22 @@
26670
26752
  }, this));
26671
26753
  }, this);
26672
26754
 
26755
+ // Cross-origin iframe handling
26756
+ var allowedOrigins = validateAllowedOrigins(this.getMpConfig('record_allowed_iframe_origins'), logger);
26757
+ var isCrossOriginRecordingEnabled = allowedOrigins.length > 0;
26758
+
26759
+ if (isCrossOriginRecordingEnabled) {
26760
+ // listen for handshake requests from their own child iframes (including nested)
26761
+ this._setupParentFrameListener(allowedOrigins);
26762
+
26763
+ if (win.parent !== win) {
26764
+ // also wait for parent's replay ID
26765
+ this._setupChildFrameListener(allowedOrigins, loadRecorder);
26766
+ this._sendParentFrameRequestWithRetry(allowedOrigins);
26767
+ return PromisePolyfill.resolve();
26768
+ }
26769
+ }
26770
+
26673
26771
  /**
26674
26772
  * If the user is sampled or start_session_recording is called, we always load the recorder since it's guaranteed a recording should start.
26675
26773
  * 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.
@@ -26789,6 +26887,10 @@
26789
26887
  };
26790
26888
 
26791
26889
  RecorderManager.prototype.getSessionReplayId = function() {
26890
+ // Child iframe uses parent's replay ID
26891
+ if (this._parentReplayId) {
26892
+ return this._parentReplayId;
26893
+ }
26792
26894
  var replay_id = null;
26793
26895
  if (this._recorder) {
26794
26896
  replay_id = this._recorder['replayId'];
@@ -26801,6 +26903,86 @@
26801
26903
  return this._recorder;
26802
26904
  };
26803
26905
 
26906
+ RecorderManager.prototype._setupChildFrameListener = function(allowedOrigins, loadRecorder) {
26907
+ if (this._childFrameMessageHandler) {
26908
+ return;
26909
+ }
26910
+ var self = this;
26911
+ this._childFrameMessageHandler = function(event) {
26912
+ if (allowedOrigins.indexOf(event.origin) === -1) return;
26913
+ var data = event.data;
26914
+ if (data && data['type'] === IFRAME_HANDSHAKE_RESPONSE && data['token'] === self.getMpConfig('token') && data['replayId']) {
26915
+ self._parentReplayId = data['replayId'];
26916
+ if (data['distinctId']) {
26917
+ self.mixpanelInstance['identify'](data['distinctId']);
26918
+ }
26919
+ self._parentFrameRetryActive = false;
26920
+ win.removeEventListener('message', self._childFrameMessageHandler);
26921
+ self._childFrameMessageHandler = null;
26922
+ loadRecorder(true);
26923
+ }
26924
+ };
26925
+ win.addEventListener('message', this._childFrameMessageHandler);
26926
+ };
26927
+
26928
+ RecorderManager.prototype._sendParentFrameRequest = function(allowedOrigins) {
26929
+ var message = {};
26930
+ message['type'] = IFRAME_HANDSHAKE_REQUEST;
26931
+ message['token'] = this.getMpConfig('token');
26932
+ for (var i = 0; i < allowedOrigins.length; i++) {
26933
+ try {
26934
+ win.parent.postMessage(message, allowedOrigins[i]);
26935
+ } catch (e) {
26936
+ // origin mismatch - ignore
26937
+ }
26938
+ }
26939
+ };
26940
+
26941
+ RecorderManager.prototype._sendParentFrameRequestWithRetry = function(allowedOrigins) {
26942
+ var self = this;
26943
+ var maxRetries = 10;
26944
+ var retryCount = 0;
26945
+ var delay = 50;
26946
+ this._parentFrameRetryActive = true;
26947
+
26948
+ this._sendParentFrameRequest(allowedOrigins);
26949
+
26950
+ function scheduleRetry() {
26951
+ setTimeout(function() {
26952
+ if (!self._parentFrameRetryActive || self._parentReplayId || ++retryCount >= maxRetries) {
26953
+ return;
26954
+ }
26955
+ self._sendParentFrameRequest(allowedOrigins);
26956
+ delay *= 2;
26957
+ scheduleRetry();
26958
+ }, delay);
26959
+ }
26960
+ scheduleRetry();
26961
+ };
26962
+
26963
+ RecorderManager.prototype._setupParentFrameListener = function(allowedOrigins) {
26964
+ if (this._parentFrameMessageHandler) {
26965
+ return;
26966
+ }
26967
+ var self = this;
26968
+ this._parentFrameMessageHandler = function(event) {
26969
+ if (allowedOrigins.indexOf(event.origin) === -1) return;
26970
+ var data = event.data;
26971
+ if (data && data['type'] === IFRAME_HANDSHAKE_REQUEST && data['token'] === self.getMpConfig('token')) {
26972
+ var replayId = self.getSessionReplayId();
26973
+ if (replayId) {
26974
+ var response = {};
26975
+ response['type'] = IFRAME_HANDSHAKE_RESPONSE;
26976
+ response['token'] = self.getMpConfig('token');
26977
+ response['replayId'] = replayId;
26978
+ response['distinctId'] = self.getDistinctId();
26979
+ event.source.postMessage(response, event.origin);
26980
+ }
26981
+ }
26982
+ };
26983
+ win.addEventListener('message', this._parentFrameMessageHandler);
26984
+ };
26985
+
26804
26986
  safewrapClass(RecorderManager);
26805
26987
 
26806
26988
  /* eslint camelcase: "off" */
@@ -28175,7 +28357,6 @@
28175
28357
  /** @const */ var SETTING_FALLBACK = 'fallback';
28176
28358
  /** @const */ var SETTING_DISABLED = 'disabled';
28177
28359
 
28178
-
28179
28360
  /*
28180
28361
  * Dynamic... constants? Is that an oxymoron?
28181
28362
  */
@@ -28260,6 +28441,7 @@
28260
28441
  'batch_request_timeout_ms': 90000,
28261
28442
  'batch_autostart': true,
28262
28443
  'hooks': {},
28444
+ 'record_allowed_iframe_origins': [],
28263
28445
  'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
28264
28446
  'record_block_selector': 'img, video, audio',
28265
28447
  'record_canvas': false,