@adobe/helix-rum-enhancer 2.44.2 → 2.45.1

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 CHANGED
@@ -1,3 +1,18 @@
1
+ ## [2.45.1](https://github.com/adobe/helix-rum-enhancer/compare/v2.45.0...v2.45.1) (2026-02-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * remove blackbar-only TrustArc detection ([#532](https://github.com/adobe/helix-rum-enhancer/issues/532)) ([7fe4efc](https://github.com/adobe/helix-rum-enhancer/commit/7fe4efc196afd189b6dca73ea7e9eb8307f5936f))
7
+
8
+ # [2.45.0](https://github.com/adobe/helix-rum-enhancer/compare/v2.44.2...v2.45.0) (2026-01-21)
9
+
10
+
11
+ ### Features
12
+
13
+ * track external redirect estimates ([aff3105](https://github.com/adobe/helix-rum-enhancer/commit/aff3105c3676da3c3a0bb8ab2479fb456147d064))
14
+ * track external redirect estimates ([4015e9d](https://github.com/adobe/helix-rum-enhancer/commit/4015e9d0c626ff5b06f13bf1e62db45813446cf1))
15
+
1
16
  ## [2.44.2](https://github.com/adobe/helix-rum-enhancer/compare/v2.44.1...v2.44.2) (2025-11-14)
2
17
 
3
18
 
package/modules/index.js CHANGED
@@ -39,7 +39,7 @@ const CONSENT_PROVIDERS = [
39
39
  },
40
40
  {
41
41
  name: 'trustarc',
42
- detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(hasCookieKey) || document.querySelector('#truste-consent-track, #consent_blackbar'),
42
+ detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(hasCookieKey) || document.querySelector('#truste-consent-track'),
43
43
  },
44
44
  {
45
45
  name: 'usercentrics',
@@ -48,6 +48,10 @@ const CONSENT_PROVIDERS = [
48
48
  ];
49
49
 
50
50
  const getConsentProvider = () => CONSENT_PROVIDERS.find(({ detect }) => detect());
51
+ const bodyChildMO = {
52
+ target: document.body,
53
+ options: { attributes: false, childList: true, subtree: false },
54
+ };
51
55
 
52
56
  const PLUGINS = {
53
57
  cwv: `${pluginBasePath}/cwv.js`,
@@ -57,10 +61,13 @@ const PLUGINS = {
57
61
  url: `${pluginBasePath}/form.js`,
58
62
  when: () => document.querySelector('form'),
59
63
  isBlockDependent: true,
60
- mutationObserverParams: {
61
- target: document.body,
62
- options: { attributes: false, childList: true, subtree: false },
63
- },
64
+ mutationObserverParams: bodyChildMO,
65
+ },
66
+ redirect: {
67
+ url: `${pluginBasePath}/redirect.js`,
68
+ when: ({ perfEntry: pe, urlParameters: usp }) => (
69
+ pe && (usp.get('redirect_from') || pe.redirectCount > 0 || pe.fetchStart > 50)
70
+ ),
64
71
  },
65
72
  video: { url: `${pluginBasePath}/video.js`, when: () => document.querySelector('video'), isBlockDependent: true },
66
73
  webcomponent: {
@@ -73,10 +80,7 @@ const PLUGINS = {
73
80
  consent: {
74
81
  when: () => getConsentProvider(),
75
82
  isBlockDependent: true,
76
- mutationObserverParams: {
77
- target: document.body,
78
- options: { attributes: false, childList: true, subtree: false },
79
- },
83
+ mutationObserverParams: bodyChildMO,
80
84
  },
81
85
  // test: broken-plugin
82
86
  };
@@ -119,14 +123,13 @@ const pluginCache = new Map();
119
123
  function loadPlugin(key, params) {
120
124
  const plugin = PLUGINS[key];
121
125
  const usp = new URLSearchParams(window.location.search);
122
- if (!pluginCache.has(key) && plugin.when && !plugin.when({ urlParameters: usp })) {
126
+ if (!pluginCache.has(key) && plugin.when && !plugin.when({ ...params, urlParameters: usp })) {
123
127
  if (plugin.mutationObserverParams && !plugin.isBeingObserved) {
124
128
  // eslint-disable-next-line no-use-before-define
125
129
  createPluginMO(key, params, usp);
126
130
  }
127
131
  return null;
128
132
  }
129
-
130
133
  if (key === 'consent') {
131
134
  plugin.url = `${pluginBasePath}/${getConsentProvider().name}.js`;
132
135
  }
@@ -200,7 +203,7 @@ function processQueue() {
200
203
 
201
204
  function addNavigationTracking() {
202
205
  // enter checkpoint when referrer is not the current page url
203
- const navigate = (source, type, redirectCount) => {
206
+ const navigate = (source, type, perfEntry) => {
204
207
  const payload = { source, target: document.visibilityState };
205
208
  /* c8 ignore next 13 */
206
209
  // prerendering cannot be tested yet with headless browsers
@@ -225,12 +228,8 @@ function addNavigationTracking() {
225
228
  } else {
226
229
  sampleRUM('enter', payload); // enter site
227
230
  }
228
- const from = new URLSearchParams(window.location.search).get('redirect_from');
229
- if (redirectCount || from) {
230
- sampleRUM('redirect', { source: from, target: redirectCount || 1 });
231
- }
231
+ loadPlugin('redirect', { ...PLUGIN_PARAMETERS, perfEntry });
232
232
  };
233
-
234
233
  const processed = new Set(); // avoid processing duplicate types
235
234
  new PerformanceObserver((list) => list
236
235
  .getEntries()
@@ -239,7 +238,7 @@ function addNavigationTracking() {
239
238
  .map(([e]) => navigate(
240
239
  window.hlx.referrer || document.referrer,
241
240
  e.type,
242
- e.redirectCount,
241
+ e,
243
242
  ))).observe({ type: 'navigation', buffered: true });
244
243
  }
245
244
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-rum-enhancer",
3
- "version": "2.44.2",
3
+ "version": "2.45.1",
4
4
  "description": "Helix RUM Enhancer",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -36,13 +36,13 @@
36
36
  "@adobe/eslint-config-helix": "3.0.13",
37
37
  "@adobe/helix-rum-js": "2.13.6",
38
38
  "@adobe/rollup-plugin-checksum": "1.2.0",
39
- "@eslint/config-helpers": "0.4.1",
39
+ "@eslint/config-helpers": "0.5.1",
40
40
  "@esm-bundle/chai": "4.3.4-fix.0",
41
41
  "@rollup/plugin-babel": "6.1.0",
42
42
  "@semantic-release/changelog": "6.0.3",
43
43
  "@semantic-release/exec": "7.1.0",
44
44
  "@semantic-release/git": "10.0.1",
45
- "@semantic-release/npm": "13.1.1",
45
+ "@semantic-release/npm": "13.1.3",
46
46
  "@web/test-runner": "0.20.2",
47
47
  "@web/test-runner-commands": "0.9.0",
48
48
  "@web/test-runner-junit-reporter": "0.8.0",
@@ -53,16 +53,16 @@
53
53
  "eslint": "9.30.1",
54
54
  "eslint-plugin-header": "3.1.1",
55
55
  "eslint-plugin-import": "2.32.0",
56
- "globals": "16.4.0",
56
+ "globals": "16.5.0",
57
57
  "husky": "9.1.7",
58
58
  "jsdoc-to-markdown": "9.1.3",
59
59
  "junit-report-builder": "5.1.1",
60
- "lint-staged": "16.2.6",
61
- "mocha": "11.7.4",
60
+ "lint-staged": "16.2.7",
61
+ "mocha": "11.7.5",
62
62
  "mocha-multi-reporters": "1.5.1",
63
- "rollup": "4.52.5",
63
+ "rollup": "4.55.2",
64
64
  "rollup-plugin-eslint-bundle": "9.0.0",
65
- "semantic-release": "25.0.1",
65
+ "semantic-release": "25.0.2",
66
66
  "semantic-release-slack-bot": "^4.0.2",
67
67
  "web-vitals": "5.1.0"
68
68
  },
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ /* eslint-env browser */
13
+
14
+ /**
15
+ * Estimate external redirect hops from elapsed ms before fetchStart.
16
+ * Uses a conservative 5-RTT model and subtracts one for the final request.
17
+ * @param {number} ms
18
+ * @return {number}
19
+ */
20
+ function estimateRedirectCount(ms) {
21
+ const rtt = (navigator.connection && navigator.connection.rtt) || 100;
22
+ return Math.max(1, Math.round(ms / (rtt * 5)) - 1);
23
+ }
24
+ export default function addRedirectTracking({ sampleRUM, perfEntry }) {
25
+ try {
26
+ const from = new URLSearchParams(window.location.search).get('redirect_from');
27
+
28
+ let duration;
29
+ let redirectValue;
30
+ if (perfEntry && perfEntry.redirectCount > 0) {
31
+ duration = Math.max(0, Math.round(perfEntry.redirectEnd - perfEntry.redirectStart));
32
+ redirectValue = `${perfEntry.redirectCount}:${duration}`;
33
+ } else if (perfEntry && perfEntry.fetchStart > 50) {
34
+ duration = Math.round(perfEntry.fetchStart);
35
+ redirectValue = `${estimateRedirectCount(duration)}~${duration}`;
36
+ }
37
+
38
+ if (redirectValue || from) {
39
+ const fallback = perfEntry && perfEntry.fetchStart ? Math.round(perfEntry.fetchStart) : 0;
40
+ sampleRUM('redirect', { source: from, target: redirectValue || `1~${fallback}` });
41
+ }
42
+ /* c8 ignore next 3 */
43
+ } catch (e) {
44
+ // silent failure
45
+ }
46
+ }
package/src/index.js CHANGED
@@ -131,7 +131,7 @@
131
131
  detect: () => hasCookieKey('OptanonAlertBoxClosed') || document.querySelector('#onetrust-banner-sdk, #onetrust-pc-sdk')
132
132
  }, {
133
133
  name: 'trustarc',
134
- detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(hasCookieKey) || document.querySelector('#truste-consent-track, #consent_blackbar')
134
+ detect: () => ['notice_gdpr_prefs', 'notice_preferences'].some(hasCookieKey) || document.querySelector('#truste-consent-track')
135
135
  }, {
136
136
  name: 'usercentrics',
137
137
  detect: () => window.localStorage.getItem('uc_gcm') || document.querySelector('#usercentrics-root')
@@ -139,6 +139,14 @@
139
139
  const getConsentProvider = () => CONSENT_PROVIDERS.find(({
140
140
  detect
141
141
  }) => detect());
142
+ const bodyChildMO = {
143
+ target: document.body,
144
+ options: {
145
+ attributes: false,
146
+ childList: true,
147
+ subtree: false
148
+ }
149
+ };
142
150
  const PLUGINS = {
143
151
  cwv: `${pluginBasePath}/cwv.js`,
144
152
  a11y: `${pluginBasePath}/a11y.js`,
@@ -146,14 +154,14 @@
146
154
  url: `${pluginBasePath}/form.js`,
147
155
  when: () => document.querySelector('form'),
148
156
  isBlockDependent: true,
149
- mutationObserverParams: {
150
- target: document.body,
151
- options: {
152
- attributes: false,
153
- childList: true,
154
- subtree: false
155
- }
156
- }
157
+ mutationObserverParams: bodyChildMO
158
+ },
159
+ redirect: {
160
+ url: `${pluginBasePath}/redirect.js`,
161
+ when: ({
162
+ perfEntry: pe,
163
+ urlParameters: usp
164
+ }) => pe && (usp.get('redirect_from') || pe.redirectCount > 0 || pe.fetchStart > 50)
157
165
  },
158
166
  video: {
159
167
  url: `${pluginBasePath}/video.js`,
@@ -174,14 +182,7 @@
174
182
  consent: {
175
183
  when: () => getConsentProvider(),
176
184
  isBlockDependent: true,
177
- mutationObserverParams: {
178
- target: document.body,
179
- options: {
180
- attributes: false,
181
- childList: true,
182
- subtree: false
183
- }
184
- }
185
+ mutationObserverParams: bodyChildMO
185
186
  }
186
187
  };
187
188
  function getIntersectionObserver(checkpoint) {
@@ -217,6 +218,7 @@
217
218
  const plugin = PLUGINS[key];
218
219
  const usp = new URLSearchParams(window.location.search);
219
220
  if (!pluginCache.has(key) && plugin.when && !plugin.when({
221
+ ...params,
220
222
  urlParameters: usp
221
223
  })) {
222
224
  if (plugin.mutationObserverParams && !plugin.isBeingObserved) {
@@ -290,7 +292,7 @@
290
292
  }
291
293
  }
292
294
  function addNavigationTracking() {
293
- const navigate = (source, type, redirectCount) => {
295
+ const navigate = (source, type, perfEntry) => {
294
296
  const payload = {
295
297
  source,
296
298
  target: document.visibilityState
@@ -314,18 +316,15 @@
314
316
  } else {
315
317
  sampleRUM('enter', payload);
316
318
  }
317
- const from = new URLSearchParams(window.location.search).get('redirect_from');
318
- if (redirectCount || from) {
319
- sampleRUM('redirect', {
320
- source: from,
321
- target: redirectCount || 1
322
- });
323
- }
319
+ loadPlugin('redirect', {
320
+ ...PLUGIN_PARAMETERS,
321
+ perfEntry
322
+ });
324
323
  };
325
324
  const processed = new Set();
326
325
  new PerformanceObserver(list => list.getEntries().filter(({
327
326
  type
328
- }) => !processed.has(type)).map(e => [e, processed.add(e.type)]).map(([e]) => navigate(window.hlx.referrer || document.referrer, e.type, e.redirectCount))).observe({
327
+ }) => !processed.has(type)).map(e => [e, processed.add(e.type)]).map(([e]) => navigate(window.hlx.referrer || document.referrer, e.type, e))).observe({
329
328
  type: 'navigation',
330
329
  buffered: true
331
330
  });
package/src/index.md5 CHANGED
@@ -1 +1 @@
1
- 55b1128ec28268801a506ca3ba02e344
1
+ 972077ed1c81b5557acd8b25197a7fef
package/src/index.sri CHANGED
@@ -1 +1 @@
1
- sha384-VosLASRx7DNO3LKUFFVMgcqlBdUzQp8iYtO5V+vKLBOVwf2vWi2qOQYloBWc++NJ
1
+ sha384-hUQpmOlRV0eoZOXPoD5OzkmKdyqkGtpaG2rlC2lev/vmrSH+5isShLouE8dvQtBc
@@ -1 +1 @@
1
- 3ef39d6c29619ddd5c5aaa77d2ce54d7
1
+ 3b10d31bb1dbd2e5281b8de4c9478454
@@ -1 +1 @@
1
- 866b5825b7bdb273170fbab6fa8099bb
1
+ 5a20c1d914d19b130034e4df532b8b4d
@@ -1 +1 @@
1
- 4b5cf6c41be188be11c519f419592e7e
1
+ c00518b019647f564ce00dce9d07c74b
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ function estimateRedirectCount(ms) {
13
+ const rtt = navigator.connection && navigator.connection.rtt || 100;
14
+ return Math.max(1, Math.round(ms / (rtt * 5)) - 1);
15
+ }
16
+ function addRedirectTracking({
17
+ sampleRUM,
18
+ perfEntry
19
+ }) {
20
+ try {
21
+ const from = new URLSearchParams(window.location.search).get('redirect_from');
22
+ let duration;
23
+ let redirectValue;
24
+ if (perfEntry && perfEntry.redirectCount > 0) {
25
+ duration = Math.max(0, Math.round(perfEntry.redirectEnd - perfEntry.redirectStart));
26
+ redirectValue = `${perfEntry.redirectCount}:${duration}`;
27
+ } else if (perfEntry && perfEntry.fetchStart > 50) {
28
+ duration = Math.round(perfEntry.fetchStart);
29
+ redirectValue = `${estimateRedirectCount(duration)}~${duration}`;
30
+ }
31
+ if (redirectValue || from) {
32
+ const fallback = perfEntry && perfEntry.fetchStart ? Math.round(perfEntry.fetchStart) : 0;
33
+ sampleRUM('redirect', {
34
+ source: from,
35
+ target: redirectValue || `1~${fallback}`
36
+ });
37
+ }
38
+ } catch (e) {}
39
+ }
40
+
41
+ export { addRedirectTracking as default };
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ function estimateRedirectCount(ms) {
13
+ const rtt = navigator.connection && navigator.connection.rtt || 100;
14
+ return Math.max(1, Math.round(ms / (rtt * 5)) - 1);
15
+ }
16
+ function addRedirectTracking({
17
+ sampleRUM,
18
+ perfEntry
19
+ }) {
20
+ try {
21
+ const from = new URLSearchParams(window.location.search).get('redirect_from');
22
+ let duration;
23
+ let redirectValue;
24
+ if (perfEntry && perfEntry.redirectCount > 0) {
25
+ duration = Math.max(0, Math.round(perfEntry.redirectEnd - perfEntry.redirectStart));
26
+ redirectValue = `${perfEntry.redirectCount}:${duration}`;
27
+ } else if (perfEntry && perfEntry.fetchStart > 50) {
28
+ duration = Math.round(perfEntry.fetchStart);
29
+ redirectValue = `${estimateRedirectCount(duration)}~${duration}`;
30
+ }
31
+ if (redirectValue || from) {
32
+ const fallback = perfEntry && perfEntry.fetchStart ? Math.round(perfEntry.fetchStart) : 0;
33
+ sampleRUM('redirect', {
34
+ source: from,
35
+ target: redirectValue || `1~${fallback}`
36
+ });
37
+ }
38
+ } catch (e) {}
39
+ }
40
+
41
+ export { addRedirectTracking as default };
42
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXJlY3QubWFwLmpzIiwic291cmNlcyI6WyIuLi8uLi9wbHVnaW5zL3JlZGlyZWN0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgMjAyNSBBZG9iZS4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIFRoaXMgZmlsZSBpcyBsaWNlbnNlZCB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5XG4gKiBvZiB0aGUgTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyXG4gKiB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBSRVBSRVNFTlRBVElPTlNcbiAqIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZVxuICogZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuLyogZXNsaW50LWVudiBicm93c2VyICovXG5cbi8qKlxuICogRXN0aW1hdGUgZXh0ZXJuYWwgcmVkaXJlY3QgaG9wcyBmcm9tIGVsYXBzZWQgbXMgYmVmb3JlIGZldGNoU3RhcnQuXG4gKiBVc2VzIGEgY29uc2VydmF0aXZlIDUtUlRUIG1vZGVsIGFuZCBzdWJ0cmFjdHMgb25lIGZvciB0aGUgZmluYWwgcmVxdWVzdC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtc1xuICogQHJldHVybiB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiBlc3RpbWF0ZVJlZGlyZWN0Q291bnQobXMpIHtcbiAgY29uc3QgcnR0ID0gKG5hdmlnYXRvci5jb25uZWN0aW9uICYmIG5hdmlnYXRvci5jb25uZWN0aW9uLnJ0dCkgfHwgMTAwO1xuICByZXR1cm4gTWF0aC5tYXgoMSwgTWF0aC5yb3VuZChtcyAvIChydHQgKiA1KSkgLSAxKTtcbn1cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGFkZFJlZGlyZWN0VHJhY2tpbmcoeyBzYW1wbGVSVU0sIHBlcmZFbnRyeSB9KSB7XG4gIHRyeSB7XG4gICAgY29uc3QgZnJvbSA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCkuZ2V0KCdyZWRpcmVjdF9mcm9tJyk7XG5cbiAgICBsZXQgZHVyYXRpb247XG4gICAgbGV0IHJlZGlyZWN0VmFsdWU7XG4gICAgaWYgKHBlcmZFbnRyeSAmJiBwZXJmRW50cnkucmVkaXJlY3RDb3VudCA+IDApIHtcbiAgICAgIGR1cmF0aW9uID0gTWF0aC5tYXgoMCwgTWF0aC5yb3VuZChwZXJmRW50cnkucmVkaXJlY3RFbmQgLSBwZXJmRW50cnkucmVkaXJlY3RTdGFydCkpO1xuICAgICAgcmVkaXJlY3RWYWx1ZSA9IGAke3BlcmZFbnRyeS5yZWRpcmVjdENvdW50fToke2R1cmF0aW9ufWA7XG4gICAgfSBlbHNlIGlmIChwZXJmRW50cnkgJiYgcGVyZkVudHJ5LmZldGNoU3RhcnQgPiA1MCkge1xuICAgICAgZHVyYXRpb24gPSBNYXRoLnJvdW5kKHBlcmZFbnRyeS5mZXRjaFN0YXJ0KTtcbiAgICAgIHJlZGlyZWN0VmFsdWUgPSBgJHtlc3RpbWF0ZVJlZGlyZWN0Q291bnQoZHVyYXRpb24pfX4ke2R1cmF0aW9ufWA7XG4gICAgfVxuXG4gICAgaWYgKHJlZGlyZWN0VmFsdWUgfHwgZnJvbSkge1xuICAgICAgY29uc3QgZmFsbGJhY2sgPSBwZXJmRW50cnkgJiYgcGVyZkVudHJ5LmZldGNoU3RhcnQgPyBNYXRoLnJvdW5kKHBlcmZFbnRyeS5mZXRjaFN0YXJ0KSA6IDA7XG4gICAgICBzYW1wbGVSVU0oJ3JlZGlyZWN0JywgeyBzb3VyY2U6IGZyb20sIHRhcmdldDogcmVkaXJlY3RWYWx1ZSB8fCBgMX4ke2ZhbGxiYWNrfWAgfSk7XG4gICAgfVxuICAgIC8qIGM4IGlnbm9yZSBuZXh0IDMgKi9cbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIHNpbGVudCBmYWlsdXJlXG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJlc3RpbWF0ZVJlZGlyZWN0Q291bnQiLCJtcyIsInJ0dCIsIm5hdmlnYXRvciIsImNvbm5lY3Rpb24iLCJNYXRoIiwibWF4Iiwicm91bmQiLCJhZGRSZWRpcmVjdFRyYWNraW5nIiwic2FtcGxlUlVNIiwicGVyZkVudHJ5IiwiZnJvbSIsIlVSTFNlYXJjaFBhcmFtcyIsIndpbmRvdyIsImxvY2F0aW9uIiwic2VhcmNoIiwiZ2V0IiwiZHVyYXRpb24iLCJyZWRpcmVjdFZhbHVlIiwicmVkaXJlY3RDb3VudCIsInJlZGlyZWN0RW5kIiwicmVkaXJlY3RTdGFydCIsImZldGNoU3RhcnQiLCJmYWxsYmFjayIsInNvdXJjZSIsInRhcmdldCIsImUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBbUJBLFNBQVNBLHFCQUFxQkEsQ0FBQ0MsRUFBRSxFQUFFO0FBQ2pDLEVBQUEsTUFBTUMsR0FBRyxHQUFJQyxTQUFTLENBQUNDLFVBQVUsSUFBSUQsU0FBUyxDQUFDQyxVQUFVLENBQUNGLEdBQUcsSUFBSyxHQUFHO0FBQ3JFLEVBQUEsT0FBT0csSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQyxFQUFFRCxJQUFJLENBQUNFLEtBQUssQ0FBQ04sRUFBRSxJQUFJQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDcEQ7QUFDZSxTQUFTTSxtQkFBbUJBLENBQUM7RUFBRUMsU0FBUztBQUFFQyxFQUFBQTtBQUFVLENBQUMsRUFBRTtFQUNwRSxJQUFJO0FBQ0YsSUFBQSxNQUFNQyxJQUFJLEdBQUcsSUFBSUMsZUFBZSxDQUFDQyxNQUFNLENBQUNDLFFBQVEsQ0FBQ0MsTUFBTSxDQUFDLENBQUNDLEdBQUcsQ0FBQyxlQUFlLENBQUM7QUFFN0UsSUFBQSxJQUFJQyxRQUFRO0FBQ1osSUFBQSxJQUFJQyxhQUFhO0FBQ2pCLElBQUEsSUFBSVIsU0FBUyxJQUFJQSxTQUFTLENBQUNTLGFBQWEsR0FBRyxDQUFDLEVBQUU7QUFDNUNGLE1BQUFBLFFBQVEsR0FBR1osSUFBSSxDQUFDQyxHQUFHLENBQUMsQ0FBQyxFQUFFRCxJQUFJLENBQUNFLEtBQUssQ0FBQ0csU0FBUyxDQUFDVSxXQUFXLEdBQUdWLFNBQVMsQ0FBQ1csYUFBYSxDQUFDLENBQUM7QUFDbkZILE1BQUFBLGFBQWEsR0FBRyxDQUFBLEVBQUdSLFNBQVMsQ0FBQ1MsYUFBYSxDQUFBLENBQUEsRUFBSUYsUUFBUSxDQUFBLENBQUU7SUFDMUQsQ0FBQyxNQUFNLElBQUlQLFNBQVMsSUFBSUEsU0FBUyxDQUFDWSxVQUFVLEdBQUcsRUFBRSxFQUFFO01BQ2pETCxRQUFRLEdBQUdaLElBQUksQ0FBQ0UsS0FBSyxDQUFDRyxTQUFTLENBQUNZLFVBQVUsQ0FBQztNQUMzQ0osYUFBYSxHQUFHLEdBQUdsQixxQkFBcUIsQ0FBQ2lCLFFBQVEsQ0FBQyxDQUFBLENBQUEsRUFBSUEsUUFBUSxDQUFBLENBQUU7QUFDbEUsSUFBQTtJQUVBLElBQUlDLGFBQWEsSUFBSVAsSUFBSSxFQUFFO0FBQ3pCLE1BQUEsTUFBTVksUUFBUSxHQUFHYixTQUFTLElBQUlBLFNBQVMsQ0FBQ1ksVUFBVSxHQUFHakIsSUFBSSxDQUFDRSxLQUFLLENBQUNHLFNBQVMsQ0FBQ1ksVUFBVSxDQUFDLEdBQUcsQ0FBQztNQUN6RmIsU0FBUyxDQUFDLFVBQVUsRUFBRTtBQUFFZSxRQUFBQSxNQUFNLEVBQUViLElBQUk7QUFBRWMsUUFBQUEsTUFBTSxFQUFFUCxhQUFhLElBQUksQ0FBQSxFQUFBLEVBQUtLLFFBQVEsQ0FBQTtBQUFHLE9BQUMsQ0FBQztBQUNuRixJQUFBO0FBRUYsRUFBQSxDQUFDLENBQUMsT0FBT0csQ0FBQyxFQUFFLENBRVo7QUFDRjs7OzsifQ==
@@ -0,0 +1 @@
1
+ f7be09c5b13268f51780ee91d44006bd
@@ -1 +1 @@
1
- ebe320b3bc258db22786d472559793c1
1
+ d241929d3af96465ac32a4158c0e0fe8