@newrelic/browser-agent 1.234.0 → 1.236.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 (372) hide show
  1. package/README.md +42 -2
  2. package/dist/cjs/common/config/state/init.js +3 -0
  3. package/dist/cjs/common/config/state/runtime.js +4 -4
  4. package/dist/cjs/common/constants/env.cdn.js +2 -2
  5. package/dist/cjs/common/constants/env.npm.js +1 -1
  6. package/dist/cjs/common/constants/runtime.js +52 -0
  7. package/dist/cjs/common/constants/shared-channel.js +19 -0
  8. package/dist/cjs/common/event-listener/event-listener-opts.js +3 -3
  9. package/dist/cjs/common/harvest/harvest-scheduler.js +35 -16
  10. package/dist/cjs/common/harvest/harvest.js +163 -144
  11. package/dist/cjs/common/harvest/types.js +54 -0
  12. package/dist/cjs/common/ids/id.js +2 -2
  13. package/dist/cjs/common/ids/unique-id.js +3 -3
  14. package/dist/cjs/common/session/session-entity.js +21 -13
  15. package/dist/cjs/common/timer/interaction-timer.js +3 -3
  16. package/dist/cjs/common/unload/eol.js +10 -11
  17. package/dist/cjs/common/url/canonicalize-url.js +2 -2
  18. package/dist/cjs/common/url/parse-url.js +3 -3
  19. package/dist/cjs/common/url/protocol.js +2 -2
  20. package/dist/cjs/common/util/feature-flags.js +23 -12
  21. package/dist/cjs/common/util/obfuscate.js +2 -2
  22. package/dist/cjs/common/util/submit-data.js +61 -79
  23. package/dist/cjs/common/window/nreum.js +14 -14
  24. package/dist/cjs/common/wrap/wrap-events.js +3 -3
  25. package/dist/cjs/common/wrap/wrap-fetch.js +5 -5
  26. package/dist/cjs/common/wrap/wrap-history.js +2 -2
  27. package/dist/cjs/common/wrap/wrap-jsonp.js +2 -2
  28. package/dist/cjs/common/wrap/wrap-mutation.js +2 -2
  29. package/dist/cjs/common/wrap/wrap-promise.js +2 -2
  30. package/dist/cjs/common/wrap/wrap-raf.js +3 -3
  31. package/dist/cjs/common/wrap/wrap-timer.js +5 -5
  32. package/dist/cjs/common/wrap/wrap-xhr.js +3 -3
  33. package/dist/cjs/features/ajax/aggregate/index.js +1 -1
  34. package/dist/cjs/features/ajax/instrument/distributed-tracing.js +2 -2
  35. package/dist/cjs/features/ajax/instrument/index.js +6 -7
  36. package/dist/cjs/features/jserrors/aggregate/index.js +11 -4
  37. package/dist/cjs/features/jserrors/instrument/index.js +6 -19
  38. package/dist/cjs/features/metrics/aggregate/framework-detection.js +2 -2
  39. package/dist/cjs/features/metrics/aggregate/index.js +3 -3
  40. package/dist/cjs/features/page_action/aggregate/index.js +3 -3
  41. package/dist/cjs/features/page_view_event/aggregate/index.js +10 -11
  42. package/dist/cjs/features/page_view_event/instrument/index.js +2 -2
  43. package/dist/cjs/features/page_view_timing/aggregate/index.js +3 -5
  44. package/dist/cjs/features/page_view_timing/instrument/index.js +2 -2
  45. package/dist/cjs/features/session_replay/aggregate/index.js +99 -82
  46. package/dist/cjs/features/session_replay/replay-mode.js +28 -0
  47. package/dist/cjs/features/session_trace/aggregate/index.js +222 -99
  48. package/dist/cjs/features/session_trace/constants.js +1 -3
  49. package/dist/cjs/features/session_trace/instrument/index.js +2 -18
  50. package/dist/cjs/features/spa/aggregate/index.js +1 -1
  51. package/dist/cjs/features/spa/constants.js +0 -1
  52. package/dist/cjs/features/spa/instrument/index.js +2 -2
  53. package/dist/cjs/features/utils/agent-session.js +20 -36
  54. package/dist/cjs/features/utils/aggregate-base.js +7 -12
  55. package/dist/cjs/features/utils/handler-cache.js +28 -23
  56. package/dist/cjs/features/utils/instrument-base.js +58 -40
  57. package/dist/cjs/index.js +7 -0
  58. package/dist/cjs/loaders/agent.js +7 -1
  59. package/dist/cjs/loaders/api/api.js +2 -2
  60. package/dist/cjs/loaders/api/apiAsync.js +6 -4
  61. package/dist/cjs/loaders/configure/configure.js +2 -2
  62. package/dist/cjs/loaders/features/featureDependencies.js +2 -0
  63. package/dist/cjs/loaders/micro-agent.js +29 -38
  64. package/dist/esm/common/config/state/init.js +3 -0
  65. package/dist/esm/common/config/state/runtime.js +1 -1
  66. package/dist/esm/common/constants/env.cdn.js +2 -2
  67. package/dist/esm/common/constants/env.npm.js +1 -1
  68. package/dist/esm/common/constants/runtime.js +38 -0
  69. package/dist/esm/common/constants/shared-channel.js +12 -0
  70. package/dist/esm/common/event-listener/event-listener-opts.js +1 -1
  71. package/dist/esm/common/harvest/harvest-scheduler.js +34 -17
  72. package/dist/esm/common/harvest/harvest.js +160 -142
  73. package/dist/esm/common/harvest/types.js +47 -0
  74. package/dist/esm/common/ids/id.js +1 -1
  75. package/dist/esm/common/ids/unique-id.js +1 -1
  76. package/dist/esm/common/session/session-entity.js +18 -12
  77. package/dist/esm/common/timer/interaction-timer.js +2 -2
  78. package/dist/esm/common/unload/eol.js +1 -2
  79. package/dist/esm/common/url/canonicalize-url.js +1 -1
  80. package/dist/esm/common/url/parse-url.js +1 -1
  81. package/dist/esm/common/url/protocol.js +1 -1
  82. package/dist/esm/common/util/feature-flags.js +23 -12
  83. package/dist/esm/common/util/obfuscate.js +2 -2
  84. package/dist/esm/common/util/submit-data.js +58 -76
  85. package/dist/esm/common/window/nreum.js +1 -1
  86. package/dist/esm/common/wrap/wrap-events.js +1 -1
  87. package/dist/esm/common/wrap/wrap-fetch.js +1 -1
  88. package/dist/esm/common/wrap/wrap-history.js +1 -1
  89. package/dist/esm/common/wrap/wrap-jsonp.js +1 -1
  90. package/dist/esm/common/wrap/wrap-mutation.js +1 -1
  91. package/dist/esm/common/wrap/wrap-promise.js +1 -1
  92. package/dist/esm/common/wrap/wrap-raf.js +2 -2
  93. package/dist/esm/common/wrap/wrap-timer.js +2 -2
  94. package/dist/esm/common/wrap/wrap-xhr.js +1 -1
  95. package/dist/esm/features/ajax/aggregate/index.js +1 -1
  96. package/dist/esm/features/ajax/instrument/distributed-tracing.js +1 -1
  97. package/dist/esm/features/ajax/instrument/index.js +1 -2
  98. package/dist/esm/features/jserrors/aggregate/index.js +10 -3
  99. package/dist/esm/features/jserrors/instrument/index.js +3 -16
  100. package/dist/esm/features/metrics/aggregate/framework-detection.js +1 -1
  101. package/dist/esm/features/metrics/aggregate/index.js +1 -1
  102. package/dist/esm/features/page_action/aggregate/index.js +1 -1
  103. package/dist/esm/features/page_view_event/aggregate/index.js +1 -2
  104. package/dist/esm/features/page_view_event/instrument/index.js +1 -1
  105. package/dist/esm/features/page_view_timing/aggregate/index.js +2 -4
  106. package/dist/esm/features/page_view_timing/instrument/index.js +1 -1
  107. package/dist/esm/features/session_replay/aggregate/index.js +92 -78
  108. package/dist/esm/features/session_replay/replay-mode.js +23 -0
  109. package/dist/esm/features/session_trace/aggregate/index.js +223 -100
  110. package/dist/esm/features/session_trace/constants.js +0 -1
  111. package/dist/esm/features/session_trace/instrument/index.js +2 -18
  112. package/dist/esm/features/spa/aggregate/index.js +1 -1
  113. package/dist/esm/features/spa/constants.js +0 -1
  114. package/dist/esm/features/spa/instrument/index.js +1 -1
  115. package/dist/esm/features/utils/agent-session.js +21 -37
  116. package/dist/esm/features/utils/aggregate-base.js +7 -12
  117. package/dist/esm/features/utils/handler-cache.js +28 -23
  118. package/dist/esm/features/utils/instrument-base.js +57 -39
  119. package/dist/esm/index.js +1 -4
  120. package/dist/esm/loaders/agent.js +7 -1
  121. package/dist/esm/loaders/api/api.js +2 -2
  122. package/dist/esm/loaders/api/apiAsync.js +3 -3
  123. package/dist/esm/loaders/configure/configure.js +1 -1
  124. package/dist/esm/loaders/features/featureDependencies.js +2 -0
  125. package/dist/esm/loaders/micro-agent.js +29 -38
  126. package/dist/types/common/config/state/init.d.ts.map +1 -1
  127. package/dist/types/common/constants/runtime.d.ts +29 -0
  128. package/dist/types/common/constants/runtime.d.ts.map +1 -0
  129. package/dist/types/common/constants/shared-channel.d.ts +5 -0
  130. package/dist/types/common/constants/shared-channel.d.ts.map +1 -0
  131. package/dist/types/common/harvest/harvest-scheduler.d.ts +5 -1
  132. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  133. package/dist/types/common/harvest/harvest.d.ts +49 -38
  134. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  135. package/dist/types/common/harvest/types.d.ts +100 -0
  136. package/dist/types/common/harvest/types.d.ts.map +1 -0
  137. package/dist/types/common/session/session-entity.d.ts +9 -5
  138. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  139. package/dist/types/common/unload/eol.d.ts.map +1 -1
  140. package/dist/types/common/util/feature-flags.d.ts +1 -0
  141. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  142. package/dist/types/common/util/submit-data.d.ts +62 -64
  143. package/dist/types/common/util/submit-data.d.ts.map +1 -1
  144. package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
  145. package/dist/types/features/jserrors/aggregate/index.d.ts +2 -1
  146. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  147. package/dist/types/features/jserrors/instrument/index.d.ts +1 -1
  148. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  149. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  150. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  151. package/dist/types/features/session_replay/aggregate/index.d.ts +14 -5
  152. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  153. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
  154. package/dist/types/features/session_replay/replay-mode.d.ts +9 -0
  155. package/dist/types/features/session_replay/replay-mode.d.ts.map +1 -0
  156. package/dist/types/features/session_trace/aggregate/index.d.ts +21 -3
  157. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  158. package/dist/types/features/session_trace/constants.d.ts +0 -1
  159. package/dist/types/features/session_trace/constants.d.ts.map +1 -1
  160. package/dist/types/features/session_trace/instrument/index.d.ts +0 -2
  161. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  162. package/dist/types/features/spa/constants.d.ts.map +1 -1
  163. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  164. package/dist/types/features/utils/aggregate-base.d.ts +6 -1
  165. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  166. package/dist/types/features/utils/handler-cache.d.ts +12 -11
  167. package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
  168. package/dist/types/features/utils/instrument-base.d.ts +17 -1
  169. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  170. package/dist/types/index.d.ts +1 -0
  171. package/dist/types/loaders/agent.d.ts +4 -4
  172. package/dist/types/loaders/agent.d.ts.map +1 -1
  173. package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
  174. package/dist/types/loaders/micro-agent.d.ts +3 -4
  175. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  176. package/package.json +14 -7
  177. package/src/common/config/__mocks__/config.js +11 -0
  178. package/src/common/config/state/init.js +1 -0
  179. package/src/common/config/state/runtime.js +1 -1
  180. package/src/common/constants/__mocks__/env.js +3 -0
  181. package/src/common/constants/__mocks__/runtime.js +8 -0
  182. package/src/common/constants/env.cdn.test.js +7 -0
  183. package/src/common/constants/env.npm.test.js +7 -0
  184. package/src/common/constants/env.test.js +7 -0
  185. package/src/common/constants/runtime.js +71 -0
  186. package/src/common/constants/runtime.test.js +168 -0
  187. package/src/common/constants/shared-channel.js +13 -0
  188. package/src/common/context/__mocks__/shared-context.js +8 -0
  189. package/src/common/event-listener/__mocks__/event-listener-opts.js +7 -0
  190. package/src/common/event-listener/event-listener-opts.js +1 -1
  191. package/src/common/harvest/__mocks__/harvest.js +13 -0
  192. package/src/common/harvest/harvest-scheduler.js +31 -19
  193. package/src/common/harvest/harvest-scheduler.test.js +491 -20
  194. package/src/common/harvest/harvest.js +147 -130
  195. package/src/common/harvest/harvest.test.js +788 -139
  196. package/src/common/harvest/types.js +47 -0
  197. package/src/common/ids/id.js +1 -1
  198. package/src/common/ids/unique-id.js +1 -1
  199. package/src/common/session/__mocks__/session-entity.js +25 -0
  200. package/src/common/session/{session-entity.test.js → session-entity.component-test.js} +71 -48
  201. package/src/common/session/session-entity.js +16 -13
  202. package/src/common/timer/interaction-timer.js +2 -2
  203. package/src/common/timing/__mocks__/now.js +1 -0
  204. package/src/common/unload/__mocks__/eol.js +1 -0
  205. package/src/common/unload/eol.js +1 -2
  206. package/src/common/url/__mocks__/clean-url.js +1 -0
  207. package/src/common/url/__mocks__/encode.js +7 -0
  208. package/src/common/url/__mocks__/location.js +1 -0
  209. package/src/common/url/canonicalize-url.js +1 -1
  210. package/src/common/url/canonicalize-url.test.js +32 -21
  211. package/src/common/url/parse-url.js +1 -1
  212. package/src/common/url/parse-url.test.js +3 -3
  213. package/src/common/url/protocol.js +1 -1
  214. package/src/common/util/__mocks__/obfuscate.js +10 -0
  215. package/src/common/util/__mocks__/stringify.js +1 -0
  216. package/src/common/util/__mocks__/submit-data.js +6 -0
  217. package/src/common/util/__mocks__/traverse.js +1 -0
  218. package/src/common/util/data-size.test.js +27 -20
  219. package/src/common/util/feature-flags.js +24 -12
  220. package/src/common/util/feature-flags.test.js +98 -0
  221. package/src/common/util/obfuscate.component-test.js +173 -0
  222. package/src/common/util/obfuscate.js +2 -2
  223. package/src/common/util/submit-data.js +42 -56
  224. package/src/common/util/submit-data.test.js +158 -137
  225. package/src/common/window/nreum.js +1 -1
  226. package/src/common/wrap/wrap-events.js +1 -1
  227. package/src/common/wrap/wrap-fetch.js +1 -1
  228. package/src/common/wrap/wrap-history.js +1 -1
  229. package/src/common/wrap/wrap-jsonp.js +1 -1
  230. package/src/common/wrap/wrap-mutation.js +1 -1
  231. package/src/common/wrap/wrap-promise.js +1 -1
  232. package/src/common/wrap/wrap-promise.test.js +2 -2
  233. package/src/common/wrap/wrap-raf.js +2 -2
  234. package/src/common/wrap/wrap-timer.js +2 -2
  235. package/src/common/wrap/wrap-xhr.js +1 -1
  236. package/src/features/ajax/aggregate/index.js +1 -1
  237. package/src/features/ajax/instrument/distributed-tracing.js +1 -1
  238. package/src/features/ajax/instrument/index.js +1 -2
  239. package/src/features/jserrors/aggregate/compute-stack-trace.test.js +1 -1
  240. package/src/features/jserrors/aggregate/index.js +12 -3
  241. package/src/features/jserrors/instrument/index.js +3 -16
  242. package/src/features/metrics/aggregate/framework-detection.js +1 -1
  243. package/src/features/metrics/aggregate/framework-detection.test.js +2 -2
  244. package/src/features/metrics/aggregate/index.js +1 -1
  245. package/src/features/page_action/aggregate/index.js +1 -1
  246. package/src/features/page_view_event/aggregate/index.js +1 -2
  247. package/src/features/page_view_event/instrument/index.js +1 -1
  248. package/src/features/page_view_timing/aggregate/index.js +2 -4
  249. package/src/features/page_view_timing/instrument/index.js +1 -1
  250. package/src/features/session_replay/aggregate/index.component-test.js +368 -0
  251. package/src/features/session_replay/aggregate/index.js +96 -71
  252. package/src/features/session_replay/instrument/index.js +0 -1
  253. package/src/features/session_replay/replay-mode.js +23 -0
  254. package/src/features/session_trace/aggregate/index.js +198 -79
  255. package/src/features/session_trace/constants.js +0 -1
  256. package/src/features/session_trace/instrument/index.js +3 -20
  257. package/src/features/spa/aggregate/index.js +1 -1
  258. package/src/features/spa/constants.js +0 -1
  259. package/src/features/spa/instrument/index.js +1 -1
  260. package/src/features/utils/agent-session.js +22 -34
  261. package/src/features/utils/agent-session.test.js +194 -0
  262. package/src/features/utils/aggregate-base.js +12 -9
  263. package/src/features/utils/aggregate-base.test.js +122 -0
  264. package/src/features/utils/feature-base.test.js +45 -0
  265. package/src/features/utils/handler-cache.js +29 -23
  266. package/src/features/utils/handler-cache.test.js +72 -0
  267. package/src/features/utils/instrument-base.js +45 -29
  268. package/src/features/utils/instrument-base.test.js +209 -0
  269. package/src/features/utils/lazy-feature-loader.test.js +37 -0
  270. package/src/index.js +1 -3
  271. package/src/loaders/agent.js +8 -1
  272. package/src/loaders/api/api.js +2 -2
  273. package/src/loaders/api/apiAsync.js +3 -3
  274. package/src/loaders/configure/configure.js +1 -1
  275. package/src/loaders/features/featureDependencies.js +2 -0
  276. package/src/loaders/micro-agent.js +26 -30
  277. package/dist/cjs/common/browser-version/firefox-version.js +0 -17
  278. package/dist/cjs/common/browser-version/ios-version.js +0 -19
  279. package/dist/cjs/common/event-emitter/contextual-ee.test.js +0 -282
  280. package/dist/cjs/common/event-emitter/handle.test.js +0 -58
  281. package/dist/cjs/common/event-emitter/register-handler.test.js +0 -55
  282. package/dist/cjs/common/harvest/harvest-scheduler.test.js +0 -39
  283. package/dist/cjs/common/harvest/harvest.test.js +0 -224
  284. package/dist/cjs/common/ids/id.test.js +0 -85
  285. package/dist/cjs/common/ids/unique-id.test.js +0 -49
  286. package/dist/cjs/common/session/session-entity.test.js +0 -460
  287. package/dist/cjs/common/storage/local-memory.js +0 -35
  288. package/dist/cjs/common/storage/local-memory.test.js +0 -20
  289. package/dist/cjs/common/storage/local-storage.test.js +0 -14
  290. package/dist/cjs/common/timer/interaction-timer.test.js +0 -216
  291. package/dist/cjs/common/timer/timer.test.js +0 -105
  292. package/dist/cjs/common/timing/nav-timing.test.js +0 -192
  293. package/dist/cjs/common/url/canonicalize-url.test.js +0 -42
  294. package/dist/cjs/common/url/clean-url.test.js +0 -9
  295. package/dist/cjs/common/url/encode.test.js +0 -74
  296. package/dist/cjs/common/url/location.test.js +0 -13
  297. package/dist/cjs/common/url/parse-url.test.js +0 -111
  298. package/dist/cjs/common/url/protocol.test.js +0 -15
  299. package/dist/cjs/common/util/console.test.js +0 -30
  300. package/dist/cjs/common/util/data-size.test.js +0 -47
  301. package/dist/cjs/common/util/get-or-set.test.js +0 -47
  302. package/dist/cjs/common/util/global-scope.js +0 -58
  303. package/dist/cjs/common/util/invoke.test.js +0 -49
  304. package/dist/cjs/common/util/map-own.test.js +0 -49
  305. package/dist/cjs/common/util/stringify.test.js +0 -48
  306. package/dist/cjs/common/util/submit-data.test.js +0 -221
  307. package/dist/cjs/common/util/traverse.test.js +0 -44
  308. package/dist/cjs/common/wrap/wrap-promise.test.js +0 -119
  309. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.test.js +0 -31
  310. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +0 -383
  311. package/dist/cjs/features/jserrors/aggregate/format-stack-trace.test.js +0 -40
  312. package/dist/cjs/features/jserrors/aggregate/string-hash-code.test.js +0 -27
  313. package/dist/cjs/features/metrics/aggregate/framework-detection.test.js +0 -137
  314. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.test.js +0 -17
  315. package/dist/cjs/features/metrics/aggregate/polyfill-detection.test.js +0 -165
  316. package/dist/cjs/features/spa/aggregate/interaction-node.test.js +0 -16
  317. package/dist/esm/common/browser-version/firefox-version.js +0 -10
  318. package/dist/esm/common/browser-version/ios-version.js +0 -11
  319. package/dist/esm/common/event-emitter/contextual-ee.test.js +0 -278
  320. package/dist/esm/common/event-emitter/handle.test.js +0 -54
  321. package/dist/esm/common/event-emitter/register-handler.test.js +0 -51
  322. package/dist/esm/common/harvest/harvest-scheduler.test.js +0 -37
  323. package/dist/esm/common/harvest/harvest.test.js +0 -222
  324. package/dist/esm/common/ids/id.test.js +0 -81
  325. package/dist/esm/common/ids/unique-id.test.js +0 -44
  326. package/dist/esm/common/session/session-entity.test.js +0 -458
  327. package/dist/esm/common/storage/local-memory.js +0 -28
  328. package/dist/esm/common/storage/local-memory.test.js +0 -18
  329. package/dist/esm/common/storage/local-storage.test.js +0 -12
  330. package/dist/esm/common/timer/interaction-timer.test.js +0 -214
  331. package/dist/esm/common/timer/timer.test.js +0 -103
  332. package/dist/esm/common/timing/nav-timing.test.js +0 -190
  333. package/dist/esm/common/url/canonicalize-url.test.js +0 -38
  334. package/dist/esm/common/url/clean-url.test.js +0 -7
  335. package/dist/esm/common/url/encode.test.js +0 -70
  336. package/dist/esm/common/url/location.test.js +0 -11
  337. package/dist/esm/common/url/parse-url.test.js +0 -107
  338. package/dist/esm/common/url/protocol.test.js +0 -13
  339. package/dist/esm/common/util/console.test.js +0 -28
  340. package/dist/esm/common/util/data-size.test.js +0 -45
  341. package/dist/esm/common/util/get-or-set.test.js +0 -45
  342. package/dist/esm/common/util/global-scope.js +0 -45
  343. package/dist/esm/common/util/invoke.test.js +0 -47
  344. package/dist/esm/common/util/map-own.test.js +0 -47
  345. package/dist/esm/common/util/stringify.test.js +0 -46
  346. package/dist/esm/common/util/submit-data.test.js +0 -219
  347. package/dist/esm/common/util/traverse.test.js +0 -42
  348. package/dist/esm/common/wrap/wrap-promise.test.js +0 -115
  349. package/dist/esm/features/jserrors/aggregate/canonical-function-name.test.js +0 -29
  350. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +0 -379
  351. package/dist/esm/features/jserrors/aggregate/format-stack-trace.test.js +0 -38
  352. package/dist/esm/features/jserrors/aggregate/string-hash-code.test.js +0 -25
  353. package/dist/esm/features/metrics/aggregate/framework-detection.test.js +0 -133
  354. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.test.js +0 -15
  355. package/dist/esm/features/metrics/aggregate/polyfill-detection.test.js +0 -163
  356. package/dist/esm/features/spa/aggregate/interaction-node.test.js +0 -14
  357. package/dist/types/common/browser-version/firefox-version.d.ts +0 -2
  358. package/dist/types/common/browser-version/firefox-version.d.ts.map +0 -1
  359. package/dist/types/common/browser-version/ios-version.d.ts +0 -3
  360. package/dist/types/common/browser-version/ios-version.d.ts.map +0 -1
  361. package/dist/types/common/storage/local-memory.d.ts +0 -8
  362. package/dist/types/common/storage/local-memory.d.ts.map +0 -1
  363. package/dist/types/common/util/global-scope.d.ts +0 -14
  364. package/dist/types/common/util/global-scope.d.ts.map +0 -1
  365. package/src/common/browser-version/firefox-version.js +0 -10
  366. package/src/common/browser-version/ios-version.js +0 -11
  367. package/src/common/storage/local-memory.js +0 -30
  368. package/src/common/storage/local-memory.test.js +0 -19
  369. package/src/common/util/global-scope.js +0 -49
  370. /package/src/common/timer/{interaction-timer.test.js → interaction-timer.component-test.js} +0 -0
  371. /package/src/common/url/{encode.test.js → encode.component-test.js} +0 -0
  372. /package/src/common/url/{protocol.test.js → protocol.component-test.js} +0 -0
@@ -13,10 +13,19 @@ export class InstrumentBase extends FeatureBase {
13
13
  * immediately. Primarily useful for fine-grained control in tests.
14
14
  */
15
15
  constructor(agentIdentifier: string, aggregator: Aggregator, featureName: string, auto?: boolean | undefined);
16
- hasAggregator: boolean;
17
16
  auto: boolean;
18
17
  /** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
19
18
  abortHandler: Function | undefined;
19
+ /**
20
+ * @type {Class} Holds the reference to the feature's aggregate module counterpart, if and after it has been initialized. This may not be assigned until after page loads!
21
+ * The only purpose of this for now is to expose it to the NREUM interface, as the feature's instrument instance is already exposed.
22
+ */
23
+ featAggregate: Class;
24
+ /**
25
+ * @type {Promise} Assigned immediately after @see importAggregator runs. Serves as a signal for when the inner async fn finishes execution. Useful for features to await
26
+ * one another if there are inter-features dependencies.
27
+ */
28
+ onAggregateImported: Promise<any>;
20
29
  /**
21
30
  * Lazy-load the latter part of the feature: its aggregator. This method is called by the first part of the feature
22
31
  * (the instrumentation) when instrumentation is complete.
@@ -24,6 +33,13 @@ export class InstrumentBase extends FeatureBase {
24
33
  * @returns void
25
34
  */
26
35
  importAggregator(argsObjFromInstrument?: Object | undefined): void;
36
+ /**
37
+ * Make a determination if an aggregate class should even be imported
38
+ * @param {string} featureName
39
+ * @param {SessionEntity} session
40
+ * @returns
41
+ */
42
+ shouldImportAgg(featureName: string, session: SessionEntity): boolean;
27
43
  }
28
44
  import { FeatureBase } from './feature-base';
29
45
  //# sourceMappingURL=instrument-base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrument-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/instrument-base.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH;IACE;;;;;;;;OAQG;IACH,6BAPW,MAAM,uCAEN,MAAM,8BAchB;IAPC,uBAA0B;IAC1B,cAAgB;IAEhB,8IAA8I;IAC9I,cADW,WAAW,SAAS,CACd;IAKnB;;;;;OAKG;IACH,mEAyCC;CACF;4BAhF2B,gBAAgB"}
1
+ {"version":3,"file":"instrument-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/instrument-base.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH;IACE;;;;;;;;OAQG;IACH,6BAPW,MAAM,uCAEN,MAAM,8BAuBhB;IAhBC,cAAgB;IAEhB,8IAA8I;IAC9I,cADW,WAAW,SAAS,CACd;IACjB;;;MAGE;IACF,qBAAkB;IAClB;;;MAGE;IACF,kCAAwB;IAK1B;;;;;OAKG;IACH,mEA4CC;IAED;;;;;KAKC;IACD,6BAJS,MAAM,mCAed;CACF;4BA/G2B,gBAAgB"}
@@ -1,6 +1,7 @@
1
1
  export { Agent } from "./loaders/agent";
2
2
  export { BrowserAgent } from "./loaders/browser-agent";
3
3
  export { WorkerAgent } from "./loaders/worker-agent";
4
+ export { MicroAgent } from "./loaders/micro-agent";
4
5
  export { Ajax } from "./features/ajax";
5
6
  export { JSErrors } from "./features/jserrors";
6
7
  export { Metrics } from "./features/metrics";
@@ -4,10 +4,10 @@
4
4
  */
5
5
  export class Agent {
6
6
  constructor(options: any, agentIdentifier?: string);
7
- agentIdentifier: string;
8
- sharedAggregator: Aggregator;
9
- features: {};
10
- desiredFeatures: Set<any>;
7
+ agentIdentifier: string | undefined;
8
+ sharedAggregator: Aggregator | undefined;
9
+ features: {} | undefined;
10
+ desiredFeatures: Set<any> | undefined;
11
11
  get config(): {
12
12
  info: any;
13
13
  init: any;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH;IACE,oDAeC;IAdC,wBAAsC;IACtC,6BAAiF;IACjF,aAAkB;IAElB,0BAAsD;IAYxD;;;;;MAOC;IAED,2BAgCC;CACF;2BAvE0B,gCAAgC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAgBA;;;GAGG;AACH;IACE,oDAqBC;IAbC,oCAAsC;IACtC,yCAAiF;IACjF,yBAAkB;IAElB,sCAAsD;IAWxD;;;;;MAOC;IAED,2BAgCC;CACF;2BA9E0B,gCAAgC"}
@@ -1 +1 @@
1
- {"version":3,"file":"featureDependencies.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/featureDependencies.js"],"names":[],"mappings":"AAEA,kEAWC"}
1
+ {"version":3,"file":"featureDependencies.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/featureDependencies.js"],"names":[],"mappings":"AAEA,kEAaC"}
@@ -1,8 +1,7 @@
1
1
  /**
2
- * A minimal agent class designed to be loaded multiple times on the same page, each instance narrowly scoped to the
3
- * concerns of a particular component, as with the micro-frontend architectural pattern. This class does not
4
- * automatically instrument. Instead, each MicroAgent instance may be configured to lazy-load specific
5
- * instrumentations at runtime, and to report desired data, events, and errors programatically.
2
+ * A minimal agent class designed to only respond to manual user input. As such, this class does not
3
+ * automatically instrument. Instead, each MicroAgent instance will lazy load the required features and can support loading multiple instances on one page.
4
+ * Out of the box, it can manually handle and report Page View, Page Action, and Error events.
6
5
  */
7
6
  export class MicroAgent {
8
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAoBA;;;;;GAKG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,cAUhB;IAPC,wBAAsC;IACtC,6BAAiF;IACjF,aAAkB;IAOpB;;;;;MAOC;IAED,4BAgCC;CACF;2BA/E0B,gCAAgC"}
1
+ {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,cAUhB;IAPC,wBAAsC;IACtC,6BAAiF;IACjF,aAAkB;IAOpB;;;;;MAOC;IAED,4BA8BC;CACF;2BA1E0B,gCAAgC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.234.0",
3
+ "version": "1.236.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "Tests for the New Relic JavaScript agent",
@@ -37,6 +37,11 @@
37
37
  "require": "./dist/cjs/loaders/browser-agent.js",
38
38
  "default": "./dist/esm/loaders/browser-agent.js"
39
39
  },
40
+ "./loaders/micro-agent": {
41
+ "types": "./dist/types/loaders/micro-agent.d.ts",
42
+ "require": "./dist/cjs/loaders/micro-agent.js",
43
+ "default": "./dist/esm/loaders/micro-agent.js"
44
+ },
40
45
  "./loaders/worker-agent": {
41
46
  "types": "./dist/types/loaders/worker-agent.d.ts",
42
47
  "require": "./dist/cjs/loaders/worker-agent.js",
@@ -89,9 +94,8 @@
89
94
  "scripts": {
90
95
  "wdio": "node --max-old-space-size=8192 tools/wdio/bin/cli.js",
91
96
  "start": "npm-run-all --parallel cdn:watch test-server",
92
- "test": "jest",
93
- "test:watch": "jest --watch",
94
- "test:coverage": "jest --coverage",
97
+ "test:unit": "jest",
98
+ "test:component": "jest --config jest.component-config.js",
95
99
  "build:all": "npm run cdn:build:local && npm run build:npm && npm run tools:test-builds",
96
100
  "build:npm": "npm run npm:build:esm && npm run npm:build:cjs && npm run npm:build:types && npm run npm:pack",
97
101
  "build:browser-tests": "npm --prefix ./tools/test-builds/browser-tests run build",
@@ -196,10 +200,13 @@
196
200
  "gzip-size": "^7.0.0",
197
201
  "html-webpack-plugin": "^5.5.0",
198
202
  "husky": "^8.0.0",
199
- "jest": "^28.1.1",
200
- "jest-environment-jsdom": "28.1.1",
203
+ "istanbul-lib-coverage": "^3.2.0",
204
+ "istanbul-lib-instrument": "^5.2.1",
205
+ "istanbul-lib-report": "^3.0.0",
206
+ "istanbul-reports": "^3.1.5",
207
+ "jest": "^29.5.0",
208
+ "jest-environment-jsdom": "29.5.0",
201
209
  "jest-extended": "^3.2.4",
202
- "jquery": "1.11.3",
203
210
  "jung": "^2.1.0",
204
211
  "just-debounce": "^1.0.0",
205
212
  "mime-types": "^2.1.11",
@@ -0,0 +1,11 @@
1
+ export const isConfigured = jest.fn()
2
+ export const getInfo = jest.fn()
3
+ export const setInfo = jest.fn()
4
+ export const getConfiguration = jest.fn()
5
+ export const getConfigurationValue = jest.fn()
6
+ export const setConfiguration = jest.fn()
7
+ export const getLoaderConfig = jest.fn()
8
+ export const setLoaderConfig = jest.fn()
9
+ export const originals = {}
10
+ export const getRuntime = jest.fn()
11
+ export const setRuntime = jest.fn()
@@ -31,6 +31,7 @@ const model = () => {
31
31
  page_view_event: { enabled: true },
32
32
  page_view_timing: { enabled: true, harvestTimeSeconds: 30, long_task: false },
33
33
  session_trace: { enabled: true, harvestTimeSeconds: 10 },
34
+ harvest: { tooManyRequestsDelay: 60 },
34
35
  session_replay: {
35
36
  // feature settings
36
37
  enabled: false,
@@ -1,6 +1,6 @@
1
1
  import { getModeledObject } from './configurable'
2
2
  import { gosNREUMInitializedAgents } from '../../window/nreum'
3
- import { globalScope } from '../../util/global-scope'
3
+ import { globalScope } from '../../constants/runtime'
4
4
  import { BUILD_ENV, DIST_METHOD, VERSION } from '../../constants/env'
5
5
 
6
6
  const model = {
@@ -0,0 +1,3 @@
1
+ export const VERSION = '0.0.0'
2
+ export const BUILD_ENV = 'TEST'
3
+ export const DIST_METHOD = 'TEST'
@@ -0,0 +1,8 @@
1
+ export const isBrowserScope = true
2
+ export const isWorkerScope = false
3
+ export const globalScope = window
4
+ export const initialLocation = '' + globalScope?.location
5
+ export const isiOS = false
6
+ export const iOS_below16 = false
7
+ export const ffVersion = 0
8
+ export const supportsSendBeacon = true
@@ -0,0 +1,7 @@
1
+ import * as env from './env.cdn'
2
+
3
+ test('should default environment variables to CDN values', async () => {
4
+ expect(env.VERSION).toMatch(/\d{1,3}\.\d{1,3}\.\d{1,3}/)
5
+ expect(env.BUILD_ENV).toEqual('CDN')
6
+ expect(env.DIST_METHOD).toEqual('CDN')
7
+ })
@@ -0,0 +1,7 @@
1
+ import * as env from './env.npm'
2
+
3
+ test('should default environment variables to NPM values', () => {
4
+ expect(env.VERSION).toMatch(/\d{1,3}\.\d{1,3}\.\d{1,3}/)
5
+ expect(env.BUILD_ENV).toEqual('NPM')
6
+ expect(env.DIST_METHOD).toEqual('NPM')
7
+ })
@@ -0,0 +1,7 @@
1
+ import * as env from './env'
2
+
3
+ test('should default environment variables to NPM values', () => {
4
+ expect(env.VERSION).toMatch(/\d{1,3}\.\d{1,3}\.\d{1,3}/)
5
+ expect(env.BUILD_ENV).toEqual('NPM')
6
+ expect(env.DIST_METHOD).toEqual('NPM')
7
+ })
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @file Contains constants about the environment the agent is running
3
+ * within. These values are derived at the time the agent is first loaded.
4
+ * @copyright 2023 New Relic Corporation. All rights reserved.
5
+ * @license Apache-2.0
6
+ */
7
+
8
+ /**
9
+ * Indicates if the agent is running within a normal browser window context.
10
+ */
11
+ export const isBrowserScope =
12
+ typeof window !== 'undefined' &&
13
+ !!window.document
14
+
15
+ /**
16
+ * Indicates if the agent is running within a worker context.
17
+ */
18
+ export const isWorkerScope =
19
+ typeof WorkerGlobalScope !== 'undefined' &&
20
+ (
21
+ (
22
+ typeof self !== 'undefined' &&
23
+ self instanceof WorkerGlobalScope &&
24
+ self.navigator instanceof WorkerNavigator
25
+ ) ||
26
+ (
27
+ (
28
+ typeof globalThis !== 'undefined' &&
29
+ globalThis instanceof WorkerGlobalScope &&
30
+ globalThis.navigator instanceof WorkerNavigator
31
+ )
32
+ )
33
+ )
34
+
35
+ export const globalScope = isBrowserScope
36
+ ? window
37
+ : typeof WorkerGlobalScope !== 'undefined' && ((
38
+ typeof self !== 'undefined' &&
39
+ self instanceof WorkerGlobalScope &&
40
+ self
41
+ ) || (
42
+ typeof globalThis !== 'undefined' &&
43
+ globalThis instanceof WorkerGlobalScope &&
44
+ globalThis
45
+ ))
46
+
47
+ export const initialLocation = '' + globalScope?.location
48
+
49
+ export const isiOS = /iPad|iPhone|iPod/.test(navigator.userAgent)
50
+
51
+ /**
52
+ * Shared Web Workers introduced in iOS 16.0+ and n/a in 15.6-
53
+ *
54
+ * It was discovered in Safari 14 (https://bugs.webkit.org/show_bug.cgi?id=225305) that the buffered flag in PerformanceObserver
55
+ * did not work. This affects our onFCP metric in particular since web-vitals uses that flag to retrieve paint timing entries.
56
+ * This was fixed in v16+.
57
+ */
58
+ export const iOS_below16 = (isiOS && typeof SharedWorker === 'undefined')
59
+
60
+ export const ffVersion = (() => {
61
+ const match = navigator.userAgent.match(/Firefox[/\s](\d+\.\d+)/)
62
+ if (Array.isArray(match) && match.length >= 2) {
63
+ return +match[1]
64
+ }
65
+
66
+ return 0
67
+ })()
68
+
69
+ export const isIE = Boolean(isBrowserScope && window.document.documentMode) // deprecated property that only works in IE
70
+
71
+ export const supportsSendBeacon = !!navigator.sendBeacon
@@ -0,0 +1,168 @@
1
+ /**
2
+ * The runtime module exports variables whose values are set at the time of import and
3
+ * can depend on the environment the agent is running within. To make testing this module
4
+ * easier, use async import to import the module and only use the node jest environment so
5
+ * we can more easily define environment variables.
6
+ * @jest-environment node
7
+ */
8
+
9
+ import { faker } from '@faker-js/faker'
10
+
11
+ beforeEach(() => {
12
+ // We assume every runtime has a global navigator variable
13
+ global.navigator = {
14
+ userAgent: faker.lorem.sentence()
15
+ }
16
+ })
17
+
18
+ afterEach(() => {
19
+ delete global.navigator
20
+ jest.resetModules()
21
+ })
22
+
23
+ test('should indicate agent is running in a browser scope', async () => {
24
+ const mockedWindow = global.window = {
25
+ [faker.datatype.uuid()]: faker.lorem.sentence,
26
+ document: {
27
+ [faker.datatype.uuid()]: faker.lorem.sentence
28
+ }
29
+ }
30
+
31
+ const runtime = await import('./runtime')
32
+
33
+ delete global.window
34
+
35
+ expect(runtime.isBrowserScope).toEqual(true)
36
+ expect(runtime.isWorkerScope).toEqual(false)
37
+ expect(runtime.globalScope).toEqual(mockedWindow)
38
+ })
39
+
40
+ test('should indicate agent is running in a worker scope using global self variable', async () => {
41
+ global.WorkerGlobalScope = class WorkerGlobalScope {}
42
+ global.WorkerNavigator = class WorkerNavigator {}
43
+ const mockedGlobalSelf = global.self = new global.WorkerGlobalScope()
44
+ mockedGlobalSelf.navigator = new global.WorkerNavigator()
45
+
46
+ const runtime = await import('./runtime')
47
+
48
+ delete global.WorkerGlobalScope
49
+ delete global.WorkerNavigator
50
+ delete global.self
51
+
52
+ expect(runtime.isBrowserScope).toEqual(false)
53
+ expect(runtime.isWorkerScope).toEqual(true)
54
+ expect(runtime.globalScope).toEqual(mockedGlobalSelf)
55
+ })
56
+
57
+ test('should indicate agent is running in a worker scope using global self variable', async () => {
58
+ global.WorkerGlobalScope = class WorkerGlobalScope {}
59
+ global.WorkerNavigator = class WorkerNavigator {}
60
+ const cachedGlobalThis = global.globalThis
61
+ const mockedGlobalThis = global.globalThis = new WorkerGlobalScope()
62
+ Object.defineProperties(global.globalThis, Object.getOwnPropertyDescriptors(cachedGlobalThis))
63
+ global.globalThis.navigator = new WorkerNavigator()
64
+
65
+ const runtime = await import('./runtime')
66
+
67
+ delete global.WorkerGlobalScope
68
+ delete global.WorkerNavigator
69
+ global.globalThis = cachedGlobalThis
70
+
71
+ expect(runtime.isBrowserScope).toEqual(false)
72
+ expect(runtime.isWorkerScope).toEqual(true)
73
+ expect(runtime.globalScope).toEqual(mockedGlobalThis)
74
+ })
75
+
76
+ test('should store the initial page location', async () => {
77
+ const initialLocation = faker.internet.url()
78
+ const mockedWindow = global.window = {
79
+ [faker.datatype.uuid()]: faker.lorem.sentence,
80
+ document: {
81
+ [faker.datatype.uuid()]: faker.lorem.sentence
82
+ },
83
+ location: {
84
+ href: initialLocation,
85
+ toString () {
86
+ return this.href
87
+ }
88
+ }
89
+ }
90
+
91
+ const runtime = await import('./runtime')
92
+ mockedWindow.location.href = faker.internet.url()
93
+
94
+ delete global.window
95
+
96
+ expect(runtime.initialLocation).toEqual(initialLocation)
97
+ expect(runtime.initialLocation).not.toEqual(mockedWindow.location.href)
98
+ })
99
+
100
+ test.each([
101
+ { userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: true },
102
+ { userAgent: 'Mozilla/5.0 (iPad; CPU OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: true },
103
+ { userAgent: 'Mozilla/5.0 (iPod touch; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: true },
104
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15', expected: false },
105
+ { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0', expected: false },
106
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.4; rv:109.0) Gecko/20100101 Firefox/114.0', expected: false }
107
+ ])('should set isiOS to $expected for $userAgent', async ({ userAgent, expected }) => {
108
+ global.navigator.userAgent = userAgent
109
+
110
+ const runtime = await import('./runtime')
111
+
112
+ expect(runtime.isiOS).toEqual(expected)
113
+ })
114
+
115
+ test.each([
116
+ { userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: false },
117
+ { userAgent: 'Mozilla/5.0 (iPad; CPU OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: false },
118
+ { userAgent: 'Mozilla/5.0 (iPod touch; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: false },
119
+ { userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1', expected: true },
120
+ { userAgent: 'Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1', expected: true },
121
+ { userAgent: 'Mozilla/5.0 (iPod touch; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1', expected: true },
122
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15', expected: false },
123
+ { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0', expected: false },
124
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.4; rv:109.0) Gecko/20100101 Firefox/114.0', expected: false }
125
+ ])('should set iOS_below16 to $expected for $userAgent', async ({ userAgent, expected }) => {
126
+ if (!expected) {
127
+ global.SharedWorker = class SharedWorker {}
128
+ }
129
+ global.navigator.userAgent = userAgent
130
+
131
+ const runtime = await import('./runtime')
132
+
133
+ delete global.SharedWorker
134
+
135
+ expect(runtime.iOS_below16).toEqual(expected)
136
+ })
137
+
138
+ test.each([
139
+ { userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: 0 },
140
+ { userAgent: 'Mozilla/5.0 (iPad; CPU OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: 0 },
141
+ { userAgent: 'Mozilla/5.0 (iPod touch; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1', expected: 0 },
142
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15', expected: 0 },
143
+ { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0', expected: 114 },
144
+ { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13.4; rv:109.0) Gecko/20100101 Firefox/114.0', expected: 114 }
145
+ ])('should set ffVersion to $expected for $userAgent', async ({ userAgent, expected }) => {
146
+ global.navigator.userAgent = userAgent
147
+
148
+ const runtime = await import('./runtime')
149
+
150
+ expect(runtime.ffVersion).toEqual(expected)
151
+ })
152
+
153
+ test('should set supportsSendBeacon to false', async () => {
154
+ // Ensure we don't have a sendBeacon function
155
+ delete global.navigator.sendBeacon
156
+
157
+ const runtime = await import('./runtime')
158
+
159
+ expect(runtime.supportsSendBeacon).toEqual(false)
160
+ })
161
+
162
+ test('should set supportsSendBeacon to true', async () => {
163
+ global.navigator.sendBeacon = jest.fn()
164
+
165
+ const runtime = await import('./runtime')
166
+
167
+ expect(runtime.supportsSendBeacon).toEqual(true)
168
+ })
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @file Keeps an object alive that is passed to all feature aggregate modules.
3
+ * The purpose is to have a way for communication and signals to relay across features at runtime.
4
+ * This object can hold any arbitrary values and should be treated as on-the-fly dynamic.
5
+ */
6
+
7
+ let onReplayReady
8
+ const sessionReplayInitialized = new Promise(resolve => onReplayReady = resolve)
9
+
10
+ export const sharedChannel = Object.freeze({
11
+ onReplayReady,
12
+ sessionReplayInitialized
13
+ })
@@ -0,0 +1,8 @@
1
+ export const SharedContext = jest.fn(function () {
2
+ this.sharedContext = {
3
+ agentIdentifier: 'abcd',
4
+ ee: {
5
+ on: jest.fn()
6
+ }
7
+ }
8
+ })
@@ -0,0 +1,7 @@
1
+ export const eventListenerOpts = jest.fn((useCapture, abortSignal) => ({
2
+ capture: !!useCapture,
3
+ passive: true,
4
+ signal: abortSignal
5
+ }))
6
+ export const windowAddEventListener = jest.fn()
7
+ export const documentAddEventListener = jest.fn()
@@ -1,4 +1,4 @@
1
- import { globalScope } from '../util/global-scope'
1
+ import { globalScope } from '../constants/runtime'
2
2
 
3
3
  /*
4
4
  * See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#safely_detecting_option_support
@@ -0,0 +1,13 @@
1
+ export const Harvest = jest.fn(function () {
2
+ this.sharedContext = {
3
+ agentIdentifier: 'abcd'
4
+ }
5
+ this.sendX = jest.fn()
6
+ this.send = jest.fn()
7
+ this.obfuscateAndSend = jest.fn()
8
+ this._send = jest.fn()
9
+ this.baseQueryString = jest.fn()
10
+ this.createPayload = jest.fn()
11
+ this.cleanPayload = jest.fn()
12
+ this.on = jest.fn()
13
+ })
@@ -3,11 +3,12 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
- import { submitData } from '../util/submit-data'
6
+ import * as submitData from '../util/submit-data'
7
7
  import { SharedContext } from '../context/shared-context'
8
- import { Harvest, getSubmitMethod } from './harvest'
8
+ import { Harvest } from './harvest'
9
9
  import { subscribeToEOL } from '../unload/eol'
10
10
  import { getConfigurationValue } from '../config/config'
11
+ import { SESSION_EVENTS } from '../session/session-entity'
11
12
 
12
13
  /**
13
14
  * Periodically invokes harvest calls and handles retries
@@ -37,10 +38,16 @@ export class HarvestScheduler extends SharedContext {
37
38
  // unload if EOL mechanism fires
38
39
  subscribeToEOL(this.unload.bind(this), getConfigurationValue(this.sharedContext.agentIdentifier, 'allow_bfcache')) // TO DO: remove feature flag after rls stable
39
40
 
40
- // unload if session resets
41
- this.sharedContext?.ee.on('session-reset', this.unload.bind(this))
41
+ /* Flush all buffered data if session resets and give up retries. This should be synchronous to ensure that the correct `session` value is sent.
42
+ Since session-reset generates a new session ID and the ID is grabbed at send-time, any delays or retries would cause the payload to be sent under
43
+ the wrong session ID. */
44
+ this.sharedContext?.ee.on(SESSION_EVENTS.RESET, () => this.runHarvest({ forceNoRetry: true }))
42
45
  }
43
46
 
47
+ /**
48
+ * This function is only meant for the last outgoing harvest cycle of a page. It trickles down to using sendBeacon, which should not be used
49
+ * to send payloads while the page is still active, due to limitations on how much data can be buffered in the API at any one time.
50
+ */
44
51
  unload () {
45
52
  if (this.aborted) return
46
53
  // If opts.onUnload is defined, these are special actions to execute before attempting to send the final payload.
@@ -64,30 +71,39 @@ export class HarvestScheduler extends SharedContext {
64
71
 
65
72
  scheduleHarvest (delay, opts) {
66
73
  if (this.timeoutHandle) return
67
- var timer = this
68
74
 
69
75
  if (delay == null) {
70
76
  delay = this.interval
71
77
  }
72
78
  this.timeoutHandle = setTimeout(() => {
73
- timer.timeoutHandle = null
74
- timer.runHarvest(opts)
79
+ this.timeoutHandle = null
80
+ this.runHarvest(opts)
75
81
  }, delay * 1000)
76
82
  }
77
83
 
78
84
  runHarvest (opts) {
79
85
  if (this.aborted) return
80
- var scheduler = this
86
+
87
+ /**
88
+ * This is executed immediately after harvest sends the data via XHR, or if there's nothing to send. Note that this excludes on unloading / sendBeacon.
89
+ * @param {Object} result
90
+ */
91
+ const cbRanAfterSend = (result) => {
92
+ if (opts?.forceNoRetry) result.retry = false // discard unsent data rather than re-queuing for next harvest attempt
93
+ this.onHarvestFinished(opts, result)
94
+ }
81
95
 
82
96
  let harvests = []
83
97
  let submitMethod
98
+ let payload
84
99
 
85
- if (this.opts.getPayload) { // Ajax & PVT & SR
86
- submitMethod = getSubmitMethod(this.endpoint, opts)
100
+ if (this.opts.getPayload) {
101
+ // Ajax & PVT & SR features provide a callback function to get data for harvesting
102
+ submitMethod = submitData.getSubmitMethod({ isFinalHarvest: opts?.unload })
87
103
  if (!submitMethod) return false
88
104
 
89
- const retry = submitMethod.method === submitData.xhr
90
- var payload = this.opts.getPayload({ retry: retry })
105
+ const retry = !opts?.unload && submitMethod === submitData.xhr
106
+ payload = this.opts.getPayload({ retry: retry })
91
107
 
92
108
  if (!payload) {
93
109
  if (this.started) {
@@ -118,7 +134,7 @@ export class HarvestScheduler extends SharedContext {
118
134
  payload,
119
135
  opts,
120
136
  submitMethod,
121
- cbFinished: onHarvestFinished,
137
+ cbFinished: cbRanAfterSend,
122
138
  customUrl: this.opts.customUrl,
123
139
  raw: this.opts.raw
124
140
  })
@@ -127,12 +143,8 @@ export class HarvestScheduler extends SharedContext {
127
143
  if (this.started) {
128
144
  this.scheduleHarvest()
129
145
  }
130
- return
131
146
 
132
- function onHarvestFinished (result) {
133
- if (result.blocked) scheduler.onHarvestBlocked(opts, result)
134
- else scheduler.onHarvestFinished(opts, result)
135
- }
147
+ return
136
148
  }
137
149
 
138
150
  onHarvestFinished (opts, result) {
@@ -141,7 +153,7 @@ export class HarvestScheduler extends SharedContext {
141
153
  }
142
154
 
143
155
  if (result.sent && result.retry) {
144
- var delay = result.delay || this.opts.retryDelay
156
+ const delay = result.delay || this.opts.retryDelay
145
157
  // reschedule next harvest if should be delayed longer
146
158
  if (this.started && delay) {
147
159
  clearTimeout(this.timeoutHandle)