@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.
Files changed (42) hide show
  1. package/dist/cjs/common/messages.gen.d.ts +57 -7
  2. package/dist/cjs/entry.js +555 -240
  3. package/dist/cjs/entry.js.map +1 -1
  4. package/dist/cjs/index.js +555 -240
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/main/app/guards.d.ts +1 -0
  7. package/dist/cjs/main/app/index.d.ts +5 -5
  8. package/dist/cjs/main/app/messages.gen.d.ts +7 -2
  9. package/dist/cjs/main/app/observer/observer.d.ts +4 -0
  10. package/dist/cjs/main/app/observer/top_observer.d.ts +2 -1
  11. package/dist/cjs/main/index.d.ts +9 -1
  12. package/dist/cjs/main/modules/longAnimationTask.d.ts +25 -0
  13. package/dist/cjs/main/modules/tagWatcher.d.ts +1 -1
  14. package/dist/cjs/main/modules/webAnimations.d.ts +9 -0
  15. package/dist/cjs/main/utils.d.ts +3 -0
  16. package/dist/lib/common/messages.gen.d.ts +57 -7
  17. package/dist/lib/entry.js +555 -240
  18. package/dist/lib/entry.js.map +1 -1
  19. package/dist/lib/index.js +555 -240
  20. package/dist/lib/index.js.map +1 -1
  21. package/dist/lib/main/app/guards.d.ts +1 -0
  22. package/dist/lib/main/app/index.d.ts +5 -5
  23. package/dist/lib/main/app/messages.gen.d.ts +7 -2
  24. package/dist/lib/main/app/observer/observer.d.ts +4 -0
  25. package/dist/lib/main/app/observer/top_observer.d.ts +2 -1
  26. package/dist/lib/main/index.d.ts +9 -1
  27. package/dist/lib/main/modules/longAnimationTask.d.ts +25 -0
  28. package/dist/lib/main/modules/tagWatcher.d.ts +1 -1
  29. package/dist/lib/main/modules/webAnimations.d.ts +9 -0
  30. package/dist/lib/main/utils.d.ts +3 -0
  31. package/dist/types/common/messages.gen.d.ts +57 -7
  32. package/dist/types/main/app/guards.d.ts +1 -0
  33. package/dist/types/main/app/index.d.ts +5 -5
  34. package/dist/types/main/app/messages.gen.d.ts +7 -2
  35. package/dist/types/main/app/observer/observer.d.ts +4 -0
  36. package/dist/types/main/app/observer/top_observer.d.ts +2 -1
  37. package/dist/types/main/index.d.ts +9 -1
  38. package/dist/types/main/modules/longAnimationTask.d.ts +25 -0
  39. package/dist/types/main/modules/tagWatcher.d.ts +1 -1
  40. package/dist/types/main/modules/webAnimations.d.ts +9 -0
  41. package/dist/types/main/utils.d.ts +3 -0
  42. 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 ResourceTimingDeprecated(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator) {
1850
+ function ResourceTimingDeprecatedDeprecated(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator) {
1807
1851
  return [
1808
- 53 /* Messages.Type.ResourceTimingDeprecated */,
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 ResourceTiming(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator, transferredSize, cached) {
2145
+ function ResourceTimingDeprecated(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator, transferredSize, cached) {
2054
2146
  return [
2055
- 116 /* Messages.Type.ResourceTiming */,
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.intervals = {};
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.intervals = {};
2308
- tags.forEach((tag) => {
2309
- this.intervals[tag.id] = setInterval(() => {
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
- }, 500);
2318
- });
2417
+ });
2418
+ }, 500);
2319
2419
  }
2320
2420
  onTagRendered(tagId) {
2321
- if (this.intervals[tagId]) {
2322
- clearInterval(this.intervals[tagId]);
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.intervals = {};
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
- // @ts-ignore SALESFORCE
4518
- const parent = node.assignedSlot ? node.assignedSlot : node.parentNode;
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
- parentID = this.app.nodes.getID(parent);
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.sendNodeData(id, parent, node.data);
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.sendNodeData(id, parent, node.data);
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 simulated AdoptedStyleSheets behavior programmaticaly for the replay */
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.10-beta.0'; // TODO: version compatability check inside each plugin.
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([['q_end']]);
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
- if (this.insideIframe && this.rootId) {
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
- var e,o=-1,a=function(e){addEventListener("pageshow",(function(n){n.persisted&&(o=n.timeStamp,e(n));}),true);},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r="navigate";o>=0?r="back-forward-cache":t&&(document.prerendering||u()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-")));return {name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries());}));}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n));}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}));},p=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e();}));},v=function(e){var n=false;return function(){n||(e(),n=true);}},m=-1,h=function(){return "hidden"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){"hidden"===document.visibilityState&&m>-1&&(m="visibilitychange"===e.type?e.timeStamp:0,T());},y=function(){addEventListener("visibilitychange",g,true),addEventListener("prerenderingchange",g,true);},T=function(){removeEventListener("visibilitychange",g,true),removeEventListener("prerenderingchange",g,true);},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y();}),0);}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),true):e();},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("FCP"),o=s("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(true)));}));}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f("FCP"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(true);}));})));}));},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f("CLS",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e]);}})),i>r.value&&(r.value=i,r.entries=o,t());},u=s("layout-shift",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(true);})),a((function(){i=0,r=f("CLS",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}));})),setTimeout(t,0));})));},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0);}));},k=function(){return e?A:performance.interactionCount||0},F=function(){"interactionCount"in performance||e||(e=s("event",M,{type:"event",buffered:true,durationThreshold:0}));},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else {var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r);}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}));}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),"hidden"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f("INP"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r());}));},c=s("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:"first-input",buffered:true}),p((function(){o(c.takeRecords()),r(true);})),a((function(){R=k(),D.length=0,x.clear(),i=f("INP"),r=d(e,i,N,n.reportAllChanges);})));})));},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t());}));},c=s("largest-contentful-paint",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=true,t(true));}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:true,capture:true});})),p(m),a((function(r){i=f("LCP"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=true,t(true);}));}));}}));},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),true):setTimeout(n,0);},Q=function(e,n){n=n||{};var t=f("TTFB"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(true),a((function(){t=f("TTFB",0),(r=d(e,t,J,n.reportAllChanges))(true);})));}));};
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, entry.responseStart && entry.startTime ? entry.responseStart - entry.startTime : 0, 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));
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
- w(onVitalsSignal);
7718
- j(onVitalsSignal);
7719
- G(onVitalsSignal);
7720
- Q(onVitalsSignal);
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 isGraphql = messageInfo.url.includes("/graphql");
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 !== "AbortError") {
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/constructor';
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.10-beta.0',
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) {