@openreplay/tracker 5.0.1 → 5.0.2-beta

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.
Files changed (135) hide show
  1. package/package.json +1 -1
  2. package/cjs/app/guards.d.ts +0 -21
  3. package/cjs/app/guards.js +0 -37
  4. package/cjs/app/index.d.ts +0 -118
  5. package/cjs/app/index.js +0 -438
  6. package/cjs/app/logger.d.ts +0 -26
  7. package/cjs/app/logger.js +0 -45
  8. package/cjs/app/messages.gen.d.ts +0 -63
  9. package/cjs/app/messages.gen.js +0 -551
  10. package/cjs/app/nodes.d.ts +0 -18
  11. package/cjs/app/nodes.js +0 -82
  12. package/cjs/app/observer/iframe_observer.d.ts +0 -4
  13. package/cjs/app/observer/iframe_observer.js +0 -23
  14. package/cjs/app/observer/iframe_offsets.d.ts +0 -8
  15. package/cjs/app/observer/iframe_offsets.js +0 -59
  16. package/cjs/app/observer/observer.d.ts +0 -23
  17. package/cjs/app/observer/observer.js +0 -340
  18. package/cjs/app/observer/shadow_root_observer.d.ts +0 -4
  19. package/cjs/app/observer/shadow_root_observer.js +0 -21
  20. package/cjs/app/observer/top_observer.d.ts +0 -24
  21. package/cjs/app/observer/top_observer.js +0 -113
  22. package/cjs/app/sanitizer.d.ts +0 -24
  23. package/cjs/app/sanitizer.js +0 -76
  24. package/cjs/app/session.d.ts +0 -38
  25. package/cjs/app/session.js +0 -114
  26. package/cjs/app/ticker.d.ts +0 -12
  27. package/cjs/app/ticker.js +0 -42
  28. package/cjs/common/interaction.d.ts +0 -24
  29. package/cjs/common/interaction.js +0 -2
  30. package/cjs/common/messages.gen.d.ts +0 -427
  31. package/cjs/common/messages.gen.js +0 -4
  32. package/cjs/index.d.ts +0 -47
  33. package/cjs/index.js +0 -254
  34. package/cjs/modules/connection.d.ts +0 -2
  35. package/cjs/modules/connection.js +0 -15
  36. package/cjs/modules/console.d.ts +0 -6
  37. package/cjs/modules/console.js +0 -119
  38. package/cjs/modules/constructedStyleSheets.d.ts +0 -4
  39. package/cjs/modules/constructedStyleSheets.js +0 -131
  40. package/cjs/modules/cssrules.d.ts +0 -2
  41. package/cjs/modules/cssrules.js +0 -99
  42. package/cjs/modules/exception.d.ts +0 -16
  43. package/cjs/modules/exception.js +0 -77
  44. package/cjs/modules/focus.d.ts +0 -2
  45. package/cjs/modules/focus.js +0 -45
  46. package/cjs/modules/fonts.d.ts +0 -2
  47. package/cjs/modules/fonts.js +0 -57
  48. package/cjs/modules/img.d.ts +0 -2
  49. package/cjs/modules/img.js +0 -110
  50. package/cjs/modules/input.d.ts +0 -16
  51. package/cjs/modules/input.js +0 -163
  52. package/cjs/modules/mouse.d.ts +0 -2
  53. package/cjs/modules/mouse.js +0 -148
  54. package/cjs/modules/network.d.ts +0 -28
  55. package/cjs/modules/network.js +0 -203
  56. package/cjs/modules/performance.d.ts +0 -7
  57. package/cjs/modules/performance.js +0 -53
  58. package/cjs/modules/scroll.d.ts +0 -2
  59. package/cjs/modules/scroll.js +0 -79
  60. package/cjs/modules/timing.d.ts +0 -7
  61. package/cjs/modules/timing.js +0 -160
  62. package/cjs/modules/viewport.d.ts +0 -2
  63. package/cjs/modules/viewport.js +0 -43
  64. package/cjs/package.json +0 -1
  65. package/cjs/utils.d.ts +0 -13
  66. package/cjs/utils.js +0 -71
  67. package/cjs/vendors/finder/finder.d.ts +0 -12
  68. package/cjs/vendors/finder/finder.js +0 -352
  69. package/lib/app/guards.d.ts +0 -21
  70. package/lib/app/guards.js +0 -26
  71. package/lib/app/index.d.ts +0 -118
  72. package/lib/app/index.js +0 -434
  73. package/lib/app/logger.d.ts +0 -26
  74. package/lib/app/logger.js +0 -41
  75. package/lib/app/messages.gen.d.ts +0 -63
  76. package/lib/app/messages.gen.js +0 -486
  77. package/lib/app/nodes.d.ts +0 -18
  78. package/lib/app/nodes.js +0 -79
  79. package/lib/app/observer/iframe_observer.d.ts +0 -4
  80. package/lib/app/observer/iframe_observer.js +0 -20
  81. package/lib/app/observer/iframe_offsets.d.ts +0 -8
  82. package/lib/app/observer/iframe_offsets.js +0 -56
  83. package/lib/app/observer/observer.d.ts +0 -23
  84. package/lib/app/observer/observer.js +0 -337
  85. package/lib/app/observer/shadow_root_observer.d.ts +0 -4
  86. package/lib/app/observer/shadow_root_observer.js +0 -18
  87. package/lib/app/observer/top_observer.d.ts +0 -24
  88. package/lib/app/observer/top_observer.js +0 -110
  89. package/lib/app/sanitizer.d.ts +0 -24
  90. package/lib/app/sanitizer.js +0 -72
  91. package/lib/app/session.d.ts +0 -38
  92. package/lib/app/session.js +0 -111
  93. package/lib/app/ticker.d.ts +0 -12
  94. package/lib/app/ticker.js +0 -39
  95. package/lib/common/interaction.d.ts +0 -24
  96. package/lib/common/interaction.js +0 -1
  97. package/lib/common/messages.gen.d.ts +0 -427
  98. package/lib/common/messages.gen.js +0 -3
  99. package/lib/common/tsconfig.tsbuildinfo +0 -1
  100. package/lib/index.d.ts +0 -47
  101. package/lib/index.js +0 -248
  102. package/lib/modules/connection.d.ts +0 -2
  103. package/lib/modules/connection.js +0 -12
  104. package/lib/modules/console.d.ts +0 -6
  105. package/lib/modules/console.js +0 -116
  106. package/lib/modules/constructedStyleSheets.d.ts +0 -4
  107. package/lib/modules/constructedStyleSheets.js +0 -126
  108. package/lib/modules/cssrules.d.ts +0 -2
  109. package/lib/modules/cssrules.js +0 -97
  110. package/lib/modules/exception.d.ts +0 -16
  111. package/lib/modules/exception.js +0 -71
  112. package/lib/modules/focus.d.ts +0 -2
  113. package/lib/modules/focus.js +0 -42
  114. package/lib/modules/fonts.d.ts +0 -2
  115. package/lib/modules/fonts.js +0 -54
  116. package/lib/modules/img.d.ts +0 -2
  117. package/lib/modules/img.js +0 -107
  118. package/lib/modules/input.d.ts +0 -16
  119. package/lib/modules/input.js +0 -158
  120. package/lib/modules/mouse.d.ts +0 -2
  121. package/lib/modules/mouse.js +0 -145
  122. package/lib/modules/network.d.ts +0 -28
  123. package/lib/modules/network.js +0 -200
  124. package/lib/modules/performance.d.ts +0 -7
  125. package/lib/modules/performance.js +0 -49
  126. package/lib/modules/scroll.d.ts +0 -2
  127. package/lib/modules/scroll.js +0 -76
  128. package/lib/modules/timing.d.ts +0 -7
  129. package/lib/modules/timing.js +0 -157
  130. package/lib/modules/viewport.d.ts +0 -2
  131. package/lib/modules/viewport.js +0 -40
  132. package/lib/utils.d.ts +0 -13
  133. package/lib/utils.js +0 -61
  134. package/lib/vendors/finder/finder.d.ts +0 -12
  135. package/lib/vendors/finder/finder.js +0 -348
@@ -1,158 +0,0 @@
1
- import { normSpaces, IN_BROWSER, getLabelAttribute } from '../utils.js';
2
- import { hasTag } from '../app/guards.js';
3
- import { SetInputTarget, SetInputValue, SetInputChecked } from '../app/messages.gen.js';
4
- const INPUT_TYPES = ['text', 'password', 'email', 'search', 'number', 'range', 'date', 'tel'];
5
- function isTextEditable(node) {
6
- if (hasTag(node, 'textarea')) {
7
- return true;
8
- }
9
- if (!hasTag(node, 'input')) {
10
- return false;
11
- }
12
- return INPUT_TYPES.includes(node.type);
13
- }
14
- function isCheckable(node) {
15
- if (!hasTag(node, 'input')) {
16
- return false;
17
- }
18
- const type = node.type;
19
- return type === 'checkbox' || type === 'radio';
20
- }
21
- const labelElementFor = IN_BROWSER && 'labels' in HTMLInputElement.prototype
22
- ? (node) => {
23
- let p = node;
24
- while ((p = p.parentNode) !== null) {
25
- if (hasTag(p, 'label')) {
26
- return p;
27
- }
28
- }
29
- const labels = node.labels;
30
- if (labels !== null && labels.length === 1) {
31
- return labels[0];
32
- }
33
- }
34
- : (node) => {
35
- let p = node;
36
- while ((p = p.parentNode) !== null) {
37
- if (hasTag(p, 'label')) {
38
- return p;
39
- }
40
- }
41
- const id = node.id;
42
- if (id) {
43
- const labels = node.ownerDocument.querySelectorAll('label[for="' + id + '"]');
44
- if (labels !== null && labels.length === 1) {
45
- return labels[0];
46
- }
47
- }
48
- };
49
- export function getInputLabel(node) {
50
- let label = getLabelAttribute(node);
51
- if (label === null) {
52
- const labelElement = labelElementFor(node);
53
- label =
54
- (labelElement && labelElement.innerText) ||
55
- node.placeholder ||
56
- node.name ||
57
- node.id ||
58
- node.className ||
59
- node.type;
60
- }
61
- return normSpaces(label).slice(0, 100);
62
- }
63
- export default function (app, opts) {
64
- const options = Object.assign({
65
- obscureInputNumbers: true,
66
- obscureInputEmails: true,
67
- defaultInputMode: 1 /* InputMode.Obscured */,
68
- obscureInputDates: false,
69
- }, opts);
70
- function sendInputTarget(id, node) {
71
- const label = getInputLabel(node);
72
- if (label !== '') {
73
- app.send(SetInputTarget(id, label));
74
- }
75
- }
76
- function sendInputValue(id, node) {
77
- let value = node.value;
78
- let inputMode = options.defaultInputMode;
79
- if (node.type === 'password' || app.sanitizer.isHidden(id)) {
80
- inputMode = 2 /* InputMode.Hidden */;
81
- }
82
- else if (app.sanitizer.isObscured(id) ||
83
- (inputMode === 0 /* InputMode.Plain */ &&
84
- ((options.obscureInputNumbers && node.type !== 'date' && /\d\d\d\d/.test(value)) ||
85
- (options.obscureInputDates && node.type === 'date') ||
86
- (options.obscureInputEmails && (node.type === 'email' || !!~value.indexOf('@')))))) {
87
- inputMode = 1 /* InputMode.Obscured */;
88
- }
89
- let mask = 0;
90
- switch (inputMode) {
91
- case 2 /* InputMode.Hidden */:
92
- mask = -1;
93
- value = '';
94
- break;
95
- case 1 /* InputMode.Obscured */:
96
- mask = value.length;
97
- value = '';
98
- break;
99
- }
100
- app.send(SetInputValue(id, value, mask));
101
- }
102
- const inputValues = new Map();
103
- const checkableValues = new Map();
104
- const registeredTargets = new Set();
105
- app.attachStopCallback(() => {
106
- inputValues.clear();
107
- checkableValues.clear();
108
- registeredTargets.clear();
109
- });
110
- app.ticker.attach(() => {
111
- inputValues.forEach((value, id) => {
112
- const node = app.nodes.getNode(id);
113
- if (!node)
114
- return inputValues.delete(id);
115
- if (value !== node.value) {
116
- inputValues.set(id, node.value);
117
- if (!registeredTargets.has(id)) {
118
- registeredTargets.add(id);
119
- sendInputTarget(id, node);
120
- }
121
- sendInputValue(id, node);
122
- }
123
- });
124
- checkableValues.forEach((checked, id) => {
125
- const node = app.nodes.getNode(id);
126
- if (!node)
127
- return checkableValues.delete(id);
128
- if (checked !== node.checked) {
129
- checkableValues.set(id, node.checked);
130
- app.send(SetInputChecked(id, node.checked));
131
- }
132
- });
133
- });
134
- app.ticker.attach(Set.prototype.clear, 100, false, registeredTargets);
135
- app.nodes.attachNodeCallback(app.safe((node) => {
136
- const id = app.nodes.getID(node);
137
- if (id === undefined) {
138
- return;
139
- }
140
- // TODO: support multiple select (?): use selectedOptions; Need send target?
141
- if (hasTag(node, 'select')) {
142
- sendInputValue(id, node);
143
- app.attachEventListener(node, 'change', () => {
144
- sendInputValue(id, node);
145
- });
146
- }
147
- if (isTextEditable(node)) {
148
- inputValues.set(id, node.value);
149
- sendInputValue(id, node);
150
- return;
151
- }
152
- if (isCheckable(node)) {
153
- checkableValues.set(id, node.checked);
154
- app.send(SetInputChecked(id, node.checked));
155
- return;
156
- }
157
- }));
158
- }
@@ -1,2 +0,0 @@
1
- import type App from '../app/index.js';
2
- export default function (app: App): void;
@@ -1,145 +0,0 @@
1
- import { hasTag, isSVGElement, isDocument } from '../app/guards.js';
2
- import { normSpaces, hasOpenreplayAttribute, getLabelAttribute } from '../utils.js';
3
- import { MouseMove, MouseClick } from '../app/messages.gen.js';
4
- import { getInputLabel } from './input.js';
5
- import { finder } from '@medv/finder';
6
- function _getSelector(target, document) {
7
- const selector = finder(target, {
8
- root: document.body,
9
- seedMinLength: 3,
10
- optimizedMinLength: 2,
11
- threshold: 1000,
12
- maxNumberOfTries: 10000,
13
- });
14
- return selector;
15
- }
16
- function isClickable(element) {
17
- const tag = element.tagName.toUpperCase();
18
- return (tag === 'BUTTON' ||
19
- tag === 'A' ||
20
- tag === 'LI' ||
21
- tag === 'SELECT' ||
22
- tag === 'TR' ||
23
- tag === 'TH' ||
24
- element.onclick != null ||
25
- element.getAttribute('role') === 'button');
26
- //|| element.className.includes("btn")
27
- // MBTODO: intersept addEventListener
28
- }
29
- //TODO: fix (typescript is not sure about target variable after assignation of svg)
30
- function getTarget(target, document) {
31
- if (target instanceof Element) {
32
- return _getTarget(target, document);
33
- }
34
- return null;
35
- }
36
- function _getTarget(target, document) {
37
- let element = target;
38
- while (element !== null && element !== document.documentElement) {
39
- if (hasOpenreplayAttribute(element, 'masked')) {
40
- return null;
41
- }
42
- element = element.parentElement;
43
- }
44
- if (isSVGElement(target)) {
45
- let owner = target.ownerSVGElement;
46
- while (owner !== null) {
47
- target = owner;
48
- owner = owner.ownerSVGElement;
49
- }
50
- }
51
- element = target;
52
- while (element !== null && element !== document.documentElement) {
53
- const tag = element.tagName.toUpperCase();
54
- if (tag === 'LABEL') {
55
- return null;
56
- }
57
- if (tag === 'INPUT') {
58
- return element;
59
- }
60
- if (isClickable(element) || getLabelAttribute(element) !== null) {
61
- return element;
62
- }
63
- element = element.parentElement;
64
- }
65
- return target === document.documentElement ? null : target;
66
- }
67
- export default function (app) {
68
- function getTargetLabel(target) {
69
- const dl = getLabelAttribute(target);
70
- if (dl !== null) {
71
- return dl;
72
- }
73
- if (hasTag(target, 'input')) {
74
- return getInputLabel(target);
75
- }
76
- if (isClickable(target)) {
77
- let label = '';
78
- if (target instanceof HTMLElement) {
79
- label = app.sanitizer.getInnerTextSecure(target);
80
- }
81
- label = label || target.id || target.className;
82
- return normSpaces(label).slice(0, 100);
83
- }
84
- return '';
85
- }
86
- let mousePositionX = -1;
87
- let mousePositionY = -1;
88
- let mousePositionChanged = false;
89
- let mouseTarget = null;
90
- let mouseTargetTime = 0;
91
- let selectorMap = {};
92
- app.attachStopCallback(() => {
93
- mousePositionX = -1;
94
- mousePositionY = -1;
95
- mousePositionChanged = false;
96
- mouseTarget = null;
97
- selectorMap = {};
98
- });
99
- const sendMouseMove = () => {
100
- if (mousePositionChanged) {
101
- app.send(MouseMove(mousePositionX, mousePositionY));
102
- mousePositionChanged = false;
103
- }
104
- };
105
- const patchDocument = (document, topframe = false) => {
106
- function getSelector(id, target) {
107
- return (selectorMap[id] = selectorMap[id] || _getSelector(target, document));
108
- }
109
- const attachListener = topframe
110
- ? app.attachEventListener.bind(app) // attached/removed on start/stop
111
- : app.nodes.attachNodeListener.bind(app.nodes); // attached/removed on node register/unregister
112
- attachListener(document.documentElement, 'mouseover', (e) => {
113
- const target = getTarget(e.target, document);
114
- if (target !== mouseTarget) {
115
- mouseTarget = target;
116
- mouseTargetTime = performance.now();
117
- }
118
- });
119
- attachListener(document, 'mousemove', (e) => {
120
- const [left, top] = app.observer.getDocumentOffset(document); // MBTODO?: document-id related message
121
- mousePositionX = e.clientX + left;
122
- mousePositionY = e.clientY + top;
123
- mousePositionChanged = true;
124
- }, false);
125
- attachListener(document, 'click', (e) => {
126
- const target = getTarget(e.target, document);
127
- if ((!e.clientX && !e.clientY) || target === null) {
128
- return;
129
- }
130
- const id = app.nodes.getID(target);
131
- if (id !== undefined) {
132
- sendMouseMove();
133
- app.send(MouseClick(id, mouseTarget === target ? Math.round(performance.now() - mouseTargetTime) : 0, getTargetLabel(target), isClickable(target) ? getSelector(id, target) : ''), true);
134
- }
135
- mouseTarget = null;
136
- });
137
- };
138
- app.nodes.attachNodeCallback((node) => {
139
- if (isDocument(node)) {
140
- patchDocument(node);
141
- }
142
- });
143
- patchDocument(document, true);
144
- app.ticker.attach(sendMouseMove, 10);
145
- }
@@ -1,28 +0,0 @@
1
- import type App from '../app/index.js';
2
- type XHRRequestBody = Parameters<XMLHttpRequest['send']>[0];
3
- type FetchRequestBody = RequestInit['body'];
4
- interface RequestData {
5
- body: XHRRequestBody | FetchRequestBody;
6
- headers: Record<string, string>;
7
- }
8
- interface ResponseData {
9
- body: any;
10
- headers: Record<string, string>;
11
- }
12
- interface RequestResponseData {
13
- readonly status: number;
14
- readonly method: string;
15
- url: string;
16
- request: RequestData;
17
- response: ResponseData;
18
- }
19
- type Sanitizer = (data: RequestResponseData) => RequestResponseData | null;
20
- export interface Options {
21
- sessionTokenHeader: string | boolean;
22
- failuresOnly: boolean;
23
- ignoreHeaders: Array<string> | boolean;
24
- capturePayload: boolean;
25
- sanitizer?: Sanitizer;
26
- }
27
- export default function (app: App, opts?: Partial<Options>): void;
28
- export {};
@@ -1,200 +0,0 @@
1
- import { NetworkRequest } from '../app/messages.gen.js';
2
- import { getTimeOrigin } from '../utils.js';
3
- function getXHRRequestDataObject(xhr) {
4
- // @ts-ignore this is 3x faster than using Map<XHR, XHRRequestData>
5
- if (!xhr.__or_req_data__) {
6
- // @ts-ignore
7
- xhr.__or_req_data__ = { body: undefined, headers: {} };
8
- }
9
- // @ts-ignore
10
- return xhr.__or_req_data__;
11
- }
12
- function strMethod(method) {
13
- return typeof method === 'string' ? method.toUpperCase() : 'GET';
14
- }
15
- export default function (app, opts = {}) {
16
- const options = Object.assign({
17
- failuresOnly: false,
18
- ignoreHeaders: ['Cookie', 'Set-Cookie', 'Authorization'],
19
- capturePayload: false,
20
- sessionTokenHeader: false,
21
- }, opts);
22
- const ignoreHeaders = options.ignoreHeaders;
23
- const isHIgnored = Array.isArray(ignoreHeaders)
24
- ? (name) => ignoreHeaders.includes(name)
25
- : () => ignoreHeaders;
26
- const stHeader = options.sessionTokenHeader === true ? 'X-OpenReplay-SessionToken' : options.sessionTokenHeader;
27
- function setSessionTokenHeader(setRequestHeader) {
28
- if (stHeader) {
29
- const sessionToken = app.getSessionToken();
30
- if (sessionToken) {
31
- app.safe(setRequestHeader)(stHeader, sessionToken);
32
- }
33
- }
34
- }
35
- function sanitize(reqResInfo) {
36
- if (!options.capturePayload) {
37
- delete reqResInfo.request.body;
38
- delete reqResInfo.response.body;
39
- }
40
- if (options.sanitizer) {
41
- const resBody = reqResInfo.response.body;
42
- if (typeof resBody === 'string') {
43
- // Parse response in order to have handy view in sanitisation function
44
- try {
45
- reqResInfo.response.body = JSON.parse(resBody);
46
- }
47
- catch (_a) { }
48
- }
49
- return options.sanitizer(reqResInfo);
50
- }
51
- return reqResInfo;
52
- }
53
- function stringify(r) {
54
- if (r && typeof r.body !== 'string') {
55
- try {
56
- r.body = JSON.stringify(r.body);
57
- }
58
- catch (_a) {
59
- r.body = '<unable to stringify>';
60
- app.notify.warn("Openreplay fetch couldn't stringify body:", r.body);
61
- }
62
- }
63
- return JSON.stringify(r);
64
- }
65
- /* ====== Fetch ====== */
66
- const origFetch = window.fetch.bind(window);
67
- window.fetch = (input, init = {}) => {
68
- if (!(typeof input === 'string' || input instanceof URL) || app.isServiceURL(String(input))) {
69
- return origFetch(input, init);
70
- }
71
- setSessionTokenHeader(function (name, value) {
72
- if (init.headers === undefined) {
73
- init.headers = {};
74
- }
75
- if (init.headers instanceof Headers) {
76
- init.headers.append(name, value);
77
- }
78
- else if (Array.isArray(init.headers)) {
79
- init.headers.push([name, value]);
80
- }
81
- else {
82
- init.headers[name] = value;
83
- }
84
- });
85
- const startTime = performance.now();
86
- return origFetch(input, init).then((response) => {
87
- const duration = performance.now() - startTime;
88
- if (options.failuresOnly && response.status < 400) {
89
- return response;
90
- }
91
- const r = response.clone();
92
- r.text()
93
- .then((text) => {
94
- const reqHs = {};
95
- const resHs = {};
96
- if (ignoreHeaders !== true) {
97
- // request headers
98
- const writeReqHeader = ([n, v]) => {
99
- if (!isHIgnored(n)) {
100
- reqHs[n] = v;
101
- }
102
- };
103
- if (init.headers instanceof Headers) {
104
- init.headers.forEach((v, n) => writeReqHeader([n, v]));
105
- }
106
- else if (Array.isArray(init.headers)) {
107
- init.headers.forEach(writeReqHeader);
108
- }
109
- else if (typeof init.headers === 'object') {
110
- Object.entries(init.headers).forEach(writeReqHeader);
111
- }
112
- // response headers
113
- r.headers.forEach((v, n) => {
114
- if (!isHIgnored(n))
115
- resHs[n] = v;
116
- });
117
- }
118
- const method = strMethod(init.method);
119
- const reqResInfo = sanitize({
120
- url: String(input),
121
- method,
122
- status: r.status,
123
- request: {
124
- headers: reqHs,
125
- body: init.body,
126
- },
127
- response: {
128
- headers: resHs,
129
- body: text,
130
- },
131
- });
132
- if (!reqResInfo) {
133
- return;
134
- }
135
- app.send(NetworkRequest('fetch', method, String(reqResInfo.url), stringify(reqResInfo.request), stringify(reqResInfo.response), r.status, startTime + getTimeOrigin(), duration));
136
- })
137
- .catch((e) => app.debug.error('Could not process Fetch response:', e));
138
- return response;
139
- });
140
- };
141
- /* ====== <> ====== */
142
- /* ====== XHR ====== */
143
- const nativeOpen = XMLHttpRequest.prototype.open;
144
- XMLHttpRequest.prototype.open = function (initMethod, url) {
145
- const xhr = this;
146
- setSessionTokenHeader((name, value) => xhr.setRequestHeader(name, value));
147
- let startTime = 0;
148
- xhr.addEventListener('loadstart', (e) => {
149
- startTime = e.timeStamp;
150
- });
151
- xhr.addEventListener('load', app.safe((e) => {
152
- const { headers: reqHs, body: reqBody } = getXHRRequestDataObject(xhr);
153
- const duration = startTime > 0 ? e.timeStamp - startTime : 0;
154
- const hString = ignoreHeaders ? '' : xhr.getAllResponseHeaders(); // might be null (though only if no response received though)
155
- const resHs = hString
156
- ? hString
157
- .split('\r\n')
158
- .map((h) => h.split(':'))
159
- .filter((entry) => !isHIgnored(entry[0]))
160
- .reduce((hds, [name, value]) => (Object.assign(Object.assign({}, hds), { [name]: value })), {})
161
- : {};
162
- const method = strMethod(initMethod);
163
- const reqResInfo = sanitize({
164
- url: String(url),
165
- method,
166
- status: xhr.status,
167
- request: {
168
- headers: reqHs,
169
- body: reqBody,
170
- },
171
- response: {
172
- headers: resHs,
173
- body: xhr.response,
174
- },
175
- });
176
- if (!reqResInfo) {
177
- return;
178
- }
179
- app.send(NetworkRequest('xhr', method, String(reqResInfo.url), stringify(reqResInfo.request), stringify(reqResInfo.response), xhr.status, startTime + getTimeOrigin(), duration));
180
- }));
181
- //TODO: handle error (though it has no Error API nor any useful information)
182
- //xhr.addEventListener('error', (e) => {})
183
- return nativeOpen.apply(this, arguments);
184
- };
185
- const nativeSend = XMLHttpRequest.prototype.send;
186
- XMLHttpRequest.prototype.send = function (body) {
187
- const rdo = getXHRRequestDataObject(this);
188
- rdo.body = body;
189
- return nativeSend.apply(this, arguments);
190
- };
191
- const nativeSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
192
- XMLHttpRequest.prototype.setRequestHeader = function (name, value) {
193
- if (!isHIgnored(name)) {
194
- const rdo = getXHRRequestDataObject(this);
195
- rdo.headers[name] = value;
196
- }
197
- return nativeSetRequestHeader.apply(this, arguments);
198
- };
199
- /* ====== <> ====== */
200
- }
@@ -1,7 +0,0 @@
1
- import type App from '../app/index.js';
2
- export declare const deviceMemory: number;
3
- export declare const jsHeapSizeLimit: number;
4
- export interface Options {
5
- capturePerformance: boolean;
6
- }
7
- export default function (app: App, opts: Partial<Options>): void;
@@ -1,49 +0,0 @@
1
- import { IN_BROWSER } from '../utils.js';
2
- import { PerformanceTrack } from '../app/messages.gen.js';
3
- const perf = IN_BROWSER && 'performance' in window && 'memory' in performance // works in Chrome only
4
- ? performance
5
- : { memory: {} };
6
- export const deviceMemory = IN_BROWSER ? (navigator.deviceMemory || 0) * 1024 : 0;
7
- export const jsHeapSizeLimit = perf.memory.jsHeapSizeLimit || 0;
8
- export default function (app, opts) {
9
- const options = Object.assign({
10
- capturePerformance: true,
11
- }, opts);
12
- if (!options.capturePerformance) {
13
- return;
14
- }
15
- let frames;
16
- let ticks;
17
- const nextFrame = () => {
18
- if (frames === undefined || frames === -1) {
19
- return;
20
- }
21
- frames++;
22
- requestAnimationFrame(nextFrame);
23
- };
24
- app.ticker.attach(() => {
25
- if (ticks === undefined || ticks === -1) {
26
- return;
27
- }
28
- ticks++;
29
- }, 0, false);
30
- const sendPerformanceTrack = () => {
31
- if (frames === undefined || ticks === undefined) {
32
- return;
33
- }
34
- app.send(PerformanceTrack(frames, ticks, perf.memory.totalJSHeapSize || 0, perf.memory.usedJSHeapSize || 0));
35
- ticks = frames = document.hidden ? -1 : 0;
36
- };
37
- app.attachStartCallback(() => {
38
- ticks = frames = -1;
39
- sendPerformanceTrack();
40
- nextFrame();
41
- });
42
- app.attachStopCallback(() => {
43
- ticks = frames = undefined;
44
- });
45
- app.ticker.attach(sendPerformanceTrack, 40, false);
46
- if (document.hidden !== undefined) {
47
- app.attachEventListener(document, 'visibilitychange', sendPerformanceTrack, false, false);
48
- }
49
- }
@@ -1,2 +0,0 @@
1
- import type App from '../app/index.js';
2
- export default function (app: App): void;
@@ -1,76 +0,0 @@
1
- import { SetViewportScroll, SetNodeScroll } from '../app/messages.gen.js';
2
- import { isNode, isElementNode, isRootNode, isDocument } from '../app/guards.js';
3
- function getDocumentScroll(doc) {
4
- const win = doc.defaultView;
5
- return [
6
- (win && win.pageXOffset) ||
7
- (doc.documentElement && doc.documentElement.scrollLeft) ||
8
- (doc.body && doc.body.scrollLeft) ||
9
- 0,
10
- (win && win.pageYOffset) ||
11
- (doc.documentElement && doc.documentElement.scrollTop) ||
12
- (doc.body && doc.body.scrollTop) ||
13
- 0,
14
- ];
15
- }
16
- export default function (app) {
17
- let documentScroll = false;
18
- const nodeScroll = new Map();
19
- function setNodeScroll(target) {
20
- if (!isNode(target)) {
21
- return;
22
- }
23
- if (isElementNode(target)) {
24
- nodeScroll.set(target, [target.scrollLeft, target.scrollTop]);
25
- }
26
- if (isDocument(target)) {
27
- nodeScroll.set(target, getDocumentScroll(target));
28
- }
29
- }
30
- const sendSetViewportScroll = app.safe(() => app.send(SetViewportScroll(...getDocumentScroll(document))));
31
- const sendSetNodeScroll = app.safe((s, node) => {
32
- const id = app.nodes.getID(node);
33
- if (id !== undefined) {
34
- app.send(SetNodeScroll(id, s[0], s[1]));
35
- }
36
- });
37
- app.attachStartCallback(sendSetViewportScroll);
38
- app.attachStopCallback(() => {
39
- documentScroll = false;
40
- nodeScroll.clear();
41
- });
42
- app.nodes.attachNodeCallback((node, isStart) => {
43
- // MBTODO: iterate over all the nodes on start instead of using isStart hack
44
- if (isStart) {
45
- if (isElementNode(node) && node.scrollLeft + node.scrollTop > 0) {
46
- nodeScroll.set(node, [node.scrollLeft, node.scrollTop]);
47
- }
48
- else if (isDocument(node)) {
49
- // DRY somehow?
50
- nodeScroll.set(node, getDocumentScroll(node));
51
- }
52
- }
53
- if (isRootNode(node)) {
54
- // scroll is not-composed event (https://javascript.info/shadow-dom-events)
55
- app.nodes.attachNodeListener(node, 'scroll', (e) => {
56
- setNodeScroll(e.target);
57
- });
58
- }
59
- });
60
- app.attachEventListener(document, 'scroll', (e) => {
61
- const target = e.target;
62
- if (target === document) {
63
- documentScroll = true;
64
- return;
65
- }
66
- setNodeScroll(target);
67
- });
68
- app.ticker.attach(() => {
69
- if (documentScroll) {
70
- sendSetViewportScroll();
71
- documentScroll = false;
72
- }
73
- nodeScroll.forEach(sendSetNodeScroll);
74
- nodeScroll.clear();
75
- }, 5, false);
76
- }
@@ -1,7 +0,0 @@
1
- import type App from '../app/index.js';
2
- export interface Options {
3
- captureResourceTimings: boolean;
4
- capturePageLoadTimings: boolean;
5
- capturePageRenderTimings: boolean;
6
- }
7
- export default function (app: App, opts: Partial<Options>): void;