mixpanel-browser 2.61.2 → 2.62.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.62.0** (26 Mar 2025)
2
+ - Replace UUID generator with UUIDv4 (using native API when available)
3
+ - Consistently use native JSON serialization when available
4
+ - Fix for session recording idle timeout race condition
5
+
1
6
  **2.61.2** (14 Mar 2025)
2
7
  - Revert 10ms throttle on enqueueing events to improve tracking reliability on page unload
3
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  var Config = {
4
4
  DEBUG: false,
5
- LIB_VERSION: '2.61.2'
5
+ LIB_VERSION: '2.62.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
@@ -12,6 +12,7 @@ if (typeof(window) === 'undefined') {
12
12
  hostname: ''
13
13
  };
14
14
  win = {
15
+ crypto: {randomUUID: function() {throw Error('unsupported');}},
15
16
  navigator: { userAgent: '', onLine: true },
16
17
  document: {
17
18
  createElement: function() { return {}; },
@@ -1225,71 +1226,27 @@ _.utf8Encode = function(string) {
1225
1226
  return utftext;
1226
1227
  };
1227
1228
 
1228
- _.UUID = (function() {
1229
-
1230
- // Time-based entropy
1231
- var T = function() {
1232
- var time = 1 * new Date(); // cross-browser version of Date.now()
1233
- var ticks;
1234
- if (win.performance && win.performance.now) {
1235
- ticks = win.performance.now();
1236
- } else {
1237
- // fall back to busy loop
1238
- ticks = 0;
1239
-
1240
- // this while loop figures how many browser ticks go by
1241
- // before 1*new Date() returns a new number, ie the amount
1242
- // of ticks that go by per millisecond
1243
- while (time == 1 * new Date()) {
1244
- ticks++;
1245
- }
1246
- }
1247
- return time.toString(16) + Math.floor(ticks).toString(16);
1248
- };
1249
-
1250
- // Math.Random entropy
1251
- var R = function() {
1252
- return Math.random().toString(16).replace('.', '');
1253
- };
1254
-
1255
- // User agent entropy
1256
- // This function takes the user agent string, and then xors
1257
- // together each sequence of 8 bytes. This produces a final
1258
- // sequence of 8 bytes which it returns as hex.
1259
- var UA = function() {
1260
- var ua = userAgent,
1261
- i, ch, buffer = [],
1262
- ret = 0;
1263
-
1264
- function xor(result, byte_array) {
1265
- var j, tmp = 0;
1266
- for (j = 0; j < byte_array.length; j++) {
1267
- tmp |= (buffer[j] << j * 8);
1268
- }
1269
- return result ^ tmp;
1270
- }
1271
-
1272
- for (i = 0; i < ua.length; i++) {
1273
- ch = ua.charCodeAt(i);
1274
- buffer.unshift(ch & 0xFF);
1275
- if (buffer.length >= 4) {
1276
- ret = xor(ret, buffer);
1277
- buffer = [];
1278
- }
1279
- }
1280
-
1281
- if (buffer.length > 0) {
1282
- ret = xor(ret, buffer);
1229
+ _.UUID = function() {
1230
+ try {
1231
+ // use native Crypto API when available
1232
+ return win['crypto']['randomUUID']();
1233
+ } catch (err) {
1234
+ // fall back to generating our own UUID
1235
+ // based on https://gist.github.com/scwood/3bff42cc005cc20ab7ec98f0d8e1d59d
1236
+ var uuid = new Array(36);
1237
+ for (var i = 0; i < 36; i++) {
1238
+ uuid[i] = Math.floor(Math.random() * 16);
1283
1239
  }
1240
+ uuid[14] = 4; // set bits 12-15 of time-high-and-version to 0100
1241
+ uuid[19] = uuid[19] &= ~(1 << 2); // set bit 6 of clock-seq-and-reserved to zero
1242
+ uuid[19] = uuid[19] |= (1 << 3); // set bit 7 of clock-seq-and-reserved to one
1243
+ uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
1284
1244
 
1285
- return ret.toString(16);
1286
- };
1287
-
1288
- return function() {
1289
- var se = (screen.height * screen.width).toString(16);
1290
- return (T() + '-' + R() + '-' + UA() + '-' + se + '-' + T());
1291
- };
1292
- })();
1245
+ return _.map(uuid, function(x) {
1246
+ return x.toString(16);
1247
+ }).join('');
1248
+ }
1249
+ };
1293
1250
 
1294
1251
  // _.isBlockedUA()
1295
1252
  // This is to block various web spiders from executing our JS and
@@ -5231,7 +5188,7 @@ MixpanelPersistence.prototype.save = function() {
5231
5188
 
5232
5189
  this.storage.set(
5233
5190
  this.name,
5234
- _.JSONEncode(this['props']),
5191
+ JSONStringify(this['props']),
5235
5192
  this.expire_days,
5236
5193
  this.cross_subdomain,
5237
5194
  this.secure,
@@ -6575,7 +6532,7 @@ MixpanelLib.prototype.disable = function(events) {
6575
6532
  };
6576
6533
 
6577
6534
  MixpanelLib.prototype._encode_data_for_request = function(data) {
6578
- var encoded_data = _.JSONEncode(data);
6535
+ var encoded_data = JSONStringify(data);
6579
6536
  if (this.get_config('api_payload_format') === PAYLOAD_TYPE_BASE64) {
6580
6537
  encoded_data = _.base64Encode(encoded_data);
6581
6538
  }
@@ -8,6 +8,7 @@
8
8
  hostname: ''
9
9
  };
10
10
  win = {
11
+ crypto: {randomUUID: function() {throw Error('unsupported');}},
11
12
  navigator: { userAgent: '', onLine: true },
12
13
  document: {
13
14
  createElement: function() { return {}; },
@@ -4894,7 +4895,7 @@
4894
4895
 
4895
4896
  var Config = {
4896
4897
  DEBUG: false,
4897
- LIB_VERSION: '2.61.2'
4898
+ LIB_VERSION: '2.62.0'
4898
4899
  };
4899
4900
 
4900
4901
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -5683,71 +5684,27 @@
5683
5684
  return utftext;
5684
5685
  };
5685
5686
 
5686
- _.UUID = (function() {
5687
-
5688
- // Time-based entropy
5689
- var T = function() {
5690
- var time = 1 * new Date(); // cross-browser version of Date.now()
5691
- var ticks;
5692
- if (win.performance && win.performance.now) {
5693
- ticks = win.performance.now();
5694
- } else {
5695
- // fall back to busy loop
5696
- ticks = 0;
5697
-
5698
- // this while loop figures how many browser ticks go by
5699
- // before 1*new Date() returns a new number, ie the amount
5700
- // of ticks that go by per millisecond
5701
- while (time == 1 * new Date()) {
5702
- ticks++;
5703
- }
5704
- }
5705
- return time.toString(16) + Math.floor(ticks).toString(16);
5706
- };
5707
-
5708
- // Math.Random entropy
5709
- var R = function() {
5710
- return Math.random().toString(16).replace('.', '');
5711
- };
5712
-
5713
- // User agent entropy
5714
- // This function takes the user agent string, and then xors
5715
- // together each sequence of 8 bytes. This produces a final
5716
- // sequence of 8 bytes which it returns as hex.
5717
- var UA = function() {
5718
- var ua = userAgent,
5719
- i, ch, buffer = [],
5720
- ret = 0;
5721
-
5722
- function xor(result, byte_array) {
5723
- var j, tmp = 0;
5724
- for (j = 0; j < byte_array.length; j++) {
5725
- tmp |= (buffer[j] << j * 8);
5726
- }
5727
- return result ^ tmp;
5728
- }
5729
-
5730
- for (i = 0; i < ua.length; i++) {
5731
- ch = ua.charCodeAt(i);
5732
- buffer.unshift(ch & 0xFF);
5733
- if (buffer.length >= 4) {
5734
- ret = xor(ret, buffer);
5735
- buffer = [];
5736
- }
5737
- }
5738
-
5739
- if (buffer.length > 0) {
5740
- ret = xor(ret, buffer);
5687
+ _.UUID = function() {
5688
+ try {
5689
+ // use native Crypto API when available
5690
+ return win['crypto']['randomUUID']();
5691
+ } catch (err) {
5692
+ // fall back to generating our own UUID
5693
+ // based on https://gist.github.com/scwood/3bff42cc005cc20ab7ec98f0d8e1d59d
5694
+ var uuid = new Array(36);
5695
+ for (var i = 0; i < 36; i++) {
5696
+ uuid[i] = Math.floor(Math.random() * 16);
5741
5697
  }
5742
-
5743
- return ret.toString(16);
5744
- };
5745
-
5746
- return function() {
5747
- var se = (screen.height * screen.width).toString(16);
5748
- return (T() + '-' + R() + '-' + UA() + '-' + se + '-' + T());
5749
- };
5750
- })();
5698
+ uuid[14] = 4; // set bits 12-15 of time-high-and-version to 0100
5699
+ uuid[19] = uuid[19] &= ~(1 << 2); // set bit 6 of clock-seq-and-reserved to zero
5700
+ uuid[19] = uuid[19] |= (1 << 3); // set bit 7 of clock-seq-and-reserved to one
5701
+ uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
5702
+
5703
+ return _.map(uuid, function(x) {
5704
+ return x.toString(16);
5705
+ }).join('');
5706
+ }
5707
+ };
5751
5708
 
5752
5709
  // _.isBlockedUA()
5753
5710
  // This is to block various web spiders from executing our JS and
@@ -7991,6 +7948,7 @@
7991
7948
  this.idleTimeoutId = setTimeout(this._onIdleTimeout, idleTimeoutMs);
7992
7949
  this.idleExpires = new Date().getTime() + idleTimeoutMs;
7993
7950
  }.bind(this);
7951
+ resetIdleTimeout();
7994
7952
 
7995
7953
  var blockSelector = this.getConfig('record_block_selector');
7996
7954
  if (blockSelector === '' || blockSelector === null) {
@@ -8000,6 +7958,10 @@
8000
7958
  try {
8001
7959
  this._stopRecording = this._rrwebRecord({
8002
7960
  'emit': function (ev) {
7961
+ if (this.idleExpires && this.idleExpires < ev.timestamp) {
7962
+ this._onIdleTimeout();
7963
+ return;
7964
+ }
8003
7965
  if (isUserEvent(ev)) {
8004
7966
  if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
8005
7967
  // start flushing again after user activity
@@ -8036,8 +7998,6 @@
8036
7998
  return;
8037
7999
  }
8038
8000
 
8039
- resetIdleTimeout();
8040
-
8041
8001
  var maxTimeoutMs = this.maxExpires - new Date().getTime();
8042
8002
  this.maxTimeoutId = setTimeout(this._onMaxLengthReached.bind(this), maxTimeoutMs);
8043
8003
  };
@@ -8216,7 +8176,7 @@
8216
8176
  'replay_start_url': this.replayStartUrl,
8217
8177
  'seq': this.seqNo
8218
8178
  };
8219
- var eventsJson = _.JSONEncode(data);
8179
+ var eventsJson = JSON.stringify(data);
8220
8180
 
8221
8181
  // send ID management props if they exist
8222
8182
  var deviceId = this._mixpanel.get_property('$device_id');