mixpanel-browser 2.68.0 → 2.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mixpanel-core.cjs.js +18 -3
- package/dist/mixpanel-recorder.js +186 -47
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +18 -3
- package/dist/mixpanel-with-recorder.js +194 -48
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.js +194 -48
- package/dist/mixpanel.cjs.js +194 -48
- package/dist/mixpanel.globals.js +18 -3
- package/dist/mixpanel.min.js +68 -68
- package/dist/mixpanel.module.js +194 -48
- package/dist/mixpanel.umd.js +194 -48
- package/dist/rrweb-compiled.js +190 -59
- package/package.json +14 -2
- package/rollup.config.mjs +2 -2
- package/src/config.js +1 -1
- package/src/index.d.ts +1 -0
- package/src/mixpanel-core.js +8 -1
- package/src/recorder/recorder.js +1 -1
- package/src/recorder/recording-registry.js +37 -2
- package/src/recorder/session-recording.js +2 -3
- package/src/request-queue.js +1 -1
- package/src/storage/indexed-db.js +4 -0
- package/src/storage/local-storage.js +4 -0
- package/src/storage/wrapper.js +1 -0
package/dist/rrweb-compiled.js
CHANGED
|
@@ -460,6 +460,30 @@ function querySelectorAll$1(n2, selectors) {
|
|
|
460
460
|
function mutationObserverCtor$1() {
|
|
461
461
|
return getUntaintedPrototype$1("MutationObserver").constructor;
|
|
462
462
|
}
|
|
463
|
+
function patch$1(source, name, replacement) {
|
|
464
|
+
try {
|
|
465
|
+
if (!(name in source)) {
|
|
466
|
+
return function() {};
|
|
467
|
+
}
|
|
468
|
+
var original = source[name];
|
|
469
|
+
var wrapped = replacement(original);
|
|
470
|
+
if (typeof wrapped === "function") {
|
|
471
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
472
|
+
Object.defineProperties(wrapped, {
|
|
473
|
+
__rrweb_original__: {
|
|
474
|
+
enumerable: false,
|
|
475
|
+
value: original
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
source[name] = wrapped;
|
|
480
|
+
return function() {
|
|
481
|
+
source[name] = original;
|
|
482
|
+
};
|
|
483
|
+
} catch (e) {
|
|
484
|
+
return function() {};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
463
487
|
var index$1 = {
|
|
464
488
|
childNodes: childNodes$1,
|
|
465
489
|
parentNode: parentNode$1,
|
|
@@ -472,7 +496,8 @@ var index$1 = {
|
|
|
472
496
|
shadowRoot: shadowRoot$1,
|
|
473
497
|
querySelector: querySelector$1,
|
|
474
498
|
querySelectorAll: querySelectorAll$1,
|
|
475
|
-
mutationObserver: mutationObserverCtor$1
|
|
499
|
+
mutationObserver: mutationObserverCtor$1,
|
|
500
|
+
patch: patch$1
|
|
476
501
|
};
|
|
477
502
|
function isElement(n2) {
|
|
478
503
|
return n2.nodeType === n2.ELEMENT_NODE;
|
|
@@ -731,26 +756,82 @@ function absolutifyURLs(cssText, href) {
|
|
|
731
756
|
return "url(" + maybeQuote + stack.join("/") + maybeQuote + ")";
|
|
732
757
|
});
|
|
733
758
|
}
|
|
734
|
-
function normalizeCssString(cssText) {
|
|
735
|
-
|
|
759
|
+
function normalizeCssString(cssText, _testNoPxNorm) {
|
|
760
|
+
if (_testNoPxNorm === void 0) _testNoPxNorm = false;
|
|
761
|
+
if (_testNoPxNorm) {
|
|
762
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
|
|
763
|
+
} else {
|
|
764
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "").replace(/0px/g, "0");
|
|
765
|
+
}
|
|
736
766
|
}
|
|
737
|
-
function splitCssText(cssText, style) {
|
|
767
|
+
function splitCssText(cssText, style, _testNoPxNorm) {
|
|
768
|
+
if (_testNoPxNorm === void 0) _testNoPxNorm = false;
|
|
738
769
|
var childNodes2 = Array.from(style.childNodes);
|
|
739
770
|
var splits = [];
|
|
771
|
+
var iterCount = 0;
|
|
740
772
|
if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
|
|
741
|
-
var cssTextNorm = normalizeCssString(cssText);
|
|
773
|
+
var cssTextNorm = normalizeCssString(cssText, _testNoPxNorm);
|
|
774
|
+
var normFactor = cssTextNorm.length / cssText.length;
|
|
742
775
|
for(var i2 = 1; i2 < childNodes2.length; i2++){
|
|
743
776
|
if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") {
|
|
744
|
-
var textContentNorm = normalizeCssString(childNodes2[i2].textContent);
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
777
|
+
var textContentNorm = normalizeCssString(childNodes2[i2].textContent, _testNoPxNorm);
|
|
778
|
+
var jLimit = 100;
|
|
779
|
+
var j = 3;
|
|
780
|
+
for(; j < textContentNorm.length; j++){
|
|
781
|
+
if (// keep consuming css identifiers (to get a decent chunk more quickly)
|
|
782
|
+
textContentNorm[j].match(/[a-zA-Z0-9]/) || // substring needs to be unique to this section
|
|
783
|
+
textContentNorm.indexOf(textContentNorm.substring(0, j), 1) !== -1) {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
for(; j < textContentNorm.length; j++){
|
|
789
|
+
var startSubstring = textContentNorm.substring(0, j);
|
|
790
|
+
var cssNormSplits = cssTextNorm.split(startSubstring);
|
|
791
|
+
var splitNorm = -1;
|
|
792
|
+
if (cssNormSplits.length === 2) {
|
|
793
|
+
splitNorm = cssNormSplits[0].length;
|
|
794
|
+
} else if (cssNormSplits.length > 2 && cssNormSplits[0] === "" && childNodes2[i2 - 1].textContent !== "") {
|
|
795
|
+
splitNorm = cssTextNorm.indexOf(startSubstring, 1);
|
|
796
|
+
} else if (cssNormSplits.length === 1) {
|
|
797
|
+
startSubstring = startSubstring.substring(0, startSubstring.length - 1);
|
|
798
|
+
cssNormSplits = cssTextNorm.split(startSubstring);
|
|
799
|
+
if (cssNormSplits.length <= 1) {
|
|
800
|
+
splits.push(cssText);
|
|
801
|
+
return splits;
|
|
802
|
+
}
|
|
803
|
+
j = jLimit + 1;
|
|
804
|
+
} else if (j === textContentNorm.length - 1) {
|
|
805
|
+
splitNorm = cssTextNorm.indexOf(startSubstring);
|
|
806
|
+
}
|
|
807
|
+
if (cssNormSplits.length >= 2 && j > jLimit) {
|
|
808
|
+
var prevTextContent = childNodes2[i2 - 1].textContent;
|
|
809
|
+
if (prevTextContent && typeof prevTextContent === "string") {
|
|
810
|
+
var prevMinLength = normalizeCssString(prevTextContent).length;
|
|
811
|
+
splitNorm = cssTextNorm.indexOf(startSubstring, prevMinLength);
|
|
812
|
+
}
|
|
813
|
+
if (splitNorm === -1) {
|
|
814
|
+
splitNorm = cssNormSplits[0].length;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
if (splitNorm !== -1) {
|
|
818
|
+
var k = Math.floor(splitNorm / normFactor);
|
|
819
|
+
for(; k > 0 && k < cssText.length;){
|
|
820
|
+
iterCount += 1;
|
|
821
|
+
if (iterCount > 50 * childNodes2.length) {
|
|
822
|
+
splits.push(cssText);
|
|
823
|
+
return splits;
|
|
824
|
+
}
|
|
825
|
+
var normPart = normalizeCssString(cssText.substring(0, k), _testNoPxNorm);
|
|
826
|
+
if (normPart.length === splitNorm) {
|
|
751
827
|
splits.push(cssText.substring(0, k));
|
|
752
828
|
cssText = cssText.substring(k);
|
|
829
|
+
cssTextNorm = cssTextNorm.substring(splitNorm);
|
|
753
830
|
break;
|
|
831
|
+
} else if (normPart.length < splitNorm) {
|
|
832
|
+
k += Math.max(1, Math.floor((splitNorm - normPart.length) / normFactor));
|
|
833
|
+
} else {
|
|
834
|
+
k -= Math.max(1, Math.floor((normPart.length - splitNorm) * normFactor));
|
|
754
835
|
}
|
|
755
836
|
}
|
|
756
837
|
break;
|
|
@@ -1267,7 +1348,7 @@ function slimDOMExcluded(sn, slimDOMOptions) {
|
|
|
1267
1348
|
} else if (sn.type === NodeType$3.Element) {
|
|
1268
1349
|
if (slimDOMOptions.script && // script tag
|
|
1269
1350
|
(sn.tagName === "script" || // (module)preload link
|
|
1270
|
-
sn.tagName === "link" && (sn.attributes.rel === "preload"
|
|
1351
|
+
sn.tagName === "link" && (sn.attributes.rel === "preload" && sn.attributes.as === "script" || sn.attributes.rel === "modulepreload") || // prefetch link
|
|
1271
1352
|
sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
|
|
1272
1353
|
return true;
|
|
1273
1354
|
} else if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(/^msapplication-tile(image|color)$/) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
|
|
@@ -5764,11 +5845,16 @@ function getTagName(n2) {
|
|
|
5764
5845
|
function adaptCssForReplay(cssText, cache) {
|
|
5765
5846
|
var cachedStyle = cache == null ? void 0 : cache.stylesWithHoverClass.get(cssText);
|
|
5766
5847
|
if (cachedStyle) return cachedStyle;
|
|
5767
|
-
var
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5848
|
+
var result2 = cssText;
|
|
5849
|
+
try {
|
|
5850
|
+
var ast = postcss$1$1([
|
|
5851
|
+
mediaSelectorPlugin,
|
|
5852
|
+
pseudoClassPlugin
|
|
5853
|
+
]).process(cssText);
|
|
5854
|
+
result2 = ast.css;
|
|
5855
|
+
} catch (error) {
|
|
5856
|
+
console.warn("Failed to adapt css for replay", error);
|
|
5857
|
+
}
|
|
5772
5858
|
cache == null ? void 0 : cache.stylesWithHoverClass.set(cssText, result2);
|
|
5773
5859
|
return result2;
|
|
5774
5860
|
}
|
|
@@ -5790,11 +5876,39 @@ function applyCssSplits(n2, cssText, hackCss, cache) {
|
|
|
5790
5876
|
while(cssTextSplits.length > 1 && cssTextSplits.length > childTextNodes.length){
|
|
5791
5877
|
cssTextSplits.splice(-2, 2, cssTextSplits.slice(-2).join(""));
|
|
5792
5878
|
}
|
|
5879
|
+
var adaptedCss = "";
|
|
5880
|
+
if (hackCss) {
|
|
5881
|
+
adaptedCss = adaptCssForReplay(cssTextSplits.join(""), cache);
|
|
5882
|
+
}
|
|
5883
|
+
var startIndex = 0;
|
|
5793
5884
|
for(var i2 = 0; i2 < childTextNodes.length; i2++){
|
|
5885
|
+
if (i2 === cssTextSplits.length) {
|
|
5886
|
+
break;
|
|
5887
|
+
}
|
|
5794
5888
|
var childTextNode = childTextNodes[i2];
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5889
|
+
if (!hackCss) {
|
|
5890
|
+
childTextNode.textContent = cssTextSplits[i2];
|
|
5891
|
+
} else if (i2 < cssTextSplits.length - 1) {
|
|
5892
|
+
var endIndex = startIndex;
|
|
5893
|
+
var endSearch = cssTextSplits[i2 + 1].length;
|
|
5894
|
+
endSearch = Math.min(endSearch, 30);
|
|
5895
|
+
var found = false;
|
|
5896
|
+
for(; endSearch > 2; endSearch--){
|
|
5897
|
+
var searchBit = cssTextSplits[i2 + 1].substring(0, endSearch);
|
|
5898
|
+
var searchIndex = adaptedCss.substring(startIndex).indexOf(searchBit);
|
|
5899
|
+
found = searchIndex !== -1;
|
|
5900
|
+
if (found) {
|
|
5901
|
+
endIndex += searchIndex;
|
|
5902
|
+
break;
|
|
5903
|
+
}
|
|
5904
|
+
}
|
|
5905
|
+
if (!found) {
|
|
5906
|
+
endIndex += cssTextSplits[i2].length;
|
|
5907
|
+
}
|
|
5908
|
+
childTextNode.textContent = adaptedCss.substring(startIndex, endIndex);
|
|
5909
|
+
startIndex = endIndex;
|
|
5910
|
+
} else {
|
|
5911
|
+
childTextNode.textContent = adaptedCss.substring(startIndex);
|
|
5798
5912
|
}
|
|
5799
5913
|
}
|
|
5800
5914
|
}
|
|
@@ -5918,7 +6032,7 @@ function buildNode(n2, options) {
|
|
|
5918
6032
|
} else if (tagName === "meta" && n2.attributes["http-equiv"] === "Content-Security-Policy" && name === "content") {
|
|
5919
6033
|
node2.setAttribute("csp-content", value.toString());
|
|
5920
6034
|
continue;
|
|
5921
|
-
} else if (tagName === "link" && (n2.attributes.rel === "preload"
|
|
6035
|
+
} else if (tagName === "link" && (n2.attributes.rel === "preload" && n2.attributes.as === "script" || n2.attributes.rel === "modulepreload")) {} else if (tagName === "link" && n2.attributes.rel === "prefetch" && typeof n2.attributes.href === "string" && extractFileExtension(n2.attributes.href) === "js") {} else if (tagName === "img" && n2.attributes.srcset && n2.attributes.rr_dataURL) {
|
|
5922
6036
|
node2.setAttribute("rrweb-original-srcset", n2.attributes.srcset);
|
|
5923
6037
|
} else {
|
|
5924
6038
|
node2.setAttribute(name, value.toString());
|
|
@@ -11791,6 +11905,30 @@ function querySelectorAll(n2, selectors) {
|
|
|
11791
11905
|
function mutationObserverCtor() {
|
|
11792
11906
|
return getUntaintedPrototype("MutationObserver").constructor;
|
|
11793
11907
|
}
|
|
11908
|
+
function patch(source, name, replacement) {
|
|
11909
|
+
try {
|
|
11910
|
+
if (!(name in source)) {
|
|
11911
|
+
return function() {};
|
|
11912
|
+
}
|
|
11913
|
+
var original = source[name];
|
|
11914
|
+
var wrapped = replacement(original);
|
|
11915
|
+
if (typeof wrapped === "function") {
|
|
11916
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
11917
|
+
Object.defineProperties(wrapped, {
|
|
11918
|
+
__rrweb_original__: {
|
|
11919
|
+
enumerable: false,
|
|
11920
|
+
value: original
|
|
11921
|
+
}
|
|
11922
|
+
});
|
|
11923
|
+
}
|
|
11924
|
+
source[name] = wrapped;
|
|
11925
|
+
return function() {
|
|
11926
|
+
source[name] = original;
|
|
11927
|
+
};
|
|
11928
|
+
} catch (e) {
|
|
11929
|
+
return function() {};
|
|
11930
|
+
}
|
|
11931
|
+
}
|
|
11794
11932
|
var index = {
|
|
11795
11933
|
childNodes: childNodes,
|
|
11796
11934
|
parentNode: parentNode,
|
|
@@ -11803,7 +11941,8 @@ var index = {
|
|
|
11803
11941
|
shadowRoot: shadowRoot,
|
|
11804
11942
|
querySelector: querySelector,
|
|
11805
11943
|
querySelectorAll: querySelectorAll,
|
|
11806
|
-
mutationObserver: mutationObserverCtor
|
|
11944
|
+
mutationObserver: mutationObserverCtor,
|
|
11945
|
+
patch: patch
|
|
11807
11946
|
};
|
|
11808
11947
|
function on(type, fn, target) {
|
|
11809
11948
|
if (target === void 0) target = document;
|
|
@@ -11896,30 +12035,6 @@ function hookSetter(target, key, d, isRevoked, win) {
|
|
|
11896
12035
|
return hookSetter(target, key, original || {}, true);
|
|
11897
12036
|
};
|
|
11898
12037
|
}
|
|
11899
|
-
function patch(source, name, replacement) {
|
|
11900
|
-
try {
|
|
11901
|
-
if (!(name in source)) {
|
|
11902
|
-
return function() {};
|
|
11903
|
-
}
|
|
11904
|
-
var original = source[name];
|
|
11905
|
-
var wrapped = replacement(original);
|
|
11906
|
-
if (typeof wrapped === "function") {
|
|
11907
|
-
wrapped.prototype = wrapped.prototype || {};
|
|
11908
|
-
Object.defineProperties(wrapped, {
|
|
11909
|
-
__rrweb_original__: {
|
|
11910
|
-
enumerable: false,
|
|
11911
|
-
value: original
|
|
11912
|
-
}
|
|
11913
|
-
});
|
|
11914
|
-
}
|
|
11915
|
-
source[name] = wrapped;
|
|
11916
|
-
return function() {
|
|
11917
|
-
source[name] = original;
|
|
11918
|
-
};
|
|
11919
|
-
} catch (e) {
|
|
11920
|
-
return function() {};
|
|
11921
|
-
}
|
|
11922
|
-
}
|
|
11923
12038
|
var nowTimestamp = Date.now;
|
|
11924
12039
|
if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
|
|
11925
12040
|
nowTimestamp = function() {
|
|
@@ -12202,7 +12317,6 @@ var utils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty(
|
|
|
12202
12317
|
return nowTimestamp;
|
|
12203
12318
|
},
|
|
12204
12319
|
on: on,
|
|
12205
|
-
patch: patch,
|
|
12206
12320
|
polyfill: polyfill$1,
|
|
12207
12321
|
queueToResolveTrees: queueToResolveTrees,
|
|
12208
12322
|
shadowHostInDom: shadowHostInDom,
|
|
@@ -12659,9 +12773,17 @@ var MutationBuffer = /*#__PURE__*/ function() {
|
|
|
12659
12773
|
_this.attributes.push(item);
|
|
12660
12774
|
_this.attributeMap.set(textarea, item);
|
|
12661
12775
|
}
|
|
12662
|
-
|
|
12776
|
+
var value = Array.from(index.childNodes(textarea), function(cn) {
|
|
12663
12777
|
return index.textContent(cn) || "";
|
|
12664
12778
|
}).join("");
|
|
12779
|
+
item.attributes.value = maskInputValue({
|
|
12780
|
+
element: textarea,
|
|
12781
|
+
maskInputOptions: _this.maskInputOptions,
|
|
12782
|
+
tagName: textarea.tagName,
|
|
12783
|
+
type: getInputType(textarea),
|
|
12784
|
+
value: value,
|
|
12785
|
+
maskInputFn: _this.maskInputFn
|
|
12786
|
+
});
|
|
12665
12787
|
});
|
|
12666
12788
|
__publicField(this, "processMutation", function(m) {
|
|
12667
12789
|
if (isIgnored(m.target, _this.mirror, _this.slimDOMOptions)) {
|
|
@@ -15462,8 +15584,15 @@ function record(options) {
|
|
|
15462
15584
|
}, window));
|
|
15463
15585
|
}
|
|
15464
15586
|
return function() {
|
|
15465
|
-
handlers.forEach(function(
|
|
15466
|
-
|
|
15587
|
+
handlers.forEach(function(handler) {
|
|
15588
|
+
try {
|
|
15589
|
+
handler();
|
|
15590
|
+
} catch (error) {
|
|
15591
|
+
var msg = String(error).toLowerCase();
|
|
15592
|
+
if (!msg.includes("cross-origin")) {
|
|
15593
|
+
console.warn(error);
|
|
15594
|
+
}
|
|
15595
|
+
}
|
|
15467
15596
|
});
|
|
15468
15597
|
processedNodeManager.destroy();
|
|
15469
15598
|
recording = false;
|
|
@@ -17093,21 +17222,21 @@ var Replayer = /*#__PURE__*/ function() {
|
|
|
17093
17222
|
event: event
|
|
17094
17223
|
}
|
|
17095
17224
|
});
|
|
17096
|
-
var
|
|
17097
|
-
if (!_this.config.liveMode && event === _this.service.state.context.events[
|
|
17225
|
+
var lastIndex = _this.service.state.context.events.length - 1;
|
|
17226
|
+
if (!_this.config.liveMode && event === _this.service.state.context.events[lastIndex]) {
|
|
17098
17227
|
var finish = function() {
|
|
17099
|
-
if (
|
|
17228
|
+
if (lastIndex < _this.service.state.context.events.length - 1) {
|
|
17100
17229
|
return;
|
|
17101
17230
|
}
|
|
17102
17231
|
_this.backToNormal();
|
|
17103
17232
|
_this.service.send("END");
|
|
17104
17233
|
_this.emitter.emit(ReplayerEvents.Finish);
|
|
17105
17234
|
};
|
|
17106
|
-
var
|
|
17235
|
+
var finishBuffer = 50;
|
|
17107
17236
|
if (event.type === EventType.IncrementalSnapshot && event.data.source === IncrementalSource.MouseMove && event.data.positions.length) {
|
|
17108
|
-
|
|
17237
|
+
finishBuffer += Math.max(0, -event.data.positions[0].timeOffset);
|
|
17109
17238
|
}
|
|
17110
|
-
setTimeout(finish,
|
|
17239
|
+
setTimeout(finish, finishBuffer);
|
|
17111
17240
|
}
|
|
17112
17241
|
_this.emitter.emit(ReplayerEvents.EventCast, event);
|
|
17113
17242
|
};
|
|
@@ -18300,8 +18429,9 @@ var Replayer = /*#__PURE__*/ function() {
|
|
|
18300
18429
|
if (attributeName === "_cssText" && (target.nodeName === "LINK" || target.nodeName === "STYLE")) {
|
|
18301
18430
|
try {
|
|
18302
18431
|
var newSn = mirror2.getMeta(target);
|
|
18303
|
-
|
|
18304
|
-
|
|
18432
|
+
var newNode = buildNodeWithSN(_extends({}, newSn, {
|
|
18433
|
+
attributes: _extends({}, newSn.attributes, mutation.attributes)
|
|
18434
|
+
}), {
|
|
18305
18435
|
doc: target.ownerDocument,
|
|
18306
18436
|
// can be Document or RRDocument
|
|
18307
18437
|
mirror: mirror2,
|
|
@@ -18309,6 +18439,7 @@ var Replayer = /*#__PURE__*/ function() {
|
|
|
18309
18439
|
hackCss: true,
|
|
18310
18440
|
cache: _this.cache
|
|
18311
18441
|
});
|
|
18442
|
+
Object.assign(newSn.attributes, mutation.attributes);
|
|
18312
18443
|
var siblingNode = target.nextSibling;
|
|
18313
18444
|
var parentNode2 = target.parentNode;
|
|
18314
18445
|
if (newNode && parentNode2) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mixpanel-browser",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.69.0",
|
|
4
4
|
"description": "The official Mixpanel JavaScript browser client library",
|
|
5
5
|
"main": "dist/mixpanel.cjs.js",
|
|
6
6
|
"module": "dist/mixpanel.module.js",
|
|
@@ -23,6 +23,18 @@
|
|
|
23
23
|
"validate": "npm ls"
|
|
24
24
|
},
|
|
25
25
|
"types": "./src/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
"./src/loaders/loader-module-core": {
|
|
28
|
+
"types": "./src/index.d.ts",
|
|
29
|
+
"import": "./src/loaders/loader-module-core.js",
|
|
30
|
+
"require": "./src/loaders/loader-module-core.js"
|
|
31
|
+
},
|
|
32
|
+
"./src/loaders/loader-module-with-async-recorder": {
|
|
33
|
+
"types": "./src/index.d.ts",
|
|
34
|
+
"import": "./src/loaders/loader-module-with-async-recorder.js",
|
|
35
|
+
"require": "./src/loaders/loader-module-with-async-recorder.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
26
38
|
"repository": {
|
|
27
39
|
"type": "git",
|
|
28
40
|
"url": "https://github.com/mixpanel/mixpanel-js.git"
|
|
@@ -66,6 +78,6 @@
|
|
|
66
78
|
"webpack": "1.12.2"
|
|
67
79
|
},
|
|
68
80
|
"dependencies": {
|
|
69
|
-
"rrweb": "2.0.0-alpha.18"
|
|
81
|
+
"@mixpanel/rrweb": "2.0.0-alpha.18.1"
|
|
70
82
|
}
|
|
71
83
|
}
|
package/rollup.config.mjs
CHANGED
|
@@ -8,7 +8,7 @@ const COMPILED_RRWEB_PATH = 'build/rrweb-compiled.js';
|
|
|
8
8
|
|
|
9
9
|
const aliasRrweb = () => alias({
|
|
10
10
|
entries: [
|
|
11
|
-
{ find: 'rrweb', replacement: COMPILED_RRWEB_PATH },
|
|
11
|
+
{ find: '@mixpanel/rrweb', replacement: COMPILED_RRWEB_PATH },
|
|
12
12
|
]
|
|
13
13
|
});
|
|
14
14
|
|
|
@@ -24,7 +24,7 @@ const MINIFY = process.env.MINIFY || process.env.FULL;
|
|
|
24
24
|
const MAIN_BUILDS = [
|
|
25
25
|
// compile rrweb first to es5 with swc, we'll replace the import later on
|
|
26
26
|
{
|
|
27
|
-
'input': 'rrweb',
|
|
27
|
+
'input': '@mixpanel/rrweb',
|
|
28
28
|
'output': [
|
|
29
29
|
{
|
|
30
30
|
file: COMPILED_RRWEB_PATH,
|
package/src/config.js
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -198,6 +198,7 @@ export interface Config {
|
|
|
198
198
|
record_inline_images: boolean;
|
|
199
199
|
record_mask_text_class: string;
|
|
200
200
|
record_mask_text_selector: string;
|
|
201
|
+
record_min_ms: number;
|
|
201
202
|
record_max_ms: number;
|
|
202
203
|
record_sessions_percent: number;
|
|
203
204
|
record_canvas: boolean;
|
package/src/mixpanel-core.js
CHANGED
|
@@ -392,7 +392,9 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
392
392
|
* This is primarily used for session recording, where data must be isolated to the current tab.
|
|
393
393
|
*/
|
|
394
394
|
MixpanelLib.prototype._init_tab_id = function() {
|
|
395
|
-
if (
|
|
395
|
+
if (this.get_config('disable_persistence')) {
|
|
396
|
+
console.log('Tab ID initialization skipped due to disable_persistence config');
|
|
397
|
+
} else if (_.sessionStorage.is_supported()) {
|
|
396
398
|
try {
|
|
397
399
|
var key_suffix = this.get_config('name') + '_' + this.get_config('token');
|
|
398
400
|
var tab_id_key = 'mp_tab_id_' + key_suffix;
|
|
@@ -426,6 +428,11 @@ MixpanelLib.prototype.get_tab_id = function () {
|
|
|
426
428
|
};
|
|
427
429
|
|
|
428
430
|
MixpanelLib.prototype._should_load_recorder = function () {
|
|
431
|
+
if (this.get_config('disable_persistence')) {
|
|
432
|
+
console.log('Load recorder check skipped due to disable_persistence config');
|
|
433
|
+
return Promise.resolve(false);
|
|
434
|
+
}
|
|
435
|
+
|
|
429
436
|
var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
430
437
|
var tab_id = this.get_tab_id();
|
|
431
438
|
return recording_registry_idb.init()
|
package/src/recorder/recorder.js
CHANGED
|
@@ -8,12 +8,17 @@ import { isRecordingExpired } from './utils';
|
|
|
8
8
|
* Makes sure that only one tab can be recording at a time.
|
|
9
9
|
*/
|
|
10
10
|
var RecordingRegistry = function (options) {
|
|
11
|
+
/** @type {IDBStorageWrapper} */
|
|
11
12
|
this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
12
13
|
this.errorReporter = options.errorReporter;
|
|
13
14
|
this.mixpanelInstance = options.mixpanelInstance;
|
|
14
15
|
this.sharedLockStorage = options.sharedLockStorage;
|
|
15
16
|
};
|
|
16
17
|
|
|
18
|
+
RecordingRegistry.prototype.isPersistenceEnabled = function() {
|
|
19
|
+
return !this.mixpanelInstance.get_config('disable_persistence');
|
|
20
|
+
};
|
|
21
|
+
|
|
17
22
|
RecordingRegistry.prototype.handleError = function (err) {
|
|
18
23
|
this.errorReporter('IndexedDB error: ', err);
|
|
19
24
|
};
|
|
@@ -22,6 +27,10 @@ RecordingRegistry.prototype.handleError = function (err) {
|
|
|
22
27
|
* @param {import('./session-recording').SerializedRecording} serializedRecording
|
|
23
28
|
*/
|
|
24
29
|
RecordingRegistry.prototype.setActiveRecording = function (serializedRecording) {
|
|
30
|
+
if (!this.isPersistenceEnabled()) {
|
|
31
|
+
return Promise.resolve();
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
var tabId = serializedRecording['tabId'];
|
|
26
35
|
if (!tabId) {
|
|
27
36
|
console.warn('No tab ID is set, cannot persist recording metadata.');
|
|
@@ -39,6 +48,10 @@ RecordingRegistry.prototype.setActiveRecording = function (serializedRecording)
|
|
|
39
48
|
* @returns {Promise<import('./session-recording').SerializedRecording>}
|
|
40
49
|
*/
|
|
41
50
|
RecordingRegistry.prototype.getActiveRecording = function () {
|
|
51
|
+
if (!this.isPersistenceEnabled()) {
|
|
52
|
+
return Promise.resolve(null);
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
return this.idb.init()
|
|
43
56
|
.then(function () {
|
|
44
57
|
return this.idb.getItem(this.mixpanelInstance.get_tab_id());
|
|
@@ -50,8 +63,16 @@ RecordingRegistry.prototype.getActiveRecording = function () {
|
|
|
50
63
|
};
|
|
51
64
|
|
|
52
65
|
RecordingRegistry.prototype.clearActiveRecording = function () {
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
if (this.isPersistenceEnabled()) {
|
|
67
|
+
// mark recording as expired instead of deleting it in case the page unloads mid-flush and doesn't make it to ingestion.
|
|
68
|
+
// this will ensure the next pageload will flush the remaining events, but not try to continue the recording.
|
|
69
|
+
return this.markActiveRecordingExpired();
|
|
70
|
+
} else {
|
|
71
|
+
return this.deleteActiveRecording();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
RecordingRegistry.prototype.markActiveRecordingExpired = function () {
|
|
55
76
|
return this.getActiveRecording()
|
|
56
77
|
.then(function (serializedRecording) {
|
|
57
78
|
if (serializedRecording) {
|
|
@@ -62,11 +83,25 @@ RecordingRegistry.prototype.clearActiveRecording = function () {
|
|
|
62
83
|
.catch(this.handleError.bind(this));
|
|
63
84
|
};
|
|
64
85
|
|
|
86
|
+
RecordingRegistry.prototype.deleteActiveRecording = function () {
|
|
87
|
+
// avoid initializing IDB if this registry instance hasn't already written a recording
|
|
88
|
+
if (this.idb.isInitialized()) {
|
|
89
|
+
return this.idb.removeItem(this.mixpanelInstance.get_tab_id())
|
|
90
|
+
.catch(this.handleError.bind(this));
|
|
91
|
+
} else {
|
|
92
|
+
return Promise.resolve();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
65
96
|
/**
|
|
66
97
|
* Flush any inactive recordings from the registry to minimize data loss.
|
|
67
98
|
* The main idea here is that we can flush remaining rrweb events on the next page load if a tab is closed mid-batch.
|
|
68
99
|
*/
|
|
69
100
|
RecordingRegistry.prototype.flushInactiveRecordings = function () {
|
|
101
|
+
if (!this.isPersistenceEnabled()) {
|
|
102
|
+
return Promise.resolve([]);
|
|
103
|
+
}
|
|
104
|
+
|
|
70
105
|
return this.idb.init()
|
|
71
106
|
.then(function() {
|
|
72
107
|
return this.idb.getAll();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { window } from '../window';
|
|
2
|
-
import { IncrementalSource, EventType } from 'rrweb';
|
|
2
|
+
import { IncrementalSource, EventType } from '@mixpanel/rrweb';
|
|
3
3
|
import { MAX_RECORDING_MS, MAX_VALUE_FOR_MIN_RECORDING_MS, console_with_prefix, NOOP_FUNC, _, localStorageSupported} from '../utils'; // eslint-disable-line camelcase
|
|
4
4
|
import { IDBStorageWrapper, RECORDING_EVENTS_STORE_NAME } from '../storage/indexed-db';
|
|
5
5
|
import { addOptOutCheckMixpanelLib } from '../gdpr-utils';
|
|
@@ -101,10 +101,9 @@ var SessionRecording = function(options) {
|
|
|
101
101
|
|
|
102
102
|
// disable persistence if localStorage is not supported
|
|
103
103
|
// request-queue will automatically disable persistence if indexedDB fails to initialize
|
|
104
|
-
var usePersistence = localStorageSupported(options.sharedLockStorage, true);
|
|
104
|
+
var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
|
|
105
105
|
|
|
106
106
|
// each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
|
|
107
|
-
// this will be important when persistence is introduced
|
|
108
107
|
this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
|
|
109
108
|
this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
|
|
110
109
|
this.batcher = new RequestBatcher(this.batcherKey, {
|
package/src/request-queue.js
CHANGED
|
@@ -61,6 +61,10 @@ IDBStorageWrapper.prototype.init = function () {
|
|
|
61
61
|
});
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
+
IDBStorageWrapper.prototype.isInitialized = function () {
|
|
65
|
+
return !!this.dbPromise;
|
|
66
|
+
};
|
|
67
|
+
|
|
64
68
|
/**
|
|
65
69
|
* @param {IDBTransactionMode} mode
|
|
66
70
|
* @param {function(IDBObjectStore): void} storeCb
|
|
@@ -13,6 +13,10 @@ LocalStorageWrapper.prototype.init = function () {
|
|
|
13
13
|
return Promise.resolve();
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
LocalStorageWrapper.prototype.isInitialized = function () {
|
|
17
|
+
return true;
|
|
18
|
+
};
|
|
19
|
+
|
|
16
20
|
LocalStorageWrapper.prototype.setItem = function (key, value) {
|
|
17
21
|
return new Promise(_.bind(function (resolve, reject) {
|
|
18
22
|
try {
|
package/src/storage/wrapper.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* @typedef {Object} StorageWrapper
|
|
8
8
|
* @property {function():Promise<void>} init - Initializes the wrapper, async storage like IDB needs to create a table and upgrade if needed.
|
|
9
|
+
* @property {function():boolean} isInitialized - Checks if the storage is initialized.
|
|
9
10
|
* @property {function(string, any):Promise<void>} setItem - Sets an item in storage.
|
|
10
11
|
* @property {function(string):Promise<any>} getItem - Retrieves an item from storage.
|
|
11
12
|
* @property {function(string):Promise<void>} removeItem - Removes an item from storage.
|