@openreplay/tracker 4.0.1 → 4.1.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/cjs/app/guards.d.ts +1 -0
- package/cjs/app/guards.js +6 -1
- package/cjs/app/index.d.ts +1 -1
- package/cjs/app/index.js +14 -8
- package/cjs/app/messages.gen.js +1 -0
- package/cjs/app/nodes.d.ts +1 -1
- package/cjs/app/nodes.js +3 -5
- package/cjs/app/observer/iframe_observer.js +1 -0
- package/cjs/app/observer/iframe_offsets.d.ts +8 -0
- package/cjs/app/observer/iframe_offsets.js +59 -0
- package/cjs/app/observer/observer.js +4 -4
- package/cjs/app/observer/top_observer.d.ts +2 -4
- package/cjs/app/observer/top_observer.js +11 -21
- package/cjs/app/sanitizer.d.ts +10 -4
- package/cjs/app/sanitizer.js +33 -15
- package/cjs/app/session.js +1 -1
- package/cjs/common/messages.gen.js +1 -0
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +6 -6
- package/cjs/modules/constructedStyleSheets.d.ts +4 -0
- package/cjs/modules/{adoptedStyleSheets.js → constructedStyleSheets.js} +21 -20
- package/cjs/modules/cssrules.js +65 -18
- package/cjs/modules/img.js +27 -19
- package/cjs/modules/input.js +2 -2
- package/cjs/modules/mouse.js +11 -7
- package/cjs/modules/scroll.js +32 -12
- package/cjs/utils.d.ts +5 -3
- package/cjs/utils.js +18 -13
- package/lib/app/guards.d.ts +1 -0
- package/lib/app/guards.js +4 -0
- package/lib/app/index.d.ts +1 -1
- package/lib/app/index.js +14 -8
- package/lib/app/messages.gen.js +1 -0
- package/lib/app/nodes.d.ts +1 -1
- package/lib/app/nodes.js +3 -5
- package/lib/app/observer/iframe_observer.js +1 -0
- package/lib/app/observer/iframe_offsets.d.ts +8 -0
- package/lib/app/observer/iframe_offsets.js +56 -0
- package/lib/app/observer/observer.js +4 -4
- package/lib/app/observer/top_observer.d.ts +2 -4
- package/lib/app/observer/top_observer.js +11 -21
- package/lib/app/sanitizer.d.ts +10 -4
- package/lib/app/sanitizer.js +32 -15
- package/lib/app/session.js +1 -1
- package/lib/common/messages.gen.js +1 -0
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -5
- package/lib/modules/constructedStyleSheets.d.ts +4 -0
- package/lib/modules/{adoptedStyleSheets.js → constructedStyleSheets.js} +20 -21
- package/lib/modules/cssrules.js +67 -19
- package/lib/modules/img.js +28 -20
- package/lib/modules/input.js +3 -3
- package/lib/modules/mouse.js +11 -7
- package/lib/modules/scroll.js +33 -13
- package/lib/utils.d.ts +5 -3
- package/lib/utils.js +17 -11
- package/package.json +1 -1
- package/cjs/modules/adoptedStyleSheets.d.ts +0 -2
- package/lib/modules/adoptedStyleSheets.d.ts +0 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.styleSheetIDMap = exports.nextID = void 0;
|
|
3
4
|
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
4
5
|
const guards_js_1 = require("../app/guards.js");
|
|
5
6
|
function hasAdoptedSS(node) {
|
|
@@ -7,6 +8,13 @@ function hasAdoptedSS(node) {
|
|
|
7
8
|
// @ts-ignore
|
|
8
9
|
!!node.adoptedStyleSheets);
|
|
9
10
|
}
|
|
11
|
+
// TODO: incapsulate to be init-ed on-start and join with cssrules.ts under one folder
|
|
12
|
+
let _id = 0xf;
|
|
13
|
+
function nextID() {
|
|
14
|
+
return _id++;
|
|
15
|
+
}
|
|
16
|
+
exports.nextID = nextID;
|
|
17
|
+
exports.styleSheetIDMap = new Map();
|
|
10
18
|
function default_1(app) {
|
|
11
19
|
if (app === null) {
|
|
12
20
|
return;
|
|
@@ -18,10 +26,9 @@ function default_1(app) {
|
|
|
18
26
|
});
|
|
19
27
|
return;
|
|
20
28
|
}
|
|
21
|
-
let nextID = 0xf;
|
|
22
29
|
const styleSheetIDMap = new Map();
|
|
23
30
|
const adoptedStyleSheetsOwnings = new Map();
|
|
24
|
-
const
|
|
31
|
+
const sendAdoptedStyleSheetsUpdate = (root) => {
|
|
25
32
|
let nodeID = app.nodes.getID(root);
|
|
26
33
|
if (root === document) {
|
|
27
34
|
nodeID = 0; // main document doesn't have nodeID. ID count starts from the documentElement
|
|
@@ -39,7 +46,7 @@ function default_1(app) {
|
|
|
39
46
|
let sheetID = styleSheetIDMap.get(s);
|
|
40
47
|
const init = !sheetID;
|
|
41
48
|
if (!sheetID) {
|
|
42
|
-
sheetID =
|
|
49
|
+
sheetID = nextID();
|
|
43
50
|
}
|
|
44
51
|
nowOwning.push(sheetID);
|
|
45
52
|
if (!pastOwning.includes(sheetID)) {
|
|
@@ -65,12 +72,20 @@ function default_1(app) {
|
|
|
65
72
|
Object.defineProperty(prototype, 'adoptedStyleSheets', Object.assign(Object.assign({}, nativeAdoptedStyleSheetsDescriptor), { set: function (value) {
|
|
66
73
|
// @ts-ignore
|
|
67
74
|
const retVal = nativeAdoptedStyleSheetsDescriptor.set.call(this, value);
|
|
68
|
-
|
|
75
|
+
sendAdoptedStyleSheetsUpdate(this);
|
|
69
76
|
return retVal;
|
|
70
77
|
} }));
|
|
71
78
|
}
|
|
72
79
|
}
|
|
73
80
|
const patchContext = (context) => {
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
if (context.__openreplay_adpss_patched__) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
context.__openreplay_adpss_patched__ = true;
|
|
88
|
+
}
|
|
74
89
|
patchAdoptedStyleSheets(context.Document.prototype);
|
|
75
90
|
patchAdoptedStyleSheets(context.ShadowRoot.prototype);
|
|
76
91
|
//@ts-ignore TODO: configure ts (use necessary lib)
|
|
@@ -93,20 +108,6 @@ function default_1(app) {
|
|
|
93
108
|
}
|
|
94
109
|
return replaceSync.call(this, text);
|
|
95
110
|
};
|
|
96
|
-
context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
|
|
97
|
-
const sheetID = styleSheetIDMap.get(this);
|
|
98
|
-
if (sheetID) {
|
|
99
|
-
app.send((0, messages_gen_js_1.AdoptedSSInsertRuleURLBased)(sheetID, rule, index, app.getBaseHref()));
|
|
100
|
-
}
|
|
101
|
-
return insertRule.call(this, rule, index);
|
|
102
|
-
};
|
|
103
|
-
context.CSSStyleSheet.prototype.deleteRule = function (index) {
|
|
104
|
-
const sheetID = styleSheetIDMap.get(this);
|
|
105
|
-
if (sheetID) {
|
|
106
|
-
app.send((0, messages_gen_js_1.AdoptedSSDeleteRule)(sheetID, index));
|
|
107
|
-
}
|
|
108
|
-
return deleteRule.call(this, index);
|
|
109
|
-
};
|
|
110
111
|
};
|
|
111
112
|
patchContext(window);
|
|
112
113
|
app.observer.attachContextCallback(patchContext);
|
|
@@ -116,11 +117,11 @@ function default_1(app) {
|
|
|
116
117
|
});
|
|
117
118
|
// So far main Document is not triggered with nodeCallbacks
|
|
118
119
|
app.attachStartCallback(() => {
|
|
119
|
-
|
|
120
|
+
sendAdoptedStyleSheetsUpdate(document);
|
|
120
121
|
});
|
|
121
122
|
app.nodes.attachNodeCallback((node) => {
|
|
122
123
|
if (hasAdoptedSS(node)) {
|
|
123
|
-
|
|
124
|
+
sendAdoptedStyleSheetsUpdate(node);
|
|
124
125
|
}
|
|
125
126
|
});
|
|
126
127
|
}
|
package/cjs/modules/cssrules.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
4
4
|
const guards_js_1 = require("../app/guards.js");
|
|
5
|
+
const constructedStyleSheets_js_1 = require("./constructedStyleSheets.js");
|
|
5
6
|
function default_1(app) {
|
|
6
7
|
if (app === null) {
|
|
7
8
|
return;
|
|
@@ -10,42 +11,88 @@ function default_1(app) {
|
|
|
10
11
|
app.send((0, messages_gen_js_1.TechnicalInfo)('no_stylesheet_prototype_in_window', ''));
|
|
11
12
|
return;
|
|
12
13
|
}
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
14
|
+
const sendInserDeleteRule = app.safe((sheet, index, rule) => {
|
|
15
|
+
const sheetID = constructedStyleSheets_js_1.styleSheetIDMap.get(sheet);
|
|
16
|
+
if (!sheetID) {
|
|
17
|
+
// OK-case. Sheet haven't been registered yet. Rules will be sent on registration.
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (typeof rule === 'string') {
|
|
21
|
+
app.send((0, messages_gen_js_1.AdoptedSSInsertRuleURLBased)(sheetID, rule, index, app.getBaseHref()));
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
app.send((0, messages_gen_js_1.AdoptedSSDeleteRule)(sheetID, index));
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
// TODO: proper rule insertion/removal (how?)
|
|
28
|
+
const sendReplaceGroupingRule = app.safe((rule) => {
|
|
29
|
+
let topmostRule = rule;
|
|
30
|
+
while (topmostRule.parentRule) {
|
|
31
|
+
topmostRule = topmostRule.parentRule;
|
|
32
|
+
}
|
|
33
|
+
const sheet = topmostRule.parentStyleSheet;
|
|
34
|
+
if (!sheet) {
|
|
35
|
+
app.debug.warn('No parent StyleSheet found for', topmostRule, rule);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const sheetID = constructedStyleSheets_js_1.styleSheetIDMap.get(sheet);
|
|
39
|
+
if (!sheetID) {
|
|
40
|
+
app.debug.warn('No sheedID found for', sheet, constructedStyleSheets_js_1.styleSheetIDMap);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const cssText = topmostRule.cssText;
|
|
44
|
+
const ruleList = sheet.cssRules;
|
|
45
|
+
const idx = Array.from(ruleList).indexOf(topmostRule);
|
|
46
|
+
if (idx >= 0) {
|
|
47
|
+
app.send((0, messages_gen_js_1.AdoptedSSInsertRuleURLBased)(sheetID, cssText, idx, app.getBaseHref()));
|
|
48
|
+
app.send((0, messages_gen_js_1.AdoptedSSDeleteRule)(sheetID, idx + 1)); // Remove previous clone
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
app.debug.warn('Rule index not found in', sheet, topmostRule);
|
|
52
|
+
}
|
|
25
53
|
});
|
|
26
54
|
const patchContext = (context) => {
|
|
27
55
|
const { insertRule, deleteRule } = context.CSSStyleSheet.prototype;
|
|
56
|
+
const { insertRule: groupInsertRule, deleteRule: groupDeleteRule } = context.CSSGroupingRule.prototype;
|
|
28
57
|
context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
|
|
29
|
-
|
|
58
|
+
sendInserDeleteRule(this, index, rule);
|
|
30
59
|
return insertRule.call(this, rule, index);
|
|
31
60
|
};
|
|
32
61
|
context.CSSStyleSheet.prototype.deleteRule = function (index) {
|
|
33
|
-
|
|
62
|
+
sendInserDeleteRule(this, index);
|
|
34
63
|
return deleteRule.call(this, index);
|
|
35
64
|
};
|
|
65
|
+
context.CSSGroupingRule.prototype.insertRule = function (rule, index = 0) {
|
|
66
|
+
const result = groupInsertRule.call(this, rule, index);
|
|
67
|
+
sendReplaceGroupingRule(this);
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
context.CSSGroupingRule.prototype.deleteRule = function (index = 0) {
|
|
71
|
+
const result = groupDeleteRule.call(this, index);
|
|
72
|
+
sendReplaceGroupingRule(this);
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
36
75
|
};
|
|
37
76
|
patchContext(window);
|
|
38
77
|
app.observer.attachContextCallback(patchContext);
|
|
39
78
|
app.nodes.attachNodeCallback((node) => {
|
|
40
|
-
if (!(0, guards_js_1.hasTag)(node, 'STYLE') || !node.sheet) {
|
|
79
|
+
if (!((0, guards_js_1.hasTag)(node, 'STYLE') || (0, guards_js_1.hasTag)(node, 'style')) || !node.sheet) {
|
|
41
80
|
return;
|
|
42
81
|
}
|
|
43
82
|
if (node.textContent !== null && node.textContent.trim().length > 0) {
|
|
44
|
-
return; //
|
|
83
|
+
return; // Non-virtual styles captured by the observer as a text
|
|
84
|
+
}
|
|
85
|
+
const nodeID = app.nodes.getID(node);
|
|
86
|
+
if (!nodeID) {
|
|
87
|
+
return;
|
|
45
88
|
}
|
|
46
|
-
const
|
|
89
|
+
const sheet = node.sheet;
|
|
90
|
+
const sheetID = (0, constructedStyleSheets_js_1.nextID)();
|
|
91
|
+
constructedStyleSheets_js_1.styleSheetIDMap.set(sheet, sheetID);
|
|
92
|
+
app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
|
|
93
|
+
const rules = sheet.cssRules;
|
|
47
94
|
for (let i = 0; i < rules.length; i++) {
|
|
48
|
-
|
|
95
|
+
sendInserDeleteRule(sheet, i, rules[i].cssText);
|
|
49
96
|
}
|
|
50
97
|
});
|
|
51
98
|
}
|
package/cjs/modules/img.js
CHANGED
|
@@ -10,7 +10,7 @@ function resolveURL(url, location = document.location) {
|
|
|
10
10
|
}
|
|
11
11
|
else if (url.startsWith('http://') ||
|
|
12
12
|
url.startsWith('https://') ||
|
|
13
|
-
url.startsWith('data:') // any other possible value here?
|
|
13
|
+
url.startsWith('data:') // any other possible value here? https://bugzilla.mozilla.org/show_bug.cgi?id=1758035
|
|
14
14
|
) {
|
|
15
15
|
return url;
|
|
16
16
|
}
|
|
@@ -18,6 +18,10 @@ function resolveURL(url, location = document.location) {
|
|
|
18
18
|
return location.origin + location.pathname + url;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=1607081
|
|
22
|
+
function isSVGInFireFox(url) {
|
|
23
|
+
return utils_js_1.IS_FIREFOX && (url.startsWith('data:image/svg+xml') || url.match(/.svg$|/i));
|
|
24
|
+
}
|
|
21
25
|
const PLACEHOLDER_SRC = 'https://static.openreplay.com/tracker/placeholder.jpeg';
|
|
22
26
|
function default_1(app) {
|
|
23
27
|
function sendPlaceholder(id, node) {
|
|
@@ -42,30 +46,34 @@ function default_1(app) {
|
|
|
42
46
|
app.send((0, messages_gen_js_1.SetNodeAttribute)(id, 'srcset', resolvedSrcset));
|
|
43
47
|
};
|
|
44
48
|
const sendSrc = function (id, img) {
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
if (img.src.length > utils_js_1.MAX_STR_LEN) {
|
|
50
|
+
sendPlaceholder(id, img);
|
|
51
|
+
}
|
|
52
|
+
app.send((0, messages_gen_js_1.SetNodeAttributeURLBased)(id, 'src', img.src, app.getBaseHref()));
|
|
47
53
|
};
|
|
48
|
-
const
|
|
49
|
-
const
|
|
54
|
+
const sendImgError = app.safe(function (img) {
|
|
55
|
+
const resolvedSrc = resolveURL(img.src || ''); // Src type is null sometimes. - is it true?
|
|
56
|
+
if ((0, utils_js_1.isURL)(resolvedSrc)) {
|
|
57
|
+
app.send((0, messages_gen_js_1.ResourceTiming)((0, utils_js_1.timestamp)(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const sendImgAttrs = app.safe(function (img) {
|
|
61
|
+
const id = app.nodes.getID(img);
|
|
50
62
|
if (id === undefined) {
|
|
51
63
|
return;
|
|
52
64
|
}
|
|
53
|
-
|
|
54
|
-
if (!complete) {
|
|
65
|
+
if (!img.complete) {
|
|
55
66
|
return;
|
|
56
67
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if ((0, utils_js_1.isURL)(resolvedSrc)) {
|
|
60
|
-
app.send((0, messages_gen_js_1.ResourceTiming)((0, utils_js_1.timestamp)(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
|
|
61
|
-
}
|
|
68
|
+
if (img.naturalHeight === 0 && img.naturalWidth === 0 && !isSVGInFireFox(img.src)) {
|
|
69
|
+
sendImgError(img);
|
|
62
70
|
}
|
|
63
|
-
else if (
|
|
64
|
-
sendPlaceholder(id,
|
|
71
|
+
else if (app.sanitizer.isHidden(id) || app.sanitizer.isObscured(id)) {
|
|
72
|
+
sendPlaceholder(id, img);
|
|
65
73
|
}
|
|
66
74
|
else {
|
|
67
|
-
sendSrc(id,
|
|
68
|
-
sendSrcset(id,
|
|
75
|
+
sendSrc(id, img);
|
|
76
|
+
sendSrcset(id, img);
|
|
69
77
|
}
|
|
70
78
|
});
|
|
71
79
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -92,9 +100,9 @@ function default_1(app) {
|
|
|
92
100
|
if (!(0, guards_js_1.hasTag)(node, 'IMG')) {
|
|
93
101
|
return;
|
|
94
102
|
}
|
|
95
|
-
app.nodes.
|
|
96
|
-
app.nodes.
|
|
97
|
-
sendImgAttrs
|
|
103
|
+
app.nodes.attachNodeListener(node, 'error', () => sendImgError(node));
|
|
104
|
+
app.nodes.attachNodeListener(node, 'load', () => sendImgAttrs(node));
|
|
105
|
+
sendImgAttrs(node);
|
|
98
106
|
observer.observe(node, { attributes: true, attributeFilter: ['src', 'srcset'] });
|
|
99
107
|
});
|
|
100
108
|
}
|
package/cjs/modules/input.js
CHANGED
|
@@ -80,10 +80,10 @@ function default_1(app, opts) {
|
|
|
80
80
|
function sendInputValue(id, node) {
|
|
81
81
|
let value = node.value;
|
|
82
82
|
let inputMode = options.defaultInputMode;
|
|
83
|
-
if (node.type === 'password' ||
|
|
83
|
+
if (node.type === 'password' || app.sanitizer.isHidden(id)) {
|
|
84
84
|
inputMode = 2 /* Hidden */;
|
|
85
85
|
}
|
|
86
|
-
else if (
|
|
86
|
+
else if (app.sanitizer.isObscured(id) ||
|
|
87
87
|
(inputMode === 0 /* Plain */ &&
|
|
88
88
|
((options.obscureInputNumbers && node.type !== 'date' && /\d\d\d\d/.test(value)) ||
|
|
89
89
|
(options.obscureInputDates && node.type === 'date') ||
|
package/cjs/modules/mouse.js
CHANGED
|
@@ -98,11 +98,13 @@ function default_1(app) {
|
|
|
98
98
|
let mousePositionChanged = false;
|
|
99
99
|
let mouseTarget = null;
|
|
100
100
|
let mouseTargetTime = 0;
|
|
101
|
+
let selectorMap = {};
|
|
101
102
|
app.attachStopCallback(() => {
|
|
102
103
|
mousePositionX = -1;
|
|
103
104
|
mousePositionY = -1;
|
|
104
105
|
mousePositionChanged = false;
|
|
105
106
|
mouseTarget = null;
|
|
107
|
+
selectorMap = {};
|
|
106
108
|
});
|
|
107
109
|
const sendMouseMove = () => {
|
|
108
110
|
if (mousePositionChanged) {
|
|
@@ -110,25 +112,27 @@ function default_1(app) {
|
|
|
110
112
|
mousePositionChanged = false;
|
|
111
113
|
}
|
|
112
114
|
};
|
|
113
|
-
const patchDocument = (document) => {
|
|
114
|
-
const selectorMap = {};
|
|
115
|
+
const patchDocument = (document, topframe = false) => {
|
|
115
116
|
function getSelector(id, target) {
|
|
116
117
|
return (selectorMap[id] = selectorMap[id] || _getSelector(target, document));
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
+
const attachListener = topframe
|
|
120
|
+
? app.attachEventListener.bind(app) // attached/removed on start/stop
|
|
121
|
+
: app.nodes.attachNodeListener.bind(app.nodes); // attached/removed on node register/unregister
|
|
122
|
+
attachListener(document.documentElement, 'mouseover', (e) => {
|
|
119
123
|
const target = getTarget(e.target, document);
|
|
120
124
|
if (target !== mouseTarget) {
|
|
121
125
|
mouseTarget = target;
|
|
122
126
|
mouseTargetTime = performance.now();
|
|
123
127
|
}
|
|
124
128
|
});
|
|
125
|
-
|
|
126
|
-
const
|
|
129
|
+
attachListener(document, 'mousemove', (e) => {
|
|
130
|
+
const [left, top] = app.observer.getDocumentOffset(document); // MBTODO?: document-id related message
|
|
127
131
|
mousePositionX = e.clientX + left;
|
|
128
132
|
mousePositionY = e.clientY + top;
|
|
129
133
|
mousePositionChanged = true;
|
|
130
134
|
}, false);
|
|
131
|
-
|
|
135
|
+
attachListener(document, 'click', (e) => {
|
|
132
136
|
const target = getTarget(e.target, document);
|
|
133
137
|
if ((!e.clientX && !e.clientY) || target === null) {
|
|
134
138
|
return;
|
|
@@ -146,7 +150,7 @@ function default_1(app) {
|
|
|
146
150
|
patchDocument(node);
|
|
147
151
|
}
|
|
148
152
|
});
|
|
149
|
-
patchDocument(document);
|
|
153
|
+
patchDocument(document, true);
|
|
150
154
|
app.ticker.attach(sendMouseMove, 10);
|
|
151
155
|
}
|
|
152
156
|
exports.default = default_1;
|
package/cjs/modules/scroll.js
CHANGED
|
@@ -2,21 +2,34 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
4
4
|
const guards_js_1 = require("../app/guards.js");
|
|
5
|
+
function getDocumentScroll(doc) {
|
|
6
|
+
const win = doc.defaultView;
|
|
7
|
+
return [
|
|
8
|
+
(win && win.pageXOffset) ||
|
|
9
|
+
(doc.documentElement && doc.documentElement.scrollLeft) ||
|
|
10
|
+
(doc.body && doc.body.scrollLeft) ||
|
|
11
|
+
0,
|
|
12
|
+
(win && win.pageYOffset) ||
|
|
13
|
+
(doc.documentElement && doc.documentElement.scrollTop) ||
|
|
14
|
+
(doc.body && doc.body.scrollTop) ||
|
|
15
|
+
0,
|
|
16
|
+
];
|
|
17
|
+
}
|
|
5
18
|
function default_1(app) {
|
|
6
19
|
let documentScroll = false;
|
|
7
20
|
const nodeScroll = new Map();
|
|
8
21
|
function setNodeScroll(target) {
|
|
9
|
-
if (
|
|
22
|
+
if (!(0, guards_js_1.isNode)(target)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if ((0, guards_js_1.isElementNode)(target)) {
|
|
10
26
|
nodeScroll.set(target, [target.scrollLeft, target.scrollTop]);
|
|
11
27
|
}
|
|
28
|
+
if ((0, guards_js_1.isDocument)(target)) {
|
|
29
|
+
nodeScroll.set(target, getDocumentScroll(target));
|
|
30
|
+
}
|
|
12
31
|
}
|
|
13
|
-
const sendSetViewportScroll = app.safe(() => app.send((0, messages_gen_js_1.SetViewportScroll)(
|
|
14
|
-
(document.documentElement && document.documentElement.scrollLeft) ||
|
|
15
|
-
(document.body && document.body.scrollLeft) ||
|
|
16
|
-
0, window.pageYOffset ||
|
|
17
|
-
(document.documentElement && document.documentElement.scrollTop) ||
|
|
18
|
-
(document.body && document.body.scrollTop) ||
|
|
19
|
-
0)));
|
|
32
|
+
const sendSetViewportScroll = app.safe(() => app.send((0, messages_gen_js_1.SetViewportScroll)(...getDocumentScroll(document))));
|
|
20
33
|
const sendSetNodeScroll = app.safe((s, node) => {
|
|
21
34
|
const id = app.nodes.getID(node);
|
|
22
35
|
if (id !== undefined) {
|
|
@@ -29,12 +42,19 @@ function default_1(app) {
|
|
|
29
42
|
nodeScroll.clear();
|
|
30
43
|
});
|
|
31
44
|
app.nodes.attachNodeCallback((node, isStart) => {
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
// MBTODO: iterate over all the nodes on start instead of using isStart hack
|
|
46
|
+
if (isStart) {
|
|
47
|
+
if ((0, guards_js_1.isElementNode)(node) && node.scrollLeft + node.scrollTop > 0) {
|
|
48
|
+
nodeScroll.set(node, [node.scrollLeft, node.scrollTop]);
|
|
49
|
+
}
|
|
50
|
+
else if ((0, guards_js_1.isDocument)(node)) {
|
|
51
|
+
// DRY somehow?
|
|
52
|
+
nodeScroll.set(node, getDocumentScroll(node));
|
|
53
|
+
}
|
|
34
54
|
}
|
|
35
|
-
|
|
55
|
+
if ((0, guards_js_1.isRootNode)(node)) {
|
|
36
56
|
// scroll is not-composed event (https://javascript.info/shadow-dom-events)
|
|
37
|
-
app.
|
|
57
|
+
app.nodes.attachNodeListener(node, 'scroll', (e) => {
|
|
38
58
|
setNodeScroll(e.target);
|
|
39
59
|
});
|
|
40
60
|
}
|
package/cjs/utils.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const IN_BROWSER: boolean;
|
|
2
|
+
export declare const IS_FIREFOX: false | RegExpMatchArray | null;
|
|
3
|
+
export declare const MAX_STR_LEN = 100000;
|
|
4
|
+
export declare const timestamp: () => number;
|
|
2
5
|
export declare const stars: (str: string) => string;
|
|
3
6
|
export declare function normSpaces(str: string): string;
|
|
4
7
|
export declare function isURL(s: string): boolean;
|
|
5
|
-
export declare const IN_BROWSER: boolean;
|
|
6
8
|
export declare const DOCS_HOST = "https://docs.openreplay.com";
|
|
7
9
|
export declare function deprecationWarn(nameOfFeature: string, useInstead: string, docsPath?: string): void;
|
|
8
10
|
export declare function getLabelAttribute(e: Element): string | null;
|
|
9
|
-
export declare function hasOpenreplayAttribute(e: Element,
|
|
11
|
+
export declare function hasOpenreplayAttribute(e: Element, attr: string): boolean;
|
package/cjs/utils.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.
|
|
3
|
+
exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.timestamp = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
|
|
4
|
+
const DEPRECATED_ATTRS = { htmlmasked: 'hidden', masked: 'obscured' };
|
|
5
|
+
exports.IN_BROWSER = !(typeof window === 'undefined');
|
|
6
|
+
exports.IS_FIREFOX = exports.IN_BROWSER && navigator.userAgent.match(/firefox|fxios/i);
|
|
7
|
+
exports.MAX_STR_LEN = 1e5;
|
|
8
|
+
const navigationStart = (exports.IN_BROWSER && performance.timing.navigationStart) || performance.timeOrigin;
|
|
9
|
+
// performance.now() is buggy in some browsers
|
|
10
|
+
exports.timestamp = exports.IN_BROWSER && performance.now() && navigationStart
|
|
11
|
+
? () => Math.round(performance.now() + navigationStart)
|
|
12
|
+
: () => Date.now();
|
|
8
13
|
exports.stars = 'repeat' in String.prototype
|
|
9
14
|
? (str) => '*'.repeat(str.length)
|
|
10
15
|
: (str) => str.replace(/./g, '*');
|
|
@@ -17,7 +22,6 @@ function isURL(s) {
|
|
|
17
22
|
return s.startsWith('https://') || s.startsWith('http://');
|
|
18
23
|
}
|
|
19
24
|
exports.isURL = isURL;
|
|
20
|
-
exports.IN_BROWSER = !(typeof window === 'undefined');
|
|
21
25
|
// TODO: JOIN IT WITH LOGGER somehow (use logging decorators?); Don't forget about index.js loggin when there is no logger instance.
|
|
22
26
|
exports.DOCS_HOST = 'https://docs.openreplay.com';
|
|
23
27
|
const warnedFeatures = {};
|
|
@@ -41,14 +45,15 @@ function getLabelAttribute(e) {
|
|
|
41
45
|
return value;
|
|
42
46
|
}
|
|
43
47
|
exports.getLabelAttribute = getLabelAttribute;
|
|
44
|
-
function hasOpenreplayAttribute(e,
|
|
45
|
-
const newName = `data-openreplay-${
|
|
48
|
+
function hasOpenreplayAttribute(e, attr) {
|
|
49
|
+
const newName = `data-openreplay-${attr}`;
|
|
46
50
|
if (e.hasAttribute(newName)) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
if (DEPRECATED_ATTRS[attr]) {
|
|
53
|
+
deprecationWarn(`"${newName}" attribute`,
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
`"${DEPRECATED_ATTRS[attr]}" attribute`, '/installation/sanitize-data');
|
|
56
|
+
}
|
|
52
57
|
return true;
|
|
53
58
|
}
|
|
54
59
|
return false;
|
package/lib/app/guards.d.ts
CHANGED
package/lib/app/guards.js
CHANGED
package/lib/app/index.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export default class App {
|
|
|
77
77
|
private _debug;
|
|
78
78
|
send(message: Message, urgent?: boolean): void;
|
|
79
79
|
private commit;
|
|
80
|
-
safe<T extends (...args: any[]) => void>(fn: T): T;
|
|
80
|
+
safe<T extends (this: any, ...args: any[]) => void>(fn: T): T;
|
|
81
81
|
attachCommitCallback(cb: CommitCallback): void;
|
|
82
82
|
attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
|
|
83
83
|
attachStopCallback(cb: () => any, useSafe?: boolean): void;
|
package/lib/app/index.js
CHANGED
|
@@ -71,17 +71,17 @@ export default class App {
|
|
|
71
71
|
this.session.applySessionHash(sessionToken);
|
|
72
72
|
}
|
|
73
73
|
try {
|
|
74
|
-
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==
|
|
74
|
+
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==f&&(clearInterval(f),f=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){self.postMessage("restart"),a()}n.NotActive;let c,f=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return u(),void a();if(Array.isArray(i)){if(!h)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const t=h;i.forEach(i=>{55===i[0]&&(i[1]?c=setTimeout(()=>o(),18e5):clearTimeout(c)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{o()},()=>{self.postMessage("failed"),a()},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===f&&(f=setInterval(u,1e4)),n.Active;if("auth"===i.type){if(!r)throw new Error("WebWorker: sender not initialised. Received auth.");if(!h)throw new Error("WebWorker: writer not initialised. Received auth.");return r.authorise(i.token),void(i.beaconSizeLimit&&h.setBeaconSizeLimit(i.beaconSizeLimit))}}}else u()};'], { type: 'text/javascript' })));
|
|
75
75
|
this.worker.onerror = (e) => {
|
|
76
76
|
this._debug('webworker_error', e);
|
|
77
77
|
};
|
|
78
78
|
this.worker.onmessage = ({ data }) => {
|
|
79
79
|
if (data === 'failed') {
|
|
80
|
-
this.stop();
|
|
80
|
+
this.stop(false);
|
|
81
81
|
this._debug('worker_failed', {}); // add context (from worker)
|
|
82
82
|
}
|
|
83
83
|
else if (data === 'restart') {
|
|
84
|
-
this.stop();
|
|
84
|
+
this.stop(false);
|
|
85
85
|
this.start({ forceNew: true });
|
|
86
86
|
}
|
|
87
87
|
};
|
|
@@ -150,8 +150,6 @@ export default class App {
|
|
|
150
150
|
}; // TODO: correct typing
|
|
151
151
|
}
|
|
152
152
|
attachCommitCallback(cb) {
|
|
153
|
-
// TODO!: what if start callback added when activityState === Active ?
|
|
154
|
-
// For example - attachEventListener() called during dynamic <iframe> appearance
|
|
155
153
|
this.commitCallbacks.push(cb);
|
|
156
154
|
}
|
|
157
155
|
attachStartCallback(cb, useSafe = false) {
|
|
@@ -166,6 +164,7 @@ export default class App {
|
|
|
166
164
|
}
|
|
167
165
|
this.stopCallbacks.push(cb);
|
|
168
166
|
}
|
|
167
|
+
// Use app.nodes.attachNodeListener for registered nodes instead
|
|
169
168
|
attachEventListener(target, type, listener, useSafe = true, useCapture = true) {
|
|
170
169
|
if (useSafe) {
|
|
171
170
|
listener = this.safe(listener);
|
|
@@ -288,14 +287,15 @@ export default class App {
|
|
|
288
287
|
});
|
|
289
288
|
const sReset = this.sessionStorage.getItem(this.options.session_reset_key);
|
|
290
289
|
this.sessionStorage.removeItem(this.options.session_reset_key);
|
|
290
|
+
const shouldReset = startOpts.forceNew || sReset !== null;
|
|
291
291
|
return window
|
|
292
292
|
.fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
293
293
|
method: 'POST',
|
|
294
294
|
headers: {
|
|
295
295
|
'Content-Type': 'application/json',
|
|
296
296
|
},
|
|
297
|
-
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: this.session.getSessionToken(), deviceMemory,
|
|
298
|
-
jsHeapSizeLimit
|
|
297
|
+
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: shouldReset ? undefined : this.session.getSessionToken(), deviceMemory,
|
|
298
|
+
jsHeapSizeLimit })),
|
|
299
299
|
})
|
|
300
300
|
.then((r) => {
|
|
301
301
|
if (r.status === 200) {
|
|
@@ -313,6 +313,9 @@ export default class App {
|
|
|
313
313
|
if (!this.worker) {
|
|
314
314
|
return Promise.reject('no worker found after start request (this might not happen)');
|
|
315
315
|
}
|
|
316
|
+
if (this.activityState === ActivityState.NotActive) {
|
|
317
|
+
return Promise.reject('Tracker stopped during authorisation');
|
|
318
|
+
}
|
|
316
319
|
const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
|
|
317
320
|
} = r;
|
|
318
321
|
if (typeof token !== 'string' ||
|
|
@@ -322,9 +325,12 @@ export default class App {
|
|
|
322
325
|
(typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
|
|
323
326
|
return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
|
|
324
327
|
}
|
|
328
|
+
if (sessionID !== this.session.getInfo().sessionID) {
|
|
329
|
+
this.session.reset();
|
|
330
|
+
}
|
|
325
331
|
this.session.setSessionToken(token);
|
|
326
|
-
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
327
332
|
this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
|
|
333
|
+
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
328
334
|
const startWorkerMsg = {
|
|
329
335
|
type: 'auth',
|
|
330
336
|
token,
|