@openreplay/tracker 16.4.10-beta.0 → 16.4.11-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/common/messages.gen.d.ts +57 -7
- package/dist/cjs/entry.js +555 -240
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +555 -240
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/guards.d.ts +1 -0
- package/dist/cjs/main/app/index.d.ts +5 -5
- package/dist/cjs/main/app/messages.gen.d.ts +7 -2
- package/dist/cjs/main/app/observer/observer.d.ts +4 -0
- package/dist/cjs/main/app/observer/top_observer.d.ts +2 -1
- package/dist/cjs/main/index.d.ts +9 -1
- package/dist/cjs/main/modules/longAnimationTask.d.ts +25 -0
- package/dist/cjs/main/modules/tagWatcher.d.ts +1 -1
- package/dist/cjs/main/modules/webAnimations.d.ts +9 -0
- package/dist/cjs/main/utils.d.ts +3 -0
- package/dist/lib/common/messages.gen.d.ts +57 -7
- package/dist/lib/entry.js +555 -240
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +555 -240
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/guards.d.ts +1 -0
- package/dist/lib/main/app/index.d.ts +5 -5
- package/dist/lib/main/app/messages.gen.d.ts +7 -2
- package/dist/lib/main/app/observer/observer.d.ts +4 -0
- package/dist/lib/main/app/observer/top_observer.d.ts +2 -1
- package/dist/lib/main/index.d.ts +9 -1
- package/dist/lib/main/modules/longAnimationTask.d.ts +25 -0
- package/dist/lib/main/modules/tagWatcher.d.ts +1 -1
- package/dist/lib/main/modules/webAnimations.d.ts +9 -0
- package/dist/lib/main/utils.d.ts +3 -0
- package/dist/types/common/messages.gen.d.ts +57 -7
- package/dist/types/main/app/guards.d.ts +1 -0
- package/dist/types/main/app/index.d.ts +5 -5
- package/dist/types/main/app/messages.gen.d.ts +7 -2
- package/dist/types/main/app/observer/observer.d.ts +4 -0
- package/dist/types/main/app/observer/top_observer.d.ts +2 -1
- package/dist/types/main/index.d.ts +9 -1
- package/dist/types/main/modules/longAnimationTask.d.ts +25 -0
- package/dist/types/main/modules/tagWatcher.d.ts +1 -1
- package/dist/types/main/modules/webAnimations.d.ts +9 -0
- package/dist/types/main/utils.d.ts +3 -0
- package/package.json +2 -2
package/dist/lib/entry.js
CHANGED
|
@@ -56,12 +56,12 @@ fl[28] = 258, revfl[258] = 28;
|
|
|
56
56
|
var _b = freb(fdeb, 0), revfd = _b.r;
|
|
57
57
|
// map of value to reverse (assuming 16 bits)
|
|
58
58
|
var rev = new u16(32768);
|
|
59
|
-
for (var i = 0; i < 32768; ++i) {
|
|
59
|
+
for (var i$1 = 0; i$1 < 32768; ++i$1) {
|
|
60
60
|
// reverse table algorithm from SO
|
|
61
|
-
var x$1 = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1);
|
|
61
|
+
var x$1 = ((i$1 & 0xAAAA) >> 1) | ((i$1 & 0x5555) << 1);
|
|
62
62
|
x$1 = ((x$1 & 0xCCCC) >> 2) | ((x$1 & 0x3333) << 2);
|
|
63
63
|
x$1 = ((x$1 & 0xF0F0) >> 4) | ((x$1 & 0x0F0F) << 4);
|
|
64
|
-
rev[i] = (((x$1 & 0xFF00) >> 8) | ((x$1 & 0x00FF) << 8)) >> 1;
|
|
64
|
+
rev[i$1] = (((x$1 & 0xFF00) >> 8) | ((x$1 & 0x00FF) << 8)) >> 1;
|
|
65
65
|
}
|
|
66
66
|
// create huffman tree from u8 "map": index -> code length for code index
|
|
67
67
|
// mb (max bits) must be at most 15
|
|
@@ -117,18 +117,18 @@ var hMap = (function (cd, mb, r) {
|
|
|
117
117
|
});
|
|
118
118
|
// fixed length tree
|
|
119
119
|
var flt = new u8(288);
|
|
120
|
-
for (var i = 0; i < 144; ++i)
|
|
121
|
-
flt[i] = 8;
|
|
122
|
-
for (var i = 144; i < 256; ++i)
|
|
123
|
-
flt[i] = 9;
|
|
124
|
-
for (var i = 256; i < 280; ++i)
|
|
125
|
-
flt[i] = 7;
|
|
126
|
-
for (var i = 280; i < 288; ++i)
|
|
127
|
-
flt[i] = 8;
|
|
120
|
+
for (var i$1 = 0; i$1 < 144; ++i$1)
|
|
121
|
+
flt[i$1] = 8;
|
|
122
|
+
for (var i$1 = 144; i$1 < 256; ++i$1)
|
|
123
|
+
flt[i$1] = 9;
|
|
124
|
+
for (var i$1 = 256; i$1 < 280; ++i$1)
|
|
125
|
+
flt[i$1] = 7;
|
|
126
|
+
for (var i$1 = 280; i$1 < 288; ++i$1)
|
|
127
|
+
flt[i$1] = 8;
|
|
128
128
|
// fixed distance tree
|
|
129
129
|
var fdt = new u8(32);
|
|
130
|
-
for (var i = 0; i < 32; ++i)
|
|
131
|
-
fdt[i] = 5;
|
|
130
|
+
for (var i$1 = 0; i$1 < 32; ++i$1)
|
|
131
|
+
fdt[i$1] = 5;
|
|
132
132
|
// fixed length map
|
|
133
133
|
var flm = /*#__PURE__*/ hMap(flt, 9, 0);
|
|
134
134
|
// fixed distance map
|
|
@@ -1465,6 +1465,43 @@ function simpleMerge(defaultObj, givenObj) {
|
|
|
1465
1465
|
}
|
|
1466
1466
|
return result;
|
|
1467
1467
|
}
|
|
1468
|
+
function throttleWithTrailing(fn, interval) {
|
|
1469
|
+
const lastCalls = new Map();
|
|
1470
|
+
const timeouts = new Map();
|
|
1471
|
+
const lastArgs = new Map();
|
|
1472
|
+
const throttled = function (key, ...args) {
|
|
1473
|
+
const now = Date.now();
|
|
1474
|
+
const lastCall = lastCalls.get(key) ?? 0;
|
|
1475
|
+
const remaining = interval - (now - lastCall);
|
|
1476
|
+
lastArgs.set(key, args);
|
|
1477
|
+
if (remaining <= 0) {
|
|
1478
|
+
if (timeouts.has(key)) {
|
|
1479
|
+
clearTimeout(timeouts.get(key));
|
|
1480
|
+
timeouts.delete(key);
|
|
1481
|
+
}
|
|
1482
|
+
lastCalls.set(key, now);
|
|
1483
|
+
fn(key, ...args);
|
|
1484
|
+
}
|
|
1485
|
+
else if (!timeouts.has(key)) {
|
|
1486
|
+
const timeoutId = setTimeout(() => {
|
|
1487
|
+
lastCalls.set(key, Date.now());
|
|
1488
|
+
timeouts.delete(key);
|
|
1489
|
+
const finalArgs = lastArgs.get(key);
|
|
1490
|
+
fn(key, ...finalArgs);
|
|
1491
|
+
}, remaining);
|
|
1492
|
+
timeouts.set(key, timeoutId);
|
|
1493
|
+
}
|
|
1494
|
+
};
|
|
1495
|
+
throttled.clear = () => {
|
|
1496
|
+
for (const timeout of timeouts.values()) {
|
|
1497
|
+
clearTimeout(timeout);
|
|
1498
|
+
}
|
|
1499
|
+
timeouts.clear();
|
|
1500
|
+
lastArgs.clear();
|
|
1501
|
+
lastCalls.clear();
|
|
1502
|
+
};
|
|
1503
|
+
return throttled;
|
|
1504
|
+
}
|
|
1468
1505
|
|
|
1469
1506
|
// Auto-generated, do not edit
|
|
1470
1507
|
/* eslint-disable */
|
|
@@ -1675,6 +1712,13 @@ function SetNodeAttributeDictGlobal(id, name, value) {
|
|
|
1675
1712
|
value,
|
|
1676
1713
|
];
|
|
1677
1714
|
}
|
|
1715
|
+
function NodeAnimationResult(id, styles) {
|
|
1716
|
+
return [
|
|
1717
|
+
36 /* Messages.Type.NodeAnimationResult */,
|
|
1718
|
+
id,
|
|
1719
|
+
styles,
|
|
1720
|
+
];
|
|
1721
|
+
}
|
|
1678
1722
|
function CSSInsertRule(id, rule, index) {
|
|
1679
1723
|
return [
|
|
1680
1724
|
37 /* Messages.Type.CSSInsertRule */,
|
|
@@ -1803,9 +1847,9 @@ function SetNodeAttributeDict(id, name, value) {
|
|
|
1803
1847
|
value,
|
|
1804
1848
|
];
|
|
1805
1849
|
}
|
|
1806
|
-
function
|
|
1850
|
+
function ResourceTimingDeprecatedDeprecated(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator) {
|
|
1807
1851
|
return [
|
|
1808
|
-
53 /* Messages.Type.
|
|
1852
|
+
53 /* Messages.Type.ResourceTimingDeprecatedDeprecated */,
|
|
1809
1853
|
timestamp,
|
|
1810
1854
|
duration,
|
|
1811
1855
|
ttfb,
|
|
@@ -1887,6 +1931,13 @@ function CustomIssue(name, payload) {
|
|
|
1887
1931
|
payload,
|
|
1888
1932
|
];
|
|
1889
1933
|
}
|
|
1934
|
+
function SetNodeSlot(id, slotID) {
|
|
1935
|
+
return [
|
|
1936
|
+
65 /* Messages.Type.SetNodeSlot */,
|
|
1937
|
+
id,
|
|
1938
|
+
slotID,
|
|
1939
|
+
];
|
|
1940
|
+
}
|
|
1890
1941
|
function CSSInsertRuleURLBased(id, rule, index, baseURL) {
|
|
1891
1942
|
return [
|
|
1892
1943
|
67 /* Messages.Type.CSSInsertRuleURLBased */,
|
|
@@ -2019,6 +2070,47 @@ function WSChannel(chType, channelName, data, timestamp, dir, messageType) {
|
|
|
2019
2070
|
messageType,
|
|
2020
2071
|
];
|
|
2021
2072
|
}
|
|
2073
|
+
function ResourceTiming(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator, transferredSize, cached, queueing, dnsLookup, initialConnection, ssl, contentDownload, total, stalled) {
|
|
2074
|
+
return [
|
|
2075
|
+
85 /* Messages.Type.ResourceTiming */,
|
|
2076
|
+
timestamp,
|
|
2077
|
+
duration,
|
|
2078
|
+
ttfb,
|
|
2079
|
+
headerSize,
|
|
2080
|
+
encodedBodySize,
|
|
2081
|
+
decodedBodySize,
|
|
2082
|
+
url,
|
|
2083
|
+
initiator,
|
|
2084
|
+
transferredSize,
|
|
2085
|
+
cached,
|
|
2086
|
+
queueing,
|
|
2087
|
+
dnsLookup,
|
|
2088
|
+
initialConnection,
|
|
2089
|
+
ssl,
|
|
2090
|
+
contentDownload,
|
|
2091
|
+
total,
|
|
2092
|
+
stalled,
|
|
2093
|
+
];
|
|
2094
|
+
}
|
|
2095
|
+
function Incident(label, startTime, endTime) {
|
|
2096
|
+
return [
|
|
2097
|
+
87 /* Messages.Type.Incident */,
|
|
2098
|
+
label,
|
|
2099
|
+
startTime,
|
|
2100
|
+
endTime,
|
|
2101
|
+
];
|
|
2102
|
+
}
|
|
2103
|
+
function LongAnimationTask$1(name, duration, blockingDuration, firstUIEventTimestamp, startTime, scripts) {
|
|
2104
|
+
return [
|
|
2105
|
+
89 /* Messages.Type.LongAnimationTask */,
|
|
2106
|
+
name,
|
|
2107
|
+
duration,
|
|
2108
|
+
blockingDuration,
|
|
2109
|
+
firstUIEventTimestamp,
|
|
2110
|
+
startTime,
|
|
2111
|
+
scripts,
|
|
2112
|
+
];
|
|
2113
|
+
}
|
|
2022
2114
|
function InputChange(id, value, valueMasked, label, hesitationTime, inputDuration) {
|
|
2023
2115
|
return [
|
|
2024
2116
|
112 /* Messages.Type.InputChange */,
|
|
@@ -2050,9 +2142,9 @@ function UnbindNodes(totalRemovedPercent) {
|
|
|
2050
2142
|
totalRemovedPercent,
|
|
2051
2143
|
];
|
|
2052
2144
|
}
|
|
2053
|
-
function
|
|
2145
|
+
function ResourceTimingDeprecated(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator, transferredSize, cached) {
|
|
2054
2146
|
return [
|
|
2055
|
-
116 /* Messages.Type.
|
|
2147
|
+
116 /* Messages.Type.ResourceTimingDeprecated */,
|
|
2056
2148
|
timestamp,
|
|
2057
2149
|
duration,
|
|
2058
2150
|
ttfb,
|
|
@@ -2149,9 +2241,11 @@ var _Messages = /*#__PURE__*/Object.freeze({
|
|
|
2149
2241
|
Fetch: Fetch,
|
|
2150
2242
|
GraphQL: GraphQL,
|
|
2151
2243
|
GraphQLDeprecated: GraphQLDeprecated,
|
|
2244
|
+
Incident: Incident,
|
|
2152
2245
|
InputChange: InputChange,
|
|
2153
2246
|
JSException: JSException,
|
|
2154
2247
|
LoadFontFace: LoadFontFace,
|
|
2248
|
+
LongAnimationTask: LongAnimationTask$1,
|
|
2155
2249
|
LongTask: LongTask,
|
|
2156
2250
|
Metadata: Metadata,
|
|
2157
2251
|
MobX: MobX,
|
|
@@ -2163,6 +2257,7 @@ var _Messages = /*#__PURE__*/Object.freeze({
|
|
|
2163
2257
|
NetworkRequest: NetworkRequest,
|
|
2164
2258
|
NetworkRequestDeprecated: NetworkRequestDeprecated,
|
|
2165
2259
|
NgRx: NgRx,
|
|
2260
|
+
NodeAnimationResult: NodeAnimationResult,
|
|
2166
2261
|
OTable: OTable,
|
|
2167
2262
|
PageLoadTiming: PageLoadTiming,
|
|
2168
2263
|
PageRenderTiming: PageRenderTiming,
|
|
@@ -2175,6 +2270,7 @@ var _Messages = /*#__PURE__*/Object.freeze({
|
|
|
2175
2270
|
RemoveNodeAttribute: RemoveNodeAttribute,
|
|
2176
2271
|
ResourceTiming: ResourceTiming,
|
|
2177
2272
|
ResourceTimingDeprecated: ResourceTimingDeprecated,
|
|
2273
|
+
ResourceTimingDeprecatedDeprecated: ResourceTimingDeprecatedDeprecated,
|
|
2178
2274
|
SelectionChange: SelectionChange,
|
|
2179
2275
|
SetCSSDataURLBased: SetCSSDataURLBased,
|
|
2180
2276
|
SetInputChecked: SetInputChecked,
|
|
@@ -2188,6 +2284,7 @@ var _Messages = /*#__PURE__*/Object.freeze({
|
|
|
2188
2284
|
SetNodeData: SetNodeData,
|
|
2189
2285
|
SetNodeFocus: SetNodeFocus,
|
|
2190
2286
|
SetNodeScroll: SetNodeScroll,
|
|
2287
|
+
SetNodeSlot: SetNodeSlot,
|
|
2191
2288
|
SetPageLocation: SetPageLocation,
|
|
2192
2289
|
SetPageLocationDeprecated: SetPageLocationDeprecated,
|
|
2193
2290
|
SetPageVisibility: SetPageVisibility,
|
|
@@ -2262,7 +2359,7 @@ function Performance (app, opts) {
|
|
|
2262
2359
|
const WATCHED_TAGS_KEY = '__or__watched_tags__';
|
|
2263
2360
|
class TagWatcher {
|
|
2264
2361
|
constructor(params) {
|
|
2265
|
-
this.
|
|
2362
|
+
this.interval = null;
|
|
2266
2363
|
this.tags = [];
|
|
2267
2364
|
this.sessionStorage = params.sessionStorage;
|
|
2268
2365
|
this.errLog = params.errLog;
|
|
@@ -2304,9 +2401,12 @@ class TagWatcher {
|
|
|
2304
2401
|
}
|
|
2305
2402
|
setTags(tags) {
|
|
2306
2403
|
this.tags = tags;
|
|
2307
|
-
this.
|
|
2308
|
-
|
|
2309
|
-
this.
|
|
2404
|
+
if (this.interval) {
|
|
2405
|
+
clearInterval(this.interval);
|
|
2406
|
+
this.interval = null;
|
|
2407
|
+
}
|
|
2408
|
+
this.interval = setInterval(() => {
|
|
2409
|
+
this.tags.forEach((tag) => {
|
|
2310
2410
|
const possibleEls = document.querySelectorAll(tag.selector);
|
|
2311
2411
|
if (possibleEls.length > 0) {
|
|
2312
2412
|
const el = possibleEls[0];
|
|
@@ -2314,21 +2414,21 @@ class TagWatcher {
|
|
|
2314
2414
|
el.__or_watcher_tagname = tag.id;
|
|
2315
2415
|
this.observer.observe(el);
|
|
2316
2416
|
}
|
|
2317
|
-
}
|
|
2318
|
-
});
|
|
2417
|
+
});
|
|
2418
|
+
}, 500);
|
|
2319
2419
|
}
|
|
2320
2420
|
onTagRendered(tagId) {
|
|
2321
|
-
if (this.
|
|
2322
|
-
|
|
2421
|
+
if (this.tags.findIndex(t => t.id === tagId)) {
|
|
2422
|
+
this.tags = this.tags.filter((tag) => tag.id !== tagId);
|
|
2323
2423
|
}
|
|
2324
2424
|
this.onTag(tagId);
|
|
2325
2425
|
}
|
|
2326
2426
|
clear() {
|
|
2327
|
-
this.tags.forEach((tag) => {
|
|
2328
|
-
clearInterval(this.intervals[tag.id]);
|
|
2329
|
-
});
|
|
2330
2427
|
this.tags = [];
|
|
2331
|
-
this.
|
|
2428
|
+
if (this.interval) {
|
|
2429
|
+
clearInterval(this.interval);
|
|
2430
|
+
this.interval = null;
|
|
2431
|
+
}
|
|
2332
2432
|
this.observer.disconnect();
|
|
2333
2433
|
}
|
|
2334
2434
|
}
|
|
@@ -4136,6 +4236,13 @@ async function parseUseEl(useElement, mode, domParser) {
|
|
|
4136
4236
|
return;
|
|
4137
4237
|
}
|
|
4138
4238
|
let [url, symbolId] = href.split('#');
|
|
4239
|
+
if (!url && !symbolId) {
|
|
4240
|
+
console.warn('Openreplay: Invalid xlink:href or href found on <use>.');
|
|
4241
|
+
return;
|
|
4242
|
+
}
|
|
4243
|
+
if (iconCache[symbolId]) {
|
|
4244
|
+
return iconCache[symbolId];
|
|
4245
|
+
}
|
|
4139
4246
|
// happens if svg spritemap is local, fastest case for us
|
|
4140
4247
|
if (!url && symbolId) {
|
|
4141
4248
|
const hasHashtag = href.startsWith('#');
|
|
@@ -4161,13 +4268,6 @@ async function parseUseEl(useElement, mode, domParser) {
|
|
|
4161
4268
|
return;
|
|
4162
4269
|
}
|
|
4163
4270
|
}
|
|
4164
|
-
if (!url && !symbolId) {
|
|
4165
|
-
console.warn('Openreplay: Invalid xlink:href or href found on <use>.');
|
|
4166
|
-
return;
|
|
4167
|
-
}
|
|
4168
|
-
if (iconCache[symbolId]) {
|
|
4169
|
-
return iconCache[symbolId];
|
|
4170
|
-
}
|
|
4171
4271
|
let svgDoc;
|
|
4172
4272
|
if (svgUrlCache[url]) {
|
|
4173
4273
|
if (svgUrlCache[url] === 1) {
|
|
@@ -4267,6 +4367,7 @@ class Observer {
|
|
|
4267
4367
|
this.indexes = [];
|
|
4268
4368
|
this.attributesMap = new Map();
|
|
4269
4369
|
this.textSet = new Set();
|
|
4370
|
+
this.slotMap = new Map();
|
|
4270
4371
|
this.disableSprites = false;
|
|
4271
4372
|
/**
|
|
4272
4373
|
* this option means that, instead of using link element with href to load css,
|
|
@@ -4276,6 +4377,9 @@ class Observer {
|
|
|
4276
4377
|
this.inlineRemoteCss = false;
|
|
4277
4378
|
this.inlinerOptions = undefined;
|
|
4278
4379
|
this.domParser = new DOMParser();
|
|
4380
|
+
this.throttling = true;
|
|
4381
|
+
this.throttledSetNodeData = throttleWithTrailing((id, parentElement, data) => this.sendNodeData(id, parentElement, data), 30);
|
|
4382
|
+
this.throttling = !Boolean(options.disableThrottling);
|
|
4279
4383
|
this.disableSprites = Boolean(options.disableSprites);
|
|
4280
4384
|
this.inlineRemoteCss = Boolean(options.inlineRemoteCss);
|
|
4281
4385
|
this.inlinerOptions = options.inlinerOptions;
|
|
@@ -4456,6 +4560,18 @@ class Observer {
|
|
|
4456
4560
|
}
|
|
4457
4561
|
bindNode(node) {
|
|
4458
4562
|
const [id, isNew] = this.app.nodes.registerNode(node);
|
|
4563
|
+
if (isElementNode(node) && hasTag(node, 'slot')) {
|
|
4564
|
+
this.app.nodes.attachNodeListener(node, 'slotchange', () => {
|
|
4565
|
+
const sl = node;
|
|
4566
|
+
sl.assignedNodes({ flatten: true }).forEach((n) => {
|
|
4567
|
+
const nid = this.app.nodes.getID(n);
|
|
4568
|
+
if (nid !== undefined) {
|
|
4569
|
+
this.recents.set(nid, RecentsType.Removed);
|
|
4570
|
+
this.commitNode(nid);
|
|
4571
|
+
}
|
|
4572
|
+
});
|
|
4573
|
+
});
|
|
4574
|
+
}
|
|
4459
4575
|
if (isNew) {
|
|
4460
4576
|
this.recents.set(id, RecentsType.New);
|
|
4461
4577
|
}
|
|
@@ -4486,6 +4602,9 @@ class Observer {
|
|
|
4486
4602
|
}
|
|
4487
4603
|
unbindTree(node) {
|
|
4488
4604
|
const id = this.app.nodes.unregisterNode(node);
|
|
4605
|
+
if (id !== undefined) {
|
|
4606
|
+
this.slotMap.delete(id);
|
|
4607
|
+
}
|
|
4489
4608
|
if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
|
|
4490
4609
|
// Sending RemoveNode only for parent to maintain
|
|
4491
4610
|
this.app.send(RemoveNode(id));
|
|
@@ -4514,8 +4633,15 @@ class Observer {
|
|
|
4514
4633
|
if (isRootNode(node)) {
|
|
4515
4634
|
return true;
|
|
4516
4635
|
}
|
|
4517
|
-
|
|
4518
|
-
|
|
4636
|
+
let slot = node.assignedSlot;
|
|
4637
|
+
let isLightDom = false;
|
|
4638
|
+
if (slot) {
|
|
4639
|
+
// Check if the node is in light DOM (not in shadow DOM)
|
|
4640
|
+
// This is a workaround for the issue with shadow DOM and slots
|
|
4641
|
+
// where the slot is not assigned to the node in shadow DOM.
|
|
4642
|
+
isLightDom = node.getRootNode() instanceof ShadowRoot;
|
|
4643
|
+
}
|
|
4644
|
+
const parent = node.parentNode;
|
|
4519
4645
|
let parentID;
|
|
4520
4646
|
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
|
4521
4647
|
// TODO: get rid of "special" cases (there is an issue with CreateDocument altered behaviour though)
|
|
@@ -4527,7 +4653,15 @@ class Observer {
|
|
|
4527
4653
|
this.unbindTree(node);
|
|
4528
4654
|
return false;
|
|
4529
4655
|
}
|
|
4530
|
-
|
|
4656
|
+
if (isLightDom && slot) {
|
|
4657
|
+
parentID = this.app.nodes.getID(slot);
|
|
4658
|
+
// in light dom, we don't "slot" the node,
|
|
4659
|
+
// but rather use the slot as a parent
|
|
4660
|
+
slot = null;
|
|
4661
|
+
}
|
|
4662
|
+
else {
|
|
4663
|
+
parentID = this.app.nodes.getID(parent);
|
|
4664
|
+
}
|
|
4531
4665
|
if (parentID === undefined) {
|
|
4532
4666
|
this.unbindTree(node);
|
|
4533
4667
|
return false;
|
|
@@ -4587,12 +4721,35 @@ class Observer {
|
|
|
4587
4721
|
else if (isTextNode(node)) {
|
|
4588
4722
|
// for text node id != 0, hence parentID !== undefined and parent is Element
|
|
4589
4723
|
this.app.send(CreateTextNode(id, parentID, index));
|
|
4590
|
-
this.
|
|
4724
|
+
if (this.throttling) {
|
|
4725
|
+
this.throttledSetNodeData(id, parent, node.data);
|
|
4726
|
+
}
|
|
4727
|
+
else {
|
|
4728
|
+
this.sendNodeData(id, parent, node.data);
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
if (slot) {
|
|
4732
|
+
const slotID = this.app.nodes.getID(slot);
|
|
4733
|
+
if (slotID !== undefined) {
|
|
4734
|
+
this.slotMap.set(id, slotID);
|
|
4735
|
+
this.app.send(SetNodeSlot(id, slotID));
|
|
4736
|
+
}
|
|
4591
4737
|
}
|
|
4592
4738
|
return true;
|
|
4593
4739
|
}
|
|
4594
4740
|
if (recentsType === RecentsType.Removed && parentID !== undefined) {
|
|
4595
4741
|
this.app.send(MoveNode(id, parentID, index));
|
|
4742
|
+
if (slot) {
|
|
4743
|
+
const slotID = this.app.nodes.getID(slot);
|
|
4744
|
+
if (slotID !== undefined && this.slotMap.get(id) !== slotID) {
|
|
4745
|
+
this.slotMap.set(id, slotID);
|
|
4746
|
+
this.app.send(SetNodeSlot(id, slotID));
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
else if (this.slotMap.has(id)) {
|
|
4750
|
+
this.slotMap.delete(id);
|
|
4751
|
+
this.app.send(SetNodeSlot(id, 0));
|
|
4752
|
+
}
|
|
4596
4753
|
}
|
|
4597
4754
|
const attr = this.attributesMap.get(id);
|
|
4598
4755
|
if (attr !== undefined) {
|
|
@@ -4608,7 +4765,12 @@ class Observer {
|
|
|
4608
4765
|
throw 'commitNode: node is not a text';
|
|
4609
4766
|
}
|
|
4610
4767
|
// for text node id != 0, hence parent is Element
|
|
4611
|
-
this.
|
|
4768
|
+
if (this.throttling) {
|
|
4769
|
+
this.throttledSetNodeData(id, parent, node.data);
|
|
4770
|
+
}
|
|
4771
|
+
else {
|
|
4772
|
+
this.sendNodeData(id, parent, node.data);
|
|
4773
|
+
}
|
|
4612
4774
|
}
|
|
4613
4775
|
return true;
|
|
4614
4776
|
}
|
|
@@ -4651,6 +4813,7 @@ class Observer {
|
|
|
4651
4813
|
disconnect() {
|
|
4652
4814
|
this.observer.disconnect();
|
|
4653
4815
|
this.clear();
|
|
4816
|
+
this.throttledSetNodeData.clear();
|
|
4654
4817
|
}
|
|
4655
4818
|
}
|
|
4656
4819
|
|
|
@@ -4758,7 +4921,7 @@ var InlineCssMode;
|
|
|
4758
4921
|
InlineCssMode[InlineCssMode["Disabled"] = 0] = "Disabled";
|
|
4759
4922
|
/** will attempt to record the linked css file as AdoptedStyleSheet object */
|
|
4760
4923
|
InlineCssMode[InlineCssMode["Inline"] = 1] = "Inline";
|
|
4761
|
-
/** will fetch the file, then
|
|
4924
|
+
/** will fetch the file, then simulate AdoptedStyleSheets behavior programmaticaly for the replay */
|
|
4762
4925
|
InlineCssMode[InlineCssMode["InlineFetched"] = 2] = "InlineFetched";
|
|
4763
4926
|
/** will fetch the file, then save it as plain css inside <style> node */
|
|
4764
4927
|
InlineCssMode[InlineCssMode["PlainFetched"] = 3] = "PlainFetched";
|
|
@@ -4810,6 +4973,7 @@ class TopObserver extends Observer {
|
|
|
4810
4973
|
}, params.options);
|
|
4811
4974
|
const observerOptions = {
|
|
4812
4975
|
disableSprites: opts.disableSprites,
|
|
4976
|
+
disableThrottling: opts.disableThrottling,
|
|
4813
4977
|
...getInlineOptions(opts.inlineCss)
|
|
4814
4978
|
};
|
|
4815
4979
|
super(params.app, true, observerOptions);
|
|
@@ -5218,7 +5382,7 @@ class Ticker {
|
|
|
5218
5382
|
* this value is injected during build time via rollup
|
|
5219
5383
|
* */
|
|
5220
5384
|
// @ts-ignore
|
|
5221
|
-
const workerBodyFn = "!function(){\"use strict\";class t{constructor(t,s,i,e=10,n=250,h,r){this.onUnauthorised=s,this.onFailure=i,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.pageNo=r,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.lastBatchNum=0,this.ingestURL=t+\"/v1/web/i\",this.isCompressing=void 0!==h}getQueueStatus(){return 0===this.queue.length&&!this.busy}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){if(this.busy||!this.token)this.queue.push(t);else if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t);else{const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}}sendNext(){const t=this.queue.shift();if(t)if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t);else{const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}else this.busy=!1}retry(t,s,i){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout((()=>this.sendBatch(t,s,i)),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t,s,i){var e;const n=null==i?void 0:i.toString().replace(/^([^_]+)_([^_]+).*/,\"$1_$2_$3\");this.busy=!0;const h={Authorization:`Bearer ${this.token}`};s&&(h[\"Content-Encoding\"]=\"gzip\"),null!==this.token?fetch(`${this.ingestURL}?batch=${null!==(e=this.pageNo)&&void 0!==e?e:\"noPageNum\"}_${null!=n?n:\"noBatchNum\"}`,{body:t,method:\"POST\",headers:h,keepalive:t.length<65536}).then((e=>{if(401===e.status)return this.busy=!1,void this.onUnauthorised();e.status>=400?this.retry(t,s,`${null!=i?i:\"noBatchNum\"}_network:${e.status}`):(this.attemptsCount=0,this.sendNext())})).catch((e=>{console.warn(\"OpenReplay:\",e),this.retry(t,s,`${null!=i?i:\"noBatchNum\"}_reject:${e.message}`)})):setTimeout((()=>{this.sendBatch(t,s,`${null!=i?i:\"noBatchNum\"}_newToken`)}),500)}sendCompressed(t){const s=++this.lastBatchNum;this.sendBatch(t,!0,s)}sendUncompressed(t){const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}clean(){this.sendNext(),setTimeout((()=>{this.token=null,this.queue.length=0}),10)}}const s=\"function\"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let e=-1;for(let n=0,h=0,r=0;r!==s;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===s){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){i[e+=1]=240|n>>>18,i[e+=1]=128|n>>>12&63,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n;continue}}n<=127?i[e+=1]=0|n:n<=2047?(i[e+=1]=192|n>>>6,i[e+=1]=128|63&n):(i[e+=1]=224|n>>>12,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n)}return i.subarray(0,e+1)}};class i{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}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,s){this.data.set(t,s)}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 i=s.encode(t),e=i.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(i,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}}class e extends i{encode(t){switch(t[0]){case 0:case 11:case 114:case 115:return this.uint(t[1]);case 4:case 44:case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:case 20:case 38:case 70:case 75:case 76:case 77:case 82: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:case 24:case 35:case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 12:case 52:case 61:case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:case 17:case 34:case 50:case 54: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 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 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:case 27:case 30:case 41:case 45:case 46:case 43:case 63:case 64:case 79:case 124: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 28:case 29:case 42:case 117:case 118:return this.string(t[1]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);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 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.int(t[5]);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 55:return this.boolean(t[1]);case 57:case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:case 120: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 67:case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 68:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 83:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 84:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 116: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])&&this.uint(t[9])&&this.boolean(t[10]);case 119:return this.string(t[1])&&this.uint(t[2]);case 121:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 122:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 123:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])}}}class n{constructor(t,s,i,n,h,r){this.pageNo=t,this.timestamp=s,this.url=i,this.onBatch=n,this.tabId=h,this.onOfflineEnd=r,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new e(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.checkpoints=[],this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,s){for(let s=0;s<3;s++)this.sizeBuffer[s]=t>>8*s;this.encoder.set(this.sizeBuffer,s)}prepare(){if(!this.encoder.isEmpty)return;this.checkpoints.length=0;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url],s=[0,this.timestamp],i=[118,this.tabId];this.writeType(t),this.writeFields(t),this.writeWithSize(s),this.writeWithSize(i),this.isEmpty=!0}writeWithSize(t){const s=this.encoder;if(!this.writeType(t)||!s.skip(3))return!1;const i=s.getCurrentOffset(),e=this.writeFields(t);if(e){const e=s.getCurrentOffset()-i;if(e>16777215)return console.warn(\"OpenReplay: max message size overflow.\"),!1;this.writeSizeAt(e,i-3),s.checkpoint(),this.checkpoints.push(s.getCurrentOffset()),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(\"q_end\"===t[0])return this.finaliseBatch(),this.onOfflineEnd();0===t[0]&&(this.timestamp=t[1]),122===t[0]&&(this.url=t[1]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new e(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn(\"OpenReplay: beacon size overflow. Skipping large message.\",t,this),this.encoder=new e(this.beaconSize),this.prepare()))}finaliseBatch(t=!1){if(this.isEmpty)return;const s=this.encoder.flush();this.onBatch(s,t),this.prepare()}clean(){this.encoder.reset(),this.checkpoints.length=0}}var h;!function(t){t[t.NotActive=0]=\"NotActive\",t[t.Starting=1]=\"Starting\",t[t.Stopping=2]=\"Stopping\",t[t.Active=3]=\"Active\",t[t.Stopped=4]=\"Stopped\"}(h||(h={}));let r=null,a=null,u=h.NotActive;function o(t){a&&a.finaliseBatch(t)}function c(){return new Promise((t=>{u=h.Stopping,null!==p&&(clearInterval(p),p=null),a&&(a.clean(),a=null),r&&(r.clean(),setTimeout((()=>{r=null}),20)),setTimeout((()=>{u=h.NotActive,t(null)}),100)}))}function g(){[h.Stopped,h.Stopping].includes(u)||(postMessage(\"a_stop\"),c().then((()=>{postMessage(\"a_start\")})))}let l,p=null;self.onmessage=({data:s})=>{if(\"stop\"===s)return o(),void c().then((()=>{u=h.Stopped}));if(\"forceFlushBatch\"!==s)if(\"closing\"!==s){if(!Array.isArray(s)){if(\"compressed\"===s.type){if(!r)return console.debug(\"OR WebWorker: sender not initialised. Compressed batch.\"),void g();s.batch&&r.sendCompressed(s.batch)}if(\"uncompressed\"===s.type){if(!r)return console.debug(\"OR WebWorker: sender not initialised. Uncompressed batch.\"),void g();s.batch&&r.sendUncompressed(s.batch)}return\"start\"===s.type?(u=h.Starting,r=new t(s.ingestPoint,(()=>{g()}),(t=>{!function(t){postMessage({type:\"failure\",reason:t}),c()}(t)}),s.connAttemptCount,s.connAttemptGap,(t=>{postMessage({type:\"compress\",batch:t},[t.buffer])}),s.pageNo),a=new n(s.pageNo,s.timestamp,s.url,((t,s)=>{r&&(s?r.sendUncompressed(t):r.push(t))}),s.tabId,(()=>postMessage({type:\"queue_empty\"}))),null===p&&(p=setInterval(o,3e4)),u=h.Active):\"auth\"===s.type?r?a?(r.authorise(s.token),void(s.beaconSizeLimit&&a.setBeaconSizeLimit(s.beaconSizeLimit))):(console.debug(\"OR WebWorker: writer not initialised. Received auth.\"),void g()):(console.debug(\"OR WebWorker: sender not initialised. Received auth.\"),void g()):void 0}if(a){const t=a;s.forEach((s=>{55===s[0]&&(s[1]?l=setTimeout((()=>g()),18e5):clearTimeout(l)),t.writeMessage(s)}))}else postMessage(\"not_init\"),g()}else o(!0);else o()}}();\n";
|
|
5385
|
+
const workerBodyFn = "!function(){\"use strict\";class t{constructor(t,s,i,e=10,n=250,h,r){this.onUnauthorised=s,this.onFailure=i,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.pageNo=r,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.lastBatchNum=0,this.ingestURL=t+\"/v1/web/i\",this.isCompressing=void 0!==h}getQueueStatus(){return 0===this.queue.length&&!this.busy}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){if(this.busy||!this.token)this.queue.push(t);else if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t);else{const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}}sendNext(){const t=this.queue.shift();if(t)if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t);else{const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}else this.busy=!1}retry(t,s,i){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout((()=>this.sendBatch(t,s,i)),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t,s,i){var e;const n=null==i?void 0:i.toString().replace(/^([^_]+)_([^_]+).*/,\"$1_$2_$3\");this.busy=!0;const h={Authorization:`Bearer ${this.token}`};s&&(h[\"Content-Encoding\"]=\"gzip\"),null!==this.token?fetch(`${this.ingestURL}?batch=${null!==(e=this.pageNo)&&void 0!==e?e:\"noPageNum\"}_${null!=n?n:\"noBatchNum\"}`,{body:t,method:\"POST\",headers:h,keepalive:t.length<65536}).then((e=>{if(401===e.status)return this.busy=!1,void this.onUnauthorised();e.status>=400?this.retry(t,s,`${null!=i?i:\"noBatchNum\"}_network:${e.status}`):(this.attemptsCount=0,this.sendNext())})).catch((e=>{console.warn(\"OpenReplay:\",e),this.retry(t,s,`${null!=i?i:\"noBatchNum\"}_reject:${e.message}`)})):setTimeout((()=>{this.sendBatch(t,s,`${null!=i?i:\"noBatchNum\"}_newToken`)}),500)}sendCompressed(t){const s=++this.lastBatchNum;this.sendBatch(t,!0,s)}sendUncompressed(t){const s=++this.lastBatchNum;this.sendBatch(t,!1,s)}clean(){this.sendNext(),setTimeout((()=>{this.token=null,this.queue.length=0}),10)}}const s=\"function\"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let e=-1;for(let n=0,h=0,r=0;r!==s;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===s){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){i[e+=1]=240|n>>>18,i[e+=1]=128|n>>>12&63,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n;continue}}n<=127?i[e+=1]=0|n:n<=2047?(i[e+=1]=192|n>>>6,i[e+=1]=128|63&n):(i[e+=1]=224|n>>>12,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n)}return i.subarray(0,e+1)}};class i{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}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,s){this.data.set(t,s)}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 i=s.encode(t),e=i.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(i,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}}class e extends i{encode(t){switch(t[0]){case 0:case 11:case 114:case 115:return this.uint(t[1]);case 4:case 44:case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:case 20:case 38:case 65:case 70:case 75:case 76:case 77:case 82: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:case 24:case 35:case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 12:case 52:case 61:case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:case 17:case 34:case 36:case 50:case 54: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 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 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:case 27:case 30:case 41:case 45:case 46:case 43:case 63:case 64:case 79:case 124: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 28:case 29:case 42:case 117:case 118:return this.string(t[1]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);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 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.int(t[5]);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 55:return this.boolean(t[1]);case 57:case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:case 120: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 67:case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 68:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 83:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 84:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6]);case 85: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])&&this.uint(t[9])&&this.boolean(t[10])&&this.uint(t[11])&&this.uint(t[12])&&this.uint(t[13])&&this.uint(t[14])&&this.uint(t[15])&&this.uint(t[16])&&this.uint(t[17]);case 87:return this.string(t[1])&&this.int(t[2])&&this.int(t[3]);case 89:return this.string(t[1])&&this.int(t[2])&&this.int(t[3])&&this.int(t[4])&&this.int(t[5])&&this.string(t[6]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 116: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])&&this.uint(t[9])&&this.boolean(t[10]);case 119:return this.string(t[1])&&this.uint(t[2]);case 121:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 122:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 123:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])}}}class n{constructor(t,s,i,n,h,r){this.pageNo=t,this.timestamp=s,this.url=i,this.onBatch=n,this.tabId=h,this.onOfflineEnd=r,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new e(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.checkpoints=[],this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,s){for(let s=0;s<3;s++)this.sizeBuffer[s]=t>>8*s;this.encoder.set(this.sizeBuffer,s)}prepare(){if(!this.encoder.isEmpty)return;this.checkpoints.length=0;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url],s=[0,this.timestamp],i=[118,this.tabId];this.writeType(t),this.writeFields(t),this.writeWithSize(s),this.writeWithSize(i),this.isEmpty=!0}writeWithSize(t){const s=this.encoder;if(!this.writeType(t)||!s.skip(3))return!1;const i=s.getCurrentOffset(),e=this.writeFields(t);if(e){const e=s.getCurrentOffset()-i;if(e>16777215)return console.warn(\"OpenReplay: max message size overflow.\"),!1;this.writeSizeAt(e,i-3),s.checkpoint(),this.checkpoints.push(s.getCurrentOffset()),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(-1===t[0])return this.finaliseBatch(),this.onOfflineEnd();0===t[0]&&(this.timestamp=t[1]),122===t[0]&&(this.url=t[1]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new e(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn(\"OpenReplay: beacon size overflow. Skipping large message.\",t,this),this.encoder=new e(this.beaconSize),this.prepare()))}finaliseBatch(t=!1){if(this.isEmpty)return;const s=this.encoder.flush();this.onBatch(s,t),this.prepare()}clean(){this.encoder.reset(),this.checkpoints.length=0}}var h;!function(t){t[t.NotActive=0]=\"NotActive\",t[t.Starting=1]=\"Starting\",t[t.Stopping=2]=\"Stopping\",t[t.Active=3]=\"Active\",t[t.Stopped=4]=\"Stopped\"}(h||(h={}));let r=null,u=null,a=h.NotActive;function o(t){u&&u.finaliseBatch(t)}function c(){return new Promise((t=>{a=h.Stopping,null!==p&&(clearInterval(p),p=null),u&&(u.clean(),u=null),r&&(r.clean(),setTimeout((()=>{r=null}),20)),setTimeout((()=>{a=h.NotActive,t(null)}),100)}))}function g(){[h.Stopped,h.Stopping].includes(a)||(postMessage(\"a_stop\"),c().then((()=>{postMessage(\"a_start\")})))}let l,p=null;self.onmessage=({data:s})=>{if(\"stop\"===s)return o(),void c().then((()=>{a=h.Stopped}));if(\"forceFlushBatch\"!==s)if(\"closing\"!==s){if(!Array.isArray(s)){if(\"compressed\"===s.type){if(!r)return console.debug(\"OR WebWorker: sender not initialised. Compressed batch.\"),void g();s.batch&&r.sendCompressed(s.batch)}if(\"uncompressed\"===s.type){if(!r)return console.debug(\"OR WebWorker: sender not initialised. Uncompressed batch.\"),void g();s.batch&&r.sendUncompressed(s.batch)}return\"start\"===s.type?(a=h.Starting,r=new t(s.ingestPoint,(()=>{g()}),(t=>{!function(t){postMessage({type:\"failure\",reason:t}),c()}(t)}),s.connAttemptCount,s.connAttemptGap,(t=>{postMessage({type:\"compress\",batch:t},[t.buffer])}),s.pageNo),u=new n(s.pageNo,s.timestamp,s.url,((t,s)=>{r&&(s?r.sendUncompressed(t):r.push(t))}),s.tabId,(()=>postMessage({type:\"queue_empty\"}))),null===p&&(p=setInterval(o,3e4)),a=h.Active):\"auth\"===s.type?r?u?(r.authorise(s.token),void(s.beaconSizeLimit&&u.setBeaconSizeLimit(s.beaconSizeLimit))):(console.debug(\"OR WebWorker: writer not initialised. Received auth.\"),void g()):(console.debug(\"OR WebWorker: sender not initialised. Received auth.\"),void g()):void 0}if(u){const t=u;s.forEach((s=>{55===s[0]&&(s[1]?l=setTimeout((()=>g()),18e5):clearTimeout(l)),t.writeMessage(s)}))}else postMessage(\"not_init\"),g()}else o(!0);else o()}}();\n";
|
|
5222
5386
|
const CANCELED = 'canceled';
|
|
5223
5387
|
const uxtStorageKey = 'or_uxt_active';
|
|
5224
5388
|
const bufferStorageKey = 'or_buffer_1';
|
|
@@ -5272,7 +5436,7 @@ class App {
|
|
|
5272
5436
|
this.stopCallbacks = [];
|
|
5273
5437
|
this.commitCallbacks = [];
|
|
5274
5438
|
this.activityState = ActivityState.NotActive;
|
|
5275
|
-
this.version = '16.4.
|
|
5439
|
+
this.version = '16.4.11-beta.0'; // TODO: version compatability check inside each plugin.
|
|
5276
5440
|
this.socketMode = false;
|
|
5277
5441
|
this.compressionThreshold = 24 * 1000;
|
|
5278
5442
|
this.bc = null;
|
|
@@ -5376,13 +5540,6 @@ class App {
|
|
|
5376
5540
|
}
|
|
5377
5541
|
};
|
|
5378
5542
|
void signalId();
|
|
5379
|
-
if (this.active()) {
|
|
5380
|
-
// @ts-ignore
|
|
5381
|
-
event.source?.postMessage({ line: proto.startIframe }, '*');
|
|
5382
|
-
}
|
|
5383
|
-
else {
|
|
5384
|
-
this.addCommand(proto.startIframe);
|
|
5385
|
-
}
|
|
5386
5543
|
}
|
|
5387
5544
|
/**
|
|
5388
5545
|
* proxying messages from iframe to main body, so they can be in one batch (same indexes, etc)
|
|
@@ -5567,170 +5724,9 @@ class App {
|
|
|
5567
5724
|
this.orderNumber = 0;
|
|
5568
5725
|
this.coldStartTs = 0;
|
|
5569
5726
|
this.singleBuffer = false;
|
|
5570
|
-
/**
|
|
5571
|
-
* start buffering messages without starting the actual session, which gives
|
|
5572
|
-
* user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
|
|
5573
|
-
* and we will then send buffered batch, so it won't get lost
|
|
5574
|
-
* */
|
|
5575
|
-
this.coldStart = async (startOpts = {}, conditional) => {
|
|
5576
|
-
this.singleBuffer = false;
|
|
5577
|
-
const second = 1000;
|
|
5578
|
-
const isNewSession = this.checkSessionToken(startOpts.forceNew);
|
|
5579
|
-
if (conditional) {
|
|
5580
|
-
await this.setupConditionalStart(startOpts);
|
|
5581
|
-
}
|
|
5582
|
-
const cycle = () => {
|
|
5583
|
-
this.orderNumber += 1;
|
|
5584
|
-
adjustTimeOrigin();
|
|
5585
|
-
this.coldStartTs = now();
|
|
5586
|
-
if (this.orderNumber % 2 === 0) {
|
|
5587
|
-
this.bufferedMessages1.length = 0;
|
|
5588
|
-
this.bufferedMessages1.push(Timestamp(this.timestamp()));
|
|
5589
|
-
this.bufferedMessages1.push(TabData(this.session.getTabId()));
|
|
5590
|
-
}
|
|
5591
|
-
else {
|
|
5592
|
-
this.bufferedMessages2.length = 0;
|
|
5593
|
-
this.bufferedMessages2.push(Timestamp(this.timestamp()));
|
|
5594
|
-
this.bufferedMessages2.push(TabData(this.session.getTabId()));
|
|
5595
|
-
}
|
|
5596
|
-
this.stop(false);
|
|
5597
|
-
this.activityState = ActivityState.ColdStart;
|
|
5598
|
-
if (startOpts.sessionHash) {
|
|
5599
|
-
this.session.applySessionHash(startOpts.sessionHash);
|
|
5600
|
-
}
|
|
5601
|
-
if (startOpts.forceNew) {
|
|
5602
|
-
this.session.reset();
|
|
5603
|
-
}
|
|
5604
|
-
this.session.assign({
|
|
5605
|
-
userID: startOpts.userID,
|
|
5606
|
-
metadata: startOpts.metadata,
|
|
5607
|
-
});
|
|
5608
|
-
if (!isNewSession) {
|
|
5609
|
-
this.debug.log('continuing session on new tab', this.session.getTabId());
|
|
5610
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
5611
|
-
this.send(TabChange(this.session.getTabId()));
|
|
5612
|
-
}
|
|
5613
|
-
this.observer.observe();
|
|
5614
|
-
this.ticker.start();
|
|
5615
|
-
};
|
|
5616
|
-
this.coldInterval = setInterval(() => {
|
|
5617
|
-
cycle();
|
|
5618
|
-
}, 30 * second);
|
|
5619
|
-
cycle();
|
|
5620
|
-
};
|
|
5621
|
-
this.setupConditionalStart = async (startOpts) => {
|
|
5622
|
-
this.conditionsManager = new ConditionsManager(this, startOpts);
|
|
5623
|
-
const r = await fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
5624
|
-
method: 'POST',
|
|
5625
|
-
headers: {
|
|
5626
|
-
'Content-Type': 'application/json',
|
|
5627
|
-
},
|
|
5628
|
-
body: JSON.stringify({
|
|
5629
|
-
...this.getTrackerInfo(),
|
|
5630
|
-
timestamp: now(),
|
|
5631
|
-
doNotRecord: true,
|
|
5632
|
-
bufferDiff: 0,
|
|
5633
|
-
userID: this.session.getInfo().userID,
|
|
5634
|
-
token: undefined,
|
|
5635
|
-
deviceMemory,
|
|
5636
|
-
jsHeapSizeLimit,
|
|
5637
|
-
timezone: getTimezone(),
|
|
5638
|
-
width: window.screen.width,
|
|
5639
|
-
height: window.screen.height,
|
|
5640
|
-
}),
|
|
5641
|
-
});
|
|
5642
|
-
const {
|
|
5643
|
-
// this token is needed to fetch conditions and flags,
|
|
5644
|
-
// but it can't be used to record a session
|
|
5645
|
-
token, userBrowser, userCity, userCountry, userDevice, userOS, userState, projectID, features, } = await r.json();
|
|
5646
|
-
this.features = features ? features : this.features;
|
|
5647
|
-
this.session.assign({ projectID });
|
|
5648
|
-
this.session.setUserInfo({
|
|
5649
|
-
userBrowser,
|
|
5650
|
-
userCity,
|
|
5651
|
-
userCountry,
|
|
5652
|
-
userDevice,
|
|
5653
|
-
userOS,
|
|
5654
|
-
userState,
|
|
5655
|
-
});
|
|
5656
|
-
const onStartInfo = { sessionToken: token, userUUID: '', sessionID: '' };
|
|
5657
|
-
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
5658
|
-
await this.conditionsManager?.fetchConditions(projectID, token);
|
|
5659
|
-
if (this.features['feature-flags']) {
|
|
5660
|
-
await this.featureFlags.reloadFlags(token);
|
|
5661
|
-
this.conditionsManager?.processFlags(this.featureFlags.flags);
|
|
5662
|
-
}
|
|
5663
|
-
await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
5664
|
-
};
|
|
5665
5727
|
this.onSessionSent = () => {
|
|
5666
5728
|
return;
|
|
5667
5729
|
};
|
|
5668
|
-
/**
|
|
5669
|
-
* Starts offline session recording
|
|
5670
|
-
* @param {Object} startOpts - options for session start, same as .start()
|
|
5671
|
-
* @param {Function} onSessionSent - callback that will be called once session is fully sent
|
|
5672
|
-
* */
|
|
5673
|
-
this.offlineRecording = (startOpts = {}, onSessionSent) => {
|
|
5674
|
-
this.onSessionSent = onSessionSent;
|
|
5675
|
-
this.singleBuffer = true;
|
|
5676
|
-
const isNewSession = this.checkSessionToken(startOpts.forceNew);
|
|
5677
|
-
adjustTimeOrigin();
|
|
5678
|
-
this.coldStartTs = now();
|
|
5679
|
-
const saverBuffer = this.localStorage.getItem(bufferStorageKey);
|
|
5680
|
-
if (saverBuffer) {
|
|
5681
|
-
const data = JSON.parse(saverBuffer);
|
|
5682
|
-
this.bufferedMessages1 = Array.isArray(data) ? data : this.bufferedMessages1;
|
|
5683
|
-
this.localStorage.removeItem(bufferStorageKey);
|
|
5684
|
-
}
|
|
5685
|
-
this.bufferedMessages1.push(Timestamp(this.timestamp()));
|
|
5686
|
-
this.bufferedMessages1.push(TabData(this.session.getTabId()));
|
|
5687
|
-
this.activityState = ActivityState.ColdStart;
|
|
5688
|
-
if (startOpts.sessionHash) {
|
|
5689
|
-
this.session.applySessionHash(startOpts.sessionHash);
|
|
5690
|
-
}
|
|
5691
|
-
if (startOpts.forceNew) {
|
|
5692
|
-
this.session.reset();
|
|
5693
|
-
}
|
|
5694
|
-
this.session.assign({
|
|
5695
|
-
userID: startOpts.userID,
|
|
5696
|
-
metadata: startOpts.metadata,
|
|
5697
|
-
});
|
|
5698
|
-
const onStartInfo = { sessionToken: '', userUUID: '', sessionID: '' };
|
|
5699
|
-
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
5700
|
-
if (!isNewSession) {
|
|
5701
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
5702
|
-
this.send(TabChange(this.session.getTabId()));
|
|
5703
|
-
}
|
|
5704
|
-
this.observer.observe();
|
|
5705
|
-
this.ticker.start();
|
|
5706
|
-
return {
|
|
5707
|
-
saveBuffer: this.saveBuffer,
|
|
5708
|
-
getBuffer: this.getBuffer,
|
|
5709
|
-
setBuffer: this.setBuffer,
|
|
5710
|
-
};
|
|
5711
|
-
};
|
|
5712
|
-
/**
|
|
5713
|
-
* Saves the captured messages in localStorage (or whatever is used in its place)
|
|
5714
|
-
*
|
|
5715
|
-
* Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
|
|
5716
|
-
*
|
|
5717
|
-
* Keeping the size of local storage reasonable is up to the end users of this library
|
|
5718
|
-
* */
|
|
5719
|
-
this.saveBuffer = () => {
|
|
5720
|
-
this.localStorage.setItem(bufferStorageKey, JSON.stringify(this.bufferedMessages1));
|
|
5721
|
-
};
|
|
5722
|
-
/**
|
|
5723
|
-
* @returns buffer with stored messages for offline recording
|
|
5724
|
-
* */
|
|
5725
|
-
this.getBuffer = () => {
|
|
5726
|
-
return this.bufferedMessages1;
|
|
5727
|
-
};
|
|
5728
|
-
/**
|
|
5729
|
-
* Used to set a buffer with messages array
|
|
5730
|
-
* */
|
|
5731
|
-
this.setBuffer = (buffer) => {
|
|
5732
|
-
this.bufferedMessages1 = buffer;
|
|
5733
|
-
};
|
|
5734
5730
|
this.prevOpts = {};
|
|
5735
5731
|
this.restartCanvasTracking = () => {
|
|
5736
5732
|
this.canvasRecorder?.restartTracking();
|
|
@@ -5797,6 +5793,7 @@ class App {
|
|
|
5797
5793
|
forceNgOff: false,
|
|
5798
5794
|
inlineCss: 0,
|
|
5799
5795
|
disableSprites: false,
|
|
5796
|
+
disableThrottling: false,
|
|
5800
5797
|
};
|
|
5801
5798
|
this.options = simpleMerge(defaultOptions, options);
|
|
5802
5799
|
if (!this.insideIframe &&
|
|
@@ -5853,9 +5850,6 @@ class App {
|
|
|
5853
5850
|
* */
|
|
5854
5851
|
window.addEventListener('message', this.parentCrossDomainFrameListener);
|
|
5855
5852
|
setInterval(() => {
|
|
5856
|
-
if (document.hidden) {
|
|
5857
|
-
return;
|
|
5858
|
-
}
|
|
5859
5853
|
window.parent.postMessage({
|
|
5860
5854
|
line: proto.polling,
|
|
5861
5855
|
context: this.contextId,
|
|
@@ -6238,6 +6232,167 @@ class App {
|
|
|
6238
6232
|
const sessionToken = this.session.getSessionToken(this.projectKey);
|
|
6239
6233
|
return needNewSessionID || !sessionToken;
|
|
6240
6234
|
}
|
|
6235
|
+
/**
|
|
6236
|
+
* start buffering messages without starting the actual session, which gives
|
|
6237
|
+
* user 30 seconds to "activate" and record session by calling `start()` on conditional trigger,
|
|
6238
|
+
* and we will then send buffered batch, so it won't get lost
|
|
6239
|
+
* */
|
|
6240
|
+
async coldStart(startOpts = {}, conditional) {
|
|
6241
|
+
this.singleBuffer = false;
|
|
6242
|
+
const second = 1000;
|
|
6243
|
+
const isNewSession = this.checkSessionToken(startOpts.forceNew);
|
|
6244
|
+
if (conditional) {
|
|
6245
|
+
await this.setupConditionalStart(startOpts);
|
|
6246
|
+
}
|
|
6247
|
+
const cycle = () => {
|
|
6248
|
+
this.orderNumber += 1;
|
|
6249
|
+
adjustTimeOrigin();
|
|
6250
|
+
this.coldStartTs = now();
|
|
6251
|
+
if (this.orderNumber % 2 === 0) {
|
|
6252
|
+
this.bufferedMessages1.length = 0;
|
|
6253
|
+
this.bufferedMessages1.push(Timestamp(this.timestamp()));
|
|
6254
|
+
this.bufferedMessages1.push(TabData(this.session.getTabId()));
|
|
6255
|
+
}
|
|
6256
|
+
else {
|
|
6257
|
+
this.bufferedMessages2.length = 0;
|
|
6258
|
+
this.bufferedMessages2.push(Timestamp(this.timestamp()));
|
|
6259
|
+
this.bufferedMessages2.push(TabData(this.session.getTabId()));
|
|
6260
|
+
}
|
|
6261
|
+
this.stop(false);
|
|
6262
|
+
this.activityState = ActivityState.ColdStart;
|
|
6263
|
+
if (startOpts.sessionHash) {
|
|
6264
|
+
this.session.applySessionHash(startOpts.sessionHash);
|
|
6265
|
+
}
|
|
6266
|
+
if (startOpts.forceNew) {
|
|
6267
|
+
this.session.reset();
|
|
6268
|
+
}
|
|
6269
|
+
this.session.assign({
|
|
6270
|
+
userID: startOpts.userID,
|
|
6271
|
+
metadata: startOpts.metadata,
|
|
6272
|
+
});
|
|
6273
|
+
if (!isNewSession) {
|
|
6274
|
+
this.debug.log('continuing session on new tab', this.session.getTabId());
|
|
6275
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
6276
|
+
this.send(TabChange(this.session.getTabId()));
|
|
6277
|
+
}
|
|
6278
|
+
this.observer.observe();
|
|
6279
|
+
this.ticker.start();
|
|
6280
|
+
};
|
|
6281
|
+
this.coldInterval = setInterval(() => {
|
|
6282
|
+
cycle();
|
|
6283
|
+
}, 30 * second);
|
|
6284
|
+
cycle();
|
|
6285
|
+
}
|
|
6286
|
+
async setupConditionalStart(startOpts) {
|
|
6287
|
+
this.conditionsManager = new ConditionsManager(this, startOpts);
|
|
6288
|
+
const r = await fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
6289
|
+
method: 'POST',
|
|
6290
|
+
headers: {
|
|
6291
|
+
'Content-Type': 'application/json',
|
|
6292
|
+
},
|
|
6293
|
+
body: JSON.stringify({
|
|
6294
|
+
...this.getTrackerInfo(),
|
|
6295
|
+
timestamp: now(),
|
|
6296
|
+
doNotRecord: true,
|
|
6297
|
+
bufferDiff: 0,
|
|
6298
|
+
userID: this.session.getInfo().userID,
|
|
6299
|
+
token: undefined,
|
|
6300
|
+
deviceMemory,
|
|
6301
|
+
jsHeapSizeLimit,
|
|
6302
|
+
timezone: getTimezone(),
|
|
6303
|
+
width: window.screen.width,
|
|
6304
|
+
height: window.screen.height,
|
|
6305
|
+
}),
|
|
6306
|
+
});
|
|
6307
|
+
const {
|
|
6308
|
+
// this token is needed to fetch conditions and flags,
|
|
6309
|
+
// but it can't be used to record a session
|
|
6310
|
+
token, userBrowser, userCity, userCountry, userDevice, userOS, userState, projectID, features, } = await r.json();
|
|
6311
|
+
this.features = features ? features : this.features;
|
|
6312
|
+
this.session.assign({ projectID });
|
|
6313
|
+
this.session.setUserInfo({
|
|
6314
|
+
userBrowser,
|
|
6315
|
+
userCity,
|
|
6316
|
+
userCountry,
|
|
6317
|
+
userDevice,
|
|
6318
|
+
userOS,
|
|
6319
|
+
userState,
|
|
6320
|
+
});
|
|
6321
|
+
const onStartInfo = { sessionToken: token, userUUID: '', sessionID: '' };
|
|
6322
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
6323
|
+
await this.conditionsManager?.fetchConditions(projectID, token);
|
|
6324
|
+
if (this.features['feature-flags']) {
|
|
6325
|
+
await this.featureFlags.reloadFlags(token);
|
|
6326
|
+
this.conditionsManager?.processFlags(this.featureFlags.flags);
|
|
6327
|
+
}
|
|
6328
|
+
await this.tagWatcher.fetchTags(this.options.ingestPoint, token);
|
|
6329
|
+
}
|
|
6330
|
+
/**
|
|
6331
|
+
* Starts offline session recording
|
|
6332
|
+
* @param {Object} startOpts - options for session start, same as .start()
|
|
6333
|
+
* @param {Function} onSessionSent - callback that will be called once session is fully sent
|
|
6334
|
+
* */
|
|
6335
|
+
offlineRecording(startOpts = {}, onSessionSent) {
|
|
6336
|
+
this.onSessionSent = onSessionSent;
|
|
6337
|
+
this.singleBuffer = true;
|
|
6338
|
+
const isNewSession = this.checkSessionToken(startOpts.forceNew);
|
|
6339
|
+
adjustTimeOrigin();
|
|
6340
|
+
this.coldStartTs = now();
|
|
6341
|
+
const saverBuffer = this.localStorage.getItem(bufferStorageKey);
|
|
6342
|
+
if (saverBuffer) {
|
|
6343
|
+
const data = JSON.parse(saverBuffer);
|
|
6344
|
+
this.bufferedMessages1 = Array.isArray(data) ? data : this.bufferedMessages1;
|
|
6345
|
+
this.localStorage.removeItem(bufferStorageKey);
|
|
6346
|
+
}
|
|
6347
|
+
this.bufferedMessages1.push(Timestamp(this.timestamp()));
|
|
6348
|
+
this.bufferedMessages1.push(TabData(this.session.getTabId()));
|
|
6349
|
+
this.activityState = ActivityState.ColdStart;
|
|
6350
|
+
if (startOpts.sessionHash) {
|
|
6351
|
+
this.session.applySessionHash(startOpts.sessionHash);
|
|
6352
|
+
}
|
|
6353
|
+
if (startOpts.forceNew) {
|
|
6354
|
+
this.session.reset();
|
|
6355
|
+
}
|
|
6356
|
+
this.session.assign({
|
|
6357
|
+
userID: startOpts.userID,
|
|
6358
|
+
metadata: startOpts.metadata,
|
|
6359
|
+
});
|
|
6360
|
+
const onStartInfo = { sessionToken: '', userUUID: '', sessionID: '' };
|
|
6361
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
6362
|
+
if (!isNewSession) {
|
|
6363
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
6364
|
+
this.send(TabChange(this.session.getTabId()));
|
|
6365
|
+
}
|
|
6366
|
+
this.observer.observe();
|
|
6367
|
+
this.ticker.start();
|
|
6368
|
+
return {
|
|
6369
|
+
saveBuffer: this.saveBuffer,
|
|
6370
|
+
getBuffer: this.getBuffer,
|
|
6371
|
+
setBuffer: this.setBuffer,
|
|
6372
|
+
};
|
|
6373
|
+
}
|
|
6374
|
+
/**
|
|
6375
|
+
* Saves the captured messages in localStorage (or whatever is used in its place)
|
|
6376
|
+
*
|
|
6377
|
+
* Then, when this.offlineRecording is called, it will preload this messages and clear the storage item
|
|
6378
|
+
*
|
|
6379
|
+
* Keeping the size of local storage reasonable is up to the end users of this library
|
|
6380
|
+
* */
|
|
6381
|
+
saveBuffer() {
|
|
6382
|
+
this.localStorage.setItem(bufferStorageKey, JSON.stringify(this.bufferedMessages1));
|
|
6383
|
+
}
|
|
6384
|
+
/**
|
|
6385
|
+
* @returns buffer with stored messages for offline recording
|
|
6386
|
+
* */
|
|
6387
|
+
getBuffer() {
|
|
6388
|
+
return this.bufferedMessages1;
|
|
6389
|
+
}
|
|
6390
|
+
/**
|
|
6391
|
+
* Used to set a buffer with messages array
|
|
6392
|
+
* */
|
|
6393
|
+
setBuffer(buffer) {
|
|
6394
|
+
this.bufferedMessages1 = buffer;
|
|
6395
|
+
}
|
|
6241
6396
|
/**
|
|
6242
6397
|
* Uploads the stored session buffer to backend
|
|
6243
6398
|
* @returns promise that resolves once messages are loaded, it has to be awaited
|
|
@@ -6293,7 +6448,7 @@ class App {
|
|
|
6293
6448
|
while (this.bufferedMessages1.length > 0) {
|
|
6294
6449
|
await this.flushBuffer(this.bufferedMessages1);
|
|
6295
6450
|
}
|
|
6296
|
-
this.postToWorker([[
|
|
6451
|
+
this.postToWorker([[-1]]);
|
|
6297
6452
|
this.clearBuffers();
|
|
6298
6453
|
}
|
|
6299
6454
|
async _start(startOpts = {}, resetByWorker = false, conditionName) {
|
|
@@ -6471,15 +6626,13 @@ class App {
|
|
|
6471
6626
|
this.commit();
|
|
6472
6627
|
/** --------------- COLD START BUFFER ------------------*/
|
|
6473
6628
|
}
|
|
6629
|
+
if (this.insideIframe && this.rootId) {
|
|
6630
|
+
this.observer.crossdomainObserve(this.rootId, this.frameOderNumber);
|
|
6631
|
+
}
|
|
6474
6632
|
else {
|
|
6475
|
-
|
|
6476
|
-
this.observer.crossdomainObserve(this.rootId, this.frameOderNumber);
|
|
6477
|
-
}
|
|
6478
|
-
else {
|
|
6479
|
-
this.observer.observe();
|
|
6480
|
-
}
|
|
6481
|
-
this.ticker.start();
|
|
6633
|
+
this.observer.observe();
|
|
6482
6634
|
}
|
|
6635
|
+
this.ticker.start();
|
|
6483
6636
|
this.canvasRecorder?.startTracking();
|
|
6484
6637
|
if (this.features['usability-test'] && !this.insideIframe) {
|
|
6485
6638
|
this.uxtManager = this.uxtManager
|
|
@@ -7082,7 +7235,7 @@ function Img (app) {
|
|
|
7082
7235
|
const sendImgError = app.safe(function (img) {
|
|
7083
7236
|
const resolvedSrc = resolveURL(img.src || ''); // Src type is null sometimes. - is it true?
|
|
7084
7237
|
if (isURL(resolvedSrc)) {
|
|
7085
|
-
app.send(ResourceTiming(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img', 0, false));
|
|
7238
|
+
app.send(ResourceTiming(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img', 0, false, 0, 0, 0, 0, 0, 0, 0));
|
|
7086
7239
|
}
|
|
7087
7240
|
});
|
|
7088
7241
|
const sendImgAttrs = app.safe(function (img) {
|
|
@@ -7601,7 +7754,7 @@ function getUniqueSiblingClass(el) {
|
|
|
7601
7754
|
return null;
|
|
7602
7755
|
}
|
|
7603
7756
|
|
|
7604
|
-
|
|
7757
|
+
let e=-1;const t=t=>{addEventListener("pageshow",(n=>{n.persisted&&(e=n.timeStamp,t(n));}),true);},n=(e,t,n,i)=>{let s,o;return r=>{t.value>=0&&(r||i)&&(o=t.value-(s??0),(o||void 0===s)&&(s=t.value,t.delta=o,t.rating=((e,t)=>e>t[1]?"poor":e>t[0]?"needs-improvement":"good")(t.value,n),e(t)));}},i=e=>{requestAnimationFrame((()=>requestAnimationFrame((()=>e()))));},s=()=>{const e=performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},o=()=>{const e=s();return e?.activationStart??0},r=(t,n=-1)=>{const i=s();let r="navigate";e>=0?r="back-forward-cache":i&&(document.prerendering||o()>0?r="prerender":document.wasDiscarded?r="restore":i.type&&(r=i.type.replace(/_/g,"-")));return {name:t,value:n,rating:"good",delta:0,entries:[],id:`v5-${Date.now()}-${Math.floor(8999999999999*Math.random())+1e12}`,navigationType:r}},c=new WeakMap;function a(e,t){return c.get(e)||c.set(e,new t),c.get(e)}class d{t;i=0;o=[];h(e){if(e.hadRecentInput)return;const t=this.o[0],n=this.o.at(-1);this.i&&t&&n&&e.startTime-n.startTime<1e3&&e.startTime-t.startTime<5e3?(this.i+=e.value,this.o.push(e)):(this.i=e.value,this.o=[e]),this.t?.(e);}}const h=(e,t,n={})=>{try{if(PerformanceObserver.supportedEntryTypes.includes(e)){const i=new PerformanceObserver((e=>{Promise.resolve().then((()=>{t(e.getEntries());}));}));return i.observe({type:e,buffered:!0,...n}),i}}catch{}},f=e=>{let t=false;return ()=>{t||(e(),t=true);}};let u=-1;const l=new Set,m=()=>"hidden"!==document.visibilityState||document.prerendering?1/0:0,p=e=>{if("hidden"===document.visibilityState){if("visibilitychange"===e.type)for(const e of l)e();isFinite(u)||(u="visibilitychange"===e.type?e.timeStamp:0,removeEventListener("prerenderingchange",p,true));}},v=()=>{if(u<0){const e=o(),n=document.prerendering?void 0:globalThis.performance.getEntriesByType("visibility-state").filter((t=>"hidden"===t.name&&t.startTime>e))[0]?.startTime;u=n??m(),addEventListener("visibilitychange",p,true),addEventListener("prerenderingchange",p,true),t((()=>{setTimeout((()=>{u=m();}));}));}return {get firstHiddenTime(){return u},onHidden(e){l.add(e);}}},g=e=>{document.prerendering?addEventListener("prerenderingchange",(()=>e()),true):e();},y=[1800,3e3],E=(e,s={})=>{g((()=>{const c=v();let a,d=r("FCP");const f=h("paint",(e=>{for(const t of e)"first-contentful-paint"===t.name&&(f.disconnect(),t.startTime<c.firstHiddenTime&&(d.value=Math.max(t.startTime-o(),0),d.entries.push(t),a(true)));}));f&&(a=n(e,d,y,s.reportAllChanges),t((t=>{d=r("FCP"),a=n(e,d,y,s.reportAllChanges),i((()=>{d.value=performance.now()-t.timeStamp,a(true);}));})));}));},b=[.1,.25],L=(e,s={})=>{const o=v();E(f((()=>{let c,f=r("CLS",0);const u=a(s,d),l=e=>{for(const t of e)u.h(t);u.i>f.value&&(f.value=u.i,f.entries=u.o,c());},m=h("layout-shift",l);m&&(c=n(e,f,b,s.reportAllChanges),o.onHidden((()=>{l(m.takeRecords()),c(true);})),t((()=>{u.i=0,f=r("CLS",0),c=n(e,f,b,s.reportAllChanges),i((()=>c()));})),setTimeout(c));})));};let P=0,T=1/0,_=0;const M=e=>{for(const t of e)t.interactionId&&(T=Math.min(T,t.interactionId),_=Math.max(_,t.interactionId),P=_?(_-T)/7+1:0);};let w;const C=()=>w?P:performance.interactionCount??0,I=()=>{"interactionCount"in performance||w||(w=h("event",M,{type:"event",buffered:true,durationThreshold:0}));};let F=0;class k{u=[];l=new Map;m;p;v(){F=C(),this.u.length=0,this.l.clear();}L(){const e=Math.min(this.u.length-1,Math.floor((C()-F)/50));return this.u[e]}h(e){if(this.m?.(e),!e.interactionId&&"first-input"!==e.entryType)return;const t=this.u.at(-1);let n=this.l.get(e.interactionId);if(n||this.u.length<10||e.duration>t.P){if(n?e.duration>n.P?(n.entries=[e],n.P=e.duration):e.duration===n.P&&e.startTime===n.entries[0].startTime&&n.entries.push(e):(n={id:e.interactionId,entries:[e],P:e.duration},this.l.set(n.id,n),this.u.push(n)),this.u.sort(((e,t)=>t.P-e.P)),this.u.length>10){const e=this.u.splice(10);for(const t of e)this.l.delete(t.id);}this.p?.(n);}}}const A=e=>{const t=globalThis.requestIdleCallback||setTimeout;"hidden"===document.visibilityState?e():(e=f(e),addEventListener("visibilitychange",e,{once:true,capture:true}),t((()=>{e(),removeEventListener("visibilitychange",e,{capture:true});})));},B=[200,500],S=(e,i={})=>{if(!globalThis.PerformanceEventTiming||!("interactionId"in PerformanceEventTiming.prototype))return;const s=v();g((()=>{I();let o,c=r("INP");const d=a(i,k),f=e=>{A((()=>{for(const t of e)d.h(t);const t=d.L();t&&t.P!==c.value&&(c.value=t.P,c.entries=t.entries,o());}));},u=h("event",f,{durationThreshold:i.durationThreshold??40});o=n(e,c,B,i.reportAllChanges),u&&(u.observe({type:"first-input",buffered:true}),s.onHidden((()=>{f(u.takeRecords()),o(true);})),t((()=>{d.v(),c=r("INP"),o=n(e,c,B,i.reportAllChanges);})));}));};class N{m;h(e){this.m?.(e);}}const q=[2500,4e3],x=(e,s={})=>{g((()=>{const c=v();let d,u=r("LCP");const l=a(s,N),m=e=>{s.reportAllChanges||(e=e.slice(-1));for(const t of e)l.h(t),t.startTime<c.firstHiddenTime&&(u.value=Math.max(t.startTime-o(),0),u.entries=[t],d());},p=h("largest-contentful-paint",m);if(p){d=n(e,u,q,s.reportAllChanges);const o=f((()=>{m(p.takeRecords()),p.disconnect(),d(true);})),c=e=>{e.isTrusted&&(A(o),removeEventListener(e.type,c,{capture:true}));};for(const e of ["keydown","click","visibilitychange"])addEventListener(e,c,{capture:true});t((t=>{u=r("LCP"),d=n(e,u,q,s.reportAllChanges),i((()=>{u.value=performance.now()-t.timeStamp,d(true);}));}));}}));},H=[800,1800],O=e=>{document.prerendering?g((()=>O(e))):"complete"!==document.readyState?addEventListener("load",(()=>O(e)),true):setTimeout(e);},$=(e,i={})=>{let c=r("TTFB"),a=n(e,c,H,i.reportAllChanges);O((()=>{const d=s();d&&(c.value=Math.max(d.responseStart-o(),0),c.entries=[d],a(true),t((()=>{c=r("TTFB",0),a=n(e,c,H,i.reportAllChanges),a(true);})));}));};
|
|
7605
7758
|
|
|
7606
7759
|
function getPaintBlocks(resources) {
|
|
7607
7760
|
const paintBlocks = [];
|
|
@@ -7686,18 +7839,38 @@ function Timing (app, opts) {
|
|
|
7686
7839
|
if (shouldSkip) {
|
|
7687
7840
|
return;
|
|
7688
7841
|
}
|
|
7842
|
+
// will probably require custom header added to responses for tracked requests:
|
|
7843
|
+
// Timing-Allow-Origin: *
|
|
7844
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Timing-Allow-Origin
|
|
7845
|
+
let stalled = 0;
|
|
7846
|
+
if (entry.connectEnd && entry.connectEnd > entry.domainLookupEnd) {
|
|
7847
|
+
// Usual case stalled is time between connection establishment and request start
|
|
7848
|
+
stalled = Math.max(0, entry.requestStart - entry.connectEnd);
|
|
7849
|
+
}
|
|
7850
|
+
else {
|
|
7851
|
+
// Connection reuse case - stalled is time between domain lookup and request start
|
|
7852
|
+
stalled = Math.max(0, entry.requestStart - entry.domainLookupEnd);
|
|
7853
|
+
}
|
|
7854
|
+
const timings = {
|
|
7855
|
+
queueing: entry.requestStart - entry.fetchStart,
|
|
7856
|
+
dnsLookup: entry.domainLookupEnd - entry.domainLookupStart,
|
|
7857
|
+
initialConnection: entry.connectEnd - entry.connectStart,
|
|
7858
|
+
ssl: entry.secureConnectionStart > 0 ? entry.connectEnd - entry.secureConnectionStart : 0,
|
|
7859
|
+
ttfb: entry.responseStart - entry.requestStart,
|
|
7860
|
+
contentDownload: entry.responseEnd - entry.responseStart,
|
|
7861
|
+
total: entry.duration ?? entry.responseEnd - entry.startTime,
|
|
7862
|
+
stalled,
|
|
7863
|
+
};
|
|
7689
7864
|
const entryName = options.resourceNameSanitizer
|
|
7690
7865
|
? options.resourceNameSanitizer(entry.name)
|
|
7691
7866
|
: entry.name;
|
|
7692
|
-
const cached =
|
|
7693
|
-
// @ts-ignore
|
|
7694
|
-
(entry.responseStatus && entry.responseStatus === 304) ||
|
|
7867
|
+
const cached = (entry.responseStatus && entry.responseStatus === 304) ||
|
|
7695
7868
|
// @ts-ignore
|
|
7696
7869
|
(entry.deliveryType && entry.deliveryType === 'cache') ||
|
|
7697
7870
|
(entry.transferSize === 0 && entry.decodedBodySize > 0);
|
|
7698
7871
|
const requestFailed = entry.responseStatus && entry.responseStatus >= 400;
|
|
7699
7872
|
const decodedBodySize = requestFailed ? -111 : entry.decodedBodySize || 0;
|
|
7700
|
-
app.send(ResourceTiming(entry.startTime + getTimeOrigin(), entry.duration,
|
|
7873
|
+
app.send(ResourceTiming(entry.startTime + getTimeOrigin(), entry.duration, timings.ttfb, entry.transferSize > entry.encodedBodySize ? entry.transferSize - entry.encodedBodySize : 0, entry.encodedBodySize || 0, decodedBodySize, app.sanitizer.privateMode ? entry.name.replaceAll(/./g, '*') : entryName, entry.initiatorType, entry.transferSize, cached, timings.queueing, timings.dnsLookup, timings.initialConnection, timings.ssl, timings.contentDownload, timings.total, timings.stalled));
|
|
7701
7874
|
}
|
|
7702
7875
|
const observer = new PerformanceObserver((list) => list.getEntries().forEach(resourceTiming));
|
|
7703
7876
|
function onVitalsSignal(msg) {
|
|
@@ -7714,10 +7887,10 @@ function Timing (app, opts) {
|
|
|
7714
7887
|
// onINP(): Chromium
|
|
7715
7888
|
// onLCP(): Chromium, Firefox
|
|
7716
7889
|
// onTTFB(): Chromium, Firefox, Safari
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7890
|
+
L(onVitalsSignal);
|
|
7891
|
+
S(onVitalsSignal);
|
|
7892
|
+
x(onVitalsSignal);
|
|
7893
|
+
$(onVitalsSignal);
|
|
7721
7894
|
});
|
|
7722
7895
|
app.attachStopCallback(function () {
|
|
7723
7896
|
observer.disconnect();
|
|
@@ -8508,7 +8681,9 @@ class NetworkMessage {
|
|
|
8508
8681
|
});
|
|
8509
8682
|
if (!messageInfo)
|
|
8510
8683
|
return null;
|
|
8511
|
-
const
|
|
8684
|
+
const gqlHeader = "application/graphql-response";
|
|
8685
|
+
const isGraphql = messageInfo.url.includes("/graphql")
|
|
8686
|
+
|| Object.values(messageInfo.request.headers).some(v => v.includes(gqlHeader));
|
|
8512
8687
|
if (isGraphql && messageInfo.response.body && typeof messageInfo.response.body === 'string') {
|
|
8513
8688
|
const isError = messageInfo.response.body.includes("errors");
|
|
8514
8689
|
messageInfo.status = isError ? 400 : 200;
|
|
@@ -8814,6 +8989,7 @@ class FetchProxyHandler {
|
|
|
8814
8989
|
this.tokenUrlMatcher = tokenUrlMatcher;
|
|
8815
8990
|
}
|
|
8816
8991
|
apply(target, _, argsList) {
|
|
8992
|
+
var _a;
|
|
8817
8993
|
const input = argsList[0];
|
|
8818
8994
|
const init = argsList[1];
|
|
8819
8995
|
if (!input ||
|
|
@@ -8829,6 +9005,31 @@ class FetchProxyHandler {
|
|
|
8829
9005
|
}
|
|
8830
9006
|
const item = new NetworkMessage(this.ignoredHeaders, this.setSessionTokenHeader, this.sanitize);
|
|
8831
9007
|
this.beforeFetch(item, input, init);
|
|
9008
|
+
const signal = (argsList[0] instanceof Request ? argsList[0].signal : undefined) ||
|
|
9009
|
+
((_a = argsList[1]) === null || _a === void 0 ? void 0 : _a.signal);
|
|
9010
|
+
// guard to avoid double-send
|
|
9011
|
+
let abortedNotified = false;
|
|
9012
|
+
const notifyAbort = () => {
|
|
9013
|
+
if (abortedNotified)
|
|
9014
|
+
return;
|
|
9015
|
+
abortedNotified = true;
|
|
9016
|
+
item.endTime = performance.now();
|
|
9017
|
+
item.duration = item.endTime - (item.startTime || item.endTime);
|
|
9018
|
+
item.status = 0;
|
|
9019
|
+
item.statusText = "Aborted";
|
|
9020
|
+
item.readyState = 0;
|
|
9021
|
+
const msg = item.getMessage();
|
|
9022
|
+
if (msg)
|
|
9023
|
+
this.sendMessage(msg);
|
|
9024
|
+
};
|
|
9025
|
+
if (signal) {
|
|
9026
|
+
if (signal.aborted) {
|
|
9027
|
+
notifyAbort();
|
|
9028
|
+
}
|
|
9029
|
+
else {
|
|
9030
|
+
signal.addEventListener("abort", notifyAbort, { once: true });
|
|
9031
|
+
}
|
|
9032
|
+
}
|
|
8832
9033
|
this.setSessionTokenHeader((name, value) => {
|
|
8833
9034
|
if (this.tokenUrlMatcher !== undefined) {
|
|
8834
9035
|
if (!this.tokenUrlMatcher(item.url)) {
|
|
@@ -8857,11 +9058,22 @@ class FetchProxyHandler {
|
|
|
8857
9058
|
}
|
|
8858
9059
|
});
|
|
8859
9060
|
return target.apply(window, argsList)
|
|
8860
|
-
.then(this.afterFetch(item)
|
|
9061
|
+
.then(this.afterFetch(item, () => {
|
|
9062
|
+
abortedNotified = true;
|
|
9063
|
+
}))
|
|
8861
9064
|
.catch((e) => {
|
|
8862
|
-
// mock finally
|
|
8863
9065
|
item.endTime = performance.now();
|
|
8864
9066
|
item.duration = item.endTime - (item.startTime || item.endTime);
|
|
9067
|
+
if (e && e.name === "AbortError") {
|
|
9068
|
+
item.status = 0;
|
|
9069
|
+
item.statusText = "Aborted";
|
|
9070
|
+
item.readyState = 0;
|
|
9071
|
+
if (!abortedNotified) {
|
|
9072
|
+
const msg = item.getMessage();
|
|
9073
|
+
if (msg)
|
|
9074
|
+
this.sendMessage(msg);
|
|
9075
|
+
}
|
|
9076
|
+
}
|
|
8865
9077
|
throw e;
|
|
8866
9078
|
});
|
|
8867
9079
|
}
|
|
@@ -8913,8 +9125,10 @@ class FetchProxyHandler {
|
|
|
8913
9125
|
item.requestData = genStringBody(init.body);
|
|
8914
9126
|
}
|
|
8915
9127
|
}
|
|
8916
|
-
afterFetch(item) {
|
|
9128
|
+
afterFetch(item, onResolved) {
|
|
8917
9129
|
return (resp) => {
|
|
9130
|
+
if (onResolved)
|
|
9131
|
+
onResolved === null || onResolved === void 0 ? void 0 : onResolved();
|
|
8918
9132
|
item.endTime = performance.now();
|
|
8919
9133
|
item.duration = item.endTime - (item.startTime || item.endTime);
|
|
8920
9134
|
item.status = resp.status;
|
|
@@ -8950,7 +9164,15 @@ class FetchProxyHandler {
|
|
|
8950
9164
|
}
|
|
8951
9165
|
})
|
|
8952
9166
|
.catch((e) => {
|
|
8953
|
-
if (e.name
|
|
9167
|
+
if (e.name === "AbortError") {
|
|
9168
|
+
item.status = 0;
|
|
9169
|
+
item.statusText = "Aborted";
|
|
9170
|
+
item.readyState = 0;
|
|
9171
|
+
const msg = item.getMessage();
|
|
9172
|
+
if (msg)
|
|
9173
|
+
this.sendMessage(msg);
|
|
9174
|
+
}
|
|
9175
|
+
else {
|
|
8954
9176
|
throw e;
|
|
8955
9177
|
}
|
|
8956
9178
|
});
|
|
@@ -9595,8 +9817,86 @@ function Tabs (app) {
|
|
|
9595
9817
|
app.attachEventListener(window, 'focus', changeTab, false, false);
|
|
9596
9818
|
}
|
|
9597
9819
|
|
|
9820
|
+
function LongAnimationTask (app, opts) {
|
|
9821
|
+
if (!opts.longTasks || !('PerformanceObserver' in window)) {
|
|
9822
|
+
return;
|
|
9823
|
+
}
|
|
9824
|
+
const onEntry = (entry) => {
|
|
9825
|
+
app.send(LongAnimationTask$1(entry.name, entry.duration, entry.blockingDuration, entry.firstUIEventTimestamp, entry.startTime, JSON.stringify(entry.scripts ?? [])));
|
|
9826
|
+
};
|
|
9827
|
+
const observer = new PerformanceObserver((entryList) => {
|
|
9828
|
+
entryList.getEntries().forEach((entry) => {
|
|
9829
|
+
if (entry.entryType === 'long-animation-frame') {
|
|
9830
|
+
onEntry(entry);
|
|
9831
|
+
}
|
|
9832
|
+
});
|
|
9833
|
+
});
|
|
9834
|
+
app.attachStartCallback(() => {
|
|
9835
|
+
performance.getEntriesByType('long-animation-frame').forEach((lat) => {
|
|
9836
|
+
onEntry(lat);
|
|
9837
|
+
});
|
|
9838
|
+
observer.observe({
|
|
9839
|
+
entryTypes: ['long-animation-frame'],
|
|
9840
|
+
});
|
|
9841
|
+
});
|
|
9842
|
+
app.attachStopCallback(() => {
|
|
9843
|
+
observer.disconnect();
|
|
9844
|
+
});
|
|
9845
|
+
}
|
|
9846
|
+
|
|
9847
|
+
const toIgnore = ["composite", "computedOffset", "easing", "offset"];
|
|
9848
|
+
function webAnimations(app, options = {}) {
|
|
9849
|
+
const { allElements = false } = options;
|
|
9850
|
+
let listening = new WeakSet();
|
|
9851
|
+
let handled = new WeakSet();
|
|
9852
|
+
function wire(anim, el, nodeId) {
|
|
9853
|
+
if (handled.has(anim))
|
|
9854
|
+
return;
|
|
9855
|
+
handled.add(anim);
|
|
9856
|
+
anim.addEventListener('finish', () => {
|
|
9857
|
+
const lastKF = anim.effect.getKeyframes().at(-1);
|
|
9858
|
+
const computedStyle = getComputedStyle(el);
|
|
9859
|
+
const keys = Object.keys(lastKF).filter((p) => !toIgnore.includes(p));
|
|
9860
|
+
// @ts-ignore
|
|
9861
|
+
const finalStyle = {};
|
|
9862
|
+
keys.forEach((key) => {
|
|
9863
|
+
finalStyle[key] = computedStyle[key];
|
|
9864
|
+
});
|
|
9865
|
+
app.send(NodeAnimationResult(nodeId, JSON.stringify(finalStyle)));
|
|
9866
|
+
}, { once: true });
|
|
9867
|
+
}
|
|
9868
|
+
function scanElement(el, nodeId) {
|
|
9869
|
+
el.getAnimations({ subtree: false }).forEach((anim) => wire(anim, el, nodeId));
|
|
9870
|
+
}
|
|
9871
|
+
app.nodes.attachNodeCallback((node) => {
|
|
9872
|
+
if ((allElements || node.nodeName.includes('-')) && 'getAnimations' in node) {
|
|
9873
|
+
const animations = node.getAnimations({ subtree: false });
|
|
9874
|
+
const id = app.nodes.getID(node);
|
|
9875
|
+
if (animations.length > 0 && !listening.has(node) && id) {
|
|
9876
|
+
listening.add(node);
|
|
9877
|
+
scanElement(node, id);
|
|
9878
|
+
node.addEventListener('animationstart', () => scanElement(node, id));
|
|
9879
|
+
}
|
|
9880
|
+
}
|
|
9881
|
+
});
|
|
9882
|
+
const origAnimate = Element.prototype.animate;
|
|
9883
|
+
Element.prototype.animate = function (...args) {
|
|
9884
|
+
const anim = origAnimate.apply(this, args);
|
|
9885
|
+
const id = app.nodes.getID(this);
|
|
9886
|
+
if (!id)
|
|
9887
|
+
return anim;
|
|
9888
|
+
wire(anim, this, id);
|
|
9889
|
+
return anim;
|
|
9890
|
+
};
|
|
9891
|
+
app.attachStopCallback(() => {
|
|
9892
|
+
Element.prototype.animate = origAnimate; // Restore original animate method
|
|
9893
|
+
listening = new WeakSet();
|
|
9894
|
+
handled = new WeakSet();
|
|
9895
|
+
});
|
|
9896
|
+
}
|
|
9897
|
+
|
|
9598
9898
|
const Messages = _Messages;
|
|
9599
|
-
const DOCS_SETUP = '/en/sdk
|
|
9899
|
+
const DOCS_SETUP = '/en/sdk';
|
|
9600
9900
|
function processOptions(obj) {
|
|
9601
9901
|
if (obj == null) {
|
|
9602
9902
|
console.error(`OpenReplay: invalid options argument type. Please, check documentation on ${DOCS_HOST}${DOCS_SETUP}`);
|
|
@@ -9646,7 +9946,7 @@ class API {
|
|
|
9646
9946
|
this.signalStartIssue = (reason, missingApi) => {
|
|
9647
9947
|
const doNotTrack = this.checkDoNotTrack();
|
|
9648
9948
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
9649
|
-
trackerVersion: '16.4.
|
|
9949
|
+
trackerVersion: '16.4.11-beta.0',
|
|
9650
9950
|
projectKey: this.options.projectKey,
|
|
9651
9951
|
doNotTrack,
|
|
9652
9952
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|
|
@@ -9674,6 +9974,12 @@ class API {
|
|
|
9674
9974
|
}
|
|
9675
9975
|
}
|
|
9676
9976
|
};
|
|
9977
|
+
this.incident = (options) => {
|
|
9978
|
+
if (this.app === null) {
|
|
9979
|
+
return;
|
|
9980
|
+
}
|
|
9981
|
+
this.app.send(Incident(options.label ?? '', options.startTime, options.endTime ?? options.startTime));
|
|
9982
|
+
};
|
|
9677
9983
|
this.crossdomainMode = Boolean(inIframe() && options.crossdomain?.enabled);
|
|
9678
9984
|
if (!IN_BROWSER || !processOptions(options)) {
|
|
9679
9985
|
return;
|
|
@@ -9752,6 +10058,7 @@ class API {
|
|
|
9752
10058
|
Img(app);
|
|
9753
10059
|
Input(app, options);
|
|
9754
10060
|
Timing(app, options);
|
|
10061
|
+
LongAnimationTask(app, options);
|
|
9755
10062
|
Focus(app);
|
|
9756
10063
|
Fonts(app);
|
|
9757
10064
|
const skipNetwork = options.network?.disabled;
|
|
@@ -9759,6 +10066,7 @@ class API {
|
|
|
9759
10066
|
Network(app, options.network);
|
|
9760
10067
|
}
|
|
9761
10068
|
selection(app);
|
|
10069
|
+
webAnimations(app, options.webAnimations);
|
|
9762
10070
|
window.__OPENREPLAY__ = this;
|
|
9763
10071
|
if (options.flags && options.flags.onFlagsLoad) {
|
|
9764
10072
|
this.onFlagsLoad(options.flags.onFlagsLoad);
|
|
@@ -9983,6 +10291,13 @@ class API {
|
|
|
9983
10291
|
}
|
|
9984
10292
|
else {
|
|
9985
10293
|
try {
|
|
10294
|
+
if ('or_timestamp' in payload) {
|
|
10295
|
+
const startTs = this.getSessionInfo()?.timestamp ?? 0;
|
|
10296
|
+
const diff = payload.or_timestamp - startTs;
|
|
10297
|
+
if (diff < 0) {
|
|
10298
|
+
console.error(`OpenReplay: event ${key} has or_timestamp (${payload.or_timestamp}) before session start (${startTs}). It will be ignored.`);
|
|
10299
|
+
}
|
|
10300
|
+
}
|
|
9986
10301
|
payload = JSON.stringify(payload);
|
|
9987
10302
|
}
|
|
9988
10303
|
catch (e) {
|