@openreplay/tracker 4.1.4 → 4.1.6
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/index.d.ts +2 -0
- package/cjs/app/index.js +34 -26
- package/cjs/app/messages.d.ts +1 -1
- package/cjs/app/messages.gen.d.ts +4 -1
- package/cjs/app/messages.gen.js +32 -5
- package/cjs/app/messages.js +2 -2
- package/cjs/app/nodes.d.ts +1 -1
- package/cjs/app/nodes.js +4 -4
- package/cjs/app/observer/top_observer.js +2 -0
- package/cjs/common/interaction.d.ts +6 -1
- package/cjs/common/messages.gen.d.ts +26 -5
- package/cjs/index.d.ts +3 -3
- package/cjs/index.js +11 -6
- package/cjs/modules/constructedStyleSheets.js +14 -11
- package/cjs/modules/cssrules.js +6 -6
- package/cjs/modules/exception.d.ts +2 -2
- package/cjs/modules/exception.js +8 -8
- package/cjs/modules/focus.d.ts +2 -0
- package/cjs/modules/focus.js +45 -0
- package/cjs/modules/fonts.d.ts +2 -0
- package/cjs/modules/fonts.js +57 -0
- package/cjs/modules/img.js +1 -1
- package/cjs/utils.d.ts +1 -1
- package/cjs/utils.js +2 -2
- package/lib/app/guards.d.ts +1 -0
- package/lib/app/index.d.ts +2 -0
- package/lib/app/index.js +34 -26
- package/lib/app/messages.d.ts +1 -1
- package/lib/app/messages.gen.d.ts +4 -1
- package/lib/app/messages.gen.js +26 -2
- package/lib/app/messages.js +2 -2
- package/lib/app/nodes.d.ts +1 -1
- package/lib/app/nodes.js +4 -4
- package/lib/app/observer/top_observer.js +2 -0
- package/lib/common/interaction.d.ts +6 -1
- package/lib/common/messages.gen.d.ts +26 -5
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.js +11 -6
- package/lib/modules/constructedStyleSheets.js +15 -12
- package/lib/modules/cssrules.js +6 -6
- package/lib/modules/exception.d.ts +2 -2
- package/lib/modules/exception.js +8 -8
- package/lib/modules/focus.d.ts +2 -0
- package/lib/modules/focus.js +42 -0
- package/lib/modules/fonts.d.ts +2 -0
- package/lib/modules/fonts.js +54 -0
- package/lib/modules/img.js +2 -2
- package/lib/utils.d.ts +1 -1
- package/lib/utils.js +1 -1
- package/package.json +1 -1
|
@@ -20,20 +20,16 @@ function default_1(app) {
|
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
if (!hasAdoptedSS(document)) {
|
|
23
|
-
app.attachStartCallback(() => {
|
|
24
|
-
// MBTODO: pre-start sendQueue app
|
|
25
|
-
app.send((0, messages_gen_js_1.TechnicalInfo)('no_adopted_stylesheets', ''));
|
|
26
|
-
});
|
|
27
23
|
return;
|
|
28
24
|
}
|
|
29
25
|
const styleSheetIDMap = new Map();
|
|
30
26
|
const adoptedStyleSheetsOwnings = new Map();
|
|
31
|
-
const sendAdoptedStyleSheetsUpdate = (root) => {
|
|
27
|
+
const sendAdoptedStyleSheetsUpdate = (root) => setTimeout(() => {
|
|
32
28
|
let nodeID = app.nodes.getID(root);
|
|
33
29
|
if (root === document) {
|
|
34
30
|
nodeID = 0; // main document doesn't have nodeID. ID count starts from the documentElement
|
|
35
31
|
}
|
|
36
|
-
if (
|
|
32
|
+
if (nodeID === undefined) {
|
|
37
33
|
return;
|
|
38
34
|
}
|
|
39
35
|
let pastOwning = adoptedStyleSheetsOwnings.get(nodeID);
|
|
@@ -47,8 +43,8 @@ function default_1(app) {
|
|
|
47
43
|
const init = !sheetID;
|
|
48
44
|
if (!sheetID) {
|
|
49
45
|
sheetID = nextID();
|
|
46
|
+
styleSheetIDMap.set(s, sheetID);
|
|
50
47
|
}
|
|
51
|
-
nowOwning.push(sheetID);
|
|
52
48
|
if (!pastOwning.includes(sheetID)) {
|
|
53
49
|
app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
|
|
54
50
|
}
|
|
@@ -58,6 +54,7 @@ function default_1(app) {
|
|
|
58
54
|
app.send((0, messages_gen_js_1.AdoptedSSInsertRuleURLBased)(sheetID, rules[i].cssText, i, app.getBaseHref()));
|
|
59
55
|
}
|
|
60
56
|
}
|
|
57
|
+
nowOwning.push(sheetID);
|
|
61
58
|
}
|
|
62
59
|
for (const sheetID of pastOwning) {
|
|
63
60
|
if (!nowOwning.includes(sheetID)) {
|
|
@@ -65,7 +62,13 @@ function default_1(app) {
|
|
|
65
62
|
}
|
|
66
63
|
}
|
|
67
64
|
adoptedStyleSheetsOwnings.set(nodeID, nowOwning);
|
|
68
|
-
};
|
|
65
|
+
}, 20); // Misterious bug:
|
|
66
|
+
/* On the page https://explore.fast.design/components/fast-accordion
|
|
67
|
+
the only rule inside the only adoptedStyleSheet of the iframe-s document
|
|
68
|
+
gets changed during first milliseconds after the load.
|
|
69
|
+
Howerer, none of the documented methods (replace, insertRule) is triggered.
|
|
70
|
+
The rule is not substituted (remains the same object), however the text gets changed.
|
|
71
|
+
*/
|
|
69
72
|
function patchAdoptedStyleSheets(prototype) {
|
|
70
73
|
const nativeAdoptedStyleSheetsDescriptor = Object.getOwnPropertyDescriptor(prototype, 'adoptedStyleSheets');
|
|
71
74
|
if (nativeAdoptedStyleSheetsDescriptor) {
|
|
@@ -88,8 +91,8 @@ function default_1(app) {
|
|
|
88
91
|
}
|
|
89
92
|
patchAdoptedStyleSheets(context.Document.prototype);
|
|
90
93
|
patchAdoptedStyleSheets(context.ShadowRoot.prototype);
|
|
91
|
-
//@ts-ignore TODO:
|
|
92
|
-
const {
|
|
94
|
+
//@ts-ignore TODO: upgrade ts to 4.8+
|
|
95
|
+
const { replace, replaceSync } = context.CSSStyleSheet.prototype;
|
|
93
96
|
//@ts-ignore
|
|
94
97
|
context.CSSStyleSheet.prototype.replace = function (text) {
|
|
95
98
|
return replace.call(this, text).then((sheet) => {
|
|
@@ -110,7 +113,7 @@ function default_1(app) {
|
|
|
110
113
|
};
|
|
111
114
|
};
|
|
112
115
|
patchContext(window);
|
|
113
|
-
app.observer.attachContextCallback(patchContext);
|
|
116
|
+
app.observer.attachContextCallback(app.safe(patchContext));
|
|
114
117
|
app.attachStopCallback(() => {
|
|
115
118
|
styleSheetIDMap.clear();
|
|
116
119
|
adoptedStyleSheetsOwnings.clear();
|
package/cjs/modules/cssrules.js
CHANGED
|
@@ -11,7 +11,7 @@ function default_1(app) {
|
|
|
11
11
|
app.send((0, messages_gen_js_1.TechnicalInfo)('no_stylesheet_prototype_in_window', ''));
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
-
const
|
|
14
|
+
const sendInsertDeleteRule = app.safe((sheet, index, rule) => {
|
|
15
15
|
const sheetID = constructedStyleSheets_js_1.styleSheetIDMap.get(sheet);
|
|
16
16
|
if (!sheetID) {
|
|
17
17
|
// OK-case. Sheet haven't been registered yet. Rules will be sent on registration.
|
|
@@ -51,15 +51,15 @@ function default_1(app) {
|
|
|
51
51
|
app.debug.warn('Rule index not found in', sheet, topmostRule);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
-
const patchContext = (context) => {
|
|
54
|
+
const patchContext = app.safe((context) => {
|
|
55
55
|
const { insertRule, deleteRule } = context.CSSStyleSheet.prototype;
|
|
56
56
|
const { insertRule: groupInsertRule, deleteRule: groupDeleteRule } = context.CSSGroupingRule.prototype;
|
|
57
57
|
context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
|
|
58
|
-
|
|
58
|
+
sendInsertDeleteRule(this, index, rule);
|
|
59
59
|
return insertRule.call(this, rule, index);
|
|
60
60
|
};
|
|
61
61
|
context.CSSStyleSheet.prototype.deleteRule = function (index) {
|
|
62
|
-
|
|
62
|
+
sendInsertDeleteRule(this, index);
|
|
63
63
|
return deleteRule.call(this, index);
|
|
64
64
|
};
|
|
65
65
|
context.CSSGroupingRule.prototype.insertRule = function (rule, index = 0) {
|
|
@@ -72,7 +72,7 @@ function default_1(app) {
|
|
|
72
72
|
sendReplaceGroupingRule(this);
|
|
73
73
|
return result;
|
|
74
74
|
};
|
|
75
|
-
};
|
|
75
|
+
});
|
|
76
76
|
patchContext(window);
|
|
77
77
|
app.observer.attachContextCallback(patchContext);
|
|
78
78
|
app.nodes.attachNodeCallback((node) => {
|
|
@@ -92,7 +92,7 @@ function default_1(app) {
|
|
|
92
92
|
app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
|
|
93
93
|
const rules = sheet.cssRules;
|
|
94
94
|
for (let i = 0; i < rules.length; i++) {
|
|
95
|
-
|
|
95
|
+
sendInsertDeleteRule(sheet, i, rules[i].cssText);
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
}
|
|
@@ -10,7 +10,7 @@ interface StackFrame {
|
|
|
10
10
|
functionName?: string;
|
|
11
11
|
source?: string;
|
|
12
12
|
}
|
|
13
|
-
export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>): Message;
|
|
14
|
-
export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis): Message | null;
|
|
13
|
+
export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>, metadata?: Record<string, any>): Message;
|
|
14
|
+
export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis, metadata?: Record<string, any>): Message | null;
|
|
15
15
|
export default function (app: App, opts: Partial<Options>): void;
|
|
16
16
|
export {};
|
package/cjs/modules/exception.js
CHANGED
|
@@ -14,19 +14,19 @@ function getDefaultStack(e) {
|
|
|
14
14
|
},
|
|
15
15
|
];
|
|
16
16
|
}
|
|
17
|
-
function getExceptionMessage(error, fallbackStack) {
|
|
17
|
+
function getExceptionMessage(error, fallbackStack, metadata = {}) {
|
|
18
18
|
let stack = fallbackStack;
|
|
19
19
|
try {
|
|
20
20
|
stack = error_stack_parser_1.default.parse(error);
|
|
21
21
|
}
|
|
22
22
|
catch (e) { }
|
|
23
|
-
return (0, messages_gen_js_1.JSException)(error.name, error.message, JSON.stringify(stack));
|
|
23
|
+
return (0, messages_gen_js_1.JSException)(error.name, error.message, JSON.stringify(stack), JSON.stringify(metadata));
|
|
24
24
|
}
|
|
25
25
|
exports.getExceptionMessage = getExceptionMessage;
|
|
26
|
-
function getExceptionMessageFromEvent(e, context = window) {
|
|
26
|
+
function getExceptionMessageFromEvent(e, context = window, metadata = {}) {
|
|
27
27
|
if (e instanceof ErrorEvent) {
|
|
28
28
|
if (e.error instanceof Error) {
|
|
29
|
-
return getExceptionMessage(e.error, getDefaultStack(e));
|
|
29
|
+
return getExceptionMessage(e.error, getDefaultStack(e), metadata);
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
32
|
let [name, message] = e.message.split(':');
|
|
@@ -34,12 +34,12 @@ function getExceptionMessageFromEvent(e, context = window) {
|
|
|
34
34
|
name = 'Error';
|
|
35
35
|
message = e.message;
|
|
36
36
|
}
|
|
37
|
-
return (0, messages_gen_js_1.JSException)(name, message, JSON.stringify(getDefaultStack(e)));
|
|
37
|
+
return (0, messages_gen_js_1.JSException)(name, message, JSON.stringify(getDefaultStack(e)), JSON.stringify(metadata));
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
else if ('PromiseRejectionEvent' in context && e instanceof context.PromiseRejectionEvent) {
|
|
41
41
|
if (e.reason instanceof Error) {
|
|
42
|
-
return getExceptionMessage(e.reason, []);
|
|
42
|
+
return getExceptionMessage(e.reason, [], metadata);
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
45
|
let message;
|
|
@@ -49,7 +49,7 @@ function getExceptionMessageFromEvent(e, context = window) {
|
|
|
49
49
|
catch (_) {
|
|
50
50
|
message = String(e.reason);
|
|
51
51
|
}
|
|
52
|
-
return (0, messages_gen_js_1.JSException)('Unhandled Promise Rejection', message, '[]');
|
|
52
|
+
return (0, messages_gen_js_1.JSException)('Unhandled Promise Rejection', message, '[]', JSON.stringify(metadata));
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
return null;
|
|
@@ -70,7 +70,7 @@ function default_1(app, opts) {
|
|
|
70
70
|
app.attachEventListener(context, 'error', handler);
|
|
71
71
|
}
|
|
72
72
|
if (options.captureExceptions) {
|
|
73
|
-
app.observer.attachContextCallback(patchContext);
|
|
73
|
+
app.observer.attachContextCallback(patchContext); // TODO: attach once-per-iframe (?)
|
|
74
74
|
patchContext(window);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const guards_js_1 = require("../app/guards.js");
|
|
4
|
+
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
5
|
+
function default_1(app) {
|
|
6
|
+
function sendSetNodeFocus(n) {
|
|
7
|
+
const id = app.nodes.getID(n);
|
|
8
|
+
if (id !== undefined) {
|
|
9
|
+
app.send((0, messages_gen_js_1.SetNodeFocus)(id));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
let blurred = false;
|
|
13
|
+
app.nodes.attachNodeCallback((node) => {
|
|
14
|
+
if (!(0, guards_js_1.hasTag)(node, 'BODY')) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
app.nodes.attachNodeListener(node, 'focus', (e) => {
|
|
18
|
+
if (!(0, guards_js_1.isNode)(e.target)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
sendSetNodeFocus(e.target);
|
|
22
|
+
blurred = false;
|
|
23
|
+
});
|
|
24
|
+
app.nodes.attachNodeListener(node, 'blur', (e) => {
|
|
25
|
+
if (e.relatedTarget === null) {
|
|
26
|
+
blurred = true;
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
if (blurred) {
|
|
29
|
+
app.send((0, messages_gen_js_1.SetNodeFocus)(-1));
|
|
30
|
+
}
|
|
31
|
+
}, 0);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
app.attachStartCallback(() => {
|
|
36
|
+
let elem = document.activeElement;
|
|
37
|
+
while (elem && (0, guards_js_1.hasTag)(elem, 'IFRAME') && elem.contentDocument) {
|
|
38
|
+
elem = elem.contentDocument.activeElement;
|
|
39
|
+
}
|
|
40
|
+
if (elem && elem !== elem.ownerDocument.body) {
|
|
41
|
+
sendSetNodeFocus(elem);
|
|
42
|
+
}
|
|
43
|
+
}, true);
|
|
44
|
+
}
|
|
45
|
+
exports.default = default_1;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const guards_js_1 = require("../app/guards.js");
|
|
4
|
+
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
5
|
+
function default_1(app) {
|
|
6
|
+
if (!window.FontFace) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const docFonts = new Map();
|
|
10
|
+
const patchWindow = (wnd) => {
|
|
11
|
+
class FontFaceInterceptor extends wnd.FontFace {
|
|
12
|
+
constructor(...args) {
|
|
13
|
+
//maybe do this on load(). In this case check if the document.fonts.load(...) function calls the font's load()
|
|
14
|
+
if (typeof args[1] === 'string') {
|
|
15
|
+
let desc = '';
|
|
16
|
+
if (args[2]) {
|
|
17
|
+
app.safe(() => {
|
|
18
|
+
desc = JSON.stringify(args[2]);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const ffData = [args[0], args[1], desc];
|
|
22
|
+
const ffDataArr = docFonts.get(wnd.document) || [];
|
|
23
|
+
ffDataArr.push(ffData);
|
|
24
|
+
docFonts.set(wnd.document, ffDataArr);
|
|
25
|
+
const parentID = wnd === window ? 0 : app.nodes.getID(wnd.document);
|
|
26
|
+
if (parentID === undefined) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (app.active()) {
|
|
30
|
+
app.send((0, messages_gen_js_1.LoadFontFace)(parentID, ...ffData));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
super(...args);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
wnd.FontFace = FontFaceInterceptor;
|
|
37
|
+
};
|
|
38
|
+
app.observer.attachContextCallback(patchWindow);
|
|
39
|
+
patchWindow(window);
|
|
40
|
+
app.nodes.attachNodeCallback((node) => {
|
|
41
|
+
if (!(0, guards_js_1.isDocument)(node)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const ffDataArr = docFonts.get(node);
|
|
45
|
+
if (!ffDataArr) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const parentID = node.defaultView === window ? 0 : app.nodes.getID(node);
|
|
49
|
+
if (parentID === undefined) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
ffDataArr.forEach((ffData) => {
|
|
53
|
+
app.send((0, messages_gen_js_1.LoadFontFace)(parentID, ...ffData));
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
exports.default = default_1;
|
package/cjs/modules/img.js
CHANGED
|
@@ -54,7 +54,7 @@ function default_1(app) {
|
|
|
54
54
|
const sendImgError = app.safe(function (img) {
|
|
55
55
|
const resolvedSrc = resolveURL(img.src || ''); // Src type is null sometimes. - is it true?
|
|
56
56
|
if ((0, utils_js_1.isURL)(resolvedSrc)) {
|
|
57
|
-
app.send((0, messages_gen_js_1.ResourceTiming)(
|
|
57
|
+
app.send((0, messages_gen_js_1.ResourceTiming)(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
const sendImgAttrs = app.safe(function (img) {
|
package/cjs/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const IN_BROWSER: boolean;
|
|
2
2
|
export declare const IS_FIREFOX: false | RegExpMatchArray | null;
|
|
3
3
|
export declare const MAX_STR_LEN = 100000;
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const now: () => number;
|
|
5
5
|
export declare const stars: (str: string) => string;
|
|
6
6
|
export declare function normSpaces(str: string): string;
|
|
7
7
|
export declare function isURL(s: string): boolean;
|
package/cjs/utils.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.
|
|
3
|
+
exports.hasOpenreplayAttribute = exports.getLabelAttribute = exports.deprecationWarn = exports.DOCS_HOST = exports.isURL = exports.normSpaces = exports.stars = exports.now = exports.MAX_STR_LEN = exports.IS_FIREFOX = exports.IN_BROWSER = void 0;
|
|
4
4
|
const DEPRECATED_ATTRS = { htmlmasked: 'hidden', masked: 'obscured' };
|
|
5
5
|
exports.IN_BROWSER = !(typeof window === 'undefined');
|
|
6
6
|
exports.IS_FIREFOX = exports.IN_BROWSER && navigator.userAgent.match(/firefox|fxios/i);
|
|
7
7
|
exports.MAX_STR_LEN = 1e5;
|
|
8
8
|
const navigationStart = exports.IN_BROWSER && (performance.timing.navigationStart || performance.timeOrigin);
|
|
9
9
|
// performance.now() is buggy in some browsers
|
|
10
|
-
exports.
|
|
10
|
+
exports.now = exports.IN_BROWSER && performance.now() && navigationStart
|
|
11
11
|
? () => Math.round(performance.now() + navigationStart)
|
|
12
12
|
: () => Date.now();
|
|
13
13
|
exports.stars = 'repeat' in String.prototype
|
package/lib/app/guards.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare function isDocument(node: Node): node is Document;
|
|
|
6
6
|
export declare function isRootNode(node: Node): node is Document | DocumentFragment;
|
|
7
7
|
declare type TagTypeMap = {
|
|
8
8
|
HTML: HTMLHtmlElement;
|
|
9
|
+
BODY: HTMLBodyElement;
|
|
9
10
|
IMG: HTMLImageElement;
|
|
10
11
|
INPUT: HTMLInputElement;
|
|
11
12
|
TEXTAREA: HTMLTextAreaElement;
|
package/lib/app/index.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export default class App {
|
|
|
77
77
|
private _debug;
|
|
78
78
|
send(message: Message, urgent?: boolean): void;
|
|
79
79
|
private commit;
|
|
80
|
+
private delay;
|
|
81
|
+
timestamp(): number;
|
|
80
82
|
safe<T extends (this: any, ...args: any[]) => void>(fn: T): T;
|
|
81
83
|
attachCommitCallback(cb: CommitCallback): void;
|
|
82
84
|
attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
|
package/lib/app/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Timestamp, Metadata, UserID } from './messages.gen.js';
|
|
2
|
-
import {
|
|
2
|
+
import { now } from '../utils.js';
|
|
3
3
|
import Nodes from './nodes.js';
|
|
4
4
|
import Observer from './observer/top_observer.js';
|
|
5
5
|
import Sanitizer from './sanitizer.js';
|
|
@@ -24,12 +24,14 @@ export default class App {
|
|
|
24
24
|
// if (options.onStart !== undefined) {
|
|
25
25
|
// deprecationWarn("'onStart' option", "tracker.start().then(/* handle session info */)")
|
|
26
26
|
// } ?? maybe onStart is good
|
|
27
|
+
var _a, _b;
|
|
27
28
|
this.messages = [];
|
|
28
29
|
this.startCallbacks = [];
|
|
29
30
|
this.stopCallbacks = [];
|
|
30
31
|
this.commitCallbacks = [];
|
|
31
32
|
this.activityState = ActivityState.NotActive;
|
|
32
|
-
this.version = '4.1.
|
|
33
|
+
this.version = '4.1.6'; // TODO: version compatability check inside each plugin.
|
|
34
|
+
this.delay = 0;
|
|
33
35
|
this.projectKey = projectKey;
|
|
34
36
|
this.options = Object.assign({
|
|
35
37
|
revID: '',
|
|
@@ -43,10 +45,12 @@ export default class App {
|
|
|
43
45
|
verbose: false,
|
|
44
46
|
__is_snippet: false,
|
|
45
47
|
__debug_report_edp: null,
|
|
46
|
-
localStorage:
|
|
47
|
-
sessionStorage:
|
|
48
|
+
localStorage: null,
|
|
49
|
+
sessionStorage: null,
|
|
48
50
|
}, options);
|
|
49
51
|
this.revID = this.options.revID;
|
|
52
|
+
this.localStorage = (_a = this.options.localStorage) !== null && _a !== void 0 ? _a : window.localStorage;
|
|
53
|
+
this.sessionStorage = (_b = this.options.sessionStorage) !== null && _b !== void 0 ? _b : window.sessionStorage;
|
|
50
54
|
this.sanitizer = new Sanitizer(this, options);
|
|
51
55
|
this.nodes = new Nodes(this.options.node_id);
|
|
52
56
|
this.observer = new Observer(this, options);
|
|
@@ -54,8 +58,6 @@ export default class App {
|
|
|
54
58
|
this.ticker.attach(() => this.commit());
|
|
55
59
|
this.debug = new Logger(this.options.__debug__);
|
|
56
60
|
this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent);
|
|
57
|
-
this.localStorage = this.options.localStorage || window.localStorage;
|
|
58
|
-
this.sessionStorage = this.options.sessionStorage || window.sessionStorage;
|
|
59
61
|
this.session = new Session(this, this.options);
|
|
60
62
|
this.session.attachUpdateCallback(({ userID, metadata }) => {
|
|
61
63
|
if (userID != null) {
|
|
@@ -71,18 +73,18 @@ export default class App {
|
|
|
71
73
|
this.session.applySessionHash(sessionToken);
|
|
72
74
|
}
|
|
73
75
|
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!==
|
|
76
|
+
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(`Failed to send batch after ${this.attemptsCount} attempts.`):(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 57:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:return this.int(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]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])}}}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!==g&&(clearInterval(g),g=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){postMessage("restart"),a()}n.NotActive;let c,g=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()},t=>{!function(t){postMessage({type:"failure",reason:t}),a()}(t)},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===g&&(g=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
77
|
this.worker.onerror = (e) => {
|
|
76
78
|
this._debug('webworker_error', e);
|
|
77
79
|
};
|
|
78
80
|
this.worker.onmessage = ({ data }) => {
|
|
79
|
-
if (data === '
|
|
81
|
+
if (data === 'restart') {
|
|
80
82
|
this.stop(false);
|
|
81
|
-
this.
|
|
83
|
+
this.start({ forceNew: true }); // TODO: keep userID & metadata (draw scenarios)
|
|
82
84
|
}
|
|
83
|
-
else if (data === '
|
|
85
|
+
else if (data.type === 'failure') {
|
|
84
86
|
this.stop(false);
|
|
85
|
-
this.
|
|
87
|
+
this._debug('worker_failed', data.reason);
|
|
86
88
|
}
|
|
87
89
|
};
|
|
88
90
|
const alertWorker = () => {
|
|
@@ -102,7 +104,7 @@ export default class App {
|
|
|
102
104
|
}
|
|
103
105
|
_debug(context, e) {
|
|
104
106
|
if (this.options.__debug_report_edp !== null) {
|
|
105
|
-
fetch(this.options.__debug_report_edp, {
|
|
107
|
+
void fetch(this.options.__debug_report_edp, {
|
|
106
108
|
method: 'POST',
|
|
107
109
|
headers: { 'Content-Type': 'application/json' },
|
|
108
110
|
body: JSON.stringify({
|
|
@@ -115,25 +117,30 @@ export default class App {
|
|
|
115
117
|
}
|
|
116
118
|
send(message, urgent = false) {
|
|
117
119
|
if (this.activityState === ActivityState.NotActive) {
|
|
120
|
+
// this.debug.log('SendiTrying to send when not active', message) <- crashing the app
|
|
118
121
|
return;
|
|
119
122
|
}
|
|
120
123
|
this.messages.push(message);
|
|
121
124
|
// TODO: commit on start if there were `urgent` sends;
|
|
122
|
-
//
|
|
123
|
-
//
|
|
125
|
+
// Clarify where urgent can be used for;
|
|
126
|
+
// Clarify workflow for each type of message in case it was sent before start
|
|
124
127
|
// (like Fetch before start; maybe add an option "preCapture: boolean" or sth alike)
|
|
128
|
+
// Careful: `this.delay` is equal to zero before start hense all Timestamp-s will have to be updated on start
|
|
125
129
|
if (this.activityState === ActivityState.Active && urgent) {
|
|
126
130
|
this.commit();
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
commit() {
|
|
130
134
|
if (this.worker && this.messages.length) {
|
|
131
|
-
this.messages.unshift(Timestamp(
|
|
135
|
+
this.messages.unshift(Timestamp(this.timestamp()));
|
|
132
136
|
this.worker.postMessage(this.messages);
|
|
133
137
|
this.commitCallbacks.forEach((cb) => cb(this.messages));
|
|
134
138
|
this.messages.length = 0;
|
|
135
139
|
}
|
|
136
140
|
}
|
|
141
|
+
timestamp() {
|
|
142
|
+
return now() + this.delay;
|
|
143
|
+
}
|
|
137
144
|
safe(fn) {
|
|
138
145
|
const app = this;
|
|
139
146
|
return function (...args) {
|
|
@@ -142,7 +149,7 @@ export default class App {
|
|
|
142
149
|
}
|
|
143
150
|
catch (e) {
|
|
144
151
|
app._debug('safe_fn_call', e);
|
|
145
|
-
// time:
|
|
152
|
+
// time: this.timestamp(),
|
|
146
153
|
// name: e.name,
|
|
147
154
|
// message: e.message,
|
|
148
155
|
// stack: e.stack
|
|
@@ -169,8 +176,8 @@ export default class App {
|
|
|
169
176
|
if (useSafe) {
|
|
170
177
|
listener = this.safe(listener);
|
|
171
178
|
}
|
|
172
|
-
this.attachStartCallback(() => target.addEventListener(type, listener, useCapture), useSafe);
|
|
173
|
-
this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture), useSafe);
|
|
179
|
+
this.attachStartCallback(() => target === null || target === void 0 ? void 0 : target.addEventListener(type, listener, useCapture), useSafe);
|
|
180
|
+
this.attachStopCallback(() => target === null || target === void 0 ? void 0 : target.removeEventListener(type, listener, useCapture), useSafe);
|
|
174
181
|
}
|
|
175
182
|
// TODO: full correct semantic
|
|
176
183
|
checkRequiredVersion(version) {
|
|
@@ -271,7 +278,7 @@ export default class App {
|
|
|
271
278
|
this.session.applySessionHash(startOpts.sessionHash);
|
|
272
279
|
}
|
|
273
280
|
const timestamp = now();
|
|
274
|
-
|
|
281
|
+
this.worker.postMessage({
|
|
275
282
|
type: 'start',
|
|
276
283
|
pageNo: this.session.incPageNo(),
|
|
277
284
|
ingestPoint: this.options.ingestPoint,
|
|
@@ -279,8 +286,7 @@ export default class App {
|
|
|
279
286
|
url: document.URL,
|
|
280
287
|
connAttemptCount: this.options.connAttemptCount,
|
|
281
288
|
connAttemptGap: this.options.connAttemptGap,
|
|
282
|
-
};
|
|
283
|
-
this.worker.postMessage(startWorkerMsg);
|
|
289
|
+
});
|
|
284
290
|
this.session.update({
|
|
285
291
|
// TODO: transparent "session" module logic AND explicit internal api for plugins.
|
|
286
292
|
// "updating" with old metadata in order to trigger session's UpdateCallbacks.
|
|
@@ -320,14 +326,16 @@ export default class App {
|
|
|
320
326
|
return Promise.reject('Tracker stopped during authorisation');
|
|
321
327
|
}
|
|
322
328
|
const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
|
|
323
|
-
|
|
329
|
+
delay, } = r;
|
|
324
330
|
if (typeof token !== 'string' ||
|
|
325
331
|
typeof userUUID !== 'string' ||
|
|
326
332
|
//typeof startTimestamp !== 'number' ||
|
|
327
333
|
//typeof sessionID !== 'string' ||
|
|
334
|
+
typeof delay !== 'number' ||
|
|
328
335
|
(typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
|
|
329
336
|
return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
|
|
330
337
|
}
|
|
338
|
+
this.delay = delay;
|
|
331
339
|
const prevSessionID = this.session.getInfo().sessionID;
|
|
332
340
|
if (prevSessionID && prevSessionID !== sessionID) {
|
|
333
341
|
this.session.reset();
|
|
@@ -335,14 +343,14 @@ export default class App {
|
|
|
335
343
|
this.session.setSessionToken(token);
|
|
336
344
|
this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
|
|
337
345
|
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
338
|
-
|
|
346
|
+
this.worker.postMessage({
|
|
339
347
|
type: 'auth',
|
|
340
348
|
token,
|
|
341
349
|
beaconSizeLimit,
|
|
342
|
-
};
|
|
343
|
-
this.worker.postMessage(startWorkerMsg);
|
|
350
|
+
});
|
|
344
351
|
const onStartInfo = { sessionToken: token, userUUID, sessionID };
|
|
345
|
-
|
|
352
|
+
// TODO: start as early as possible (before receiving the token)
|
|
353
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo)); // MBTODO: callbacks after DOM "mounted" (observed)
|
|
346
354
|
this.observer.observe();
|
|
347
355
|
this.ticker.start();
|
|
348
356
|
this.activityState = ActivityState.Active;
|
package/lib/app/messages.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
|
|
|
22
22
|
export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
|
|
23
23
|
export declare function PageLoadTiming(requestStart: number, responseStart: number, responseEnd: number, domContentLoadedEventStart: number, domContentLoadedEventEnd: number, loadEventStart: number, loadEventEnd: number, firstPaint: number, firstContentfulPaint: number): Messages.PageLoadTiming;
|
|
24
24
|
export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
|
|
25
|
-
export declare function JSException(name: string, message: string, payload: string): Messages.JSException;
|
|
25
|
+
export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
|
|
26
26
|
export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
|
|
27
27
|
export declare function UserID(id: string): Messages.UserID;
|
|
28
28
|
export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
|
|
@@ -22,7 +22,7 @@ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
|
|
|
22
22
|
export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
|
|
23
23
|
export declare function PageLoadTiming(requestStart: number, responseStart: number, responseEnd: number, domContentLoadedEventStart: number, domContentLoadedEventEnd: number, loadEventStart: number, loadEventEnd: number, firstPaint: number, firstContentfulPaint: number): Messages.PageLoadTiming;
|
|
24
24
|
export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
|
|
25
|
-
export declare function
|
|
25
|
+
export declare function JSExceptionDeprecated(name: string, message: string, payload: string): Messages.JSExceptionDeprecated;
|
|
26
26
|
export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
|
|
27
27
|
export declare function UserID(id: string): Messages.UserID;
|
|
28
28
|
export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
|
|
@@ -42,6 +42,8 @@ export declare function PerformanceTrack(frames: number, ticks: number, totalJSH
|
|
|
42
42
|
export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string): Messages.ResourceTiming;
|
|
43
43
|
export declare function ConnectionInformation(downlink: number, type: string): Messages.ConnectionInformation;
|
|
44
44
|
export declare function SetPageVisibility(hidden: boolean): Messages.SetPageVisibility;
|
|
45
|
+
export declare function LoadFontFace(parentID: number, family: string, source: string, descriptors: string): Messages.LoadFontFace;
|
|
46
|
+
export declare function SetNodeFocus(id: number): Messages.SetNodeFocus;
|
|
45
47
|
export declare function LongTask(timestamp: number, duration: number, context: number, containerType: number, containerSrc: string, containerId: string, containerName: string): Messages.LongTask;
|
|
46
48
|
export declare function SetNodeAttributeURLBased(id: number, name: string, value: string, baseURL: string): Messages.SetNodeAttributeURLBased;
|
|
47
49
|
export declare function SetCSSDataURLBased(id: number, data: string, baseURL: string): Messages.SetCSSDataURLBased;
|
|
@@ -56,3 +58,4 @@ export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Mes
|
|
|
56
58
|
export declare function AdoptedSSAddOwner(sheetID: number, id: number): Messages.AdoptedSSAddOwner;
|
|
57
59
|
export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messages.AdoptedSSRemoveOwner;
|
|
58
60
|
export declare function Zustand(mutation: string, state: string): Messages.Zustand;
|
|
61
|
+
export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
|