mixpanel-browser 2.67.0 → 2.69.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.
@@ -489,6 +489,30 @@
489
489
  function mutationObserverCtor$1() {
490
490
  return getUntaintedPrototype$1("MutationObserver").constructor;
491
491
  }
492
+ function patch$1(source, name, replacement) {
493
+ try {
494
+ if (!(name in source)) {
495
+ return function() {};
496
+ }
497
+ var original = source[name];
498
+ var wrapped = replacement(original);
499
+ if (typeof wrapped === "function") {
500
+ wrapped.prototype = wrapped.prototype || {};
501
+ Object.defineProperties(wrapped, {
502
+ __rrweb_original__: {
503
+ enumerable: false,
504
+ value: original
505
+ }
506
+ });
507
+ }
508
+ source[name] = wrapped;
509
+ return function() {
510
+ source[name] = original;
511
+ };
512
+ } catch (e) {
513
+ return function() {};
514
+ }
515
+ }
492
516
  var index$1 = {
493
517
  childNodes: childNodes$1,
494
518
  parentNode: parentNode$1,
@@ -501,7 +525,8 @@
501
525
  shadowRoot: shadowRoot$1,
502
526
  querySelector: querySelector$1,
503
527
  querySelectorAll: querySelectorAll$1,
504
- mutationObserver: mutationObserverCtor$1
528
+ mutationObserver: mutationObserverCtor$1,
529
+ patch: patch$1
505
530
  };
506
531
  function isElement(n2) {
507
532
  return n2.nodeType === n2.ELEMENT_NODE;
@@ -752,26 +777,82 @@
752
777
  return "url(" + maybeQuote + stack.join("/") + maybeQuote + ")";
753
778
  });
754
779
  }
755
- function normalizeCssString(cssText) {
756
- return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
780
+ function normalizeCssString(cssText, _testNoPxNorm) {
781
+ if (_testNoPxNorm === void 0) _testNoPxNorm = false;
782
+ if (_testNoPxNorm) {
783
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
784
+ } else {
785
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
786
+ }
757
787
  }
758
- function splitCssText(cssText, style) {
788
+ function splitCssText(cssText, style, _testNoPxNorm) {
789
+ if (_testNoPxNorm === void 0) _testNoPxNorm = false;
759
790
  var childNodes2 = Array.from(style.childNodes);
760
791
  var splits = [];
792
+ var iterCount = 0;
761
793
  if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
762
- var cssTextNorm = normalizeCssString(cssText);
794
+ var cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
795
+ var normFactor = cssTextNorm.length / cssText.length;
763
796
  for(var i2 = 1; i2 < childNodes2.length; i2++){
764
797
  if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
765
- var textContentNorm = normalizeCssString(childNodes2[i2].textContent);
766
- for(var j = 3; j < textContentNorm.length; j++){
767
- var bit = textContentNorm.substring(0, j);
768
- if (cssTextNorm.split(bit).length === 2) {
769
- var splitNorm = cssTextNorm.indexOf(bit);
770
- for(var k = splitNorm; k < cssText.length; k++){
771
- if (normalizeCssString(cssText.substring(0, k)).length === splitNorm) {
798
+ var textContentNorm = normalizeCssString(childNodes2[i2].textContent, _testNoPxNorm);
799
+ var jLimit = 100;
800
+ var j = 3;
801
+ for(; j < textContentNorm.length; j++){
802
+ if (// keep consuming css identifiers (to get a decent chunk more quickly)
803
+ textContentNorm[j].match(/[a-zA-Z0-9]/) || // substring needs to be unique to this section
804
+ textContentNorm.indexOf(textContentNorm.substring(0, j), 1) !== -1) {
805
+ continue;
806
+ }
807
+ break;
808
+ }
809
+ for(; j < textContentNorm.length; j++){
810
+ var startSubstring = textContentNorm.substring(0, j);
811
+ var cssNormSplits = cssTextNorm.split(startSubstring);
812
+ var splitNorm = -1;
813
+ if (cssNormSplits.length === 2) {
814
+ splitNorm = cssNormSplits[0].length;
815
+ } else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
816
+ splitNorm = cssTextNorm.indexOf(startSubstring, 1);
817
+ } else if (cssNormSplits.length === 1) {
818
+ startSubstring = startSubstring.substring(0, startSubstring.length - 1);
819
+ cssNormSplits = cssTextNorm.split(startSubstring);
820
+ if (cssNormSplits.length <= 1) {
821
+ splits.push(cssText);
822
+ return splits;
823
+ }
824
+ j = jLimit + 1;
825
+ } else if (j === textContentNorm.length - 1) {
826
+ splitNorm = cssTextNorm.indexOf(startSubstring);
827
+ }
828
+ if (cssNormSplits.length >= 2 && j > jLimit) {
829
+ var prevTextContent = childNodes2[i2 - 1].textContent;
830
+ if (prevTextContent && typeof prevTextContent === "string") {
831
+ var prevMinLength = normalizeCssString(prevTextContent).length;
832
+ splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
833
+ }
834
+ if (splitNorm === -1) {
835
+ splitNorm = cssNormSplits[0].length;
836
+ }
837
+ }
838
+ if (splitNorm !== -1) {
839
+ var k = Math.floor(splitNorm / normFactor);
840
+ for(; k > 0 && k < cssText.length;){
841
+ iterCount += 1;
842
+ if (iterCount > 50 * childNodes2.length) {
843
+ splits.push(cssText);
844
+ return splits;
845
+ }
846
+ var normPart = normalizeCssString(cssText.substring(0, k), _testNoPxNorm);
847
+ if (normPart.length === splitNorm) {
772
848
  splits.push(cssText.substring(0, k));
773
849
  cssText = cssText.substring(k);
850
+ cssTextNorm = cssTextNorm.substring(splitNorm);
774
851
  break;
852
+ } else if (normPart.length < splitNorm) {
853
+ k += Math.max(1, Math.floor((splitNorm - normPart.length) / normFactor));
854
+ } else {
855
+ k -= Math.max(1, Math.floor((normPart.length - splitNorm) * normFactor));
775
856
  }
776
857
  }
777
858
  break;
@@ -1288,7 +1369,7 @@
1288
1369
  } else if (sn.type === NodeType$3.Element) {
1289
1370
  if (slimDOMOptions.script && // script tag
1290
1371
  (sn.tagName === "script" || // (module)preload link
1291
- sn.tagName === "link" && (sn.attributes.rel === "preload" || sn.attributes.rel === "modulepreload") && sn.attributes.as === "script" || // prefetch link
1372
+ sn.tagName === "link" && (sn.attributes.rel === "preload" && sn.attributes.as === "script" || sn.attributes.rel === "modulepreload") || // prefetch link
1292
1373
  sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
1293
1374
  return true;
1294
1375
  } else if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(/^msapplication-tile(image|color)$/) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
@@ -10039,6 +10120,30 @@
10039
10120
  function mutationObserverCtor() {
10040
10121
  return getUntaintedPrototype("MutationObserver").constructor;
10041
10122
  }
10123
+ function patch(source, name, replacement) {
10124
+ try {
10125
+ if (!(name in source)) {
10126
+ return function() {};
10127
+ }
10128
+ var original = source[name];
10129
+ var wrapped = replacement(original);
10130
+ if (typeof wrapped === "function") {
10131
+ wrapped.prototype = wrapped.prototype || {};
10132
+ Object.defineProperties(wrapped, {
10133
+ __rrweb_original__: {
10134
+ enumerable: false,
10135
+ value: original
10136
+ }
10137
+ });
10138
+ }
10139
+ source[name] = wrapped;
10140
+ return function() {
10141
+ source[name] = original;
10142
+ };
10143
+ } catch (e) {
10144
+ return function() {};
10145
+ }
10146
+ }
10042
10147
  var index = {
10043
10148
  childNodes: childNodes,
10044
10149
  parentNode: parentNode,
@@ -10051,7 +10156,8 @@
10051
10156
  shadowRoot: shadowRoot,
10052
10157
  querySelector: querySelector,
10053
10158
  querySelectorAll: querySelectorAll,
10054
- mutationObserver: mutationObserverCtor
10159
+ mutationObserver: mutationObserverCtor,
10160
+ patch: patch
10055
10161
  };
10056
10162
  function on(type, fn, target) {
10057
10163
  if (target === void 0) target = document;
@@ -10144,30 +10250,6 @@
10144
10250
  return hookSetter(target, key, original || {}, true);
10145
10251
  };
10146
10252
  }
10147
- function patch(source, name, replacement) {
10148
- try {
10149
- if (!(name in source)) {
10150
- return function() {};
10151
- }
10152
- var original = source[name];
10153
- var wrapped = replacement(original);
10154
- if (typeof wrapped === "function") {
10155
- wrapped.prototype = wrapped.prototype || {};
10156
- Object.defineProperties(wrapped, {
10157
- __rrweb_original__: {
10158
- enumerable: false,
10159
- value: original
10160
- }
10161
- });
10162
- }
10163
- source[name] = wrapped;
10164
- return function() {
10165
- source[name] = original;
10166
- };
10167
- } catch (e) {
10168
- return function() {};
10169
- }
10170
- }
10171
10253
  var nowTimestamp = Date.now;
10172
10254
  if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
10173
10255
  nowTimestamp = function() {
@@ -10758,9 +10840,17 @@
10758
10840
  _this.attributes.push(item);
10759
10841
  _this.attributeMap.set(textarea, item);
10760
10842
  }
10761
- item.attributes.value = Array.from(index.childNodes(textarea), function(cn) {
10843
+ var value = Array.from(index.childNodes(textarea), function(cn) {
10762
10844
  return index.textContent(cn) || "";
10763
10845
  }).join("");
10846
+ item.attributes.value = maskInputValue({
10847
+ element: textarea,
10848
+ maskInputOptions: _this.maskInputOptions,
10849
+ tagName: textarea.tagName,
10850
+ type: getInputType(textarea),
10851
+ value: value,
10852
+ maskInputFn: _this.maskInputFn
10853
+ });
10764
10854
  });
10765
10855
  __publicField(this, "processMutation", function(m) {
10766
10856
  if (isIgnored(m.target, _this.mirror, _this.slimDOMOptions)) {
@@ -13541,8 +13631,15 @@
13541
13631
  }, window));
13542
13632
  }
13543
13633
  return function() {
13544
- handlers.forEach(function(h) {
13545
- return h();
13634
+ handlers.forEach(function(handler) {
13635
+ try {
13636
+ handler();
13637
+ } catch (error) {
13638
+ var msg = String(error).toLowerCase();
13639
+ if (!msg.includes("cross-origin")) {
13640
+ console.warn(error);
13641
+ }
13642
+ }
13546
13643
  });
13547
13644
  processedNodeManager.destroy();
13548
13645
  recording = false;
@@ -13948,7 +14045,7 @@
13948
14045
 
13949
14046
  var Config = {
13950
14047
  DEBUG: false,
13951
- LIB_VERSION: '2.67.0'
14048
+ LIB_VERSION: '2.69.0'
13952
14049
  };
13953
14050
 
13954
14051
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -15748,6 +15845,10 @@
15748
15845
  });
15749
15846
  };
15750
15847
 
15848
+ IDBStorageWrapper.prototype.isInitialized = function () {
15849
+ return !!this.dbPromise;
15850
+ };
15851
+
15751
15852
  /**
15752
15853
  * @param {IDBTransactionMode} mode
15753
15854
  * @param {function(IDBObjectStore): void} storeCb
@@ -16272,6 +16373,10 @@
16272
16373
  return PromisePolyfill.resolve();
16273
16374
  };
16274
16375
 
16376
+ LocalStorageWrapper.prototype.isInitialized = function () {
16377
+ return true;
16378
+ };
16379
+
16275
16380
  LocalStorageWrapper.prototype.setItem = function (key, value) {
16276
16381
  return new PromisePolyfill(_.bind(function (resolve, reject) {
16277
16382
  try {
@@ -16352,7 +16457,7 @@
16352
16457
  };
16353
16458
 
16354
16459
  RequestQueue.prototype.ensureInit = function () {
16355
- if (this.initialized) {
16460
+ if (this.initialized || !this.usePersistence) {
16356
16461
  return PromisePolyfill.resolve();
16357
16462
  }
16358
16463
 
@@ -17104,10 +17209,9 @@
17104
17209
 
17105
17210
  // disable persistence if localStorage is not supported
17106
17211
  // request-queue will automatically disable persistence if indexedDB fails to initialize
17107
- var usePersistence = localStorageSupported(options.sharedLockStorage, true);
17212
+ var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
17108
17213
 
17109
17214
  // each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
17110
- // this will be important when persistence is introduced
17111
17215
  this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
17112
17216
  this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
17113
17217
  this.batcher = new RequestBatcher(this.batcherKey, {
@@ -17488,12 +17592,17 @@
17488
17592
  * Makes sure that only one tab can be recording at a time.
17489
17593
  */
17490
17594
  var RecordingRegistry = function (options) {
17595
+ /** @type {IDBStorageWrapper} */
17491
17596
  this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
17492
17597
  this.errorReporter = options.errorReporter;
17493
17598
  this.mixpanelInstance = options.mixpanelInstance;
17494
17599
  this.sharedLockStorage = options.sharedLockStorage;
17495
17600
  };
17496
17601
 
17602
+ RecordingRegistry.prototype.isPersistenceEnabled = function() {
17603
+ return !this.mixpanelInstance.get_config('disable_persistence');
17604
+ };
17605
+
17497
17606
  RecordingRegistry.prototype.handleError = function (err) {
17498
17607
  this.errorReporter('IndexedDB error: ', err);
17499
17608
  };
@@ -17502,6 +17611,10 @@
17502
17611
  * @param {import('./session-recording').SerializedRecording} serializedRecording
17503
17612
  */
17504
17613
  RecordingRegistry.prototype.setActiveRecording = function (serializedRecording) {
17614
+ if (!this.isPersistenceEnabled()) {
17615
+ return PromisePolyfill.resolve();
17616
+ }
17617
+
17505
17618
  var tabId = serializedRecording['tabId'];
17506
17619
  if (!tabId) {
17507
17620
  console.warn('No tab ID is set, cannot persist recording metadata.');
@@ -17519,6 +17632,10 @@
17519
17632
  * @returns {Promise<import('./session-recording').SerializedRecording>}
17520
17633
  */
17521
17634
  RecordingRegistry.prototype.getActiveRecording = function () {
17635
+ if (!this.isPersistenceEnabled()) {
17636
+ return PromisePolyfill.resolve(null);
17637
+ }
17638
+
17522
17639
  return this.idb.init()
17523
17640
  .then(function () {
17524
17641
  return this.idb.getItem(this.mixpanelInstance.get_tab_id());
@@ -17530,8 +17647,16 @@
17530
17647
  };
17531
17648
 
17532
17649
  RecordingRegistry.prototype.clearActiveRecording = function () {
17533
- // mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
17534
- // this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
17650
+ if (this.isPersistenceEnabled()) {
17651
+ // mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
17652
+ // this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
17653
+ return this.markActiveRecordingExpired();
17654
+ } else {
17655
+ return this.deleteActiveRecording();
17656
+ }
17657
+ };
17658
+
17659
+ RecordingRegistry.prototype.markActiveRecordingExpired = function () {
17535
17660
  return this.getActiveRecording()
17536
17661
  .then(function (serializedRecording) {
17537
17662
  if (serializedRecording) {
@@ -17542,11 +17667,25 @@
17542
17667
  .catch(this.handleError.bind(this));
17543
17668
  };
17544
17669
 
17670
+ RecordingRegistry.prototype.deleteActiveRecording = function () {
17671
+ // avoid initializing IDB if this registry instance hasn't already written a recording
17672
+ if (this.idb.isInitialized()) {
17673
+ return this.idb.removeItem(this.mixpanelInstance.get_tab_id())
17674
+ .catch(this.handleError.bind(this));
17675
+ } else {
17676
+ return PromisePolyfill.resolve();
17677
+ }
17678
+ };
17679
+
17545
17680
  /**
17546
17681
  * Flush any inactive recordings from the registry to minimize data loss.
17547
17682
  * The main idea here is that we can flush remaining rrweb events on the next page load if a tab is closed mid-batch.
17548
17683
  */
17549
17684
  RecordingRegistry.prototype.flushInactiveRecordings = function () {
17685
+ if (!this.isPersistenceEnabled()) {
17686
+ return PromisePolyfill.resolve([]);
17687
+ }
17688
+
17550
17689
  return this.idb.init()
17551
17690
  .then(function() {
17552
17691
  return this.idb.getAll();
@@ -18233,6 +18372,38 @@
18233
18372
  return true;
18234
18373
  }
18235
18374
 
18375
+ /** @const */ var DEFAULT_RAGE_CLICK_THRESHOLD_PX = 30;
18376
+ /** @const */ var DEFAULT_RAGE_CLICK_TIMEOUT_MS = 1000;
18377
+ /** @const */ var DEFAULT_RAGE_CLICK_CLICK_COUNT = 4;
18378
+
18379
+ function RageClickTracker() {
18380
+ this.clicks = [];
18381
+ }
18382
+
18383
+ RageClickTracker.prototype.isRageClick = function(x, y, options) {
18384
+ options = options || {};
18385
+ var thresholdPx = options['threshold_px'] || DEFAULT_RAGE_CLICK_THRESHOLD_PX;
18386
+ var timeoutMs = options['timeout_ms'] || DEFAULT_RAGE_CLICK_TIMEOUT_MS;
18387
+ var clickCount = options['click_count'] || DEFAULT_RAGE_CLICK_CLICK_COUNT;
18388
+ var timestamp = Date.now();
18389
+
18390
+ var lastClick = this.clicks[this.clicks.length - 1];
18391
+ if (
18392
+ lastClick &&
18393
+ timestamp - lastClick.timestamp < timeoutMs &&
18394
+ Math.sqrt(Math.pow(x - lastClick.x, 2) + Math.pow(y - lastClick.y, 2)) < thresholdPx
18395
+ ) {
18396
+ this.clicks.push({ x: x, y: y, timestamp: timestamp });
18397
+ if (this.clicks.length >= clickCount) {
18398
+ this.clicks = [];
18399
+ return true;
18400
+ }
18401
+ } else {
18402
+ this.clicks = [{ x: x, y: y, timestamp: timestamp }];
18403
+ }
18404
+ return false;
18405
+ };
18406
+
18236
18407
  var AUTOCAPTURE_CONFIG_KEY = 'autocapture';
18237
18408
  var LEGACY_PAGEVIEW_CONFIG_KEY = 'track_pageview';
18238
18409
 
@@ -18254,6 +18425,7 @@
18254
18425
  var CONFIG_TRACK_CLICK = 'click';
18255
18426
  var CONFIG_TRACK_INPUT = 'input';
18256
18427
  var CONFIG_TRACK_PAGEVIEW = 'pageview';
18428
+ var CONFIG_TRACK_RAGE_CLICK = 'rage_click';
18257
18429
  var CONFIG_TRACK_SCROLL = 'scroll';
18258
18430
  var CONFIG_TRACK_SUBMIT = 'submit';
18259
18431
 
@@ -18271,6 +18443,7 @@
18271
18443
  CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
18272
18444
  CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
18273
18445
  CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
18446
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_RAGE_CLICK] = true;
18274
18447
  CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
18275
18448
  CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
18276
18449
 
@@ -18280,6 +18453,7 @@
18280
18453
 
18281
18454
  var MP_EV_CLICK = '$mp_click';
18282
18455
  var MP_EV_INPUT = '$mp_input_change';
18456
+ var MP_EV_RAGE_CLICK = '$mp_rage_click';
18283
18457
  var MP_EV_SCROLL = '$mp_scroll';
18284
18458
  var MP_EV_SUBMIT = '$mp_submit';
18285
18459
 
@@ -18302,6 +18476,7 @@
18302
18476
  this.initInputTracking();
18303
18477
  this.initScrollTracking();
18304
18478
  this.initSubmitTracking();
18479
+ this.initRageClickTracking();
18305
18480
  };
18306
18481
 
18307
18482
  Autocapture.prototype.getFullConfig = function() {
@@ -18380,6 +18555,11 @@
18380
18555
  return;
18381
18556
  }
18382
18557
 
18558
+ var isCapturedForHeatMap = this.mp.is_recording_heatmap_data() && (
18559
+ (mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK)) ||
18560
+ (mpEventName === MP_EV_RAGE_CLICK && !this._getRageClickConfig())
18561
+ );
18562
+
18383
18563
  var props = getPropsForDOMEvent(ev, {
18384
18564
  allowElementCallback: this.getConfig(CONFIG_ALLOW_ELEMENT_CALLBACK),
18385
18565
  allowSelectors: this.getConfig(CONFIG_ALLOW_SELECTORS),
@@ -18388,7 +18568,7 @@
18388
18568
  blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
18389
18569
  captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
18390
18570
  captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
18391
- capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
18571
+ capturedForHeatMap: isCapturedForHeatMap,
18392
18572
  });
18393
18573
  if (props) {
18394
18574
  _.extend(props, DEFAULT_PROPS);
@@ -18396,6 +18576,24 @@
18396
18576
  }
18397
18577
  };
18398
18578
 
18579
+ Autocapture.prototype._getRageClickConfig = function() {
18580
+ var config = this.getConfig(CONFIG_TRACK_RAGE_CLICK);
18581
+
18582
+ if (!config) {
18583
+ return null; // rage click tracking disabled
18584
+ }
18585
+
18586
+ if (config === true) {
18587
+ return {}; // use defaults
18588
+ }
18589
+
18590
+ if (typeof config === 'object') {
18591
+ return config; // use custom configuration
18592
+ }
18593
+
18594
+ return {}; // fallback to defaults for any other truthy value
18595
+ };
18596
+
18399
18597
  Autocapture.prototype.initClickTracking = function() {
18400
18598
  win.removeEventListener(EV_CLICK, this.listenerClick);
18401
18599
 
@@ -18497,6 +18695,36 @@
18497
18695
  }.bind(this)));
18498
18696
  };
18499
18697
 
18698
+ Autocapture.prototype.initRageClickTracking = function() {
18699
+ win.removeEventListener(EV_CLICK, this.listenerRageClick);
18700
+
18701
+ var rageClickConfig = this._getRageClickConfig();
18702
+ if (!rageClickConfig && !this.mp.get_config('record_heatmap_data')) {
18703
+ return;
18704
+ }
18705
+
18706
+ logger$1.log('Initializing rage click tracking');
18707
+ if (!this._rageClickTracker) {
18708
+ this._rageClickTracker = new RageClickTracker();
18709
+ }
18710
+
18711
+ this.listenerRageClick = function(ev) {
18712
+ var currentRageClickConfig = this._getRageClickConfig();
18713
+ if (!currentRageClickConfig && !this.mp.is_recording_heatmap_data()) {
18714
+ return;
18715
+ }
18716
+
18717
+ if (this.currentUrlBlocked()) {
18718
+ return;
18719
+ }
18720
+
18721
+ if (this._rageClickTracker.isRageClick(ev['pageX'], ev['pageY'], currentRageClickConfig)) {
18722
+ this.trackDomEvent(ev, MP_EV_RAGE_CLICK);
18723
+ }
18724
+ }.bind(this);
18725
+ win.addEventListener(EV_CLICK, this.listenerRageClick);
18726
+ };
18727
+
18500
18728
  Autocapture.prototype.initScrollTracking = function() {
18501
18729
  win.removeEventListener(EV_SCROLLEND, this.listenerScroll);
18502
18730
 
@@ -18583,6 +18811,7 @@
18583
18811
  var FeatureFlagManager = function(initOptions) {
18584
18812
  this.getFullApiRoute = initOptions.getFullApiRoute;
18585
18813
  this.getMpConfig = initOptions.getConfigFunc;
18814
+ this.setMpConfig = initOptions.setConfigFunc;
18586
18815
  this.getMpProperty = initOptions.getPropertyFunc;
18587
18816
  this.track = initOptions.trackingFunc;
18588
18817
  };
@@ -18620,6 +18849,23 @@
18620
18849
  return !!this.getMpConfig(FLAGS_CONFIG_KEY);
18621
18850
  };
18622
18851
 
18852
+ FeatureFlagManager.prototype.updateContext = function(newContext, options) {
18853
+ if (!this.isSystemEnabled()) {
18854
+ logger.critical('Feature Flags not enabled, cannot update context');
18855
+ return Promise.resolve();
18856
+ }
18857
+
18858
+ var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
18859
+ if (!_.isObject(ffConfig)) {
18860
+ ffConfig = {};
18861
+ }
18862
+ var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
18863
+ ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
18864
+
18865
+ this.setMpConfig(FLAGS_CONFIG_KEY, ffConfig);
18866
+ return this.fetchFlags();
18867
+ };
18868
+
18623
18869
  FeatureFlagManager.prototype.areFlagsReady = function() {
18624
18870
  if (!this.isSystemEnabled()) {
18625
18871
  logger.error('Feature Flags not enabled');
@@ -18629,7 +18875,7 @@
18629
18875
 
18630
18876
  FeatureFlagManager.prototype.fetchFlags = function() {
18631
18877
  if (!this.isSystemEnabled()) {
18632
- return;
18878
+ return Promise.resolve();
18633
18879
  }
18634
18880
 
18635
18881
  var distinctId = this.getMpProperty('distinct_id');
@@ -18669,6 +18915,8 @@
18669
18915
  this.markFetchComplete();
18670
18916
  logger.error(error);
18671
18917
  }.bind(this));
18918
+
18919
+ return this.fetchPromise;
18672
18920
  };
18673
18921
 
18674
18922
  FeatureFlagManager.prototype.markFetchComplete = function() {
@@ -18781,6 +19029,7 @@
18781
19029
  FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
18782
19030
  FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
18783
19031
  FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
19032
+ FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
18784
19033
 
18785
19034
  // Deprecated method
18786
19035
  FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
@@ -20241,7 +20490,7 @@
20241
20490
  'batch_autostart': true,
20242
20491
  'hooks': {},
20243
20492
  'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
20244
- 'record_block_selector': 'img, video',
20493
+ 'record_block_selector': 'img, video, audio',
20245
20494
  'record_canvas': false,
20246
20495
  'record_collect_fonts': false,
20247
20496
  'record_heatmap_data': false,
@@ -20465,6 +20714,7 @@
20465
20714
  return this.get_api_host('flags') + '/' + this.get_config('api_routes')['flags'];
20466
20715
  }, this),
20467
20716
  getConfigFunc: _.bind(this.get_config, this),
20717
+ setConfigFunc: _.bind(this.set_config, this),
20468
20718
  getPropertyFunc: _.bind(this.get_property, this),
20469
20719
  trackingFunc: _.bind(this.track, this)
20470
20720
  });
@@ -20483,7 +20733,9 @@
20483
20733
  * This is primarily used for session recording, where data must be isolated to the current tab.
20484
20734
  */
20485
20735
  MixpanelLib.prototype._init_tab_id = function() {
20486
- if (_.sessionStorage.is_supported()) {
20736
+ if (this.get_config('disable_persistence')) {
20737
+ console$1.log('Tab ID initialization skipped due to disable_persistence config');
20738
+ } else if (_.sessionStorage.is_supported()) {
20487
20739
  try {
20488
20740
  var key_suffix = this.get_config('name') + '_' + this.get_config('token');
20489
20741
  var tab_id_key = 'mp_tab_id_' + key_suffix;
@@ -20517,6 +20769,11 @@
20517
20769
  };
20518
20770
 
20519
20771
  MixpanelLib.prototype._should_load_recorder = function () {
20772
+ if (this.get_config('disable_persistence')) {
20773
+ console$1.log('Load recorder check skipped due to disable_persistence config');
20774
+ return Promise.resolve(false);
20775
+ }
20776
+
20520
20777
  var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
20521
20778
  var tab_id = this.get_tab_id();
20522
20779
  return recording_registry_idb.init()