mixpanel-browser 2.61.0 → 2.61.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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  var Config = {
4
4
  DEBUG: false,
5
- LIB_VERSION: '2.61.0'
5
+ LIB_VERSION: '2.61.1'
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
@@ -5624,7 +5624,7 @@ IDBStorageWrapper.prototype.makeTransaction = function (mode, storeCb) {
5624
5624
  return this.dbPromise
5625
5625
  .then(doTransaction)
5626
5626
  .catch(function (err) {
5627
- if (err['name'] === 'InvalidStateError') {
5627
+ if (err && err['name'] === 'InvalidStateError') {
5628
5628
  // try reopening the DB if the connection is closed
5629
5629
  this.dbPromise = this._openDb();
5630
5630
  return this.dbPromise.then(doTransaction);
@@ -4893,7 +4893,7 @@ define((function () { 'use strict';
4893
4893
 
4894
4894
  var Config = {
4895
4895
  DEBUG: false,
4896
- LIB_VERSION: '2.61.0'
4896
+ LIB_VERSION: '2.61.1'
4897
4897
  };
4898
4898
 
4899
4899
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -6756,7 +6756,7 @@ define((function () { 'use strict';
6756
6756
  return this.dbPromise
6757
6757
  .then(doTransaction)
6758
6758
  .catch(function (err) {
6759
- if (err['name'] === 'InvalidStateError') {
6759
+ if (err && err['name'] === 'InvalidStateError') {
6760
6760
  // try reopening the DB if the connection is closed
6761
6761
  this.dbPromise = this._openDb();
6762
6762
  return this.dbPromise.then(doTransaction);
@@ -8180,34 +8180,37 @@ define((function () { 'use strict';
8180
8180
  blockSelector = undefined;
8181
8181
  }
8182
8182
 
8183
- this._stopRecording = this._rrwebRecord({
8184
- 'emit': addOptOutCheckMixpanelLib(function (ev) {
8185
- if (isUserEvent(ev)) {
8186
- if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8187
- // start flushing again after user activity
8188
- this.batcher.start();
8183
+ try {
8184
+ this._stopRecording = this._rrwebRecord({
8185
+ 'emit': function (ev) {
8186
+ if (isUserEvent(ev)) {
8187
+ if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8188
+ // start flushing again after user activity
8189
+ this.batcher.start();
8190
+ }
8191
+ resetIdleTimeout();
8189
8192
  }
8190
- resetIdleTimeout();
8193
+ // promise only used to await during tests
8194
+ this.__enqueuePromise = this.batcher.enqueue(ev);
8195
+ }.bind(this),
8196
+ 'blockClass': this.getConfig('record_block_class'),
8197
+ 'blockSelector': blockSelector,
8198
+ 'collectFonts': this.getConfig('record_collect_fonts'),
8199
+ 'dataURLOptions': { // canvas image options (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)
8200
+ 'type': 'image/webp',
8201
+ 'quality': 0.6
8202
+ },
8203
+ 'maskAllInputs': true,
8204
+ 'maskTextClass': this.getConfig('record_mask_text_class'),
8205
+ 'maskTextSelector': this.getConfig('record_mask_text_selector'),
8206
+ 'recordCanvas': this.getConfig('record_canvas'),
8207
+ 'sampling': {
8208
+ 'canvas': 15
8191
8209
  }
8192
-
8193
- // promise only used to await during tests
8194
- this.__enqueuePromise = this.batcher.enqueue(ev);
8195
- }.bind(this)),
8196
- 'blockClass': this.getConfig('record_block_class'),
8197
- 'blockSelector': blockSelector,
8198
- 'collectFonts': this.getConfig('record_collect_fonts'),
8199
- 'dataURLOptions': { // canvas image options (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)
8200
- 'type': 'image/webp',
8201
- 'quality': 0.6
8202
- },
8203
- 'maskAllInputs': true,
8204
- 'maskTextClass': this.getConfig('record_mask_text_class'),
8205
- 'maskTextSelector': this.getConfig('record_mask_text_selector'),
8206
- 'recordCanvas': this.getConfig('record_canvas'),
8207
- 'sampling': {
8208
- 'canvas': 15
8209
- }
8210
- });
8210
+ });
8211
+ } catch (err) {
8212
+ this.reportError('Unexpected error when starting rrweb recording.', err);
8213
+ }
8211
8214
 
8212
8215
  if (typeof this._stopRecording !== 'function') {
8213
8216
  this.reportError('rrweb failed to start, skipping this recording.');
@@ -8251,12 +8254,21 @@ define((function () { 'use strict';
8251
8254
  return this._stopRecording === null;
8252
8255
  };
8253
8256
 
8257
+
8254
8258
  /**
8255
8259
  * Flushes the current batch of events to the server, but passes an opt-out callback to make sure
8256
8260
  * we stop recording and dump any queued events if the user has opted out.
8257
8261
  */
8258
8262
  SessionRecording.prototype.flushEventsWithOptOut = function (data, options, cb) {
8259
- this._flushEvents(data, options, cb, this._onOptOut.bind(this));
8263
+ var onOptOut = function (code) {
8264
+ // addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
8265
+ if (code === 0) {
8266
+ this.stopRecording();
8267
+ cb({error: 'Tracking has been opted out, stopping recording.'});
8268
+ }
8269
+ }.bind(this);
8270
+
8271
+ this._flushEvents(data, options, cb, onOptOut);
8260
8272
  };
8261
8273
 
8262
8274
  /**
@@ -8306,13 +8318,6 @@ define((function () { 'use strict';
8306
8318
  return recording;
8307
8319
  };
8308
8320
 
8309
- SessionRecording.prototype._onOptOut = function (code) {
8310
- // addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
8311
- if (code === 0) {
8312
- this.stopRecording();
8313
- }
8314
- };
8315
-
8316
8321
  SessionRecording.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) {
8317
8322
  var onSuccess = function (response, responseBody) {
8318
8323
  // Update batch specific props only if the request was successful to guarantee ordering.
@@ -8355,17 +8360,32 @@ define((function () { 'use strict';
8355
8360
 
8356
8361
  if (numEvents > 0) {
8357
8362
  var replayId = this.replayId;
8363
+
8358
8364
  // each rrweb event has a timestamp - leverage those to get time properties
8359
- var batchStartTime = data[0].timestamp;
8360
- if (this.seqNo === 0 || !this.replayStartTime) {
8361
- // extra safety net so that we don't send a null replay start time
8362
- if (this.seqNo !== 0) {
8363
- this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.');
8365
+ var batchStartTime = Infinity;
8366
+ var batchEndTime = -Infinity;
8367
+ var hasFullSnapshot = false;
8368
+ for (var i = 0; i < numEvents; i++) {
8369
+ batchStartTime = Math.min(batchStartTime, data[i].timestamp);
8370
+ batchEndTime = Math.max(batchEndTime, data[i].timestamp);
8371
+ if (data[i].type === EventType.FullSnapshot) {
8372
+ hasFullSnapshot = true;
8364
8373
  }
8374
+ }
8365
8375
 
8376
+ if (this.seqNo === 0) {
8377
+ if (!hasFullSnapshot) {
8378
+ callback({error: 'First batch does not contain a full snapshot. Aborting recording.'});
8379
+ this.stopRecording(true);
8380
+ return;
8381
+ }
8382
+ this.replayStartTime = batchStartTime;
8383
+ } else if (!this.replayStartTime) {
8384
+ this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.');
8366
8385
  this.replayStartTime = batchStartTime;
8367
8386
  }
8368
- var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime;
8387
+
8388
+ var replayLengthMs = batchEndTime - this.replayStartTime;
8369
8389
 
8370
8390
  var reqParams = {
8371
8391
  '$current_url': this.batchStartUrl,
@@ -4893,7 +4893,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
4893
4893
 
4894
4894
  var Config = {
4895
4895
  DEBUG: false,
4896
- LIB_VERSION: '2.61.0'
4896
+ LIB_VERSION: '2.61.1'
4897
4897
  };
4898
4898
 
4899
4899
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -6756,7 +6756,7 @@ IDBStorageWrapper.prototype.makeTransaction = function (mode, storeCb) {
6756
6756
  return this.dbPromise
6757
6757
  .then(doTransaction)
6758
6758
  .catch(function (err) {
6759
- if (err['name'] === 'InvalidStateError') {
6759
+ if (err && err['name'] === 'InvalidStateError') {
6760
6760
  // try reopening the DB if the connection is closed
6761
6761
  this.dbPromise = this._openDb();
6762
6762
  return this.dbPromise.then(doTransaction);
@@ -8180,34 +8180,37 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
8180
8180
  blockSelector = undefined;
8181
8181
  }
8182
8182
 
8183
- this._stopRecording = this._rrwebRecord({
8184
- 'emit': addOptOutCheckMixpanelLib(function (ev) {
8185
- if (isUserEvent(ev)) {
8186
- if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8187
- // start flushing again after user activity
8188
- this.batcher.start();
8183
+ try {
8184
+ this._stopRecording = this._rrwebRecord({
8185
+ 'emit': function (ev) {
8186
+ if (isUserEvent(ev)) {
8187
+ if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8188
+ // start flushing again after user activity
8189
+ this.batcher.start();
8190
+ }
8191
+ resetIdleTimeout();
8189
8192
  }
8190
- resetIdleTimeout();
8193
+ // promise only used to await during tests
8194
+ this.__enqueuePromise = this.batcher.enqueue(ev);
8195
+ }.bind(this),
8196
+ 'blockClass': this.getConfig('record_block_class'),
8197
+ 'blockSelector': blockSelector,
8198
+ 'collectFonts': this.getConfig('record_collect_fonts'),
8199
+ 'dataURLOptions': { // canvas image options (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)
8200
+ 'type': 'image/webp',
8201
+ 'quality': 0.6
8202
+ },
8203
+ 'maskAllInputs': true,
8204
+ 'maskTextClass': this.getConfig('record_mask_text_class'),
8205
+ 'maskTextSelector': this.getConfig('record_mask_text_selector'),
8206
+ 'recordCanvas': this.getConfig('record_canvas'),
8207
+ 'sampling': {
8208
+ 'canvas': 15
8191
8209
  }
8192
-
8193
- // promise only used to await during tests
8194
- this.__enqueuePromise = this.batcher.enqueue(ev);
8195
- }.bind(this)),
8196
- 'blockClass': this.getConfig('record_block_class'),
8197
- 'blockSelector': blockSelector,
8198
- 'collectFonts': this.getConfig('record_collect_fonts'),
8199
- 'dataURLOptions': { // canvas image options (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)
8200
- 'type': 'image/webp',
8201
- 'quality': 0.6
8202
- },
8203
- 'maskAllInputs': true,
8204
- 'maskTextClass': this.getConfig('record_mask_text_class'),
8205
- 'maskTextSelector': this.getConfig('record_mask_text_selector'),
8206
- 'recordCanvas': this.getConfig('record_canvas'),
8207
- 'sampling': {
8208
- 'canvas': 15
8209
- }
8210
- });
8210
+ });
8211
+ } catch (err) {
8212
+ this.reportError('Unexpected error when starting rrweb recording.', err);
8213
+ }
8211
8214
 
8212
8215
  if (typeof this._stopRecording !== 'function') {
8213
8216
  this.reportError('rrweb failed to start, skipping this recording.');
@@ -8251,12 +8254,21 @@ SessionRecording.prototype.isRrwebStopped = function () {
8251
8254
  return this._stopRecording === null;
8252
8255
  };
8253
8256
 
8257
+
8254
8258
  /**
8255
8259
  * Flushes the current batch of events to the server, but passes an opt-out callback to make sure
8256
8260
  * we stop recording and dump any queued events if the user has opted out.
8257
8261
  */
8258
8262
  SessionRecording.prototype.flushEventsWithOptOut = function (data, options, cb) {
8259
- this._flushEvents(data, options, cb, this._onOptOut.bind(this));
8263
+ var onOptOut = function (code) {
8264
+ // addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
8265
+ if (code === 0) {
8266
+ this.stopRecording();
8267
+ cb({error: 'Tracking has been opted out, stopping recording.'});
8268
+ }
8269
+ }.bind(this);
8270
+
8271
+ this._flushEvents(data, options, cb, onOptOut);
8260
8272
  };
8261
8273
 
8262
8274
  /**
@@ -8306,13 +8318,6 @@ SessionRecording.deserialize = function (serializedRecording, options) {
8306
8318
  return recording;
8307
8319
  };
8308
8320
 
8309
- SessionRecording.prototype._onOptOut = function (code) {
8310
- // addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
8311
- if (code === 0) {
8312
- this.stopRecording();
8313
- }
8314
- };
8315
-
8316
8321
  SessionRecording.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) {
8317
8322
  var onSuccess = function (response, responseBody) {
8318
8323
  // Update batch specific props only if the request was successful to guarantee ordering.
@@ -8355,17 +8360,32 @@ SessionRecording.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da
8355
8360
 
8356
8361
  if (numEvents > 0) {
8357
8362
  var replayId = this.replayId;
8363
+
8358
8364
  // each rrweb event has a timestamp - leverage those to get time properties
8359
- var batchStartTime = data[0].timestamp;
8360
- if (this.seqNo === 0 || !this.replayStartTime) {
8361
- // extra safety net so that we don't send a null replay start time
8362
- if (this.seqNo !== 0) {
8363
- this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.');
8365
+ var batchStartTime = Infinity;
8366
+ var batchEndTime = -Infinity;
8367
+ var hasFullSnapshot = false;
8368
+ for (var i = 0; i < numEvents; i++) {
8369
+ batchStartTime = Math.min(batchStartTime, data[i].timestamp);
8370
+ batchEndTime = Math.max(batchEndTime, data[i].timestamp);
8371
+ if (data[i].type === EventType.FullSnapshot) {
8372
+ hasFullSnapshot = true;
8364
8373
  }
8374
+ }
8365
8375
 
8376
+ if (this.seqNo === 0) {
8377
+ if (!hasFullSnapshot) {
8378
+ callback({error: 'First batch does not contain a full snapshot. Aborting recording.'});
8379
+ this.stopRecording(true);
8380
+ return;
8381
+ }
8382
+ this.replayStartTime = batchStartTime;
8383
+ } else if (!this.replayStartTime) {
8384
+ this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.');
8366
8385
  this.replayStartTime = batchStartTime;
8367
8386
  }
8368
- var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime;
8387
+
8388
+ var replayLengthMs = batchEndTime - this.replayStartTime;
8369
8389
 
8370
8390
  var reqParams = {
8371
8391
  '$current_url': this.batchStartUrl,
@@ -3,7 +3,7 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.61.0'
6
+ LIB_VERSION: '2.61.1'
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
@@ -5625,7 +5625,7 @@
5625
5625
  return this.dbPromise
5626
5626
  .then(doTransaction)
5627
5627
  .catch(function (err) {
5628
- if (err['name'] === 'InvalidStateError') {
5628
+ if (err && err['name'] === 'InvalidStateError') {
5629
5629
  // try reopening the DB if the connection is closed
5630
5630
  this.dbPromise = this._openDb();
5631
5631
  return this.dbPromise.then(doTransaction);
@@ -56,7 +56,7 @@ Tb="dclid,fbclid,gclid,ko_click_id,li_fat_id,msclkid,sccid,ttclid,twclid,wbraid"
56
56
  "Chrome iOS":/CriOS\/(\d+(\.\d+)?)/,"UC Browser":/(UCBrowser|UCWEB)\/(\d+(\.\d+)?)/,Safari:/Version\/(\d+(\.\d+)?)/,"Mobile Safari":/Version\/(\d+(\.\d+)?)/,Opera:/(Opera|OPR)\/(\d+(\.\d+)?)/,Firefox:/Firefox\/(\d+(\.\d+)?)/,"Firefox iOS":/FxiOS\/(\d+(\.\d+)?)/,Konqueror:/Konqueror:(\d+(\.\d+)?)/,BlackBerry:/BlackBerry (\d+(\.\d+)?)/,"Android Mobile":/android\s(\d+(\.\d+)?)/,"Samsung Internet":/SamsungBrowser\/(\d+(\.\d+)?)/,"Internet Explorer":/(rv:|MSIE )(\d+(\.\d+)?)/,Mozilla:/rv:(\d+(\.\d+)?)/}[c.info.xa(a,
57
57
  b,d)];if(b===k)return r;a=a.match(b);return!a?r:parseFloat(a[a.length-2])},mc:function(){return/Windows/i.test(B)?/Phone/.test(B)||/WPDesktop/.test(B)?"Windows Phone":"Windows":/(iPhone|iPad|iPod)/.test(B)?"iOS":/Android/.test(B)?"Android":/(BlackBerry|PlayBook|BB10)/i.test(B)?"BlackBerry":/Mac/i.test(B)?"Mac OS X":/Linux/.test(B)?"Linux":/CrOS/.test(B)?"Chrome OS":""},$b:function(a){return/Windows Phone/i.test(a)||/WPDesktop/.test(a)?"Windows Phone":/iPad/.test(a)?"iPad":/iPod/.test(a)?"iPod Touch":
58
58
  /iPhone/.test(a)?"iPhone":/(BlackBerry|PlayBook|BB10)/i.test(a)?"BlackBerry":/Android/.test(a)?"Android":""},tc:function(a){a=a.split("/");return 3<=a.length?a[2]:""},Aa:function(){return j.location.href},la:function(a){"object"!==typeof a&&(a={});return c.extend(c.X({$os:c.info.mc(),$browser:c.info.xa(B,P.vendor,na),$referrer:v.referrer,$referring_domain:c.info.tc(v.referrer),$device:c.info.$b(B)}),{$current_url:c.info.Aa(),$browser_version:c.info.ab(B,P.vendor,na),$screen_height:oa.height,$screen_width:oa.width,
59
- mp_lib:"web",$lib_version:"2.61.0",$insert_id:va(),time:c.timestamp()/1E3},c.X(a))},Xd:function(){return c.extend(c.X({$os:c.info.mc(),$browser:c.info.xa(B,P.vendor,na)}),{$browser_version:c.info.ab(B,P.vendor,na)})},Td:function(){return c.X({current_page_title:v.title,current_domain:j.location.hostname,current_url_path:j.location.pathname,current_url_protocol:j.location.protocol,current_url_search:j.location.search})}};var Bb=/[a-z0-9][a-z0-9-]*\.[a-z]+$/i,Ab=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,
59
+ mp_lib:"web",$lib_version:"2.61.1",$insert_id:va(),time:c.timestamp()/1E3},c.X(a))},Xd:function(){return c.extend(c.X({$os:c.info.mc(),$browser:c.info.xa(B,P.vendor,na)}),{$browser_version:c.info.ab(B,P.vendor,na)})},Td:function(){return c.X({current_page_title:v.title,current_domain:j.location.hostname,current_url_path:j.location.pathname,current_url_protocol:j.location.protocol,current_url_search:j.location.search})}};var Bb=/[a-z0-9][a-z0-9-]*\.[a-z]+$/i,Ab=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,
60
60
  pa=r,qa=r;if("undefined"!==typeof JSON)pa=JSON.stringify,qa=JSON.parse;pa=pa||c.sa;qa=qa||c.aa;c.info=c.info;c.info.browser=c.info.xa;c.info.browserVersion=c.info.ab;c.info.device=c.info.$b;c.info.properties=c.info.la;c.isBlockedUA=c.ic;c.isEmptyObject=c.Ha;c.isObject=c.g;c.JSONDecode=c.aa;c.JSONEncode=c.sa;c.toArray=c.Y;c.NPO=M;var ia="change",$="click",Ha="submit",Ib="clientX,clientY,offsetX,offsetY,pageX,pageY,screenX,screenY,x,y".split(","),eb=["mp-include"],Ga=["mp-no-track"],db=Ga.concat(["mp-sensitive"]),
61
61
  Fb="aria-label,aria-labelledby,aria-describedby,href,name,role,title,type".split(","),D=fa("autocapture"),qb={allow_selectors:[],allow_url_regexes:[],block_attrs:[],block_element_callback:r,block_selectors:[],block_url_regexes:[],capture_extra_attrs:[],capture_text_content:C,scroll_capture_all:C,scroll_depth_percent_checkpoints:[25,50,75,100],click:l,input:l,pageview:"full-url",scroll:l,submit:l},ra={$mp_autocapture:l};E.prototype.A=function(){var a;try{a=!!v.createElement("div").matches}catch(b){a=
62
62
  C}a?(this.Ed(),this.Cd(),this.Dd(),this.Fd(),this.Gd()):D.m("Autocapture unavailable: missing required DOM APIs")};E.prototype.wd=function(){var a=this.B.c("autocapture");return a?c.g(a)?c.extend({},qb,a):qb:{}};E.prototype.j=function(a){return this.wd()[a]};E.prototype.Ba=function(){var a,b=c.info.Aa(),d=this.j("allow_url_regexes")||[];if(d.length){var g=C;for(a=0;a<d.length;a++){var f=d[a];try{if(b.match(f)){g=l;break}}catch(e){return D.m("Error while checking block URL regex: "+f,e),l}}if(!g)return l}d=
@@ -79,7 +79,7 @@ a},this)).catch(c.bind(function(a){this.h("Error clearing queue",a);return C},th
79
79
  w.resolve(l)};G.prototype.oa=function(){return this.O().then(c.bind(function(){return this.K.getItem(this.W)},this)).then(c.bind(function(a){a&&!c.isArray(a)&&(this.h("Invalid storage entry:",a),a=r);return a||[]},this)).catch(c.bind(function(a){this.h("Error retrieving queue",a);return[]},this))};G.prototype.tb=function(a){return this.O().then(c.bind(function(){return this.K.setItem(this.W,a)},this)).then(function(){return l}).catch(c.bind(function(a){this.h("Error saving queue",a);return C},this))};
80
80
  G.prototype.clear=function(){this.F=[];return this.v?this.O().then(c.bind(function(){return this.K.removeItem(this.W)},this)):w.resolve()};var ba=fa("batch");F.prototype.fb=function(a){return this.ma.fb(a,this.Ea)};F.prototype.start=function(){this.pa=C;this.bb=0;return this.flush()};F.prototype.stop=function(){this.pa=l;if(this.wb)clearTimeout(this.wb),this.wb=r};F.prototype.clear=function(){return this.ma.clear()};F.prototype.wc=function(){this.M=this.J.batch_size};F.prototype.U=function(){this.yc(this.J.batch_flush_interval_ms)};
81
81
  F.prototype.yc=function(a){this.Ea=a;if(!this.pa)this.wb=setTimeout(c.bind(function(){if(!this.pa)this.Wc=this.flush()},this),this.Ea)};F.prototype.ge=function(a,b){return new w(c.bind(function(c){this.ee(a,b,c)},this))};F.prototype.flush=function(a){if(this.sb)return ba.log("Flush: Request already in progress"),w.resolve();this.sb=l;var a=a||{},b=this.J.batch_request_timeout_ms,d=(new Date).getTime(),g=this.M;return this.ma.td(g).then(c.bind(function(f){var e=f.length===g,t=[],i={};c.a(f,function(a){var b=
82
- a.payload;this.wa&&!a.Vd&&(b=this.wa(b));if(b){b.event&&b.properties&&(b.properties=c.extend({},b.properties,{mp_sent_by_lib_version:"2.61.0"}));var d=l,g=a.id;if(g){if(5<(this.Q[g]||0))this.h("[dupe] item ID sent too many times, not sending",{item:a,M:f.length,xe:this.Q[g]}),d=C}else this.h("[dupe] found item with no ID",{item:a});d&&t.push(b)}i[a.id]=b},this);if(1>t.length)return this.sb=C,this.U(),w.resolve();var m=c.bind(function(){return this.ma.Yd(c.map(f,function(a){return a.id})).then(c.bind(function(a){c.a(f,
82
+ a.payload;this.wa&&!a.Vd&&(b=this.wa(b));if(b){b.event&&b.properties&&(b.properties=c.extend({},b.properties,{mp_sent_by_lib_version:"2.61.1"}));var d=l,g=a.id;if(g){if(5<(this.Q[g]||0))this.h("[dupe] item ID sent too many times, not sending",{item:a,M:f.length,xe:this.Q[g]}),d=C}else this.h("[dupe] found item with no ID",{item:a});d&&t.push(b)}i[a.id]=b},this);if(1>t.length)return this.sb=C,this.U(),w.resolve();var m=c.bind(function(){return this.ma.Yd(c.map(f,function(a){return a.id})).then(c.bind(function(a){c.a(f,
83
83
  c.bind(function(a){var b=a.id;b?(this.Q[b]=this.Q[b]||0,this.Q[b]++,5<this.Q[b]&&this.h("[dupe] item ID sent too many times",{item:a,M:f.length,xe:this.Q[b]})):this.h("[dupe] found item with no ID while removing",{item:a})},this));if(a){this.bb=0;return this.ac&&!e?(this.U(),w.resolve()):this.flush()}5<++this.bb?(this.h("Too many queue failures; disabling batching system."),this.qe()):this.U();return w.resolve()},this))},this),p=c.bind(function(e){this.sb=C;try{if(a.Lc)return this.ma.Ee(i);if(c.g(e)&&
84
84
  "timeout"===e.error&&(new Date).getTime()-d>=b)return this.h("Network timeout; retrying"),this.flush();var h;if(h=c.g(e)){var t;if(!(t=500<=e.Ga)){var q;if(!(q=429===e.Ga)){var p;if(p=0>=e.Ga){var n=j.navigator.onLine;p=!(c.e(n)||n)}q=p||"timeout"===e.error}t=q}h=t}if(h){var o=2*this.Ea;e.xc&&(o=1E3*parseInt(e.xc,10)||o);o=Math.min(6E5,o);this.h("Error; retry in "+o+" ms");this.yc(o);return w.resolve()}if(c.g(e)&&413===e.Ga){if(1<f.length){var s=Math.max(1,Math.floor(g/2));this.M=Math.min(this.M,
85
85
  s,f.length-1);this.h("413 response; reducing batch size to "+this.M);this.U();return w.resolve()}this.h("Single-event request too large; dropping",f);this.wc()}return m()}catch(v){this.h("Error handling API response",v),this.U()}},this),q={method:"POST",Pc:l,Bd:l,Ic:b};if(a.Lc)q.Ab="sendBeacon";ba.log("MIXPANEL REQUEST:",t);return this.ge(t,q).then(p)},this)).catch(c.bind(function(a){this.h("Error flushing request queue",a);this.U()},this))};F.prototype.h=function(a,b){ba.error.apply(ba.error,arguments);
@@ -103,10 +103,10 @@ a?l:C,this.remove(),this.save()};o.prototype.w=function(a,b){var d=this.ua(a),e=
103
103
  l}):"__mpa"===d?(c.a(e,function(a,b){b in f?f[b]+=a:(b in i||(i[b]=0),i[b]+=a)},this),this.D("$unset",e)):"__mpu"===d?(c.a(e,function(a,b){c.isArray(a)&&(b in m||(m[b]=[]),c.a(a,function(a){c.lb(m[b],a)||m[b].push(a)}))}),this.D("$unset",e)):"__mpr"===d?(p.push(e),this.D("$append",e)):"__mpap"===d&&(q.push(e),this.D("$unset",e));s.log("MIXPANEL PEOPLE REQUEST (QUEUED, PENDING IDENTIFY):");s.log(b);this.save()};o.prototype.D=function(a,b){var d=this.props[this.ua(a)];c.e(d)||c.a(b,function(b,e){"$append"===
104
104
  a||"$remove"===a?c.a(d,function(a){a[e]===b&&delete a[e]}):delete d[e]},this)};o.prototype.ja=function(a){return this.Ja(this.ua(a))};o.prototype.ua=function(a){if("$set"===a)return"__mps";if("$set_once"===a)return"__mpso";if("$unset"===a)return"__mpus";if("$add"===a)return"__mpa";if("$append"===a)return"__mpap";if("$remove"===a)return"__mpr";if("$union"===a)return"__mpu";s.error("Invalid queue:",a)};o.prototype.L=function(a,b){var d=this.ua(a),b=c.e(b)?{}:b;return this.props[d]||(this.props[d]=b)};
105
105
  o.prototype.le=function(a){var b=(new Date).getTime(),c=this.Ja("__timers")||{};c[a]=b;this.props.__timers=c;this.save()};o.prototype.Zd=function(a){var b=(this.Ja("__timers")||{})[a];c.e(b)||(delete this.props.__timers[a],this.save());return b};var Wb=["mixpanelRecordingEvents","mixpanelRecordingRegistry"];L.prototype.Lb=function(){return new w(function(a,b){var c=j.indexedDB.open("mixpanelBrowserDb",1);c.onerror=function(){b(c.error)};c.onsuccess=function(){a(c.result)};c.onupgradeneeded=function(a){var b=
106
- a.target.result;Wb.forEach(function(a){b.createObjectStore(a)})}})};L.prototype.A=function(){if(!j.indexedDB)return w.reject("indexedDB is not supported in this browser");if(!this.R)this.R=this.Lb();return this.R.then(function(a){return a instanceof j.IDBDatabase?w.resolve():w.reject(a)})};L.prototype.La=function(a,b){function c(d){return new w(function(c,j){var i=d.transaction(e,a);i.oncomplete=function(){c(i)};i.onabort=i.onerror=function(){j(i.error)};b(i.objectStore(e))})}var e=this.se;return this.R.then(c).catch(function(a){return"InvalidStateError"===
107
- a.name?(this.R=this.Lb(),this.R.then(c)):w.reject(a)}.bind(this))};L.prototype.setItem=function(a,b){return this.La("readwrite",function(c){c.put(b,a)})};L.prototype.getItem=function(a){var b;return this.La("readonly",function(c){b=c.get(a)}).then(function(){return b.result})};L.prototype.removeItem=function(a){return this.La("readwrite",function(b){b.Le(a)})};L.prototype.getAll=function(){var a;return this.La("readonly",function(b){a=b.getAll()}).then(function(){return a.result})};var ta,y,U=j.XMLHttpRequest&&
108
- "withCredentials"in new XMLHttpRequest,Na=!U&&-1===B.indexOf("MSIE")&&-1===B.indexOf("Mozilla"),sa=r;P.sendBeacon&&(sa=function(){return P.sendBeacon.apply(P,arguments)});var sb={track:"track/",engage:"engage/",groups:"groups/",record:"record/"},tb={api_host:"https://api-js.mixpanel.com",api_routes:sb,api_method:"POST",api_transport:"XHR",api_payload_format:"base64",app_host:"https://mixpanel.com",autocapture:C,cdn:"https://cdn.mxpnl.com",cross_site_cookie:C,cross_subdomain_cookie:l,error_reporter:X,
109
- persistence:"cookie",persistence_name:"",cookie_domain:"",cookie_name:"",loaded:X,mp_loader:r,track_marketing:l,track_pageview:C,skip_first_touch_marketing:C,store_google:l,stop_utm_persistence:C,save_referrer:l,test:C,verbose:C,img:C,debug:C,track_links_timeout:300,cookie_expiration:365,upgrade:C,disable_persistence:C,disable_cookie:C,secure_cookie:C,ip:l,opt_out_tracking_by_default:C,opt_out_persistence_by_default:C,opt_out_tracking_persistence_type:"localStorage",opt_out_tracking_cookie_prefix:r,
106
+ a.target.result;Wb.forEach(function(a){b.createObjectStore(a)})}})};L.prototype.A=function(){if(!j.indexedDB)return w.reject("indexedDB is not supported in this browser");if(!this.R)this.R=this.Lb();return this.R.then(function(a){return a instanceof j.IDBDatabase?w.resolve():w.reject(a)})};L.prototype.La=function(a,b){function c(d){return new w(function(c,j){var i=d.transaction(e,a);i.oncomplete=function(){c(i)};i.onabort=i.onerror=function(){j(i.error)};b(i.objectStore(e))})}var e=this.se;return this.R.then(c).catch(function(a){return a&&
107
+ "InvalidStateError"===a.name?(this.R=this.Lb(),this.R.then(c)):w.reject(a)}.bind(this))};L.prototype.setItem=function(a,b){return this.La("readwrite",function(c){c.put(b,a)})};L.prototype.getItem=function(a){var b;return this.La("readonly",function(c){b=c.get(a)}).then(function(){return b.result})};L.prototype.removeItem=function(a){return this.La("readwrite",function(b){b.Le(a)})};L.prototype.getAll=function(){var a;return this.La("readonly",function(b){a=b.getAll()}).then(function(){return a.result})};
108
+ var ta,y,U=j.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest,Na=!U&&-1===B.indexOf("MSIE")&&-1===B.indexOf("Mozilla"),sa=r;P.sendBeacon&&(sa=function(){return P.sendBeacon.apply(P,arguments)});var sb={track:"track/",engage:"engage/",groups:"groups/",record:"record/"},tb={api_host:"https://api-js.mixpanel.com",api_routes:sb,api_method:"POST",api_transport:"XHR",api_payload_format:"base64",app_host:"https://mixpanel.com",autocapture:C,cdn:"https://cdn.mxpnl.com",cross_site_cookie:C,cross_subdomain_cookie:l,
109
+ error_reporter:X,persistence:"cookie",persistence_name:"",cookie_domain:"",cookie_name:"",loaded:X,mp_loader:r,track_marketing:l,track_pageview:C,skip_first_touch_marketing:C,store_google:l,stop_utm_persistence:C,save_referrer:l,test:C,verbose:C,img:C,debug:C,track_links_timeout:300,cookie_expiration:365,upgrade:C,disable_persistence:C,disable_cookie:C,secure_cookie:C,ip:l,opt_out_tracking_by_default:C,opt_out_persistence_by_default:C,opt_out_tracking_persistence_type:"localStorage",opt_out_tracking_cookie_prefix:r,
110
110
  property_blacklist:[],xhr_headers:{},ignore_dnt:C,batch_requests:l,batch_size:50,batch_flush_interval_ms:5E3,batch_request_timeout_ms:9E4,batch_autostart:l,hooks:{},record_block_class:/^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$/,record_block_selector:"img, video",record_canvas:C,record_collect_fonts:C,record_idle_timeout_ms:18E5,record_mask_text_class:/^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$/,record_mask_text_selector:"*",record_max_ms:864E5,record_min_ms:0,record_sessions_percent:0,
111
111
  recorder_src:"https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js"},Ma=C;e.prototype.A=function(a,b,d){if(c.e(d))this.l("You must name your new library: init(token, config, name)");else if("mixpanel"===d)this.l("You must initialize the main mixpanel object right after you include the Mixpanel js snippet");else return a=ca(a,b,d),y[d]=a,a.va(),a};e.prototype.fa=function(a,b,d){b=b||{};this.__loaded=l;this.config={};var e={};"api_payload_format"in b||(b.api_host||tb.api_host).match(/\.mixpanel\.com/)&&
112
112
  (e.api_payload_format="json");this.Bc(c.extend({},tb,e,b,{name:d,token:a,callback_fn:("mixpanel"===d?d:"mixpanel."+d)+"._jsc"}));this._jsc=X;this.Qa=[];this.Ra=[];this.Pa=[];this.ca={disable_all_events:C,identify_called:C};this.C={};if(this.ba=this.c("batch_requests"))if(!c.localStorage.ia(l)||!U)this.ba=C,s.log("Turning off Mixpanel request-queueing; needs XHR and localStorage support"),c.a(this.bc(),function(a){s.log("Clearing batch queue "+a.na);c.localStorage.remove(a.na)});else if(this.Hd(),
@@ -4891,7 +4891,7 @@ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
4891
4891
 
4892
4892
  var Config = {
4893
4893
  DEBUG: false,
4894
- LIB_VERSION: '2.61.0'
4894
+ LIB_VERSION: '2.61.1'
4895
4895
  };
4896
4896
 
4897
4897
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -6754,7 +6754,7 @@ IDBStorageWrapper.prototype.makeTransaction = function (mode, storeCb) {
6754
6754
  return this.dbPromise
6755
6755
  .then(doTransaction)
6756
6756
  .catch(function (err) {
6757
- if (err['name'] === 'InvalidStateError') {
6757
+ if (err && err['name'] === 'InvalidStateError') {
6758
6758
  // try reopening the DB if the connection is closed
6759
6759
  this.dbPromise = this._openDb();
6760
6760
  return this.dbPromise.then(doTransaction);
@@ -8178,34 +8178,37 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
8178
8178
  blockSelector = undefined;
8179
8179
  }
8180
8180
 
8181
- this._stopRecording = this._rrwebRecord({
8182
- 'emit': addOptOutCheckMixpanelLib(function (ev) {
8183
- if (isUserEvent(ev)) {
8184
- if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8185
- // start flushing again after user activity
8186
- this.batcher.start();
8181
+ try {
8182
+ this._stopRecording = this._rrwebRecord({
8183
+ 'emit': function (ev) {
8184
+ if (isUserEvent(ev)) {
8185
+ if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8186
+ // start flushing again after user activity
8187
+ this.batcher.start();
8188
+ }
8189
+ resetIdleTimeout();
8187
8190
  }
8188
- resetIdleTimeout();
8191
+ // promise only used to await during tests
8192
+ this.__enqueuePromise = this.batcher.enqueue(ev);
8193
+ }.bind(this),
8194
+ 'blockClass': this.getConfig('record_block_class'),
8195
+ 'blockSelector': blockSelector,
8196
+ 'collectFonts': this.getConfig('record_collect_fonts'),
8197
+ 'dataURLOptions': { // canvas image options (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)
8198
+ 'type': 'image/webp',
8199
+ 'quality': 0.6
8200
+ },
8201
+ 'maskAllInputs': true,
8202
+ 'maskTextClass': this.getConfig('record_mask_text_class'),
8203
+ 'maskTextSelector': this.getConfig('record_mask_text_selector'),
8204
+ 'recordCanvas': this.getConfig('record_canvas'),
8205
+ 'sampling': {
8206
+ 'canvas': 15
8189
8207
  }
8190
-
8191
- // promise only used to await during tests
8192
- this.__enqueuePromise = this.batcher.enqueue(ev);
8193
- }.bind(this)),
8194
- 'blockClass': this.getConfig('record_block_class'),
8195
- 'blockSelector': blockSelector,
8196
- 'collectFonts': this.getConfig('record_collect_fonts'),
8197
- 'dataURLOptions': { // canvas image options (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)
8198
- 'type': 'image/webp',
8199
- 'quality': 0.6
8200
- },
8201
- 'maskAllInputs': true,
8202
- 'maskTextClass': this.getConfig('record_mask_text_class'),
8203
- 'maskTextSelector': this.getConfig('record_mask_text_selector'),
8204
- 'recordCanvas': this.getConfig('record_canvas'),
8205
- 'sampling': {
8206
- 'canvas': 15
8207
- }
8208
- });
8208
+ });
8209
+ } catch (err) {
8210
+ this.reportError('Unexpected error when starting rrweb recording.', err);
8211
+ }
8209
8212
 
8210
8213
  if (typeof this._stopRecording !== 'function') {
8211
8214
  this.reportError('rrweb failed to start, skipping this recording.');
@@ -8249,12 +8252,21 @@ SessionRecording.prototype.isRrwebStopped = function () {
8249
8252
  return this._stopRecording === null;
8250
8253
  };
8251
8254
 
8255
+
8252
8256
  /**
8253
8257
  * Flushes the current batch of events to the server, but passes an opt-out callback to make sure
8254
8258
  * we stop recording and dump any queued events if the user has opted out.
8255
8259
  */
8256
8260
  SessionRecording.prototype.flushEventsWithOptOut = function (data, options, cb) {
8257
- this._flushEvents(data, options, cb, this._onOptOut.bind(this));
8261
+ var onOptOut = function (code) {
8262
+ // addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
8263
+ if (code === 0) {
8264
+ this.stopRecording();
8265
+ cb({error: 'Tracking has been opted out, stopping recording.'});
8266
+ }
8267
+ }.bind(this);
8268
+
8269
+ this._flushEvents(data, options, cb, onOptOut);
8258
8270
  };
8259
8271
 
8260
8272
  /**
@@ -8304,13 +8316,6 @@ SessionRecording.deserialize = function (serializedRecording, options) {
8304
8316
  return recording;
8305
8317
  };
8306
8318
 
8307
- SessionRecording.prototype._onOptOut = function (code) {
8308
- // addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
8309
- if (code === 0) {
8310
- this.stopRecording();
8311
- }
8312
- };
8313
-
8314
8319
  SessionRecording.prototype._sendRequest = function(currentReplayId, reqParams, reqBody, callback) {
8315
8320
  var onSuccess = function (response, responseBody) {
8316
8321
  // Update batch specific props only if the request was successful to guarantee ordering.
@@ -8353,17 +8358,32 @@ SessionRecording.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da
8353
8358
 
8354
8359
  if (numEvents > 0) {
8355
8360
  var replayId = this.replayId;
8361
+
8356
8362
  // each rrweb event has a timestamp - leverage those to get time properties
8357
- var batchStartTime = data[0].timestamp;
8358
- if (this.seqNo === 0 || !this.replayStartTime) {
8359
- // extra safety net so that we don't send a null replay start time
8360
- if (this.seqNo !== 0) {
8361
- this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.');
8363
+ var batchStartTime = Infinity;
8364
+ var batchEndTime = -Infinity;
8365
+ var hasFullSnapshot = false;
8366
+ for (var i = 0; i < numEvents; i++) {
8367
+ batchStartTime = Math.min(batchStartTime, data[i].timestamp);
8368
+ batchEndTime = Math.max(batchEndTime, data[i].timestamp);
8369
+ if (data[i].type === EventType.FullSnapshot) {
8370
+ hasFullSnapshot = true;
8362
8371
  }
8372
+ }
8363
8373
 
8374
+ if (this.seqNo === 0) {
8375
+ if (!hasFullSnapshot) {
8376
+ callback({error: 'First batch does not contain a full snapshot. Aborting recording.'});
8377
+ this.stopRecording(true);
8378
+ return;
8379
+ }
8380
+ this.replayStartTime = batchStartTime;
8381
+ } else if (!this.replayStartTime) {
8382
+ this.reportError('Replay start time not set but seqNo is not 0. Using current batch start time as a fallback.');
8364
8383
  this.replayStartTime = batchStartTime;
8365
8384
  }
8366
- var replayLengthMs = data[numEvents - 1].timestamp - this.replayStartTime;
8385
+
8386
+ var replayLengthMs = batchEndTime - this.replayStartTime;
8367
8387
 
8368
8388
  var reqParams = {
8369
8389
  '$current_url': this.batchStartUrl,