@newrelic/browser-agent 1.253.0 → 1.254.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/CHANGELOG.md +15 -0
- package/README.md +1 -1
- package/dist/cjs/cdn/polyfills.js +2 -1
- package/dist/cjs/common/config/state/runtime.js +4 -1
- 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 +41 -27
- package/dist/cjs/common/event-emitter/contextual-ee.js +24 -22
- package/dist/cjs/common/harvest/harvest.js +5 -1
- package/dist/cjs/common/timing/time-keeper.js +94 -0
- package/dist/cjs/common/util/feature-flags.js +14 -31
- package/dist/cjs/common/wrap/wrap-events.js +2 -2
- package/dist/cjs/common/wrap/wrap-fetch.js +1 -2
- package/dist/cjs/common/wrap/wrap-function.js +7 -5
- package/dist/cjs/common/wrap/wrap-promise.js +1 -2
- package/dist/cjs/features/ajax/aggregate/index.js +7 -13
- package/dist/cjs/features/jserrors/aggregate/index.js +25 -24
- package/dist/cjs/features/metrics/aggregate/index.js +25 -24
- package/dist/cjs/features/page_action/aggregate/index.js +6 -4
- package/dist/cjs/features/page_view_event/aggregate/index.js +22 -2
- package/dist/cjs/features/page_view_timing/aggregate/index.js +15 -16
- package/dist/cjs/features/session_replay/aggregate/index.js +12 -4
- package/dist/cjs/features/session_trace/aggregate/index.js +11 -8
- package/dist/cjs/features/soft_navigations/aggregate/index.js +17 -12
- package/dist/cjs/features/spa/aggregate/index.js +19 -14
- package/dist/cjs/features/utils/aggregate-base.js +18 -5
- package/dist/cjs/features/utils/feature-base.js +2 -0
- package/dist/cjs/features/utils/instrument-base.js +1 -0
- package/dist/cjs/loaders/agent-base.js +2 -7
- package/dist/cjs/loaders/agent.js +4 -4
- package/dist/cjs/loaders/api/api.js +1 -1
- package/dist/cjs/loaders/configure/configure.js +1 -1
- package/dist/cjs/loaders/configure/nonce.cdn.js +13 -0
- package/dist/cjs/loaders/configure/nonce.js +2 -13
- package/dist/cjs/loaders/configure/public-path.cdn.js +16 -0
- package/dist/cjs/loaders/configure/public-path.js +2 -8
- package/dist/esm/cdn/polyfills.js +2 -1
- package/dist/esm/common/config/state/runtime.js +4 -1
- 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 +40 -27
- package/dist/esm/common/event-emitter/contextual-ee.js +24 -22
- package/dist/esm/common/harvest/harvest.js +5 -1
- package/dist/esm/common/timing/time-keeper.js +88 -0
- package/dist/esm/common/util/feature-flags.js +14 -31
- package/dist/esm/common/wrap/wrap-events.js +3 -3
- package/dist/esm/common/wrap/wrap-fetch.js +2 -3
- package/dist/esm/common/wrap/wrap-function.js +5 -4
- package/dist/esm/common/wrap/wrap-promise.js +2 -3
- package/dist/esm/features/ajax/aggregate/index.js +7 -13
- package/dist/esm/features/jserrors/aggregate/index.js +25 -24
- package/dist/esm/features/metrics/aggregate/index.js +25 -24
- package/dist/esm/features/page_action/aggregate/index.js +6 -4
- package/dist/esm/features/page_view_event/aggregate/index.js +22 -2
- package/dist/esm/features/page_view_timing/aggregate/index.js +15 -16
- package/dist/esm/features/session_replay/aggregate/index.js +12 -4
- package/dist/esm/features/session_trace/aggregate/index.js +11 -8
- package/dist/esm/features/soft_navigations/aggregate/index.js +17 -12
- package/dist/esm/features/spa/aggregate/index.js +19 -14
- package/dist/esm/features/utils/aggregate-base.js +18 -5
- package/dist/esm/features/utils/feature-base.js +2 -0
- package/dist/esm/features/utils/instrument-base.js +1 -0
- package/dist/esm/loaders/agent-base.js +2 -7
- package/dist/esm/loaders/agent.js +4 -4
- package/dist/esm/loaders/api/api.js +1 -1
- package/dist/esm/loaders/configure/configure.js +1 -1
- package/dist/esm/loaders/configure/nonce.cdn.js +11 -0
- package/dist/esm/loaders/configure/nonce.js +1 -11
- package/dist/esm/loaders/configure/public-path.cdn.js +9 -0
- package/dist/esm/loaders/configure/public-path.js +2 -8
- package/dist/types/common/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/drain/drain.d.ts +6 -0
- package/dist/types/common/drain/drain.d.ts.map +1 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts +4 -3
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/event-emitter/event-context.d.ts.map +1 -0
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/timing/time-keeper.d.ts +31 -0
- package/dist/types/common/timing/time-keeper.d.ts.map +1 -0
- package/dist/types/common/util/feature-flags.d.ts +11 -2
- package/dist/types/common/util/feature-flags.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 +1 -0
- package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +5 -5
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
- 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 +0 -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.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +0 -2
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +2 -0
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +2 -2
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/feature-base.d.ts +1 -0
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +2 -2
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/configure/public-path.d.ts +1 -1
- package/dist/types/loaders/configure/public-path.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cdn/polyfills.js +1 -0
- package/src/common/config/state/runtime.js +4 -1
- package/src/common/drain/drain.js +41 -28
- package/src/common/event-emitter/contextual-ee.js +29 -31
- package/src/common/harvest/harvest.js +4 -1
- package/src/common/timing/time-keeper.js +96 -0
- package/src/common/util/feature-flags.js +13 -31
- package/src/common/wrap/wrap-events.js +3 -3
- package/src/common/wrap/wrap-fetch.js +2 -3
- package/src/common/wrap/wrap-function.js +6 -4
- package/src/common/wrap/wrap-promise.js +2 -3
- package/src/features/ajax/aggregate/index.js +8 -16
- package/src/features/jserrors/aggregate/index.js +12 -14
- package/src/features/metrics/aggregate/index.js +18 -17
- package/src/features/page_action/aggregate/index.js +6 -5
- package/src/features/page_view_event/aggregate/index.js +18 -2
- package/src/features/page_view_timing/aggregate/index.js +15 -15
- package/src/features/session_replay/aggregate/index.js +10 -4
- package/src/features/session_trace/aggregate/index.js +2 -2
- package/src/features/soft_navigations/aggregate/index.js +14 -12
- package/src/features/spa/aggregate/index.js +15 -13
- package/src/features/utils/aggregate-base.js +16 -8
- package/src/features/utils/feature-base.js +3 -0
- package/src/features/utils/instrument-base.js +1 -0
- package/src/loaders/agent-base.js +2 -7
- package/src/loaders/agent.js +2 -2
- package/src/loaders/api/api.js +1 -1
- package/src/loaders/configure/nonce.cdn.js +12 -0
- package/src/loaders/configure/nonce.js +1 -12
- package/src/loaders/configure/public-path.cdn.js +9 -0
- package/src/loaders/configure/public-path.js +2 -8
- package/dist/cjs/common/context/observation-context-manager.js +0 -56
- package/dist/cjs/loaders/configure/nonce.npm.js +0 -2
- package/dist/cjs/loaders/configure/public-path.npm.js +0 -10
- package/dist/esm/common/context/observation-context-manager.js +0 -49
- package/dist/esm/loaders/configure/nonce.npm.js +0 -1
- package/dist/esm/loaders/configure/public-path.npm.js +0 -3
- package/dist/types/common/context/event-context.d.ts.map +0 -1
- package/dist/types/common/context/observation-context-manager.d.ts +0 -28
- package/dist/types/common/context/observation-context-manager.d.ts.map +0 -1
- package/dist/types/loaders/configure/nonce.npm.d.ts +0 -1
- package/dist/types/loaders/configure/nonce.npm.d.ts.map +0 -1
- package/dist/types/loaders/configure/public-path.npm.d.ts +0 -2
- package/dist/types/loaders/configure/public-path.npm.d.ts.map +0 -1
- package/src/common/context/observation-context-manager.js +0 -55
- package/src/loaders/configure/nonce.npm.js +0 -1
- package/src/loaders/configure/public-path.npm.js +0 -3
- /package/dist/cjs/common/{context → event-emitter}/event-context.js +0 -0
- /package/dist/esm/common/{context → event-emitter}/event-context.js +0 -0
- /package/dist/types/common/{context → event-emitter}/event-context.d.ts +0 -0
- /package/src/common/{context → event-emitter}/event-context.js +0 -0
|
@@ -35,15 +35,6 @@ export class Aggregate extends AggregateBase {
|
|
|
35
35
|
this.timingsSent = []
|
|
36
36
|
this.curSessEndRecorded = false
|
|
37
37
|
|
|
38
|
-
firstPaint.subscribe(this.#handleVitalMetric)
|
|
39
|
-
firstContentfulPaint.subscribe(this.#handleVitalMetric)
|
|
40
|
-
firstInputDelay.subscribe(this.#handleVitalMetric)
|
|
41
|
-
largestContentfulPaint.subscribe(this.#handleVitalMetric)
|
|
42
|
-
interactionToNextPaint.subscribe(this.#handleVitalMetric)
|
|
43
|
-
timeToFirstByte.subscribe(({ entries }) => {
|
|
44
|
-
this.addTiming('load', Math.round(entries[0].loadEventEnd))
|
|
45
|
-
})
|
|
46
|
-
|
|
47
38
|
if (getConfigurationValue(this.agentIdentifier, 'page_view_timing.long_task') === true) longTask.subscribe(this.#handleVitalMetric)
|
|
48
39
|
|
|
49
40
|
/* It's important that CWV api, like "onLCP", is called before this scheduler is initialized. The reason is because they listen to the same
|
|
@@ -54,16 +45,25 @@ export class Aggregate extends AggregateBase {
|
|
|
54
45
|
|
|
55
46
|
const initialHarvestSeconds = getConfigurationValue(this.agentIdentifier, 'page_view_timing.initialHarvestSeconds') || 10
|
|
56
47
|
const harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'page_view_timing.harvestTimeSeconds') || 30
|
|
57
|
-
|
|
58
|
-
this.
|
|
59
|
-
|
|
48
|
+
|
|
49
|
+
this.waitForFlags(([])).then(() => {
|
|
50
|
+
firstPaint.subscribe(this.#handleVitalMetric)
|
|
51
|
+
firstContentfulPaint.subscribe(this.#handleVitalMetric)
|
|
52
|
+
firstInputDelay.subscribe(this.#handleVitalMetric)
|
|
53
|
+
largestContentfulPaint.subscribe(this.#handleVitalMetric)
|
|
54
|
+
interactionToNextPaint.subscribe(this.#handleVitalMetric)
|
|
55
|
+
timeToFirstByte.subscribe(({ entries }) => {
|
|
56
|
+
this.addTiming('load', Math.round(entries[0].loadEventEnd))
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const scheduler = new HarvestScheduler('events', {
|
|
60
60
|
onFinished: (...args) => this.onHarvestFinished(...args),
|
|
61
61
|
getPayload: (...args) => this.prepareHarvest(...args)
|
|
62
62
|
}, this)
|
|
63
|
-
|
|
64
|
-
})
|
|
63
|
+
scheduler.startTimer(harvestTimeSeconds, initialHarvestSeconds)
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
this.drain()
|
|
66
|
+
})
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -27,6 +27,7 @@ import { now } from '../../../common/timing/now'
|
|
|
27
27
|
import { MODE, SESSION_EVENTS, SESSION_EVENT_TYPES } from '../../../common/session/constants'
|
|
28
28
|
import { stringify } from '../../../common/util/stringify'
|
|
29
29
|
import { stylesheetEvaluator } from '../shared/stylesheet-evaluator'
|
|
30
|
+
import { deregisterDrain } from '../../../common/drain/drain'
|
|
30
31
|
|
|
31
32
|
export class Aggregate extends AggregateBase {
|
|
32
33
|
static featureName = FEATURE_NAME
|
|
@@ -116,11 +117,15 @@ export class Aggregate extends AggregateBase {
|
|
|
116
117
|
|
|
117
118
|
this.waitForFlags(['sr']).then(([flagOn]) => {
|
|
118
119
|
this.entitled = flagOn
|
|
119
|
-
if (!this.entitled
|
|
120
|
-
this.
|
|
121
|
-
|
|
120
|
+
if (!this.entitled) {
|
|
121
|
+
deregisterDrain(this.agentIdentifier, this.featureName)
|
|
122
|
+
if (this.recorder?.recording) {
|
|
123
|
+
this.abort(ABORT_REASONS.ENTITLEMENTS)
|
|
124
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/EnabledNotEntitled/Detected'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
125
|
+
}
|
|
122
126
|
return
|
|
123
127
|
}
|
|
128
|
+
this.drain()
|
|
124
129
|
this.initializeRecording(
|
|
125
130
|
(Math.random() * 100) < error_sampling_rate,
|
|
126
131
|
(Math.random() * 100) < sampling_rate
|
|
@@ -141,7 +146,6 @@ export class Aggregate extends AggregateBase {
|
|
|
141
146
|
|
|
142
147
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/SamplingRate/Value', sampling_rate], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
143
148
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/ErrorSamplingRate/Value', error_sampling_rate], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
144
|
-
this.drain()
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
switchToFull () {
|
|
@@ -304,6 +308,7 @@ export class Aggregate extends AggregateBase {
|
|
|
304
308
|
const firstTimestamp = firstEventTimestamp || recorderEvents.cycleTimestamp // from rrweb node || from when the harvest cycle started
|
|
305
309
|
const lastTimestamp = lastEventTimestamp || agentOffset + relativeNow
|
|
306
310
|
|
|
311
|
+
const agentMetadata = agentRuntime.appMetadata?.agents?.[0] || {}
|
|
307
312
|
return {
|
|
308
313
|
qs: {
|
|
309
314
|
browser_monitoring_key: info.licenseKey,
|
|
@@ -314,6 +319,7 @@ export class Aggregate extends AggregateBase {
|
|
|
314
319
|
// this section of attributes must be controllable and stay below the query param padding limit -- see QUERY_PARAM_PADDING
|
|
315
320
|
// if not, data could be lost to truncation at time of sending, potentially breaking parsing / API behavior in NR1
|
|
316
321
|
...(!!this.gzipper && !!this.u8 && { content_encoding: 'gzip' }),
|
|
322
|
+
...(agentMetadata.entityGuid && { entityGuid: agentMetadata.entityGuid }),
|
|
317
323
|
'replay.firstTimestamp': firstTimestamp,
|
|
318
324
|
'replay.firstTimestampOffset': firstTimestamp - agentOffset,
|
|
319
325
|
'replay.lastTimestamp': lastTimestamp,
|
|
@@ -109,7 +109,7 @@ export class Aggregate extends AggregateBase {
|
|
|
109
109
|
if (!sessionEntity) {
|
|
110
110
|
// Since session manager isn't around, do the old Trace behavior of waiting for RUM response to decide feature activation.
|
|
111
111
|
this.isStandalone = true
|
|
112
|
-
|
|
112
|
+
this.waitForFlags((['stn'])).then(([on]) => controlTraceOp(on), this.featureName, this.ee)
|
|
113
113
|
} else {
|
|
114
114
|
registerHandler('errorAgg', () => {
|
|
115
115
|
seenAnError = true
|
|
@@ -151,7 +151,7 @@ export class Aggregate extends AggregateBase {
|
|
|
151
151
|
if (replayMode === MODE.OFF) this.isStandalone = true // without SR, Traces are still subject to old harvest limits
|
|
152
152
|
|
|
153
153
|
let startingMode
|
|
154
|
-
if (traceOn
|
|
154
|
+
if (traceOn) { // CASE: both trace (entitlement+sampling) & replay (entitlement) flags are true from RUM
|
|
155
155
|
startingMode = MODE.FULL // always full capture regardless of replay sampling decisions
|
|
156
156
|
} else { // CASE: trace flag is off, BUT it must still run if replay is on (possibly)
|
|
157
157
|
// At this point, it's possible that 1 or more exception was thrown, in which case just start in full if Replay originally started in ERROR mode.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getConfigurationValue } from '../../../common/config/config'
|
|
2
|
+
import { deregisterDrain } from '../../../common/drain/drain'
|
|
2
3
|
import { handle } from '../../../common/event-emitter/handle'
|
|
3
4
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
4
5
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
@@ -22,13 +23,6 @@ export class Aggregate extends AggregateBase {
|
|
|
22
23
|
this.interactionsAwaitingRetry = []
|
|
23
24
|
this.domObserver = domObserver
|
|
24
25
|
|
|
25
|
-
this.scheduler = new HarvestScheduler('events', {
|
|
26
|
-
onFinished: this.onHarvestFinished.bind(this),
|
|
27
|
-
retryDelay: harvestTimeSeconds,
|
|
28
|
-
onUnload: () => this.interactionInProgress?.done() // return any held ajax or jserr events so they can be sent with EoL harvest
|
|
29
|
-
}, { agentIdentifier, ee: this.ee })
|
|
30
|
-
this.scheduler.harvest.on('events', this.onHarvestStarted.bind(this))
|
|
31
|
-
|
|
32
26
|
this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentIdentifier)
|
|
33
27
|
timeToFirstByte.subscribe(({ entries }) => {
|
|
34
28
|
const loadEventTime = entries[0].loadEventEnd
|
|
@@ -45,8 +39,19 @@ export class Aggregate extends AggregateBase {
|
|
|
45
39
|
|
|
46
40
|
this.blocked = false
|
|
47
41
|
this.waitForFlags(['spa']).then(([spaOn]) => {
|
|
48
|
-
if (spaOn)
|
|
49
|
-
|
|
42
|
+
if (spaOn) {
|
|
43
|
+
this.drain()
|
|
44
|
+
const scheduler = new HarvestScheduler('events', {
|
|
45
|
+
onFinished: this.onHarvestFinished.bind(this),
|
|
46
|
+
retryDelay: harvestTimeSeconds,
|
|
47
|
+
onUnload: () => this.interactionInProgress?.done() // return any held ajax or jserr events so they can be sent with EoL harvest
|
|
48
|
+
}, { agentIdentifier, ee: this.ee })
|
|
49
|
+
scheduler.harvest.on('events', this.onHarvestStarted.bind(this))
|
|
50
|
+
scheduler.startTimer(harvestTimeSeconds, 0)
|
|
51
|
+
} else {
|
|
52
|
+
this.blocked = true // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
|
|
53
|
+
deregisterDrain(this.agentIdentifier, this.featureName)
|
|
54
|
+
}
|
|
50
55
|
})
|
|
51
56
|
|
|
52
57
|
// By default, a complete UI driven interaction requires event -> URL change -> DOM mod in that exact order.
|
|
@@ -61,13 +66,10 @@ export class Aggregate extends AggregateBase {
|
|
|
61
66
|
|
|
62
67
|
registerHandler('ajax', this.#handleAjaxEvent.bind(this), this.featureName, this.ee)
|
|
63
68
|
registerHandler('jserror', this.#handleJserror.bind(this), this.featureName, this.ee)
|
|
64
|
-
|
|
65
|
-
this.drain()
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
onHarvestStarted (options) {
|
|
69
72
|
if (this.interactionsToHarvest.length === 0 || this.blocked) return
|
|
70
|
-
|
|
71
73
|
// The payload depacker takes the first ixn of a payload (if there are multiple ixns) and positively offset the subsequent ixns timestamps by that amount.
|
|
72
74
|
// In order to accurately portray the real start & end times of the 2nd & onward ixns, we hence need to negatively offset their start timestamps with that of the 1st ixn.
|
|
73
75
|
let firstIxnStartTime = 0 // the very 1st ixn does not require any offsetting
|
|
@@ -24,6 +24,7 @@ import { bundleId } from '../../../common/ids/bundle-id'
|
|
|
24
24
|
import { loadedAsDeferredBrowserScript } from '../../../common/constants/runtime'
|
|
25
25
|
import { handle } from '../../../common/event-emitter/handle'
|
|
26
26
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
|
|
27
|
+
import { deregisterDrain } from '../../../common/drain/drain'
|
|
27
28
|
|
|
28
29
|
const {
|
|
29
30
|
FEATURE_NAME, INTERACTION_EVENTS, MAX_TIMER_BUDGET, FN_START, FN_END, CB_START, INTERACTION_API, REMAINING,
|
|
@@ -54,6 +55,7 @@ export class Aggregate extends AggregateBase {
|
|
|
54
55
|
disableSpaFix: (getConfigurationValue(agentIdentifier, 'feature_flags') || []).indexOf('disable-spa-fix') > -1
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
let scheduler
|
|
57
59
|
this.serializer = new Serializer(this)
|
|
58
60
|
|
|
59
61
|
const { state, serializer } = this
|
|
@@ -70,12 +72,6 @@ export class Aggregate extends AggregateBase {
|
|
|
70
72
|
const xhrEE = baseEE.get('xhr')
|
|
71
73
|
const tracerEE = baseEE.get('tracer')
|
|
72
74
|
|
|
73
|
-
const scheduler = new HarvestScheduler('events', {
|
|
74
|
-
onFinished: onHarvestFinished,
|
|
75
|
-
retryDelay: state.harvestTimeSeconds
|
|
76
|
-
}, { agentIdentifier, ee: baseEE })
|
|
77
|
-
scheduler.harvest.on('events', onHarvestStarted)
|
|
78
|
-
|
|
79
75
|
// childTime is used when calculating exclusive time for a cb duration.
|
|
80
76
|
//
|
|
81
77
|
// Exclusive time will be different than the total time for either callbacks
|
|
@@ -108,11 +104,19 @@ export class Aggregate extends AggregateBase {
|
|
|
108
104
|
// | click ending: | 65 | 50 | | | |
|
|
109
105
|
// click fn-end | 70 | 0 | 0 | 70 | 20 |
|
|
110
106
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
this.waitForFlags((['spa'])).then(([spaFlag]) => {
|
|
108
|
+
if (spaFlag) {
|
|
109
|
+
scheduler = this.scheduler = new HarvestScheduler('events', {
|
|
110
|
+
onFinished: onHarvestFinished,
|
|
111
|
+
retryDelay: state.harvestTimeSeconds
|
|
112
|
+
}, { agentIdentifier, ee: baseEE })
|
|
113
|
+
this.scheduler.harvest.on('events', onHarvestStarted)
|
|
114
|
+
this.drain()
|
|
115
|
+
} else {
|
|
116
|
+
this.blocked = true
|
|
117
|
+
deregisterDrain(this.agentIdentifier, this.featureName)
|
|
118
|
+
}
|
|
119
|
+
})
|
|
116
120
|
|
|
117
121
|
if (!isEnabled()) return
|
|
118
122
|
|
|
@@ -740,7 +744,5 @@ export class Aggregate extends AggregateBase {
|
|
|
740
744
|
var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled')
|
|
741
745
|
return enabled !== false
|
|
742
746
|
}
|
|
743
|
-
|
|
744
|
-
this.drain()
|
|
745
747
|
}
|
|
746
748
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { registerHandler } from '../../common/event-emitter/register-handler'
|
|
2
1
|
import { FeatureBase } from './feature-base'
|
|
3
2
|
import { getInfo, isConfigured, getRuntime } from '../../common/config/config'
|
|
4
3
|
import { configure } from '../../loaders/configure/configure'
|
|
5
4
|
import { gosCDN } from '../../common/window/nreum'
|
|
6
5
|
import { drain } from '../../common/drain/drain'
|
|
6
|
+
import { activatedFeatures } from '../../common/util/feature-flags'
|
|
7
7
|
|
|
8
8
|
export class AggregateBase extends FeatureBase {
|
|
9
9
|
constructor (...args) {
|
|
@@ -14,16 +14,24 @@ export class AggregateBase extends FeatureBase {
|
|
|
14
14
|
/**
|
|
15
15
|
* New handler for waiting for multiple flags. Useful when expecting multiple flags simultaneously (ex. stn vs sr)
|
|
16
16
|
* @param {string[]} flagNames
|
|
17
|
-
* @returns
|
|
17
|
+
* @returns {Promise}
|
|
18
18
|
*/
|
|
19
19
|
waitForFlags (flagNames = []) {
|
|
20
|
-
return Promise
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
if (activatedFeatures[this.agentIdentifier]) {
|
|
22
|
+
resolve(buildOutput(activatedFeatures[this.agentIdentifier]))
|
|
23
|
+
} else {
|
|
24
|
+
this.ee.on('rumresp', (resp = {}) => {
|
|
25
|
+
resolve(buildOutput(resp))
|
|
24
26
|
})
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
}
|
|
28
|
+
function buildOutput (ref) {
|
|
29
|
+
return flagNames.map(flag => {
|
|
30
|
+
if (!ref[flag]) return 0
|
|
31
|
+
return ref[flag]
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
})
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
drain () {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ee } from '../../common/event-emitter/contextual-ee'
|
|
2
|
+
import { TimeKeeper } from '../../common/timing/time-keeper'
|
|
2
3
|
|
|
3
4
|
export class FeatureBase {
|
|
4
5
|
constructor (agentIdentifier, aggregator, featureName) {
|
|
@@ -16,5 +17,7 @@ export class FeatureBase {
|
|
|
16
17
|
* @type {boolean}
|
|
17
18
|
*/
|
|
18
19
|
this.blocked = false
|
|
20
|
+
|
|
21
|
+
this.timeKeeper = TimeKeeper.getTimeKeeperByAgentIdentifier(this.agentIdentifier)
|
|
19
22
|
}
|
|
20
23
|
}
|
|
@@ -111,6 +111,7 @@ export class InstrumentBase extends FeatureBase {
|
|
|
111
111
|
// not supported yet but nice to do: "abort" this agent's EE for this feature specifically
|
|
112
112
|
drain(this.agentIdentifier, this.featureName, true)
|
|
113
113
|
loadedSuccessfully(false)
|
|
114
|
+
if (this.ee) this.ee.abort()
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { warn } from '../common/util/console'
|
|
4
4
|
import { SR_EVENT_EMITTER_TYPES } from '../features/session_replay/constants'
|
|
5
|
-
import { ObservationContextManager } from '../common/context/observation-context-manager'
|
|
6
5
|
import { generateRandomHexString } from '../common/ids/unique-id'
|
|
7
|
-
import {
|
|
6
|
+
import { TimeKeeper } from '../common/timing/time-keeper'
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* @typedef {import('./api/interaction-types').InteractionInstance} InteractionInstance
|
|
@@ -12,14 +11,10 @@ import { ee } from '../common/event-emitter/contextual-ee'
|
|
|
12
11
|
|
|
13
12
|
export class AgentBase {
|
|
14
13
|
agentIdentifier
|
|
15
|
-
|
|
14
|
+
timeKeeper = new TimeKeeper(this)
|
|
16
15
|
|
|
17
16
|
constructor (agentIdentifier = generateRandomHexString(16)) {
|
|
18
17
|
this.agentIdentifier = agentIdentifier
|
|
19
|
-
|
|
20
|
-
// Assign the observation context to the event emitter, so it knows how to create observation contexts
|
|
21
|
-
const eventEmitter = ee.get(agentIdentifier)
|
|
22
|
-
eventEmitter.observationContext = this.observationContext
|
|
23
18
|
}
|
|
24
19
|
|
|
25
20
|
/**
|
package/src/loaders/agent.js
CHANGED
|
@@ -85,8 +85,8 @@ export class Agent extends AgentBase {
|
|
|
85
85
|
delete newrelic.initializedAgents[this.agentIdentifier]?.features // GC mem used internally by features
|
|
86
86
|
delete this.sharedAggregator
|
|
87
87
|
// Keep the initialized agent object with its configs for troubleshooting purposes.
|
|
88
|
-
newrelic.ee
|
|
89
|
-
|
|
88
|
+
const thisEE = newrelic.ee.get(this.agentIdentifier)
|
|
89
|
+
thisEE.abort() // set flag and clear backlog
|
|
90
90
|
return false
|
|
91
91
|
}
|
|
92
92
|
}
|
package/src/loaders/api/api.js
CHANGED
|
@@ -198,7 +198,7 @@ export function setAPI (agentIdentifier, forceDrain, runSoftNavOverSpa = false)
|
|
|
198
198
|
drain(agentIdentifier, 'api')
|
|
199
199
|
}).catch(() => {
|
|
200
200
|
warn('Downloading runtime APIs failed...')
|
|
201
|
-
|
|
201
|
+
instanceEE.abort()
|
|
202
202
|
})
|
|
203
203
|
}
|
|
204
204
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* global __webpack_require__ */
|
|
2
|
+
|
|
3
|
+
__webpack_require__.nc = (() => {
|
|
4
|
+
try {
|
|
5
|
+
return document?.currentScript?.nonce
|
|
6
|
+
} catch (ex) {
|
|
7
|
+
// Swallow error and proceed like nonce is not defined
|
|
8
|
+
// This will happen when the agent is loaded in a worker scope
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return ''
|
|
12
|
+
})()
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
__webpack_require__.nc = (() => {
|
|
4
|
-
try {
|
|
5
|
-
return document?.currentScript?.nonce
|
|
6
|
-
} catch (ex) {
|
|
7
|
-
// Swallow error and proceed like nonce is not defined
|
|
8
|
-
// This will happen when the agent is loaded in a worker scope
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return ''
|
|
12
|
-
})()
|
|
1
|
+
// We don't support setting automating the nonce attribute in the npm package
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Set the default CDN or remote for fetching the assets; NPM shouldn't change this var.
|
|
2
|
+
|
|
3
|
+
export const redefinePublicPath = (urlString) => {
|
|
4
|
+
const isOrigin = urlString.startsWith('http')
|
|
5
|
+
// Input is not expected to end in a slash, but webpack concats as-is, so one is inserted.
|
|
6
|
+
urlString += '/'
|
|
7
|
+
// If there's no existing HTTP scheme, the secure protocol is prepended by default.
|
|
8
|
+
__webpack_public_path__ = isOrigin ? urlString : 'https://' + urlString // eslint-disable-line
|
|
9
|
+
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const redefinePublicPath = (urlString) => {
|
|
4
|
-
const isOrigin = urlString.startsWith('http')
|
|
5
|
-
// Input is not expected to end in a slash, but webpack concats as-is, so one is inserted.
|
|
6
|
-
urlString += '/'
|
|
7
|
-
// If there's no existing HTTP scheme, the secure protocol is prepended by default.
|
|
8
|
-
__webpack_public_path__ = isOrigin ? urlString : 'https://' + urlString // eslint-disable-line
|
|
1
|
+
export const redefinePublicPath = () => {
|
|
2
|
+
// We don't support setting public path in webpack via NPM build.
|
|
9
3
|
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.ObservationContextManager = void 0;
|
|
7
|
-
var _nreum = require("../window/nreum");
|
|
8
|
-
var _bundleId = require("../ids/bundle-id");
|
|
9
|
-
var _eventContext = require("./event-context");
|
|
10
|
-
class ObservationContextManager {
|
|
11
|
-
// These IDs are provided for backwards compatibility until the agent is fully updated
|
|
12
|
-
// use the observation context class.
|
|
13
|
-
|
|
14
|
-
static contextId = "nr@context:".concat(_bundleId.bundleId);
|
|
15
|
-
static contextOriginalId = "nr@original:".concat(_bundleId.bundleId);
|
|
16
|
-
static contextWrappedId = "nr@wrapped:".concat(ObservationContextManager.contextId);
|
|
17
|
-
static getObservationContextByAgentIdentifier(agentIdentifier) {
|
|
18
|
-
const nr = (0, _nreum.gosNREUM)();
|
|
19
|
-
return Object.keys(nr?.initializedAgents || {}).indexOf(agentIdentifier) > -1 ? nr.initializedAgents[agentIdentifier].observationContext : undefined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @type {WeakMap<WeakKey, {[key: string]: unknown}>}
|
|
24
|
-
*/
|
|
25
|
-
#observationContext = new WeakMap();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Returns the observation context tied to the supplied construct. If there has been
|
|
29
|
-
* no observation construct created, an empty object is created and stored as the current
|
|
30
|
-
* context.
|
|
31
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
32
|
-
* @return {EventContext} An object of key:value pairs to track as
|
|
33
|
-
* part of the observation
|
|
34
|
-
*/
|
|
35
|
-
getCreateContext(key) {
|
|
36
|
-
if (!this.#observationContext.has(key)) {
|
|
37
|
-
this.#observationContext.set(key, new _eventContext.EventContext());
|
|
38
|
-
}
|
|
39
|
-
return this.#observationContext.get(key);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Set the observation context for an observed construct. If values of the context
|
|
44
|
-
* need to be updated, they should be done so directly on the context. This function
|
|
45
|
-
* is only for the setting of a whole context.
|
|
46
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
47
|
-
* @param value {EventContext} An object of key:value pairs to track as
|
|
48
|
-
* part of the observation
|
|
49
|
-
* @return {EventContext} The updated observation context
|
|
50
|
-
*/
|
|
51
|
-
setContext(key, value) {
|
|
52
|
-
this.#observationContext.set(key, value);
|
|
53
|
-
return this.#observationContext.get(key);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
exports.ObservationContextManager = ObservationContextManager;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.redefinePublicPath = void 0;
|
|
7
|
-
const redefinePublicPath = () => {
|
|
8
|
-
// We don't support setting public path in webpack via NPM build.
|
|
9
|
-
};
|
|
10
|
-
exports.redefinePublicPath = redefinePublicPath;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { gosNREUM } from '../window/nreum';
|
|
2
|
-
import { bundleId } from '../ids/bundle-id';
|
|
3
|
-
import { EventContext } from './event-context';
|
|
4
|
-
export class ObservationContextManager {
|
|
5
|
-
// These IDs are provided for backwards compatibility until the agent is fully updated
|
|
6
|
-
// use the observation context class.
|
|
7
|
-
|
|
8
|
-
static contextId = "nr@context:".concat(bundleId);
|
|
9
|
-
static contextOriginalId = "nr@original:".concat(bundleId);
|
|
10
|
-
static contextWrappedId = "nr@wrapped:".concat(ObservationContextManager.contextId);
|
|
11
|
-
static getObservationContextByAgentIdentifier(agentIdentifier) {
|
|
12
|
-
const nr = gosNREUM();
|
|
13
|
-
return Object.keys(nr?.initializedAgents || {}).indexOf(agentIdentifier) > -1 ? nr.initializedAgents[agentIdentifier].observationContext : undefined;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @type {WeakMap<WeakKey, {[key: string]: unknown}>}
|
|
18
|
-
*/
|
|
19
|
-
#observationContext = new WeakMap();
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Returns the observation context tied to the supplied construct. If there has been
|
|
23
|
-
* no observation construct created, an empty object is created and stored as the current
|
|
24
|
-
* context.
|
|
25
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
26
|
-
* @return {EventContext} An object of key:value pairs to track as
|
|
27
|
-
* part of the observation
|
|
28
|
-
*/
|
|
29
|
-
getCreateContext(key) {
|
|
30
|
-
if (!this.#observationContext.has(key)) {
|
|
31
|
-
this.#observationContext.set(key, new EventContext());
|
|
32
|
-
}
|
|
33
|
-
return this.#observationContext.get(key);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Set the observation context for an observed construct. If values of the context
|
|
38
|
-
* need to be updated, they should be done so directly on the context. This function
|
|
39
|
-
* is only for the setting of a whole context.
|
|
40
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
41
|
-
* @param value {EventContext} An object of key:value pairs to track as
|
|
42
|
-
* part of the observation
|
|
43
|
-
* @return {EventContext} The updated observation context
|
|
44
|
-
*/
|
|
45
|
-
setContext(key, value) {
|
|
46
|
-
this.#observationContext.set(key, value);
|
|
47
|
-
return this.#observationContext.get(key);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// We don't support setting automating the nonce attribute in the npm package
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-context.d.ts","sourceRoot":"","sources":["../../../../src/common/context/event-context.js"],"names":[],"mappings":"AAAA;IACE,4BAEC;IADC,eAA0B;CAE7B"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export class ObservationContextManager {
|
|
2
|
-
static contextId: string;
|
|
3
|
-
static contextOriginalId: string;
|
|
4
|
-
static contextWrappedId: string;
|
|
5
|
-
static getObservationContextByAgentIdentifier(agentIdentifier: any): any;
|
|
6
|
-
/**
|
|
7
|
-
* Returns the observation context tied to the supplied construct. If there has been
|
|
8
|
-
* no observation construct created, an empty object is created and stored as the current
|
|
9
|
-
* context.
|
|
10
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
11
|
-
* @return {EventContext} An object of key:value pairs to track as
|
|
12
|
-
* part of the observation
|
|
13
|
-
*/
|
|
14
|
-
getCreateContext(key: unknown): EventContext;
|
|
15
|
-
/**
|
|
16
|
-
* Set the observation context for an observed construct. If values of the context
|
|
17
|
-
* need to be updated, they should be done so directly on the context. This function
|
|
18
|
-
* is only for the setting of a whole context.
|
|
19
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
20
|
-
* @param value {EventContext} An object of key:value pairs to track as
|
|
21
|
-
* part of the observation
|
|
22
|
-
* @return {EventContext} The updated observation context
|
|
23
|
-
*/
|
|
24
|
-
setContext(key: unknown, value: EventContext): EventContext;
|
|
25
|
-
#private;
|
|
26
|
-
}
|
|
27
|
-
import { EventContext } from './event-context';
|
|
28
|
-
//# sourceMappingURL=observation-context-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observation-context-manager.d.ts","sourceRoot":"","sources":["../../../../src/common/context/observation-context-manager.js"],"names":[],"mappings":"AAIA;IAIE,yBAA2C;IAC3C,iCAAoD;IACpD,gCAA6E;IAE7E,yEAKC;IAOD;;;;;;;OAOG;IACH,sBAJe,OAAO,GACV,YAAY,CASvB;IAED;;;;;;;;OAQG;IACH,gBALe,OAAO,SACL,YAAY,GAEjB,YAAY,CAMvB;;CACF;6BApD4B,iBAAiB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=nonce.npm.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nonce.npm.d.ts","sourceRoot":"","sources":["../../../../src/loaders/configure/nonce.npm.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"public-path.npm.d.ts","sourceRoot":"","sources":["../../../../src/loaders/configure/public-path.npm.js"],"names":[],"mappings":"AAAO,2CAEN"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { gosNREUM } from '../window/nreum'
|
|
2
|
-
import { bundleId } from '../ids/bundle-id'
|
|
3
|
-
import { EventContext } from './event-context'
|
|
4
|
-
|
|
5
|
-
export class ObservationContextManager {
|
|
6
|
-
// These IDs are provided for backwards compatibility until the agent is fully updated
|
|
7
|
-
// use the observation context class.
|
|
8
|
-
|
|
9
|
-
static contextId = `nr@context:${bundleId}`
|
|
10
|
-
static contextOriginalId = `nr@original:${bundleId}`
|
|
11
|
-
static contextWrappedId = `nr@wrapped:${ObservationContextManager.contextId}`
|
|
12
|
-
|
|
13
|
-
static getObservationContextByAgentIdentifier (agentIdentifier) {
|
|
14
|
-
const nr = gosNREUM()
|
|
15
|
-
return Object.keys(nr?.initializedAgents || {}).indexOf(agentIdentifier) > -1
|
|
16
|
-
? nr.initializedAgents[agentIdentifier].observationContext
|
|
17
|
-
: undefined
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @type {WeakMap<WeakKey, {[key: string]: unknown}>}
|
|
22
|
-
*/
|
|
23
|
-
#observationContext = new WeakMap()
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Returns the observation context tied to the supplied construct. If there has been
|
|
27
|
-
* no observation construct created, an empty object is created and stored as the current
|
|
28
|
-
* context.
|
|
29
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
30
|
-
* @return {EventContext} An object of key:value pairs to track as
|
|
31
|
-
* part of the observation
|
|
32
|
-
*/
|
|
33
|
-
getCreateContext (key) {
|
|
34
|
-
if (!this.#observationContext.has(key)) {
|
|
35
|
-
this.#observationContext.set(key, new EventContext())
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return this.#observationContext.get(key)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Set the observation context for an observed construct. If values of the context
|
|
43
|
-
* need to be updated, they should be done so directly on the context. This function
|
|
44
|
-
* is only for the setting of a whole context.
|
|
45
|
-
* @param key {unknown} The construct being observed such as an XHR instance
|
|
46
|
-
* @param value {EventContext} An object of key:value pairs to track as
|
|
47
|
-
* part of the observation
|
|
48
|
-
* @return {EventContext} The updated observation context
|
|
49
|
-
*/
|
|
50
|
-
setContext (key, value) {
|
|
51
|
-
this.#observationContext.set(key, value)
|
|
52
|
-
|
|
53
|
-
return this.#observationContext.get(key)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// We don't support setting automating the nonce attribute in the npm package
|