@newrelic/browser-agent 1.238.0 → 1.239.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 (249) hide show
  1. package/dist/cjs/common/config/state/init.js +21 -13
  2. package/dist/cjs/common/config/state/runtime.js +0 -4
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/constants/runtime.js +3 -3
  6. package/dist/cjs/common/constants/shared-channel.js +3 -1
  7. package/dist/cjs/common/deny-list/deny-list.js +2 -8
  8. package/dist/cjs/common/drain/drain.js +1 -1
  9. package/dist/cjs/common/event-emitter/contextual-ee.js +6 -6
  10. package/dist/cjs/common/harvest/harvest-scheduler.js +2 -4
  11. package/dist/cjs/common/harvest/harvest.js +2 -6
  12. package/dist/cjs/common/serialize/bel-serializer.js +1 -1
  13. package/dist/cjs/common/session/session-entity.js +16 -12
  14. package/dist/cjs/common/storage/first-party-cookies.js +5 -4
  15. package/dist/cjs/common/storage/local-storage.js +3 -2
  16. package/dist/cjs/common/timer/interaction-timer.js +14 -6
  17. package/dist/cjs/common/timing/nav-timing.js +1 -1
  18. package/dist/cjs/common/unload/eol.js +4 -30
  19. package/dist/cjs/common/util/feature-flags.js +14 -15
  20. package/dist/cjs/common/util/invoke.js +3 -1
  21. package/dist/cjs/common/util/obfuscate.js +3 -5
  22. package/dist/cjs/common/util/traverse.js +1 -0
  23. package/dist/cjs/common/window/page-visibility.js +1 -2
  24. package/dist/cjs/common/wrap/wrap-jsonp.js +1 -1
  25. package/dist/cjs/features/ajax/aggregate/index.js +5 -7
  26. package/dist/cjs/features/ajax/instrument/distributed-tracing.js +8 -8
  27. package/dist/cjs/features/ajax/instrument/index.js +47 -15
  28. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +0 -1
  29. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +4 -4
  30. package/dist/cjs/features/jserrors/aggregate/index.js +4 -5
  31. package/dist/cjs/features/metrics/aggregate/framework-detection.js +103 -7
  32. package/dist/cjs/features/metrics/aggregate/index.js +20 -37
  33. package/dist/cjs/features/metrics/instrument/index.js +0 -2
  34. package/dist/cjs/features/page_action/aggregate/index.js +17 -19
  35. package/dist/cjs/features/page_view_event/aggregate/index.js +1 -2
  36. package/dist/cjs/features/page_view_event/instrument/index.js +4 -2
  37. package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -7
  38. package/dist/cjs/features/session_replay/aggregate/index.js +3 -3
  39. package/dist/cjs/features/session_trace/aggregate/index.js +8 -8
  40. package/dist/cjs/features/spa/aggregate/index.js +14 -20
  41. package/dist/cjs/features/spa/aggregate/interaction.js +0 -2
  42. package/dist/cjs/features/spa/aggregate/serializer.js +1 -1
  43. package/dist/cjs/features/utils/aggregate-base.js +4 -0
  44. package/dist/cjs/features/utils/handler-cache.js +3 -1
  45. package/dist/cjs/features/utils/instrument-base.js +24 -6
  46. package/dist/cjs/loaders/agent-base.js +11 -0
  47. package/dist/cjs/loaders/agent.js +7 -7
  48. package/dist/cjs/loaders/api/api.js +21 -4
  49. package/dist/cjs/loaders/api/apiAsync.js +19 -20
  50. package/dist/cjs/loaders/configure/configure.js +3 -0
  51. package/dist/cjs/loaders/micro-agent.js +20 -3
  52. package/dist/esm/common/config/state/init.js +21 -13
  53. package/dist/esm/common/config/state/runtime.js +0 -4
  54. package/dist/esm/common/constants/env.cdn.js +1 -1
  55. package/dist/esm/common/constants/env.npm.js +1 -1
  56. package/dist/esm/common/constants/runtime.js +1 -1
  57. package/dist/esm/common/constants/shared-channel.js +3 -1
  58. package/dist/esm/common/deny-list/deny-list.js +2 -8
  59. package/dist/esm/common/drain/drain.js +1 -1
  60. package/dist/esm/common/event-emitter/contextual-ee.js +6 -6
  61. package/dist/esm/common/harvest/harvest-scheduler.js +2 -4
  62. package/dist/esm/common/harvest/harvest.js +2 -6
  63. package/dist/esm/common/serialize/bel-serializer.js +1 -1
  64. package/dist/esm/common/session/session-entity.js +16 -12
  65. package/dist/esm/common/storage/first-party-cookies.js +5 -4
  66. package/dist/esm/common/storage/local-storage.js +3 -2
  67. package/dist/esm/common/timer/interaction-timer.js +14 -6
  68. package/dist/esm/common/timing/nav-timing.js +1 -1
  69. package/dist/esm/common/unload/eol.js +5 -31
  70. package/dist/esm/common/util/feature-flags.js +14 -15
  71. package/dist/esm/common/util/invoke.js +3 -1
  72. package/dist/esm/common/util/obfuscate.js +3 -5
  73. package/dist/esm/common/util/traverse.js +1 -0
  74. package/dist/esm/common/window/page-visibility.js +1 -2
  75. package/dist/esm/common/wrap/wrap-jsonp.js +1 -1
  76. package/dist/esm/features/ajax/aggregate/index.js +5 -7
  77. package/dist/esm/features/ajax/instrument/distributed-tracing.js +8 -8
  78. package/dist/esm/features/ajax/instrument/index.js +47 -15
  79. package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +0 -1
  80. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +4 -4
  81. package/dist/esm/features/jserrors/aggregate/index.js +4 -5
  82. package/dist/esm/features/metrics/aggregate/framework-detection.js +103 -7
  83. package/dist/esm/features/metrics/aggregate/index.js +22 -39
  84. package/dist/esm/features/metrics/instrument/index.js +1 -3
  85. package/dist/esm/features/page_action/aggregate/index.js +17 -19
  86. package/dist/esm/features/page_view_event/aggregate/index.js +1 -2
  87. package/dist/esm/features/page_view_event/instrument/index.js +4 -2
  88. package/dist/esm/features/page_view_timing/aggregate/index.js +7 -8
  89. package/dist/esm/features/session_replay/aggregate/index.js +2 -2
  90. package/dist/esm/features/session_trace/aggregate/index.js +8 -8
  91. package/dist/esm/features/spa/aggregate/index.js +14 -20
  92. package/dist/esm/features/spa/aggregate/interaction.js +0 -2
  93. package/dist/esm/features/spa/aggregate/serializer.js +1 -1
  94. package/dist/esm/features/utils/aggregate-base.js +4 -0
  95. package/dist/esm/features/utils/handler-cache.js +3 -1
  96. package/dist/esm/features/utils/instrument-base.js +24 -6
  97. package/dist/esm/loaders/agent-base.js +11 -0
  98. package/dist/esm/loaders/agent.js +7 -7
  99. package/dist/esm/loaders/api/api.js +21 -4
  100. package/dist/esm/loaders/api/apiAsync.js +19 -20
  101. package/dist/esm/loaders/configure/configure.js +3 -0
  102. package/dist/esm/loaders/features/enabled-features.js +1 -1
  103. package/dist/esm/loaders/micro-agent.js +21 -4
  104. package/dist/types/common/config/state/init.d.ts.map +1 -1
  105. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  106. package/dist/types/common/constants/runtime.d.ts +1 -1
  107. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  108. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  109. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  110. package/dist/types/common/session/session-entity.d.ts +6 -9
  111. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  112. package/dist/types/common/storage/first-party-cookies.d.ts +1 -1
  113. package/dist/types/common/storage/first-party-cookies.d.ts.map +1 -1
  114. package/dist/types/common/storage/local-storage.d.ts.map +1 -1
  115. package/dist/types/common/timer/interaction-timer.d.ts +3 -0
  116. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
  117. package/dist/types/common/unload/eol.d.ts +1 -2
  118. package/dist/types/common/unload/eol.d.ts.map +1 -1
  119. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  120. package/dist/types/common/util/obfuscate.d.ts.map +1 -1
  121. package/dist/types/common/util/traverse.d.ts.map +1 -1
  122. package/dist/types/common/window/page-visibility.d.ts.map +1 -1
  123. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  124. package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
  125. package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts.map +1 -1
  126. package/dist/types/features/jserrors/aggregate/index.d.ts +1 -1
  127. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  128. package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -1
  129. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  130. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  131. package/dist/types/features/page_action/aggregate/index.d.ts +2 -2
  132. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  133. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  134. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  135. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  136. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  137. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  138. package/dist/types/features/spa/aggregate/interaction.d.ts.map +1 -1
  139. package/dist/types/features/utils/aggregate-base.d.ts +1 -0
  140. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  141. package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
  142. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  143. package/dist/types/loaders/agent-base.d.ts +6 -0
  144. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  145. package/dist/types/loaders/agent.d.ts +1 -1
  146. package/dist/types/loaders/agent.d.ts.map +1 -1
  147. package/dist/types/loaders/api/api.d.ts +1 -0
  148. package/dist/types/loaders/api/api.d.ts.map +1 -1
  149. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  150. package/dist/types/loaders/configure/configure.d.ts +1 -0
  151. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  152. package/dist/types/loaders/micro-agent.d.ts +7 -1
  153. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  154. package/package.json +41 -12
  155. package/src/common/aggregate/aggregator.test.js +107 -0
  156. package/src/common/config/state/configurable.test.js +73 -0
  157. package/src/common/config/state/info.test.js +31 -0
  158. package/src/common/config/state/init.js +13 -12
  159. package/src/common/config/state/init.test.js +28 -0
  160. package/src/common/config/state/loader-config.test.js +21 -0
  161. package/src/common/config/state/runtime.js +0 -2
  162. package/src/common/config/state/runtime.test.js +21 -0
  163. package/src/common/constants/__mocks__/runtime.js +1 -1
  164. package/src/common/constants/runtime.js +1 -1
  165. package/src/common/constants/runtime.test.js +2 -2
  166. package/src/common/constants/shared-channel.js +1 -1
  167. package/src/common/deny-list/deny-list.js +2 -10
  168. package/src/common/drain/drain.js +1 -1
  169. package/src/common/drain/drain.test.js +74 -0
  170. package/src/common/event-emitter/contextual-ee.js +6 -6
  171. package/src/common/harvest/harvest-scheduler.js +2 -5
  172. package/src/common/harvest/harvest-scheduler.test.js +2 -6
  173. package/src/common/harvest/harvest.js +2 -6
  174. package/src/common/harvest/harvest.test.js +0 -2
  175. package/src/common/ids/id.test.js +6 -6
  176. package/src/common/serialize/bel-serializer.js +1 -1
  177. package/src/common/session/session-entity.component-test.js +3 -2
  178. package/src/common/session/session-entity.js +11 -9
  179. package/src/common/storage/first-party-cookies.js +5 -4
  180. package/src/common/storage/local-storage.js +3 -2
  181. package/src/common/timer/interaction-timer.component-test.js +52 -7
  182. package/src/common/timer/interaction-timer.js +15 -6
  183. package/src/common/timer/timer.test.js +0 -1
  184. package/src/common/timing/nav-timing.js +1 -1
  185. package/src/common/unload/eol.js +5 -31
  186. package/src/common/url/encode.test.js +1 -0
  187. package/src/common/util/__mocks__/invoke.js +1 -0
  188. package/src/common/util/data-size.test.js +0 -1
  189. package/src/common/util/feature-flags.js +15 -17
  190. package/src/common/util/feature-flags.test.js +4 -8
  191. package/src/common/util/invoke.js +1 -1
  192. package/src/common/util/obfuscate.js +3 -5
  193. package/src/common/util/submit-data.test.js +1 -1
  194. package/src/common/util/traverse.js +1 -0
  195. package/src/common/window/__mocks__/nreum.js +3 -1
  196. package/src/common/window/page-visibility.js +1 -2
  197. package/src/common/wrap/wrap-jsonp.js +1 -1
  198. package/src/features/ajax/aggregate/index.js +5 -7
  199. package/src/features/ajax/instrument/distributed-tracing.js +8 -8
  200. package/src/features/ajax/instrument/index.js +40 -17
  201. package/src/features/jserrors/aggregate/canonical-function-name.js +0 -2
  202. package/src/features/jserrors/aggregate/compute-stack-trace.js +4 -4
  203. package/src/features/jserrors/aggregate/compute-stack-trace.test.js +1 -1
  204. package/src/features/jserrors/aggregate/index.js +4 -5
  205. package/src/features/metrics/aggregate/framework-detection.js +129 -8
  206. package/src/features/metrics/aggregate/framework-detection.test.js +213 -82
  207. package/src/features/metrics/aggregate/index.js +22 -45
  208. package/src/features/metrics/instrument/index.js +1 -3
  209. package/src/features/page_action/aggregate/index.js +12 -13
  210. package/src/features/page_view_event/aggregate/index.js +1 -2
  211. package/src/features/page_view_event/instrument/index.js +2 -2
  212. package/src/features/page_view_timing/aggregate/index.js +7 -8
  213. package/src/features/session_replay/aggregate/index.component-test.js +3 -15
  214. package/src/features/session_replay/aggregate/index.js +2 -2
  215. package/src/features/session_trace/aggregate/index.js +6 -9
  216. package/src/features/spa/aggregate/index.js +14 -20
  217. package/src/features/spa/aggregate/interaction.js +0 -2
  218. package/src/features/spa/aggregate/serializer.js +1 -1
  219. package/src/features/utils/aggregate-base.js +5 -0
  220. package/src/features/utils/aggregate-base.test.js +2 -1
  221. package/src/features/utils/handler-cache.js +3 -2
  222. package/src/features/utils/instrument-base.js +25 -6
  223. package/src/features/utils/instrument-base.test.js +2 -2
  224. package/src/loaders/agent-base.js +11 -0
  225. package/src/loaders/agent.js +7 -7
  226. package/src/loaders/api/api.js +21 -4
  227. package/src/loaders/api/api.test.js +85 -0
  228. package/src/loaders/api/apiAsync.js +19 -20
  229. package/src/loaders/api/apiAsync.test.js +17 -0
  230. package/src/loaders/configure/configure.js +3 -0
  231. package/src/loaders/features/enabled-features.js +1 -1
  232. package/src/loaders/micro-agent.js +22 -4
  233. package/dist/cjs/features/metrics/aggregate/endpoint-map.js +0 -14
  234. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +0 -14
  235. package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +0 -53
  236. package/dist/esm/features/metrics/aggregate/endpoint-map.js +0 -7
  237. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +0 -8
  238. package/dist/esm/features/metrics/aggregate/polyfill-detection.js +0 -47
  239. package/dist/types/features/metrics/aggregate/endpoint-map.d.ts +0 -8
  240. package/dist/types/features/metrics/aggregate/endpoint-map.d.ts.map +0 -1
  241. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +0 -6
  242. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +0 -1
  243. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +0 -7
  244. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +0 -1
  245. package/src/features/metrics/aggregate/endpoint-map.js +0 -7
  246. package/src/features/metrics/aggregate/polyfill-detection.es5.js +0 -8
  247. package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +0 -16
  248. package/src/features/metrics/aggregate/polyfill-detection.js +0 -48
  249. package/src/features/metrics/aggregate/polyfill-detection.test.js +0 -163
@@ -18,7 +18,6 @@ import { now } from '../../../common/timing/now'
18
18
  import { globalScope } from '../../../common/constants/runtime'
19
19
 
20
20
  import { FEATURE_NAME } from '../constants'
21
- import { drain } from '../../../common/drain/drain'
22
21
  import { FEATURE_NAMES } from '../../../loaders/features/features'
23
22
  import { AggregateBase } from '../../utils/aggregate-base'
24
23
 
@@ -35,7 +34,7 @@ export class Aggregate extends AggregateBase {
35
34
  this.observedAt = {}
36
35
  this.pageviewReported = {}
37
36
  this.errorCache = {}
38
- this.currentBody
37
+ this.currentBody = undefined
39
38
  this.errorOnPage = false
40
39
 
41
40
  // this will need to change to match whatever ee we use in the instrument
@@ -63,7 +62,7 @@ export class Aggregate extends AggregateBase {
63
62
  scheduler.stopTimer(true)
64
63
  }, this.featureName, this.ee)
65
64
 
66
- drain(this.agentIdentifier, this.featureName)
65
+ this.drain()
67
66
  }
68
67
 
69
68
  onHarvestStarted (options) {
@@ -74,7 +73,7 @@ export class Aggregate extends AggregateBase {
74
73
  this.currentBody = body
75
74
  }
76
75
 
77
- var payload = { body: body, qs: {} }
76
+ var payload = { body, qs: {} }
78
77
  var releaseIds = stringify(getRuntime(this.agentIdentifier).releaseIds)
79
78
 
80
79
  if (releaseIds !== '{}') {
@@ -196,7 +195,7 @@ export class Aggregate extends AggregateBase {
196
195
  params.firstOccurrenceTimestamp = this.observedAt[bucketHash]
197
196
 
198
197
  var type = internal ? 'ierr' : 'err'
199
- var newMetrics = { time: time }
198
+ var newMetrics = { time }
200
199
 
201
200
  // sr, stn and spa aggregators listen to this event - stn sends the error in its payload,
202
201
  // and spa annotates the error with interaction info
@@ -2,15 +2,30 @@ import { isBrowserScope } from '../../../common/constants/runtime'
2
2
 
3
3
  const FRAMEWORKS = {
4
4
  REACT: 'React',
5
+ NEXTJS: 'NextJS',
6
+
7
+ VUE: 'Vue',
8
+ NUXTJS: 'NuxtJS',
9
+
5
10
  ANGULAR: 'Angular',
11
+ ANGULARUNIVERSAL: 'AngularUniversal',
12
+
13
+ SVELTE: 'Svelte',
14
+ SVELTEKIT: 'SvelteKit',
15
+
16
+ PREACT: 'Preact',
17
+ PREACTSSR: 'PreactSSR',
18
+
6
19
  ANGULARJS: 'AngularJS',
7
20
  BACKBONE: 'Backbone',
8
21
  EMBER: 'Ember',
9
- VUE: 'Vue',
10
22
  METEOR: 'Meteor',
11
23
  ZEPTO: 'Zepto',
12
24
  JQUERY: 'Jquery',
13
- MOOTOOLS: 'MooTools'
25
+ MOOTOOLS: 'MooTools',
26
+ QWIK: 'Qwik',
27
+
28
+ ELECTRON: 'Electron'
14
29
  }
15
30
 
16
31
  export function getFrameworks () {
@@ -18,16 +33,42 @@ export function getFrameworks () {
18
33
 
19
34
  const frameworks = []
20
35
  try {
21
- if (detectReact()) frameworks.push(FRAMEWORKS.REACT)
36
+ if (detectReact()) {
37
+ frameworks.push(FRAMEWORKS.REACT)
38
+
39
+ if (detectNextJS()) frameworks.push(FRAMEWORKS.NEXTJS)
40
+ }
41
+ if (detectVue()) {
42
+ frameworks.push(FRAMEWORKS.VUE)
43
+
44
+ if (detectNuxtJS()) frameworks.push(FRAMEWORKS.NUXTJS)
45
+ }
46
+ if (detectAngular()) {
47
+ frameworks.push(FRAMEWORKS.ANGULAR)
48
+
49
+ if (detectAngularUniversal()) frameworks.push(FRAMEWORKS.ANGULARUNIVERSAL)
50
+ }
51
+ if (detectSvelte()) {
52
+ frameworks.push(FRAMEWORKS.SVELTE)
53
+
54
+ if (detectSvelteKit()) frameworks.push(FRAMEWORKS.SVELTEKIT)
55
+ }
56
+ if (detectPreact()) {
57
+ frameworks.push(FRAMEWORKS.PREACT)
58
+
59
+ if (detectPreactSSR()) frameworks.push(FRAMEWORKS.PREACTSSR)
60
+ }
61
+
22
62
  if (detectAngularJs()) frameworks.push(FRAMEWORKS.ANGULARJS)
23
- if (detectAngular()) frameworks.push(FRAMEWORKS.ANGULAR)
24
63
  if (Object.prototype.hasOwnProperty.call(window, 'Backbone')) frameworks.push(FRAMEWORKS.BACKBONE)
25
64
  if (Object.prototype.hasOwnProperty.call(window, 'Ember')) frameworks.push(FRAMEWORKS.EMBER)
26
- if (Object.prototype.hasOwnProperty.call(window, 'Vue')) frameworks.push(FRAMEWORKS.VUE)
27
65
  if (Object.prototype.hasOwnProperty.call(window, 'Meteor')) frameworks.push(FRAMEWORKS.METEOR)
28
66
  if (Object.prototype.hasOwnProperty.call(window, 'Zepto')) frameworks.push(FRAMEWORKS.ZEPTO)
29
67
  if (Object.prototype.hasOwnProperty.call(window, 'jQuery')) frameworks.push(FRAMEWORKS.JQUERY)
30
68
  if (Object.prototype.hasOwnProperty.call(window, 'MooTools')) frameworks.push(FRAMEWORKS.MOOTOOLS)
69
+ if (Object.prototype.hasOwnProperty.call(window, 'qwikevents')) frameworks.push(FRAMEWORKS.QWIK)
70
+
71
+ if (detectElectron()) frameworks.push(FRAMEWORKS.ELECTRON)
31
72
  } catch (err) {
32
73
  // Possibly not supported
33
74
  }
@@ -53,6 +94,86 @@ function detectReact () {
53
94
  }
54
95
  }
55
96
 
97
+ function detectNextJS () {
98
+ // React SSR
99
+ try {
100
+ return Object.prototype.hasOwnProperty.call(window, 'next') &&
101
+ Object.prototype.hasOwnProperty.call(window.next, 'version')
102
+ } catch (err) {
103
+ return false
104
+ }
105
+ }
106
+
107
+ function detectVue () {
108
+ try {
109
+ return Object.prototype.hasOwnProperty.call(window, 'Vue')
110
+ } catch (err) {
111
+ return false
112
+ }
113
+ }
114
+
115
+ function detectNuxtJS () {
116
+ // Vue SSR
117
+ try {
118
+ return Object.prototype.hasOwnProperty.call(window, '$nuxt') &&
119
+ Object.prototype.hasOwnProperty.call(window.$nuxt, 'nuxt')
120
+ } catch (err) {
121
+ return false
122
+ }
123
+ }
124
+
125
+ function detectAngular () {
126
+ try {
127
+ return Object.prototype.hasOwnProperty.call(window, 'ng') ||
128
+ document.querySelector('[ng-version]')
129
+ } catch (err) {
130
+ return false
131
+ }
132
+ }
133
+
134
+ function detectAngularUniversal () {
135
+ // Anguler SSR
136
+ try {
137
+ return document.querySelector('[ng-server-context]')
138
+ } catch (err) {
139
+ return false
140
+ }
141
+ }
142
+
143
+ function detectSvelte () {
144
+ try {
145
+ return Object.prototype.hasOwnProperty.call(window, '__svelte')
146
+ } catch (err) {
147
+ return false
148
+ }
149
+ }
150
+
151
+ function detectSvelteKit () {
152
+ // Svelte SSR
153
+ try {
154
+ return !!Object.keys(window).find(prop => prop.startsWith('__sveltekit'))
155
+ } catch (err) {
156
+ return false
157
+ }
158
+ }
159
+
160
+ function detectPreact () {
161
+ try {
162
+ return Object.prototype.hasOwnProperty.call(window, 'preact')
163
+ } catch (err) {
164
+ return false
165
+ }
166
+ }
167
+
168
+ function detectPreactSSR () {
169
+ // Svelte SSR
170
+ try {
171
+ return document.querySelector('script[type="__PREACT_CLI_DATA__"]')
172
+ } catch (err) {
173
+ return false
174
+ }
175
+ }
176
+
56
177
  function detectAngularJs () {
57
178
  try {
58
179
  return Object.prototype.hasOwnProperty.call(window, 'angular') ||
@@ -63,10 +184,10 @@ function detectAngularJs () {
63
184
  }
64
185
  }
65
186
 
66
- function detectAngular () {
187
+ function detectElectron () {
67
188
  try {
68
- return Object.prototype.hasOwnProperty.call(window, 'ng') ||
69
- document.querySelector('[ng-version]')
189
+ return typeof navigator === 'object' && typeof navigator.userAgent === 'string' &&
190
+ navigator.userAgent.indexOf('Electron') >= 0
70
191
  } catch (err) {
71
192
  return false
72
193
  }
@@ -23,125 +23,252 @@ test('framework detection should not happen in non-browser scope', async () => {
23
23
  delete global.React
24
24
  })
25
25
 
26
- test('should detect react from global React property', () => {
27
- global.React = {}
26
+ describe('react', () => {
27
+ test('should detect react from global React property', () => {
28
+ global.React = {}
28
29
 
29
- expect(getFrameworks()).toEqual(['React'])
30
+ expect(getFrameworks()).toEqual(['React'])
30
31
 
31
- delete global.React
32
- })
32
+ delete global.React
33
+ })
33
34
 
34
- test('should detect react from global ReactDOM property', () => {
35
- global.ReactDOM = {}
35
+ test('should detect react from global ReactDOM property', () => {
36
+ global.ReactDOM = {}
36
37
 
37
- expect(getFrameworks()).toEqual(['React'])
38
+ expect(getFrameworks()).toEqual(['React'])
38
39
 
39
- delete global.ReactDOM
40
- })
40
+ delete global.ReactDOM
41
+ })
41
42
 
42
- test('should detect react from global ReactRedux property', () => {
43
- global.ReactRedux = {}
43
+ test('should detect react from global ReactRedux property', () => {
44
+ global.ReactRedux = {}
44
45
 
45
- expect(getFrameworks()).toEqual(['React'])
46
+ expect(getFrameworks()).toEqual(['React'])
46
47
 
47
- delete global.ReactRedux
48
- })
48
+ delete global.ReactRedux
49
+ })
49
50
 
50
- test('should detect react from html [data-reactroot] property', () => {
51
- document.body.innerHTML = '<div data-reactroot=""></div>'
51
+ test('should detect react from html [data-reactroot] property', () => {
52
+ document.body.innerHTML = '<div data-reactroot=""></div>'
52
53
 
53
- expect(getFrameworks()).toEqual(['React'])
54
- })
54
+ expect(getFrameworks()).toEqual(['React'])
55
+ })
55
56
 
56
- test('should detect react from html [data-reactid] property', () => {
57
- document.body.innerHTML = '<div data-reactid=""></div>'
57
+ test('should detect react from html [data-reactid] property', () => {
58
+ document.body.innerHTML = '<div data-reactid=""></div>'
58
59
 
59
- expect(getFrameworks()).toEqual(['React'])
60
- })
60
+ expect(getFrameworks()).toEqual(['React'])
61
+ })
61
62
 
62
- test('should detect react from element _reactRootContainer property', () => {
63
- const element = document.createElement('div')
64
- element._reactRootContainer = {}
65
- document.body.innerHTML = '<html><body></body></html>'
66
- document.body.appendChild(element)
63
+ test('should detect react from element _reactRootContainer property', () => {
64
+ const element = document.createElement('div')
65
+ element._reactRootContainer = {}
66
+ document.body.innerHTML = '<html><body></body></html>'
67
+ document.body.appendChild(element)
67
68
 
68
- expect(getFrameworks()).toEqual(['React'])
69
- })
69
+ expect(getFrameworks()).toEqual(['React'])
70
+ })
70
71
 
71
- test('should detect angularjs from global angular property', () => {
72
- global.angular = {}
72
+ describe('nextjs', () => {
73
+ test('should not detect nextjs if react is not detected', () => {
74
+ global.next = { version: 'test' }
73
75
 
74
- expect(getFrameworks()).toEqual(['AngularJS'])
76
+ expect(getFrameworks()).toEqual([])
75
77
 
76
- delete global.angular
77
- })
78
+ delete global.next
79
+ })
80
+
81
+ test('should detect nextjs if global is set', () => {
82
+ global.React = {}
83
+ global.next = { version: 'test' }
78
84
 
79
- test('should detect angularjs from html .ng-binding property', () => {
80
- document.body.innerHTML = '<div class="ng-binding"></div>'
85
+ expect(getFrameworks()).toEqual(['React', 'NextJS'])
81
86
 
82
- expect(getFrameworks()).toEqual(['AngularJS'])
87
+ delete global.React
88
+ delete global.next
89
+ })
90
+ })
83
91
  })
84
92
 
85
- test('should detect angularjs from html [ng-app] property', () => {
86
- document.body.innerHTML = '<div ng-app=""></div>'
93
+ describe('vue', () => {
94
+ test('should detect vue from global Vue property', () => {
95
+ global.Vue = {}
87
96
 
88
- expect(getFrameworks()).toEqual(['AngularJS'])
89
- })
97
+ expect(getFrameworks()).toEqual(['Vue'])
90
98
 
91
- test('should detect angularjs from html [data-ng-app] property', () => {
92
- document.body.innerHTML = '<div data-ng-app=""></div>'
99
+ delete global.Vue
100
+ })
93
101
 
94
- expect(getFrameworks()).toEqual(['AngularJS'])
95
- })
102
+ describe('nuxtjs', () => {
103
+ test('should not detect nuxtjs if vue is not detected', () => {
104
+ global.$nuxt = { nuxt: {} }
96
105
 
97
- test('should detect angularjs from html [ng-controller] property', () => {
98
- document.body.innerHTML = '<div ng-controller=""></div>'
106
+ expect(getFrameworks()).toEqual([])
99
107
 
100
- expect(getFrameworks()).toEqual(['AngularJS'])
101
- })
108
+ delete global.$nuxt
109
+ })
110
+
111
+ test('should detect nuxtjs if global is set', () => {
112
+ global.Vue = {}
113
+ global.$nuxt = { nuxt: {} }
102
114
 
103
- test('should detect angularjs from html [data-ng-controller] property', () => {
104
- document.body.innerHTML = '<div data-ng-controller=""></div>'
115
+ expect(getFrameworks()).toEqual(['Vue', 'NuxtJS'])
105
116
 
106
- expect(getFrameworks()).toEqual(['AngularJS'])
117
+ delete global.Vue
118
+ delete global.$nuxt
119
+ })
120
+ })
107
121
  })
108
122
 
109
- test('should detect angularjs from html [ng-repeat] property', () => {
110
- document.body.innerHTML = '<div ng-repeat=""></div>'
123
+ describe('angular', () => {
124
+ test('should detect angular from global ng property', () => {
125
+ global.ng = {}
111
126
 
112
- expect(getFrameworks()).toEqual(['AngularJS'])
113
- })
127
+ expect(getFrameworks()).toEqual(['Angular'])
114
128
 
115
- test('should detect angularjs from html [data-ng-repeat] property', () => {
116
- document.body.innerHTML = '<div data-ng-repeat=""></div>'
129
+ delete global.ng
130
+ })
117
131
 
118
- expect(getFrameworks()).toEqual(['AngularJS'])
119
- })
132
+ test('should detect angular from html [ng-version] property', () => {
133
+ document.body.innerHTML = '<div ng-version=""></div>'
134
+
135
+ expect(getFrameworks()).toEqual(['Angular'])
136
+ })
137
+
138
+ describe('angular universal', () => {
139
+ test('should not detect angular universal if angular is not detected', () => {
140
+ document.body.innerHTML = '<div ng-server-context=""></div>'
141
+
142
+ expect(getFrameworks()).toEqual([])
143
+ })
120
144
 
121
- test('should detect angularjs from angular.js script element', () => {
122
- document.body.innerHTML = `<script src="${faker.internet.url()}/angular.js"></script>`
145
+ test('should detect nuxtjs if global is set', () => {
146
+ document.body.innerHTML = '<div ng-version="" ng-server-context=""></div>'
123
147
 
124
- expect(getFrameworks()).toEqual(['AngularJS'])
148
+ expect(getFrameworks()).toEqual(['Angular', 'AngularUniversal'])
149
+ })
150
+ })
125
151
  })
126
152
 
127
- test('should detect angularjs from angular.min.js script element', () => {
128
- document.body.innerHTML = `<script src="${faker.internet.url()}/angular.min.js"></script>`
153
+ describe('svelte', () => {
154
+ test('should detect svelte from global __svelte property', () => {
155
+ global.__svelte = {}
156
+
157
+ expect(getFrameworks()).toEqual(['Svelte'])
158
+
159
+ delete global.__svelte
160
+ })
161
+
162
+ describe('sveltekit', () => {
163
+ test('should not detect sveltekit if svelte is not detected', () => {
164
+ global.__sveltekit_1234 = { }
129
165
 
130
- expect(getFrameworks()).toEqual(['AngularJS'])
166
+ expect(getFrameworks()).toEqual([])
167
+
168
+ delete global.__sveltekit_1234
169
+ })
170
+
171
+ test('should detect sveltekit if global is set', () => {
172
+ global.__svelte = {}
173
+ global.__sveltekit_4567 = {}
174
+
175
+ expect(getFrameworks()).toEqual(['Svelte', 'SvelteKit'])
176
+
177
+ delete global.__svelte
178
+ delete global.__sveltekit_4567
179
+ })
180
+ })
131
181
  })
132
182
 
133
- test('should detect angular from global ng property', () => {
134
- global.ng = {}
183
+ describe('preact', () => {
184
+ test('should detect preact from global preact property', () => {
185
+ global.preact = {}
186
+
187
+ expect(getFrameworks()).toEqual(['Preact'])
188
+
189
+ delete global.preact
190
+ })
191
+
192
+ describe('preact ssr', () => {
193
+ test('should not detect preact ssr if preact is not detected', () => {
194
+ document.body.innerHTML = '<script type="__PREACT_CLI_DATA__"></div>'
135
195
 
136
- expect(getFrameworks()).toEqual(['Angular'])
196
+ expect(getFrameworks()).toEqual([])
197
+ })
137
198
 
138
- delete global.ng
199
+ test('should detect sveltekit if global is set', () => {
200
+ global.preact = {}
201
+ document.body.innerHTML = '<script type="__PREACT_CLI_DATA__"></div>'
202
+
203
+ expect(getFrameworks()).toEqual(['Preact', 'PreactSSR'])
204
+
205
+ delete global.preact
206
+ })
207
+ })
139
208
  })
140
209
 
141
- test('should detect angular from html [ng-version] property', () => {
142
- document.body.innerHTML = '<div ng-version=""></div>'
210
+ describe('angularjs', () => {
211
+ test('should detect angularjs from global angular property', () => {
212
+ global.angular = {}
213
+
214
+ expect(getFrameworks()).toEqual(['AngularJS'])
215
+
216
+ delete global.angular
217
+ })
218
+
219
+ test('should detect angularjs from html .ng-binding property', () => {
220
+ document.body.innerHTML = '<div class="ng-binding"></div>'
221
+
222
+ expect(getFrameworks()).toEqual(['AngularJS'])
223
+ })
224
+
225
+ test('should detect angularjs from html [ng-app] property', () => {
226
+ document.body.innerHTML = '<div ng-app=""></div>'
227
+
228
+ expect(getFrameworks()).toEqual(['AngularJS'])
229
+ })
230
+
231
+ test('should detect angularjs from html [data-ng-app] property', () => {
232
+ document.body.innerHTML = '<div data-ng-app=""></div>'
233
+
234
+ expect(getFrameworks()).toEqual(['AngularJS'])
235
+ })
236
+
237
+ test('should detect angularjs from html [ng-controller] property', () => {
238
+ document.body.innerHTML = '<div ng-controller=""></div>'
239
+
240
+ expect(getFrameworks()).toEqual(['AngularJS'])
241
+ })
242
+
243
+ test('should detect angularjs from html [data-ng-controller] property', () => {
244
+ document.body.innerHTML = '<div data-ng-controller=""></div>'
245
+
246
+ expect(getFrameworks()).toEqual(['AngularJS'])
247
+ })
248
+
249
+ test('should detect angularjs from html [ng-repeat] property', () => {
250
+ document.body.innerHTML = '<div ng-repeat=""></div>'
143
251
 
144
- expect(getFrameworks()).toEqual(['Angular'])
252
+ expect(getFrameworks()).toEqual(['AngularJS'])
253
+ })
254
+
255
+ test('should detect angularjs from html [data-ng-repeat] property', () => {
256
+ document.body.innerHTML = '<div data-ng-repeat=""></div>'
257
+
258
+ expect(getFrameworks()).toEqual(['AngularJS'])
259
+ })
260
+
261
+ test('should detect angularjs from angular.js script element', () => {
262
+ document.body.innerHTML = `<script src="${faker.internet.url()}/angular.js"></script>`
263
+
264
+ expect(getFrameworks()).toEqual(['AngularJS'])
265
+ })
266
+
267
+ test('should detect angularjs from angular.min.js script element', () => {
268
+ document.body.innerHTML = `<script src="${faker.internet.url()}/angular.min.js"></script>`
269
+
270
+ expect(getFrameworks()).toEqual(['AngularJS'])
271
+ })
145
272
  })
146
273
 
147
274
  test('should detect backbone from global Backbone property', () => {
@@ -160,14 +287,6 @@ test('should detect ember from global Ember property', () => {
160
287
  delete global.Ember
161
288
  })
162
289
 
163
- test('should detect vue from global Vue property', () => {
164
- global.Vue = {}
165
-
166
- expect(getFrameworks()).toEqual(['Vue'])
167
-
168
- delete global.Vue
169
- })
170
-
171
290
  test('should detect meteor from global Meteor property', () => {
172
291
  global.Meteor = {}
173
292
 
@@ -199,3 +318,15 @@ test('should detect mootools from global MooTools property', () => {
199
318
 
200
319
  delete global.MooTools
201
320
  })
321
+
322
+ test('should detect electron from user agent', () => {
323
+ const currentNavigator = global.navigator
324
+ Object.defineProperty(global, 'navigator', {
325
+ value: { userAgent: 'This is a test; Electron some version; foobar' },
326
+ writable: true
327
+ })
328
+
329
+ expect(getFrameworks()).toEqual(['Electron'])
330
+
331
+ global.navigator = currentNavigator
332
+ })