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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ **2.68.0** (11 Aug 2025)
2
+ - Initial rage-click detection support
3
+ - Block `<audio>` tags by default in Session Recording
4
+ - Add `flags.update_context()` method for updating context variables and refetching variants
5
+
1
6
  **2.67.0** (17 Jul 2025)
2
7
  - Use `get_api_host()` consistently across the SDK
3
8
  - Include `device_id` in default Feature Flag context
@@ -2,7 +2,7 @@
2
2
 
3
3
  var Config = {
4
4
  DEBUG: false,
5
- LIB_VERSION: '2.67.0'
5
+ LIB_VERSION: '2.69.0'
6
6
  };
7
7
 
8
8
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -2654,6 +2654,38 @@ function shouldTrackValue(value) {
2654
2654
  return true;
2655
2655
  }
2656
2656
 
2657
+ /** @const */ var DEFAULT_RAGE_CLICK_THRESHOLD_PX = 30;
2658
+ /** @const */ var DEFAULT_RAGE_CLICK_TIMEOUT_MS = 1000;
2659
+ /** @const */ var DEFAULT_RAGE_CLICK_CLICK_COUNT = 4;
2660
+
2661
+ function RageClickTracker() {
2662
+ this.clicks = [];
2663
+ }
2664
+
2665
+ RageClickTracker.prototype.isRageClick = function(x, y, options) {
2666
+ options = options || {};
2667
+ var thresholdPx = options['threshold_px'] || DEFAULT_RAGE_CLICK_THRESHOLD_PX;
2668
+ var timeoutMs = options['timeout_ms'] || DEFAULT_RAGE_CLICK_TIMEOUT_MS;
2669
+ var clickCount = options['click_count'] || DEFAULT_RAGE_CLICK_CLICK_COUNT;
2670
+ var timestamp = Date.now();
2671
+
2672
+ var lastClick = this.clicks[this.clicks.length - 1];
2673
+ if (
2674
+ lastClick &&
2675
+ timestamp - lastClick.timestamp < timeoutMs &&
2676
+ Math.sqrt(Math.pow(x - lastClick.x, 2) + Math.pow(y - lastClick.y, 2)) < thresholdPx
2677
+ ) {
2678
+ this.clicks.push({ x: x, y: y, timestamp: timestamp });
2679
+ if (this.clicks.length >= clickCount) {
2680
+ this.clicks = [];
2681
+ return true;
2682
+ }
2683
+ } else {
2684
+ this.clicks = [{ x: x, y: y, timestamp: timestamp }];
2685
+ }
2686
+ return false;
2687
+ };
2688
+
2657
2689
  var AUTOCAPTURE_CONFIG_KEY = 'autocapture';
2658
2690
  var LEGACY_PAGEVIEW_CONFIG_KEY = 'track_pageview';
2659
2691
 
@@ -2675,6 +2707,7 @@ var CONFIG_SCROLL_CHECKPOINTS = 'scroll_depth_percent_checkpoints';
2675
2707
  var CONFIG_TRACK_CLICK = 'click';
2676
2708
  var CONFIG_TRACK_INPUT = 'input';
2677
2709
  var CONFIG_TRACK_PAGEVIEW = 'pageview';
2710
+ var CONFIG_TRACK_RAGE_CLICK = 'rage_click';
2678
2711
  var CONFIG_TRACK_SCROLL = 'scroll';
2679
2712
  var CONFIG_TRACK_SUBMIT = 'submit';
2680
2713
 
@@ -2692,6 +2725,7 @@ CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
2692
2725
  CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
2693
2726
  CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
2694
2727
  CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
2728
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_RAGE_CLICK] = true;
2695
2729
  CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
2696
2730
  CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
2697
2731
 
@@ -2701,6 +2735,7 @@ var DEFAULT_PROPS = {
2701
2735
 
2702
2736
  var MP_EV_CLICK = '$mp_click';
2703
2737
  var MP_EV_INPUT = '$mp_input_change';
2738
+ var MP_EV_RAGE_CLICK = '$mp_rage_click';
2704
2739
  var MP_EV_SCROLL = '$mp_scroll';
2705
2740
  var MP_EV_SUBMIT = '$mp_submit';
2706
2741
 
@@ -2723,6 +2758,7 @@ Autocapture.prototype.init = function() {
2723
2758
  this.initInputTracking();
2724
2759
  this.initScrollTracking();
2725
2760
  this.initSubmitTracking();
2761
+ this.initRageClickTracking();
2726
2762
  };
2727
2763
 
2728
2764
  Autocapture.prototype.getFullConfig = function() {
@@ -2801,6 +2837,11 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
2801
2837
  return;
2802
2838
  }
2803
2839
 
2840
+ var isCapturedForHeatMap = this.mp.is_recording_heatmap_data() && (
2841
+ (mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK)) ||
2842
+ (mpEventName === MP_EV_RAGE_CLICK && !this._getRageClickConfig())
2843
+ );
2844
+
2804
2845
  var props = getPropsForDOMEvent(ev, {
2805
2846
  allowElementCallback: this.getConfig(CONFIG_ALLOW_ELEMENT_CALLBACK),
2806
2847
  allowSelectors: this.getConfig(CONFIG_ALLOW_SELECTORS),
@@ -2809,7 +2850,7 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
2809
2850
  blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
2810
2851
  captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
2811
2852
  captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
2812
- capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
2853
+ capturedForHeatMap: isCapturedForHeatMap,
2813
2854
  });
2814
2855
  if (props) {
2815
2856
  _.extend(props, DEFAULT_PROPS);
@@ -2817,6 +2858,24 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
2817
2858
  }
2818
2859
  };
2819
2860
 
2861
+ Autocapture.prototype._getRageClickConfig = function() {
2862
+ var config = this.getConfig(CONFIG_TRACK_RAGE_CLICK);
2863
+
2864
+ if (!config) {
2865
+ return null; // rage click tracking disabled
2866
+ }
2867
+
2868
+ if (config === true) {
2869
+ return {}; // use defaults
2870
+ }
2871
+
2872
+ if (typeof config === 'object') {
2873
+ return config; // use custom configuration
2874
+ }
2875
+
2876
+ return {}; // fallback to defaults for any other truthy value
2877
+ };
2878
+
2820
2879
  Autocapture.prototype.initClickTracking = function() {
2821
2880
  win.removeEventListener(EV_CLICK, this.listenerClick);
2822
2881
 
@@ -2918,6 +2977,36 @@ Autocapture.prototype.initPageviewTracking = function() {
2918
2977
  }.bind(this)));
2919
2978
  };
2920
2979
 
2980
+ Autocapture.prototype.initRageClickTracking = function() {
2981
+ win.removeEventListener(EV_CLICK, this.listenerRageClick);
2982
+
2983
+ var rageClickConfig = this._getRageClickConfig();
2984
+ if (!rageClickConfig && !this.mp.get_config('record_heatmap_data')) {
2985
+ return;
2986
+ }
2987
+
2988
+ logger$4.log('Initializing rage click tracking');
2989
+ if (!this._rageClickTracker) {
2990
+ this._rageClickTracker = new RageClickTracker();
2991
+ }
2992
+
2993
+ this.listenerRageClick = function(ev) {
2994
+ var currentRageClickConfig = this._getRageClickConfig();
2995
+ if (!currentRageClickConfig && !this.mp.is_recording_heatmap_data()) {
2996
+ return;
2997
+ }
2998
+
2999
+ if (this.currentUrlBlocked()) {
3000
+ return;
3001
+ }
3002
+
3003
+ if (this._rageClickTracker.isRageClick(ev['pageX'], ev['pageY'], currentRageClickConfig)) {
3004
+ this.trackDomEvent(ev, MP_EV_RAGE_CLICK);
3005
+ }
3006
+ }.bind(this);
3007
+ win.addEventListener(EV_CLICK, this.listenerRageClick);
3008
+ };
3009
+
2921
3010
  Autocapture.prototype.initScrollTracking = function() {
2922
3011
  win.removeEventListener(EV_SCROLLEND, this.listenerScroll);
2923
3012
 
@@ -3004,6 +3093,7 @@ CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
3004
3093
  var FeatureFlagManager = function(initOptions) {
3005
3094
  this.getFullApiRoute = initOptions.getFullApiRoute;
3006
3095
  this.getMpConfig = initOptions.getConfigFunc;
3096
+ this.setMpConfig = initOptions.setConfigFunc;
3007
3097
  this.getMpProperty = initOptions.getPropertyFunc;
3008
3098
  this.track = initOptions.trackingFunc;
3009
3099
  };
@@ -3041,6 +3131,23 @@ FeatureFlagManager.prototype.isSystemEnabled = function() {
3041
3131
  return !!this.getMpConfig(FLAGS_CONFIG_KEY);
3042
3132
  };
3043
3133
 
3134
+ FeatureFlagManager.prototype.updateContext = function(newContext, options) {
3135
+ if (!this.isSystemEnabled()) {
3136
+ logger$3.critical('Feature Flags not enabled, cannot update context');
3137
+ return Promise.resolve();
3138
+ }
3139
+
3140
+ var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
3141
+ if (!_.isObject(ffConfig)) {
3142
+ ffConfig = {};
3143
+ }
3144
+ var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
3145
+ ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
3146
+
3147
+ this.setMpConfig(FLAGS_CONFIG_KEY, ffConfig);
3148
+ return this.fetchFlags();
3149
+ };
3150
+
3044
3151
  FeatureFlagManager.prototype.areFlagsReady = function() {
3045
3152
  if (!this.isSystemEnabled()) {
3046
3153
  logger$3.error('Feature Flags not enabled');
@@ -3050,7 +3157,7 @@ FeatureFlagManager.prototype.areFlagsReady = function() {
3050
3157
 
3051
3158
  FeatureFlagManager.prototype.fetchFlags = function() {
3052
3159
  if (!this.isSystemEnabled()) {
3053
- return;
3160
+ return Promise.resolve();
3054
3161
  }
3055
3162
 
3056
3163
  var distinctId = this.getMpProperty('distinct_id');
@@ -3090,6 +3197,8 @@ FeatureFlagManager.prototype.fetchFlags = function() {
3090
3197
  this.markFetchComplete();
3091
3198
  logger$3.error(error);
3092
3199
  }.bind(this));
3200
+
3201
+ return this.fetchPromise;
3093
3202
  };
3094
3203
 
3095
3204
  FeatureFlagManager.prototype.markFetchComplete = function() {
@@ -3202,6 +3311,7 @@ FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype
3202
3311
  FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
3203
3312
  FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
3204
3313
  FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
3314
+ FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
3205
3315
 
3206
3316
  // Deprecated method
3207
3317
  FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
@@ -3519,6 +3629,10 @@ LocalStorageWrapper.prototype.init = function () {
3519
3629
  return PromisePolyfill.resolve();
3520
3630
  };
3521
3631
 
3632
+ LocalStorageWrapper.prototype.isInitialized = function () {
3633
+ return true;
3634
+ };
3635
+
3522
3636
  LocalStorageWrapper.prototype.setItem = function (key, value) {
3523
3637
  return new PromisePolyfill(_.bind(function (resolve, reject) {
3524
3638
  try {
@@ -3599,7 +3713,7 @@ var RequestQueue = function (storageKey, options) {
3599
3713
  };
3600
3714
 
3601
3715
  RequestQueue.prototype.ensureInit = function () {
3602
- if (this.initialized) {
3716
+ if (this.initialized || !this.usePersistence) {
3603
3717
  return PromisePolyfill.resolve();
3604
3718
  }
3605
3719
 
@@ -5783,6 +5897,10 @@ IDBStorageWrapper.prototype.init = function () {
5783
5897
  });
5784
5898
  };
5785
5899
 
5900
+ IDBStorageWrapper.prototype.isInitialized = function () {
5901
+ return !!this.dbPromise;
5902
+ };
5903
+
5786
5904
  /**
5787
5905
  * @param {IDBTransactionMode} mode
5788
5906
  * @param {function(IDBObjectStore): void} storeCb
@@ -5973,7 +6091,7 @@ var DEFAULT_CONFIG = {
5973
6091
  'batch_autostart': true,
5974
6092
  'hooks': {},
5975
6093
  'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
5976
- 'record_block_selector': 'img, video',
6094
+ 'record_block_selector': 'img, video, audio',
5977
6095
  'record_canvas': false,
5978
6096
  'record_collect_fonts': false,
5979
6097
  'record_heatmap_data': false,
@@ -6197,6 +6315,7 @@ MixpanelLib.prototype._init = function(token, config, name) {
6197
6315
  return this.get_api_host('flags') + '/' + this.get_config('api_routes')['flags'];
6198
6316
  }, this),
6199
6317
  getConfigFunc: _.bind(this.get_config, this),
6318
+ setConfigFunc: _.bind(this.set_config, this),
6200
6319
  getPropertyFunc: _.bind(this.get_property, this),
6201
6320
  trackingFunc: _.bind(this.track, this)
6202
6321
  });
@@ -6215,7 +6334,9 @@ MixpanelLib.prototype._init = function(token, config, name) {
6215
6334
  * This is primarily used for session recording, where data must be isolated to the current tab.
6216
6335
  */
6217
6336
  MixpanelLib.prototype._init_tab_id = function() {
6218
- if (_.sessionStorage.is_supported()) {
6337
+ if (this.get_config('disable_persistence')) {
6338
+ console.log('Tab ID initialization skipped due to disable_persistence config');
6339
+ } else if (_.sessionStorage.is_supported()) {
6219
6340
  try {
6220
6341
  var key_suffix = this.get_config('name') + '_' + this.get_config('token');
6221
6342
  var tab_id_key = 'mp_tab_id_' + key_suffix;
@@ -6249,6 +6370,11 @@ MixpanelLib.prototype.get_tab_id = function () {
6249
6370
  };
6250
6371
 
6251
6372
  MixpanelLib.prototype._should_load_recorder = function () {
6373
+ if (this.get_config('disable_persistence')) {
6374
+ console.log('Load recorder check skipped due to disable_persistence config');
6375
+ return Promise.resolve(false);
6376
+ }
6377
+
6252
6378
  var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
6253
6379
  var tab_id = this.get_tab_id();
6254
6380
  return recording_registry_idb.init()
@@ -486,6 +486,30 @@
486
486
  function mutationObserverCtor$1() {
487
487
  return getUntaintedPrototype$1("MutationObserver").constructor;
488
488
  }
489
+ function patch$1(source, name, replacement) {
490
+ try {
491
+ if (!(name in source)) {
492
+ return function() {};
493
+ }
494
+ var original = source[name];
495
+ var wrapped = replacement(original);
496
+ if (typeof wrapped === "function") {
497
+ wrapped.prototype = wrapped.prototype || {};
498
+ Object.defineProperties(wrapped, {
499
+ __rrweb_original__: {
500
+ enumerable: false,
501
+ value: original
502
+ }
503
+ });
504
+ }
505
+ source[name] = wrapped;
506
+ return function() {
507
+ source[name] = original;
508
+ };
509
+ } catch (e) {
510
+ return function() {};
511
+ }
512
+ }
489
513
  var index$1 = {
490
514
  childNodes: childNodes$1,
491
515
  parentNode: parentNode$1,
@@ -498,7 +522,8 @@
498
522
  shadowRoot: shadowRoot$1,
499
523
  querySelector: querySelector$1,
500
524
  querySelectorAll: querySelectorAll$1,
501
- mutationObserver: mutationObserverCtor$1
525
+ mutationObserver: mutationObserverCtor$1,
526
+ patch: patch$1
502
527
  };
503
528
  function isElement(n2) {
504
529
  return n2.nodeType === n2.ELEMENT_NODE;
@@ -749,26 +774,82 @@
749
774
  return "url(" + maybeQuote + stack.join("/") + maybeQuote + ")";
750
775
  });
751
776
  }
752
- function normalizeCssString(cssText) {
753
- return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
777
+ function normalizeCssString(cssText, _testNoPxNorm) {
778
+ if (_testNoPxNorm === void 0) _testNoPxNorm = false;
779
+ if (_testNoPxNorm) {
780
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
781
+ } else {
782
+ return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
783
+ }
754
784
  }
755
- function splitCssText(cssText, style) {
785
+ function splitCssText(cssText, style, _testNoPxNorm) {
786
+ if (_testNoPxNorm === void 0) _testNoPxNorm = false;
756
787
  var childNodes2 = Array.from(style.childNodes);
757
788
  var splits = [];
789
+ var iterCount = 0;
758
790
  if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
759
- var cssTextNorm = normalizeCssString(cssText);
791
+ var cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
792
+ var normFactor = cssTextNorm.length / cssText.length;
760
793
  for(var i2 = 1; i2 < childNodes2.length; i2++){
761
794
  if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
762
- var textContentNorm = normalizeCssString(childNodes2[i2].textContent);
763
- for(var j = 3; j < textContentNorm.length; j++){
764
- var bit = textContentNorm.substring(0, j);
765
- if (cssTextNorm.split(bit).length === 2) {
766
- var splitNorm = cssTextNorm.indexOf(bit);
767
- for(var k = splitNorm; k < cssText.length; k++){
768
- if (normalizeCssString(cssText.substring(0, k)).length === splitNorm) {
795
+ var textContentNorm = normalizeCssString(childNodes2[i2].textContent, _testNoPxNorm);
796
+ var jLimit = 100;
797
+ var j = 3;
798
+ for(; j < textContentNorm.length; j++){
799
+ if (// keep consuming css identifiers (to get a decent chunk more quickly)
800
+ textContentNorm[j].match(/[a-zA-Z0-9]/) || // substring needs to be unique to this section
801
+ textContentNorm.indexOf(textContentNorm.substring(0, j), 1) !== -1) {
802
+ continue;
803
+ }
804
+ break;
805
+ }
806
+ for(; j < textContentNorm.length; j++){
807
+ var startSubstring = textContentNorm.substring(0, j);
808
+ var cssNormSplits = cssTextNorm.split(startSubstring);
809
+ var splitNorm = -1;
810
+ if (cssNormSplits.length === 2) {
811
+ splitNorm = cssNormSplits[0].length;
812
+ } else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
813
+ splitNorm = cssTextNorm.indexOf(startSubstring, 1);
814
+ } else if (cssNormSplits.length === 1) {
815
+ startSubstring = startSubstring.substring(0, startSubstring.length - 1);
816
+ cssNormSplits = cssTextNorm.split(startSubstring);
817
+ if (cssNormSplits.length <= 1) {
818
+ splits.push(cssText);
819
+ return splits;
820
+ }
821
+ j = jLimit + 1;
822
+ } else if (j === textContentNorm.length - 1) {
823
+ splitNorm = cssTextNorm.indexOf(startSubstring);
824
+ }
825
+ if (cssNormSplits.length >= 2 && j > jLimit) {
826
+ var prevTextContent = childNodes2[i2 - 1].textContent;
827
+ if (prevTextContent && typeof prevTextContent === "string") {
828
+ var prevMinLength = normalizeCssString(prevTextContent).length;
829
+ splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
830
+ }
831
+ if (splitNorm === -1) {
832
+ splitNorm = cssNormSplits[0].length;
833
+ }
834
+ }
835
+ if (splitNorm !== -1) {
836
+ var k = Math.floor(splitNorm / normFactor);
837
+ for(; k > 0 && k < cssText.length;){
838
+ iterCount += 1;
839
+ if (iterCount > 50 * childNodes2.length) {
840
+ splits.push(cssText);
841
+ return splits;
842
+ }
843
+ var normPart = normalizeCssString(cssText.substring(0, k), _testNoPxNorm);
844
+ if (normPart.length === splitNorm) {
769
845
  splits.push(cssText.substring(0, k));
770
846
  cssText = cssText.substring(k);
847
+ cssTextNorm = cssTextNorm.substring(splitNorm);
771
848
  break;
849
+ } else if (normPart.length < splitNorm) {
850
+ k += Math.max(1, Math.floor((splitNorm - normPart.length) / normFactor));
851
+ } else {
852
+ k -= Math.max(1, Math.floor((normPart.length - splitNorm) * normFactor));
772
853
  }
773
854
  }
774
855
  break;
@@ -1285,7 +1366,7 @@
1285
1366
  } else if (sn.type === NodeType$3.Element) {
1286
1367
  if (slimDOMOptions.script && // script tag
1287
1368
  (sn.tagName === "script" || // (module)preload link
1288
- sn.tagName === "link" && (sn.attributes.rel === "preload" || sn.attributes.rel === "modulepreload") && sn.attributes.as === "script" || // prefetch link
1369
+ sn.tagName === "link" && (sn.attributes.rel === "preload" && sn.attributes.as === "script" || sn.attributes.rel === "modulepreload") || // prefetch link
1289
1370
  sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
1290
1371
  return true;
1291
1372
  } 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"))) {
@@ -10036,6 +10117,30 @@
10036
10117
  function mutationObserverCtor() {
10037
10118
  return getUntaintedPrototype("MutationObserver").constructor;
10038
10119
  }
10120
+ function patch(source, name, replacement) {
10121
+ try {
10122
+ if (!(name in source)) {
10123
+ return function() {};
10124
+ }
10125
+ var original = source[name];
10126
+ var wrapped = replacement(original);
10127
+ if (typeof wrapped === "function") {
10128
+ wrapped.prototype = wrapped.prototype || {};
10129
+ Object.defineProperties(wrapped, {
10130
+ __rrweb_original__: {
10131
+ enumerable: false,
10132
+ value: original
10133
+ }
10134
+ });
10135
+ }
10136
+ source[name] = wrapped;
10137
+ return function() {
10138
+ source[name] = original;
10139
+ };
10140
+ } catch (e) {
10141
+ return function() {};
10142
+ }
10143
+ }
10039
10144
  var index = {
10040
10145
  childNodes: childNodes,
10041
10146
  parentNode: parentNode,
@@ -10048,7 +10153,8 @@
10048
10153
  shadowRoot: shadowRoot,
10049
10154
  querySelector: querySelector,
10050
10155
  querySelectorAll: querySelectorAll,
10051
- mutationObserver: mutationObserverCtor
10156
+ mutationObserver: mutationObserverCtor,
10157
+ patch: patch
10052
10158
  };
10053
10159
  function on(type, fn, target) {
10054
10160
  if (target === void 0) target = document;
@@ -10141,30 +10247,6 @@
10141
10247
  return hookSetter(target, key, original || {}, true);
10142
10248
  };
10143
10249
  }
10144
- function patch(source, name, replacement) {
10145
- try {
10146
- if (!(name in source)) {
10147
- return function() {};
10148
- }
10149
- var original = source[name];
10150
- var wrapped = replacement(original);
10151
- if (typeof wrapped === "function") {
10152
- wrapped.prototype = wrapped.prototype || {};
10153
- Object.defineProperties(wrapped, {
10154
- __rrweb_original__: {
10155
- enumerable: false,
10156
- value: original
10157
- }
10158
- });
10159
- }
10160
- source[name] = wrapped;
10161
- return function() {
10162
- source[name] = original;
10163
- };
10164
- } catch (e) {
10165
- return function() {};
10166
- }
10167
- }
10168
10250
  var nowTimestamp = Date.now;
10169
10251
  if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
10170
10252
  nowTimestamp = function() {
@@ -10755,9 +10837,17 @@
10755
10837
  _this.attributes.push(item);
10756
10838
  _this.attributeMap.set(textarea, item);
10757
10839
  }
10758
- item.attributes.value = Array.from(index.childNodes(textarea), function(cn) {
10840
+ var value = Array.from(index.childNodes(textarea), function(cn) {
10759
10841
  return index.textContent(cn) || "";
10760
10842
  }).join("");
10843
+ item.attributes.value = maskInputValue({
10844
+ element: textarea,
10845
+ maskInputOptions: _this.maskInputOptions,
10846
+ tagName: textarea.tagName,
10847
+ type: getInputType(textarea),
10848
+ value: value,
10849
+ maskInputFn: _this.maskInputFn
10850
+ });
10761
10851
  });
10762
10852
  __publicField(this, "processMutation", function(m) {
10763
10853
  if (isIgnored(m.target, _this.mirror, _this.slimDOMOptions)) {
@@ -13538,8 +13628,15 @@
13538
13628
  }, window));
13539
13629
  }
13540
13630
  return function() {
13541
- handlers.forEach(function(h) {
13542
- return h();
13631
+ handlers.forEach(function(handler) {
13632
+ try {
13633
+ handler();
13634
+ } catch (error) {
13635
+ var msg = String(error).toLowerCase();
13636
+ if (!msg.includes("cross-origin")) {
13637
+ console.warn(error);
13638
+ }
13639
+ }
13543
13640
  });
13544
13641
  processedNodeManager.destroy();
13545
13642
  recording = false;
@@ -13944,7 +14041,7 @@
13944
14041
  }
13945
14042
 
13946
14043
  var Config = {
13947
- LIB_VERSION: '2.67.0'
14044
+ LIB_VERSION: '2.69.0'
13948
14045
  };
13949
14046
 
13950
14047
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -15692,6 +15789,10 @@
15692
15789
  });
15693
15790
  };
15694
15791
 
15792
+ IDBStorageWrapper.prototype.isInitialized = function () {
15793
+ return !!this.dbPromise;
15794
+ };
15795
+
15695
15796
  /**
15696
15797
  * @param {IDBTransactionMode} mode
15697
15798
  * @param {function(IDBObjectStore): void} storeCb
@@ -16084,6 +16185,10 @@
16084
16185
  return PromisePolyfill.resolve();
16085
16186
  };
16086
16187
 
16188
+ LocalStorageWrapper.prototype.isInitialized = function () {
16189
+ return true;
16190
+ };
16191
+
16087
16192
  LocalStorageWrapper.prototype.setItem = function (key, value) {
16088
16193
  return new PromisePolyfill(_.bind(function (resolve, reject) {
16089
16194
  try {
@@ -16164,7 +16269,7 @@
16164
16269
  };
16165
16270
 
16166
16271
  RequestQueue.prototype.ensureInit = function () {
16167
- if (this.initialized) {
16272
+ if (this.initialized || !this.usePersistence) {
16168
16273
  return PromisePolyfill.resolve();
16169
16274
  }
16170
16275
 
@@ -16916,10 +17021,9 @@
16916
17021
 
16917
17022
  // disable persistence if localStorage is not supported
16918
17023
  // request-queue will automatically disable persistence if indexedDB fails to initialize
16919
- var usePersistence = localStorageSupported(options.sharedLockStorage, true);
17024
+ var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
16920
17025
 
16921
17026
  // each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
16922
- // this will be important when persistence is introduced
16923
17027
  this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
16924
17028
  this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
16925
17029
  this.batcher = new RequestBatcher(this.batcherKey, {
@@ -17300,12 +17404,17 @@
17300
17404
  * Makes sure that only one tab can be recording at a time.
17301
17405
  */
17302
17406
  var RecordingRegistry = function (options) {
17407
+ /** @type {IDBStorageWrapper} */
17303
17408
  this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
17304
17409
  this.errorReporter = options.errorReporter;
17305
17410
  this.mixpanelInstance = options.mixpanelInstance;
17306
17411
  this.sharedLockStorage = options.sharedLockStorage;
17307
17412
  };
17308
17413
 
17414
+ RecordingRegistry.prototype.isPersistenceEnabled = function() {
17415
+ return !this.mixpanelInstance.get_config('disable_persistence');
17416
+ };
17417
+
17309
17418
  RecordingRegistry.prototype.handleError = function (err) {
17310
17419
  this.errorReporter('IndexedDB error: ', err);
17311
17420
  };
@@ -17314,6 +17423,10 @@
17314
17423
  * @param {import('./session-recording').SerializedRecording} serializedRecording
17315
17424
  */
17316
17425
  RecordingRegistry.prototype.setActiveRecording = function (serializedRecording) {
17426
+ if (!this.isPersistenceEnabled()) {
17427
+ return PromisePolyfill.resolve();
17428
+ }
17429
+
17317
17430
  var tabId = serializedRecording['tabId'];
17318
17431
  if (!tabId) {
17319
17432
  console.warn('No tab ID is set, cannot persist recording metadata.');
@@ -17331,6 +17444,10 @@
17331
17444
  * @returns {Promise<import('./session-recording').SerializedRecording>}
17332
17445
  */
17333
17446
  RecordingRegistry.prototype.getActiveRecording = function () {
17447
+ if (!this.isPersistenceEnabled()) {
17448
+ return PromisePolyfill.resolve(null);
17449
+ }
17450
+
17334
17451
  return this.idb.init()
17335
17452
  .then(function () {
17336
17453
  return this.idb.getItem(this.mixpanelInstance.get_tab_id());
@@ -17342,8 +17459,16 @@
17342
17459
  };
17343
17460
 
17344
17461
  RecordingRegistry.prototype.clearActiveRecording = function () {
17345
- // mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
17346
- // this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
17462
+ if (this.isPersistenceEnabled()) {
17463
+ // mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
17464
+ // this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
17465
+ return this.markActiveRecordingExpired();
17466
+ } else {
17467
+ return this.deleteActiveRecording();
17468
+ }
17469
+ };
17470
+
17471
+ RecordingRegistry.prototype.markActiveRecordingExpired = function () {
17347
17472
  return this.getActiveRecording()
17348
17473
  .then(function (serializedRecording) {
17349
17474
  if (serializedRecording) {
@@ -17354,11 +17479,25 @@
17354
17479
  .catch(this.handleError.bind(this));
17355
17480
  };
17356
17481
 
17482
+ RecordingRegistry.prototype.deleteActiveRecording = function () {
17483
+ // avoid initializing IDB if this registry instance hasn't already written a recording
17484
+ if (this.idb.isInitialized()) {
17485
+ return this.idb.removeItem(this.mixpanelInstance.get_tab_id())
17486
+ .catch(this.handleError.bind(this));
17487
+ } else {
17488
+ return PromisePolyfill.resolve();
17489
+ }
17490
+ };
17491
+
17357
17492
  /**
17358
17493
  * Flush any inactive recordings from the registry to minimize data loss.
17359
17494
  * The main idea here is that we can flush remaining rrweb events on the next page load if a tab is closed mid-batch.
17360
17495
  */
17361
17496
  RecordingRegistry.prototype.flushInactiveRecordings = function () {
17497
+ if (!this.isPersistenceEnabled()) {
17498
+ return PromisePolyfill.resolve([]);
17499
+ }
17500
+
17362
17501
  return this.idb.init()
17363
17502
  .then(function() {
17364
17503
  return this.idb.getAll();