mixpanel-browser 2.76.0 → 2.78.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/.claude/settings.local.json +3 -1
- package/.github/dependabot.yml +8 -0
- package/.github/workflows/integration-tests.yml +2 -2
- package/.github/workflows/unit-tests.yml +2 -2
- package/CHANGELOG.md +8 -0
- package/dist/async-modules/mixpanel-recorder-BjSlYaNJ.min.js +2 -0
- package/dist/async-modules/mixpanel-recorder-BjSlYaNJ.min.js.map +1 -0
- package/dist/async-modules/{mixpanel-recorder-bIS4LMGd.js → mixpanel-recorder-zMBXIyeG.js} +84 -10
- package/dist/async-modules/{mixpanel-targeting-VOeN7RWY.min.js → mixpanel-targeting-BSHal4N9.min.js} +2 -2
- package/dist/async-modules/{mixpanel-targeting-VOeN7RWY.min.js.map → mixpanel-targeting-BSHal4N9.min.js.map} +1 -1
- package/dist/async-modules/{mixpanel-targeting-BcAPS-Mz.js → mixpanel-targeting-UHf4eBfC.js} +1 -1
- package/dist/mixpanel-core.cjs.d.ts +3 -1
- package/dist/mixpanel-core.cjs.js +292 -130
- package/dist/mixpanel-recorder.js +84 -10
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-targeting.js +1 -1
- package/dist/mixpanel-targeting.min.js +1 -1
- package/dist/mixpanel-targeting.min.js.map +1 -1
- package/dist/mixpanel-with-async-modules.cjs.d.ts +3 -1
- package/dist/mixpanel-with-async-modules.cjs.js +294 -132
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +3 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +294 -132
- package/dist/mixpanel-with-recorder.d.ts +3 -1
- package/dist/mixpanel-with-recorder.js +381 -168
- package/dist/mixpanel-with-recorder.min.d.ts +3 -1
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +3 -1
- package/dist/mixpanel.amd.js +381 -168
- package/dist/mixpanel.cjs.d.ts +3 -1
- package/dist/mixpanel.cjs.js +381 -168
- package/dist/mixpanel.globals.js +294 -132
- package/dist/mixpanel.min.js +191 -186
- package/dist/mixpanel.module.d.ts +3 -1
- package/dist/mixpanel.module.js +381 -168
- package/dist/mixpanel.umd.d.ts +3 -1
- package/dist/mixpanel.umd.js +381 -168
- package/dist/rrweb-bundled.js +61 -9
- package/dist/rrweb-compiled.js +56 -9
- package/package.json +6 -5
- package/src/config.js +1 -1
- package/src/flags/CLAUDE.md +24 -0
- package/src/flags/index.js +109 -80
- package/src/index.d.ts +3 -1
- package/src/mixpanel-core.js +4 -2
- package/src/recorder/session-recording.js +5 -1
- package/src/recorder/utils.js +27 -1
- package/src/recorder-manager.js +110 -2
- package/testServer.js +16 -1
- package/dist/async-modules/mixpanel-recorder-hFoTniVR.min.js +0 -2
- package/dist/async-modules/mixpanel-recorder-hFoTniVR.min.js.map +0 -1
- /package/src/loaders/{loader-module-with-async-recorder.d.ts → loader-module-with-async-modules.d.ts} +0 -0
package/dist/mixpanel.cjs.js
CHANGED
|
@@ -27,7 +27,7 @@ if (typeof(window) === 'undefined') {
|
|
|
27
27
|
|
|
28
28
|
var Config = {
|
|
29
29
|
DEBUG: false,
|
|
30
|
-
LIB_VERSION: '2.
|
|
30
|
+
LIB_VERSION: '2.78.0'
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
// Window global names for async modules
|
|
@@ -10735,13 +10735,7 @@ var MutationBuffer = /*#__PURE__*/ function() {
|
|
|
10735
10735
|
};
|
|
10736
10736
|
while(_this.mapRemoves.length){
|
|
10737
10737
|
var removedNode = _this.mapRemoves.shift();
|
|
10738
|
-
|
|
10739
|
-
try {
|
|
10740
|
-
_this.iframeManager.removeIframe(removedNode);
|
|
10741
|
-
} catch (e2) {}
|
|
10742
|
-
} else {
|
|
10743
|
-
_this.stylesheetManager.cleanupStylesheetsForRemovedNode(removedNode);
|
|
10744
|
-
}
|
|
10738
|
+
_this.cleanupRemovedNode(removedNode);
|
|
10745
10739
|
_this.mirror.removeNodeFromMap(removedNode);
|
|
10746
10740
|
}
|
|
10747
10741
|
for(var _iterator = _create_for_of_iterator_helper_loose(_this.movedSet), _step; !(_step = _iterator()).done;){
|
|
@@ -11061,6 +11055,20 @@ var MutationBuffer = /*#__PURE__*/ function() {
|
|
|
11061
11055
|
}
|
|
11062
11056
|
}
|
|
11063
11057
|
});
|
|
11058
|
+
__publicField$1(this, "cleanupRemovedNode", function(node2) {
|
|
11059
|
+
if (node2.nodeName === "IFRAME") {
|
|
11060
|
+
try {
|
|
11061
|
+
_this.iframeManager.removeIframe(node2);
|
|
11062
|
+
} catch (e2) {}
|
|
11063
|
+
} else {
|
|
11064
|
+
try {
|
|
11065
|
+
_this.stylesheetManager.cleanupStylesheetsForRemovedNode(node2);
|
|
11066
|
+
} catch (e2) {}
|
|
11067
|
+
}
|
|
11068
|
+
node2.childNodes.forEach(function(child) {
|
|
11069
|
+
_this.cleanupRemovedNode(child);
|
|
11070
|
+
});
|
|
11071
|
+
});
|
|
11064
11072
|
}
|
|
11065
11073
|
var _proto = MutationBuffer.prototype;
|
|
11066
11074
|
_proto.init = function init(options) {
|
|
@@ -13288,6 +13296,31 @@ var ProcessedNodeManager = /*#__PURE__*/ function() {
|
|
|
13288
13296
|
_proto.destroy = function destroy() {};
|
|
13289
13297
|
return ProcessedNodeManager;
|
|
13290
13298
|
}();
|
|
13299
|
+
function toOrigin(url) {
|
|
13300
|
+
try {
|
|
13301
|
+
var origin = new URL(url).origin;
|
|
13302
|
+
return origin !== "null" ? origin : null;
|
|
13303
|
+
} catch (e) {
|
|
13304
|
+
return null;
|
|
13305
|
+
}
|
|
13306
|
+
}
|
|
13307
|
+
function buildAllowedOriginSet(origins) {
|
|
13308
|
+
if (!Array.isArray(origins) || origins.length === 0) {
|
|
13309
|
+
throw new Error("[rrweb] allowedIframeOrigins must be a non-empty array of origin strings.");
|
|
13310
|
+
}
|
|
13311
|
+
var set = /* @__PURE__ */ new Set();
|
|
13312
|
+
for(var i2 = 0; i2 < origins.length; i2++){
|
|
13313
|
+
var entry = origins[i2];
|
|
13314
|
+
if (typeof entry !== "string") {
|
|
13315
|
+
throw new Error("[rrweb] allowedIframeOrigins[" + i2 + "] must be a string, got " + (typeof entry === "undefined" ? "undefined" : _type_of(entry)) + ".");
|
|
13316
|
+
}
|
|
13317
|
+
var origin = toOrigin(entry);
|
|
13318
|
+
if (origin) {
|
|
13319
|
+
set.add(origin);
|
|
13320
|
+
}
|
|
13321
|
+
}
|
|
13322
|
+
return Object.freeze(set);
|
|
13323
|
+
}
|
|
13291
13324
|
var wrappedEmit;
|
|
13292
13325
|
var takeFullSnapshot$1;
|
|
13293
13326
|
var canvasManager;
|
|
@@ -13309,10 +13342,17 @@ try {
|
|
|
13309
13342
|
var mirror = createMirror$2();
|
|
13310
13343
|
function record(options) {
|
|
13311
13344
|
if (options === void 0) options = {};
|
|
13312
|
-
var emit = options.emit, checkoutEveryNms = options.checkoutEveryNms, checkoutEveryNth = options.checkoutEveryNth, _options_blockClass = options.blockClass, blockClass = _options_blockClass === void 0 ? "rr-block" : _options_blockClass, _options_blockSelector = options.blockSelector, blockSelector = _options_blockSelector === void 0 ? null : _options_blockSelector, _options_ignoreClass = options.ignoreClass, ignoreClass = _options_ignoreClass === void 0 ? "rr-ignore" : _options_ignoreClass, _options_ignoreSelector = options.ignoreSelector, ignoreSelector = _options_ignoreSelector === void 0 ? null : _options_ignoreSelector, _options_maskTextClass = options.maskTextClass, maskTextClass = _options_maskTextClass === void 0 ? "rr-mask" : _options_maskTextClass, _options_maskTextSelector = options.maskTextSelector, maskTextSelector = _options_maskTextSelector === void 0 ? null : _options_maskTextSelector, _options_inlineStylesheet = options.inlineStylesheet, inlineStylesheet = _options_inlineStylesheet === void 0 ? true : _options_inlineStylesheet, maskAllInputs = options.maskAllInputs, _maskInputOptions = options.maskInputOptions, _slimDOMOptions = options.slimDOMOptions, maskInputFn = options.maskInputFn, maskTextFn = options.maskTextFn, hooks = options.hooks, packFn = options.packFn, _options_sampling = options.sampling, sampling = _options_sampling === void 0 ? {} : _options_sampling, _options_dataURLOptions = options.dataURLOptions, dataURLOptions = _options_dataURLOptions === void 0 ? {} : _options_dataURLOptions, mousemoveWait = options.mousemoveWait, _options_recordDOM = options.recordDOM, recordDOM = _options_recordDOM === void 0 ? true : _options_recordDOM, _options_recordCanvas = options.recordCanvas, recordCanvas = _options_recordCanvas === void 0 ? false : _options_recordCanvas, _options_recordCrossOriginIframes = options.recordCrossOriginIframes, recordCrossOriginIframes = _options_recordCrossOriginIframes === void 0 ? false : _options_recordCrossOriginIframes, _options_recordAfter = options.recordAfter, recordAfter = _options_recordAfter === void 0 ? options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load" : _options_recordAfter, _options_userTriggeredOnInput = options.userTriggeredOnInput, userTriggeredOnInput = _options_userTriggeredOnInput === void 0 ? false : _options_userTriggeredOnInput, _options_collectFonts = options.collectFonts, collectFonts = _options_collectFonts === void 0 ? false : _options_collectFonts, _options_inlineImages = options.inlineImages, inlineImages = _options_inlineImages === void 0 ? false : _options_inlineImages, plugins = options.plugins, _options_keepIframeSrcFn = options.keepIframeSrcFn, keepIframeSrcFn = _options_keepIframeSrcFn === void 0 ? function() {
|
|
13345
|
+
var emit = options.emit, checkoutEveryNms = options.checkoutEveryNms, checkoutEveryNth = options.checkoutEveryNth, _options_blockClass = options.blockClass, blockClass = _options_blockClass === void 0 ? "rr-block" : _options_blockClass, _options_blockSelector = options.blockSelector, blockSelector = _options_blockSelector === void 0 ? null : _options_blockSelector, _options_ignoreClass = options.ignoreClass, ignoreClass = _options_ignoreClass === void 0 ? "rr-ignore" : _options_ignoreClass, _options_ignoreSelector = options.ignoreSelector, ignoreSelector = _options_ignoreSelector === void 0 ? null : _options_ignoreSelector, _options_maskTextClass = options.maskTextClass, maskTextClass = _options_maskTextClass === void 0 ? "rr-mask" : _options_maskTextClass, _options_maskTextSelector = options.maskTextSelector, maskTextSelector = _options_maskTextSelector === void 0 ? null : _options_maskTextSelector, _options_inlineStylesheet = options.inlineStylesheet, inlineStylesheet = _options_inlineStylesheet === void 0 ? true : _options_inlineStylesheet, maskAllInputs = options.maskAllInputs, _maskInputOptions = options.maskInputOptions, _slimDOMOptions = options.slimDOMOptions, maskInputFn = options.maskInputFn, maskTextFn = options.maskTextFn, hooks = options.hooks, packFn = options.packFn, _options_sampling = options.sampling, sampling = _options_sampling === void 0 ? {} : _options_sampling, _options_dataURLOptions = options.dataURLOptions, dataURLOptions = _options_dataURLOptions === void 0 ? {} : _options_dataURLOptions, mousemoveWait = options.mousemoveWait, _options_recordDOM = options.recordDOM, recordDOM = _options_recordDOM === void 0 ? true : _options_recordDOM, _options_recordCanvas = options.recordCanvas, recordCanvas = _options_recordCanvas === void 0 ? false : _options_recordCanvas, _options_recordCrossOriginIframes = options.recordCrossOriginIframes, recordCrossOriginIframes = _options_recordCrossOriginIframes === void 0 ? false : _options_recordCrossOriginIframes, allowedIframeOrigins = options.allowedIframeOrigins, _options_recordAfter = options.recordAfter, recordAfter = _options_recordAfter === void 0 ? options.recordAfter === "DOMContentLoaded" ? options.recordAfter : "load" : _options_recordAfter, _options_userTriggeredOnInput = options.userTriggeredOnInput, userTriggeredOnInput = _options_userTriggeredOnInput === void 0 ? false : _options_userTriggeredOnInput, _options_collectFonts = options.collectFonts, collectFonts = _options_collectFonts === void 0 ? false : _options_collectFonts, _options_inlineImages = options.inlineImages, inlineImages = _options_inlineImages === void 0 ? false : _options_inlineImages, plugins = options.plugins, _options_keepIframeSrcFn = options.keepIframeSrcFn, keepIframeSrcFn = _options_keepIframeSrcFn === void 0 ? function() {
|
|
13313
13346
|
return false;
|
|
13314
13347
|
} : _options_keepIframeSrcFn, _options_ignoreCSSAttributes = options.ignoreCSSAttributes, ignoreCSSAttributes = _options_ignoreCSSAttributes === void 0 ? /* @__PURE__ */ new Set([]) : _options_ignoreCSSAttributes, errorHandler2 = options.errorHandler;
|
|
13315
13348
|
registerErrorHandler(errorHandler2);
|
|
13349
|
+
var validatedOrigins;
|
|
13350
|
+
if (recordCrossOriginIframes && allowedIframeOrigins && allowedIframeOrigins.length > 0) {
|
|
13351
|
+
validatedOrigins = buildAllowedOriginSet(allowedIframeOrigins);
|
|
13352
|
+
if (validatedOrigins.size === 0) {
|
|
13353
|
+
validatedOrigins = void 0;
|
|
13354
|
+
}
|
|
13355
|
+
}
|
|
13316
13356
|
var inEmittingFrame = recordCrossOriginIframes ? window.parent === window : true;
|
|
13317
13357
|
var passEmitsToParent = false;
|
|
13318
13358
|
if (!inEmittingFrame) {
|
|
@@ -13404,7 +13444,14 @@ function record(options) {
|
|
|
13404
13444
|
origin: window.location.origin,
|
|
13405
13445
|
isCheckout: isCheckout
|
|
13406
13446
|
};
|
|
13407
|
-
|
|
13447
|
+
if (validatedOrigins) {
|
|
13448
|
+
for(var _iterator = _create_for_of_iterator_helper_loose(validatedOrigins), _step; !(_step = _iterator()).done;){
|
|
13449
|
+
var targetOrigin = _step.value;
|
|
13450
|
+
window.parent.postMessage(message, targetOrigin);
|
|
13451
|
+
}
|
|
13452
|
+
} else {
|
|
13453
|
+
window.parent.postMessage(message, "*");
|
|
13454
|
+
}
|
|
13408
13455
|
}
|
|
13409
13456
|
if (e2.type === EventType.FullSnapshot) {
|
|
13410
13457
|
lastFullSnapshotEvent = e2;
|
|
@@ -21188,7 +21235,7 @@ function _addOptOutCheck(method, getConfigValue) {
|
|
|
21188
21235
|
};
|
|
21189
21236
|
}
|
|
21190
21237
|
|
|
21191
|
-
var logger$
|
|
21238
|
+
var logger$8 = console_with_prefix('lock');
|
|
21192
21239
|
|
|
21193
21240
|
/**
|
|
21194
21241
|
* SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
|
|
@@ -21240,7 +21287,7 @@ SharedLock.prototype.withLock = function(lockedCB, pid) {
|
|
|
21240
21287
|
|
|
21241
21288
|
var delay = function(cb) {
|
|
21242
21289
|
if (new Date().getTime() - startTime > timeoutMS) {
|
|
21243
|
-
logger$
|
|
21290
|
+
logger$8.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
|
|
21244
21291
|
storage.removeItem(keyZ);
|
|
21245
21292
|
storage.removeItem(keyY);
|
|
21246
21293
|
loop();
|
|
@@ -21387,7 +21434,7 @@ LocalStorageWrapper.prototype.removeItem = function (key) {
|
|
|
21387
21434
|
}, this));
|
|
21388
21435
|
};
|
|
21389
21436
|
|
|
21390
|
-
var logger$
|
|
21437
|
+
var logger$7 = console_with_prefix('batch');
|
|
21391
21438
|
|
|
21392
21439
|
/**
|
|
21393
21440
|
* RequestQueue: queue for batching API requests with localStorage backup for retries.
|
|
@@ -21416,7 +21463,7 @@ var RequestQueue = function (storageKey, options) {
|
|
|
21416
21463
|
timeoutMS: options.sharedLockTimeoutMS,
|
|
21417
21464
|
});
|
|
21418
21465
|
}
|
|
21419
|
-
this.reportError = options.errorReporter || _.bind(logger$
|
|
21466
|
+
this.reportError = options.errorReporter || _.bind(logger$7.error, logger$7);
|
|
21420
21467
|
|
|
21421
21468
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
21422
21469
|
|
|
@@ -21749,7 +21796,7 @@ RequestQueue.prototype.clear = function () {
|
|
|
21749
21796
|
// maximum interval between request retries after exponential backoff
|
|
21750
21797
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
21751
21798
|
|
|
21752
|
-
var logger$
|
|
21799
|
+
var logger$6 = console_with_prefix('batch');
|
|
21753
21800
|
|
|
21754
21801
|
/**
|
|
21755
21802
|
* RequestBatcher: manages the queueing, flushing, retry etc of requests of one
|
|
@@ -21877,7 +21924,7 @@ RequestBatcher.prototype.sendRequestPromise = function(data, options) {
|
|
|
21877
21924
|
*/
|
|
21878
21925
|
RequestBatcher.prototype.flush = function(options) {
|
|
21879
21926
|
if (this.requestInProgress) {
|
|
21880
|
-
logger$
|
|
21927
|
+
logger$6.log('Flush: Request already in progress');
|
|
21881
21928
|
return PromisePolyfill.resolve();
|
|
21882
21929
|
}
|
|
21883
21930
|
|
|
@@ -22054,7 +22101,7 @@ RequestBatcher.prototype.flush = function(options) {
|
|
|
22054
22101
|
if (options.unloading) {
|
|
22055
22102
|
requestOptions.transport = 'sendBeacon';
|
|
22056
22103
|
}
|
|
22057
|
-
logger$
|
|
22104
|
+
logger$6.log('MIXPANEL REQUEST:', dataForRequest);
|
|
22058
22105
|
return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
|
|
22059
22106
|
}, this))
|
|
22060
22107
|
.catch(_.bind(function(err) {
|
|
@@ -22067,7 +22114,7 @@ RequestBatcher.prototype.flush = function(options) {
|
|
|
22067
22114
|
* Log error to global logger and optional user-defined logger.
|
|
22068
22115
|
*/
|
|
22069
22116
|
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
22070
|
-
logger$
|
|
22117
|
+
logger$6.error.apply(logger$6.error, arguments);
|
|
22071
22118
|
if (this.errorReporter) {
|
|
22072
22119
|
try {
|
|
22073
22120
|
if (!(err instanceof Error)) {
|
|
@@ -22075,7 +22122,7 @@ RequestBatcher.prototype.reportError = function(msg, err) {
|
|
|
22075
22122
|
}
|
|
22076
22123
|
this.errorReporter(msg, err);
|
|
22077
22124
|
} catch(err) {
|
|
22078
|
-
logger$
|
|
22125
|
+
logger$6.error(err);
|
|
22079
22126
|
}
|
|
22080
22127
|
}
|
|
22081
22128
|
};
|
|
@@ -22092,6 +22139,29 @@ var isRecordingExpired = function(serializedRecording) {
|
|
|
22092
22139
|
|
|
22093
22140
|
var RECORD_ENQUEUE_THROTTLE_MS = 250;
|
|
22094
22141
|
|
|
22142
|
+
var validateAllowedOrigins = function(origins, logger) {
|
|
22143
|
+
if (!_.isArray(origins)) {
|
|
22144
|
+
if (origins) {
|
|
22145
|
+
logger.critical('record_allowed_iframe_origins must be an array of origin strings, cross-origin recording will be disabled.');
|
|
22146
|
+
}
|
|
22147
|
+
return [];
|
|
22148
|
+
}
|
|
22149
|
+
var valid = [];
|
|
22150
|
+
for (var i = 0; i < origins.length; i++) {
|
|
22151
|
+
try {
|
|
22152
|
+
var origin = new URL(origins[i]).origin;
|
|
22153
|
+
if (origin === 'null') {
|
|
22154
|
+
logger.critical(origins[i] + ' has an opaque origin. Skipping this entry.');
|
|
22155
|
+
continue;
|
|
22156
|
+
}
|
|
22157
|
+
valid.push(origin);
|
|
22158
|
+
} catch (e) {
|
|
22159
|
+
logger.critical(origins[i] + ' is not a valid origin URL. Skipping this entry.');
|
|
22160
|
+
}
|
|
22161
|
+
}
|
|
22162
|
+
return valid;
|
|
22163
|
+
};
|
|
22164
|
+
|
|
22095
22165
|
// stateless utils
|
|
22096
22166
|
// mostly from https://github.com/mixpanel/mixpanel-js/blob/989ada50f518edab47b9c4fd9535f9fbd5ec5fc0/src/autotrack-utils.js
|
|
22097
22167
|
|
|
@@ -22197,7 +22267,7 @@ var EVENT_HANDLER_ATTRIBUTES = [
|
|
|
22197
22267
|
|
|
22198
22268
|
var MAX_DEPTH = 5;
|
|
22199
22269
|
|
|
22200
|
-
var logger$
|
|
22270
|
+
var logger$5 = console_with_prefix('autocapture');
|
|
22201
22271
|
|
|
22202
22272
|
|
|
22203
22273
|
function getClasses(el) {
|
|
@@ -22461,7 +22531,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
|
22461
22531
|
return false;
|
|
22462
22532
|
}
|
|
22463
22533
|
} catch (err) {
|
|
22464
|
-
logger$
|
|
22534
|
+
logger$5.critical('Error while checking element in allowElementCallback', err);
|
|
22465
22535
|
return false;
|
|
22466
22536
|
}
|
|
22467
22537
|
}
|
|
@@ -22478,7 +22548,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
|
22478
22548
|
return true;
|
|
22479
22549
|
}
|
|
22480
22550
|
} catch (err) {
|
|
22481
|
-
logger$
|
|
22551
|
+
logger$5.critical('Error while checking selector: ' + sel, err);
|
|
22482
22552
|
}
|
|
22483
22553
|
}
|
|
22484
22554
|
return false;
|
|
@@ -22493,7 +22563,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
|
22493
22563
|
return true;
|
|
22494
22564
|
}
|
|
22495
22565
|
} catch (err) {
|
|
22496
|
-
logger$
|
|
22566
|
+
logger$5.critical('Error while checking element in blockElementCallback', err);
|
|
22497
22567
|
return true;
|
|
22498
22568
|
}
|
|
22499
22569
|
}
|
|
@@ -22507,7 +22577,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
|
22507
22577
|
return true;
|
|
22508
22578
|
}
|
|
22509
22579
|
} catch (err) {
|
|
22510
|
-
logger$
|
|
22580
|
+
logger$5.critical('Error while checking selector: ' + sel, err);
|
|
22511
22581
|
}
|
|
22512
22582
|
}
|
|
22513
22583
|
}
|
|
@@ -23063,7 +23133,7 @@ function shouldMaskText(element, privacyConfig) {
|
|
|
23063
23133
|
*
|
|
23064
23134
|
*/
|
|
23065
23135
|
|
|
23066
|
-
var logger$
|
|
23136
|
+
var logger$4 = console_with_prefix('network-plugin');
|
|
23067
23137
|
|
|
23068
23138
|
/**
|
|
23069
23139
|
* Get the time origin for converting performance timestamps to absolute timestamps.
|
|
@@ -23215,7 +23285,7 @@ function truncateBody(str) {
|
|
|
23215
23285
|
return str;
|
|
23216
23286
|
}
|
|
23217
23287
|
if (str.length > MAX_BODY_SIZE) {
|
|
23218
|
-
logger$
|
|
23288
|
+
logger$4.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
|
|
23219
23289
|
return str.substring(0, MAX_BODY_SIZE) + '... [truncated]';
|
|
23220
23290
|
}
|
|
23221
23291
|
return str;
|
|
@@ -23229,7 +23299,7 @@ function truncateBody(str) {
|
|
|
23229
23299
|
*/
|
|
23230
23300
|
function initPerformanceObserver(cb, win, options) {
|
|
23231
23301
|
if (!win.PerformanceObserver) {
|
|
23232
|
-
logger$
|
|
23302
|
+
logger$4.error('PerformanceObserver not supported');
|
|
23233
23303
|
return function() {
|
|
23234
23304
|
//
|
|
23235
23305
|
};
|
|
@@ -23382,7 +23452,7 @@ function getRequestPerformanceEntry(win, initiatorType, url, after, before, atte
|
|
|
23382
23452
|
attempt = 0;
|
|
23383
23453
|
}
|
|
23384
23454
|
if (attempt > 10) {
|
|
23385
|
-
logger$
|
|
23455
|
+
logger$4.error('Cannot find performance entry');
|
|
23386
23456
|
return Promise.resolve(null);
|
|
23387
23457
|
}
|
|
23388
23458
|
var urlPerformanceEntries = /** @type {PerformanceResourceTiming[]} */ (
|
|
@@ -23503,7 +23573,7 @@ function initXhrObserver(cb, win, options) {
|
|
|
23503
23573
|
)
|
|
23504
23574
|
.then(function(entry) {
|
|
23505
23575
|
if (!entry) {
|
|
23506
|
-
logger$
|
|
23576
|
+
logger$4.error('Failed to get performance entry for XHR request to ' + req.url);
|
|
23507
23577
|
return;
|
|
23508
23578
|
}
|
|
23509
23579
|
/** @type {NetworkRequest} */
|
|
@@ -23523,7 +23593,7 @@ function initXhrObserver(cb, win, options) {
|
|
|
23523
23593
|
cb({ requests: [request] });
|
|
23524
23594
|
})
|
|
23525
23595
|
.catch(function(e) {
|
|
23526
|
-
logger$
|
|
23596
|
+
logger$4.error('Error recording XHR request to ' + req.url + ': ' + String(e));
|
|
23527
23597
|
});
|
|
23528
23598
|
});
|
|
23529
23599
|
|
|
@@ -23615,7 +23685,7 @@ function initFetchObserver(cb, win, options) {
|
|
|
23615
23685
|
})
|
|
23616
23686
|
.then(function(entry) {
|
|
23617
23687
|
if (!entry) {
|
|
23618
|
-
logger$
|
|
23688
|
+
logger$4.error('Failed to get performance entry for fetch request to ' + req.url);
|
|
23619
23689
|
return;
|
|
23620
23690
|
}
|
|
23621
23691
|
/** @type {NetworkRequest} */
|
|
@@ -23635,7 +23705,7 @@ function initFetchObserver(cb, win, options) {
|
|
|
23635
23705
|
cb({ requests: [request] });
|
|
23636
23706
|
})
|
|
23637
23707
|
.catch(function (e) {
|
|
23638
|
-
logger$
|
|
23708
|
+
logger$4.error('Error recording fetch request to ' + req.url + ': ' + String(e));
|
|
23639
23709
|
});
|
|
23640
23710
|
|
|
23641
23711
|
return originalFetchPromise;
|
|
@@ -23708,7 +23778,7 @@ var getRecordNetworkPlugin = function(options) {
|
|
|
23708
23778
|
*/
|
|
23709
23779
|
|
|
23710
23780
|
|
|
23711
|
-
var logger$
|
|
23781
|
+
var logger$3 = console_with_prefix('recorder');
|
|
23712
23782
|
var CompressionStream = win['CompressionStream'];
|
|
23713
23783
|
|
|
23714
23784
|
var RECORDER_BATCHER_LIB_CONFIG = {
|
|
@@ -23888,14 +23958,14 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
|
|
|
23888
23958
|
}
|
|
23889
23959
|
|
|
23890
23960
|
if (this._stopRecording !== null) {
|
|
23891
|
-
logger$
|
|
23961
|
+
logger$3.log('Recording already in progress, skipping startRecording.');
|
|
23892
23962
|
return;
|
|
23893
23963
|
}
|
|
23894
23964
|
|
|
23895
23965
|
this.recordMaxMs = this.getConfig('record_max_ms');
|
|
23896
23966
|
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
23897
23967
|
this.recordMaxMs = MAX_RECORDING_MS;
|
|
23898
|
-
logger$
|
|
23968
|
+
logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
23899
23969
|
}
|
|
23900
23970
|
|
|
23901
23971
|
if (!this.maxExpires) {
|
|
@@ -23959,6 +24029,8 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
|
|
|
23959
24029
|
);
|
|
23960
24030
|
}
|
|
23961
24031
|
|
|
24032
|
+
var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$3);
|
|
24033
|
+
|
|
23962
24034
|
try {
|
|
23963
24035
|
this._stopRecording = this._rrwebRecord({
|
|
23964
24036
|
'emit': function (ev) {
|
|
@@ -23993,6 +24065,8 @@ SessionRecording.prototype.startRecording = function (shouldStopBatcher) {
|
|
|
23993
24065
|
'maskTextSelector': '*',
|
|
23994
24066
|
'maskInputFn': this._getMaskFn(shouldMaskInput, privacyConfig),
|
|
23995
24067
|
'maskTextFn': this._getMaskFn(shouldMaskText, privacyConfig),
|
|
24068
|
+
'recordCrossOriginIframes': validatedOrigins.length > 0,
|
|
24069
|
+
'allowedIframeOrigins': validatedOrigins,
|
|
23996
24070
|
'recordCanvas': this.getConfig('record_canvas'),
|
|
23997
24071
|
'sampling': {
|
|
23998
24072
|
'canvas': 15
|
|
@@ -24217,14 +24291,14 @@ SessionRecording.prototype._flushEvents = addOptOutCheckMixpanelLib(function (da
|
|
|
24217
24291
|
|
|
24218
24292
|
|
|
24219
24293
|
SessionRecording.prototype.reportError = function(msg, err) {
|
|
24220
|
-
logger$
|
|
24294
|
+
logger$3.error.apply(logger$3.error, arguments);
|
|
24221
24295
|
try {
|
|
24222
24296
|
if (!err && !(msg instanceof Error)) {
|
|
24223
24297
|
msg = new Error(msg);
|
|
24224
24298
|
}
|
|
24225
24299
|
this.getConfig('error_reporter')(msg, err);
|
|
24226
24300
|
} catch(err) {
|
|
24227
|
-
logger$
|
|
24301
|
+
logger$3.error(err);
|
|
24228
24302
|
}
|
|
24229
24303
|
};
|
|
24230
24304
|
|
|
@@ -24253,7 +24327,7 @@ SessionRecording.prototype._getRecordMinMs = function() {
|
|
|
24253
24327
|
var configValue = this.getConfig('record_min_ms');
|
|
24254
24328
|
|
|
24255
24329
|
if (configValue > MAX_VALUE_FOR_MIN_RECORDING_MS) {
|
|
24256
|
-
logger$
|
|
24330
|
+
logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
|
|
24257
24331
|
return MAX_VALUE_FOR_MIN_RECORDING_MS;
|
|
24258
24332
|
}
|
|
24259
24333
|
|
|
@@ -24416,7 +24490,7 @@ RecordingRegistry.prototype.flushInactiveRecordings = function () {
|
|
|
24416
24490
|
.catch(this.handleError.bind(this));
|
|
24417
24491
|
};
|
|
24418
24492
|
|
|
24419
|
-
var logger$
|
|
24493
|
+
var logger$2 = console_with_prefix('recorder');
|
|
24420
24494
|
|
|
24421
24495
|
/**
|
|
24422
24496
|
* Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
|
|
@@ -24432,7 +24506,7 @@ var MixpanelRecorder = function(mixpanelInstance, rrwebRecord, sharedLockStorage
|
|
|
24432
24506
|
*/
|
|
24433
24507
|
this.recordingRegistry = new RecordingRegistry({
|
|
24434
24508
|
mixpanelInstance: this.mixpanelInstance,
|
|
24435
|
-
errorReporter: logger$
|
|
24509
|
+
errorReporter: logger$2.error,
|
|
24436
24510
|
sharedLockStorage: sharedLockStorage
|
|
24437
24511
|
});
|
|
24438
24512
|
this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
|
|
@@ -24444,17 +24518,17 @@ var MixpanelRecorder = function(mixpanelInstance, rrwebRecord, sharedLockStorage
|
|
|
24444
24518
|
MixpanelRecorder.prototype.startRecording = function(options) {
|
|
24445
24519
|
options = options || {};
|
|
24446
24520
|
if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
|
|
24447
|
-
logger$
|
|
24521
|
+
logger$2.log('Recording already in progress, skipping startRecording.');
|
|
24448
24522
|
return;
|
|
24449
24523
|
}
|
|
24450
24524
|
|
|
24451
24525
|
var onIdleTimeout = function () {
|
|
24452
|
-
logger$
|
|
24526
|
+
logger$2.log('Idle timeout reached, restarting recording.');
|
|
24453
24527
|
this.resetRecording();
|
|
24454
24528
|
}.bind(this);
|
|
24455
24529
|
|
|
24456
24530
|
var onMaxLengthReached = function () {
|
|
24457
|
-
logger$
|
|
24531
|
+
logger$2.log('Max recording length reached, stopping recording.');
|
|
24458
24532
|
this.resetRecording();
|
|
24459
24533
|
}.bind(this);
|
|
24460
24534
|
|
|
@@ -24524,7 +24598,7 @@ MixpanelRecorder.prototype.resumeRecording = function (startNewIfInactive) {
|
|
|
24524
24598
|
} else if (startNewIfInactive) {
|
|
24525
24599
|
return this.startRecording({shouldStopBatcher: false});
|
|
24526
24600
|
} else {
|
|
24527
|
-
logger$
|
|
24601
|
+
logger$2.log('No resumable recording found.');
|
|
24528
24602
|
return null;
|
|
24529
24603
|
}
|
|
24530
24604
|
}.bind(this));
|
|
@@ -25189,7 +25263,7 @@ ShadowDOMObserver.prototype.observeShadowRoot = function(shadowRoot) {
|
|
|
25189
25263
|
observer.observe(shadowRoot, this.observerConfig);
|
|
25190
25264
|
this.shadowObservers.push(observer);
|
|
25191
25265
|
} catch (e) {
|
|
25192
|
-
logger$
|
|
25266
|
+
logger$5.critical('Error while observing shadow root', e);
|
|
25193
25267
|
}
|
|
25194
25268
|
};
|
|
25195
25269
|
|
|
@@ -25200,7 +25274,7 @@ ShadowDOMObserver.prototype.start = function() {
|
|
|
25200
25274
|
}
|
|
25201
25275
|
|
|
25202
25276
|
if (!weakSetSupported()) {
|
|
25203
|
-
logger$
|
|
25277
|
+
logger$5.critical('Shadow DOM observation unavailable: WeakSet not supported');
|
|
25204
25278
|
return;
|
|
25205
25279
|
}
|
|
25206
25280
|
|
|
@@ -25216,7 +25290,7 @@ ShadowDOMObserver.prototype.stop = function() {
|
|
|
25216
25290
|
try {
|
|
25217
25291
|
this.shadowObservers[i].disconnect();
|
|
25218
25292
|
} catch (e) {
|
|
25219
|
-
logger$
|
|
25293
|
+
logger$5.critical('Error while disconnecting shadow DOM observer', e);
|
|
25220
25294
|
}
|
|
25221
25295
|
}
|
|
25222
25296
|
this.shadowObservers = [];
|
|
@@ -25404,7 +25478,7 @@ DeadClickTracker.prototype.startTracking = function() {
|
|
|
25404
25478
|
|
|
25405
25479
|
this.mutationObserver.observe(document.body || document.documentElement, MUTATION_OBSERVER_CONFIG);
|
|
25406
25480
|
} catch (e) {
|
|
25407
|
-
logger$
|
|
25481
|
+
logger$5.critical('Error while setting up mutation observer', e);
|
|
25408
25482
|
}
|
|
25409
25483
|
}
|
|
25410
25484
|
|
|
@@ -25419,7 +25493,7 @@ DeadClickTracker.prototype.startTracking = function() {
|
|
|
25419
25493
|
);
|
|
25420
25494
|
this.shadowDOMObserver.start();
|
|
25421
25495
|
} catch (e) {
|
|
25422
|
-
logger$
|
|
25496
|
+
logger$5.critical('Error while setting up shadow DOM observer', e);
|
|
25423
25497
|
this.shadowDOMObserver = null;
|
|
25424
25498
|
}
|
|
25425
25499
|
}
|
|
@@ -25446,7 +25520,7 @@ DeadClickTracker.prototype.stopTracking = function() {
|
|
|
25446
25520
|
try {
|
|
25447
25521
|
listener.target.removeEventListener(listener.event, listener.handler, listener.options);
|
|
25448
25522
|
} catch (e) {
|
|
25449
|
-
logger$
|
|
25523
|
+
logger$5.critical('Error while removing event listener', e);
|
|
25450
25524
|
}
|
|
25451
25525
|
}
|
|
25452
25526
|
this.eventListeners = [];
|
|
@@ -25455,7 +25529,7 @@ DeadClickTracker.prototype.stopTracking = function() {
|
|
|
25455
25529
|
try {
|
|
25456
25530
|
this.mutationObserver.disconnect();
|
|
25457
25531
|
} catch (e) {
|
|
25458
|
-
logger$
|
|
25532
|
+
logger$5.critical('Error while disconnecting mutation observer', e);
|
|
25459
25533
|
}
|
|
25460
25534
|
this.mutationObserver = null;
|
|
25461
25535
|
}
|
|
@@ -25464,7 +25538,7 @@ DeadClickTracker.prototype.stopTracking = function() {
|
|
|
25464
25538
|
try {
|
|
25465
25539
|
this.shadowDOMObserver.stop();
|
|
25466
25540
|
} catch (e) {
|
|
25467
|
-
logger$
|
|
25541
|
+
logger$5.critical('Error while stopping shadow DOM observer', e);
|
|
25468
25542
|
}
|
|
25469
25543
|
this.shadowDOMObserver = null;
|
|
25470
25544
|
}
|
|
@@ -25542,7 +25616,7 @@ var Autocapture = function(mp) {
|
|
|
25542
25616
|
|
|
25543
25617
|
Autocapture.prototype.init = function() {
|
|
25544
25618
|
if (!minDOMApisSupported()) {
|
|
25545
|
-
logger$
|
|
25619
|
+
logger$5.critical('Autocapture unavailable: missing required DOM APIs');
|
|
25546
25620
|
return;
|
|
25547
25621
|
}
|
|
25548
25622
|
this.initPageListeners();
|
|
@@ -25582,7 +25656,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
25582
25656
|
try {
|
|
25583
25657
|
return !urlMatchesRegexList(currentUrl, allowUrlRegexes);
|
|
25584
25658
|
} catch (err) {
|
|
25585
|
-
logger$
|
|
25659
|
+
logger$5.critical('Error while checking block URL regexes: ', err);
|
|
25586
25660
|
return true;
|
|
25587
25661
|
}
|
|
25588
25662
|
}
|
|
@@ -25595,7 +25669,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
25595
25669
|
try {
|
|
25596
25670
|
return urlMatchesRegexList(currentUrl, blockUrlRegexes);
|
|
25597
25671
|
} catch (err) {
|
|
25598
|
-
logger$
|
|
25672
|
+
logger$5.critical('Error while checking block URL regexes: ', err);
|
|
25599
25673
|
return true;
|
|
25600
25674
|
}
|
|
25601
25675
|
};
|
|
@@ -25733,7 +25807,7 @@ Autocapture.prototype._initScrollDepthTracking = function() {
|
|
|
25733
25807
|
return;
|
|
25734
25808
|
}
|
|
25735
25809
|
|
|
25736
|
-
logger$
|
|
25810
|
+
logger$5.log('Initializing scroll depth tracking');
|
|
25737
25811
|
|
|
25738
25812
|
this.maxScrollViewDepth = Math.max(document$1.documentElement.clientHeight, win.innerHeight || 0);
|
|
25739
25813
|
|
|
@@ -25759,7 +25833,7 @@ Autocapture.prototype.initClickTracking = function() {
|
|
|
25759
25833
|
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
25760
25834
|
return;
|
|
25761
25835
|
}
|
|
25762
|
-
logger$
|
|
25836
|
+
logger$5.log('Initializing click tracking');
|
|
25763
25837
|
|
|
25764
25838
|
this.listenerClick = function(ev) {
|
|
25765
25839
|
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
@@ -25778,7 +25852,7 @@ Autocapture.prototype.initDeadClickTracking = function() {
|
|
|
25778
25852
|
return;
|
|
25779
25853
|
}
|
|
25780
25854
|
|
|
25781
|
-
logger$
|
|
25855
|
+
logger$5.log('Initializing dead click tracking');
|
|
25782
25856
|
if (!this._deadClickTracker) {
|
|
25783
25857
|
this._deadClickTracker = new DeadClickTracker(function(deadClickEvent) {
|
|
25784
25858
|
this.trackDomEvent(deadClickEvent, MP_EV_DEAD_CLICK);
|
|
@@ -25812,7 +25886,7 @@ Autocapture.prototype.initInputTracking = function() {
|
|
|
25812
25886
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
25813
25887
|
return;
|
|
25814
25888
|
}
|
|
25815
|
-
logger$
|
|
25889
|
+
logger$5.log('Initializing input tracking');
|
|
25816
25890
|
|
|
25817
25891
|
this.listenerChange = function(ev) {
|
|
25818
25892
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -25829,7 +25903,7 @@ Autocapture.prototype.initPageviewTracking = function() {
|
|
|
25829
25903
|
if (!this.pageviewTrackingConfig()) {
|
|
25830
25904
|
return;
|
|
25831
25905
|
}
|
|
25832
|
-
logger$
|
|
25906
|
+
logger$5.log('Initializing pageview tracking');
|
|
25833
25907
|
|
|
25834
25908
|
var previousTrackedUrl = '';
|
|
25835
25909
|
var tracked = false;
|
|
@@ -25864,7 +25938,7 @@ Autocapture.prototype.initPageviewTracking = function() {
|
|
|
25864
25938
|
}
|
|
25865
25939
|
if (didPathChange) {
|
|
25866
25940
|
this.lastScrollCheckpoint = 0;
|
|
25867
|
-
logger$
|
|
25941
|
+
logger$5.log('Path change: re-initializing scroll depth checkpoints');
|
|
25868
25942
|
}
|
|
25869
25943
|
}
|
|
25870
25944
|
}.bind(this));
|
|
@@ -25879,7 +25953,7 @@ Autocapture.prototype.initRageClickTracking = function() {
|
|
|
25879
25953
|
return;
|
|
25880
25954
|
}
|
|
25881
25955
|
|
|
25882
|
-
logger$
|
|
25956
|
+
logger$5.log('Initializing rage click tracking');
|
|
25883
25957
|
if (!this._rageClickTracker) {
|
|
25884
25958
|
this._rageClickTracker = new RageClickTracker();
|
|
25885
25959
|
}
|
|
@@ -25909,7 +25983,7 @@ Autocapture.prototype.initScrollTracking = function() {
|
|
|
25909
25983
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
25910
25984
|
return;
|
|
25911
25985
|
}
|
|
25912
|
-
logger$
|
|
25986
|
+
logger$5.log('Initializing scroll tracking');
|
|
25913
25987
|
this.lastScrollCheckpoint = 0;
|
|
25914
25988
|
|
|
25915
25989
|
var scrollTrackFunction = function() {
|
|
@@ -25946,7 +26020,7 @@ Autocapture.prototype.initScrollTracking = function() {
|
|
|
25946
26020
|
}
|
|
25947
26021
|
}
|
|
25948
26022
|
} catch (err) {
|
|
25949
|
-
logger$
|
|
26023
|
+
logger$5.critical('Error while calculating scroll percentage', err);
|
|
25950
26024
|
}
|
|
25951
26025
|
if (shouldTrack) {
|
|
25952
26026
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -25964,7 +26038,7 @@ Autocapture.prototype.initSubmitTracking = function() {
|
|
|
25964
26038
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
25965
26039
|
return;
|
|
25966
26040
|
}
|
|
25967
|
-
logger$
|
|
26041
|
+
logger$5.log('Initializing submit tracking');
|
|
25968
26042
|
|
|
25969
26043
|
this.listenerSubmit = function(ev) {
|
|
25970
26044
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -25986,7 +26060,7 @@ Autocapture.prototype.initPageLeaveTracking = function() {
|
|
|
25986
26060
|
return;
|
|
25987
26061
|
}
|
|
25988
26062
|
|
|
25989
|
-
logger$
|
|
26063
|
+
logger$5.log('Initializing page visibility tracking.');
|
|
25990
26064
|
this._initScrollDepthTracking();
|
|
25991
26065
|
var previousTrackedUrl = _.info.currentUrl();
|
|
25992
26066
|
|
|
@@ -26071,7 +26145,7 @@ var getTargetingPromise = function(loadExtraBundle, targetingSrc) {
|
|
|
26071
26145
|
return win[TARGETING_GLOBAL_NAME];
|
|
26072
26146
|
};
|
|
26073
26147
|
|
|
26074
|
-
var logger = console_with_prefix('flags');
|
|
26148
|
+
var logger$1 = console_with_prefix('flags');
|
|
26075
26149
|
var FLAGS_CONFIG_KEY = 'flags';
|
|
26076
26150
|
|
|
26077
26151
|
var CONFIG_CONTEXT = 'context';
|
|
@@ -26114,12 +26188,14 @@ var FeatureFlagManager = function(initOptions) {
|
|
|
26114
26188
|
|
|
26115
26189
|
FeatureFlagManager.prototype.init = function() {
|
|
26116
26190
|
if (!this.minApisSupported()) {
|
|
26117
|
-
logger.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
26191
|
+
logger$1.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
26118
26192
|
return;
|
|
26119
26193
|
}
|
|
26120
26194
|
|
|
26121
26195
|
this.flags = null;
|
|
26122
|
-
this.fetchFlags()
|
|
26196
|
+
this.fetchFlags().catch(function() {
|
|
26197
|
+
logger$1.error('Error fetching flags during init');
|
|
26198
|
+
});
|
|
26123
26199
|
|
|
26124
26200
|
this.trackedFeatures = new Set();
|
|
26125
26201
|
this.pendingFirstTimeEvents = {};
|
|
@@ -26149,7 +26225,7 @@ FeatureFlagManager.prototype.isSystemEnabled = function() {
|
|
|
26149
26225
|
|
|
26150
26226
|
FeatureFlagManager.prototype.updateContext = function(newContext, options) {
|
|
26151
26227
|
if (!this.isSystemEnabled()) {
|
|
26152
|
-
logger.critical('Feature Flags not enabled, cannot update context');
|
|
26228
|
+
logger$1.critical('Feature Flags not enabled, cannot update context');
|
|
26153
26229
|
return Promise.resolve();
|
|
26154
26230
|
}
|
|
26155
26231
|
|
|
@@ -26160,13 +26236,17 @@ FeatureFlagManager.prototype.updateContext = function(newContext, options) {
|
|
|
26160
26236
|
var oldContext = (options && options['replace']) ? {} : this.getConfig(CONFIG_CONTEXT);
|
|
26161
26237
|
ffConfig[CONFIG_CONTEXT] = _.extend({}, oldContext, newContext);
|
|
26162
26238
|
|
|
26163
|
-
|
|
26164
|
-
|
|
26239
|
+
var configUpdate = {};
|
|
26240
|
+
configUpdate[FLAGS_CONFIG_KEY] = ffConfig;
|
|
26241
|
+
this.setMpConfig(configUpdate);
|
|
26242
|
+
return this.fetchFlags().catch(function() {
|
|
26243
|
+
logger$1.error('Error fetching flags during updateContext');
|
|
26244
|
+
});
|
|
26165
26245
|
};
|
|
26166
26246
|
|
|
26167
26247
|
FeatureFlagManager.prototype.areFlagsReady = function() {
|
|
26168
26248
|
if (!this.isSystemEnabled()) {
|
|
26169
|
-
logger.error('Feature Flags not enabled');
|
|
26249
|
+
logger$1.error('Feature Flags not enabled');
|
|
26170
26250
|
}
|
|
26171
26251
|
return !!this.flags;
|
|
26172
26252
|
};
|
|
@@ -26179,7 +26259,7 @@ FeatureFlagManager.prototype.fetchFlags = function() {
|
|
|
26179
26259
|
var distinctId = this.getMpProperty('distinct_id');
|
|
26180
26260
|
var deviceId = this.getMpProperty('$device_id');
|
|
26181
26261
|
var traceparent = generateTraceparent();
|
|
26182
|
-
logger.log('Fetching flags for distinct ID: ' + distinctId);
|
|
26262
|
+
logger$1.log('Fetching flags for distinct ID: ' + distinctId);
|
|
26183
26263
|
|
|
26184
26264
|
var context = _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT));
|
|
26185
26265
|
var searchParams = new URLSearchParams();
|
|
@@ -26198,99 +26278,113 @@ FeatureFlagManager.prototype.fetchFlags = function() {
|
|
|
26198
26278
|
}
|
|
26199
26279
|
}).then(function(response) {
|
|
26200
26280
|
this.markFetchComplete();
|
|
26201
|
-
return response.json()
|
|
26202
|
-
|
|
26203
|
-
|
|
26204
|
-
|
|
26205
|
-
|
|
26206
|
-
|
|
26207
|
-
|
|
26208
|
-
|
|
26209
|
-
|
|
26210
|
-
|
|
26211
|
-
|
|
26212
|
-
|
|
26213
|
-
|
|
26214
|
-
|
|
26215
|
-
|
|
26216
|
-
|
|
26217
|
-
|
|
26218
|
-
}
|
|
26281
|
+
return response.json();
|
|
26282
|
+
}.bind(this)).then(function(responseBody) {
|
|
26283
|
+
var responseFlags = responseBody['flags'];
|
|
26284
|
+
if (!responseFlags) {
|
|
26285
|
+
throw new Error('No flags in API response');
|
|
26286
|
+
}
|
|
26287
|
+
var flags = new Map();
|
|
26288
|
+
var pendingFirstTimeEvents = {};
|
|
26289
|
+
|
|
26290
|
+
// Process flags from response
|
|
26291
|
+
_.each(responseFlags, function(data, key) {
|
|
26292
|
+
// Check if this flag has any activated first-time events this session
|
|
26293
|
+
var hasActivatedEvent = false;
|
|
26294
|
+
var prefix = key + ':';
|
|
26295
|
+
_.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
|
|
26296
|
+
if (eventKey.startsWith(prefix)) {
|
|
26297
|
+
hasActivatedEvent = true;
|
|
26298
|
+
}
|
|
26299
|
+
});
|
|
26219
26300
|
|
|
26220
|
-
|
|
26221
|
-
|
|
26222
|
-
|
|
26223
|
-
|
|
26224
|
-
|
|
26225
|
-
}
|
|
26226
|
-
} else {
|
|
26227
|
-
// Use server's current variant
|
|
26228
|
-
flags.set(key, {
|
|
26229
|
-
'key': data['variant_key'],
|
|
26230
|
-
'value': data['variant_value'],
|
|
26231
|
-
'experiment_id': data['experiment_id'],
|
|
26232
|
-
'is_experiment_active': data['is_experiment_active'],
|
|
26233
|
-
'is_qa_tester': data['is_qa_tester']
|
|
26234
|
-
});
|
|
26301
|
+
if (hasActivatedEvent) {
|
|
26302
|
+
// Preserve the activated variant, don't overwrite with server's current variant
|
|
26303
|
+
var currentFlag = this.flags && this.flags.get(key);
|
|
26304
|
+
if (currentFlag) {
|
|
26305
|
+
flags.set(key, currentFlag);
|
|
26235
26306
|
}
|
|
26236
|
-
}
|
|
26307
|
+
} else {
|
|
26308
|
+
// Use server's current variant
|
|
26309
|
+
flags.set(key, {
|
|
26310
|
+
'key': data['variant_key'],
|
|
26311
|
+
'value': data['variant_value'],
|
|
26312
|
+
'experiment_id': data['experiment_id'],
|
|
26313
|
+
'is_experiment_active': data['is_experiment_active'],
|
|
26314
|
+
'is_qa_tester': data['is_qa_tester']
|
|
26315
|
+
});
|
|
26316
|
+
}
|
|
26317
|
+
}, this);
|
|
26237
26318
|
|
|
26238
|
-
|
|
26239
|
-
|
|
26240
|
-
|
|
26241
|
-
|
|
26242
|
-
|
|
26243
|
-
|
|
26319
|
+
// Process top-level pending_first_time_events array
|
|
26320
|
+
var topLevelDefinitions = responseBody['pending_first_time_events'];
|
|
26321
|
+
if (topLevelDefinitions && topLevelDefinitions.length > 0) {
|
|
26322
|
+
_.each(topLevelDefinitions, function(def) {
|
|
26323
|
+
var flagKey = def['flag_key'];
|
|
26324
|
+
var eventKey = getPendingEventKey(flagKey, def['first_time_event_hash']);
|
|
26244
26325
|
|
|
26245
|
-
|
|
26246
|
-
|
|
26247
|
-
|
|
26248
|
-
|
|
26326
|
+
// Skip if this specific event has already been activated this session
|
|
26327
|
+
if (this.activatedFirstTimeEvents[eventKey]) {
|
|
26328
|
+
return;
|
|
26329
|
+
}
|
|
26249
26330
|
|
|
26250
|
-
|
|
26251
|
-
|
|
26252
|
-
|
|
26253
|
-
|
|
26254
|
-
|
|
26255
|
-
|
|
26256
|
-
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
|
|
26261
|
-
|
|
26331
|
+
// Store pending event definition using composite key
|
|
26332
|
+
pendingFirstTimeEvents[eventKey] = {
|
|
26333
|
+
'flag_key': flagKey,
|
|
26334
|
+
'flag_id': def['flag_id'],
|
|
26335
|
+
'project_id': def['project_id'],
|
|
26336
|
+
'first_time_event_hash': def['first_time_event_hash'],
|
|
26337
|
+
'event_name': def['event_name'],
|
|
26338
|
+
'property_filters': def['property_filters'],
|
|
26339
|
+
'pending_variant': def['pending_variant']
|
|
26340
|
+
};
|
|
26341
|
+
}, this);
|
|
26342
|
+
}
|
|
26262
26343
|
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26266
|
-
|
|
26267
|
-
|
|
26268
|
-
|
|
26269
|
-
|
|
26270
|
-
|
|
26271
|
-
|
|
26272
|
-
|
|
26344
|
+
// Preserve any activated orphaned flags (flags that were activated but are no longer in response)
|
|
26345
|
+
if (this.activatedFirstTimeEvents) {
|
|
26346
|
+
_.each(this.activatedFirstTimeEvents, function(activated, eventKey) {
|
|
26347
|
+
var flagKey = getFlagKeyFromPendingEventKey(eventKey);
|
|
26348
|
+
if (activated && !flags.has(flagKey) && this.flags && this.flags.has(flagKey)) {
|
|
26349
|
+
// Keep the activated flag even though it's not in the new response
|
|
26350
|
+
flags.set(flagKey, this.flags.get(flagKey));
|
|
26351
|
+
}
|
|
26352
|
+
}, this);
|
|
26353
|
+
}
|
|
26273
26354
|
|
|
26274
|
-
|
|
26275
|
-
|
|
26276
|
-
|
|
26355
|
+
this.flags = flags;
|
|
26356
|
+
this.pendingFirstTimeEvents = pendingFirstTimeEvents;
|
|
26357
|
+
this._traceparent = traceparent;
|
|
26277
26358
|
|
|
26278
|
-
|
|
26279
|
-
}.bind(this)).catch(function(error) {
|
|
26280
|
-
this.markFetchComplete();
|
|
26281
|
-
logger.error(error);
|
|
26282
|
-
}.bind(this));
|
|
26359
|
+
this._loadTargetingIfNeeded();
|
|
26283
26360
|
}.bind(this)).catch(function(error) {
|
|
26284
|
-
this.
|
|
26285
|
-
|
|
26361
|
+
if (this._fetchInProgressStartTime) {
|
|
26362
|
+
this.markFetchComplete();
|
|
26363
|
+
}
|
|
26364
|
+
logger$1.error(error);
|
|
26365
|
+
throw error;
|
|
26286
26366
|
}.bind(this));
|
|
26287
26367
|
|
|
26288
26368
|
return this.fetchPromise;
|
|
26289
26369
|
};
|
|
26290
26370
|
|
|
26371
|
+
FeatureFlagManager.prototype.loadFlags = function() {
|
|
26372
|
+
if (!this.isSystemEnabled()) {
|
|
26373
|
+
return Promise.resolve();
|
|
26374
|
+
}
|
|
26375
|
+
if (!this.trackedFeatures) {
|
|
26376
|
+
logger$1.error('loadFlags called before init');
|
|
26377
|
+
return Promise.resolve();
|
|
26378
|
+
}
|
|
26379
|
+
if (this._fetchInProgressStartTime) {
|
|
26380
|
+
return this.fetchPromise;
|
|
26381
|
+
}
|
|
26382
|
+
return this.fetchFlags();
|
|
26383
|
+
};
|
|
26384
|
+
|
|
26291
26385
|
FeatureFlagManager.prototype.markFetchComplete = function() {
|
|
26292
26386
|
if (!this._fetchInProgressStartTime) {
|
|
26293
|
-
logger.error('Fetch in progress started time not set, cannot mark fetch complete');
|
|
26387
|
+
logger$1.error('Fetch in progress started time not set, cannot mark fetch complete');
|
|
26294
26388
|
return;
|
|
26295
26389
|
}
|
|
26296
26390
|
this._fetchStartTime = this._fetchInProgressStartTime;
|
|
@@ -26312,7 +26406,7 @@ FeatureFlagManager.prototype._loadTargetingIfNeeded = function() {
|
|
|
26312
26406
|
|
|
26313
26407
|
if (hasPropertyFilters) {
|
|
26314
26408
|
this.getTargeting().then(function() {
|
|
26315
|
-
logger.log('targeting loaded for property filter evaluation');
|
|
26409
|
+
logger$1.log('targeting loaded for property filter evaluation');
|
|
26316
26410
|
});
|
|
26317
26411
|
}
|
|
26318
26412
|
};
|
|
@@ -26327,7 +26421,7 @@ FeatureFlagManager.prototype.getTargeting = function() {
|
|
|
26327
26421
|
this.loadExtraBundle.bind(this),
|
|
26328
26422
|
this.targetingSrc
|
|
26329
26423
|
).catch(function(error) {
|
|
26330
|
-
logger.error('Failed to load targeting: ' + error);
|
|
26424
|
+
logger$1.error('Failed to load targeting: ' + error);
|
|
26331
26425
|
}.bind(this));
|
|
26332
26426
|
};
|
|
26333
26427
|
|
|
@@ -26381,7 +26475,7 @@ FeatureFlagManager.prototype._processFirstTimeEventCheck = function(eventName, p
|
|
|
26381
26475
|
|
|
26382
26476
|
// If no targeting library and event has property filters, skip it
|
|
26383
26477
|
if (!targeting && pendingEvent['property_filters'] && !_.isEmptyObject(pendingEvent['property_filters'])) {
|
|
26384
|
-
logger.warn('Skipping event check for "' + flagKey + '" - property filters require targeting library');
|
|
26478
|
+
logger$1.warn('Skipping event check for "' + flagKey + '" - property filters require targeting library');
|
|
26385
26479
|
return;
|
|
26386
26480
|
}
|
|
26387
26481
|
|
|
@@ -26404,7 +26498,7 @@ FeatureFlagManager.prototype._processFirstTimeEventCheck = function(eventName, p
|
|
|
26404
26498
|
}
|
|
26405
26499
|
|
|
26406
26500
|
if (matchResult.error) {
|
|
26407
|
-
logger.error('Error checking first-time event for flag "' + flagKey + '": ' + matchResult.error);
|
|
26501
|
+
logger$1.error('Error checking first-time event for flag "' + flagKey + '": ' + matchResult.error);
|
|
26408
26502
|
return;
|
|
26409
26503
|
}
|
|
26410
26504
|
|
|
@@ -26412,7 +26506,7 @@ FeatureFlagManager.prototype._processFirstTimeEventCheck = function(eventName, p
|
|
|
26412
26506
|
return;
|
|
26413
26507
|
}
|
|
26414
26508
|
|
|
26415
|
-
logger.log('First-time event matched for flag "' + flagKey + '": ' + eventName);
|
|
26509
|
+
logger$1.log('First-time event matched for flag "' + flagKey + '": ' + eventName);
|
|
26416
26510
|
|
|
26417
26511
|
var newVariant = {
|
|
26418
26512
|
'key': pendingEvent['pending_variant']['variant_key'],
|
|
@@ -26453,7 +26547,7 @@ FeatureFlagManager.prototype.recordFirstTimeEvent = function(flagId, projectId,
|
|
|
26453
26547
|
'first_time_event_hash': firstTimeEventHash
|
|
26454
26548
|
};
|
|
26455
26549
|
|
|
26456
|
-
logger.log('Recording first-time event for flag: ' + flagId);
|
|
26550
|
+
logger$1.log('Recording first-time event for flag: ' + flagId);
|
|
26457
26551
|
|
|
26458
26552
|
// Fire-and-forget POST request
|
|
26459
26553
|
this.fetch.call(win, url, {
|
|
@@ -26466,14 +26560,14 @@ FeatureFlagManager.prototype.recordFirstTimeEvent = function(flagId, projectId,
|
|
|
26466
26560
|
'body': JSON.stringify(payload)
|
|
26467
26561
|
}).catch(function(error) {
|
|
26468
26562
|
// Silent failure - cohort sync will catch up
|
|
26469
|
-
logger.error('Failed to record first-time event for flag ' + flagId + ': ' + error);
|
|
26563
|
+
logger$1.error('Failed to record first-time event for flag ' + flagId + ': ' + error);
|
|
26470
26564
|
});
|
|
26471
26565
|
};
|
|
26472
26566
|
|
|
26473
26567
|
FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
|
|
26474
26568
|
if (!this.fetchPromise) {
|
|
26475
26569
|
return new Promise(function(resolve) {
|
|
26476
|
-
logger.critical('Feature Flags not initialized');
|
|
26570
|
+
logger$1.critical('Feature Flags not initialized');
|
|
26477
26571
|
resolve(fallback);
|
|
26478
26572
|
});
|
|
26479
26573
|
}
|
|
@@ -26481,19 +26575,19 @@ FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
|
|
|
26481
26575
|
return this.fetchPromise.then(function() {
|
|
26482
26576
|
return this.getVariantSync(featureName, fallback);
|
|
26483
26577
|
}.bind(this)).catch(function(error) {
|
|
26484
|
-
logger.error(error);
|
|
26578
|
+
logger$1.error(error);
|
|
26485
26579
|
return fallback;
|
|
26486
26580
|
});
|
|
26487
26581
|
};
|
|
26488
26582
|
|
|
26489
26583
|
FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
|
|
26490
26584
|
if (!this.areFlagsReady()) {
|
|
26491
|
-
logger.log('Flags not loaded yet');
|
|
26585
|
+
logger$1.log('Flags not loaded yet');
|
|
26492
26586
|
return fallback;
|
|
26493
26587
|
}
|
|
26494
26588
|
var feature = this.flags.get(featureName);
|
|
26495
26589
|
if (!feature) {
|
|
26496
|
-
logger.log('No flag found: "' + featureName + '"');
|
|
26590
|
+
logger$1.log('No flag found: "' + featureName + '"');
|
|
26497
26591
|
return fallback;
|
|
26498
26592
|
}
|
|
26499
26593
|
this.trackFeatureCheck(featureName, feature);
|
|
@@ -26504,14 +26598,14 @@ FeatureFlagManager.prototype.getVariantValue = function(featureName, fallbackVal
|
|
|
26504
26598
|
return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
|
|
26505
26599
|
return feature['value'];
|
|
26506
26600
|
}).catch(function(error) {
|
|
26507
|
-
logger.error(error);
|
|
26601
|
+
logger$1.error(error);
|
|
26508
26602
|
return fallbackValue;
|
|
26509
26603
|
});
|
|
26510
26604
|
};
|
|
26511
26605
|
|
|
26512
26606
|
// TODO remove deprecated method
|
|
26513
26607
|
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
26514
|
-
logger.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
|
|
26608
|
+
logger$1.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
|
|
26515
26609
|
return this.getVariantValue(featureName, fallbackValue);
|
|
26516
26610
|
};
|
|
26517
26611
|
|
|
@@ -26523,7 +26617,7 @@ FeatureFlagManager.prototype.isEnabled = function(featureName, fallbackValue) {
|
|
|
26523
26617
|
return this.getVariantValue(featureName).then(function() {
|
|
26524
26618
|
return this.isEnabledSync(featureName, fallbackValue);
|
|
26525
26619
|
}.bind(this)).catch(function(error) {
|
|
26526
|
-
logger.error(error);
|
|
26620
|
+
logger$1.error(error);
|
|
26527
26621
|
return fallbackValue;
|
|
26528
26622
|
});
|
|
26529
26623
|
};
|
|
@@ -26532,7 +26626,7 @@ FeatureFlagManager.prototype.isEnabledSync = function(featureName, fallbackValue
|
|
|
26532
26626
|
fallbackValue = fallbackValue || false;
|
|
26533
26627
|
var val = this.getVariantValueSync(featureName, fallbackValue);
|
|
26534
26628
|
if (val !== true && val !== false) {
|
|
26535
|
-
logger.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
26629
|
+
logger$1.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
26536
26630
|
val = fallbackValue;
|
|
26537
26631
|
}
|
|
26538
26632
|
return val;
|
|
@@ -26567,6 +26661,13 @@ FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature)
|
|
|
26567
26661
|
this.track('$experiment_started', trackingProperties);
|
|
26568
26662
|
};
|
|
26569
26663
|
|
|
26664
|
+
FeatureFlagManager.prototype.whenReady = function() {
|
|
26665
|
+
if (this.fetchPromise) {
|
|
26666
|
+
return this.fetchPromise;
|
|
26667
|
+
}
|
|
26668
|
+
return Promise.resolve();
|
|
26669
|
+
};
|
|
26670
|
+
|
|
26570
26671
|
FeatureFlagManager.prototype.minApisSupported = function() {
|
|
26571
26672
|
return !!this.fetch &&
|
|
26572
26673
|
typeof Promise !== 'undefined' &&
|
|
@@ -26583,7 +26684,9 @@ FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype
|
|
|
26583
26684
|
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
26584
26685
|
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
26585
26686
|
FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
|
|
26687
|
+
FeatureFlagManager.prototype['load_flags'] = FeatureFlagManager.prototype.loadFlags;
|
|
26586
26688
|
FeatureFlagManager.prototype['update_context'] = FeatureFlagManager.prototype.updateContext;
|
|
26689
|
+
FeatureFlagManager.prototype['when_ready'] = FeatureFlagManager.prototype.whenReady;
|
|
26587
26690
|
|
|
26588
26691
|
// Deprecated method
|
|
26589
26692
|
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
@@ -26594,6 +26697,12 @@ FeatureFlagManager.prototype['getTargeting'] = FeatureFlagManager.prototype.getT
|
|
|
26594
26697
|
/* eslint camelcase: "off" */
|
|
26595
26698
|
|
|
26596
26699
|
|
|
26700
|
+
var logger = console_with_prefix('recorder');
|
|
26701
|
+
|
|
26702
|
+
var IFRAME_HANDSHAKE_REQUEST = 'mp_iframe_handshake_request';
|
|
26703
|
+
var IFRAME_HANDSHAKE_RESPONSE = 'mp_iframe_handshake_response';
|
|
26704
|
+
|
|
26705
|
+
|
|
26597
26706
|
/**
|
|
26598
26707
|
* RecorderManager: manages session recording initialization, lifecycle and state
|
|
26599
26708
|
* @constructor
|
|
@@ -26613,6 +26722,8 @@ var RecorderManager = function(initOptions) {
|
|
|
26613
26722
|
this.libBasePath = initOptions.libBasePath;
|
|
26614
26723
|
|
|
26615
26724
|
this._recorder = null;
|
|
26725
|
+
this._parentReplayId = null;
|
|
26726
|
+
this._parentFrameRetryInterval = null;
|
|
26616
26727
|
};
|
|
26617
26728
|
|
|
26618
26729
|
RecorderManager.prototype.shouldLoadRecorder = function() {
|
|
@@ -26666,6 +26777,22 @@ RecorderManager.prototype.checkAndStartSessionRecording = function(force_start,
|
|
|
26666
26777
|
}, this));
|
|
26667
26778
|
}, this);
|
|
26668
26779
|
|
|
26780
|
+
// Cross-origin iframe handling
|
|
26781
|
+
var allowedOrigins = validateAllowedOrigins(this.getMpConfig('record_allowed_iframe_origins'), logger);
|
|
26782
|
+
var isCrossOriginRecordingEnabled = allowedOrigins.length > 0;
|
|
26783
|
+
|
|
26784
|
+
if (isCrossOriginRecordingEnabled) {
|
|
26785
|
+
// listen for handshake requests from their own child iframes (including nested)
|
|
26786
|
+
this._setupParentFrameListener(allowedOrigins);
|
|
26787
|
+
|
|
26788
|
+
if (win.parent !== win) {
|
|
26789
|
+
// also wait for parent's replay ID
|
|
26790
|
+
this._setupChildFrameListener(allowedOrigins, loadRecorder);
|
|
26791
|
+
this._sendParentFrameRequestWithRetry(allowedOrigins);
|
|
26792
|
+
return PromisePolyfill.resolve();
|
|
26793
|
+
}
|
|
26794
|
+
}
|
|
26795
|
+
|
|
26669
26796
|
/**
|
|
26670
26797
|
* If the user is sampled or start_session_recording is called, we always load the recorder since it's guaranteed a recording should start.
|
|
26671
26798
|
* Otherwise, if the recording registry has any records then it's likely there's a recording in progress or orphaned data that needs to be flushed.
|
|
@@ -26785,6 +26912,10 @@ RecorderManager.prototype.getSessionReplayUrl = function() {
|
|
|
26785
26912
|
};
|
|
26786
26913
|
|
|
26787
26914
|
RecorderManager.prototype.getSessionReplayId = function() {
|
|
26915
|
+
// Child iframe uses parent's replay ID
|
|
26916
|
+
if (this._parentReplayId) {
|
|
26917
|
+
return this._parentReplayId;
|
|
26918
|
+
}
|
|
26788
26919
|
var replay_id = null;
|
|
26789
26920
|
if (this._recorder) {
|
|
26790
26921
|
replay_id = this._recorder['replayId'];
|
|
@@ -26797,6 +26928,86 @@ RecorderManager.prototype.getRecorder = function() {
|
|
|
26797
26928
|
return this._recorder;
|
|
26798
26929
|
};
|
|
26799
26930
|
|
|
26931
|
+
RecorderManager.prototype._setupChildFrameListener = function(allowedOrigins, loadRecorder) {
|
|
26932
|
+
if (this._childFrameMessageHandler) {
|
|
26933
|
+
return;
|
|
26934
|
+
}
|
|
26935
|
+
var self = this;
|
|
26936
|
+
this._childFrameMessageHandler = function(event) {
|
|
26937
|
+
if (allowedOrigins.indexOf(event.origin) === -1) return;
|
|
26938
|
+
var data = event.data;
|
|
26939
|
+
if (data && data['type'] === IFRAME_HANDSHAKE_RESPONSE && data['token'] === self.getMpConfig('token') && data['replayId']) {
|
|
26940
|
+
self._parentReplayId = data['replayId'];
|
|
26941
|
+
if (data['distinctId']) {
|
|
26942
|
+
self.mixpanelInstance['identify'](data['distinctId']);
|
|
26943
|
+
}
|
|
26944
|
+
self._parentFrameRetryActive = false;
|
|
26945
|
+
win.removeEventListener('message', self._childFrameMessageHandler);
|
|
26946
|
+
self._childFrameMessageHandler = null;
|
|
26947
|
+
loadRecorder(true);
|
|
26948
|
+
}
|
|
26949
|
+
};
|
|
26950
|
+
win.addEventListener('message', this._childFrameMessageHandler);
|
|
26951
|
+
};
|
|
26952
|
+
|
|
26953
|
+
RecorderManager.prototype._sendParentFrameRequest = function(allowedOrigins) {
|
|
26954
|
+
var message = {};
|
|
26955
|
+
message['type'] = IFRAME_HANDSHAKE_REQUEST;
|
|
26956
|
+
message['token'] = this.getMpConfig('token');
|
|
26957
|
+
for (var i = 0; i < allowedOrigins.length; i++) {
|
|
26958
|
+
try {
|
|
26959
|
+
win.parent.postMessage(message, allowedOrigins[i]);
|
|
26960
|
+
} catch (e) {
|
|
26961
|
+
// origin mismatch - ignore
|
|
26962
|
+
}
|
|
26963
|
+
}
|
|
26964
|
+
};
|
|
26965
|
+
|
|
26966
|
+
RecorderManager.prototype._sendParentFrameRequestWithRetry = function(allowedOrigins) {
|
|
26967
|
+
var self = this;
|
|
26968
|
+
var maxRetries = 10;
|
|
26969
|
+
var retryCount = 0;
|
|
26970
|
+
var delay = 50;
|
|
26971
|
+
this._parentFrameRetryActive = true;
|
|
26972
|
+
|
|
26973
|
+
this._sendParentFrameRequest(allowedOrigins);
|
|
26974
|
+
|
|
26975
|
+
function scheduleRetry() {
|
|
26976
|
+
setTimeout(function() {
|
|
26977
|
+
if (!self._parentFrameRetryActive || self._parentReplayId || ++retryCount >= maxRetries) {
|
|
26978
|
+
return;
|
|
26979
|
+
}
|
|
26980
|
+
self._sendParentFrameRequest(allowedOrigins);
|
|
26981
|
+
delay *= 2;
|
|
26982
|
+
scheduleRetry();
|
|
26983
|
+
}, delay);
|
|
26984
|
+
}
|
|
26985
|
+
scheduleRetry();
|
|
26986
|
+
};
|
|
26987
|
+
|
|
26988
|
+
RecorderManager.prototype._setupParentFrameListener = function(allowedOrigins) {
|
|
26989
|
+
if (this._parentFrameMessageHandler) {
|
|
26990
|
+
return;
|
|
26991
|
+
}
|
|
26992
|
+
var self = this;
|
|
26993
|
+
this._parentFrameMessageHandler = function(event) {
|
|
26994
|
+
if (allowedOrigins.indexOf(event.origin) === -1) return;
|
|
26995
|
+
var data = event.data;
|
|
26996
|
+
if (data && data['type'] === IFRAME_HANDSHAKE_REQUEST && data['token'] === self.getMpConfig('token')) {
|
|
26997
|
+
var replayId = self.getSessionReplayId();
|
|
26998
|
+
if (replayId) {
|
|
26999
|
+
var response = {};
|
|
27000
|
+
response['type'] = IFRAME_HANDSHAKE_RESPONSE;
|
|
27001
|
+
response['token'] = self.getMpConfig('token');
|
|
27002
|
+
response['replayId'] = replayId;
|
|
27003
|
+
response['distinctId'] = self.getDistinctId();
|
|
27004
|
+
event.source.postMessage(response, event.origin);
|
|
27005
|
+
}
|
|
27006
|
+
}
|
|
27007
|
+
};
|
|
27008
|
+
win.addEventListener('message', this._parentFrameMessageHandler);
|
|
27009
|
+
};
|
|
27010
|
+
|
|
26800
27011
|
safewrapClass(RecorderManager);
|
|
26801
27012
|
|
|
26802
27013
|
/* eslint camelcase: "off" */
|
|
@@ -28171,7 +28382,6 @@ var INIT_SNIPPET = 1;
|
|
|
28171
28382
|
/** @const */ var SETTING_FALLBACK = 'fallback';
|
|
28172
28383
|
/** @const */ var SETTING_DISABLED = 'disabled';
|
|
28173
28384
|
|
|
28174
|
-
|
|
28175
28385
|
/*
|
|
28176
28386
|
* Dynamic... constants? Is that an oxymoron?
|
|
28177
28387
|
*/
|
|
@@ -28256,6 +28466,7 @@ var DEFAULT_CONFIG = {
|
|
|
28256
28466
|
'batch_request_timeout_ms': 90000,
|
|
28257
28467
|
'batch_autostart': true,
|
|
28258
28468
|
'hooks': {},
|
|
28469
|
+
'record_allowed_iframe_origins': [],
|
|
28259
28470
|
'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
|
|
28260
28471
|
'record_block_selector': 'img, video, audio',
|
|
28261
28472
|
'record_canvas': false,
|
|
@@ -29831,7 +30042,9 @@ MixpanelLib.prototype.identify = function(
|
|
|
29831
30042
|
|
|
29832
30043
|
// check feature flags again if distinct id has changed
|
|
29833
30044
|
if (new_distinct_id !== previous_distinct_id) {
|
|
29834
|
-
this.flags.fetchFlags()
|
|
30045
|
+
this.flags.fetchFlags().catch(function() {
|
|
30046
|
+
console$1.error('[flags] Error fetching flags during identify');
|
|
30047
|
+
});
|
|
29835
30048
|
}
|
|
29836
30049
|
};
|
|
29837
30050
|
|