@openreplay/tracker 3.6.2 → 4.0.1
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/.eslintignore +8 -0
- package/.prettierignore +1 -0
- package/LICENSE +1 -1
- package/cjs/app/guards.d.ts +2 -1
- package/cjs/app/guards.js +6 -3
- package/cjs/app/index.d.ts +28 -23
- package/cjs/app/index.js +107 -86
- package/cjs/app/logger.js +6 -3
- package/cjs/app/messages.d.ts +52 -0
- package/cjs/app/messages.gen.d.ts +58 -0
- package/cjs/app/messages.gen.js +501 -0
- package/cjs/app/messages.js +234 -0
- package/cjs/app/nodes.d.ts +1 -1
- package/cjs/app/nodes.js +2 -0
- package/cjs/app/observer/iframe_observer.d.ts +1 -1
- package/cjs/app/observer/iframe_observer.js +3 -3
- package/cjs/app/observer/observer.d.ts +2 -3
- package/cjs/app/observer/observer.js +50 -52
- package/cjs/app/observer/shadow_root_observer.d.ts +1 -1
- package/cjs/app/observer/shadow_root_observer.js +3 -3
- package/cjs/app/observer/top_observer.d.ts +13 -2
- package/cjs/app/observer/top_observer.js +58 -23
- package/cjs/app/sanitizer.d.ts +1 -1
- package/cjs/app/sanitizer.js +5 -5
- package/cjs/app/session.d.ts +20 -2
- package/cjs/app/session.js +65 -6
- package/cjs/app/ticker.d.ts +1 -1
- package/cjs/common/{webworker.d.ts → interaction.d.ts} +5 -5
- package/cjs/common/{types.js → interaction.js} +0 -0
- package/cjs/common/messages.gen.d.ts +388 -0
- package/cjs/common/{webworker.js → messages.gen.js} +1 -0
- package/cjs/index.d.ts +10 -9
- package/cjs/index.js +47 -36
- package/cjs/modules/adoptedStyleSheets.d.ts +2 -0
- package/cjs/modules/adoptedStyleSheets.js +127 -0
- package/cjs/modules/connection.d.ts +1 -1
- package/cjs/modules/connection.js +2 -2
- package/cjs/modules/console.d.ts +1 -1
- package/cjs/modules/console.js +7 -21
- package/cjs/modules/cssrules.d.ts +1 -1
- package/cjs/modules/cssrules.js +18 -14
- package/cjs/modules/exception.d.ts +3 -3
- package/cjs/modules/exception.js +23 -18
- package/cjs/modules/img.d.ts +1 -1
- package/cjs/modules/img.js +39 -26
- package/cjs/modules/input.d.ts +1 -1
- package/cjs/modules/input.js +21 -21
- package/cjs/modules/mouse.d.ts +1 -1
- package/cjs/modules/mouse.js +50 -43
- package/cjs/modules/performance.d.ts +1 -1
- package/cjs/modules/performance.js +2 -2
- package/cjs/modules/scroll.d.ts +1 -1
- package/cjs/modules/scroll.js +16 -7
- package/cjs/modules/timing.d.ts +1 -1
- package/cjs/modules/timing.js +14 -26
- package/cjs/modules/viewport.d.ts +1 -1
- package/cjs/modules/viewport.js +4 -4
- package/cjs/utils.js +7 -7
- package/cjs/vendors/finder/finder.js +53 -48
- package/lib/app/guards.d.ts +2 -1
- package/lib/app/guards.js +4 -2
- package/lib/app/index.d.ts +28 -23
- package/lib/app/index.js +115 -94
- package/lib/app/logger.js +6 -3
- package/lib/app/messages.d.ts +52 -0
- package/lib/app/messages.gen.d.ts +58 -0
- package/lib/app/messages.gen.js +441 -0
- package/lib/app/messages.js +181 -0
- package/lib/app/nodes.d.ts +1 -1
- package/lib/app/nodes.js +2 -0
- package/lib/app/observer/iframe_observer.d.ts +1 -1
- package/lib/app/observer/iframe_observer.js +3 -3
- package/lib/app/observer/observer.d.ts +2 -3
- package/lib/app/observer/observer.js +51 -53
- package/lib/app/observer/shadow_root_observer.d.ts +1 -1
- package/lib/app/observer/shadow_root_observer.js +3 -3
- package/lib/app/observer/top_observer.d.ts +13 -2
- package/lib/app/observer/top_observer.js +62 -27
- package/lib/app/sanitizer.d.ts +1 -1
- package/lib/app/sanitizer.js +7 -7
- package/lib/app/session.d.ts +20 -2
- package/lib/app/session.js +65 -6
- package/lib/app/ticker.d.ts +1 -1
- package/lib/common/{webworker.d.ts → interaction.d.ts} +5 -5
- package/lib/common/{types.js → interaction.js} +0 -0
- package/lib/common/messages.gen.d.ts +388 -0
- package/lib/common/messages.gen.js +2 -0
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.d.ts +10 -9
- package/lib/index.js +60 -49
- package/lib/modules/adoptedStyleSheets.d.ts +2 -0
- package/lib/modules/adoptedStyleSheets.js +124 -0
- package/lib/modules/connection.d.ts +1 -1
- package/lib/modules/connection.js +2 -2
- package/lib/modules/console.d.ts +1 -1
- package/lib/modules/console.js +8 -22
- package/lib/modules/cssrules.d.ts +1 -1
- package/lib/modules/cssrules.js +19 -15
- package/lib/modules/exception.d.ts +3 -3
- package/lib/modules/exception.js +23 -18
- package/lib/modules/img.d.ts +1 -1
- package/lib/modules/img.js +41 -28
- package/lib/modules/input.d.ts +1 -1
- package/lib/modules/input.js +23 -23
- package/lib/modules/mouse.d.ts +1 -1
- package/lib/modules/mouse.js +53 -46
- package/lib/modules/performance.d.ts +1 -1
- package/lib/modules/performance.js +3 -3
- package/lib/modules/scroll.d.ts +1 -1
- package/lib/modules/scroll.js +17 -8
- package/lib/modules/timing.d.ts +1 -1
- package/lib/modules/timing.js +16 -28
- package/lib/modules/viewport.d.ts +1 -1
- package/lib/modules/viewport.js +4 -4
- package/lib/utils.js +7 -7
- package/lib/vendors/finder/finder.js +53 -48
- package/package.json +27 -10
- package/cjs/common/messages.d.ts +0 -444
- package/cjs/common/messages.js +0 -794
- package/cjs/common/types.d.ts +0 -9
- package/cjs/modules/longtasks.d.ts +0 -2
- package/cjs/modules/longtasks.js +0 -26
- package/lib/common/messages.d.ts +0 -444
- package/lib/common/messages.js +0 -790
- package/lib/common/types.d.ts +0 -9
- package/lib/common/webworker.js +0 -1
- package/lib/modules/longtasks.d.ts +0 -2
- package/lib/modules/longtasks.js +0 -23
package/lib/index.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import App, { DEFAULT_INGEST_POINT } from
|
|
1
|
+
import App, { DEFAULT_INGEST_POINT } from './app/index.js';
|
|
2
2
|
export { default as App } from './app/index.js';
|
|
3
|
-
import { UserAnonymousID, RawCustomEvent, CustomIssue } from
|
|
4
|
-
import * as _Messages from
|
|
3
|
+
import { UserAnonymousID, RawCustomEvent, CustomIssue } from './app/messages.gen.js';
|
|
4
|
+
import * as _Messages from './app/messages.gen.js';
|
|
5
5
|
export const Messages = _Messages;
|
|
6
|
-
import Connection from
|
|
7
|
-
import Console from
|
|
8
|
-
import Exception, { getExceptionMessageFromEvent, getExceptionMessage } from
|
|
9
|
-
import Img from
|
|
10
|
-
import Input from
|
|
11
|
-
import Mouse from
|
|
12
|
-
import Timing from
|
|
13
|
-
import Performance from
|
|
14
|
-
import Scroll from
|
|
15
|
-
import Viewport from
|
|
16
|
-
import CSSRules from
|
|
17
|
-
import
|
|
6
|
+
import Connection from './modules/connection.js';
|
|
7
|
+
import Console from './modules/console.js';
|
|
8
|
+
import Exception, { getExceptionMessageFromEvent, getExceptionMessage, } from './modules/exception.js';
|
|
9
|
+
import Img from './modules/img.js';
|
|
10
|
+
import Input from './modules/input.js';
|
|
11
|
+
import Mouse from './modules/mouse.js';
|
|
12
|
+
import Timing from './modules/timing.js';
|
|
13
|
+
import Performance from './modules/performance.js';
|
|
14
|
+
import Scroll from './modules/scroll.js';
|
|
15
|
+
import Viewport from './modules/viewport.js';
|
|
16
|
+
import CSSRules from './modules/cssrules.js';
|
|
17
|
+
import AdoptedStyleSheets from './modules/adoptedStyleSheets.js';
|
|
18
|
+
import { IN_BROWSER, deprecationWarn, DOCS_HOST } from './utils.js';
|
|
18
19
|
const DOCS_SETUP = '/installation/setup-or';
|
|
19
20
|
function processOptions(obj) {
|
|
20
21
|
if (obj == null) {
|
|
@@ -23,22 +24,23 @@ function processOptions(obj) {
|
|
|
23
24
|
}
|
|
24
25
|
if (typeof obj.projectKey !== 'string') {
|
|
25
26
|
if (typeof obj.projectKey !== 'number') {
|
|
26
|
-
if (typeof obj.projectID !== 'number') {
|
|
27
|
+
if (typeof obj.projectID !== 'number') {
|
|
28
|
+
// Back compatability
|
|
27
29
|
console.error(`OpenReplay: projectKey is missing or wrong type (string is expected). Please, check ${DOCS_HOST}${DOCS_SETUP} for more information.`);
|
|
28
30
|
return false;
|
|
29
31
|
}
|
|
30
32
|
else {
|
|
31
33
|
obj.projectKey = obj.projectID.toString();
|
|
32
|
-
deprecationWarn(
|
|
34
|
+
deprecationWarn('`projectID` option', '`projectKey` option', DOCS_SETUP);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
else {
|
|
36
|
-
console.warn(
|
|
38
|
+
console.warn('OpenReplay: projectKey is expected to have a string type.');
|
|
37
39
|
obj.projectKey = obj.projectKey.toString();
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
+
if (obj.sessionToken != null) {
|
|
43
|
+
deprecationWarn('`sessionToken` option', '`sessionHash` start() option', '/');
|
|
42
44
|
}
|
|
43
45
|
return true;
|
|
44
46
|
}
|
|
@@ -65,31 +67,33 @@ export default class API {
|
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
67
69
|
if (window.__OPENREPLAY__) {
|
|
68
|
-
console.error(
|
|
70
|
+
console.error('OpenReplay: one tracker instance has been initialised already');
|
|
69
71
|
return;
|
|
70
72
|
}
|
|
71
73
|
if (!options.__DISABLE_SECURE_MODE && location.protocol !== 'https:') {
|
|
72
|
-
console.error(
|
|
74
|
+
console.error('OpenReplay: Your website must be publicly accessible and running on SSL in order for OpenReplay to properly capture and replay the user session. You can disable this check by setting `__DISABLE_SECURE_MODE` option to `true` if you are testing in localhost. Keep in mind, that asset files on a local machine are not available to the outside world. This might affect tracking if you use css files.');
|
|
73
75
|
return;
|
|
74
76
|
}
|
|
75
77
|
const doNotTrack = options.respectDoNotTrack &&
|
|
76
|
-
(navigator.doNotTrack == '1'
|
|
78
|
+
(navigator.doNotTrack == '1' ||
|
|
77
79
|
// @ts-ignore
|
|
78
|
-
|
|
79
|
-
const app = this.app =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
window.doNotTrack == '1');
|
|
81
|
+
const app = (this.app =
|
|
82
|
+
doNotTrack ||
|
|
83
|
+
!('Map' in window) ||
|
|
84
|
+
!('Set' in window) ||
|
|
85
|
+
!('MutationObserver' in window) ||
|
|
86
|
+
!('performance' in window) ||
|
|
87
|
+
!('timing' in performance) ||
|
|
88
|
+
!('startsWith' in String.prototype) ||
|
|
89
|
+
!('Blob' in window) ||
|
|
90
|
+
!('Worker' in window)
|
|
91
|
+
? null
|
|
92
|
+
: new App(options.projectKey, options.sessionToken, options));
|
|
90
93
|
if (app !== null) {
|
|
91
94
|
Viewport(app);
|
|
92
95
|
CSSRules(app);
|
|
96
|
+
AdoptedStyleSheets(app);
|
|
93
97
|
Connection(app);
|
|
94
98
|
Console(app, options);
|
|
95
99
|
Exception(app, options);
|
|
@@ -119,11 +123,11 @@ export default class API {
|
|
|
119
123
|
console.log("OpenReplay: browser doesn't support API required for tracking or doNotTrack is set to 1.");
|
|
120
124
|
const req = new XMLHttpRequest();
|
|
121
125
|
const orig = options.ingestPoint || DEFAULT_INGEST_POINT;
|
|
122
|
-
req.open(
|
|
126
|
+
req.open('POST', orig + '/v1/web/not-started');
|
|
123
127
|
// no-cors issue only with text/plain or not-set Content-Type
|
|
124
128
|
// req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
|
125
129
|
req.send(JSON.stringify({
|
|
126
|
-
trackerVersion: '
|
|
130
|
+
trackerVersion: '4.0.1',
|
|
127
131
|
projectKey: options.projectKey,
|
|
128
132
|
doNotTrack,
|
|
129
133
|
// TODO: add precise reason (an exact API missing)
|
|
@@ -142,7 +146,7 @@ export default class API {
|
|
|
142
146
|
start(startOpts) {
|
|
143
147
|
if (!IN_BROWSER) {
|
|
144
148
|
console.error(`OpenReplay: you are trying to start Tracker on a node.js environment. If you want to use OpenReplay with SSR, please, use componentDidMount or useEffect API for placing the \`tracker.start()\` line. Check documentation on ${DOCS_HOST}${DOCS_SETUP}`);
|
|
145
|
-
return Promise.reject(
|
|
149
|
+
return Promise.reject('Trying to start not in browser.');
|
|
146
150
|
}
|
|
147
151
|
if (this.app === null) {
|
|
148
152
|
return Promise.reject("Browser doesn't support required api, or doNotTrack is active.");
|
|
@@ -154,7 +158,10 @@ export default class API {
|
|
|
154
158
|
if (this.app === null) {
|
|
155
159
|
return;
|
|
156
160
|
}
|
|
157
|
-
this.app.stop(
|
|
161
|
+
this.app.stop();
|
|
162
|
+
const sessionHash = this.app.session.getSessionHash();
|
|
163
|
+
this.app.session.reset();
|
|
164
|
+
return sessionHash;
|
|
158
165
|
}
|
|
159
166
|
getSessionToken() {
|
|
160
167
|
if (this.app === null) {
|
|
@@ -169,36 +176,40 @@ export default class API {
|
|
|
169
176
|
return this.app.getSessionID();
|
|
170
177
|
}
|
|
171
178
|
sessionID() {
|
|
172
|
-
deprecationWarn("'sessionID' method", "'getSessionID' method",
|
|
179
|
+
deprecationWarn("'sessionID' method", "'getSessionID' method", '/');
|
|
173
180
|
return this.getSessionID();
|
|
174
181
|
}
|
|
182
|
+
getSessionURL() {
|
|
183
|
+
if (this.app === null) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return this.app.getSessionURL();
|
|
187
|
+
}
|
|
175
188
|
setUserID(id) {
|
|
176
189
|
if (typeof id === 'string' && this.app !== null) {
|
|
177
190
|
this.app.session.setUserID(id);
|
|
178
191
|
}
|
|
179
192
|
}
|
|
180
193
|
userID(id) {
|
|
181
|
-
deprecationWarn("'userID' method", "'setUserID' method",
|
|
194
|
+
deprecationWarn("'userID' method", "'setUserID' method", '/');
|
|
182
195
|
this.setUserID(id);
|
|
183
196
|
}
|
|
184
197
|
setUserAnonymousID(id) {
|
|
185
198
|
if (typeof id === 'string' && this.app !== null) {
|
|
186
|
-
this.app.send(
|
|
199
|
+
this.app.send(UserAnonymousID(id));
|
|
187
200
|
}
|
|
188
201
|
}
|
|
189
202
|
userAnonymousID(id) {
|
|
190
|
-
deprecationWarn("'userAnonymousID' method", "'setUserAnonymousID' method",
|
|
203
|
+
deprecationWarn("'userAnonymousID' method", "'setUserAnonymousID' method", '/');
|
|
191
204
|
this.setUserAnonymousID(id);
|
|
192
205
|
}
|
|
193
206
|
setMetadata(key, value) {
|
|
194
|
-
if (typeof key === 'string' &&
|
|
195
|
-
typeof value === 'string' &&
|
|
196
|
-
this.app !== null) {
|
|
207
|
+
if (typeof key === 'string' && typeof value === 'string' && this.app !== null) {
|
|
197
208
|
this.app.session.setMetadata(key, value);
|
|
198
209
|
}
|
|
199
210
|
}
|
|
200
211
|
metadata(key, value) {
|
|
201
|
-
deprecationWarn("'metadata' method", "'setMetadata' method",
|
|
212
|
+
deprecationWarn("'metadata' method", "'setMetadata' method", '/');
|
|
202
213
|
this.setMetadata(key, value);
|
|
203
214
|
}
|
|
204
215
|
event(key, payload, issue = false) {
|
|
@@ -213,7 +224,7 @@ export default class API {
|
|
|
213
224
|
catch (e) {
|
|
214
225
|
return;
|
|
215
226
|
}
|
|
216
|
-
this.app.send(
|
|
227
|
+
this.app.send(RawCustomEvent(key, payload));
|
|
217
228
|
}
|
|
218
229
|
}
|
|
219
230
|
}
|
|
@@ -225,7 +236,7 @@ export default class API {
|
|
|
225
236
|
catch (e) {
|
|
226
237
|
return;
|
|
227
238
|
}
|
|
228
|
-
this.app.send(
|
|
239
|
+
this.app.send(CustomIssue(key, payload));
|
|
229
240
|
}
|
|
230
241
|
}
|
|
231
242
|
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { TechnicalInfo, AdoptedSSReplaceURLBased, AdoptedSSInsertRuleURLBased, AdoptedSSDeleteRule, AdoptedSSAddOwner, AdoptedSSRemoveOwner, } from '../app/messages.gen.js';
|
|
2
|
+
import { isRootNode } from '../app/guards.js';
|
|
3
|
+
function hasAdoptedSS(node) {
|
|
4
|
+
return (isRootNode(node) &&
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
!!node.adoptedStyleSheets);
|
|
7
|
+
}
|
|
8
|
+
export default function (app) {
|
|
9
|
+
if (app === null) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (!hasAdoptedSS(document)) {
|
|
13
|
+
app.attachStartCallback(() => {
|
|
14
|
+
// MBTODO: pre-start sendQueue app
|
|
15
|
+
app.send(TechnicalInfo('no_adopted_stylesheets', ''));
|
|
16
|
+
});
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
let nextID = 0xf;
|
|
20
|
+
const styleSheetIDMap = new Map();
|
|
21
|
+
const adoptedStyleSheetsOwnings = new Map();
|
|
22
|
+
const updateAdoptedStyleSheets = (root) => {
|
|
23
|
+
let nodeID = app.nodes.getID(root);
|
|
24
|
+
if (root === document) {
|
|
25
|
+
nodeID = 0; // main document doesn't have nodeID. ID count starts from the documentElement
|
|
26
|
+
}
|
|
27
|
+
if (!nodeID) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let pastOwning = adoptedStyleSheetsOwnings.get(nodeID);
|
|
31
|
+
if (!pastOwning) {
|
|
32
|
+
pastOwning = [];
|
|
33
|
+
}
|
|
34
|
+
const nowOwning = [];
|
|
35
|
+
const styleSheets = root.adoptedStyleSheets;
|
|
36
|
+
for (const s of styleSheets) {
|
|
37
|
+
let sheetID = styleSheetIDMap.get(s);
|
|
38
|
+
const init = !sheetID;
|
|
39
|
+
if (!sheetID) {
|
|
40
|
+
sheetID = ++nextID;
|
|
41
|
+
}
|
|
42
|
+
nowOwning.push(sheetID);
|
|
43
|
+
if (!pastOwning.includes(sheetID)) {
|
|
44
|
+
app.send(AdoptedSSAddOwner(sheetID, nodeID));
|
|
45
|
+
}
|
|
46
|
+
if (init) {
|
|
47
|
+
const rules = s.cssRules;
|
|
48
|
+
for (let i = 0; i < rules.length; i++) {
|
|
49
|
+
app.send(AdoptedSSInsertRuleURLBased(sheetID, rules[i].cssText, i, app.getBaseHref()));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const sheetID of pastOwning) {
|
|
54
|
+
if (!nowOwning.includes(sheetID)) {
|
|
55
|
+
app.send(AdoptedSSRemoveOwner(sheetID, nodeID));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
adoptedStyleSheetsOwnings.set(nodeID, nowOwning);
|
|
59
|
+
};
|
|
60
|
+
function patchAdoptedStyleSheets(prototype) {
|
|
61
|
+
const nativeAdoptedStyleSheetsDescriptor = Object.getOwnPropertyDescriptor(prototype, 'adoptedStyleSheets');
|
|
62
|
+
if (nativeAdoptedStyleSheetsDescriptor) {
|
|
63
|
+
Object.defineProperty(prototype, 'adoptedStyleSheets', Object.assign(Object.assign({}, nativeAdoptedStyleSheetsDescriptor), { set: function (value) {
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
const retVal = nativeAdoptedStyleSheetsDescriptor.set.call(this, value);
|
|
66
|
+
updateAdoptedStyleSheets(this);
|
|
67
|
+
return retVal;
|
|
68
|
+
} }));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const patchContext = (context) => {
|
|
72
|
+
patchAdoptedStyleSheets(context.Document.prototype);
|
|
73
|
+
patchAdoptedStyleSheets(context.ShadowRoot.prototype);
|
|
74
|
+
//@ts-ignore TODO: configure ts (use necessary lib)
|
|
75
|
+
const { insertRule, deleteRule, replace, replaceSync } = context.CSSStyleSheet.prototype;
|
|
76
|
+
//@ts-ignore
|
|
77
|
+
context.CSSStyleSheet.prototype.replace = function (text) {
|
|
78
|
+
return replace.call(this, text).then((sheet) => {
|
|
79
|
+
const sheetID = styleSheetIDMap.get(this);
|
|
80
|
+
if (sheetID) {
|
|
81
|
+
app.send(AdoptedSSReplaceURLBased(sheetID, text, app.getBaseHref()));
|
|
82
|
+
}
|
|
83
|
+
return sheet;
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
//@ts-ignore
|
|
87
|
+
context.CSSStyleSheet.prototype.replaceSync = function (text) {
|
|
88
|
+
const sheetID = styleSheetIDMap.get(this);
|
|
89
|
+
if (sheetID) {
|
|
90
|
+
app.send(AdoptedSSReplaceURLBased(sheetID, text, app.getBaseHref()));
|
|
91
|
+
}
|
|
92
|
+
return replaceSync.call(this, text);
|
|
93
|
+
};
|
|
94
|
+
context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
|
|
95
|
+
const sheetID = styleSheetIDMap.get(this);
|
|
96
|
+
if (sheetID) {
|
|
97
|
+
app.send(AdoptedSSInsertRuleURLBased(sheetID, rule, index, app.getBaseHref()));
|
|
98
|
+
}
|
|
99
|
+
return insertRule.call(this, rule, index);
|
|
100
|
+
};
|
|
101
|
+
context.CSSStyleSheet.prototype.deleteRule = function (index) {
|
|
102
|
+
const sheetID = styleSheetIDMap.get(this);
|
|
103
|
+
if (sheetID) {
|
|
104
|
+
app.send(AdoptedSSDeleteRule(sheetID, index));
|
|
105
|
+
}
|
|
106
|
+
return deleteRule.call(this, index);
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
patchContext(window);
|
|
110
|
+
app.observer.attachContextCallback(patchContext);
|
|
111
|
+
app.attachStopCallback(() => {
|
|
112
|
+
styleSheetIDMap.clear();
|
|
113
|
+
adoptedStyleSheetsOwnings.clear();
|
|
114
|
+
});
|
|
115
|
+
// So far main Document is not triggered with nodeCallbacks
|
|
116
|
+
app.attachStartCallback(() => {
|
|
117
|
+
updateAdoptedStyleSheets(document);
|
|
118
|
+
});
|
|
119
|
+
app.nodes.attachNodeCallback((node) => {
|
|
120
|
+
if (hasAdoptedSS(node)) {
|
|
121
|
+
updateAdoptedStyleSheets(node);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import App from
|
|
1
|
+
import App from '../app/index.js';
|
|
2
2
|
export default function (app: App): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConnectionInformation } from
|
|
1
|
+
import { ConnectionInformation } from '../app/messages.gen.js';
|
|
2
2
|
export default function (app) {
|
|
3
3
|
const connection = navigator.connection ||
|
|
4
4
|
navigator.mozConnection ||
|
|
@@ -6,7 +6,7 @@ export default function (app) {
|
|
|
6
6
|
if (connection === undefined) {
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
|
-
const sendConnectionInformation = () => app.send(
|
|
9
|
+
const sendConnectionInformation = () => app.send(ConnectionInformation(Math.round(connection.downlink * 1000), connection.type || 'unknown'));
|
|
10
10
|
sendConnectionInformation();
|
|
11
11
|
connection.addEventListener('change', sendConnectionInformation);
|
|
12
12
|
}
|
package/lib/modules/console.d.ts
CHANGED
package/lib/modules/console.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ConsoleLog } from "../common/messages.js";
|
|
1
|
+
import { IN_BROWSER } from '../utils.js';
|
|
2
|
+
import { ConsoleLog } from '../app/messages.gen.js';
|
|
4
3
|
const printError = IN_BROWSER && 'InstallTrigger' in window // detect Firefox
|
|
5
4
|
? (e) => e.message + '\n' + e.stack
|
|
6
5
|
: (e) => e.stack || e.message;
|
|
@@ -87,11 +86,10 @@ export default function (app, opts) {
|
|
|
87
86
|
consoleMethods,
|
|
88
87
|
consoleThrottling: 30,
|
|
89
88
|
}, opts);
|
|
90
|
-
if (!Array.isArray(options.consoleMethods) ||
|
|
91
|
-
options.consoleMethods.length === 0) {
|
|
89
|
+
if (!Array.isArray(options.consoleMethods) || options.consoleMethods.length === 0) {
|
|
92
90
|
return;
|
|
93
91
|
}
|
|
94
|
-
const sendConsoleLog = app.safe((level, args) => app.send(
|
|
92
|
+
const sendConsoleLog = app.safe((level, args) => app.send(ConsoleLog(level, printf(args))));
|
|
95
93
|
let n;
|
|
96
94
|
const reset = () => {
|
|
97
95
|
n = 0;
|
|
@@ -100,7 +98,7 @@ export default function (app, opts) {
|
|
|
100
98
|
app.ticker.attach(reset, 33, false);
|
|
101
99
|
const patchConsole = (console) => options.consoleMethods.forEach((method) => {
|
|
102
100
|
if (consoleMethods.indexOf(method) === -1) {
|
|
103
|
-
|
|
101
|
+
app.debug.error(`OpenReplay: unsupported console method "${method}"`);
|
|
104
102
|
return;
|
|
105
103
|
}
|
|
106
104
|
const fn = console[method];
|
|
@@ -112,19 +110,7 @@ export default function (app, opts) {
|
|
|
112
110
|
sendConsoleLog(method, args);
|
|
113
111
|
};
|
|
114
112
|
});
|
|
115
|
-
patchConsole(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
let context = node.contentWindow;
|
|
119
|
-
if (context) {
|
|
120
|
-
patchConsole(context.console);
|
|
121
|
-
}
|
|
122
|
-
app.attachEventListener(node, "load", () => {
|
|
123
|
-
if (node.contentWindow !== context) {
|
|
124
|
-
context = node.contentWindow;
|
|
125
|
-
patchConsole(context.console);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}));
|
|
113
|
+
const patchContext = app.safe((context) => patchConsole(context.console));
|
|
114
|
+
patchContext(window);
|
|
115
|
+
app.observer.attachContextCallback(patchContext);
|
|
130
116
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type App from
|
|
1
|
+
import type App from '../app/index.js';
|
|
2
2
|
export default function (app: App | null): void;
|
package/lib/modules/cssrules.js
CHANGED
|
@@ -1,37 +1,41 @@
|
|
|
1
|
-
import { CSSInsertRuleURLBased, CSSDeleteRule, TechnicalInfo } from
|
|
2
|
-
import { hasTag } from
|
|
1
|
+
import { CSSInsertRuleURLBased, CSSDeleteRule, TechnicalInfo } from '../app/messages.gen.js';
|
|
2
|
+
import { hasTag } from '../app/guards.js';
|
|
3
3
|
export default function (app) {
|
|
4
4
|
if (app === null) {
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
7
7
|
if (!window.CSSStyleSheet) {
|
|
8
|
-
app.send(
|
|
8
|
+
app.send(TechnicalInfo('no_stylesheet_prototype_in_window', ''));
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
const processOperation = app.safe((stylesheet, index, rule) => {
|
|
12
12
|
const sendMessage = typeof rule === 'string'
|
|
13
|
-
? (nodeID) => app.send(
|
|
14
|
-
: (nodeID) => app.send(
|
|
13
|
+
? (nodeID) => app.send(CSSInsertRuleURLBased(nodeID, rule, index, app.getBaseHref()))
|
|
14
|
+
: (nodeID) => app.send(CSSDeleteRule(nodeID, index));
|
|
15
15
|
// TODO: Extend messages to maintain nested rules (CSSGroupingRule prototype, as well as CSSKeyframesRule)
|
|
16
16
|
if (stylesheet.ownerNode == null) {
|
|
17
|
-
throw new Error(
|
|
17
|
+
throw new Error('Owner Node not found');
|
|
18
18
|
}
|
|
19
19
|
const nodeID = app.nodes.getID(stylesheet.ownerNode);
|
|
20
20
|
if (nodeID !== undefined) {
|
|
21
21
|
sendMessage(nodeID);
|
|
22
22
|
} // else error?
|
|
23
23
|
});
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const patchContext = (context) => {
|
|
25
|
+
const { insertRule, deleteRule } = context.CSSStyleSheet.prototype;
|
|
26
|
+
context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
|
|
27
|
+
processOperation(this, index, rule);
|
|
28
|
+
return insertRule.call(this, rule, index);
|
|
29
|
+
};
|
|
30
|
+
context.CSSStyleSheet.prototype.deleteRule = function (index) {
|
|
31
|
+
processOperation(this, index);
|
|
32
|
+
return deleteRule.call(this, index);
|
|
33
|
+
};
|
|
32
34
|
};
|
|
35
|
+
patchContext(window);
|
|
36
|
+
app.observer.attachContextCallback(patchContext);
|
|
33
37
|
app.nodes.attachNodeCallback((node) => {
|
|
34
|
-
if (!hasTag(node,
|
|
38
|
+
if (!hasTag(node, 'STYLE') || !node.sheet) {
|
|
35
39
|
return;
|
|
36
40
|
}
|
|
37
41
|
if (node.textContent !== null && node.textContent.trim().length > 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type App from
|
|
2
|
-
import type Message from
|
|
1
|
+
import type App from '../app/index.js';
|
|
2
|
+
import type Message from '../app/messages.gen.js';
|
|
3
3
|
export interface Options {
|
|
4
4
|
captureExceptions: boolean;
|
|
5
5
|
}
|
|
@@ -11,6 +11,6 @@ interface StackFrame {
|
|
|
11
11
|
source?: string;
|
|
12
12
|
}
|
|
13
13
|
export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>): Message;
|
|
14
|
-
export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent): Message | null;
|
|
14
|
+
export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis): Message | null;
|
|
15
15
|
export default function (app: App, opts: Partial<Options>): void;
|
|
16
16
|
export {};
|
package/lib/modules/exception.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import { JSException } from
|
|
1
|
+
import { JSException } from '../app/messages.gen.js';
|
|
2
2
|
import ErrorStackParser from 'error-stack-parser';
|
|
3
3
|
function getDefaultStack(e) {
|
|
4
|
-
return [
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
5
6
|
columnNumber: e.colno,
|
|
6
7
|
lineNumber: e.lineno,
|
|
7
8
|
fileName: e.filename,
|
|
8
|
-
functionName:
|
|
9
|
-
source:
|
|
10
|
-
}
|
|
9
|
+
functionName: '',
|
|
10
|
+
source: '',
|
|
11
|
+
},
|
|
12
|
+
];
|
|
11
13
|
}
|
|
12
14
|
export function getExceptionMessage(error, fallbackStack) {
|
|
13
15
|
let stack = fallbackStack;
|
|
14
16
|
try {
|
|
15
17
|
stack = ErrorStackParser.parse(error);
|
|
16
18
|
}
|
|
17
|
-
catch (e) {
|
|
18
|
-
|
|
19
|
-
return new JSException(error.name, error.message, JSON.stringify(stack));
|
|
19
|
+
catch (e) { }
|
|
20
|
+
return JSException(error.name, error.message, JSON.stringify(stack));
|
|
20
21
|
}
|
|
21
|
-
export function getExceptionMessageFromEvent(e) {
|
|
22
|
+
export function getExceptionMessageFromEvent(e, context = window) {
|
|
22
23
|
if (e instanceof ErrorEvent) {
|
|
23
24
|
if (e.error instanceof Error) {
|
|
24
25
|
return getExceptionMessage(e.error, getDefaultStack(e));
|
|
@@ -29,10 +30,10 @@ export function getExceptionMessageFromEvent(e) {
|
|
|
29
30
|
name = 'Error';
|
|
30
31
|
message = e.message;
|
|
31
32
|
}
|
|
32
|
-
return
|
|
33
|
+
return JSException(name, message, JSON.stringify(getDefaultStack(e)));
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
|
-
else if ('PromiseRejectionEvent' in
|
|
36
|
+
else if ('PromiseRejectionEvent' in context && e instanceof context.PromiseRejectionEvent) {
|
|
36
37
|
if (e.reason instanceof Error) {
|
|
37
38
|
return getExceptionMessage(e.reason, []);
|
|
38
39
|
}
|
|
@@ -44,7 +45,7 @@ export function getExceptionMessageFromEvent(e) {
|
|
|
44
45
|
catch (_) {
|
|
45
46
|
message = String(e.reason);
|
|
46
47
|
}
|
|
47
|
-
return
|
|
48
|
+
return JSException('Unhandled Promise Rejection', message, '[]');
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
return null;
|
|
@@ -53,14 +54,18 @@ export default function (app, opts) {
|
|
|
53
54
|
const options = Object.assign({
|
|
54
55
|
captureExceptions: true,
|
|
55
56
|
}, opts);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const msg = getExceptionMessageFromEvent(e);
|
|
57
|
+
function patchContext(context) {
|
|
58
|
+
function handler(e) {
|
|
59
|
+
const msg = getExceptionMessageFromEvent(e, context);
|
|
59
60
|
if (msg != null) {
|
|
60
61
|
app.send(msg);
|
|
61
62
|
}
|
|
62
|
-
}
|
|
63
|
-
app.attachEventListener(
|
|
64
|
-
app.attachEventListener(
|
|
63
|
+
}
|
|
64
|
+
app.attachEventListener(context, 'unhandledrejection', handler);
|
|
65
|
+
app.attachEventListener(context, 'error', handler);
|
|
66
|
+
}
|
|
67
|
+
if (options.captureExceptions) {
|
|
68
|
+
app.observer.attachContextCallback(patchContext);
|
|
69
|
+
patchContext(window);
|
|
65
70
|
}
|
|
66
71
|
}
|
package/lib/modules/img.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type App from
|
|
1
|
+
import type App from '../app/index.js';
|
|
2
2
|
export default function (app: App): void;
|