mixpanel-browser 2.68.0 → 2.69.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -485,6 +485,30 @@ function querySelectorAll$1(n2, selectors) {
485
485
  function mutationObserverCtor$1() {
486
486
  return getUntaintedPrototype$1("MutationObserver").constructor;
487
487
  }
488
+ function patch$1(source, name, replacement) {
489
+ try {
490
+ if (!(name in source)) {
491
+ return function() {};
492
+ }
493
+ var original = source[name];
494
+ var wrapped = replacement(original);
495
+ if (typeof wrapped === "function") {
496
+ wrapped.prototype = wrapped.prototype || {};
497
+ Object.defineProperties(wrapped, {
498
+ __rrweb_original__: {
499
+ enumerable: false,
500
+ value: original
501
+ }
502
+ });
503
+ }
504
+ source[name] = wrapped;
505
+ return function() {
506
+ source[name] = original;
507
+ };
508
+ } catch (e) {
509
+ return function() {};
510
+ }
511
+ }
488
512
  var index$1 = {
489
513
  childNodes: childNodes$1,
490
514
  parentNode: parentNode$1,
@@ -497,7 +521,8 @@ var index$1 = {
497
521
  shadowRoot: shadowRoot$1,
498
522
  querySelector: querySelector$1,
499
523
  querySelectorAll: querySelectorAll$1,
500
- mutationObserver: mutationObserverCtor$1
524
+ mutationObserver: mutationObserverCtor$1,
525
+ patch: patch$1
501
526
  };
502
527
  function isElement(n2) {
503
528
  return n2.nodeType === n2.ELEMENT_NODE;
@@ -748,26 +773,82 @@ function absolutifyURLs(cssText, href) {
748
773
  return "url(" + maybeQuote + stack.join("/") + maybeQuote + ")";
749
774
  });
750
775
  }
751
- function normalizeCssString(cssText) {
752
- return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
776
+ function normalizeCssString(cssText, _testNoPxNorm) {
777
+ if (_testNoPxNorm === void 0) _testNoPxNorm = false;
778
+ if (_testNoPxNorm) {
779
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
780
+ } else {
781
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
782
+ }
753
783
  }
754
- function splitCssText(cssText, style) {
784
+ function splitCssText(cssText, style, _testNoPxNorm) {
785
+ if (_testNoPxNorm === void 0) _testNoPxNorm = false;
755
786
  var childNodes2 = Array.from(style.childNodes);
756
787
  var splits = [];
788
+ var iterCount = 0;
757
789
  if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
758
- var cssTextNorm = normalizeCssString(cssText);
790
+ var cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
791
+ var normFactor = cssTextNorm.length / cssText.length;
759
792
  for(var i2 = 1; i2 < childNodes2.length; i2++){
760
793
  if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
761
- var textContentNorm = normalizeCssString(childNodes2[i2].textContent);
762
- for(var j = 3; j < textContentNorm.length; j++){
763
- var bit = textContentNorm.substring(0, j);
764
- if (cssTextNorm.split(bit).length === 2) {
765
- var splitNorm = cssTextNorm.indexOf(bit);
766
- for(var k = splitNorm; k < cssText.length; k++){
767
- if (normalizeCssString(cssText.substring(0, k)).length === splitNorm) {
794
+ var textContentNorm = normalizeCssString(childNodes2[i2].textContent, _testNoPxNorm);
795
+ var jLimit = 100;
796
+ var j = 3;
797
+ for(; j < textContentNorm.length; j++){
798
+ if (// keep consuming css identifiers (to get a decent chunk more quickly)
799
+ textContentNorm[j].match(/[a-zA-Z0-9]/) || // substring needs to be unique to this section
800
+ textContentNorm.indexOf(textContentNorm.substring(0, j), 1) !== -1) {
801
+ continue;
802
+ }
803
+ break;
804
+ }
805
+ for(; j < textContentNorm.length; j++){
806
+ var startSubstring = textContentNorm.substring(0, j);
807
+ var cssNormSplits = cssTextNorm.split(startSubstring);
808
+ var splitNorm = -1;
809
+ if (cssNormSplits.length === 2) {
810
+ splitNorm = cssNormSplits[0].length;
811
+ } else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
812
+ splitNorm = cssTextNorm.indexOf(startSubstring, 1);
813
+ } else if (cssNormSplits.length === 1) {
814
+ startSubstring = startSubstring.substring(0, startSubstring.length - 1);
815
+ cssNormSplits = cssTextNorm.split(startSubstring);
816
+ if (cssNormSplits.length <= 1) {
817
+ splits.push(cssText);
818
+ return splits;
819
+ }
820
+ j = jLimit + 1;
821
+ } else if (j === textContentNorm.length - 1) {
822
+ splitNorm = cssTextNorm.indexOf(startSubstring);
823
+ }
824
+ if (cssNormSplits.length >= 2 && j > jLimit) {
825
+ var prevTextContent = childNodes2[i2 - 1].textContent;
826
+ if (prevTextContent && typeof prevTextContent === "string") {
827
+ var prevMinLength = normalizeCssString(prevTextContent).length;
828
+ splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
829
+ }
830
+ if (splitNorm === -1) {
831
+ splitNorm = cssNormSplits[0].length;
832
+ }
833
+ }
834
+ if (splitNorm !== -1) {
835
+ var k = Math.floor(splitNorm / normFactor);
836
+ for(; k > 0 && k < cssText.length;){
837
+ iterCount += 1;
838
+ if (iterCount > 50 * childNodes2.length) {
839
+ splits.push(cssText);
840
+ return splits;
841
+ }
842
+ var normPart = normalizeCssString(cssText.substring(0, k), _testNoPxNorm);
843
+ if (normPart.length === splitNorm) {
768
844
  splits.push(cssText.substring(0, k));
769
845
  cssText = cssText.substring(k);
846
+ cssTextNorm = cssTextNorm.substring(splitNorm);
770
847
  break;
848
+ } else if (normPart.length < splitNorm) {
849
+ k += Math.max(1, Math.floor((splitNorm - normPart.length) / normFactor));
850
+ } else {
851
+ k -= Math.max(1, Math.floor((normPart.length - splitNorm) * normFactor));
771
852
  }
772
853
  }
773
854
  break;
@@ -1284,7 +1365,7 @@ function slimDOMExcluded(sn, slimDOMOptions) {
1284
1365
  } else if (sn.type === NodeType$3.Element) {
1285
1366
  if (slimDOMOptions.script && // script tag
1286
1367
  (sn.tagName === "script" || // (module)preload link
1287
- sn.tagName === "link" && (sn.attributes.rel === "preload" || sn.attributes.rel === "modulepreload") && sn.attributes.as === "script" || // prefetch link
1368
+ sn.tagName === "link" && (sn.attributes.rel === "preload" && sn.attributes.as === "script" || sn.attributes.rel === "modulepreload") || // prefetch link
1288
1369
  sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
1289
1370
  return true;
1290
1371
  } 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"))) {
@@ -10035,6 +10116,30 @@ function querySelectorAll(n2, selectors) {
10035
10116
  function mutationObserverCtor() {
10036
10117
  return getUntaintedPrototype("MutationObserver").constructor;
10037
10118
  }
10119
+ function patch(source, name, replacement) {
10120
+ try {
10121
+ if (!(name in source)) {
10122
+ return function() {};
10123
+ }
10124
+ var original = source[name];
10125
+ var wrapped = replacement(original);
10126
+ if (typeof wrapped === "function") {
10127
+ wrapped.prototype = wrapped.prototype || {};
10128
+ Object.defineProperties(wrapped, {
10129
+ __rrweb_original__: {
10130
+ enumerable: false,
10131
+ value: original
10132
+ }
10133
+ });
10134
+ }
10135
+ source[name] = wrapped;
10136
+ return function() {
10137
+ source[name] = original;
10138
+ };
10139
+ } catch (e) {
10140
+ return function() {};
10141
+ }
10142
+ }
10038
10143
  var index = {
10039
10144
  childNodes: childNodes,
10040
10145
  parentNode: parentNode,
@@ -10047,7 +10152,8 @@ var index = {
10047
10152
  shadowRoot: shadowRoot,
10048
10153
  querySelector: querySelector,
10049
10154
  querySelectorAll: querySelectorAll,
10050
- mutationObserver: mutationObserverCtor
10155
+ mutationObserver: mutationObserverCtor,
10156
+ patch: patch
10051
10157
  };
10052
10158
  function on(type, fn, target) {
10053
10159
  if (target === void 0) target = document;
@@ -10140,30 +10246,6 @@ function hookSetter(target, key, d, isRevoked, win) {
10140
10246
  return hookSetter(target, key, original || {}, true);
10141
10247
  };
10142
10248
  }
10143
- function patch(source, name, replacement) {
10144
- try {
10145
- if (!(name in source)) {
10146
- return function() {};
10147
- }
10148
- var original = source[name];
10149
- var wrapped = replacement(original);
10150
- if (typeof wrapped === "function") {
10151
- wrapped.prototype = wrapped.prototype || {};
10152
- Object.defineProperties(wrapped, {
10153
- __rrweb_original__: {
10154
- enumerable: false,
10155
- value: original
10156
- }
10157
- });
10158
- }
10159
- source[name] = wrapped;
10160
- return function() {
10161
- source[name] = original;
10162
- };
10163
- } catch (e) {
10164
- return function() {};
10165
- }
10166
- }
10167
10249
  var nowTimestamp = Date.now;
10168
10250
  if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
10169
10251
  nowTimestamp = function() {
@@ -10754,9 +10836,17 @@ var MutationBuffer = /*#__PURE__*/ function() {
10754
10836
  _this.attributes.push(item);
10755
10837
  _this.attributeMap.set(textarea, item);
10756
10838
  }
10757
- item.attributes.value = Array.from(index.childNodes(textarea), function(cn) {
10839
+ var value = Array.from(index.childNodes(textarea), function(cn) {
10758
10840
  return index.textContent(cn) || "";
10759
10841
  }).join("");
10842
+ item.attributes.value = maskInputValue({
10843
+ element: textarea,
10844
+ maskInputOptions: _this.maskInputOptions,
10845
+ tagName: textarea.tagName,
10846
+ type: getInputType(textarea),
10847
+ value: value,
10848
+ maskInputFn: _this.maskInputFn
10849
+ });
10760
10850
  });
10761
10851
  __publicField(this, "processMutation", function(m) {
10762
10852
  if (isIgnored(m.target, _this.mirror, _this.slimDOMOptions)) {
@@ -13537,8 +13627,15 @@ function record(options) {
13537
13627
  }, window));
13538
13628
  }
13539
13629
  return function() {
13540
- handlers.forEach(function(h) {
13541
- return h();
13630
+ handlers.forEach(function(handler) {
13631
+ try {
13632
+ handler();
13633
+ } catch (error) {
13634
+ var msg = String(error).toLowerCase();
13635
+ if (!msg.includes("cross-origin")) {
13636
+ console.warn(error);
13637
+ }
13638
+ }
13542
13639
  });
13543
13640
  processedNodeManager.destroy();
13544
13641
  recording = false;
@@ -13944,7 +14041,7 @@ if (typeof Promise !== 'undefined' && Promise.toString().indexOf('[native code]'
13944
14041
 
13945
14042
  var Config = {
13946
14043
  DEBUG: false,
13947
- LIB_VERSION: '2.68.0'
14044
+ LIB_VERSION: '2.69.0'
13948
14045
  };
13949
14046
 
13950
14047
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -15744,6 +15841,10 @@ IDBStorageWrapper.prototype.init = function () {
15744
15841
  });
15745
15842
  };
15746
15843
 
15844
+ IDBStorageWrapper.prototype.isInitialized = function () {
15845
+ return !!this.dbPromise;
15846
+ };
15847
+
15747
15848
  /**
15748
15849
  * @param {IDBTransactionMode} mode
15749
15850
  * @param {function(IDBObjectStore): void} storeCb
@@ -16268,6 +16369,10 @@ LocalStorageWrapper.prototype.init = function () {
16268
16369
  return PromisePolyfill.resolve();
16269
16370
  };
16270
16371
 
16372
+ LocalStorageWrapper.prototype.isInitialized = function () {
16373
+ return true;
16374
+ };
16375
+
16271
16376
  LocalStorageWrapper.prototype.setItem = function (key, value) {
16272
16377
  return new PromisePolyfill(_.bind(function (resolve, reject) {
16273
16378
  try {
@@ -16348,7 +16453,7 @@ var RequestQueue = function (storageKey, options) {
16348
16453
  };
16349
16454
 
16350
16455
  RequestQueue.prototype.ensureInit = function () {
16351
- if (this.initialized) {
16456
+ if (this.initialized || !this.usePersistence) {
16352
16457
  return PromisePolyfill.resolve();
16353
16458
  }
16354
16459
 
@@ -17100,10 +17205,9 @@ var SessionRecording = function(options) {
17100
17205
 
17101
17206
  // disable persistence if localStorage is not supported
17102
17207
  // request-queue will automatically disable persistence if indexedDB fails to initialize
17103
- var usePersistence = localStorageSupported(options.sharedLockStorage, true);
17208
+ var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
17104
17209
 
17105
17210
  // each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
17106
- // this will be important when persistence is introduced
17107
17211
  this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
17108
17212
  this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
17109
17213
  this.batcher = new RequestBatcher(this.batcherKey, {
@@ -17484,12 +17588,17 @@ SessionRecording.prototype.reportError = function(msg, err) {
17484
17588
  * Makes sure that only one tab can be recording at a time.
17485
17589
  */
17486
17590
  var RecordingRegistry = function (options) {
17591
+ /** @type {IDBStorageWrapper} */
17487
17592
  this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
17488
17593
  this.errorReporter = options.errorReporter;
17489
17594
  this.mixpanelInstance = options.mixpanelInstance;
17490
17595
  this.sharedLockStorage = options.sharedLockStorage;
17491
17596
  };
17492
17597
 
17598
+ RecordingRegistry.prototype.isPersistenceEnabled = function() {
17599
+ return !this.mixpanelInstance.get_config('disable_persistence');
17600
+ };
17601
+
17493
17602
  RecordingRegistry.prototype.handleError = function (err) {
17494
17603
  this.errorReporter('IndexedDB error: ', err);
17495
17604
  };
@@ -17498,6 +17607,10 @@ RecordingRegistry.prototype.handleError = function (err) {
17498
17607
  * @param {import('./session-recording').SerializedRecording} serializedRecording
17499
17608
  */
17500
17609
  RecordingRegistry.prototype.setActiveRecording = function (serializedRecording) {
17610
+ if (!this.isPersistenceEnabled()) {
17611
+ return PromisePolyfill.resolve();
17612
+ }
17613
+
17501
17614
  var tabId = serializedRecording['tabId'];
17502
17615
  if (!tabId) {
17503
17616
  console.warn('No tab ID is set, cannot persist recording metadata.');
@@ -17515,6 +17628,10 @@ RecordingRegistry.prototype.setActiveRecording = function (serializedRecording)
17515
17628
  * @returns {Promise<import('./session-recording').SerializedRecording>}
17516
17629
  */
17517
17630
  RecordingRegistry.prototype.getActiveRecording = function () {
17631
+ if (!this.isPersistenceEnabled()) {
17632
+ return PromisePolyfill.resolve(null);
17633
+ }
17634
+
17518
17635
  return this.idb.init()
17519
17636
  .then(function () {
17520
17637
  return this.idb.getItem(this.mixpanelInstance.get_tab_id());
@@ -17526,8 +17643,16 @@ RecordingRegistry.prototype.getActiveRecording = function () {
17526
17643
  };
17527
17644
 
17528
17645
  RecordingRegistry.prototype.clearActiveRecording = function () {
17529
- // mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
17530
- // this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
17646
+ if (this.isPersistenceEnabled()) {
17647
+ // mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
17648
+ // this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
17649
+ return this.markActiveRecordingExpired();
17650
+ } else {
17651
+ return this.deleteActiveRecording();
17652
+ }
17653
+ };
17654
+
17655
+ RecordingRegistry.prototype.markActiveRecordingExpired = function () {
17531
17656
  return this.getActiveRecording()
17532
17657
  .then(function (serializedRecording) {
17533
17658
  if (serializedRecording) {
@@ -17538,11 +17663,25 @@ RecordingRegistry.prototype.clearActiveRecording = function () {
17538
17663
  .catch(this.handleError.bind(this));
17539
17664
  };
17540
17665
 
17666
+ RecordingRegistry.prototype.deleteActiveRecording = function () {
17667
+ // avoid initializing IDB if this registry instance hasn't already written a recording
17668
+ if (this.idb.isInitialized()) {
17669
+ return this.idb.removeItem(this.mixpanelInstance.get_tab_id())
17670
+ .catch(this.handleError.bind(this));
17671
+ } else {
17672
+ return PromisePolyfill.resolve();
17673
+ }
17674
+ };
17675
+
17541
17676
  /**
17542
17677
  * Flush any inactive recordings from the registry to minimize data loss.
17543
17678
  * The main idea here is that we can flush remaining rrweb events on the next page load if a tab is closed mid-batch.
17544
17679
  */
17545
17680
  RecordingRegistry.prototype.flushInactiveRecordings = function () {
17681
+ if (!this.isPersistenceEnabled()) {
17682
+ return PromisePolyfill.resolve([]);
17683
+ }
17684
+
17546
17685
  return this.idb.init()
17547
17686
  .then(function() {
17548
17687
  return this.idb.getAll();
@@ -20590,7 +20729,9 @@ MixpanelLib.prototype._init = function(token, config, name) {
20590
20729
  * This is primarily used for session recording, where data must be isolated to the current tab.
20591
20730
  */
20592
20731
  MixpanelLib.prototype._init_tab_id = function() {
20593
- if (_.sessionStorage.is_supported()) {
20732
+ if (this.get_config('disable_persistence')) {
20733
+ console$1.log('Tab ID initialization skipped due to disable_persistence config');
20734
+ } else if (_.sessionStorage.is_supported()) {
20594
20735
  try {
20595
20736
  var key_suffix = this.get_config('name') + '_' + this.get_config('token');
20596
20737
  var tab_id_key = 'mp_tab_id_' + key_suffix;
@@ -20624,6 +20765,11 @@ MixpanelLib.prototype.get_tab_id = function () {
20624
20765
  };
20625
20766
 
20626
20767
  MixpanelLib.prototype._should_load_recorder = function () {
20768
+ if (this.get_config('disable_persistence')) {
20769
+ console$1.log('Load recorder check skipped due to disable_persistence config');
20770
+ return Promise.resolve(false);
20771
+ }
20772
+
20627
20773
  var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
20628
20774
  var tab_id = this.get_tab_id();
20629
20775
  return recording_registry_idb.init()
@@ -3,7 +3,7 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.68.0'
6
+ LIB_VERSION: '2.69.0'
7
7
  };
8
8
 
9
9
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -3630,6 +3630,10 @@
3630
3630
  return PromisePolyfill.resolve();
3631
3631
  };
3632
3632
 
3633
+ LocalStorageWrapper.prototype.isInitialized = function () {
3634
+ return true;
3635
+ };
3636
+
3633
3637
  LocalStorageWrapper.prototype.setItem = function (key, value) {
3634
3638
  return new PromisePolyfill(_.bind(function (resolve, reject) {
3635
3639
  try {
@@ -3710,7 +3714,7 @@
3710
3714
  };
3711
3715
 
3712
3716
  RequestQueue.prototype.ensureInit = function () {
3713
- if (this.initialized) {
3717
+ if (this.initialized || !this.usePersistence) {
3714
3718
  return PromisePolyfill.resolve();
3715
3719
  }
3716
3720
 
@@ -5894,6 +5898,10 @@
5894
5898
  });
5895
5899
  };
5896
5900
 
5901
+ IDBStorageWrapper.prototype.isInitialized = function () {
5902
+ return !!this.dbPromise;
5903
+ };
5904
+
5897
5905
  /**
5898
5906
  * @param {IDBTransactionMode} mode
5899
5907
  * @param {function(IDBObjectStore): void} storeCb
@@ -6327,7 +6335,9 @@
6327
6335
  * This is primarily used for session recording, where data must be isolated to the current tab.
6328
6336
  */
6329
6337
  MixpanelLib.prototype._init_tab_id = function() {
6330
- if (_.sessionStorage.is_supported()) {
6338
+ if (this.get_config('disable_persistence')) {
6339
+ console.log('Tab ID initialization skipped due to disable_persistence config');
6340
+ } else if (_.sessionStorage.is_supported()) {
6331
6341
  try {
6332
6342
  var key_suffix = this.get_config('name') + '_' + this.get_config('token');
6333
6343
  var tab_id_key = 'mp_tab_id_' + key_suffix;
@@ -6361,6 +6371,11 @@
6361
6371
  };
6362
6372
 
6363
6373
  MixpanelLib.prototype._should_load_recorder = function () {
6374
+ if (this.get_config('disable_persistence')) {
6375
+ console.log('Load recorder check skipped due to disable_persistence config');
6376
+ return Promise.resolve(false);
6377
+ }
6378
+
6364
6379
  var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
6365
6380
  var tab_id = this.get_tab_id();
6366
6381
  return recording_registry_idb.init()