@newrelic/browser-agent 1.232.0 → 1.233.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.
- package/dist/cjs/cdn/polyfills.js +5 -2
- package/dist/cjs/common/config/state/configurable.js +15 -26
- package/dist/cjs/common/config/state/info.js +1 -1
- package/dist/cjs/common/config/state/init.js +101 -56
- package/dist/cjs/common/config/state/loader-config.js +1 -1
- package/dist/cjs/common/config/state/runtime.js +1 -5
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/drain/drain.js +1 -1
- package/dist/cjs/common/harvest/harvest-scheduler.js +30 -10
- package/dist/cjs/common/harvest/harvest.js +119 -55
- package/dist/cjs/common/session/session-entity.js +35 -22
- package/dist/cjs/common/session/session-entity.test.js +73 -49
- package/dist/cjs/common/timer/interaction-timer.js +9 -12
- package/dist/cjs/common/url/canonicalize-url.js +32 -0
- package/dist/cjs/common/url/canonicalize-url.test.js +42 -0
- package/dist/cjs/common/url/clean-url.js +10 -3
- package/dist/cjs/common/url/protocol.test.js +0 -1
- package/dist/cjs/common/util/feature-flags.js +2 -1
- package/dist/cjs/common/util/global-scope.js +4 -2
- package/dist/cjs/common/util/submit-data.js +57 -18
- package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
- package/dist/cjs/common/wrap/wrap-function.js +1 -3
- package/dist/cjs/common/wrap/wrap-promise.js +1 -1
- package/dist/cjs/features/ajax/aggregate/index.js +2 -2
- package/dist/cjs/features/ajax/instrument/index.js +1 -1
- package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +12 -4
- package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +93 -10
- package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +164 -38
- package/dist/cjs/features/jserrors/aggregate/index.js +29 -48
- package/dist/cjs/features/jserrors/instrument/index.js +0 -2
- package/dist/cjs/features/metrics/aggregate/framework-detection.js +67 -0
- package/dist/cjs/features/metrics/aggregate/framework-detection.test.js +137 -0
- package/dist/cjs/features/metrics/aggregate/index.js +7 -3
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +14 -0
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.test.js +17 -0
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +53 -0
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.test.js +165 -0
- package/dist/cjs/features/page_action/aggregate/index.js +2 -2
- package/dist/cjs/features/page_view_event/aggregate/index.js +6 -3
- package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -2
- package/dist/cjs/features/session_replay/aggregate/index.js +333 -0
- package/dist/cjs/features/session_replay/constants.js +9 -0
- package/dist/cjs/features/session_replay/index.js +12 -0
- package/dist/cjs/features/session_replay/instrument/index.js +29 -0
- package/dist/cjs/features/session_trace/aggregate/index.js +163 -164
- package/dist/cjs/features/session_trace/constants.js +2 -9
- package/dist/cjs/features/session_trace/instrument/index.js +24 -66
- package/dist/cjs/features/spa/aggregate/index.js +2 -2
- package/dist/cjs/features/utils/agent-session.js +1 -2
- package/dist/cjs/features/utils/aggregate-base.js +64 -0
- package/dist/cjs/features/utils/feature-base.js +0 -31
- package/dist/cjs/features/utils/handler-cache.js +3 -4
- package/dist/cjs/features/utils/instrument-base.js +42 -10
- package/dist/cjs/features/utils/{lazy-loader.js → lazy-feature-loader.js} +4 -2
- package/dist/cjs/loaders/agent.js +1 -1
- package/dist/cjs/loaders/api/apiAsync.js +3 -1
- package/dist/cjs/loaders/configure/configure.js +3 -3
- package/dist/cjs/loaders/features/featureDependencies.js +0 -12
- package/dist/cjs/loaders/features/features.js +3 -1
- package/dist/cjs/loaders/micro-agent.js +6 -6
- package/dist/esm/cdn/polyfills.js +5 -2
- package/dist/esm/common/config/state/configurable.js +14 -24
- package/dist/esm/common/config/state/info.js +2 -2
- package/dist/esm/common/config/state/init.js +102 -57
- package/dist/esm/common/config/state/loader-config.js +2 -2
- package/dist/esm/common/config/state/runtime.js +2 -4
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/drain/drain.js +1 -1
- package/dist/esm/common/harvest/harvest-scheduler.js +30 -10
- package/dist/esm/common/harvest/harvest.js +121 -56
- package/dist/esm/common/session/session-entity.js +35 -22
- package/dist/esm/common/session/session-entity.test.js +73 -49
- package/dist/esm/common/timer/interaction-timer.js +9 -12
- package/dist/esm/common/url/canonicalize-url.js +27 -0
- package/dist/esm/common/url/canonicalize-url.test.js +38 -0
- package/dist/esm/common/url/clean-url.js +10 -3
- package/dist/esm/common/url/protocol.test.js +0 -1
- package/dist/esm/common/util/feature-flags.js +2 -1
- package/dist/esm/common/util/global-scope.js +1 -0
- package/dist/esm/common/util/submit-data.js +57 -18
- package/dist/esm/common/wrap/wrap-fetch.js +1 -2
- package/dist/esm/common/wrap/wrap-function.js +1 -2
- package/dist/esm/common/wrap/wrap-promise.js +1 -1
- package/dist/esm/features/ajax/aggregate/index.js +2 -2
- package/dist/esm/features/ajax/instrument/index.js +1 -1
- package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +12 -4
- package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +93 -10
- package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +149 -25
- package/dist/esm/features/jserrors/aggregate/index.js +30 -48
- package/dist/esm/features/jserrors/instrument/index.js +0 -1
- package/dist/esm/features/metrics/aggregate/framework-detection.js +61 -0
- package/dist/esm/features/metrics/aggregate/framework-detection.test.js +133 -0
- package/dist/esm/features/metrics/aggregate/index.js +7 -3
- package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +8 -0
- package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.test.js +15 -0
- package/dist/esm/features/metrics/aggregate/polyfill-detection.js +47 -0
- package/dist/esm/features/metrics/aggregate/polyfill-detection.test.js +163 -0
- package/dist/esm/features/page_action/aggregate/index.js +2 -2
- package/dist/esm/features/page_view_event/aggregate/index.js +6 -3
- package/dist/esm/features/page_view_timing/aggregate/index.js +2 -2
- package/dist/esm/features/session_replay/aggregate/index.js +327 -0
- package/dist/esm/features/session_replay/constants.js +2 -0
- package/dist/esm/features/session_replay/index.js +12 -0
- package/dist/esm/features/session_replay/instrument/index.js +21 -0
- package/dist/esm/features/session_trace/aggregate/index.js +163 -163
- package/dist/esm/features/session_trace/constants.js +1 -5
- package/dist/esm/features/session_trace/instrument/index.js +24 -66
- package/dist/esm/features/spa/aggregate/index.js +2 -2
- package/dist/esm/features/utils/agent-session.js +1 -2
- package/dist/esm/features/utils/aggregate-base.js +57 -0
- package/dist/esm/features/utils/feature-base.js +1 -32
- package/dist/esm/features/utils/handler-cache.js +3 -4
- package/dist/esm/features/utils/instrument-base.js +42 -10
- package/dist/esm/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
- package/dist/esm/loaders/agent.js +1 -1
- package/dist/esm/loaders/api/apiAsync.js +3 -1
- package/dist/esm/loaders/configure/configure.js +3 -3
- package/dist/esm/loaders/features/featureDependencies.js +0 -11
- package/dist/esm/loaders/features/features.js +3 -1
- package/dist/esm/loaders/micro-agent.js +6 -6
- package/dist/types/common/config/state/configurable.d.ts +1 -3
- package/dist/types/common/config/state/configurable.d.ts.map +1 -1
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.d.ts +37 -34
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts +6 -3
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/timer/interaction-timer.d.ts +2 -1
- package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
- package/dist/types/common/url/canonicalize-url.d.ts +9 -0
- package/dist/types/common/url/canonicalize-url.d.ts.map +1 -0
- package/dist/types/common/url/clean-url.d.ts +7 -1
- package/dist/types/common/url/clean-url.d.ts.map +1 -1
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/util/global-scope.d.ts +1 -0
- package/dist/types/common/util/global-scope.d.ts.map +1 -1
- package/dist/types/common/util/submit-data.d.ts +40 -14
- package/dist/types/common/util/submit-data.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts +8 -1
- package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts +48 -19
- package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +14 -5
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -0
- package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +6 -0
- package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +1 -0
- package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +7 -0
- package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +1 -0
- package/dist/types/features/page_action/aggregate/index.d.ts +3 -3
- package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -2
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +96 -0
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -0
- package/dist/types/features/session_replay/constants.d.ts +2 -0
- package/dist/types/features/session_replay/constants.d.ts.map +1 -0
- package/dist/types/features/session_replay/index.d.ts +2 -0
- package/dist/types/features/session_replay/index.d.ts.map +1 -0
- package/dist/types/features/session_replay/instrument/index.d.ts +6 -0
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -0
- package/dist/types/features/session_trace/aggregate/index.d.ts +8 -57
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/constants.d.ts +0 -3
- package/dist/types/features/session_trace/constants.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts +1 -3
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +2 -2
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +11 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -0
- package/dist/types/features/utils/feature-base.d.ts +0 -5
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +3 -1
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/features/utils/{lazy-loader.d.ts → lazy-feature-loader.d.ts} +2 -2
- package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -0
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/features/featureDependencies.d.ts +0 -1
- package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +1 -0
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/package.json +31 -22
- package/src/cdn/polyfills.js +4 -1
- package/src/common/config/state/configurable.js +18 -24
- package/src/common/config/state/info.js +2 -2
- package/src/common/config/state/init.js +62 -28
- package/src/common/config/state/loader-config.js +2 -2
- package/src/common/config/state/runtime.js +2 -4
- package/src/common/drain/drain.js +1 -1
- package/src/common/harvest/harvest-scheduler.js +35 -10
- package/src/common/harvest/harvest.js +73 -50
- package/src/common/session/session-entity.js +34 -23
- package/src/common/session/session-entity.test.js +57 -51
- package/src/common/timer/interaction-timer.js +9 -12
- package/src/common/url/canonicalize-url.js +28 -0
- package/src/common/url/canonicalize-url.test.js +34 -0
- package/src/common/url/clean-url.js +10 -3
- package/src/common/url/protocol.test.js +0 -1
- package/src/common/util/feature-flags.js +2 -2
- package/src/common/util/global-scope.js +2 -0
- package/src/common/util/submit-data.js +28 -17
- package/src/common/wrap/wrap-fetch.js +1 -2
- package/src/common/wrap/wrap-function.js +1 -2
- package/src/common/wrap/wrap-promise.js +1 -1
- package/src/features/ajax/aggregate/index.js +2 -2
- package/src/features/ajax/instrument/index.js +1 -1
- package/src/features/jserrors/aggregate/canonical-function-name.js +12 -4
- package/src/features/jserrors/aggregate/compute-stack-trace.js +85 -11
- package/src/features/jserrors/aggregate/compute-stack-trace.test.js +141 -24
- package/src/features/jserrors/aggregate/index.js +28 -52
- package/src/features/jserrors/instrument/index.js +0 -1
- package/src/features/metrics/aggregate/framework-detection.js +73 -0
- package/src/features/metrics/aggregate/framework-detection.test.js +201 -0
- package/src/features/metrics/aggregate/index.js +8 -3
- package/src/features/metrics/aggregate/polyfill-detection.es5.js +9 -0
- package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +16 -0
- package/src/features/metrics/aggregate/polyfill-detection.js +48 -0
- package/src/features/metrics/aggregate/polyfill-detection.test.js +163 -0
- package/src/features/page_action/aggregate/index.js +2 -2
- package/src/features/page_view_event/aggregate/index.js +5 -5
- package/src/features/page_view_timing/aggregate/index.js +2 -2
- package/src/features/session_replay/aggregate/index.js +314 -0
- package/src/features/session_replay/constants.js +3 -0
- package/src/features/session_replay/index.js +12 -0
- package/src/features/session_replay/instrument/index.js +22 -0
- package/src/features/session_trace/aggregate/index.js +148 -188
- package/src/features/session_trace/constants.js +0 -4
- package/src/features/session_trace/instrument/index.js +17 -69
- package/src/features/spa/aggregate/index.js +2 -2
- package/src/features/utils/agent-session.js +1 -2
- package/src/features/utils/aggregate-base.js +51 -0
- package/src/features/utils/feature-base.js +1 -31
- package/src/features/utils/handler-cache.js +3 -4
- package/src/features/utils/instrument-base.js +40 -8
- package/src/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
- package/src/loaders/agent.js +1 -1
- package/src/loaders/api/apiAsync.js +1 -1
- package/src/loaders/configure/configure.js +4 -3
- package/src/loaders/features/featureDependencies.js +0 -12
- package/src/loaders/features/features.js +3 -1
- package/src/loaders/micro-agent.js +4 -4
- package/dist/cjs/common/metrics/framework-detection.js +0 -72
- package/dist/cjs/common/util/user-agent.js +0 -57
- package/dist/cjs/common/window/supports-performance-observer.js +0 -15
- package/dist/esm/common/metrics/framework-detection.js +0 -66
- package/dist/esm/common/util/user-agent.js +0 -48
- package/dist/esm/common/window/supports-performance-observer.js +0 -9
- package/dist/types/common/metrics/framework-detection.d.ts.map +0 -1
- package/dist/types/common/util/user-agent.d.ts +0 -5
- package/dist/types/common/util/user-agent.d.ts.map +0 -1
- package/dist/types/common/window/supports-performance-observer.d.ts +0 -2
- package/dist/types/common/window/supports-performance-observer.d.ts.map +0 -1
- package/dist/types/features/utils/lazy-loader.d.ts.map +0 -1
- package/src/common/metrics/framework-detection.js +0 -71
- package/src/common/util/user-agent.js +0 -56
- package/src/common/window/supports-performance-observer.js +0 -10
- /package/dist/types/{common/metrics → features/metrics/aggregate}/framework-detection.d.ts +0 -0
|
@@ -41,27 +41,30 @@ describe('constructor', () => {
|
|
|
41
41
|
expect(session).toMatchObject({
|
|
42
42
|
agentIdentifier: expect.any(String),
|
|
43
43
|
key: expect.any(String),
|
|
44
|
-
value: expect.any(String),
|
|
45
44
|
expiresMs: expect.any(Number),
|
|
46
|
-
expiresAt: expect.any(Number),
|
|
47
45
|
expiresTimer: expect.any(Object),
|
|
48
46
|
inactiveMs: expect.any(Number),
|
|
49
|
-
inactiveAt: expect.any(Number),
|
|
50
47
|
inactiveTimer: expect.any(Object),
|
|
51
48
|
isNew: expect.any(Boolean),
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
storage: expect.any(Object),
|
|
50
|
+
state: expect.objectContaining({
|
|
51
|
+
value: expect.any(String),
|
|
52
|
+
expiresAt: expect.any(Number),
|
|
53
|
+
inactiveAt: expect.any(Number),
|
|
54
|
+
sessionReplay: expect.any(Number),
|
|
55
|
+
sessionTraceActive: expect.any(Boolean)
|
|
56
|
+
})
|
|
55
57
|
})
|
|
56
58
|
})
|
|
57
59
|
|
|
58
60
|
test('can use sane defaults', () => {
|
|
59
61
|
const session = new SessionEntity({ agentIdentifier, key })
|
|
60
|
-
expect(session).toEqual(expect.objectContaining({
|
|
62
|
+
expect(session.state).toEqual(expect.objectContaining({
|
|
61
63
|
value: expect.any(String),
|
|
62
64
|
expiresAt: expect.any(Number),
|
|
63
65
|
inactiveAt: expect.any(Number),
|
|
64
|
-
|
|
66
|
+
updatedAt: expect.any(Number),
|
|
67
|
+
sessionReplay: expect.any(Number),
|
|
65
68
|
sessionTraceActive: expect.any(Boolean)
|
|
66
69
|
}))
|
|
67
70
|
})
|
|
@@ -76,47 +79,47 @@ describe('constructor', () => {
|
|
|
76
79
|
const now = Date.now()
|
|
77
80
|
jest.setSystemTime(now)
|
|
78
81
|
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 100 })
|
|
79
|
-
expect(session.expiresAt).toEqual(now + 100)
|
|
82
|
+
expect(session.state.expiresAt).toEqual(now + 100)
|
|
80
83
|
})
|
|
81
84
|
|
|
82
85
|
test('expiresAt is the correct future timestamp - existing session', () => {
|
|
83
86
|
const now = Date.now()
|
|
84
87
|
jest.setSystemTime(now)
|
|
85
|
-
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: now + 5000, inactiveAt: Infinity } })
|
|
88
|
+
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: now + 5000, inactiveAt: Infinity, updatedAt: now, sessionReplay: 0, sessionTraceActive: false, custom: {} } })
|
|
86
89
|
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 100, storageAPI: existingData })
|
|
87
|
-
expect(session.expiresAt).toEqual(now + 5000)
|
|
90
|
+
expect(session.state.expiresAt).toEqual(now + 5000)
|
|
88
91
|
})
|
|
89
92
|
|
|
90
93
|
test('expiresAt never expires if 0', () => {
|
|
91
94
|
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 0 })
|
|
92
|
-
expect(session.expiresAt).toEqual(Infinity)
|
|
95
|
+
expect(session.state.expiresAt).toEqual(Infinity)
|
|
93
96
|
})
|
|
94
97
|
|
|
95
98
|
test('inactiveAt is the correct future timestamp - new session', () => {
|
|
96
99
|
const now = Date.now()
|
|
97
100
|
jest.setSystemTime(now)
|
|
98
101
|
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100 })
|
|
99
|
-
expect(session.inactiveAt).toEqual(now + 100)
|
|
102
|
+
expect(session.state.inactiveAt).toEqual(now + 100)
|
|
100
103
|
})
|
|
101
104
|
|
|
102
105
|
test('inactiveAt is the correct future timestamp - existing session', () => {
|
|
103
106
|
const now = Date.now()
|
|
104
107
|
jest.setSystemTime(now)
|
|
105
|
-
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, inactiveAt: now + 5000, expiresAt: Infinity } })
|
|
108
|
+
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, inactiveAt: now + 5000, expiresAt: Infinity, updatedAt: now, sessionReplay: 0, sessionTraceActive: false, custom: {} } })
|
|
106
109
|
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100, storageAPI: existingData })
|
|
107
|
-
expect(session.inactiveAt).toEqual(now + 5000)
|
|
110
|
+
expect(session.state.inactiveAt).toEqual(now + 5000)
|
|
108
111
|
})
|
|
109
112
|
|
|
110
113
|
test('inactiveAt never expires if 0', () => {
|
|
111
114
|
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 0 })
|
|
112
|
-
expect(session.inactiveAt).toEqual(Infinity)
|
|
115
|
+
expect(session.state.inactiveAt).toEqual(Infinity)
|
|
113
116
|
})
|
|
114
117
|
|
|
115
118
|
test('should handle isNew', () => {
|
|
116
119
|
const newSession = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
117
120
|
expect(newSession.isNew).toBeTruthy()
|
|
118
121
|
|
|
119
|
-
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: Infinity, inactiveAt: Infinity } })
|
|
122
|
+
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: Infinity, inactiveAt: Infinity, updatedAt: Date.now(), sessionReplay: 0, sessionTraceActive: false, custom: {} } })
|
|
120
123
|
const existingSession = new SessionEntity({ agentIdentifier, key, expiresMs: 10, storageAPI })
|
|
121
124
|
expect(existingSession.isNew).toBeFalsy()
|
|
122
125
|
})
|
|
@@ -125,11 +128,12 @@ describe('constructor', () => {
|
|
|
125
128
|
// missing required fields
|
|
126
129
|
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { invalid_fields: true } })
|
|
127
130
|
const session = new SessionEntity({ agentIdentifier, key, storageAPI })
|
|
128
|
-
expect(session).toEqual(expect.objectContaining({
|
|
131
|
+
expect(session.state).toEqual(expect.objectContaining({
|
|
129
132
|
value: expect.any(String),
|
|
130
133
|
expiresAt: expect.any(Number),
|
|
131
134
|
inactiveAt: expect.any(Number),
|
|
132
|
-
|
|
135
|
+
updatedAt: expect.any(Number),
|
|
136
|
+
sessionReplay: expect.any(Number),
|
|
133
137
|
sessionTraceActive: expect.any(Boolean)
|
|
134
138
|
}))
|
|
135
139
|
})
|
|
@@ -139,11 +143,12 @@ describe('constructor', () => {
|
|
|
139
143
|
jest.setSystemTime(now)
|
|
140
144
|
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: now - 100, inactiveAt: Infinity } })
|
|
141
145
|
const session = new SessionEntity({ agentIdentifier, key, storageAPI })
|
|
142
|
-
expect(session).toEqual(expect.objectContaining({
|
|
146
|
+
expect(session.state).toEqual(expect.objectContaining({
|
|
143
147
|
value: expect.any(String),
|
|
144
148
|
expiresAt: expect.any(Number),
|
|
145
149
|
inactiveAt: expect.any(Number),
|
|
146
|
-
|
|
150
|
+
updatedAt: expect.any(Number),
|
|
151
|
+
sessionReplay: expect.any(Number),
|
|
147
152
|
sessionTraceActive: expect.any(Boolean)
|
|
148
153
|
}))
|
|
149
154
|
})
|
|
@@ -153,11 +158,12 @@ describe('constructor', () => {
|
|
|
153
158
|
jest.setSystemTime(now)
|
|
154
159
|
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { value, inactiveAt: now - 100, expiresAt: Infinity } })
|
|
155
160
|
const session = new SessionEntity({ agentIdentifier, key, storageAPI })
|
|
156
|
-
expect(session).toEqual(expect.objectContaining({
|
|
161
|
+
expect(session.state).toEqual(expect.objectContaining({
|
|
157
162
|
value: expect.any(String),
|
|
158
163
|
expiresAt: expect.any(Number),
|
|
159
164
|
inactiveAt: expect.any(Number),
|
|
160
|
-
|
|
165
|
+
updatedAt: expect.any(Number),
|
|
166
|
+
sessionReplay: expect.any(Number),
|
|
161
167
|
sessionTraceActive: expect.any(Boolean)
|
|
162
168
|
}))
|
|
163
169
|
})
|
|
@@ -169,10 +175,10 @@ describe('reset()', () => {
|
|
|
169
175
|
jest.setSystemTime(now)
|
|
170
176
|
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
171
177
|
const sessionVal = session.value
|
|
172
|
-
expect(session.value).toBeTruthy()
|
|
178
|
+
expect(session.state.value).toBeTruthy()
|
|
173
179
|
session.reset()
|
|
174
|
-
expect(session.value).toBeTruthy()
|
|
175
|
-
expect(session.value).not.toEqual(sessionVal)
|
|
180
|
+
expect(session.state.value).toBeTruthy()
|
|
181
|
+
expect(session.state.value).not.toEqual(sessionVal)
|
|
176
182
|
})
|
|
177
183
|
|
|
178
184
|
test('custom data should be wiped on reset', () => {
|
|
@@ -180,12 +186,12 @@ describe('reset()', () => {
|
|
|
180
186
|
jest.setSystemTime(now)
|
|
181
187
|
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
182
188
|
session.syncCustomAttribute('test', 123)
|
|
183
|
-
expect(session.custom.test).toEqual(123)
|
|
189
|
+
expect(session.state.custom.test).toEqual(123)
|
|
184
190
|
expect(session.read().custom.test).toEqual(123)
|
|
185
191
|
|
|
186
192
|
// simulate a timer expiring
|
|
187
193
|
session.reset()
|
|
188
|
-
expect(session.custom?.test).toEqual(undefined)
|
|
194
|
+
expect(session.state.custom?.test).toEqual(undefined)
|
|
189
195
|
expect(session.read()?.custom?.test).toEqual(undefined)
|
|
190
196
|
})
|
|
191
197
|
})
|
|
@@ -199,13 +205,13 @@ describe('read()', () => {
|
|
|
199
205
|
value: expect.any(String),
|
|
200
206
|
expiresAt: expect.any(Number),
|
|
201
207
|
inactiveAt: expect.any(Number),
|
|
202
|
-
|
|
208
|
+
sessionReplay: expect.any(Number),
|
|
203
209
|
sessionTraceActive: expect.any(Boolean)
|
|
204
210
|
}))
|
|
205
211
|
})
|
|
206
212
|
|
|
207
213
|
test('"pre-existing" sessions get data from read()', () => {
|
|
208
|
-
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: Infinity, inactiveAt: Infinity } })
|
|
214
|
+
const storageAPI = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: Infinity, inactiveAt: Infinity, updatedAt: Date.now(), sessionReplay: 0, sessionTraceActive: false, custom: {} } })
|
|
209
215
|
const session = new SessionEntity({ agentIdentifier, key, storageAPI })
|
|
210
216
|
expect(session.isNew).toBeFalsy()
|
|
211
217
|
expect(session.read()).toEqual(expect.objectContaining({
|
|
@@ -219,20 +225,20 @@ describe('read()', () => {
|
|
|
219
225
|
describe('write()', () => {
|
|
220
226
|
test('write() sets data to top-level wrapper', () => {
|
|
221
227
|
const session = new SessionEntity({ agentIdentifier, key })
|
|
222
|
-
expect(session.value).not.toEqual(value)
|
|
223
|
-
expect(session.expiresAt).not.toEqual(Infinity)
|
|
224
|
-
expect(session.inactiveAt).not.toEqual(Infinity)
|
|
225
|
-
session.write({ value, expiresAt: Infinity, inactiveAt: Infinity })
|
|
226
|
-
expect(session.value).toEqual(value)
|
|
227
|
-
expect(session.expiresAt).toEqual(Infinity)
|
|
228
|
-
expect(session.inactiveAt).toEqual(Infinity)
|
|
228
|
+
expect(session.state.value).not.toEqual(value)
|
|
229
|
+
expect(session.state.expiresAt).not.toEqual(Infinity)
|
|
230
|
+
expect(session.state.inactiveAt).not.toEqual(Infinity)
|
|
231
|
+
session.write({ ...session.state, value, expiresAt: Infinity, inactiveAt: Infinity })
|
|
232
|
+
expect(session.state.value).toEqual(value)
|
|
233
|
+
expect(session.state.expiresAt).toEqual(Infinity)
|
|
234
|
+
expect(session.state.inactiveAt).toEqual(Infinity)
|
|
229
235
|
})
|
|
230
236
|
|
|
231
237
|
test('write() sets data that read() can access', () => {
|
|
232
238
|
const now = Date.now()
|
|
233
239
|
jest.setSystemTime(now)
|
|
234
240
|
const session = new SessionEntity({ agentIdentifier, key })
|
|
235
|
-
session.write({ value, expiresAt: now + 100, inactiveAt: now + 100 })
|
|
241
|
+
session.write({ ...session.state, value, expiresAt: now + 100, inactiveAt: now + 100 })
|
|
236
242
|
const read = session.read()
|
|
237
243
|
expect(read.value).toEqual(value)
|
|
238
244
|
expect(read.expiresAt).toEqual(now + 100)
|
|
@@ -259,30 +265,30 @@ describe('refresh()', () => {
|
|
|
259
265
|
const now = Date.now()
|
|
260
266
|
jest.setSystemTime(now)
|
|
261
267
|
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100 })
|
|
262
|
-
expect(session.inactiveAt).toEqual(now + 100)
|
|
268
|
+
expect(session.state.inactiveAt).toEqual(now + 100)
|
|
263
269
|
jest.setSystemTime(now + 1000)
|
|
264
270
|
session.refresh()
|
|
265
|
-
expect(session.inactiveAt).toEqual(now + 100 + 1000)
|
|
271
|
+
expect(session.state.inactiveAt).toEqual(now + 100 + 1000)
|
|
266
272
|
})
|
|
267
273
|
|
|
268
274
|
test('refresh resets the entity if expiresTimer is invalid', () => {
|
|
269
275
|
const now = Date.now()
|
|
270
276
|
jest.setSystemTime(now)
|
|
271
277
|
const session = new SessionEntity({ agentIdentifier, key, value })
|
|
272
|
-
expect(session.value).toEqual(value)
|
|
273
|
-
session.write({ ...session.
|
|
278
|
+
expect(session.state.value).toEqual(value)
|
|
279
|
+
session.write({ ...session.state, expiresAt: now - 1 })
|
|
274
280
|
session.refresh()
|
|
275
|
-
expect(session.value).not.toEqual(value)
|
|
281
|
+
expect(session.state.value).not.toEqual(value)
|
|
276
282
|
})
|
|
277
283
|
|
|
278
284
|
test('refresh resets the entity if inactiveTimer is invalid', () => {
|
|
279
285
|
const now = Date.now()
|
|
280
286
|
jest.setSystemTime(now)
|
|
281
287
|
const session = new SessionEntity({ agentIdentifier, key, value })
|
|
282
|
-
expect(session.value).toEqual(value)
|
|
283
|
-
session.write({ ...session.
|
|
288
|
+
expect(session.state.value).toEqual(value)
|
|
289
|
+
session.write({ ...session.state, inactiveAt: now - 1 })
|
|
284
290
|
session.refresh()
|
|
285
|
-
expect(session.value).not.toEqual(value)
|
|
291
|
+
expect(session.state.value).not.toEqual(value)
|
|
286
292
|
})
|
|
287
293
|
})
|
|
288
294
|
|
|
@@ -292,20 +298,20 @@ describe('syncCustomAttribute()', () => {
|
|
|
292
298
|
|
|
293
299
|
// if custom has never been set, and a "delete" action is triggered, do nothing
|
|
294
300
|
session.syncCustomAttribute('test', null)
|
|
295
|
-
expect(session?.custom?.test).toEqual(undefined)
|
|
301
|
+
expect(session?.state?.custom?.test).toEqual(undefined)
|
|
296
302
|
|
|
297
303
|
session.syncCustomAttribute('test', 1)
|
|
298
|
-
expect(session?.custom?.test).toEqual(1)
|
|
304
|
+
expect(session?.state?.custom?.test).toEqual(1)
|
|
299
305
|
|
|
300
306
|
session.syncCustomAttribute('test', 'string')
|
|
301
|
-
expect(session?.custom?.test).toEqual('string')
|
|
307
|
+
expect(session?.state?.custom?.test).toEqual('string')
|
|
302
308
|
|
|
303
309
|
session.syncCustomAttribute('test', false)
|
|
304
|
-
expect(session?.custom?.test).toEqual(false)
|
|
310
|
+
expect(session?.state?.custom?.test).toEqual(false)
|
|
305
311
|
|
|
306
312
|
// null specifically deletes the object completely
|
|
307
313
|
session.syncCustomAttribute('test', null)
|
|
308
|
-
expect(session?.custom?.test).toEqual(undefined)
|
|
314
|
+
expect(session?.state?.custom?.test).toEqual(undefined)
|
|
309
315
|
})
|
|
310
316
|
|
|
311
317
|
test('Only runs in browser scope', () => {
|
|
@@ -6,8 +6,9 @@ import { isBrowserScope } from '../util/global-scope'
|
|
|
6
6
|
export class InteractionTimer extends Timer {
|
|
7
7
|
constructor (opts, ms) {
|
|
8
8
|
super(opts, ms)
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
9
|
+
this.onPause = typeof opts.onPause === 'function' ? opts.onPause : () => { /* noop */ }
|
|
10
|
+
this.onRefresh = typeof opts.onRefresh === 'function' ? opts.onRefresh : () => { /* noop */ }
|
|
11
|
+
this.onResume = typeof opts.onResume === 'function' ? opts.onResume : () => { /* noop */ }
|
|
11
12
|
|
|
12
13
|
// used by pause/resume
|
|
13
14
|
this.remainingMs = undefined
|
|
@@ -42,7 +43,10 @@ export class InteractionTimer extends Timer {
|
|
|
42
43
|
subscribeToVisibilityChange((state) => {
|
|
43
44
|
if (state === 'hidden') this.pause()
|
|
44
45
|
// vis change --> visible is treated like a new interaction with the page
|
|
45
|
-
else
|
|
46
|
+
else {
|
|
47
|
+
this.onResume()
|
|
48
|
+
this.refresh()
|
|
49
|
+
}
|
|
46
50
|
}, false, false, this.abortController?.signal)
|
|
47
51
|
}
|
|
48
52
|
}
|
|
@@ -53,7 +57,7 @@ export class InteractionTimer extends Timer {
|
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
pause () {
|
|
56
|
-
this.onPause
|
|
60
|
+
this.onPause()
|
|
57
61
|
clearTimeout(this.timer)
|
|
58
62
|
this.remainingMs = this.initialMs - (Date.now() - this.startTimestamp)
|
|
59
63
|
}
|
|
@@ -63,13 +67,6 @@ export class InteractionTimer extends Timer {
|
|
|
63
67
|
this.timer = this.create(cb, ms)
|
|
64
68
|
this.startTimestamp = Date.now()
|
|
65
69
|
this.remainingMs = undefined
|
|
66
|
-
this.onRefresh
|
|
70
|
+
this.onRefresh()
|
|
67
71
|
}
|
|
68
|
-
|
|
69
|
-
// NOT CURRENTLY UTILIZED BY ANYTHING
|
|
70
|
-
// resume () {
|
|
71
|
-
// if (!this.remainingMs || !this.isValid()) return
|
|
72
|
-
// this.timer = this.create(this.cb, this.remainingMs)
|
|
73
|
-
// this.remainingMs = undefined
|
|
74
|
-
// }
|
|
75
72
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { initialLocation } from '../util/global-scope'
|
|
7
|
+
import { cleanURL } from './clean-url'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Converts a URL to its basic form without a query string or fragment. If the resulting URL is the same as the
|
|
11
|
+
* loader's origin URL, returns '<inline>'.
|
|
12
|
+
* @param {string} url - The URL to be canonicalized.
|
|
13
|
+
* @param {string} loaderOriginUrl - The origin URL of the agent loader, used for inline detection.
|
|
14
|
+
* @returns {string} The canonicalized URL, or '<inline>' if the URL matches the loader origin URL.
|
|
15
|
+
*/
|
|
16
|
+
export function canonicalizeUrl (url) {
|
|
17
|
+
if (typeof url !== 'string') return ''
|
|
18
|
+
|
|
19
|
+
const cleanedUrl = cleanURL(url)
|
|
20
|
+
const cleanedGlobalScopeUrl = cleanURL(initialLocation)
|
|
21
|
+
|
|
22
|
+
// If the URL matches the origin URL of the loader, we assume it originated within an inline script.
|
|
23
|
+
if (cleanedUrl === cleanedGlobalScopeUrl) {
|
|
24
|
+
return '<inline>'
|
|
25
|
+
} else {
|
|
26
|
+
return cleanedUrl
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
afterEach(() => {
|
|
2
|
+
jest.resetModules()
|
|
3
|
+
})
|
|
4
|
+
|
|
5
|
+
test.each([null, undefined, 34])('returns empty string when url argument is %s', async (url) => {
|
|
6
|
+
const { canonicalizeUrl } = await import('./canonicalize-url')
|
|
7
|
+
expect(canonicalizeUrl(url)).toEqual('')
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('strips URLs of query strings and fragments', async () => {
|
|
11
|
+
jest.doMock('../util/global-scope', () => ({
|
|
12
|
+
initialLocation: 'http://different-domain.com/'
|
|
13
|
+
}))
|
|
14
|
+
const { canonicalizeUrl } = await import('./canonicalize-url')
|
|
15
|
+
expect(canonicalizeUrl('http://example.com/path?query=string#fragment')).toBe('http://example.com/path')
|
|
16
|
+
expect(canonicalizeUrl('https://www.example.com/path/to/file.html?param=value')).toBe('https://www.example.com/path/to/file.html')
|
|
17
|
+
expect(canonicalizeUrl('https://www.example.com/?param=value#fragment')).toBe('https://www.example.com/')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('returns <inline> when matching the page URL of the loader', async () => {
|
|
21
|
+
jest.doMock('../util/global-scope', () => ({
|
|
22
|
+
initialLocation: 'http://example.com/'
|
|
23
|
+
}))
|
|
24
|
+
const { canonicalizeUrl } = await import('./canonicalize-url')
|
|
25
|
+
expect(canonicalizeUrl('http://example.com/')).toEqual('<inline>')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('does not identify sub-paths of the loader origin as <inline>', async () => {
|
|
29
|
+
jest.doMock('../util/global-scope', () => ({
|
|
30
|
+
initialLocation: 'http://example.com/'
|
|
31
|
+
}))
|
|
32
|
+
const { canonicalizeUrl } = await import('./canonicalize-url')
|
|
33
|
+
expect(canonicalizeUrl('http://example.com/path/to/script.js')).not.toEqual('<inline>')
|
|
34
|
+
})
|
|
@@ -3,8 +3,15 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var patternWithHash = /([^?#]*)[^#]*(#[^?]*|$).*/
|
|
7
|
+
var patternWithoutHash = /([^?#]*)().*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Cleans a URL by removing the query string and fragment (hash portion).
|
|
11
|
+
* @param {string} url - The original URL to be cleaned.
|
|
12
|
+
* @param {boolean} [keepHash=false] - Whether to preserve the hash portion of the URL.
|
|
13
|
+
* @returns {string} The cleaned URL.
|
|
14
|
+
*/
|
|
8
15
|
export function cleanURL (url, keepHash) {
|
|
9
|
-
return url.replace(keepHash ?
|
|
16
|
+
return url.replace(keepHash ? patternWithHash : patternWithoutHash, '$1$2')
|
|
10
17
|
}
|
|
@@ -12,7 +12,8 @@ const bucketMap = {
|
|
|
12
12
|
stn: [FEATURE_NAMES.sessionTrace],
|
|
13
13
|
err: [FEATURE_NAMES.jserrors, FEATURE_NAMES.metrics],
|
|
14
14
|
ins: [FEATURE_NAMES.pageAction],
|
|
15
|
-
spa: [FEATURE_NAMES.spa]
|
|
15
|
+
spa: [FEATURE_NAMES.spa],
|
|
16
|
+
sr: [FEATURE_NAMES.sessionReplay]
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function activateFeatures (flags, agentIdentifier) {
|
|
@@ -28,7 +29,6 @@ export function activateFeatures (flags, agentIdentifier) {
|
|
|
28
29
|
if (activatedFeatures[flag]) {
|
|
29
30
|
return
|
|
30
31
|
}
|
|
31
|
-
|
|
32
32
|
handle('feat-' + flag, [], undefined, bucketMap[flag], sharedEE)
|
|
33
33
|
activatedFeatures[flag] = true
|
|
34
34
|
})
|
|
@@ -20,6 +20,8 @@ export let globalScope = (() => {
|
|
|
20
20
|
throw new Error('New Relic browser agent shutting down due to error: Unable to locate global scope. This is possibly due to code redefining browser global variables like "self" and "window".')
|
|
21
21
|
})()
|
|
22
22
|
|
|
23
|
+
export const initialLocation = '' + globalScope.location
|
|
24
|
+
|
|
23
25
|
/**
|
|
24
26
|
* The below methods are only used for testing and should be removed once the
|
|
25
27
|
* reliant tests are moved to Jest.
|
|
@@ -7,11 +7,13 @@ export const submitData = {}
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Send via JSONP. Do NOT call this function outside of a guaranteed web window environment.
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {string}
|
|
10
|
+
* @param {Object} args - The args
|
|
11
|
+
* @param {string} args.url - The URL to send to
|
|
12
|
+
* @param {string} args.jsonp - The string name of the jsonp cb method
|
|
13
|
+
* @returns {XMLHttpRequest}
|
|
12
14
|
* @returns {Element}
|
|
13
15
|
*/
|
|
14
|
-
submitData.jsonp = function jsonp (url, jsonp) {
|
|
16
|
+
submitData.jsonp = function jsonp ({ url, jsonp }) {
|
|
15
17
|
try {
|
|
16
18
|
if (isWorkerScope) {
|
|
17
19
|
try {
|
|
@@ -19,7 +21,7 @@ submitData.jsonp = function jsonp (url, jsonp) {
|
|
|
19
21
|
} catch (e) {
|
|
20
22
|
// for now theres no other way to execute the callback from ingest without jsonp, or unsafe eval / new Function calls
|
|
21
23
|
// future work needs to be conducted to allow ingest to return a more traditional JSON API-like experience for the entitlement flags
|
|
22
|
-
submitData.xhrGet(url + '&jsonp=' + jsonp)
|
|
24
|
+
submitData.xhrGet({ url: url + '&jsonp=' + jsonp })
|
|
23
25
|
return false
|
|
24
26
|
}
|
|
25
27
|
} else {
|
|
@@ -35,18 +37,21 @@ submitData.jsonp = function jsonp (url, jsonp) {
|
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
submitData.xhrGet = function xhrGet (url) {
|
|
39
|
-
return submitData.xhr(url,
|
|
40
|
+
submitData.xhrGet = function xhrGet ({ url }) {
|
|
41
|
+
return submitData.xhr({ url, sync: false, method: 'GET' })
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* Send via XHR
|
|
44
|
-
* @param {
|
|
45
|
-
* @param {string}
|
|
46
|
-
* @param {
|
|
46
|
+
* @param {Object} args - The args
|
|
47
|
+
* @param {string} args.url - The URL to send to
|
|
48
|
+
* @param {string=} args.body - The Stringified body
|
|
49
|
+
* @param {boolean=} args.sync - Run XHR as Synchronous
|
|
50
|
+
* @param {string=} [args.method=POST] - The XHR method to use
|
|
51
|
+
* @param {{key: string, value: string}[]} [args.headers] - The headers to attach
|
|
47
52
|
* @returns {XMLHttpRequest}
|
|
48
53
|
*/
|
|
49
|
-
submitData.xhr = function xhr (url, body, sync, method = 'POST') {
|
|
54
|
+
submitData.xhr = function xhr ({ url, body, sync, method = 'POST', headers = [{ key: 'content-type', value: 'text/plain' }] }) {
|
|
50
55
|
var request = new XMLHttpRequest()
|
|
51
56
|
|
|
52
57
|
request.open(method, url, !sync)
|
|
@@ -57,7 +62,10 @@ submitData.xhr = function xhr (url, body, sync, method = 'POST') {
|
|
|
57
62
|
// do nothing
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
headers.forEach(header => {
|
|
66
|
+
request.setRequestHeader(header.key, header.value)
|
|
67
|
+
})
|
|
68
|
+
|
|
61
69
|
request.send(body)
|
|
62
70
|
return request
|
|
63
71
|
}
|
|
@@ -71,10 +79,12 @@ submitData.xhr = function xhr (url, body, sync, method = 'POST') {
|
|
|
71
79
|
|
|
72
80
|
/**
|
|
73
81
|
* Send by appending an <img> element to the page. Do NOT call this function outside of a guaranteed web window environment.
|
|
74
|
-
* @param {
|
|
75
|
-
* @
|
|
82
|
+
* @param {Object} args - The args
|
|
83
|
+
* @param {string} args.url - The URL to send to
|
|
84
|
+
* @returns {HTMLImageElement}
|
|
76
85
|
*/
|
|
77
|
-
submitData.img = function img (url) {
|
|
86
|
+
submitData.img = function img ({ url }) {
|
|
87
|
+
console.log('img url', url)
|
|
78
88
|
var element = new Image()
|
|
79
89
|
element.src = url
|
|
80
90
|
return element
|
|
@@ -82,11 +92,12 @@ submitData.img = function img (url) {
|
|
|
82
92
|
|
|
83
93
|
/**
|
|
84
94
|
* Send via sendBeacon. Do NOT call this function outside of a guaranteed web window environment.
|
|
85
|
-
* @param {
|
|
86
|
-
* @param {string}
|
|
95
|
+
* @param {Object} args - The args
|
|
96
|
+
* @param {string} args.url - The URL to send to
|
|
97
|
+
* @param {string=} args.body - The Stringified body
|
|
87
98
|
* @returns {boolean}
|
|
88
99
|
*/
|
|
89
|
-
submitData.beacon = function (url, body) {
|
|
100
|
+
submitData.beacon = function ({ url, body }) {
|
|
90
101
|
// Navigator has to be bound to ensure it does not error in some browsers
|
|
91
102
|
// https://xgwang.me/posts/you-may-not-know-beacon/#it-may-throw-error%2C-be-sure-to-catch
|
|
92
103
|
const send = window.navigator.sendBeacon.bind(window.navigator)
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* This module is used by: ajax, spa.
|
|
8
8
|
*/
|
|
9
9
|
import { ee as baseEE } from '../event-emitter/contextual-ee'
|
|
10
|
-
import slice from 'lodash._slice'
|
|
11
10
|
import { globalScope } from '../util/global-scope'
|
|
12
11
|
import { flag } from './wrap-function'
|
|
13
12
|
|
|
@@ -71,7 +70,7 @@ export function wrapFetch (sharedEE) {
|
|
|
71
70
|
var fn = target[name]
|
|
72
71
|
if (typeof fn === 'function') {
|
|
73
72
|
target[name] = function () {
|
|
74
|
-
var args =
|
|
73
|
+
var args = [...arguments]
|
|
75
74
|
|
|
76
75
|
var ctx = {}
|
|
77
76
|
// we are wrapping args in an array so we can preserve the reference
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { ee } from '../event-emitter/contextual-ee'
|
|
10
|
-
import slice from 'lodash._slice'
|
|
11
10
|
export const flag = 'nr@original'
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -77,7 +76,7 @@ export function createWrapperWithEmitter (emitter, always) {
|
|
|
77
76
|
|
|
78
77
|
try {
|
|
79
78
|
originalThis = this
|
|
80
|
-
args =
|
|
79
|
+
args = [...arguments]
|
|
81
80
|
|
|
82
81
|
if (typeof getContext === 'function') {
|
|
83
82
|
ctx = getContext(args, originalThis)
|
|
@@ -71,7 +71,7 @@ export function wrapPromise (sharedEE) {
|
|
|
71
71
|
WrappedPromise[method] = function (subPromises) { // use our own wrapped version of "Promise.all" and ".race" static fns
|
|
72
72
|
let finalized = false
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
;[...subPromises || []].forEach(sub => {
|
|
75
75
|
this.resolve(sub).then(setNrId(method === 'all'), setNrId(false))
|
|
76
76
|
})
|
|
77
77
|
|
|
@@ -13,9 +13,9 @@ import { FEATURE_NAME } from '../constants'
|
|
|
13
13
|
import { drain } from '../../../common/drain/drain'
|
|
14
14
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
15
15
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
|
|
16
|
-
import {
|
|
16
|
+
import { AggregateBase } from '../../utils/aggregate-base'
|
|
17
17
|
|
|
18
|
-
export class Aggregate extends
|
|
18
|
+
export class Aggregate extends AggregateBase {
|
|
19
19
|
static featureName = FEATURE_NAME
|
|
20
20
|
constructor (agentIdentifier, aggregator) {
|
|
21
21
|
super(agentIdentifier, aggregator, FEATURE_NAME)
|
|
@@ -99,7 +99,7 @@ function subscribeToEvents (agentIdentifier, ee, handler, dt) {
|
|
|
99
99
|
|
|
100
100
|
function onOpenXhrEnd (args, xhr) {
|
|
101
101
|
var loader_config = getLoaderConfig(agentIdentifier)
|
|
102
|
-
if (
|
|
102
|
+
if (loader_config.xpid && this.sameOrigin) {
|
|
103
103
|
xhr.setRequestHeader('X-NewRelic-ID', loader_config.xpid)
|
|
104
104
|
}
|
|
105
105
|
|
|
@@ -3,11 +3,19 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
export function canonicalFunctionName (orig) {
|
|
8
|
-
if (!orig) return
|
|
6
|
+
const canonicalFunctionNameRe = /([a-z0-9]+)$/i
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Given a function name string, extracts only an alphanumeric segment at the end of the string (if one exists).
|
|
10
|
+
* This is useful for stack traces, where functions might not be named (e.g., anonymous, computed).
|
|
11
|
+
*
|
|
12
|
+
* @param {string} functionNameString - The original function name string.
|
|
13
|
+
* @returns {string|undefined} The canonical function name, or undefined if the input is falsy or no alphanumeric segments are found.
|
|
14
|
+
*/
|
|
15
|
+
export function canonicalFunctionName (functionNameString) {
|
|
16
|
+
if (!functionNameString) return
|
|
17
|
+
|
|
18
|
+
const match = functionNameString.match(canonicalFunctionNameRe)
|
|
11
19
|
if (match) return match[1]
|
|
12
20
|
|
|
13
21
|
return
|