@newrelic/browser-agent 0.1.230 → 0.1.231

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 (221) hide show
  1. package/README.md +25 -1
  2. package/dist/cjs/common/browser-version/ios-version.js +4 -3
  3. package/dist/cjs/common/config/state/configurable.js +1 -1
  4. package/dist/cjs/common/config/state/info.js +1 -1
  5. package/dist/cjs/common/config/state/init.js +1 -1
  6. package/dist/cjs/common/config/state/loader-config.js +1 -1
  7. package/dist/cjs/common/config/state/runtime.js +5 -5
  8. package/dist/cjs/common/constants/env.cdn.js +29 -0
  9. package/dist/cjs/common/constants/env.js +32 -0
  10. package/dist/cjs/common/constants/env.npm.js +30 -0
  11. package/dist/cjs/common/event-emitter/contextual-ee.test.js +282 -0
  12. package/dist/cjs/common/event-emitter/handle.test.js +58 -0
  13. package/dist/cjs/common/event-emitter/register-handler.test.js +55 -0
  14. package/dist/cjs/common/harvest/harvest.js +2 -2
  15. package/dist/cjs/common/ids/id.js +14 -6
  16. package/dist/cjs/common/ids/id.test.js +85 -0
  17. package/dist/cjs/common/ids/unique-id.js +75 -51
  18. package/dist/cjs/common/ids/unique-id.test.js +49 -0
  19. package/dist/cjs/common/timing/nav-timing.js +51 -30
  20. package/dist/cjs/common/timing/nav-timing.test.js +192 -0
  21. package/dist/cjs/common/url/clean-url.test.js +9 -0
  22. package/dist/cjs/common/url/encode.test.js +74 -0
  23. package/dist/cjs/common/url/location.js +4 -0
  24. package/dist/cjs/common/url/location.test.js +13 -0
  25. package/dist/cjs/common/url/parse-url.test.js +111 -0
  26. package/dist/cjs/common/url/protocol.js +2 -12
  27. package/dist/cjs/common/url/protocol.test.js +16 -0
  28. package/dist/cjs/common/util/console.js +1 -1
  29. package/dist/cjs/common/util/map-own.test.js +3 -3
  30. package/dist/cjs/common/util/obfuscate.js +1 -1
  31. package/dist/cjs/common/window/page-visibility.js +2 -1
  32. package/dist/cjs/common/wrap/index.js +0 -7
  33. package/dist/cjs/common/wrap/wrap-events.js +6 -9
  34. package/dist/cjs/common/wrap/wrap-fetch.js +6 -6
  35. package/dist/cjs/common/wrap/wrap-history.js +7 -6
  36. package/dist/cjs/common/wrap/wrap-jsonp.js +7 -6
  37. package/dist/cjs/common/wrap/wrap-mutation.js +7 -6
  38. package/dist/cjs/common/wrap/wrap-promise.js +7 -6
  39. package/dist/cjs/common/wrap/wrap-promise.test.js +119 -0
  40. package/dist/cjs/common/wrap/wrap-raf.js +6 -6
  41. package/dist/cjs/common/wrap/wrap-timer.js +6 -6
  42. package/dist/cjs/common/wrap/wrap-xhr.js +5 -6
  43. package/dist/cjs/features/ajax/aggregate/index.js +1 -1
  44. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +5 -5
  45. package/dist/cjs/features/jserrors/aggregate/format-stack-trace.test.js +1 -1
  46. package/dist/cjs/features/jserrors/aggregate/index.js +3 -3
  47. package/dist/cjs/features/jserrors/instrument/index.js +2 -2
  48. package/dist/cjs/features/metrics/aggregate/index.js +6 -7
  49. package/dist/cjs/features/metrics/instrument/index.js +0 -25
  50. package/dist/cjs/features/metrics/instrument/workers-helper.js +5 -5
  51. package/dist/cjs/features/page_action/aggregate/index.js +1 -1
  52. package/dist/cjs/features/page_view_event/aggregate/index.js +17 -6
  53. package/dist/cjs/features/page_view_timing/aggregate/index.js +36 -26
  54. package/dist/cjs/features/session_trace/aggregate/index.js +16 -13
  55. package/dist/cjs/features/utils/instrument-base.js +6 -2
  56. package/dist/cjs/features/utils/lazy-loader.js +1 -1
  57. package/dist/cjs/loaders/agent.js +1 -1
  58. package/dist/cjs/loaders/api/api.js +8 -5
  59. package/dist/cjs/loaders/features/enabled-features.js +1 -1
  60. package/dist/cjs/loaders/micro-agent.js +2 -1
  61. package/dist/esm/common/browser-version/ios-version.js +4 -3
  62. package/dist/esm/common/config/state/configurable.js +1 -1
  63. package/dist/esm/common/config/state/info.js +1 -1
  64. package/dist/esm/common/config/state/init.js +1 -1
  65. package/dist/esm/common/config/state/loader-config.js +1 -1
  66. package/dist/esm/common/config/state/runtime.js +2 -2
  67. package/dist/esm/common/constants/env.cdn.js +20 -0
  68. package/dist/esm/common/constants/env.js +23 -0
  69. package/dist/esm/common/constants/env.npm.js +21 -0
  70. package/dist/esm/common/event-emitter/contextual-ee.test.js +278 -0
  71. package/dist/esm/common/event-emitter/handle.test.js +54 -0
  72. package/dist/esm/common/event-emitter/register-handler.test.js +51 -0
  73. package/dist/esm/common/harvest/harvest.js +1 -1
  74. package/dist/esm/common/ids/id.js +16 -6
  75. package/dist/esm/common/ids/id.test.js +81 -0
  76. package/dist/esm/common/ids/unique-id.js +75 -51
  77. package/dist/esm/common/ids/unique-id.test.js +44 -0
  78. package/dist/esm/common/timing/nav-timing.js +51 -29
  79. package/dist/esm/common/timing/nav-timing.test.js +190 -0
  80. package/dist/esm/common/url/clean-url.test.js +7 -0
  81. package/dist/esm/common/url/encode.test.js +70 -0
  82. package/dist/esm/common/url/location.js +4 -0
  83. package/dist/esm/common/url/location.test.js +11 -0
  84. package/dist/esm/common/url/parse-url.test.js +107 -0
  85. package/dist/esm/common/url/protocol.js +3 -12
  86. package/dist/esm/common/url/protocol.test.js +14 -0
  87. package/dist/esm/common/util/console.js +1 -1
  88. package/dist/esm/common/util/map-own.test.js +3 -3
  89. package/dist/esm/common/util/obfuscate.js +2 -2
  90. package/dist/esm/common/window/page-visibility.js +2 -1
  91. package/dist/esm/common/wrap/index.js +1 -2
  92. package/dist/esm/common/wrap/wrap-events.js +6 -9
  93. package/dist/esm/common/wrap/wrap-fetch.js +6 -6
  94. package/dist/esm/common/wrap/wrap-history.js +7 -6
  95. package/dist/esm/common/wrap/wrap-jsonp.js +7 -6
  96. package/dist/esm/common/wrap/wrap-mutation.js +7 -6
  97. package/dist/esm/common/wrap/wrap-promise.js +7 -6
  98. package/dist/esm/common/wrap/wrap-promise.test.js +115 -0
  99. package/dist/esm/common/wrap/wrap-raf.js +6 -6
  100. package/dist/esm/common/wrap/wrap-timer.js +6 -6
  101. package/dist/esm/common/wrap/wrap-xhr.js +5 -6
  102. package/dist/esm/features/ajax/aggregate/index.js +1 -1
  103. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +5 -5
  104. package/dist/esm/features/jserrors/aggregate/format-stack-trace.test.js +1 -1
  105. package/dist/esm/features/jserrors/aggregate/index.js +3 -3
  106. package/dist/esm/features/jserrors/instrument/index.js +2 -2
  107. package/dist/esm/features/metrics/aggregate/index.js +7 -8
  108. package/dist/esm/features/metrics/instrument/index.js +0 -25
  109. package/dist/esm/features/metrics/instrument/workers-helper.js +5 -5
  110. package/dist/esm/features/page_action/aggregate/index.js +1 -1
  111. package/dist/esm/features/page_view_event/aggregate/index.js +17 -6
  112. package/dist/esm/features/page_view_timing/aggregate/index.js +36 -26
  113. package/dist/esm/features/session_trace/aggregate/index.js +16 -13
  114. package/dist/esm/features/utils/instrument-base.js +1 -1
  115. package/dist/esm/features/utils/lazy-loader.js +1 -1
  116. package/dist/esm/loaders/agent.js +1 -1
  117. package/dist/esm/loaders/api/api.js +4 -4
  118. package/dist/esm/loaders/features/enabled-features.js +1 -1
  119. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  120. package/dist/types/common/constants/env.cdn.d.ts +18 -0
  121. package/dist/types/common/constants/env.cdn.d.ts.map +1 -0
  122. package/dist/types/common/constants/env.d.ts +13 -0
  123. package/dist/types/common/constants/env.d.ts.map +1 -0
  124. package/dist/types/common/constants/env.npm.d.ts +19 -0
  125. package/dist/types/common/constants/env.npm.d.ts.map +1 -0
  126. package/dist/types/common/ids/id.d.ts +11 -1
  127. package/dist/types/common/ids/id.d.ts.map +1 -1
  128. package/dist/types/common/ids/unique-id.d.ts +24 -1
  129. package/dist/types/common/ids/unique-id.d.ts.map +1 -1
  130. package/dist/types/common/timing/nav-timing.d.ts +1 -2
  131. package/dist/types/common/timing/nav-timing.d.ts.map +1 -1
  132. package/dist/types/common/unload/eol.d.ts.map +1 -1
  133. package/dist/types/common/url/location.d.ts +4 -0
  134. package/dist/types/common/url/location.d.ts.map +1 -1
  135. package/dist/types/common/url/parse-url.d.ts.map +1 -1
  136. package/dist/types/common/url/protocol.d.ts +1 -6
  137. package/dist/types/common/url/protocol.d.ts.map +1 -1
  138. package/dist/types/common/util/global-scope.d.ts.map +1 -1
  139. package/dist/types/common/wrap/index.d.ts +1 -2
  140. package/dist/types/common/wrap/index.d.ts.map +1 -1
  141. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  142. package/dist/types/common/wrap/wrap-history.d.ts.map +1 -1
  143. package/dist/types/common/wrap/wrap-jsonp.d.ts.map +1 -1
  144. package/dist/types/common/wrap/wrap-mutation.d.ts.map +1 -1
  145. package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
  146. package/dist/types/common/wrap/wrap-raf.d.ts.map +1 -1
  147. package/dist/types/common/wrap/wrap-timer.d.ts.map +1 -1
  148. package/dist/types/common/wrap/wrap-xhr.d.ts.map +1 -1
  149. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  150. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  151. package/dist/types/features/metrics/instrument/index.d.ts +0 -1
  152. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  153. package/dist/types/features/metrics/instrument/workers-helper.d.ts.map +1 -1
  154. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  155. package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -2
  156. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  157. package/dist/types/features/session_trace/aggregate/index.d.ts +1 -1
  158. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  159. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  160. package/dist/types/features/spa/instrument/index.d.ts.map +1 -1
  161. package/package.json +9 -30
  162. package/src/common/browser-version/ios-version.js +4 -3
  163. package/src/common/config/state/runtime.js +26 -24
  164. package/src/common/constants/env.cdn.js +20 -0
  165. package/src/common/constants/env.js +23 -0
  166. package/src/common/constants/env.npm.js +21 -0
  167. package/src/common/event-emitter/contextual-ee.test.js +310 -0
  168. package/src/common/event-emitter/handle.test.js +56 -0
  169. package/src/common/event-emitter/register-handler.test.js +61 -0
  170. package/src/common/harvest/harvest.js +2 -2
  171. package/src/common/ids/id.js +15 -6
  172. package/src/common/ids/id.test.js +92 -0
  173. package/src/common/ids/unique-id.js +77 -54
  174. package/src/common/ids/unique-id.test.js +58 -0
  175. package/src/common/timing/nav-timing.js +50 -30
  176. package/src/common/timing/nav-timing.test.js +161 -0
  177. package/src/common/unload/eol.js +1 -2
  178. package/src/common/url/clean-url.test.js +25 -0
  179. package/src/common/url/encode.test.js +80 -0
  180. package/src/common/url/location.js +4 -0
  181. package/src/common/url/location.test.js +15 -0
  182. package/src/common/url/parse-url.js +1 -2
  183. package/src/common/url/parse-url.test.js +110 -0
  184. package/src/common/url/protocol.js +3 -13
  185. package/src/common/url/protocol.test.js +18 -0
  186. package/src/common/util/global-scope.js +1 -2
  187. package/src/common/util/obfuscate.js +2 -2
  188. package/src/common/window/page-visibility.js +1 -1
  189. package/src/common/wrap/index.js +1 -2
  190. package/src/common/wrap/wrap-events.js +5 -5
  191. package/src/common/wrap/wrap-fetch.js +4 -3
  192. package/src/common/wrap/wrap-history.js +6 -3
  193. package/src/common/wrap/wrap-jsonp.js +5 -3
  194. package/src/common/wrap/wrap-mutation.js +6 -3
  195. package/src/common/wrap/wrap-promise.js +7 -6
  196. package/src/common/wrap/wrap-promise.test.js +140 -0
  197. package/src/common/wrap/wrap-raf.js +5 -3
  198. package/src/common/wrap/wrap-timer.js +5 -3
  199. package/src/common/wrap/wrap-xhr.js +4 -3
  200. package/src/features/ajax/instrument/index.js +1 -1
  201. package/src/features/jserrors/instrument/index.js +4 -2
  202. package/src/features/metrics/aggregate/index.js +3 -4
  203. package/src/features/metrics/instrument/index.js +0 -30
  204. package/src/features/metrics/instrument/workers-helper.js +9 -6
  205. package/src/features/page_view_event/aggregate/index.js +15 -6
  206. package/src/features/page_view_timing/aggregate/index.js +36 -25
  207. package/src/features/page_view_timing/long-tasks.js +10 -10
  208. package/src/features/session_trace/aggregate/index.js +15 -12
  209. package/src/features/session_trace/instrument/index.js +3 -2
  210. package/src/features/spa/instrument/index.js +4 -2
  211. package/src/loaders/api/api.js +1 -1
  212. package/dist/cjs/common/constants/environment-variables.js +0 -20
  213. package/dist/cjs/common/wrap/wrap-console.js +0 -54
  214. package/dist/esm/common/constants/environment-variables.js +0 -11
  215. package/dist/esm/common/wrap/wrap-console.js +0 -46
  216. package/dist/types/common/constants/environment-variables.d.ts +0 -4
  217. package/dist/types/common/constants/environment-variables.d.ts.map +0 -1
  218. package/dist/types/common/wrap/wrap-console.d.ts +0 -16
  219. package/dist/types/common/wrap/wrap-console.d.ts.map +0 -1
  220. package/src/common/constants/environment-variables.js +0 -11
  221. package/src/common/wrap/wrap-console.js +0 -47
@@ -0,0 +1,107 @@
1
+ afterEach(() => {
2
+ jest.resetModules();
3
+ jest.clearAllMocks();
4
+ });
5
+ const urlTests = [{
6
+ input: 'http://example.com/path/name?qs=5&a=b',
7
+ expected: {
8
+ hostname: 'example.com',
9
+ pathname: '/path/name',
10
+ protocol: 'http',
11
+ port: '80',
12
+ sameOrigin: false
13
+ }
14
+ }, {
15
+ input: 'http://foo:bar@example.com:8080/path/@name?qs=5&a=b',
16
+ expected: {
17
+ hostname: 'example.com',
18
+ pathname: '/path/@name',
19
+ protocol: 'http',
20
+ port: '8080',
21
+ sameOrigin: false
22
+ }
23
+ }, {
24
+ input: 'https://foo:bar@example.com/path/name?qs=5&a=b',
25
+ expected: {
26
+ hostname: 'example.com',
27
+ pathname: '/path/name',
28
+ protocol: 'https',
29
+ port: '443',
30
+ sameOrigin: false
31
+ }
32
+ }, {
33
+ input: '/path/name?qs=5&a=b',
34
+ expected: {
35
+ hostname: location.hostname,
36
+ pathname: '/path/name',
37
+ protocol: location.protocol.split(':')[0],
38
+ port: '80',
39
+ sameOrigin: true
40
+ }
41
+ }, {
42
+ input: location.protocol + '//' + location.hostname + ':' + location.port + '/path/name?qs=5&a=b',
43
+ expected: {
44
+ hostname: location.hostname,
45
+ pathname: '/path/name',
46
+ protocol: location.protocol.split(':')[0],
47
+ port: '80',
48
+ sameOrigin: true
49
+ }
50
+ }, {
51
+ input: 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==',
52
+ expected: {
53
+ protocol: 'data'
54
+ }
55
+ }];
56
+ test.each(urlTests)('verify url parsing inside browser scope', async _ref => {
57
+ let {
58
+ input,
59
+ expected
60
+ } = _ref;
61
+ jest.doMock('../util/global-scope', () => ({
62
+ __esModule: true,
63
+ isBrowserScope: true,
64
+ globalScope: global
65
+ }));
66
+ const {
67
+ parseUrl
68
+ } = await import('./parse-url');
69
+ expect(parseUrl(input)).toEqual(expected);
70
+ });
71
+ test.each(urlTests)('verify url parsing outside browser scope', async _ref2 => {
72
+ let {
73
+ input,
74
+ expected
75
+ } = _ref2;
76
+ jest.doMock('../util/global-scope', () => ({
77
+ __esModule: true,
78
+ isBrowserScope: false,
79
+ globalScope: global
80
+ }));
81
+ const {
82
+ parseUrl
83
+ } = await import('./parse-url');
84
+ expect(parseUrl(input)).toEqual(expected);
85
+ });
86
+ test('should cache parsed urls', async () => {
87
+ jest.doMock('../util/global-scope', () => ({
88
+ __esModule: true,
89
+ isBrowserScope: true,
90
+ globalScope: global
91
+ }));
92
+ const input = 'http://example.com/';
93
+ const expected = {
94
+ hostname: 'example.com',
95
+ pathname: '/',
96
+ protocol: 'http',
97
+ port: '80',
98
+ sameOrigin: false
99
+ };
100
+ jest.spyOn(document, 'createElement');
101
+ const {
102
+ parseUrl
103
+ } = await import('./parse-url');
104
+ parseUrl(input);
105
+ expect(parseUrl(input)).toEqual(expected);
106
+ expect(document.createElement).toHaveBeenCalledTimes(1);
107
+ });
@@ -2,16 +2,7 @@
2
2
  * Copyright 2020 New Relic Corporation. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import { getGlobalScope } from '../util/global-scope';
6
- export const protocol = {
7
- isFileProtocol: isFileProtocol,
8
- supportabilityMetricSent: false
9
- };
10
- function isFileProtocol() {
11
- let isFile = Boolean(getGlobalScope()?.location?.protocol === 'file:');
12
- if (isFile) {
13
- //metrics.recordSupportability('Generic/FileProtocol/Detected') -- may be implemented later? Probably make sure it's once per window
14
- protocol.supportabilityMetricSent = true;
15
- }
16
- return isFile;
5
+ import { globalScope } from '../util/global-scope';
6
+ export function isFileProtocol() {
7
+ return Boolean(globalScope?.location?.protocol === 'file:');
17
8
  }
@@ -0,0 +1,14 @@
1
+ import { faker } from '@faker-js/faker';
2
+ import { isFileProtocol } from './protocol';
3
+ test('should return true when location url contains file protocol', () => {
4
+ jest.spyOn(window, 'location', 'get').mockReturnValue({
5
+ protocol: 'file:'
6
+ });
7
+ expect(isFileProtocol()).toEqual(true);
8
+ });
9
+ test('should return false when location url does not contains file protocol', () => {
10
+ jest.spyOn(window, 'location', 'get').mockReturnValue({
11
+ protocol: 'http:'
12
+ });
13
+ expect(isFileProtocol()).toEqual(false);
14
+ });
@@ -6,6 +6,6 @@
6
6
  */
7
7
  export function warn(message, secondary) {
8
8
  if (typeof console.warn !== 'function') return;
9
- console.warn(`New Relic: ${message}`);
9
+ console.warn("New Relic: ".concat(message));
10
10
  if (secondary) console.warn(secondary);
11
11
  }
@@ -8,7 +8,7 @@ test('enumerates the object properties', () => {
8
8
  expect(callback).toHaveBeenCalledWith('foo', 'bar');
9
9
  });
10
10
  test('return array of results from callback invocation', () => {
11
- const callback = jest.fn((key, value) => `${key}:${value}`);
11
+ const callback = jest.fn((key, value) => "".concat(key, ":").concat(value));
12
12
  const input = {
13
13
  foo: 'bar',
14
14
  biz: 'baz'
@@ -19,7 +19,7 @@ test('return array of results from callback invocation', () => {
19
19
  expect(result).toContain('biz:baz');
20
20
  });
21
21
  test('does not iterate symbol properties', () => {
22
- const callback = jest.fn((key, value) => `${key}:${value}`);
22
+ const callback = jest.fn((key, value) => "".concat(key, ":").concat(value));
23
23
  const input = {
24
24
  foo: 'bar',
25
25
  [Symbol.for('biz')]: 'baz'
@@ -32,7 +32,7 @@ test('does not iterate inherited properties', () => {
32
32
  F.prototype = {
33
33
  biz: 'baz'
34
34
  };
35
- const callback = jest.fn((key, value) => `${key}:${value}`);
35
+ const callback = jest.fn((key, value) => "".concat(key, ":").concat(value));
36
36
  const input = new F();
37
37
  input.foo = 'bar';
38
38
  const result = mapOwn(input, callback);
@@ -1,6 +1,6 @@
1
1
  import { getConfigurationValue } from '../config/config';
2
2
  import { SharedContext } from '../context/shared-context';
3
- import { protocol } from '../url/protocol';
3
+ import { isFileProtocol } from '../url/protocol';
4
4
  import { warn } from './console';
5
5
  var fileProtocolRule = {
6
6
  regex: /^file:\/\/(.*)/,
@@ -37,7 +37,7 @@ export function getRules(agentIdentifier) {
37
37
  var rules = [];
38
38
  var configRules = getConfigurationValue(agentIdentifier, 'obfuscate') || [];
39
39
  rules = rules.concat(configRules);
40
- if (protocol.isFileProtocol()) rules.push(fileProtocolRule);
40
+ if (isFileProtocol()) rules.push(fileProtocolRule);
41
41
  // could add additional runtime/environment-specific rules here
42
42
 
43
43
  return rules;
@@ -17,7 +17,8 @@ export function subscribeToVisibilityChange(cb) {
17
17
  function handleVisibilityChange() {
18
18
  if (toHiddenOnly) {
19
19
  // trigger cb on change to hidden state only
20
- if (document.visibilityState == 'hidden') cb();else return;
20
+ if (document.visibilityState == 'hidden') cb();
21
+ return;
21
22
  }
22
23
  cb(document.visibilityState);
23
24
  }
@@ -2,7 +2,6 @@
2
2
  * @file Wraps assorted native objects and functions for instrumentation.
3
3
  */
4
4
 
5
- import { wrapConsole } from './wrap-console';
6
5
  import { wrapEvents } from './wrap-events';
7
6
  import { wrapFetch } from './wrap-fetch';
8
7
  import { wrapHistory } from './wrap-history';
@@ -12,4 +11,4 @@ import { wrapPromise } from './wrap-promise';
12
11
  import { wrapRaf } from './wrap-raf';
13
12
  import { wrapTimer } from './wrap-timer';
14
13
  import { wrapXhr } from './wrap-xhr';
15
- export { wrapConsole, wrapEvents, wrapFetch, wrapHistory, wrapJsonP, wrapMutation, wrapPromise, wrapRaf, wrapTimer, wrapXhr };
14
+ export { wrapEvents, wrapFetch, wrapHistory, wrapJsonP, wrapMutation, wrapPromise, wrapRaf, wrapTimer, wrapXhr };
@@ -25,19 +25,16 @@ const REMOVE_EVENT_LISTENER = 'removeEventListener';
25
25
  */
26
26
  export function wrapEvents(sharedEE) {
27
27
  var ee = scopedEE(sharedEE);
28
- if (wrapped[ee.debugId]++)
29
- // Notice if our wrapping never ran yet, the falsey NaN will not early return; but if it has,
30
- {
31
- return ee;
32
- } // then we increment the count to track # of feats using this at runtime.
33
- wrapped[ee.debugId] = 1;
28
+
29
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
30
+ // then we increment the count to track # of feats using this at runtime.
31
+ if (wrapped[ee.debugId]++) return ee;
32
+ wrapped[ee.debugId] = 1; // otherwise, first feature to wrap events
34
33
  var wrapFn = wfn(ee, true);
35
34
 
36
35
  // Guard against instrumenting environments w/o necessary features
37
36
  if ('getPrototypeOf' in Object) {
38
- if (isBrowserScope) {
39
- findEventListenerProtoAndCb(document, wrapNode);
40
- }
37
+ if (isBrowserScope) findEventListenerProtoAndCb(document, wrapNode);
41
38
  findEventListenerProtoAndCb(globalScope, wrapNode);
42
39
  findEventListenerProtoAndCb(XHR.prototype, wrapNode);
43
40
  }
@@ -32,12 +32,12 @@ export function wrapFetch(sharedEE) {
32
32
  if (!(Req && Res && globalScope.fetch)) {
33
33
  return ee;
34
34
  }
35
- if (wrapped[ee.debugId]++)
36
- // Notice if our wrapping never ran yet, the falsey NaN will not early return; but if it has,
37
- {
38
- return ee;
39
- } // then we increment the count to track # of feats using this at runtime.
40
- wrapped[ee.debugId] = 1;
35
+
36
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
37
+ // then we increment the count to track # of feats using this at runtime.
38
+ if (wrapped[ee.debugId]++) return ee;
39
+ wrapped[ee.debugId] = 1; // otherwise, first feature to wrap fetch
40
+
41
41
  bodyMethods.forEach(method => {
42
42
  wrapPromiseMethod(Req[proto], method, bodyPrefix);
43
43
  wrapPromiseMethod(Res[proto], method, bodyPrefix);
@@ -20,12 +20,13 @@ const HISTORY_FNS = ['pushState', 'replaceState'];
20
20
  */
21
21
  export function wrapHistory(sharedEE) {
22
22
  const ee = scopedEE(sharedEE);
23
- if (!isBrowserScope || wrapped[ee.debugId]++)
24
- // Notice if our wrapping never ran yet, the falsey NaN will not early return; but if it has,
25
- {
26
- return ee;
27
- } // then we increment the count to track # of feats using this at runtime. (History API is only avail in browser DOM context.)
28
- wrapped[ee.debugId] = 1;
23
+
24
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
25
+ // then we increment the count to track # of feats using this at runtime. History API is only
26
+ // available in browser DOM context.
27
+ if (!isBrowserScope || wrapped[ee.debugId]++) return ee;
28
+ wrapped[ee.debugId] = 1; // otherwise, first feature to wrap history
29
+
29
30
  var wrapFn = wfn(ee);
30
31
  /*
31
32
  * For objects that will be instantiated more than once, we wrap the object's prototype methods. The history object
@@ -22,12 +22,13 @@ const domInsertMethods = ['appendChild', 'insertBefore', 'replaceChild'];
22
22
  */
23
23
  export function wrapJsonP(sharedEE) {
24
24
  const ee = scopedEE(sharedEE);
25
- if (!isBrowserScope || wrapped[ee.debugId])
26
- // JSONP deals with DOM tags so browser window env is req'd
27
- {
28
- return ee;
29
- }
30
- wrapped[ee.debugId] = true;
25
+
26
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
27
+ // then we increment the count to track # of feats using this at runtime. JSONP deals with DOM
28
+ // tags so browser window env is required.
29
+ if (!isBrowserScope || wrapped[ee.debugId]) return ee;
30
+ wrapped[ee.debugId] = true; // otherwise, first feature to wrap JSONP
31
+
31
32
  var wrapFn = wfn(ee);
32
33
  var CALLBACK_REGEX = /[?&](?:callback|cb)=([^&#]+)/;
33
34
  var PARENT_REGEX = /(.*)\.([^.]+)/;
@@ -21,12 +21,13 @@ const wrapped = {};
21
21
  */
22
22
  export function wrapMutation(sharedEE) {
23
23
  const ee = scopedEE(sharedEE);
24
- if (!isBrowserScope || wrapped[ee.debugId])
25
- // relates to the DOM tree (web env only)
26
- {
27
- return ee;
28
- }
29
- wrapped[ee.debugId] = true;
24
+
25
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
26
+ // then we increment the count to track # of feats using this at runtime. Mutations API is only
27
+ // available in browser DOM context.
28
+ if (!isBrowserScope || wrapped[ee.debugId]) return ee;
29
+ wrapped[ee.debugId] = true; // otherwise, first feature to wrap mutations
30
+
30
31
  var wrapFn = wfn(ee);
31
32
  var OriginalObserver = originals.MO;
32
33
  if (OriginalObserver) {
@@ -22,10 +22,12 @@ const wrapped = {};
22
22
  */
23
23
  export function wrapPromise(sharedEE) {
24
24
  const promiseEE = scopedEE(sharedEE);
25
- if (wrapped[promiseEE.debugId]) {
26
- return promiseEE;
27
- }
28
- wrapped[promiseEE.debugId] = true;
25
+
26
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
27
+ // then we increment the count to track # of feats using this at runtime.
28
+ if (wrapped[promiseEE.debugId]) return promiseEE;
29
+ wrapped[promiseEE.debugId] = true; // otherwise, first feature to wrap promise
30
+
29
31
  var getContext = getOrSetContext;
30
32
  var promiseWrapper = wrapFn(promiseEE);
31
33
  var prevPromiseObj = originals.PR;
@@ -67,8 +69,7 @@ export function wrapPromise(sharedEE) {
67
69
  WrappedPromise[method] = function (subPromises) {
68
70
  // use our own wrapped version of "Promise.all" and ".race" static fns
69
71
  let finalized = false;
70
- subPromises?.forEach(sub => {
71
- // eslint-disable-next-line
72
+ Array.from(subPromises || []).forEach(sub => {
72
73
  this.resolve(sub).then(setNrId(method === 'all'), setNrId(false));
73
74
  });
74
75
  const origFnCallWithThis = prevStaticFn.apply(this, arguments);
@@ -0,0 +1,115 @@
1
+ import { faker } from '@faker-js/faker';
2
+ import { globalScope } from '../util/global-scope';
3
+ import { originals } from '../config/config';
4
+ jest.mock('./wrap-function', () => ({
5
+ __esModule: true,
6
+ createWrapperWithEmitter: jest.fn(() => fn => function () {
7
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
8
+ args[_key] = arguments[_key];
9
+ }
10
+ return fn.apply(null, args);
11
+ })
12
+ }));
13
+ jest.mock('../event-emitter/contextual-ee', () => ({
14
+ __esModule: true,
15
+ getOrSetContext: jest.fn(() => ({})),
16
+ ee: {
17
+ get: jest.fn(name => ({
18
+ debugId: name,
19
+ on: jest.fn(),
20
+ context: jest.fn(() => ({})),
21
+ emit: jest.fn()
22
+ }))
23
+ }
24
+ }));
25
+ jest.mock('../config/config', () => ({
26
+ __esModule: true,
27
+ originals: {}
28
+ }));
29
+ jest.mock('../util/global-scope', () => ({
30
+ __esModule: true,
31
+ globalScope: {
32
+ NREUM: {}
33
+ }
34
+ }));
35
+ let promiseConstructorCalls;
36
+ beforeEach(async () => {
37
+ promiseConstructorCalls = [];
38
+
39
+ // Proxy the global Promise to prevent the wrapping from
40
+ // messing with Jest internal promises
41
+ originals.PR = new Proxy(class extends Promise {}, {
42
+ construct(target, args) {
43
+ promiseConstructorCalls.push(args);
44
+ return Reflect.construct(target, args);
45
+ }
46
+ });
47
+ (await import('./wrap-promise')).wrapPromise();
48
+ });
49
+ afterEach(() => {
50
+ jest.resetModules();
51
+ });
52
+ test('should wrap promise constructor', async () => {
53
+ const promiseInstance = new globalScope.Promise(jest.fn());
54
+ expect(promiseInstance).toBeInstanceOf(Promise);
55
+ expect(promiseConstructorCalls.length).toEqual(1);
56
+ expect(globalScope.Promise.toString()).toMatch(/\[native code\]/);
57
+ expect(globalScope.Promise.name).toEqual('Promise');
58
+ });
59
+ describe('all', () => {
60
+ test('should work with acceptable iterables', async () => {
61
+ const resolveValue = faker.datatype.uuid();
62
+ const customIterable = new CustomIterable([new globalScope.Promise(resolve => resolve(resolveValue))]);
63
+ const arrayIterable = [new globalScope.Promise(resolve => resolve(resolveValue))];
64
+ const setIterable = new Set();
65
+ setIterable.add(new globalScope.Promise(resolve => resolve(resolveValue)));
66
+ await expect(globalScope.Promise.all(customIterable)).resolves.toEqual([resolveValue]);
67
+ await expect(globalScope.Promise.all(arrayIterable)).resolves.toEqual([resolveValue]);
68
+ await expect(globalScope.Promise.all(setIterable)).resolves.toEqual([resolveValue]);
69
+ });
70
+ test.each([null, undefined])('should not try to iterate a non-iterable %s', async input => {
71
+ jest.spyOn(globalScope.Promise, 'resolve');
72
+ await expect(globalScope.Promise.all(input)).rejects.toThrow();
73
+ expect(globalScope.Promise.resolve).not.toHaveBeenCalled();
74
+ });
75
+ });
76
+ describe('race', () => {
77
+ test('should work with acceptable iterables', async () => {
78
+ jest.spyOn(globalScope.Promise, 'resolve');
79
+ const resolveValue = faker.datatype.uuid();
80
+ const customIterable = new CustomIterable([new globalScope.Promise(resolve => resolve(resolveValue))]);
81
+ const arrayIterable = [new globalScope.Promise(resolve => resolve(resolveValue))];
82
+ const setIterable = new Set();
83
+ setIterable.add(new globalScope.Promise(resolve => resolve(resolveValue)));
84
+ await expect(globalScope.Promise.race(customIterable)).resolves.toEqual(resolveValue);
85
+ await expect(globalScope.Promise.race(arrayIterable)).resolves.toEqual(resolveValue);
86
+ await expect(globalScope.Promise.race(setIterable)).resolves.toEqual(resolveValue);
87
+ expect(globalScope.Promise.resolve).toHaveBeenCalled();
88
+ });
89
+ test.each([null, undefined])('should not try to iterate a non-iterable %s', async input => {
90
+ jest.spyOn(globalScope.Promise, 'resolve');
91
+ await expect(globalScope.Promise.race(input)).rejects.toThrow();
92
+ expect(globalScope.Promise.resolve).not.toHaveBeenCalled();
93
+ });
94
+ });
95
+ class CustomIterable {
96
+ #iterables = [];
97
+ constructor(iterables) {
98
+ this.#iterables = iterables;
99
+ }
100
+ [Symbol.iterator]() {
101
+ return {
102
+ index: 0,
103
+ iterables: this.#iterables,
104
+ next() {
105
+ return {
106
+ done: this.index >= this.iterables.length,
107
+ value: this.iterables[this.index++] || undefined
108
+ };
109
+ },
110
+ [Symbol.iterator]() {
111
+ return this;
112
+ }
113
+ };
114
+ }
115
+ }
@@ -21,12 +21,12 @@ const RAF_NAME = 'requestAnimationFrame';
21
21
  */
22
22
  export function wrapRaf(sharedEE) {
23
23
  const ee = scopedEE(sharedEE);
24
- if (!isBrowserScope || wrapped[ee.debugId]++)
25
- // Notice if our wrapping never ran yet, the falsey NaN will not early return; but if it has,
26
- {
27
- return ee;
28
- } // then we increment the count to track # of feats using this at runtime. (RAF is only avail in browser DOM context.)
29
- wrapped[ee.debugId] = 1;
24
+
25
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
26
+ // then we increment the count to track # of feats using this at runtime.
27
+ if (!isBrowserScope || wrapped[ee.debugId]++) return ee;
28
+ wrapped[ee.debugId] = 1; // otherwise, first feature to wrap RAF
29
+
30
30
  var wrapFn = wfn(ee);
31
31
  wrapFn.inPlace(window, [RAF_NAME], 'raf-');
32
32
  ee.on('raf-start', function (args) {
@@ -28,12 +28,12 @@ const TIMER_FNS = [SET_TIMEOUT, 'setImmediate', SET_INTERVAL, CLEAR_TIMEOUT, 'cl
28
28
  //eslint-disable-next-line
29
29
  export function wrapTimer(sharedEE) {
30
30
  const ee = scopedEE(sharedEE);
31
- if (wrapped[ee.debugId]++)
32
- // Notice if our wrapping never ran yet, the falsey NaN will not early return; but if it has,
33
- {
34
- return ee;
35
- } // then we increment the count to track # of feats using this at runtime.
36
- wrapped[ee.debugId] = 1;
31
+
32
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
33
+ // then we increment the count to track # of feats using this at runtime.
34
+ if (wrapped[ee.debugId]++) return ee;
35
+ wrapped[ee.debugId] = 1; // otherwise, first feature to wrap timer
36
+
37
37
  var wrapFn = wfn(ee);
38
38
  wrapFn.inPlace(globalScope, TIMER_FNS.slice(0, 2), SET_TIMEOUT + DASH);
39
39
  wrapFn.inPlace(globalScope, TIMER_FNS.slice(2, 3), SET_INTERVAL + DASH);
@@ -27,12 +27,11 @@ const XHR_PROPS = ['open', 'send']; // these are the specific funcs being wrappe
27
27
  export function wrapXhr(sharedEE) {
28
28
  var baseEE = sharedEE || contextualEE;
29
29
  const ee = scopedEE(baseEE);
30
- if (wrapped[ee.debugId]++)
31
- // Notice if our wrapping never ran yet, the falsey NaN will not early return; but if it has,
32
- {
33
- return ee;
34
- } // then we increment the count to track # of feats using this at runtime.
35
- wrapped[ee.debugId] = 1; // <- otherwise, first feature to wrap XHR
30
+
31
+ // Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
32
+ // then we increment the count to track # of feats using this at runtime.
33
+ if (wrapped[ee.debugId]++) return ee;
34
+ wrapped[ee.debugId] = 1; // otherwise, first feature to wrap XHR
36
35
 
37
36
  wrapEvents(baseEE); // wrap-events patches XMLHttpRequest.prototype.addEventListener for us
38
37
  var wrapFn = wfn(ee);
@@ -55,7 +55,7 @@ export class Aggregate extends AggregateBase {
55
55
  onFinished: onEventsHarvestFinished,
56
56
  getPayload: prepareHarvest
57
57
  }, this);
58
- ee.on(`drain-${this.featureName}`, () => {
58
+ ee.on("drain-".concat(this.featureName), () => {
59
59
  scheduler.startTimer(harvestTimeSeconds);
60
60
  });
61
61
  }
@@ -144,7 +144,7 @@ describe('errors without stack property and with line property', () => {
144
144
  mode: 'sourceline',
145
145
  name: mockError.name,
146
146
  message: mockError.message,
147
- stackString: `${mockError.name}: ${mockError.message}\n at ${sourceURL}:${mockError.line}`
147
+ stackString: "".concat(mockError.name, ": ").concat(mockError.message, "\n at ").concat(sourceURL, ":").concat(mockError.line)
148
148
  }));
149
149
  expect(result.frames.length).toEqual(1);
150
150
  expect(result.frames).toContainEqual(expect.objectContaining({
@@ -170,7 +170,7 @@ describe('errors without stack property and with line property', () => {
170
170
  mode: 'sourceline',
171
171
  name: mockError.name,
172
172
  message: mockError.message,
173
- stackString: `${mockError.name}: ${mockError.message}\n at ${sourceURL}:${mockError.line}:${mockError.column}`
173
+ stackString: "".concat(mockError.name, ": ").concat(mockError.message, "\n at ").concat(sourceURL, ":").concat(mockError.line, ":").concat(mockError.column)
174
174
  }));
175
175
  expect(result.frames.length).toEqual(1);
176
176
  expect(result.frames).toContainEqual(expect.objectContaining({
@@ -191,7 +191,7 @@ describe('errors without stack property and with line property', () => {
191
191
  mode: 'sourceline',
192
192
  name: mockError.name,
193
193
  message: mockError.message,
194
- stackString: `RangeError: ${mockError.message}\n in evaluated code`
194
+ stackString: "RangeError: ".concat(mockError.message, "\n in evaluated code")
195
195
  }));
196
196
  expect(result.frames.length).toEqual(1);
197
197
  expect(result.frames).toContainEqual(expect.objectContaining({
@@ -230,7 +230,7 @@ describe('errors that are messages only or primitives', () => {
230
230
  expect(result).toEqual(expect.objectContaining({
231
231
  mode: 'nameonly',
232
232
  name: mockError.name,
233
- stackString: `${mockError.name}: undefined`,
233
+ stackString: "".concat(mockError.name, ": undefined"),
234
234
  frames: []
235
235
  }));
236
236
  });
@@ -246,7 +246,7 @@ describe('errors that are messages only or primitives', () => {
246
246
  mode: 'nameonly',
247
247
  name: mockError.name,
248
248
  message: mockError.message,
249
- stackString: `${mockError.name}: ${mockError.message}`,
249
+ stackString: "".concat(mockError.name, ": ").concat(mockError.message),
250
250
  frames: []
251
251
  }));
252
252
  });
@@ -23,7 +23,7 @@ describe('formatStackTrace', () => {
23
23
  });
24
24
  test('truncates the middle of the stack lines when more than 100', () => {
25
25
  const input = Array.apply(null, Array(200)).map(() => faker.datatype.uuid());
26
- const expected = input.slice(0, 50).join('\n') + `\n< ...truncated ${input.length - 100} lines... >\n` + input.slice(-50).join('\n');
26
+ const expected = input.slice(0, 50).join('\n') + "\n< ...truncated ".concat(input.length - 100, " lines... >\n") + input.slice(-50).join('\n');
27
27
  const result = formatStackTrace(input);
28
28
  expect(result).toEqual(expected);
29
29
  });
@@ -54,7 +54,7 @@ export class Aggregate extends AggregateBase {
54
54
  });
55
55
 
56
56
  // Don't start harvesting until "drain" for this feat has been called (which currently requires RUM response).
57
- this.ee.on(`drain-${this.featureName}`, () => {
57
+ this.ee.on("drain-".concat(this.featureName), () => {
58
58
  if (!this.blocked) scheduler.startTimer(harvestTimeSeconds); // and only if ingest will accept jserror payloads
59
59
  });
60
60
 
@@ -98,7 +98,7 @@ export class Aggregate extends AggregateBase {
98
98
  }
99
99
  }
100
100
  nameHash(params) {
101
- return stringHashCode(`${params.exceptionClass}_${params.message}_${params.stack_trace || params.browser_stack_hash}`);
101
+ return stringHashCode("".concat(params.exceptionClass, "_").concat(params.message, "_").concat(params.stack_trace || params.browser_stack_hash));
102
102
  }
103
103
  getBucketName(params, customParams) {
104
104
  return this.nameHash(params) + ':' + stringHashCode(stringify(customParams));
@@ -180,7 +180,7 @@ export class Aggregate extends AggregateBase {
180
180
  * the canonical stack trace excludes items like the column number increasing the hit-rate of different errors potentially
181
181
  * bucketing and ultimately resulting in the loss of data in NR1.
182
182
  */
183
- var bucketHash = stringHashCode(`${stackInfo.name}_${stackInfo.message}_${stackInfo.stackString}`);
183
+ var bucketHash = stringHashCode("".concat(stackInfo.name, "_").concat(stackInfo.message, "_").concat(stackInfo.stackString));
184
184
  if (!this.stackReported[bucketHash]) {
185
185
  this.stackReported[bucketHash] = true;
186
186
  params.stack_trace = truncateSize(stackInfo.stackString);
@@ -25,9 +25,9 @@ export class Instrument extends InstrumentBase {
25
25
  // errors that will be the same as caught errors.
26
26
  this.skipNext = 0;
27
27
  try {
28
+ // this try-catch can be removed when IE11 is completely unsupported & gone
28
29
  this.removeOnAbort = new AbortController();
29
- } // this try-catch can be removed when IE11 is completely unsupported & gone
30
- catch (e) {}
30
+ } catch (e) {}
31
31
  const thisInstrument = this;
32
32
  thisInstrument.ee.on('fn-start', function (args, obj, methodName) {
33
33
  if (thisInstrument.abortHandler) thisInstrument.skipNext += 1;