@openreplay/tracker 18.0.1 → 18.0.3
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/dist/cjs/entry.js +117 -18
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +117 -18
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/index.d.ts +4 -4
- package/dist/cjs/main/app/observer/observer.d.ts +6 -0
- package/dist/lib/entry.js +117 -18
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +117 -18
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/index.d.ts +4 -4
- package/dist/lib/main/app/observer/observer.d.ts +6 -0
- package/dist/types/main/app/index.d.ts +4 -4
- package/dist/types/main/app/observer/observer.d.ts +6 -0
- package/package.json +2 -2
package/dist/cjs/entry.js
CHANGED
|
@@ -2390,8 +2390,44 @@ function inlineRemoteCss(node, id, baseHref, getNextID, insertRule, addOwner, fo
|
|
|
2390
2390
|
})
|
|
2391
2391
|
.catch(error => {
|
|
2392
2392
|
console.error(`OpenReplay: Failed to fetch CSS from ${node.href}:`, error);
|
|
2393
|
+
// Fetch failed (likely CORS) — retry via load event + sheet access
|
|
2394
|
+
retryViaLoadEvent();
|
|
2393
2395
|
});
|
|
2394
2396
|
}
|
|
2397
|
+
else {
|
|
2398
|
+
retryViaLoadEvent();
|
|
2399
|
+
}
|
|
2400
|
+
function retryViaLoadEvent() {
|
|
2401
|
+
const trySheet = () => {
|
|
2402
|
+
const loadedSheet = node.sheet;
|
|
2403
|
+
if (loadedSheet) {
|
|
2404
|
+
try {
|
|
2405
|
+
const cssText = stringifyStylesheet(loadedSheet);
|
|
2406
|
+
if (cssText) {
|
|
2407
|
+
if (sendPlain && onPlain) {
|
|
2408
|
+
onPlain(cssText, fakeIdHolder++);
|
|
2409
|
+
}
|
|
2410
|
+
else {
|
|
2411
|
+
processCssText(cssText);
|
|
2412
|
+
}
|
|
2413
|
+
return;
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
catch (e) {
|
|
2417
|
+
// cross-origin sheet — nothing more we can do
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2421
|
+
if (node.sheet) {
|
|
2422
|
+
trySheet();
|
|
2423
|
+
}
|
|
2424
|
+
else {
|
|
2425
|
+
node.addEventListener('load', function onLoad() {
|
|
2426
|
+
node.removeEventListener('load', onLoad);
|
|
2427
|
+
trySheet();
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2395
2431
|
function processCssText(cssText) {
|
|
2396
2432
|
// Remove comments
|
|
2397
2433
|
cssText = cssText.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
@@ -2613,7 +2649,6 @@ function ConstructedStyleSheets (app) {
|
|
|
2613
2649
|
if (!hasAdoptedSS(document)) {
|
|
2614
2650
|
return;
|
|
2615
2651
|
}
|
|
2616
|
-
const styleSheetIDMap = new Map();
|
|
2617
2652
|
const adoptedStyleSheetsOwnings = new Map();
|
|
2618
2653
|
const sendAdoptedStyleSheetsUpdate = (root) => setTimeout(() => {
|
|
2619
2654
|
let nodeID = app.nodes.getID(root);
|
|
@@ -2878,6 +2913,12 @@ class Observer {
|
|
|
2878
2913
|
this.inlineRemoteCss = false;
|
|
2879
2914
|
this.inlinerOptions = undefined;
|
|
2880
2915
|
this.domParser = new DOMParser();
|
|
2916
|
+
/**
|
|
2917
|
+
* Bumped on every disconnect(). Stale async CSS-inlining callbacks from a
|
|
2918
|
+
* previous session (e.g. agent reload → tracker restart) compare against
|
|
2919
|
+
* this and bail instead of sending messages that reference vanished node ids.
|
|
2920
|
+
*/
|
|
2921
|
+
this.generation = 0;
|
|
2881
2922
|
this.throttling = true;
|
|
2882
2923
|
this.throttledSetNodeData = throttleWithTrailing((id, parentElement, data) => this.sendNodeData(id, parentElement, data), 30);
|
|
2883
2924
|
this.throttling = !Boolean(options.disableThrottling);
|
|
@@ -3024,18 +3065,23 @@ class Observer {
|
|
|
3024
3065
|
}
|
|
3025
3066
|
if (name === 'style' || (name === 'href' && hasTag(node, 'link'))) {
|
|
3026
3067
|
if ('rel' in node && node.rel === 'stylesheet' && this.inlineRemoteCss) {
|
|
3068
|
+
const gen = this.generation;
|
|
3027
3069
|
setTimeout(() => {
|
|
3028
3070
|
inlineRemoteCss(
|
|
3029
3071
|
// @ts-ignore
|
|
3030
3072
|
node, id, this.app.getBaseHref(), nextID, (id, cssText, index, baseHref) => {
|
|
3073
|
+
if (this.generation !== gen)
|
|
3074
|
+
return;
|
|
3031
3075
|
this.app.send(AdoptedSSInsertRuleURLBased(id, cssText, index, baseHref));
|
|
3032
3076
|
}, (sheetId, ownerId) => {
|
|
3077
|
+
if (this.generation !== gen)
|
|
3078
|
+
return;
|
|
3033
3079
|
this.app.send(AdoptedSSAddOwner(sheetId, ownerId));
|
|
3034
3080
|
}, this.inlinerOptions?.forceFetch, this.inlinerOptions?.forcePlain, (cssText, fakeTextId) => {
|
|
3081
|
+
if (this.generation !== gen)
|
|
3082
|
+
return;
|
|
3035
3083
|
this.app.send(CreateTextNode(fakeTextId, id, 0));
|
|
3036
|
-
|
|
3037
|
-
this.app.send(SetCSSDataURLBased(fakeTextId, cssText, this.app.getBaseHref()));
|
|
3038
|
-
}, 10);
|
|
3084
|
+
this.app.send(SetCSSDataURLBased(fakeTextId, cssText, this.app.getBaseHref()));
|
|
3039
3085
|
});
|
|
3040
3086
|
}, 0);
|
|
3041
3087
|
return;
|
|
@@ -3299,6 +3345,7 @@ class Observer {
|
|
|
3299
3345
|
this.observer.disconnect();
|
|
3300
3346
|
this.clear();
|
|
3301
3347
|
this.throttledSetNodeData.clear();
|
|
3348
|
+
this.generation++;
|
|
3302
3349
|
}
|
|
3303
3350
|
}
|
|
3304
3351
|
|
|
@@ -3962,7 +4009,7 @@ class App {
|
|
|
3962
4009
|
this.stopCallbacks = [];
|
|
3963
4010
|
this.commitCallbacks = [];
|
|
3964
4011
|
this.activityState = ActivityState.NotActive;
|
|
3965
|
-
this.version = '18.0.
|
|
4012
|
+
this.version = '18.0.3'; // TODO: version compatability check inside each plugin.
|
|
3966
4013
|
this.socketMode = false;
|
|
3967
4014
|
this.compressionThreshold = 24 * 1000;
|
|
3968
4015
|
this.bc = null;
|
|
@@ -3984,12 +4031,19 @@ class App {
|
|
|
3984
4031
|
if (!data || event.source === window)
|
|
3985
4032
|
return;
|
|
3986
4033
|
if (data.line === proto.startIframe) {
|
|
3987
|
-
|
|
4034
|
+
// Avoid corrupting an in-flight start; let it complete.
|
|
4035
|
+
if (this.activityState === ActivityState.Starting)
|
|
3988
4036
|
return;
|
|
3989
4037
|
try {
|
|
4038
|
+
if (this.active()) {
|
|
4039
|
+
this.stop();
|
|
4040
|
+
}
|
|
3990
4041
|
if (data.token) {
|
|
3991
4042
|
this.session.setSessionToken(data.token, this.projectKey);
|
|
3992
4043
|
}
|
|
4044
|
+
if (data.id !== undefined) {
|
|
4045
|
+
this.rootId = data.id;
|
|
4046
|
+
}
|
|
3993
4047
|
this.allowAppStart();
|
|
3994
4048
|
void this.start();
|
|
3995
4049
|
}
|
|
@@ -4015,17 +4069,22 @@ class App {
|
|
|
4015
4069
|
}
|
|
4016
4070
|
}
|
|
4017
4071
|
};
|
|
4018
|
-
/**
|
|
4019
|
-
* context ids for iframes,
|
|
4020
|
-
* order is not so important as long as its consistent
|
|
4021
|
-
* */
|
|
4022
4072
|
this.trackedFrames = [];
|
|
4073
|
+
this.frameLastSeen = new Map();
|
|
4074
|
+
this.FRAME_STALE_MS = 1500;
|
|
4023
4075
|
this.crossDomainIframeListener = (event) => {
|
|
4024
|
-
if (
|
|
4076
|
+
if (event.source === window)
|
|
4025
4077
|
return;
|
|
4026
4078
|
const { data } = event;
|
|
4027
4079
|
if (!data)
|
|
4028
4080
|
return;
|
|
4081
|
+
// Record liveness regardless of our own active state so the queue can prune
|
|
4082
|
+
// stale contexts reliably once we resume dispatching commands after a cycle.
|
|
4083
|
+
if ((data.line === proto.polling || data.line === proto.iframeSignal) && data.context) {
|
|
4084
|
+
this.frameLastSeen.set(data.context, Date.now());
|
|
4085
|
+
}
|
|
4086
|
+
if (!this.active())
|
|
4087
|
+
return;
|
|
4029
4088
|
if (data.line === proto.iframeSignal) {
|
|
4030
4089
|
// @ts-ignore
|
|
4031
4090
|
event.source?.postMessage({ ping: true, line: proto.parentAlive }, '*');
|
|
@@ -4123,20 +4182,41 @@ class App {
|
|
|
4123
4182
|
if (!this.pollingQueue.order.length) {
|
|
4124
4183
|
return;
|
|
4125
4184
|
}
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4185
|
+
this.pruneStaleFrames();
|
|
4186
|
+
const liveSet = new Set(this.trackedFrames);
|
|
4187
|
+
while (this.pollingQueue.order.length > 0) {
|
|
4188
|
+
const head = this.pollingQueue.order[0];
|
|
4189
|
+
this.pollingQueue[head] = this.pollingQueue[head].filter((ctx) => liveSet.has(ctx));
|
|
4190
|
+
if (this.pollingQueue[head].length === 0) {
|
|
4191
|
+
delete this.pollingQueue[head];
|
|
4192
|
+
this.pollingQueue.order.shift();
|
|
4193
|
+
}
|
|
4194
|
+
else {
|
|
4195
|
+
break;
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
if (!this.pollingQueue.order.length) {
|
|
4129
4199
|
return;
|
|
4130
4200
|
}
|
|
4201
|
+
const nextCommand = this.pollingQueue.order[0];
|
|
4131
4202
|
if (this.pollingQueue[nextCommand].includes(data.context)) {
|
|
4132
4203
|
this.pollingQueue[nextCommand] = this.pollingQueue[nextCommand].filter((c) => c !== data.context);
|
|
4133
4204
|
const message = { line: nextCommand };
|
|
4134
4205
|
if (nextCommand === proto.startIframe) {
|
|
4135
4206
|
message.token = this.session.getSessionToken(this.projectKey);
|
|
4207
|
+
const targetFrame = this.pageFrames.find((f) => f.contentWindow === event.source)
|
|
4208
|
+
|| Array.from(document.querySelectorAll('iframe')).find((f) => f.contentWindow === event.source);
|
|
4209
|
+
if (targetFrame) {
|
|
4210
|
+
const nodeId = targetFrame[this.options.node_id];
|
|
4211
|
+
if (nodeId !== undefined) {
|
|
4212
|
+
message.id = nodeId;
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4136
4215
|
}
|
|
4137
4216
|
// @ts-ignore
|
|
4138
4217
|
event.source?.postMessage(message, '*');
|
|
4139
4218
|
if (this.pollingQueue[nextCommand].length === 0) {
|
|
4219
|
+
delete this.pollingQueue[nextCommand];
|
|
4140
4220
|
this.pollingQueue.order.shift();
|
|
4141
4221
|
}
|
|
4142
4222
|
}
|
|
@@ -4150,6 +4230,11 @@ class App {
|
|
|
4150
4230
|
order: [],
|
|
4151
4231
|
};
|
|
4152
4232
|
this.addCommand = (cmd) => {
|
|
4233
|
+
this.pruneStaleFrames();
|
|
4234
|
+
if (this.pollingQueue[cmd]) {
|
|
4235
|
+
this.pollingQueue[cmd] = Array.from(new Set([...this.pollingQueue[cmd], ...this.trackedFrames]));
|
|
4236
|
+
return;
|
|
4237
|
+
}
|
|
4153
4238
|
this.pollingQueue.order.push(cmd);
|
|
4154
4239
|
this.pollingQueue[cmd] = [...this.trackedFrames];
|
|
4155
4240
|
};
|
|
@@ -4462,6 +4547,16 @@ class App {
|
|
|
4462
4547
|
};
|
|
4463
4548
|
}
|
|
4464
4549
|
}
|
|
4550
|
+
pruneStaleFrames() {
|
|
4551
|
+
const staleAfter = Date.now() - this.FRAME_STALE_MS;
|
|
4552
|
+
this.trackedFrames = this.trackedFrames.filter((ctx) => {
|
|
4553
|
+
const last = this.frameLastSeen.get(ctx);
|
|
4554
|
+
if (last !== undefined && last >= staleAfter)
|
|
4555
|
+
return true;
|
|
4556
|
+
this.frameLastSeen.delete(ctx);
|
|
4557
|
+
return false;
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4465
4560
|
allowAppStart() {
|
|
4466
4561
|
this.canStart = true;
|
|
4467
4562
|
if (this.startTimeout) {
|
|
@@ -5043,6 +5138,9 @@ class App {
|
|
|
5043
5138
|
if (Object.keys(startOpts).length !== 0) {
|
|
5044
5139
|
this.prevOpts = startOpts;
|
|
5045
5140
|
}
|
|
5141
|
+
if (startOpts.startCallback) {
|
|
5142
|
+
this.userStartCallback = startOpts.startCallback;
|
|
5143
|
+
}
|
|
5046
5144
|
const isColdStart = this.activityState === ActivityState.ColdStart;
|
|
5047
5145
|
if (isColdStart && this.coldInterval) {
|
|
5048
5146
|
clearInterval(this.coldInterval);
|
|
@@ -5184,8 +5282,8 @@ class App {
|
|
|
5184
5282
|
// TODO: start as early as possible (before receiving the token)
|
|
5185
5283
|
/** after start */
|
|
5186
5284
|
this.startCallbacks.forEach((cb) => cb(onStartInfo)); // MBTODO: callbacks after DOM "mounted" (observed)
|
|
5187
|
-
if (
|
|
5188
|
-
|
|
5285
|
+
if (this.userStartCallback) {
|
|
5286
|
+
this.userStartCallback(SuccessfulStart(onStartInfo));
|
|
5189
5287
|
}
|
|
5190
5288
|
this.activityState = ActivityState.Active;
|
|
5191
5289
|
if (this.options.crossdomain?.enabled) {
|
|
@@ -5348,6 +5446,7 @@ class App {
|
|
|
5348
5446
|
this.canvasRecorder?.clear();
|
|
5349
5447
|
this.messages.length = 0;
|
|
5350
5448
|
this.parentActive = false;
|
|
5449
|
+
this.pageFrames = [];
|
|
5351
5450
|
}
|
|
5352
5451
|
finally {
|
|
5353
5452
|
this.activityState = ActivityState.NotActive;
|
|
@@ -8877,7 +8976,7 @@ class ConstantProperties {
|
|
|
8877
8976
|
user_id: this.user_id,
|
|
8878
8977
|
distinct_id: this.deviceId,
|
|
8879
8978
|
sdk_edition: 'web',
|
|
8880
|
-
sdk_version: '18.0.
|
|
8979
|
+
sdk_version: '18.0.3',
|
|
8881
8980
|
timezone: getUTCOffsetString(),
|
|
8882
8981
|
search_engine: this.searchEngine,
|
|
8883
8982
|
};
|
|
@@ -9579,7 +9678,7 @@ class API {
|
|
|
9579
9678
|
this.signalStartIssue = (reason, missingApi) => {
|
|
9580
9679
|
const doNotTrack = this.checkDoNotTrack();
|
|
9581
9680
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
9582
|
-
trackerVersion: '18.0.
|
|
9681
|
+
trackerVersion: '18.0.3',
|
|
9583
9682
|
projectKey: this.options.projectKey,
|
|
9584
9683
|
doNotTrack,
|
|
9585
9684
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|