@openreplay/tracker 4.0.0 → 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 +15 -9
- package/cjs/app/messages.gen.d.ts +1 -0
- package/cjs/app/messages.gen.js +10 -1
- 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.d.ts +8 -2
- package/cjs/common/messages.gen.js +1 -0
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +7 -7
- 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 +15 -9
- package/lib/app/messages.gen.d.ts +1 -0
- package/lib/app/messages.gen.js +8 -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.d.ts +8 -2
- 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 +5 -6
- 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
package/cjs/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Messages = exports.App = void 0;
|
|
3
|
+
exports.SanitizeLevel = exports.Messages = exports.App = void 0;
|
|
4
4
|
const index_js_1 = require("./app/index.js");
|
|
5
5
|
var index_js_2 = require("./app/index.js");
|
|
6
6
|
Object.defineProperty(exports, "App", { enumerable: true, get: function () { return index_js_2.default; } });
|
|
7
7
|
const messages_gen_js_1 = require("./app/messages.gen.js");
|
|
8
8
|
const _Messages = require("./app/messages.gen.js");
|
|
9
9
|
exports.Messages = _Messages;
|
|
10
|
+
var sanitizer_js_1 = require("./app/sanitizer.js");
|
|
11
|
+
Object.defineProperty(exports, "SanitizeLevel", { enumerable: true, get: function () { return sanitizer_js_1.SanitizeLevel; } });
|
|
10
12
|
const connection_js_1 = require("./modules/connection.js");
|
|
11
13
|
const console_js_1 = require("./modules/console.js");
|
|
12
14
|
const exception_js_1 = require("./modules/exception.js");
|
|
@@ -18,7 +20,7 @@ const performance_js_1 = require("./modules/performance.js");
|
|
|
18
20
|
const scroll_js_1 = require("./modules/scroll.js");
|
|
19
21
|
const viewport_js_1 = require("./modules/viewport.js");
|
|
20
22
|
const cssrules_js_1 = require("./modules/cssrules.js");
|
|
21
|
-
const
|
|
23
|
+
const constructedStyleSheets_js_1 = require("./modules/constructedStyleSheets.js");
|
|
22
24
|
const utils_js_1 = require("./utils.js");
|
|
23
25
|
const DOCS_SETUP = '/installation/setup-or';
|
|
24
26
|
function processOptions(obj) {
|
|
@@ -97,7 +99,7 @@ class API {
|
|
|
97
99
|
if (app !== null) {
|
|
98
100
|
(0, viewport_js_1.default)(app);
|
|
99
101
|
(0, cssrules_js_1.default)(app);
|
|
100
|
-
(0,
|
|
102
|
+
(0, constructedStyleSheets_js_1.default)(app);
|
|
101
103
|
(0, connection_js_1.default)(app);
|
|
102
104
|
(0, console_js_1.default)(app, options);
|
|
103
105
|
(0, exception_js_1.default)(app, options);
|
|
@@ -131,7 +133,7 @@ class API {
|
|
|
131
133
|
// no-cors issue only with text/plain or not-set Content-Type
|
|
132
134
|
// req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
|
133
135
|
req.send(JSON.stringify({
|
|
134
|
-
trackerVersion: '4.0.
|
|
136
|
+
trackerVersion: '4.0.1',
|
|
135
137
|
projectKey: options.projectKey,
|
|
136
138
|
doNotTrack,
|
|
137
139
|
// TODO: add precise reason (an exact API missing)
|
|
@@ -163,9 +165,7 @@ class API {
|
|
|
163
165
|
return;
|
|
164
166
|
}
|
|
165
167
|
this.app.stop();
|
|
166
|
-
|
|
167
|
-
this.app.session.reset();
|
|
168
|
-
return sessionHash;
|
|
168
|
+
return this.app.session.getSessionHash();
|
|
169
169
|
}
|
|
170
170
|
getSessionToken() {
|
|
171
171
|
if (this.app === null) {
|
|
@@ -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;
|