@openreplay/tracker 14.0.10-beta.1 → 14.0.10

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 (273) hide show
  1. package/{cjs → dist/cjs}/index.js +27 -49
  2. package/dist/cjs/index.js.map +1 -0
  3. package/{cjs → dist/cjs/main}/app/index.d.ts +38 -6
  4. package/{lib → dist/cjs/main}/app/messages.gen.d.ts +2 -2
  5. package/{lib/app/nodes.d.ts → dist/cjs/main/app/nodes/index.d.ts} +15 -7
  6. package/dist/cjs/main/app/nodes/maintainer.d.ts +28 -0
  7. package/{cjs → dist/cjs/main}/app/observer/iframe_observer.d.ts +1 -1
  8. package/{lib → dist/cjs/main}/app/observer/iframe_offsets.d.ts +1 -1
  9. package/{lib → dist/cjs/main}/app/observer/observer.d.ts +6 -0
  10. package/{lib → dist/cjs/main}/app/observer/top_observer.d.ts +6 -2
  11. package/{cjs → dist/cjs/main}/app/sanitizer.d.ts +5 -2
  12. package/{cjs → dist/cjs/main}/app/session.d.ts +6 -3
  13. package/{lib → dist/cjs/main}/index.d.ts +2 -2
  14. package/{lib → dist/cjs/main}/modules/attributeSender.d.ts +5 -2
  15. package/{cjs → dist/cjs/main}/modules/conditionsManager.d.ts +1 -1
  16. package/{cjs → dist/cjs/main}/modules/tagWatcher.d.ts +8 -4
  17. package/{lib → dist/cjs/main}/modules/userTesting/SignalManager.d.ts +2 -2
  18. package/{lib → dist/cjs/main}/utils.d.ts +4 -3
  19. package/dist/lib/index.js +9323 -0
  20. package/dist/lib/index.js.map +1 -0
  21. package/{lib → dist/lib/main}/app/index.d.ts +38 -6
  22. package/{cjs → dist/lib/main}/app/messages.gen.d.ts +2 -2
  23. package/{cjs/app/nodes.d.ts → dist/lib/main/app/nodes/index.d.ts} +15 -7
  24. package/dist/lib/main/app/nodes/maintainer.d.ts +28 -0
  25. package/{lib → dist/lib/main}/app/observer/iframe_observer.d.ts +1 -1
  26. package/{cjs → dist/lib/main}/app/observer/iframe_offsets.d.ts +1 -1
  27. package/{cjs → dist/lib/main}/app/observer/observer.d.ts +6 -0
  28. package/{cjs → dist/lib/main}/app/observer/top_observer.d.ts +6 -2
  29. package/{lib → dist/lib/main}/app/sanitizer.d.ts +5 -2
  30. package/{lib → dist/lib/main}/app/session.d.ts +6 -3
  31. package/{cjs → dist/lib/main}/index.d.ts +2 -2
  32. package/{cjs → dist/lib/main}/modules/attributeSender.d.ts +5 -2
  33. package/{lib → dist/lib/main}/modules/conditionsManager.d.ts +1 -1
  34. package/{lib → dist/lib/main}/modules/tagWatcher.d.ts +8 -4
  35. package/{cjs → dist/lib/main}/modules/userTesting/SignalManager.d.ts +2 -2
  36. package/{cjs → dist/lib/main}/utils.d.ts +4 -3
  37. package/package.json +29 -10
  38. package/.eslintignore +0 -11
  39. package/.nvmrc +0 -1
  40. package/.prettierignore +0 -1
  41. package/CHANGELOG.md +0 -297
  42. package/bun.lockb +0 -0
  43. package/cjs/app/canvas.js +0 -204
  44. package/cjs/app/guards.js +0 -37
  45. package/cjs/app/index.js +0 -1366
  46. package/cjs/app/logger.js +0 -37
  47. package/cjs/app/messages.gen.js +0 -702
  48. package/cjs/app/nodes.js +0 -110
  49. package/cjs/app/observer/iframe_observer.js +0 -35
  50. package/cjs/app/observer/iframe_offsets.js +0 -56
  51. package/cjs/app/observer/observer.js +0 -352
  52. package/cjs/app/observer/shadow_root_observer.js +0 -24
  53. package/cjs/app/observer/top_observer.js +0 -134
  54. package/cjs/app/sanitizer.js +0 -82
  55. package/cjs/app/session.js +0 -140
  56. package/cjs/app/ticker.js +0 -48
  57. package/cjs/common/interaction.js +0 -2
  58. package/cjs/common/messages.gen.js +0 -4
  59. package/cjs/modules/attributeSender.js +0 -51
  60. package/cjs/modules/axiosSpy.js +0 -122
  61. package/cjs/modules/conditionsManager.js +0 -343
  62. package/cjs/modules/connection.js +0 -15
  63. package/cjs/modules/console.js +0 -127
  64. package/cjs/modules/constructedStyleSheets.js +0 -138
  65. package/cjs/modules/cssrules.js +0 -99
  66. package/cjs/modules/exception.js +0 -85
  67. package/cjs/modules/featureFlags.js +0 -89
  68. package/cjs/modules/focus.js +0 -45
  69. package/cjs/modules/fonts.js +0 -57
  70. package/cjs/modules/img.js +0 -110
  71. package/cjs/modules/input.js +0 -203
  72. package/cjs/modules/mouse.js +0 -195
  73. package/cjs/modules/network.js +0 -244
  74. package/cjs/modules/performance.js +0 -53
  75. package/cjs/modules/scroll.js +0 -84
  76. package/cjs/modules/selection.js +0 -37
  77. package/cjs/modules/tabs.js +0 -13
  78. package/cjs/modules/tagWatcher.js +0 -76
  79. package/cjs/modules/timing.js +0 -173
  80. package/cjs/modules/userTesting/SignalManager.js +0 -83
  81. package/cjs/modules/userTesting/dnd.js +0 -40
  82. package/cjs/modules/userTesting/index.js +0 -464
  83. package/cjs/modules/userTesting/recorder.js +0 -101
  84. package/cjs/modules/userTesting/styles.js +0 -266
  85. package/cjs/modules/userTesting/utils.js +0 -87
  86. package/cjs/modules/viewport.js +0 -43
  87. package/cjs/package.json +0 -1
  88. package/cjs/utils.js +0 -230
  89. package/coverage/clover.xml +0 -4304
  90. package/coverage/coverage-final.json +0 -55
  91. package/coverage/lcov-report/base.css +0 -224
  92. package/coverage/lcov-report/block-navigation.js +0 -87
  93. package/coverage/lcov-report/favicon.png +0 -0
  94. package/coverage/lcov-report/index.html +0 -206
  95. package/coverage/lcov-report/main/app/canvas.ts.html +0 -712
  96. package/coverage/lcov-report/main/app/guards.ts.html +0 -232
  97. package/coverage/lcov-report/main/app/index.html +0 -236
  98. package/coverage/lcov-report/main/app/index.ts.html +0 -3955
  99. package/coverage/lcov-report/main/app/logger.ts.html +0 -211
  100. package/coverage/lcov-report/main/app/messages.gen.ts.html +0 -3034
  101. package/coverage/lcov-report/main/app/nodes.ts.html +0 -406
  102. package/coverage/lcov-report/main/app/observer/iframe_observer.ts.html +0 -148
  103. package/coverage/lcov-report/main/app/observer/iframe_offsets.ts.html +0 -289
  104. package/coverage/lcov-report/main/app/observer/index.html +0 -161
  105. package/coverage/lcov-report/main/app/observer/shadow_root_observer.ts.html +0 -142
  106. package/coverage/lcov-report/main/app/observer/top_observer.ts.html +0 -541
  107. package/coverage/lcov-report/main/app/sanitizer.ts.html +0 -403
  108. package/coverage/lcov-report/main/app/session.ts.html +0 -622
  109. package/coverage/lcov-report/main/app/ticker.ts.html +0 -250
  110. package/coverage/lcov-report/main/index.html +0 -131
  111. package/coverage/lcov-report/main/index.ts.html +0 -1597
  112. package/coverage/lcov-report/main/modules/Network/beaconProxy.ts.html +0 -400
  113. package/coverage/lcov-report/main/modules/Network/fetchProxy.ts.html +0 -1075
  114. package/coverage/lcov-report/main/modules/Network/index.html +0 -191
  115. package/coverage/lcov-report/main/modules/Network/index.ts.html +0 -244
  116. package/coverage/lcov-report/main/modules/Network/networkMessage.ts.html +0 -400
  117. package/coverage/lcov-report/main/modules/Network/utils.ts.html +0 -709
  118. package/coverage/lcov-report/main/modules/Network/xhrProxy.ts.html +0 -877
  119. package/coverage/lcov-report/main/modules/attributeSender.ts.html +0 -241
  120. package/coverage/lcov-report/main/modules/axiosSpy.ts.html +0 -709
  121. package/coverage/lcov-report/main/modules/conditionsManager.ts.html +0 -1381
  122. package/coverage/lcov-report/main/modules/connection.ts.html +0 -160
  123. package/coverage/lcov-report/main/modules/console.ts.html +0 -541
  124. package/coverage/lcov-report/main/modules/constructedStyleSheets.ts.html +0 -571
  125. package/coverage/lcov-report/main/modules/cssrules.ts.html +0 -418
  126. package/coverage/lcov-report/main/modules/exception.ts.html +0 -385
  127. package/coverage/lcov-report/main/modules/featureFlags.ts.html +0 -415
  128. package/coverage/lcov-report/main/modules/focus.ts.html +0 -220
  129. package/coverage/lcov-report/main/modules/fonts.ts.html +0 -289
  130. package/coverage/lcov-report/main/modules/img.ts.html +0 -436
  131. package/coverage/lcov-report/main/modules/index.html +0 -431
  132. package/coverage/lcov-report/main/modules/input.ts.html +0 -826
  133. package/coverage/lcov-report/main/modules/mouse.ts.html +0 -826
  134. package/coverage/lcov-report/main/modules/network.ts.html +0 -1123
  135. package/coverage/lcov-report/main/modules/performance.ts.html +0 -367
  136. package/coverage/lcov-report/main/modules/scroll.ts.html +0 -364
  137. package/coverage/lcov-report/main/modules/selection.ts.html +0 -202
  138. package/coverage/lcov-report/main/modules/tabs.ts.html +0 -124
  139. package/coverage/lcov-report/main/modules/tagWatcher.ts.html +0 -337
  140. package/coverage/lcov-report/main/modules/timing.ts.html +0 -877
  141. package/coverage/lcov-report/main/modules/userTesting/SignalManager.ts.html +0 -370
  142. package/coverage/lcov-report/main/modules/userTesting/dnd.ts.html +0 -220
  143. package/coverage/lcov-report/main/modules/userTesting/index.html +0 -191
  144. package/coverage/lcov-report/main/modules/userTesting/index.ts.html +0 -1909
  145. package/coverage/lcov-report/main/modules/userTesting/recorder.ts.html +0 -430
  146. package/coverage/lcov-report/main/modules/userTesting/styles.ts.html +0 -937
  147. package/coverage/lcov-report/main/modules/userTesting/utils.ts.html +0 -364
  148. package/coverage/lcov-report/main/modules/viewport.ts.html +0 -250
  149. package/coverage/lcov-report/main/utils.ts.html +0 -814
  150. package/coverage/lcov-report/prettify.css +0 -1
  151. package/coverage/lcov-report/prettify.js +0 -2
  152. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  153. package/coverage/lcov-report/sorter.js +0 -196
  154. package/coverage/lcov-report/webworker/BatchWriter.ts.html +0 -499
  155. package/coverage/lcov-report/webworker/MessageEncoder.gen.ts.html +0 -1021
  156. package/coverage/lcov-report/webworker/PrimitiveEncoder.ts.html +0 -436
  157. package/coverage/lcov-report/webworker/QueueSender.ts.html +0 -547
  158. package/coverage/lcov-report/webworker/index.html +0 -176
  159. package/coverage/lcov-report/webworker/index.ts.html +0 -667
  160. package/coverage/lcov.info +0 -8425
  161. package/jest.config.js +0 -13
  162. package/lib/app/canvas.js +0 -202
  163. package/lib/app/guards.js +0 -26
  164. package/lib/app/index.js +0 -1336
  165. package/lib/app/logger.js +0 -33
  166. package/lib/app/messages.gen.js +0 -622
  167. package/lib/app/nodes.js +0 -107
  168. package/lib/app/observer/iframe_observer.js +0 -29
  169. package/lib/app/observer/iframe_offsets.js +0 -53
  170. package/lib/app/observer/observer.js +0 -349
  171. package/lib/app/observer/shadow_root_observer.js +0 -18
  172. package/lib/app/observer/top_observer.js +0 -128
  173. package/lib/app/sanitizer.js +0 -77
  174. package/lib/app/session.js +0 -137
  175. package/lib/app/ticker.js +0 -45
  176. package/lib/common/interaction.js +0 -1
  177. package/lib/common/messages.gen.js +0 -3
  178. package/lib/common/tsconfig.tsbuildinfo +0 -1
  179. package/lib/index.js +0 -423
  180. package/lib/modules/attributeSender.js +0 -46
  181. package/lib/modules/axiosSpy.js +0 -119
  182. package/lib/modules/conditionsManager.js +0 -340
  183. package/lib/modules/connection.js +0 -12
  184. package/lib/modules/console.js +0 -124
  185. package/lib/modules/constructedStyleSheets.js +0 -133
  186. package/lib/modules/cssrules.js +0 -97
  187. package/lib/modules/exception.js +0 -76
  188. package/lib/modules/featureFlags.js +0 -86
  189. package/lib/modules/focus.js +0 -42
  190. package/lib/modules/fonts.js +0 -54
  191. package/lib/modules/img.js +0 -107
  192. package/lib/modules/input.js +0 -198
  193. package/lib/modules/mouse.js +0 -192
  194. package/lib/modules/network.js +0 -238
  195. package/lib/modules/performance.js +0 -49
  196. package/lib/modules/scroll.js +0 -81
  197. package/lib/modules/selection.js +0 -35
  198. package/lib/modules/tabs.js +0 -10
  199. package/lib/modules/tagWatcher.js +0 -73
  200. package/lib/modules/timing.js +0 -170
  201. package/lib/modules/userTesting/SignalManager.js +0 -80
  202. package/lib/modules/userTesting/dnd.js +0 -37
  203. package/lib/modules/userTesting/index.js +0 -435
  204. package/lib/modules/userTesting/recorder.js +0 -97
  205. package/lib/modules/userTesting/styles.js +0 -263
  206. package/lib/modules/userTesting/utils.js +0 -79
  207. package/lib/modules/viewport.js +0 -40
  208. package/lib/utils.js +0 -211
  209. package/rollup.config.js +0 -12
  210. package/scripts/checkver.cjs +0 -7
  211. package/tsconfig-base.json +0 -16
  212. /package/{cjs → dist/cjs}/common/interaction.d.ts +0 -0
  213. /package/{cjs → dist/cjs}/common/messages.gen.d.ts +0 -0
  214. /package/{cjs → dist/cjs/main}/app/canvas.d.ts +0 -0
  215. /package/{cjs → dist/cjs/main}/app/guards.d.ts +0 -0
  216. /package/{cjs → dist/cjs/main}/app/logger.d.ts +0 -0
  217. /package/{cjs → dist/cjs/main}/app/observer/shadow_root_observer.d.ts +0 -0
  218. /package/{cjs → dist/cjs/main}/app/ticker.d.ts +0 -0
  219. /package/{cjs → dist/cjs/main}/modules/axiosSpy.d.ts +0 -0
  220. /package/{cjs → dist/cjs/main}/modules/connection.d.ts +0 -0
  221. /package/{cjs → dist/cjs/main}/modules/console.d.ts +0 -0
  222. /package/{cjs → dist/cjs/main}/modules/constructedStyleSheets.d.ts +0 -0
  223. /package/{cjs → dist/cjs/main}/modules/cssrules.d.ts +0 -0
  224. /package/{cjs → dist/cjs/main}/modules/exception.d.ts +0 -0
  225. /package/{cjs → dist/cjs/main}/modules/featureFlags.d.ts +0 -0
  226. /package/{cjs → dist/cjs/main}/modules/focus.d.ts +0 -0
  227. /package/{cjs → dist/cjs/main}/modules/fonts.d.ts +0 -0
  228. /package/{cjs → dist/cjs/main}/modules/img.d.ts +0 -0
  229. /package/{cjs → dist/cjs/main}/modules/input.d.ts +0 -0
  230. /package/{cjs → dist/cjs/main}/modules/mouse.d.ts +0 -0
  231. /package/{cjs → dist/cjs/main}/modules/network.d.ts +0 -0
  232. /package/{cjs → dist/cjs/main}/modules/performance.d.ts +0 -0
  233. /package/{cjs → dist/cjs/main}/modules/scroll.d.ts +0 -0
  234. /package/{cjs → dist/cjs/main}/modules/selection.d.ts +0 -0
  235. /package/{cjs → dist/cjs/main}/modules/tabs.d.ts +0 -0
  236. /package/{cjs → dist/cjs/main}/modules/timing.d.ts +0 -0
  237. /package/{cjs → dist/cjs/main}/modules/userTesting/dnd.d.ts +0 -0
  238. /package/{cjs → dist/cjs/main}/modules/userTesting/index.d.ts +0 -0
  239. /package/{cjs → dist/cjs/main}/modules/userTesting/recorder.d.ts +0 -0
  240. /package/{cjs → dist/cjs/main}/modules/userTesting/styles.d.ts +0 -0
  241. /package/{cjs → dist/cjs/main}/modules/userTesting/utils.d.ts +0 -0
  242. /package/{cjs → dist/cjs/main}/modules/viewport.d.ts +0 -0
  243. /package/{lib → dist/lib}/common/interaction.d.ts +0 -0
  244. /package/{lib → dist/lib}/common/messages.gen.d.ts +0 -0
  245. /package/{lib → dist/lib/main}/app/canvas.d.ts +0 -0
  246. /package/{lib → dist/lib/main}/app/guards.d.ts +0 -0
  247. /package/{lib → dist/lib/main}/app/logger.d.ts +0 -0
  248. /package/{lib → dist/lib/main}/app/observer/shadow_root_observer.d.ts +0 -0
  249. /package/{lib → dist/lib/main}/app/ticker.d.ts +0 -0
  250. /package/{lib → dist/lib/main}/modules/axiosSpy.d.ts +0 -0
  251. /package/{lib → dist/lib/main}/modules/connection.d.ts +0 -0
  252. /package/{lib → dist/lib/main}/modules/console.d.ts +0 -0
  253. /package/{lib → dist/lib/main}/modules/constructedStyleSheets.d.ts +0 -0
  254. /package/{lib → dist/lib/main}/modules/cssrules.d.ts +0 -0
  255. /package/{lib → dist/lib/main}/modules/exception.d.ts +0 -0
  256. /package/{lib → dist/lib/main}/modules/featureFlags.d.ts +0 -0
  257. /package/{lib → dist/lib/main}/modules/focus.d.ts +0 -0
  258. /package/{lib → dist/lib/main}/modules/fonts.d.ts +0 -0
  259. /package/{lib → dist/lib/main}/modules/img.d.ts +0 -0
  260. /package/{lib → dist/lib/main}/modules/input.d.ts +0 -0
  261. /package/{lib → dist/lib/main}/modules/mouse.d.ts +0 -0
  262. /package/{lib → dist/lib/main}/modules/network.d.ts +0 -0
  263. /package/{lib → dist/lib/main}/modules/performance.d.ts +0 -0
  264. /package/{lib → dist/lib/main}/modules/scroll.d.ts +0 -0
  265. /package/{lib → dist/lib/main}/modules/selection.d.ts +0 -0
  266. /package/{lib → dist/lib/main}/modules/tabs.d.ts +0 -0
  267. /package/{lib → dist/lib/main}/modules/timing.d.ts +0 -0
  268. /package/{lib → dist/lib/main}/modules/userTesting/dnd.d.ts +0 -0
  269. /package/{lib → dist/lib/main}/modules/userTesting/index.d.ts +0 -0
  270. /package/{lib → dist/lib/main}/modules/userTesting/recorder.d.ts +0 -0
  271. /package/{lib → dist/lib/main}/modules/userTesting/styles.d.ts +0 -0
  272. /package/{lib → dist/lib/main}/modules/userTesting/utils.d.ts +0 -0
  273. /package/{lib → dist/lib/main}/modules/viewport.d.ts +0 -0
package/lib/app/nodes.js DELETED
@@ -1,107 +0,0 @@
1
- import { createEventListener, deleteEventListener } from '../utils.js';
2
- export default class Nodes {
3
- constructor(node_id) {
4
- this.node_id = node_id;
5
- this.nodes = [];
6
- this.totalNodeAmount = 0;
7
- this.nodeCallbacks = [];
8
- this.elementListeners = new Map();
9
- this.nextNodeId = 0;
10
- this.scanTree = (cb) => {
11
- this.nodes.forEach((node) => cb(node));
12
- };
13
- }
14
- syntheticMode(frameOrder) {
15
- const maxSafeNumber = 9007199254740900;
16
- const placeholderSize = 99999999;
17
- const nextFrameId = placeholderSize * frameOrder;
18
- // I highly doubt that this will ever happen,
19
- // but it will be easier to debug if it does
20
- if (nextFrameId > maxSafeNumber) {
21
- throw new Error('Placeholder id overflow');
22
- }
23
- this.nextNodeId = nextFrameId;
24
- }
25
- // Attached once per Tracker instance
26
- attachNodeCallback(nodeCallback) {
27
- this.nodeCallbacks.push(nodeCallback);
28
- }
29
- attachNodeListener(node, type, listener, useCapture = true) {
30
- const id = this.getID(node);
31
- if (id === undefined) {
32
- return;
33
- }
34
- createEventListener(node, type, listener, useCapture);
35
- let listeners = this.elementListeners.get(id);
36
- if (listeners === undefined) {
37
- listeners = [];
38
- this.elementListeners.set(id, listeners);
39
- }
40
- listeners.push([type, listener, useCapture]);
41
- }
42
- registerNode(node) {
43
- let id = node[this.node_id];
44
- const isNew = id === undefined;
45
- if (isNew) {
46
- id = this.nextNodeId;
47
- this.totalNodeAmount++;
48
- this.nextNodeId++;
49
- this.nodes[id] = node;
50
- node[this.node_id] = id;
51
- }
52
- return [id, isNew];
53
- }
54
- unregisterNode(node) {
55
- const id = node[this.node_id];
56
- if (id !== undefined) {
57
- ;
58
- node[this.node_id] = undefined;
59
- delete node[this.node_id];
60
- delete this.nodes[id];
61
- const listeners = this.elementListeners.get(id);
62
- if (listeners !== undefined) {
63
- this.elementListeners.delete(id);
64
- listeners.forEach((listener) => deleteEventListener(node, listener[0], listener[1], listener[2]));
65
- }
66
- this.totalNodeAmount--;
67
- }
68
- return id;
69
- }
70
- cleanTree() {
71
- // sadly we keep empty items in array here resulting in some memory still being used
72
- // but its still better than keeping dead nodes or undef elements
73
- // plus we keep our index positions for new/alive nodes
74
- // performance test: 3ms for 30k nodes with 17k dead ones
75
- for (let i = 0; i < this.nodes.length; i++) {
76
- const node = this.nodes[i];
77
- if (node && !document.contains(node)) {
78
- this.unregisterNode(node);
79
- }
80
- }
81
- }
82
- callNodeCallbacks(node, isStart) {
83
- this.nodeCallbacks.forEach((cb) => cb(node, isStart));
84
- }
85
- getID(node) {
86
- if (!node)
87
- return undefined;
88
- return node[this.node_id];
89
- }
90
- getNode(id) {
91
- return this.nodes[id];
92
- }
93
- getNodeCount() {
94
- return this.totalNodeAmount;
95
- }
96
- clear() {
97
- for (let id = 0; id < this.nodes.length; id++) {
98
- const node = this.nodes[id];
99
- if (!node) {
100
- continue;
101
- }
102
- this.unregisterNode(node);
103
- }
104
- this.nextNodeId = 0;
105
- this.nodes.length = 0;
106
- }
107
- }
@@ -1,29 +0,0 @@
1
- import Observer from './observer.js';
2
- import { CreateIFrameDocument } from '../messages.gen.js';
3
- export default class IFrameObserver extends Observer {
4
- observe(iframe) {
5
- const doc = iframe.contentDocument;
6
- const hostID = this.app.nodes.getID(iframe);
7
- if (!doc || hostID === undefined) {
8
- return;
9
- } //log TODO common app.logger
10
- // Have to observe document, because the inner <html> might be changed
11
- this.observeRoot(doc, (docID) => {
12
- //MBTODO: do not send if empty (send on load? it might be in-place iframe, like our replayer, which does not get loaded)
13
- if (docID === undefined) {
14
- this.app.debug.log('OpenReplay: Iframe document not bound');
15
- return;
16
- }
17
- this.app.send(CreateIFrameDocument(hostID, docID));
18
- });
19
- }
20
- syntheticObserve(selfId, doc) {
21
- this.observeRoot(doc, (docID) => {
22
- if (docID === undefined) {
23
- this.app.debug.log('OpenReplay: Iframe document not bound');
24
- return;
25
- }
26
- this.app.send(CreateIFrameDocument(selfId, docID));
27
- });
28
- }
29
- }
@@ -1,53 +0,0 @@
1
- export default class IFrameOffsets {
2
- constructor() {
3
- this.states = new Map();
4
- }
5
- calcOffset(state) {
6
- let parLeft = 0, parTop = 0;
7
- if (state.parent) {
8
- ;
9
- [parLeft, parTop] = this.calcOffset(state.parent);
10
- }
11
- if (!state.offset) {
12
- const { left, top } = state.iFrame.getBoundingClientRect();
13
- state.offset = [left, top];
14
- }
15
- const [left, top] = state.offset;
16
- return [parLeft + left, parTop + top]; // TODO: store absolute sum, invalidate whole subtree. Otherwise it is summated on each mousemove
17
- }
18
- getDocumentOffset(doc) {
19
- const state = this.states.get(doc);
20
- if (!state) {
21
- return [0, 0];
22
- } // topmost doc
23
- return this.calcOffset(state);
24
- }
25
- observe(iFrame) {
26
- const doc = iFrame.contentDocument;
27
- if (!doc) {
28
- return;
29
- }
30
- const parentDoc = iFrame.ownerDocument;
31
- const parentState = this.states.get(parentDoc);
32
- const state = {
33
- offset: null,
34
- iFrame,
35
- parent: parentState || null,
36
- clear: () => {
37
- parentDoc.removeEventListener('scroll', invalidateOffset);
38
- parentDoc.defaultView?.removeEventListener('resize', invalidateOffset);
39
- },
40
- };
41
- const invalidateOffset = () => {
42
- state.offset = null;
43
- };
44
- // anything more reliable? This does not cover all cases (layout changes are ignored, for ex.)
45
- parentDoc.addEventListener('scroll', invalidateOffset);
46
- parentDoc.defaultView?.addEventListener('resize', invalidateOffset);
47
- this.states.set(doc, state);
48
- }
49
- clear() {
50
- this.states.forEach((s) => s.clear());
51
- this.states.clear();
52
- }
53
- }
@@ -1,349 +0,0 @@
1
- import { createMutationObserver } from '../../utils.js';
2
- import { RemoveNodeAttribute, SetNodeAttributeURLBased, SetCSSDataURLBased, SetNodeData, CreateTextNode, CreateElementNode, MoveNode, RemoveNode, UnbindNodes, } from '../messages.gen.js';
3
- import { isRootNode, isTextNode, isElementNode, isSVGElement, hasTag, isCommentNode, } from '../guards.js';
4
- function isIgnored(node) {
5
- if (isCommentNode(node)) {
6
- return true;
7
- }
8
- if (isTextNode(node)) {
9
- return false;
10
- }
11
- if (!isElementNode(node)) {
12
- return true;
13
- }
14
- const tag = node.tagName.toUpperCase();
15
- if (tag === 'LINK') {
16
- const rel = node.getAttribute('rel');
17
- const as = node.getAttribute('as');
18
- return !(rel?.includes('stylesheet') || as === 'style' || as === 'font');
19
- }
20
- return (tag === 'SCRIPT' || tag === 'NOSCRIPT' || tag === 'META' || tag === 'TITLE' || tag === 'BASE');
21
- }
22
- function isObservable(node) {
23
- if (isRootNode(node)) {
24
- return true;
25
- }
26
- return !isIgnored(node);
27
- }
28
- /*
29
- TODO:
30
- - fix unbinding logic + send all removals first (ensure sequence is correct)
31
- - use document as a 0-node in the upper context (should be updated in player at first)
32
- */
33
- var RecentsType;
34
- (function (RecentsType) {
35
- RecentsType[RecentsType["New"] = 0] = "New";
36
- RecentsType[RecentsType["Removed"] = 1] = "Removed";
37
- RecentsType[RecentsType["Changed"] = 2] = "Changed";
38
- })(RecentsType || (RecentsType = {}));
39
- export default class Observer {
40
- constructor(app, isTopContext = false) {
41
- this.app = app;
42
- this.isTopContext = isTopContext;
43
- this.commited = [];
44
- this.recents = new Map();
45
- this.indexes = [];
46
- this.attributesMap = new Map();
47
- this.textSet = new Set();
48
- this.observer = createMutationObserver(this.app.safe((mutations) => {
49
- for (const mutation of mutations) {
50
- // mutations order is sequential
51
- const target = mutation.target;
52
- const type = mutation.type;
53
- if (!isObservable(target)) {
54
- continue;
55
- }
56
- if (type === 'childList') {
57
- for (let i = 0; i < mutation.removedNodes.length; i++) {
58
- // Should be the same as bindTree(mutation.removedNodes[i]), but logic needs to be be untied
59
- if (isObservable(mutation.removedNodes[i])) {
60
- this.bindNode(mutation.removedNodes[i]);
61
- }
62
- }
63
- for (let i = 0; i < mutation.addedNodes.length; i++) {
64
- this.bindTree(mutation.addedNodes[i]);
65
- }
66
- continue;
67
- }
68
- const id = this.app.nodes.getID(target);
69
- if (id === undefined) {
70
- continue;
71
- }
72
- if (!this.recents.has(id)) {
73
- this.recents.set(id, RecentsType.Changed); // TODO only when altered
74
- }
75
- if (type === 'attributes') {
76
- const name = mutation.attributeName;
77
- if (name === null) {
78
- continue;
79
- }
80
- let attr = this.attributesMap.get(id);
81
- if (attr === undefined) {
82
- this.attributesMap.set(id, (attr = new Set()));
83
- }
84
- attr.add(name);
85
- continue;
86
- }
87
- if (type === 'characterData') {
88
- this.textSet.add(id);
89
- continue;
90
- }
91
- }
92
- this.commitNodes();
93
- }));
94
- }
95
- clear() {
96
- this.commited.length = 0;
97
- this.recents.clear();
98
- this.indexes.length = 1;
99
- this.attributesMap.clear();
100
- this.textSet.clear();
101
- }
102
- sendNodeAttribute(id, node, name, value) {
103
- if (isSVGElement(node)) {
104
- if (name.substr(0, 6) === 'xlink:') {
105
- name = name.substr(6);
106
- }
107
- if (value === null) {
108
- this.app.send(RemoveNodeAttribute(id, name));
109
- }
110
- else if (name === 'href') {
111
- if (value.length > 1e5) {
112
- value = '';
113
- }
114
- this.app.send(SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
115
- }
116
- else {
117
- this.app.attributeSender.sendSetAttribute(id, name, value);
118
- }
119
- return;
120
- }
121
- if (name === 'src' ||
122
- name === 'srcset' ||
123
- name === 'integrity' ||
124
- name === 'crossorigin' ||
125
- name === 'autocomplete' ||
126
- name.substr(0, 2) === 'on') {
127
- return;
128
- }
129
- if (name === 'value' &&
130
- hasTag(node, 'input') &&
131
- node.type !== 'button' &&
132
- node.type !== 'reset' &&
133
- node.type !== 'submit') {
134
- return;
135
- }
136
- if (value === null) {
137
- this.app.send(RemoveNodeAttribute(id, name));
138
- return;
139
- }
140
- if (name === 'style' || (name === 'href' && hasTag(node, 'link'))) {
141
- this.app.send(SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
142
- return;
143
- }
144
- if (name === 'href' || value.length > 1e5) {
145
- value = '';
146
- }
147
- this.app.attributeSender.sendSetAttribute(id, name, value);
148
- }
149
- sendNodeData(id, parentElement, data) {
150
- if (hasTag(parentElement, 'style')) {
151
- this.app.send(SetCSSDataURLBased(id, data, this.app.getBaseHref()));
152
- return;
153
- }
154
- data = this.app.sanitizer.sanitize(id, data);
155
- this.app.send(SetNodeData(id, data));
156
- }
157
- bindNode(node) {
158
- const [id, isNew] = this.app.nodes.registerNode(node);
159
- if (isNew) {
160
- this.recents.set(id, RecentsType.New);
161
- }
162
- else if (this.recents.get(id) !== RecentsType.New) {
163
- this.recents.set(id, RecentsType.Removed);
164
- }
165
- }
166
- bindTree(node) {
167
- if (!isObservable(node)) {
168
- return;
169
- }
170
- this.bindNode(node);
171
- const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
172
- acceptNode: (node) => {
173
- if (this.app.nodes.getID(node) !== undefined) {
174
- this.app.debug.error('! Node is already bound', node);
175
- }
176
- return isIgnored(node) || this.app.nodes.getID(node) !== undefined
177
- ? NodeFilter.FILTER_REJECT
178
- : NodeFilter.FILTER_ACCEPT;
179
- },
180
- },
181
- // @ts-ignore
182
- false);
183
- while (walker.nextNode()) {
184
- this.bindNode(walker.currentNode);
185
- }
186
- }
187
- unbindTree(node) {
188
- const id = this.app.nodes.unregisterNode(node);
189
- if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
190
- // Sending RemoveNode only for parent to maintain
191
- this.app.send(RemoveNode(id));
192
- // Unregistering all the children in order to clear the memory
193
- const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
194
- acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) === undefined
195
- ? NodeFilter.FILTER_REJECT
196
- : NodeFilter.FILTER_ACCEPT,
197
- },
198
- // @ts-ignore
199
- false);
200
- let removed = 0;
201
- const totalBeforeRemove = this.app.nodes.getNodeCount();
202
- while (walker.nextNode()) {
203
- removed += 1;
204
- this.app.nodes.unregisterNode(walker.currentNode);
205
- }
206
- const removedPercent = Math.floor((removed / totalBeforeRemove) * 100);
207
- if (removedPercent > 30) {
208
- this.app.send(UnbindNodes(removedPercent));
209
- }
210
- }
211
- }
212
- // A top-consumption function on the infinite lists test. (~1% of performance resources)
213
- _commitNode(id, node) {
214
- if (isRootNode(node)) {
215
- return true;
216
- }
217
- const parent = node.parentNode;
218
- let parentID;
219
- // Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
220
- // TODO: get rid of "special" cases (there is an issue with CreateDocument altered behaviour though)
221
- // TODO: Clean the logic (though now it workd fine)
222
- if (!hasTag(node, 'html') || !this.isTopContext) {
223
- if (parent === null) {
224
- // Sometimes one observation contains attribute mutations for the removimg node, which gets ignored here.
225
- // That shouldn't affect the visual rendering ( should it? maybe when transition applied? )
226
- this.unbindTree(node);
227
- return false;
228
- }
229
- parentID = this.app.nodes.getID(parent);
230
- if (parentID === undefined) {
231
- this.unbindTree(node);
232
- return false;
233
- }
234
- if (!this.commitNode(parentID)) {
235
- this.unbindTree(node);
236
- return false;
237
- }
238
- this.app.sanitizer.handleNode(id, parentID, node);
239
- if (this.app.sanitizer.isHidden(parentID)) {
240
- return false;
241
- }
242
- }
243
- // From here parentID === undefined if node is top context HTML node
244
- let sibling = node.previousSibling;
245
- while (sibling !== null) {
246
- const siblingID = this.app.nodes.getID(sibling);
247
- if (siblingID !== undefined) {
248
- this.commitNode(siblingID);
249
- this.indexes[id] = this.indexes[siblingID] + 1;
250
- break;
251
- }
252
- sibling = sibling.previousSibling;
253
- }
254
- if (sibling === null) {
255
- this.indexes[id] = 0;
256
- }
257
- const recentsType = this.recents.get(id);
258
- const isNew = recentsType === RecentsType.New;
259
- const index = this.indexes[id];
260
- if (index === undefined) {
261
- throw 'commitNode: missing node index';
262
- }
263
- if (isNew) {
264
- if (isElementNode(node)) {
265
- let el = node;
266
- if (parentID !== undefined) {
267
- if (this.app.sanitizer.isHidden(id)) {
268
- const width = el.clientWidth;
269
- const height = el.clientHeight;
270
- el = node.cloneNode();
271
- el.style.width = `${width}px`;
272
- el.style.height = `${height}px`;
273
- }
274
- this.app.send(CreateElementNode(id, parentID, index, el.tagName, isSVGElement(node)));
275
- }
276
- for (let i = 0; i < el.attributes.length; i++) {
277
- const attr = el.attributes[i];
278
- this.sendNodeAttribute(id, el, attr.nodeName, attr.value);
279
- }
280
- }
281
- else if (isTextNode(node)) {
282
- // for text node id != 0, hence parentID !== undefined and parent is Element
283
- this.app.send(CreateTextNode(id, parentID, index));
284
- this.sendNodeData(id, parent, node.data);
285
- }
286
- return true;
287
- }
288
- if (recentsType === RecentsType.Removed && parentID !== undefined) {
289
- this.app.send(MoveNode(id, parentID, index));
290
- }
291
- const attr = this.attributesMap.get(id);
292
- if (attr !== undefined) {
293
- if (!isElementNode(node)) {
294
- throw 'commitNode: node is not an element';
295
- }
296
- for (const name of attr) {
297
- this.sendNodeAttribute(id, node, name, node.getAttribute(name));
298
- }
299
- }
300
- if (this.textSet.has(id)) {
301
- if (!isTextNode(node)) {
302
- throw 'commitNode: node is not a text';
303
- }
304
- // for text node id != 0, hence parent is Element
305
- this.sendNodeData(id, parent, node.data);
306
- }
307
- return true;
308
- }
309
- commitNode(id) {
310
- const node = this.app.nodes.getNode(id);
311
- if (node === undefined) {
312
- return false;
313
- }
314
- const cmt = this.commited[id];
315
- if (cmt !== undefined) {
316
- return cmt;
317
- }
318
- return (this.commited[id] = this._commitNode(id, node));
319
- }
320
- commitNodes(isStart = false) {
321
- let node;
322
- this.recents.forEach((type, id) => {
323
- this.commitNode(id);
324
- if (type === RecentsType.New && (node = this.app.nodes.getNode(id))) {
325
- this.app.nodes.callNodeCallbacks(node, isStart);
326
- }
327
- });
328
- this.clear();
329
- }
330
- // ISSSUE (nodeToBinde should be the same as node in all cases. Look at the comment about 0-node at the beginning of the file.)
331
- // TODO: use one observer instance for all iframes/shadowRoots (composition instiad of inheritance)
332
- observeRoot(node, beforeCommit, nodeToBind = node) {
333
- this.observer.observe(node, {
334
- childList: true,
335
- attributes: true,
336
- characterData: true,
337
- subtree: true,
338
- attributeOldValue: false,
339
- characterDataOldValue: false,
340
- });
341
- this.bindTree(nodeToBind);
342
- beforeCommit(this.app.nodes.getID(node));
343
- this.commitNodes(true);
344
- }
345
- disconnect() {
346
- this.observer.disconnect();
347
- this.clear();
348
- }
349
- }
@@ -1,18 +0,0 @@
1
- import Observer from './observer.js';
2
- import { CreateIFrameDocument } from '../messages.gen.js';
3
- export default class ShadowRootObserver extends Observer {
4
- observe(el) {
5
- const shRoot = el.shadowRoot;
6
- const hostID = this.app.nodes.getID(el);
7
- if (!shRoot || hostID === undefined) {
8
- return;
9
- } // log
10
- this.observeRoot(shRoot, (rootID) => {
11
- if (rootID === undefined) {
12
- this.app.debug.error('OpenReplay: Shadow Root was not bound');
13
- return;
14
- }
15
- this.app.send(CreateIFrameDocument(hostID, rootID));
16
- });
17
- }
18
- }
@@ -1,128 +0,0 @@
1
- import Observer from './observer.js';
2
- import { isElementNode, hasTag } from '../guards.js';
3
- import IFrameObserver from './iframe_observer.js';
4
- import ShadowRootObserver from './shadow_root_observer.js';
5
- import IFrameOffsets from './iframe_offsets.js';
6
- import { CreateDocument } from '../messages.gen.js';
7
- import { IN_BROWSER, hasOpenreplayAttribute, canAccessIframe } from '../../utils.js';
8
- const attachShadowNativeFn = IN_BROWSER ? Element.prototype.attachShadow : () => new ShadowRoot();
9
- export default class TopObserver extends Observer {
10
- constructor(app, options) {
11
- super(app, true);
12
- this.iframeOffsets = new IFrameOffsets();
13
- this.contextCallbacks = [];
14
- // Attached once per Tracker instance
15
- this.contextsSet = new Set();
16
- this.iframeObservers = [];
17
- this.shadowRootObservers = [];
18
- this.options = Object.assign({
19
- captureIFrames: true,
20
- }, options);
21
- // IFrames
22
- this.app.nodes.attachNodeCallback((node) => {
23
- if (hasTag(node, 'iframe') &&
24
- ((this.options.captureIFrames && !hasOpenreplayAttribute(node, 'obscured')) ||
25
- hasOpenreplayAttribute(node, 'capture'))) {
26
- this.handleIframe(node);
27
- }
28
- });
29
- // ShadowDOM
30
- this.app.nodes.attachNodeCallback((node) => {
31
- if (isElementNode(node) && node.shadowRoot !== null) {
32
- this.handleShadowRoot(node.shadowRoot);
33
- }
34
- });
35
- }
36
- attachContextCallback(cb) {
37
- this.contextCallbacks.push(cb);
38
- }
39
- getDocumentOffset(doc) {
40
- return this.iframeOffsets.getDocumentOffset(doc);
41
- }
42
- handleIframe(iframe) {
43
- let doc = null;
44
- // setTimeout is required. Otherwise some event listeners (scroll, mousemove) applied in modules
45
- // do not work on the iframe document when it 've been loaded dynamically ((why?))
46
- const handle = this.app.safe(() => setTimeout(() => {
47
- const id = this.app.nodes.getID(iframe);
48
- if (id === undefined) {
49
- //log
50
- return;
51
- }
52
- if (!canAccessIframe(iframe))
53
- return;
54
- const currentWin = iframe.contentWindow;
55
- const currentDoc = iframe.contentDocument;
56
- if (currentDoc && currentDoc !== doc) {
57
- const observer = new IFrameObserver(this.app);
58
- this.iframeObservers.push(observer);
59
- observer.observe(iframe); // TODO: call unregisterNode for the previous doc if present (incapsulate: one iframe - one observer)
60
- doc = currentDoc;
61
- this.iframeOffsets.observe(iframe);
62
- }
63
- if (currentWin &&
64
- // Sometimes currentWin.window is null (not in specification). Such window object is not functional
65
- currentWin === currentWin.window &&
66
- !this.contextsSet.has(currentWin) // for each context callbacks called once per Tracker (TopObserver) instance
67
- //TODO: more explicit logic
68
- ) {
69
- this.contextsSet.add(currentWin);
70
- //@ts-ignore https://github.com/microsoft/TypeScript/issues/41684
71
- this.contextCallbacks.forEach((cb) => cb(currentWin));
72
- }
73
- // we need this delay because few iframes stacked one in another with rapid updates will break the player (or browser engine rather?)
74
- }, 100));
75
- iframe.addEventListener('load', handle); // why app.attachEventListener not working?
76
- handle();
77
- }
78
- handleShadowRoot(shRoot) {
79
- const observer = new ShadowRootObserver(this.app);
80
- this.shadowRootObservers.push(observer);
81
- observer.observe(shRoot.host);
82
- }
83
- observe() {
84
- // Protection from several subsequent calls?
85
- const observer = this;
86
- Element.prototype.attachShadow = function () {
87
- // eslint-disable-next-line
88
- const shadow = attachShadowNativeFn.apply(this, arguments);
89
- observer.handleShadowRoot(shadow);
90
- return shadow;
91
- };
92
- this.app.nodes.clear();
93
- // Can observe documentElement (<html>) here, because it is not supposed to be changing.
94
- // However, it is possible in some exotic cases and may cause an ignorance of the newly created <html>
95
- // In this case context.document have to be observed, but this will cause
96
- // the change in the re-player behaviour caused by CreateDocument message:
97
- // the 0-node ("fRoot") will become #document rather than documentElement as it is now.
98
- // Alternatively - observe(#document) then bindNode(documentElement)
99
- this.observeRoot(window.document, () => {
100
- this.app.send(CreateDocument());
101
- // it has no node_id here
102
- this.app.nodes.callNodeCallbacks(document, true);
103
- }, window.document.documentElement);
104
- }
105
- crossdomainObserve(selfId, frameOder) {
106
- const observer = this;
107
- Element.prototype.attachShadow = function () {
108
- // eslint-disable-next-line
109
- const shadow = attachShadowNativeFn.apply(this, arguments);
110
- observer.handleShadowRoot(shadow);
111
- return shadow;
112
- };
113
- this.app.nodes.clear();
114
- this.app.nodes.syntheticMode(frameOder);
115
- const iframeObserver = new IFrameObserver(this.app);
116
- this.iframeObservers.push(iframeObserver);
117
- iframeObserver.syntheticObserve(selfId, window.document);
118
- }
119
- disconnect() {
120
- this.iframeOffsets.clear();
121
- Element.prototype.attachShadow = attachShadowNativeFn;
122
- this.iframeObservers.forEach((o) => o.disconnect());
123
- this.iframeObservers = [];
124
- this.shadowRootObservers.forEach((o) => o.disconnect());
125
- this.shadowRootObservers = [];
126
- super.disconnect();
127
- }
128
- }