@sentry/node 8.0.0-rc.0 → 8.0.0-rc.2
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/cjs/index.js +184 -91
- package/cjs/index.js.map +1 -1
- package/esm/index.js +183 -91
- package/esm/index.js.map +1 -1
- package/esm/integrations/anr/worker-script.js +1 -1
- package/esm/integrations/local-variables/worker-script.js +1 -1
- package/import-hook.mjs +2 -0
- package/package.json +8 -8
- package/types/cron/cron.d.ts.map +1 -1
- package/types/cron/node-cron.d.ts +1 -1
- package/types/cron/node-cron.d.ts.map +1 -1
- package/types/cron/node-schedule.d.ts.map +1 -1
- package/types/integrations/tracing/connect.d.ts.map +1 -1
- package/types/integrations/tracing/express.d.ts.map +1 -1
- package/types/integrations/tracing/fastify.d.ts.map +1 -1
- package/types/integrations/tracing/hapi/index.d.ts.map +1 -1
- package/types/integrations/tracing/koa.d.ts.map +1 -1
- package/types/sdk/init.d.ts.map +1 -1
- package/types-ts3.8/cron/node-cron.d.ts +1 -1
package/esm/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import { Worker } from 'worker_threads';
|
|
|
17
17
|
import * as inspector from 'inspector';
|
|
18
18
|
import { Session } from 'inspector';
|
|
19
19
|
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
|
|
20
|
+
import { isWrapped as isWrapped$1 } from '@opentelemetry/core';
|
|
20
21
|
import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify';
|
|
21
22
|
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
|
|
22
23
|
import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb';
|
|
@@ -32,6 +33,7 @@ import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa';
|
|
|
32
33
|
import { SEMATTRS_HTTP_ROUTE, SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_NAMESPACE, SEMRESATTRS_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
33
34
|
import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect';
|
|
34
35
|
import * as http from 'http';
|
|
36
|
+
import moduleModule from 'module';
|
|
35
37
|
import * as http$1 from 'node:http';
|
|
36
38
|
import * as https from 'node:https';
|
|
37
39
|
import { Readable } from 'stream';
|
|
@@ -72,7 +74,7 @@ function getRequestUrl(requestOptions) {
|
|
|
72
74
|
return `${protocol}//${hostname}${port}${path}`;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
function _optionalChain$
|
|
77
|
+
function _optionalChain$e(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
76
78
|
|
|
77
79
|
const _httpIntegration = ((options = {}) => {
|
|
78
80
|
const _breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs;
|
|
@@ -106,7 +108,7 @@ const _httpIntegration = ((options = {}) => {
|
|
|
106
108
|
ignoreIncomingRequestHook: request => {
|
|
107
109
|
const url = getRequestUrl(request);
|
|
108
110
|
|
|
109
|
-
const method = _optionalChain$
|
|
111
|
+
const method = _optionalChain$e([request, 'access', _ => _.method, 'optionalAccess', _2 => _2.toUpperCase, 'call', _3 => _3()]);
|
|
110
112
|
// We do not capture OPTIONS/HEAD requests as transactions
|
|
111
113
|
if (method === 'OPTIONS' || method === 'HEAD') {
|
|
112
114
|
return true;
|
|
@@ -329,7 +331,7 @@ const _consoleIntegration = (() => {
|
|
|
329
331
|
*/
|
|
330
332
|
const consoleIntegration = defineIntegration(_consoleIntegration);
|
|
331
333
|
|
|
332
|
-
function _optionalChain$
|
|
334
|
+
function _optionalChain$d(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
333
335
|
const readFileAsync$1 = promisify(readFile);
|
|
334
336
|
const readDirAsync = promisify(readdir);
|
|
335
337
|
|
|
@@ -357,11 +359,11 @@ const _nodeContextIntegration = ((options = {}) => {
|
|
|
357
359
|
|
|
358
360
|
event.contexts = {
|
|
359
361
|
...event.contexts,
|
|
360
|
-
app: { ...updatedContext.app, ..._optionalChain$
|
|
361
|
-
os: { ...updatedContext.os, ..._optionalChain$
|
|
362
|
-
device: { ...updatedContext.device, ..._optionalChain$
|
|
363
|
-
culture: { ...updatedContext.culture, ..._optionalChain$
|
|
364
|
-
cloud_resource: { ...updatedContext.cloud_resource, ..._optionalChain$
|
|
362
|
+
app: { ...updatedContext.app, ..._optionalChain$d([event, 'access', _ => _.contexts, 'optionalAccess', _2 => _2.app]) },
|
|
363
|
+
os: { ...updatedContext.os, ..._optionalChain$d([event, 'access', _3 => _3.contexts, 'optionalAccess', _4 => _4.os]) },
|
|
364
|
+
device: { ...updatedContext.device, ..._optionalChain$d([event, 'access', _5 => _5.contexts, 'optionalAccess', _6 => _6.device]) },
|
|
365
|
+
culture: { ...updatedContext.culture, ..._optionalChain$d([event, 'access', _7 => _7.contexts, 'optionalAccess', _8 => _8.culture]) },
|
|
366
|
+
cloud_resource: { ...updatedContext.cloud_resource, ..._optionalChain$d([event, 'access', _9 => _9.contexts, 'optionalAccess', _10 => _10.cloud_resource]) },
|
|
365
367
|
};
|
|
366
368
|
|
|
367
369
|
return event;
|
|
@@ -416,11 +418,11 @@ const nodeContextIntegration = defineIntegration(_nodeContextIntegration);
|
|
|
416
418
|
*/
|
|
417
419
|
function _updateContext(contexts) {
|
|
418
420
|
// Only update properties if they exist
|
|
419
|
-
if (_optionalChain$
|
|
421
|
+
if (_optionalChain$d([contexts, 'optionalAccess', _11 => _11.app, 'optionalAccess', _12 => _12.app_memory])) {
|
|
420
422
|
contexts.app.app_memory = process.memoryUsage().rss;
|
|
421
423
|
}
|
|
422
424
|
|
|
423
|
-
if (_optionalChain$
|
|
425
|
+
if (_optionalChain$d([contexts, 'optionalAccess', _13 => _13.device, 'optionalAccess', _14 => _14.free_memory])) {
|
|
424
426
|
contexts.device.free_memory = os.freemem();
|
|
425
427
|
}
|
|
426
428
|
|
|
@@ -747,7 +749,7 @@ function getCloudResourceContext() {
|
|
|
747
749
|
}
|
|
748
750
|
}
|
|
749
751
|
|
|
750
|
-
function _optionalChain$
|
|
752
|
+
function _optionalChain$c(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
751
753
|
const FILE_CONTENT_CACHE = new LRUMap(100);
|
|
752
754
|
const DEFAULT_LINES_OF_CONTEXT = 7;
|
|
753
755
|
const INTEGRATION_NAME$6 = 'ContextLines';
|
|
@@ -777,9 +779,9 @@ async function addSourceContext(event, contextLines) {
|
|
|
777
779
|
const enqueuedReadSourceFileTasks = {};
|
|
778
780
|
const readSourceFileTasks = [];
|
|
779
781
|
|
|
780
|
-
if (contextLines > 0 && _optionalChain$
|
|
782
|
+
if (contextLines > 0 && _optionalChain$c([event, 'access', _2 => _2.exception, 'optionalAccess', _3 => _3.values])) {
|
|
781
783
|
for (const exception of event.exception.values) {
|
|
782
|
-
if (!_optionalChain$
|
|
784
|
+
if (!_optionalChain$c([exception, 'access', _4 => _4.stacktrace, 'optionalAccess', _5 => _5.frames])) {
|
|
783
785
|
continue;
|
|
784
786
|
}
|
|
785
787
|
|
|
@@ -806,7 +808,7 @@ async function addSourceContext(event, contextLines) {
|
|
|
806
808
|
|
|
807
809
|
// Perform the same loop as above, but this time we can assume all files are in the cache
|
|
808
810
|
// and attempt to add source context to frames.
|
|
809
|
-
if (contextLines > 0 && _optionalChain$
|
|
811
|
+
if (contextLines > 0 && _optionalChain$c([event, 'access', _6 => _6.exception, 'optionalAccess', _7 => _7.values])) {
|
|
810
812
|
for (const exception of event.exception.values) {
|
|
811
813
|
if (exception.stacktrace && exception.stacktrace.frames) {
|
|
812
814
|
await addSourceContextToFrames(exception.stacktrace.frames, contextLines);
|
|
@@ -951,9 +953,9 @@ function hashFromStack(stackParser, stack) {
|
|
|
951
953
|
return hashFrames(stackParser(stack, 1));
|
|
952
954
|
}
|
|
953
955
|
|
|
954
|
-
function _optionalChain$
|
|
956
|
+
function _optionalChain$b(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
955
957
|
// This string is a placeholder that gets overwritten with the worker code.
|
|
956
|
-
const base64WorkerScript$1 = '
|
|
958
|
+
const base64WorkerScript$1 = 'LyohIEBzZW50cnkvbm9kZSA4LjAuMC1yYy4yICg3YTNlMTZjKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgZX1mcm9tIm5vZGU6aW5zcGVjdG9yL3Byb21pc2VzIjtpbXBvcnR7d29ya2VyRGF0YSBhcyBuLHBhcmVudFBvcnQgYXMgdH1mcm9tIndvcmtlcl90aHJlYWRzIjtpbXBvcnR7cG9zaXggYXMgbyxzZXAgYXMgcn1mcm9tInBhdGgiO2NvbnN0IGk9NTAscz0iPyIsYz0vXChlcnJvcjogKC4qKVwpLyxhPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztjb25zdCB1PS9eKFxTKzpcXHxcLz8pKFtcc1xTXSo/KSgoPzpcLnsxLDJ9fFteL1xcXSs/fCkoXC5bXi4vXFxdKnwpKSg/OlsvXFxdKikkLztmdW5jdGlvbiBmKGUpe2NvbnN0IG49ZnVuY3Rpb24oZSl7Y29uc3Qgbj1lLmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7ZS5zbGljZSgtMTAyNCl9YDplLHQ9dS5leGVjKG4pO3JldHVybiB0P3Quc2xpY2UoMSk6W119KGUpLHQ9blswXTtsZXQgbz1uWzFdO3JldHVybiB0fHxvPyhvJiYobz1vLnNsaWNlKDAsby5sZW5ndGgtMSkpLHQrbyk6Ii4ifWZ1bmN0aW9uIGwoZSxuPSExKXtyZXR1cm4hKG58fGUmJiFlLnN0YXJ0c1dpdGgoIi8iKSYmIWUubWF0Y2goL15bQS1aXTovKSYmIWUuc3RhcnRzV2l0aCgiLiIpJiYhZS5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PWUmJiFlLmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9ZnVuY3Rpb24gZChlKXtjb25zdCBuPS9eXHMqWy1dezQsfSQvLHQ9L2F0ICg/OmFzeW5jICk/KD86KC4rPylccytcKCk/KD86KC4rKTooXGQrKTooXGQrKT98KFteKV0rKSlcKT8vO3JldHVybiBvPT57Y29uc3Qgcj1vLm1hdGNoKHQpO2lmKHIpe2xldCBuLHQsbyxpLGM7aWYoclsxXSl7bz1yWzFdO2xldCBlPW8ubGFzdEluZGV4T2YoIi4iKTtpZigiLiI9PT1vW2UtMV0mJmUtLSxlPjApe249by5zbGljZSgwLGUpLHQ9by5zbGljZShlKzEpO2NvbnN0IHI9bi5pbmRleE9mKCIuTW9kdWxlIik7cj4wJiYobz1vLnNsaWNlKHIrMSksbj1uLnNsaWNlKDAscikpfWk9dm9pZCAwfXQmJihpPW4sYz10KSwiPGFub255bW91cz4iPT09dCYmKGM9dm9pZCAwLG89dm9pZCAwKSx2b2lkIDA9PT1vJiYoYz1jfHxzLG89aT9gJHtpfS4ke2N9YDpjKTtsZXQgYT1yWzJdJiZyWzJdLnN0YXJ0c1dpdGgoImZpbGU6Ly8iKT9yWzJdLnNsaWNlKDcpOnJbMl07Y29uc3QgdT0ibmF0aXZlIj09PXJbNV07cmV0dXJuIGEmJmEubWF0Y2goL1wvW0EtWl06LykmJihhPWEuc2xpY2UoMSkpLGF8fCFyWzVdfHx1fHwoYT1yWzVdKSx7ZmlsZW5hbWU6YSxtb2R1bGU6ZT9lKGEpOnZvaWQgMCxmdW5jdGlvbjpvLGxpbmVubzpwYXJzZUludChyWzNdLDEwKXx8dm9pZCAwLGNvbG5vOnBhcnNlSW50KHJbNF0sMTApfHx2b2lkIDAsaW5fYXBwOmwoYSx1KX19aWYoby5tYXRjaChuKSlyZXR1cm57ZmlsZW5hbWU6b319fWZ1bmN0aW9uIHAoZSl7cmV0dXJuIGUucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBnPW4sbT1mdW5jdGlvbiguLi5lKXtjb25zdCBuPWUuc29ydCgoKGUsbik9PmVbMF0tblswXSkpLm1hcCgoZT0+ZVsxXSkpO3JldHVybihlLHQ9MCxvPTApPT57Y29uc3Qgcj1bXSx1PWUuc3BsaXQoIlxuIik7Zm9yKGxldCBlPXQ7ZTx1Lmxlbmd0aDtlKyspe2NvbnN0IHQ9dVtlXTtpZih0Lmxlbmd0aD4xMDI0KWNvbnRpbnVlO2NvbnN0IHM9Yy50ZXN0KHQpP3QucmVwbGFjZShjLCIkMSIpOnQ7aWYoIXMubWF0Y2goL1xTKkVycm9yOiAvKSl7Zm9yKGNvbnN0IGUgb2Ygbil7Y29uc3Qgbj1lKHMpO2lmKG4pe3IucHVzaChuKTticmVha319aWYoci5sZW5ndGg+PWkrbylicmVha319cmV0dXJuIGZ1bmN0aW9uKGUpe2lmKCFlLmxlbmd0aClyZXR1cm5bXTtjb25zdCBuPUFycmF5LmZyb20oZSk7L3NlbnRyeVdyYXBwZWQvLnRlc3QobltuLmxlbmd0aC0xXS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpO24ucmV2ZXJzZSgpLGEudGVzdChuW24ubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJihuLnBvcCgpLGEudGVzdChuW24ubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCkpO3JldHVybiBuLnNsaWNlKDAsaSkubWFwKChlPT4oey4uLmUsZmlsZW5hbWU6ZS5maWxlbmFtZXx8bltuLmxlbmd0aC0xXS5maWxlbmFtZSxmdW5jdGlvbjplLmZ1bmN0aW9ufHxzfSkpKX0oci5zbGljZShvKSl9fShbOTAsZChmdW5jdGlvbihlPShwcm9jZXNzLmFyZ3ZbMV0/Zihwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLG49IlxcIj09PXIpe2NvbnN0IHQ9bj9wKGUpOmU7cmV0dXJuIGU9PntpZighZSlyZXR1cm47Y29uc3Qgcj1uP3AoZSk6ZTtsZXR7ZGlyOmksYmFzZTpzLGV4dDpjfT1vLnBhcnNlKHIpOyIuanMiIT09YyYmIi5tanMiIT09YyYmIi5janMiIT09Y3x8KHM9cy5zbGljZSgwLC0xKmMubGVuZ3RoKSksaXx8KGk9Ii4iKTtjb25zdCBhPWkubGFzdEluZGV4T2YoIi9ub2RlX21vZHVsZXMiKTtpZihhPi0xKXJldHVybmAke2kuc2xpY2UoYSsxNCkucmVwbGFjZSgvXC8vZywiLiIpfToke3N9YDtpZihpLnN0YXJ0c1dpdGgodCkpe2xldCBlPWkuc2xpY2UodC5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiBlJiYoZSs9IjoiKSxlKz1zLGV9cmV0dXJuIHN9fShnLmJhc2VQYXRoKSldKTtmdW5jdGlvbiBiKC4uLmUpe2cuZGVidWcmJmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSl9YXN5bmMgZnVuY3Rpb24gdihlLG4sdCxvKXtjb25zdCByPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6bixvd25Qcm9wZXJ0aWVzOiEwfSk7b1t0XT1yLnJlc3VsdC5maWx0ZXIoKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpKS5zb3J0KCgoZSxuKT0+cGFyc2VJbnQoZS5uYW1lLDEwKS1wYXJzZUludChuLm5hbWUsMTApKSkubWFwKChlPT5lLnZhbHVlPy52YWx1ZSkpfWFzeW5jIGZ1bmN0aW9uICQoZSxuLHQsbyl7Y29uc3Qgcj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOm4sb3duUHJvcGVydGllczohMH0pO29bdF09ci5yZXN1bHQubWFwKChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkpLnJlZHVjZSgoKGUsW24sdF0pPT4oZVtuXT10LGUpKSx7fSl9ZnVuY3Rpb24gdyhlLG4pe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT9uW2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6bltlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/bltlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYobltlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiB5KGUsbil7Y29uc3QgdD1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOm4sb3duUHJvcGVydGllczohMH0pLG89e307Zm9yKGNvbnN0IG4gb2YgdC5yZXN1bHQpaWYobj8udmFsdWU/Lm9iamVjdElkJiYiQXJyYXkiPT09bj8udmFsdWUuY2xhc3NOYW1lKXtjb25zdCB0PW4udmFsdWUub2JqZWN0SWQ7YXdhaXQgdihlLHQsbi5uYW1lLG8pfWVsc2UgaWYobj8udmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PW4/LnZhbHVlPy5jbGFzc05hbWUpe2NvbnN0IHQ9bi52YWx1ZS5vYmplY3RJZDthd2FpdCAkKGUsdCxuLm5hbWUsbyl9ZWxzZSBuPy52YWx1ZSYmdyhuLG8pO3JldHVybiBvfWxldCBoOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IG49bmV3IGU7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksYigiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG89ITE7bi5vbigiRGVidWdnZXIucmVzdW1lZCIsKCgpPT57bz0hMX0pKSxuLm9uKCJEZWJ1Z2dlci5wYXVzZWQiLChlPT57bz0hMCxhc3luYyBmdW5jdGlvbihlLG4se3JlYXNvbjpvLGRhdGE6cixjYWxsRnJhbWVzOml9KXtpZigiZXhjZXB0aW9uIiE9PW8mJiJwcm9taXNlUmVqZWN0aW9uIiE9PW8pcmV0dXJuO2g/LigpO2NvbnN0IHM9ZnVuY3Rpb24oZSxuKXtpZih2b2lkIDAhPT1uKXJldHVybiBmdW5jdGlvbihlKXtpZih2b2lkIDAhPT1lKXJldHVybiBlLnNsaWNlKC0xMCkucmVkdWNlKCgoZSxuKT0+YCR7ZX0sJHtuLmZ1bmN0aW9ufSwke24ubGluZW5vfSwke24uY29sbm99YCksIiIpfShlKG4sMSkpfShuLHI/LmRlc2NyaXB0aW9uKTtpZihudWxsPT1zKXJldHVybjtjb25zdCBjPVtdO2ZvcihsZXQgbj0wO248aS5sZW5ndGg7bisrKXtjb25zdHtzY29wZUNoYWluOnQsZnVuY3Rpb25OYW1lOm8sdGhpczpyfT1pW25dLHM9dC5maW5kKChlPT4ibG9jYWwiPT09ZS50eXBlKSksYT0iZ2xvYmFsIiE9PXIuY2xhc3NOYW1lJiZyLmNsYXNzTmFtZT9gJHtyLmNsYXNzTmFtZX0uJHtvfWA6bztpZih2b2lkIDA9PT1zPy5vYmplY3Qub2JqZWN0SWQpY1tuXT17ZnVuY3Rpb246YX07ZWxzZXtjb25zdCB0PWF3YWl0IHkoZSxzLm9iamVjdC5vYmplY3RJZCk7Y1tuXT17ZnVuY3Rpb246YSx2YXJzOnR9fX10Py5wb3N0TWVzc2FnZSh7ZXhjZXB0aW9uSGFzaDpzLGZyYW1lczpjfSl9KG4sbSxlLnBhcmFtcykudGhlbigoKCk9Pm8/bi5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKTpQcm9taXNlLnJlc29sdmUoKSksKGU9Pnt9KSl9KSksYXdhaXQgbi5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCByPSExIT09Zy5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCBuLnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6cj8iYWxsIjoidW5jYXVnaHQifSkscil7Y29uc3QgZT1nLm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO2g9ZnVuY3Rpb24oZSxuLHQpe2xldCBvPTAscj01LGk9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57MD09PWk/bz5lJiYocio9Mix0KHIpLHI+ODY0MDAmJihyPTg2NDAwKSxpPXIpOihpLT0xLDA9PT1pJiZuKCkpLG89MH0pLDFlMykudW5yZWYoKSwoKT0+e28rPTF9fShlLChhc3luYygpPT57YigiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgbi5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9KSwoYXN5bmMgZT0+e2IoYFJhdGUtbGltaXQgZXhjZWVkZWQuIERpc2FibGluZyBjYXB0dXJpbmcgb2YgY2F1Z2h0IGV4Y2VwdGlvbnMgZm9yICR7ZX0gc2Vjb25kcy5gKSxhd2FpdCBuLnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6InVuY2F1Z2h0In0pfSkpfX0pKCkuY2F0Y2goKGU9PntiKCJGYWlsZWQgdG8gc3RhcnQgZGVidWdnZXIiLGUpfSkpLHNldEludGVydmFsKCgoKT0+e30pLDFlNCk7';
|
|
957
959
|
|
|
958
960
|
function log$1(...args) {
|
|
959
961
|
logger.log('[LocalVariables]', ...args);
|
|
@@ -968,7 +970,7 @@ const localVariablesAsyncIntegration = defineIntegration(((
|
|
|
968
970
|
const cachedFrames = new LRUMap(20);
|
|
969
971
|
|
|
970
972
|
function addLocalVariablesToException(exception) {
|
|
971
|
-
const hash = hashFrames(_optionalChain$
|
|
973
|
+
const hash = hashFrames(_optionalChain$b([exception, 'optionalAccess', _ => _.stacktrace, 'optionalAccess', _2 => _2.frames]));
|
|
972
974
|
|
|
973
975
|
if (hash === undefined) {
|
|
974
976
|
return;
|
|
@@ -984,7 +986,7 @@ const localVariablesAsyncIntegration = defineIntegration(((
|
|
|
984
986
|
|
|
985
987
|
// Filter out frames where the function name is `new Promise` since these are in the error.stack frames
|
|
986
988
|
// but do not appear in the debugger call frames
|
|
987
|
-
const frames = (_optionalChain$
|
|
989
|
+
const frames = (_optionalChain$b([exception, 'access', _3 => _3.stacktrace, 'optionalAccess', _4 => _4.frames]) || []).filter(frame => frame.function !== 'new Promise');
|
|
988
990
|
|
|
989
991
|
for (let i = 0; i < frames.length; i++) {
|
|
990
992
|
// Sentry frames are in reverse order
|
|
@@ -1011,7 +1013,7 @@ const localVariablesAsyncIntegration = defineIntegration(((
|
|
|
1011
1013
|
}
|
|
1012
1014
|
|
|
1013
1015
|
function addLocalVariablesToEvent(event) {
|
|
1014
|
-
for (const exception of _optionalChain$
|
|
1016
|
+
for (const exception of _optionalChain$b([event, 'access', _5 => _5.exception, 'optionalAccess', _6 => _6.values]) || []) {
|
|
1015
1017
|
addLocalVariablesToException(exception);
|
|
1016
1018
|
}
|
|
1017
1019
|
|
|
@@ -1085,7 +1087,7 @@ const localVariablesAsyncIntegration = defineIntegration(((
|
|
|
1085
1087
|
};
|
|
1086
1088
|
}) );
|
|
1087
1089
|
|
|
1088
|
-
function _optionalChain$
|
|
1090
|
+
function _optionalChain$a(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1089
1091
|
/** Creates a container for callbacks to be called sequentially */
|
|
1090
1092
|
function createCallbackList(complete) {
|
|
1091
1093
|
// A collection of callbacks to be executed last to first
|
|
@@ -1163,13 +1165,13 @@ class AsyncSession {
|
|
|
1163
1165
|
const { add, next } = createCallbackList(complete);
|
|
1164
1166
|
|
|
1165
1167
|
for (const prop of props) {
|
|
1166
|
-
if (_optionalChain$
|
|
1168
|
+
if (_optionalChain$a([prop, 'optionalAccess', _2 => _2.value, 'optionalAccess', _3 => _3.objectId]) && _optionalChain$a([prop, 'optionalAccess', _4 => _4.value, 'access', _5 => _5.className]) === 'Array') {
|
|
1167
1169
|
const id = prop.value.objectId;
|
|
1168
1170
|
add(vars => this._unrollArray(id, prop.name, vars, next));
|
|
1169
|
-
} else if (_optionalChain$
|
|
1171
|
+
} else if (_optionalChain$a([prop, 'optionalAccess', _6 => _6.value, 'optionalAccess', _7 => _7.objectId]) && _optionalChain$a([prop, 'optionalAccess', _8 => _8.value, 'optionalAccess', _9 => _9.className]) === 'Object') {
|
|
1170
1172
|
const id = prop.value.objectId;
|
|
1171
1173
|
add(vars => this._unrollObject(id, prop.name, vars, next));
|
|
1172
|
-
} else if (_optionalChain$
|
|
1174
|
+
} else if (_optionalChain$a([prop, 'optionalAccess', _10 => _10.value])) {
|
|
1173
1175
|
add(vars => this._unrollOther(prop, vars, next));
|
|
1174
1176
|
}
|
|
1175
1177
|
}
|
|
@@ -1206,7 +1208,7 @@ class AsyncSession {
|
|
|
1206
1208
|
vars[name] = props
|
|
1207
1209
|
.filter(v => v.name !== 'length' && !isNaN(parseInt(v.name, 10)))
|
|
1208
1210
|
.sort((a, b) => parseInt(a.name, 10) - parseInt(b.name, 10))
|
|
1209
|
-
.map(v => _optionalChain$
|
|
1211
|
+
.map(v => _optionalChain$a([v, 'optionalAccess', _11 => _11.value, 'optionalAccess', _12 => _12.value]));
|
|
1210
1212
|
|
|
1211
1213
|
next(vars);
|
|
1212
1214
|
});
|
|
@@ -1218,7 +1220,7 @@ class AsyncSession {
|
|
|
1218
1220
|
_unrollObject(objectId, name, vars, next) {
|
|
1219
1221
|
this._getProperties(objectId, props => {
|
|
1220
1222
|
vars[name] = props
|
|
1221
|
-
.map(v => [v.name, _optionalChain$
|
|
1223
|
+
.map(v => [v.name, _optionalChain$a([v, 'optionalAccess', _13 => _13.value, 'optionalAccess', _14 => _14.value])])
|
|
1222
1224
|
.reduce((obj, [key, val]) => {
|
|
1223
1225
|
obj[key] = val;
|
|
1224
1226
|
return obj;
|
|
@@ -1285,10 +1287,10 @@ const _localVariablesSyncIntegration = ((
|
|
|
1285
1287
|
return;
|
|
1286
1288
|
}
|
|
1287
1289
|
|
|
1288
|
-
_optionalChain$
|
|
1290
|
+
_optionalChain$a([rateLimiter, 'optionalCall', _15 => _15()]);
|
|
1289
1291
|
|
|
1290
1292
|
// data.description contains the original error.stack
|
|
1291
|
-
const exceptionHash = hashFromStack(stackParser, _optionalChain$
|
|
1293
|
+
const exceptionHash = hashFromStack(stackParser, _optionalChain$a([data, 'optionalAccess', _16 => _16.description]));
|
|
1292
1294
|
|
|
1293
1295
|
if (exceptionHash == undefined) {
|
|
1294
1296
|
complete();
|
|
@@ -1310,7 +1312,7 @@ const _localVariablesSyncIntegration = ((
|
|
|
1310
1312
|
// obj.className is undefined in ESM modules
|
|
1311
1313
|
const fn = obj.className === 'global' || !obj.className ? functionName : `${obj.className}.${functionName}`;
|
|
1312
1314
|
|
|
1313
|
-
if (_optionalChain$
|
|
1315
|
+
if (_optionalChain$a([localScope, 'optionalAccess', _17 => _17.object, 'access', _18 => _18.objectId]) === undefined) {
|
|
1314
1316
|
add(frames => {
|
|
1315
1317
|
frames[i] = { function: fn };
|
|
1316
1318
|
next(frames);
|
|
@@ -1318,7 +1320,7 @@ const _localVariablesSyncIntegration = ((
|
|
|
1318
1320
|
} else {
|
|
1319
1321
|
const id = localScope.object.objectId;
|
|
1320
1322
|
add(frames =>
|
|
1321
|
-
_optionalChain$
|
|
1323
|
+
_optionalChain$a([session, 'optionalAccess', _19 => _19.getLocalVariables, 'call', _20 => _20(id, vars => {
|
|
1322
1324
|
frames[i] = { function: fn, vars };
|
|
1323
1325
|
next(frames);
|
|
1324
1326
|
})]),
|
|
@@ -1330,7 +1332,7 @@ const _localVariablesSyncIntegration = ((
|
|
|
1330
1332
|
}
|
|
1331
1333
|
|
|
1332
1334
|
function addLocalVariablesToException(exception) {
|
|
1333
|
-
const hash = hashFrames(_optionalChain$
|
|
1335
|
+
const hash = hashFrames(_optionalChain$a([exception, 'optionalAccess', _21 => _21.stacktrace, 'optionalAccess', _22 => _22.frames]));
|
|
1334
1336
|
|
|
1335
1337
|
if (hash === undefined) {
|
|
1336
1338
|
return;
|
|
@@ -1346,7 +1348,7 @@ const _localVariablesSyncIntegration = ((
|
|
|
1346
1348
|
|
|
1347
1349
|
// Filter out frames where the function name is `new Promise` since these are in the error.stack frames
|
|
1348
1350
|
// but do not appear in the debugger call frames
|
|
1349
|
-
const frames = (_optionalChain$
|
|
1351
|
+
const frames = (_optionalChain$a([exception, 'access', _23 => _23.stacktrace, 'optionalAccess', _24 => _24.frames]) || []).filter(frame => frame.function !== 'new Promise');
|
|
1350
1352
|
|
|
1351
1353
|
for (let i = 0; i < frames.length; i++) {
|
|
1352
1354
|
// Sentry frames are in reverse order
|
|
@@ -1373,7 +1375,7 @@ const _localVariablesSyncIntegration = ((
|
|
|
1373
1375
|
}
|
|
1374
1376
|
|
|
1375
1377
|
function addLocalVariablesToEvent(event) {
|
|
1376
|
-
for (const exception of _optionalChain$
|
|
1378
|
+
for (const exception of _optionalChain$a([event, 'optionalAccess', _25 => _25.exception, 'optionalAccess', _26 => _26.values]) || []) {
|
|
1377
1379
|
addLocalVariablesToException(exception);
|
|
1378
1380
|
}
|
|
1379
1381
|
|
|
@@ -1384,9 +1386,9 @@ const _localVariablesSyncIntegration = ((
|
|
|
1384
1386
|
name: INTEGRATION_NAME$5,
|
|
1385
1387
|
setupOnce() {
|
|
1386
1388
|
const client = getClient$1();
|
|
1387
|
-
const clientOptions = _optionalChain$
|
|
1389
|
+
const clientOptions = _optionalChain$a([client, 'optionalAccess', _27 => _27.getOptions, 'call', _28 => _28()]);
|
|
1388
1390
|
|
|
1389
|
-
if (session && _optionalChain$
|
|
1391
|
+
if (session && _optionalChain$a([clientOptions, 'optionalAccess', _29 => _29.includeLocalVariables])) {
|
|
1390
1392
|
// Only setup this integration if the Node version is >= v18
|
|
1391
1393
|
// https://github.com/getsentry/sentry-javascript/issues/7697
|
|
1392
1394
|
const unsupportedNodeVersion = NODE_MAJOR < 18;
|
|
@@ -1411,13 +1413,13 @@ const _localVariablesSyncIntegration = ((
|
|
|
1411
1413
|
max,
|
|
1412
1414
|
() => {
|
|
1413
1415
|
logger.log('Local variables rate-limit lifted.');
|
|
1414
|
-
_optionalChain$
|
|
1416
|
+
_optionalChain$a([session, 'optionalAccess', _30 => _30.setPauseOnExceptions, 'call', _31 => _31(true)]);
|
|
1415
1417
|
},
|
|
1416
1418
|
seconds => {
|
|
1417
1419
|
logger.log(
|
|
1418
1420
|
`Local variables rate-limit exceeded. Disabling capturing of caught exceptions for ${seconds} seconds.`,
|
|
1419
1421
|
);
|
|
1420
|
-
_optionalChain$
|
|
1422
|
+
_optionalChain$a([session, 'optionalAccess', _32 => _32.setPauseOnExceptions, 'call', _33 => _33(false)]);
|
|
1421
1423
|
},
|
|
1422
1424
|
);
|
|
1423
1425
|
}
|
|
@@ -1784,9 +1786,9 @@ function handleRejection(
|
|
|
1784
1786
|
/* eslint-enable no-console */
|
|
1785
1787
|
}
|
|
1786
1788
|
|
|
1787
|
-
function _optionalChain$
|
|
1789
|
+
function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1788
1790
|
// This string is a placeholder that gets overwritten with the worker code.
|
|
1789
|
-
const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA4LjAuMC1yYy4wICg2ZDhkZjBhKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tImluc3BlY3RvciI7aW1wb3J0e3BhcmVudFBvcnQgYXMgZSx3b3JrZXJEYXRhIGFzIG59ZnJvbSJ3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tInN0cmVhbSI7aW1wb3J0e2NyZWF0ZUd6aXAgYXMgdX1mcm9tInpsaWIiO2ltcG9ydCphcyBhIGZyb20ibmV0IjtpbXBvcnQqYXMgZiBmcm9tInRscyI7aW1wb3J0KmFzIGggZnJvbSJodHRwIjtjb25zdCBwPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gbCh0LGUpe3JldHVybiBwLmNhbGwodCk9PT1gW29iamVjdCAke2V9XWB9ZnVuY3Rpb24gZCh0KXtyZXR1cm4gbCh0LCJPYmplY3QiKX1mdW5jdGlvbiBtKHQpe3JldHVybiBCb29sZWFuKHQmJnQudGhlbiYmImZ1bmN0aW9uIj09dHlwZW9mIHQudGhlbil9ZnVuY3Rpb24gZyh0LGUpe3RyeXtyZXR1cm4gdCBpbnN0YW5jZW9mIGV9Y2F0Y2godCl7cmV0dXJuITF9fWNvbnN0IHk9Z2xvYmFsVGhpcztmdW5jdGlvbiBiKHQsZSxuKXtjb25zdCByPW58fHksbz1yLl9fU0VOVFJZX189ci5fX1NFTlRSWV9ffHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09ZSgpKX1jb25zdCB2PXksXz04MDtmdW5jdGlvbiB3KHQsZSl7Y29uc3Qgbj10LHI9W107bGV0IG8scyxpLGMsdTtpZighbnx8IW4udGFnTmFtZSlyZXR1cm4iIjtpZih2LkhUTUxFbGVtZW50JiZuIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQmJm4uZGF0YXNldCl7aWYobi5kYXRhc2V0LnNlbnRyeUNvbXBvbmVudClyZXR1cm4gbi5kYXRhc2V0LnNlbnRyeUNvbXBvbmVudDtpZihuLmRhdGFzZXQuc2VudHJ5RWxlbWVudClyZXR1cm4gbi5kYXRhc2V0LnNlbnRyeUVsZW1lbnR9ci5wdXNoKG4udGFnTmFtZS50b0xvd2VyQ2FzZSgpKTtjb25zdCBhPWUmJmUubGVuZ3RoP2UuZmlsdGVyKCh0PT5uLmdldEF0dHJpYnV0ZSh0KSkpLm1hcCgodD0+W3Qsbi5nZXRBdHRyaWJ1dGUodCldKSk6bnVsbDtpZihhJiZhLmxlbmd0aClhLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNlIGlmKG4uaWQmJnIucHVzaChgIyR7bi5pZH1gKSxvPW4uY2xhc3NOYW1lLG8mJmwobywiU3RyaW5nIikpZm9yKHM9by5zcGxpdCgvXHMrLyksdT0wO3U8cy5sZW5ndGg7dSsrKXIucHVzaChgLiR7c1t1XX1gKTtjb25zdCBmPVsiYXJpYS1sYWJlbCIsInR5cGUiLCJuYW1lIiwidGl0bGUiLCJhbHQiXTtmb3IodT0wO3U8Zi5sZW5ndGg7dSsrKWk9Zlt1XSxjPW4uZ2V0QXR0cmlidXRlKGkpLGMmJnIucHVzaChgWyR7aX09IiR7Y30iXWApO3JldHVybiByLmpvaW4oIiIpfWNvbnN0IFM9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLCQ9WyJkZWJ1ZyIsImluZm8iLCJ3YXJuIiwiZXJyb3IiLCJsb2ciLCJhc3NlcnQiLCJ0cmFjZSJdLEU9e307ZnVuY3Rpb24geCh0KXtpZighKCJjb25zb2xlImluIHkpKXJldHVybiB0KCk7Y29uc3QgZT15LmNvbnNvbGUsbj17fSxyPU9iamVjdC5rZXlzKEUpO3IuZm9yRWFjaCgodD0+e2NvbnN0IHI9RVt0XTtuW3RdPWVbdF0sZVt0XT1yfSkpO3RyeXtyZXR1cm4gdCgpfWZpbmFsbHl7ci5mb3JFYWNoKCh0PT57ZVt0XT1uW3RdfSkpfX1jb25zdCBOPWZ1bmN0aW9uKCl7bGV0IHQ9ITE7Y29uc3QgZT17ZW5hYmxlOigpPT57dD0hMH0sZGlzYWJsZTooKT0+e3Q9ITF9LGlzRW5hYmxlZDooKT0+dH07cmV0dXJuIFM/JC5mb3JFYWNoKChuPT57ZVtuXT0oLi4uZSk9Pnt0JiZ4KCgoKT0+e3kuY29uc29sZVtuXShgU2VudHJ5IExvZ2dlciBbJHtufV06YCwuLi5lKX0pKX19KSk6JC5mb3JFYWNoKCh0PT57ZVt0XT0oKT0+e319KSksZX0oKTtmdW5jdGlvbiBrKHQsZT0hMSl7Y29uc3R7aG9zdDpuLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtlJiZvP2A6JHtvfWA6IiJ9QCR7bn0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1jbGFzcyBDIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IodCxlPSJ3YXJuIil7c3VwZXIodCksdGhpcy5tZXNzYWdlPXQsdGhpcy5uYW1lPW5ldy50YXJnZXQucHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUsT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsbmV3LnRhcmdldC5wcm90b3R5cGUpLHRoaXMubG9nTGV2ZWw9ZX19ZnVuY3Rpb24gRCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2gocC5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOnJldHVybiEwO2RlZmF1bHQ6cmV0dXJuIGcodCxFcnJvcil9fSh0KSlyZXR1cm57bWVzc2FnZTp0Lm1lc3NhZ2UsbmFtZTp0Lm5hbWUsc3RhY2s6dC5zdGFjaywuLi5PKHQpfTtpZihlPXQsInVuZGVmaW5lZCIhPXR5cGVvZiBFdmVudCYmZyhlLEV2ZW50KSl7Y29uc3QgZT17dHlwZTp0LnR5cGUsdGFyZ2V0OlQodC50YXJnZXQpLGN1cnJlbnRUYXJnZXQ6VCh0LmN1cnJlbnRUYXJnZXQpLC4uLk8odCl9O3JldHVybiJ1bmRlZmluZWQiIT10eXBlb2YgQ3VzdG9tRXZlbnQmJmcodCxDdXN0b21FdmVudCkmJihlLmRldGFpbD10LmRldGFpbCksZX1yZXR1cm4gdDt2YXIgZX1mdW5jdGlvbiBUKHQpe3RyeXtyZXR1cm4gZT10LCJ1bmRlZmluZWQiIT10eXBlb2YgRWxlbWVudCYmZyhlLEVsZW1lbnQpP2Z1bmN0aW9uKHQsZT17fSl7aWYoIXQpcmV0dXJuIjx1bmtub3duPiI7dHJ5e2xldCBuPXQ7Y29uc3Qgcj01LG89W107bGV0IHM9MCxpPTA7Y29uc3QgYz0iID4gIix1PWMubGVuZ3RoO2xldCBhO2NvbnN0IGY9QXJyYXkuaXNBcnJheShlKT9lOmUua2V5QXR0cnMsaD0hQXJyYXkuaXNBcnJheShlKSYmZS5tYXhTdHJpbmdMZW5ndGh8fF87Zm9yKDtuJiZzKys8ciYmKGE9dyhuLGYpLCEoImh0bWwiPT09YXx8cz4xJiZpK28ubGVuZ3RoKnUrYS5sZW5ndGg+PWgpKTspby5wdXNoKGEpLGkrPWEubGVuZ3RoLG49bi5wYXJlbnROb2RlO3JldHVybiBvLnJldmVyc2UoKS5qb2luKGMpfWNhdGNoKHQpe3JldHVybiI8dW5rbm93bj4ifX0odCk6T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHQpfWNhdGNoKHQpe3JldHVybiI8dW5rbm93bj4ifXZhciBlfWZ1bmN0aW9uIE8odCl7aWYoIm9iamVjdCI9PXR5cGVvZiB0JiZudWxsIT09dCl7Y29uc3QgZT17fTtmb3IoY29uc3QgbiBpbiB0KU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0LG4pJiYoZVtuXT10W25dKTtyZXR1cm4gZX1yZXR1cm57fX1mdW5jdGlvbiBqKHQpe3JldHVybiBSKHQsbmV3IE1hcCl9ZnVuY3Rpb24gUih0LGUpe2lmKGZ1bmN0aW9uKHQpe2lmKCFkKHQpKXJldHVybiExO3RyeXtjb25zdCBlPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KS5jb25zdHJ1Y3Rvci5uYW1lO3JldHVybiFlfHwiT2JqZWN0Ij09PWV9Y2F0Y2godCl7cmV0dXJuITB9fSh0KSl7Y29uc3Qgbj1lLmdldCh0KTtpZih2b2lkIDAhPT1uKXJldHVybiBuO2NvbnN0IHI9e307ZS5zZXQodCxyKTtmb3IoY29uc3QgbiBvZiBPYmplY3Qua2V5cyh0KSl2b2lkIDAhPT10W25dJiYocltuXT1SKHRbbl0sZSkpO3JldHVybiByfWlmKEFycmF5LmlzQXJyYXkodCkpe2NvbnN0IG49ZS5nZXQodCk7aWYodm9pZCAwIT09bilyZXR1cm4gbjtjb25zdCByPVtdO3JldHVybiBlLnNldCh0LHIpLHQuZm9yRWFjaCgodD0+e3IucHVzaChSKHQsZSkpfSkpLHJ9cmV0dXJuIHR9Y29uc3QgQT01MCxJPSI/IixQPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztjb25zdCBVPSI8YW5vbnltb3VzPiI7ZnVuY3Rpb24gTSgpe2NvbnN0IHQ9eSxlPXQuY3J5cHRvfHx0Lm1zQ3J5cHRvO2xldCBuPSgpPT4xNipNYXRoLnJhbmRvbSgpO3RyeXtpZihlJiZlLnJhbmRvbVVVSUQpcmV0dXJuIGUucmFuZG9tVVVJRCgpLnJlcGxhY2UoLy0vZywiIik7ZSYmZS5nZXRSYW5kb21WYWx1ZXMmJihuPSgpPT57Y29uc3QgdD1uZXcgVWludDhBcnJheSgxKTtyZXR1cm4gZS5nZXRSYW5kb21WYWx1ZXModCksdFswXX0pfWNhdGNoKHQpe31yZXR1cm4oWzFlN10rMWUzKzRlMys4ZTMrMWUxMSkucmVwbGFjZSgvWzAxOF0vZywodD0+KHReKDE1Jm4oKSk+PnQvNCkudG9TdHJpbmcoMTYpKSl9ZnVuY3Rpb24gTCh0LGU9MTAwLG49MS8wKXt0cnl7cmV0dXJuIEIoIiIsdCxlLG4pfWNhdGNoKHQpe3JldHVybntFUlJPUjpgKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19fWZ1bmN0aW9uIEIodCxlLG49MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PSJmdW5jdGlvbiI9PXR5cGVvZiBXZWFrU2V0LGU9dD9uZXcgV2Vha1NldDpbXTtyZXR1cm5bZnVuY3Rpb24obil7aWYodClyZXR1cm4hIWUuaGFzKG4pfHwoZS5hZGQobiksITEpO2ZvcihsZXQgdD0wO3Q8ZS5sZW5ndGg7dCsrKWlmKGVbdF09PT1uKXJldHVybiEwO3JldHVybiBlLnB1c2gobiksITF9LGZ1bmN0aW9uKG4pe2lmKHQpZS5kZWxldGUobik7ZWxzZSBmb3IobGV0IHQ9MDt0PGUubGVuZ3RoO3QrKylpZihlW3RdPT09bil7ZS5zcGxpY2UodCwxKTticmVha319XX0oKSl7Y29uc3RbcyxpXT1vO2lmKG51bGw9PWV8fFsibnVtYmVyIiwiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBlKSYmIU51bWJlci5pc05hTihlKSlyZXR1cm4gZTtjb25zdCBjPWZ1bmN0aW9uKHQsZSl7dHJ5e2lmKCJkb21haW4iPT09dCYmZSYmIm9iamVjdCI9PXR5cGVvZiBlJiZlLnQpcmV0dXJuIltEb21haW5dIjtpZigiZG9tYWluRW1pdHRlciI9PT10KXJldHVybiJbRG9tYWluRW1pdHRlcl0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZlPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJmU9PT13aW5kb3cpcmV0dXJuIltXaW5kb3ddIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGRvY3VtZW50JiZlPT09ZG9jdW1lbnQpcmV0dXJuIltEb2N1bWVudF0iO2lmKCJvYmplY3QiPT10eXBlb2Yobj1lKSYmbnVsbCE9PW4mJihuLl9faXNWdWV8fG4ubykpcmV0dXJuIltWdWVWaWV3TW9kZWxdIjtpZihmdW5jdGlvbih0KXtyZXR1cm4gZCh0KSYmIm5hdGl2ZUV2ZW50ImluIHQmJiJwcmV2ZW50RGVmYXVsdCJpbiB0JiYic3RvcFByb3BhZ2F0aW9uImluIHR9KGUpKXJldHVybiJbU3ludGhldGljRXZlbnRdIjtpZigibnVtYmVyIj09dHlwZW9mIGUmJmUhPWUpcmV0dXJuIltOYU5dIjtpZigiZnVuY3Rpb24iPT10eXBlb2YgZSlyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8VX1jYXRjaCh0KXtyZXR1cm4gVX19KGUpfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgZSlyZXR1cm5gWyR7U3RyaW5nKGUpfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgZSlyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcoZSl9XWA7Y29uc3Qgcj1mdW5jdGlvbih0KXtjb25zdCBlPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gZT9lLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0oZSk7cmV0dXJuL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChyKT9gW0hUTUxFbGVtZW50OiAke3J9XWA6YFtvYmplY3QgJHtyfV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfXZhciBufSh0LGUpO2lmKCFjLnN0YXJ0c1dpdGgoIltvYmplY3QgIikpcmV0dXJuIGM7aWYoZS5fX3NlbnRyeV9za2lwX25vcm1hbGl6YXRpb25fXylyZXR1cm4gZTtjb25zdCB1PSJudW1iZXIiPT10eXBlb2YgZS5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX18/ZS5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX186bjtpZigwPT09dSlyZXR1cm4gYy5yZXBsYWNlKCJvYmplY3QgIiwiIik7aWYocyhlKSlyZXR1cm4iW0NpcmN1bGFyIH5dIjtjb25zdCBhPWU7aWYoYSYmImZ1bmN0aW9uIj09dHlwZW9mIGEudG9KU09OKXRyeXtyZXR1cm4gQigiIixhLnRvSlNPTigpLHUtMSxyLG8pfWNhdGNoKHQpe31jb25zdCBmPUFycmF5LmlzQXJyYXkoZSk/W106e307bGV0IGg9MDtjb25zdCBwPUQoZSk7Zm9yKGNvbnN0IHQgaW4gcCl7aWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwLHQpKWNvbnRpbnVlO2lmKGg+PXIpe2ZbdF09IltNYXhQcm9wZXJ0aWVzIH5dIjticmVha31jb25zdCBlPXBbdF07Zlt0XT1CKHQsZSx1LTEscixvKSxoKyt9cmV0dXJuIGkoZSksZn1mdW5jdGlvbiBHKHQsZSl7Y29uc3Qgbj1lLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Ll0vZywiXFwkJiIpO2xldCByPXQ7dHJ5e3I9ZGVjb2RlVVJJKHQpfWNhdGNoKHQpe31yZXR1cm4gci5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvd2VicGFjazpcLz8vZywiIikucmVwbGFjZShuZXcgUmVnRXhwKGAoZmlsZTovLyk/Lyoke259LypgLCJpZyIpLCJhcHA6Ly8vIil9Y29uc3QgSj0vXihcUys6XFx8XC8/KShbXHNcU10qPykoKD86XC57MSwyfXxbXi9cXF0rP3wpKFwuW14uL1xcXSp8KSkoPzpbL1xcXSopJC87ZnVuY3Rpb24geih0KXtjb25zdCBlPWZ1bmN0aW9uKHQpe2NvbnN0IGU9dC5sZW5ndGg+MTAyND9gPHRydW5jYXRlZD4ke3Quc2xpY2UoLTEwMjQpfWA6dCxuPUouZXhlYyhlKTtyZXR1cm4gbj9uLnNsaWNlKDEpOltdfSh0KSxuPWVbMF07bGV0IHI9ZVsxXTtyZXR1cm4gbnx8cj8ociYmKHI9ci5zbGljZSgwLHIubGVuZ3RoLTEpKSxuK3IpOiIuIn12YXIgSDtmdW5jdGlvbiBXKHQpe3JldHVybiBuZXcgWSgoZT0+e2UodCl9KSl9IWZ1bmN0aW9uKHQpe3RbdC5QRU5ESU5HPTBdPSJQRU5ESU5HIjt0W3QuUkVTT0xWRUQ9MV09IlJFU09MVkVEIjt0W3QuUkVKRUNURUQ9Ml09IlJFSkVDVEVEIn0oSHx8KEg9e30pKTtjbGFzcyBZe2NvbnN0cnVjdG9yKHQpe1kucHJvdG90eXBlLl9faW5pdC5jYWxsKHRoaXMpLFkucHJvdG90eXBlLl9faW5pdDIuY2FsbCh0aGlzKSxZLnByb3RvdHlwZS5fX2luaXQzLmNhbGwodGhpcyksWS5wcm90b3R5cGUuX19pbml0NC5jYWxsKHRoaXMpLHRoaXMuaT1ILlBFTkRJTkcsdGhpcy51PVtdO3RyeXt0KHRoaXMuaCx0aGlzLnApfWNhdGNoKHQpe3RoaXMucCh0KX19dGhlbih0LGUpe3JldHVybiBuZXcgWSgoKG4scik9Pnt0aGlzLnUucHVzaChbITEsZT0+e2lmKHQpdHJ5e24odChlKSl9Y2F0Y2godCl7cih0KX1lbHNlIG4oZSl9LHQ9PntpZihlKXRyeXtuKGUodCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMubCgpfSkpfWNhdGNoKHQpe3JldHVybiB0aGlzLnRoZW4oKHQ9PnQpLHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBZKCgoZSxuKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbigoZT0+e289ITEscj1lLHQmJnQoKX0pLChlPT57bz0hMCxyPWUsdCYmdCgpfSkpLnRoZW4oKCgpPT57bz9uKHIpOmUocil9KSl9KSl9X19pbml0KCl7dGhpcy5oPXQ9Pnt0aGlzLm0oSC5SRVNPTFZFRCx0KX19X19pbml0Migpe3RoaXMucD10PT57dGhpcy5tKEguUkVKRUNURUQsdCl9fV9faW5pdDMoKXt0aGlzLm09KHQsZSk9Pnt0aGlzLmk9PT1ILlBFTkRJTkcmJihtKGUpP2UudGhlbih0aGlzLmgsdGhpcy5wKToodGhpcy5pPXQsdGhpcy52PWUsdGhpcy5sKCkpKX19X19pbml0NCgpe3RoaXMubD0oKT0+e2lmKHRoaXMuaT09PUguUEVORElORylyZXR1cm47Y29uc3QgdD10aGlzLnUuc2xpY2UoKTt0aGlzLnU9W10sdC5mb3JFYWNoKCh0PT57dFswXXx8KHRoaXMuaT09PUguUkVTT0xWRUQmJnRbMV0odGhpcy52KSx0aGlzLmk9PT1ILlJFSkVDVEVEJiZ0WzJdKHRoaXMudiksdFswXT0hMCl9KSl9fX1mdW5jdGlvbiBxKHQpe2NvbnN0IGU9W107ZnVuY3Rpb24gbih0KXtyZXR1cm4gZS5zcGxpY2UoZS5pbmRleE9mKHQpLDEpWzBdfXJldHVybnskOmUsYWRkOmZ1bmN0aW9uKHIpe2lmKCEodm9pZCAwPT09dHx8ZS5sZW5ndGg8dCkpcmV0dXJuIG89bmV3IEMoIk5vdCBhZGRpbmcgUHJvbWlzZSBiZWNhdXNlIGJ1ZmZlciBsaW1pdCB3YXMgcmVhY2hlZC4iKSxuZXcgWSgoKHQsZSk9PntlKG8pfSkpO3ZhciBvO2NvbnN0IHM9cigpO3JldHVybi0xPT09ZS5pbmRleE9mKHMpJiZlLnB1c2gocykscy50aGVuKCgoKT0+bihzKSkpLnRoZW4obnVsbCwoKCk9Pm4ocykudGhlbihudWxsLCgoKT0+e30pKSkpLHN9LGRyYWluOmZ1bmN0aW9uKHQpe3JldHVybiBuZXcgWSgoKG4scik9PntsZXQgbz1lLmxlbmd0aDtpZighbylyZXR1cm4gbighMCk7Y29uc3Qgcz1zZXRUaW1lb3V0KCgoKT0+e3QmJnQ+MCYmbighMSl9KSx0KTtlLmZvckVhY2goKHQ9PntXKHQpLnRoZW4oKCgpPT57LS1vfHwoY2xlYXJUaW1lb3V0KHMpLG4oITApKX0pLHIpfSkpfSkpfX19ZnVuY3Rpb24gRih0LGU9ITEpe3JldHVybiEoZXx8dCYmIXQuc3RhcnRzV2l0aCgiLyIpJiYhdC5tYXRjaCgvXltBLVpdOi8pJiYhdC5zdGFydHNXaXRoKCIuIikmJiF0Lm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKSYmdm9pZCAwIT09dCYmIXQuaW5jbHVkZXMoIm5vZGVfbW9kdWxlcy8iKX1jb25zdCBLPTFlMztmdW5jdGlvbiBWKCl7cmV0dXJuIERhdGUubm93KCkvS31jb25zdCBaPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09eTtpZighdHx8IXQubm93KXJldHVybiBWO2NvbnN0IGU9RGF0ZS5ub3coKS10Lm5vdygpLG49bnVsbD09dC50aW1lT3JpZ2luP2U6dC50aW1lT3JpZ2luO3JldHVybigpPT4obit0Lm5vdygpKS9LfSgpO2Z1bmN0aW9uIFEodCxlPVtdKXtyZXR1cm5bdCxlXX1mdW5jdGlvbiBYKHQsZSl7Y29uc3Qgbj10WzFdO2Zvcihjb25zdCB0IG9mIG4pe2lmKGUodCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIHR0KHQpe3JldHVybiB5Ll9fU0VOVFJZX18mJnkuX19TRU5UUllfXy5lbmNvZGVQb2x5ZmlsbD95Ll9fU0VOVFJZX18uZW5jb2RlUG9seWZpbGwodCk6KG5ldyBUZXh0RW5jb2RlcikuZW5jb2RlKHQpfWZ1bmN0aW9uIGV0KHQpe2NvbnN0W2Usbl09dDtsZXQgcj1KU09OLnN0cmluZ2lmeShlKTtmdW5jdGlvbiBvKHQpeyJzdHJpbmciPT10eXBlb2Ygcj9yPSJzdHJpbmciPT10eXBlb2YgdD9yK3Q6W3R0KHIpLHRdOnIucHVzaCgic3RyaW5nIj09dHlwZW9mIHQ/dHQodCk6dCl9Zm9yKGNvbnN0IHQgb2Ygbil7Y29uc3RbZSxuXT10O2lmKG8oYFxuJHtKU09OLnN0cmluZ2lmeShlKX1cbmApLCJzdHJpbmciPT10eXBlb2Ygbnx8biBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbyhuKTtlbHNle2xldCB0O3RyeXt0PUpTT04uc3RyaW5naWZ5KG4pfWNhdGNoKGUpe3Q9SlNPTi5zdHJpbmdpZnkoTChuKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3QgZT10LnJlZHVjZSgoKHQsZSk9PnQrZS5sZW5ndGgpLDApLG49bmV3IFVpbnQ4QXJyYXkoZSk7bGV0IHI9MDtmb3IoY29uc3QgZSBvZiB0KW4uc2V0KGUscikscis9ZS5sZW5ndGg7cmV0dXJuIG59KHIpfSgoKT0+e2NvbnN0e3BlcmZvcm1hbmNlOnR9PXk7aWYoIXR8fCF0Lm5vdylyZXR1cm47Y29uc3QgZT0zNmU1LG49dC5ub3coKSxyPURhdGUubm93KCksbz10LnRpbWVPcmlnaW4/TWF0aC5hYnModC50aW1lT3JpZ2luK24tcik6ZSxzPW88ZSxpPXQudGltaW5nJiZ0LnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQsYz0ibnVtYmVyIj09dHlwZW9mIGk/TWF0aC5hYnMoaStuLXIpOmU7KHN8fGM8ZSkmJihvPD1jJiZ0LnRpbWVPcmlnaW4pfSkoKTtjb25zdCBudD17c2Vzc2lvbjoic2Vzc2lvbiIsc2Vzc2lvbnM6InNlc3Npb24iLGF0dGFjaG1lbnQ6ImF0dGFjaG1lbnQiLHRyYW5zYWN0aW9uOiJ0cmFuc2FjdGlvbiIsZXZlbnQ6ImVycm9yIixjbGllbnRfcmVwb3J0OiJpbnRlcm5hbCIsdXNlcl9yZXBvcnQ6ImRlZmF1bHQiLHByb2ZpbGU6InByb2ZpbGUiLHJlcGxheV9ldmVudDoicmVwbGF5IixyZXBsYXlfcmVjb3JkaW5nOiJyZXBsYXkiLGNoZWNrX2luOiJtb25pdG9yIixmZWVkYmFjazoiZmVlZGJhY2siLHNwYW46InNwYW4iLHN0YXRzZDoibWV0cmljX2J1Y2tldCJ9O2Z1bmN0aW9uIHJ0KHQpe3JldHVybiBudFt0XX1mdW5jdGlvbiBvdCh0KXtpZighdHx8IXQuc2RrKXJldHVybjtjb25zdHtuYW1lOmUsdmVyc2lvbjpufT10LnNkaztyZXR1cm57bmFtZTplLHZlcnNpb246bn19Y29uc3Qgc3Q9NmU0O2Z1bmN0aW9uIGl0KHQse3N0YXR1c0NvZGU6ZSxoZWFkZXJzOm59LHI9RGF0ZS5ub3coKSl7Y29uc3Qgbz17Li4udH0scz1uJiZuWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLGk9biYmblsicmV0cnktYWZ0ZXIiXTtpZihzKWZvcihjb25zdCB0IG9mIHMudHJpbSgpLnNwbGl0KCIsIikpe2NvbnN0W2UsbiwsLHNdPXQuc3BsaXQoIjoiLDUpLGk9cGFyc2VJbnQoZSwxMCksYz0xZTMqKGlzTmFOKGkpPzYwOmkpO2lmKG4pZm9yKGNvbnN0IHQgb2Ygbi5zcGxpdCgiOyIpKSJtZXRyaWNfYnVja2V0Ij09PXQmJnMmJiFzLnNwbGl0KCI7IikuaW5jbHVkZXMoImN1c3RvbSIpfHwob1t0XT1yK2MpO2Vsc2Ugby5hbGw9citjfWVsc2UgaT9vLmFsbD1yK2Z1bmN0aW9uKHQsZT1EYXRlLm5vdygpKXtjb25zdCBuPXBhcnNlSW50KGAke3R9YCwxMCk7aWYoIWlzTmFOKG4pKXJldHVybiAxZTMqbjtjb25zdCByPURhdGUucGFyc2UoYCR7dH1gKTtyZXR1cm4gaXNOYU4ocik/c3Q6ci1lfShpLHIpOjQyOT09PWUmJihvLmFsbD1yKzZlNCk7cmV0dXJuIG99Y29uc3QgY3Q9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fO2Z1bmN0aW9uIHV0KCl7cmV0dXJuIGF0KHkpLHl9ZnVuY3Rpb24gYXQodCl7cmV0dXJuIHQuX19TRU5UUllfX3x8KHQuX19TRU5UUllfXz17ZXh0ZW5zaW9uczp7fX0pLHQuX19TRU5UUllfX31mdW5jdGlvbiBmdCh0KXtjb25zdCBlPVooKSxuPXtzaWQ6TSgpLGluaXQ6ITAsdGltZXN0YW1wOmUsc3RhcnRlZDplLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm4gaih7c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fSl9KG4pfTtyZXR1cm4gdCYmaHQobix0KSxufWZ1bmN0aW9uIGh0KHQsZT17fSl7aWYoZS51c2VyJiYoIXQuaXBBZGRyZXNzJiZlLnVzZXIuaXBfYWRkcmVzcyYmKHQuaXBBZGRyZXNzPWUudXNlci5pcF9hZGRyZXNzKSx0LmRpZHx8ZS5kaWR8fCh0LmRpZD1lLnVzZXIuaWR8fGUudXNlci5lbWFpbHx8ZS51c2VyLnVzZXJuYW1lKSksdC50aW1lc3RhbXA9ZS50aW1lc3RhbXB8fFooKSxlLmFibm9ybWFsX21lY2hhbmlzbSYmKHQuYWJub3JtYWxfbWVjaGFuaXNtPWUuYWJub3JtYWxfbWVjaGFuaXNtKSxlLmlnbm9yZUR1cmF0aW9uJiYodC5pZ25vcmVEdXJhdGlvbj1lLmlnbm9yZUR1cmF0aW9uKSxlLnNpZCYmKHQuc2lkPTMyPT09ZS5zaWQubGVuZ3RoP2Uuc2lkOk0oKSksdm9pZCAwIT09ZS5pbml0JiYodC5pbml0PWUuaW5pdCksIXQuZGlkJiZlLmRpZCYmKHQuZGlkPWAke2UuZGlkfWApLCJudW1iZXIiPT10eXBlb2YgZS5zdGFydGVkJiYodC5zdGFydGVkPWUuc3RhcnRlZCksdC5pZ25vcmVEdXJhdGlvbil0LmR1cmF0aW9uPXZvaWQgMDtlbHNlIGlmKCJudW1iZXIiPT10eXBlb2YgZS5kdXJhdGlvbil0LmR1cmF0aW9uPWUuZHVyYXRpb247ZWxzZXtjb25zdCBlPXQudGltZXN0YW1wLXQuc3RhcnRlZDt0LmR1cmF0aW9uPWU+PTA/ZTowfWUucmVsZWFzZSYmKHQucmVsZWFzZT1lLnJlbGVhc2UpLGUuZW52aXJvbm1lbnQmJih0LmVudmlyb25tZW50PWUuZW52aXJvbm1lbnQpLCF0LmlwQWRkcmVzcyYmZS5pcEFkZHJlc3MmJih0LmlwQWRkcmVzcz1lLmlwQWRkcmVzcyksIXQudXNlckFnZW50JiZlLnVzZXJBZ2VudCYmKHQudXNlckFnZW50PWUudXNlckFnZW50KSwibnVtYmVyIj09dHlwZW9mIGUuZXJyb3JzJiYodC5lcnJvcnM9ZS5lcnJvcnMpLGUuc3RhdHVzJiYodC5zdGF0dXM9ZS5zdGF0dXMpfWNvbnN0IHB0PSJfc2VudHJ5U3BhbiI7ZnVuY3Rpb24gbHQodCxlKXtlP2Z1bmN0aW9uKHQsZSxuKXt0cnl7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsZSx7dmFsdWU6bix3cml0YWJsZTohMCxjb25maWd1cmFibGU6ITB9KX1jYXRjaChuKXtTJiZOLmxvZyhgRmFpbGVkIHRvIGFkZCBub24tZW51bWVyYWJsZSBwcm9wZXJ0eSAiJHtlfSIgdG8gb2JqZWN0YCx0KX19KHQscHQsZSk6ZGVsZXRlIHRbcHRdfWZ1bmN0aW9uIGR0KHQpe3JldHVybiB0W3B0XX1jbGFzcyBtdHtjb25zdHJ1Y3Rvcigpe3RoaXMuXz0hMSx0aGlzLlM9W10sdGhpcy5OPVtdLHRoaXMuaz1bXSx0aGlzLkM9W10sdGhpcy5EPXt9LHRoaXMuVD17fSx0aGlzLk89e30sdGhpcy5qPXt9LHRoaXMuUj17fSx0aGlzLkE9Z3QoKX1jbG9uZSgpe2NvbnN0IHQ9bmV3IG10O3JldHVybiB0Lms9Wy4uLnRoaXMua10sdC5UPXsuLi50aGlzLlR9LHQuTz17Li4udGhpcy5PfSx0Lmo9ey4uLnRoaXMuan0sdC5EPXRoaXMuRCx0Lkk9dGhpcy5JLHQuUD10aGlzLlAsdC5VPXRoaXMuVSx0Lk09dGhpcy5NLHQuTj1bLi4udGhpcy5OXSx0Lkw9dGhpcy5MLHQuQz1bLi4udGhpcy5DXSx0LlI9ey4uLnRoaXMuUn0sdC5BPXsuLi50aGlzLkF9LHQuQj10aGlzLkIsbHQodCxkdCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5CPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuQn1hZGRTY29wZUxpc3RlbmVyKHQpe3RoaXMuUy5wdXNoKHQpfWFkZEV2ZW50UHJvY2Vzc29yKHQpe3JldHVybiB0aGlzLk4ucHVzaCh0KSx0aGlzfXNldFVzZXIodCl7cmV0dXJuIHRoaXMuRD10fHx7ZW1haWw6dm9pZCAwLGlkOnZvaWQgMCxpcF9hZGRyZXNzOnZvaWQgMCx1c2VybmFtZTp2b2lkIDB9LHRoaXMuUCYmaHQodGhpcy5QLHt1c2VyOnR9KSx0aGlzLkcoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5EfWdldFJlcXVlc3RTZXNzaW9uKCl7cmV0dXJuIHRoaXMuTH1zZXRSZXF1ZXN0U2Vzc2lvbih0KXtyZXR1cm4gdGhpcy5MPXQsdGhpc31zZXRUYWdzKHQpe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCwuLi50fSx0aGlzLkcoKSx0aGlzfXNldFRhZyh0LGUpe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCxbdF06ZX0sdGhpcy5HKCksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMuTz17Li4udGhpcy5PLC4uLnR9LHRoaXMuRygpLHRoaXN9c2V0RXh0cmEodCxlKXtyZXR1cm4gdGhpcy5PPXsuLi50aGlzLk8sW3RdOmV9LHRoaXMuRygpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuTT10LHRoaXMuRygpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuST10LHRoaXMuRygpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLlU9dCx0aGlzLkcoKSx0aGlzfXNldENvbnRleHQodCxlKXtyZXR1cm4gbnVsbD09PWU/ZGVsZXRlIHRoaXMualt0XTp0aGlzLmpbdF09ZSx0aGlzLkcoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5QPXQ6ZGVsZXRlIHRoaXMuUCx0aGlzLkcoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5QfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBlPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxbbixyXT1lIGluc3RhbmNlb2YgbXQ/W2UuZ2V0U2NvcGVEYXRhKCksZS5nZXRSZXF1ZXN0U2Vzc2lvbigpXTpkKGUpP1t0LHQucmVxdWVzdFNlc3Npb25dOltdLHt0YWdzOm8sZXh0cmE6cyx1c2VyOmksY29udGV4dHM6YyxsZXZlbDp1LGZpbmdlcnByaW50OmE9W10scHJvcGFnYXRpb25Db250ZXh0OmZ9PW58fHt9O3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCwuLi5vfSx0aGlzLk89ey4uLnRoaXMuTywuLi5zfSx0aGlzLmo9ey4uLnRoaXMuaiwuLi5jfSxpJiZPYmplY3Qua2V5cyhpKS5sZW5ndGgmJih0aGlzLkQ9aSksdSYmKHRoaXMuST11KSxhLmxlbmd0aCYmKHRoaXMuTT1hKSxmJiYodGhpcy5BPWYpLHImJih0aGlzLkw9ciksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLms9W10sdGhpcy5UPXt9LHRoaXMuTz17fSx0aGlzLkQ9e30sdGhpcy5qPXt9LHRoaXMuST12b2lkIDAsdGhpcy5VPXZvaWQgMCx0aGlzLk09dm9pZCAwLHRoaXMuTD12b2lkIDAsdGhpcy5QPXZvaWQgMCxsdCh0aGlzLHZvaWQgMCksdGhpcy5DPVtdLHRoaXMuQT1ndCgpLHRoaXMuRygpLHRoaXN9YWRkQnJlYWRjcnVtYih0LGUpe2NvbnN0IG49Im51bWJlciI9PXR5cGVvZiBlP2U6MTAwO2lmKG48PTApcmV0dXJuIHRoaXM7Y29uc3Qgcj17dGltZXN0YW1wOlYoKSwuLi50fSxvPXRoaXMuaztyZXR1cm4gby5wdXNoKHIpLHRoaXMuaz1vLmxlbmd0aD5uP28uc2xpY2UoLW4pOm8sdGhpcy5HKCksdGhpc31nZXRMYXN0QnJlYWRjcnVtYigpe3JldHVybiB0aGlzLmtbdGhpcy5rLmxlbmd0aC0xXX1jbGVhckJyZWFkY3J1bWJzKCl7cmV0dXJuIHRoaXMuaz1bXSx0aGlzLkcoKSx0aGlzfWFkZEF0dGFjaG1lbnQodCl7cmV0dXJuIHRoaXMuQy5wdXNoKHQpLHRoaXN9Y2xlYXJBdHRhY2htZW50cygpe3JldHVybiB0aGlzLkM9W10sdGhpc31nZXRTY29wZURhdGEoKXtyZXR1cm57YnJlYWRjcnVtYnM6dGhpcy5rLGF0dGFjaG1lbnRzOnRoaXMuQyxjb250ZXh0czp0aGlzLmosdGFnczp0aGlzLlQsZXh0cmE6dGhpcy5PLHVzZXI6dGhpcy5ELGxldmVsOnRoaXMuSSxmaW5nZXJwcmludDp0aGlzLk18fFtdLGV2ZW50UHJvY2Vzc29yczp0aGlzLk4scHJvcGFnYXRpb25Db250ZXh0OnRoaXMuQSxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6dGhpcy5SLHRyYW5zYWN0aW9uTmFtZTp0aGlzLlUsc3BhbjpkdCh0aGlzKX19c2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHQpe3JldHVybiB0aGlzLlI9ey4uLnRoaXMuUiwuLi50fSx0aGlzfXNldFByb3BhZ2F0aW9uQ29udGV4dCh0KXtyZXR1cm4gdGhpcy5BPXQsdGhpc31nZXRQcm9wYWdhdGlvbkNvbnRleHQoKXtyZXR1cm4gdGhpcy5BfWNhcHR1cmVFeGNlcHRpb24odCxlKXtjb25zdCBuPWUmJmUuZXZlbnRfaWQ/ZS5ldmVudF9pZDpNKCk7aWYoIXRoaXMuQilyZXR1cm4gTi53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXhjZXB0aW9uISIpLG47Y29uc3Qgcj1uZXcgRXJyb3IoIlNlbnRyeSBzeW50aGV0aWNFeGNlcHRpb24iKTtyZXR1cm4gdGhpcy5CLmNhcHR1cmVFeGNlcHRpb24odCx7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246ciwuLi5lLGV2ZW50X2lkOm59LHRoaXMpLG59Y2FwdHVyZU1lc3NhZ2UodCxlLG4pe2NvbnN0IHI9biYmbi5ldmVudF9pZD9uLmV2ZW50X2lkOk0oKTtpZighdGhpcy5CKXJldHVybiBOLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBtZXNzYWdlISIpLHI7Y29uc3Qgbz1uZXcgRXJyb3IodCk7cmV0dXJuIHRoaXMuQi5jYXB0dXJlTWVzc2FnZSh0LGUse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOm8sLi4ubixldmVudF9pZDpyfSx0aGlzKSxyfWNhcHR1cmVFdmVudCh0LGUpe2NvbnN0IG49ZSYmZS5ldmVudF9pZD9lLmV2ZW50X2lkOk0oKTtyZXR1cm4gdGhpcy5CPyh0aGlzLkIuY2FwdHVyZUV2ZW50KHQsey4uLmUsZXZlbnRfaWQ6bn0sdGhpcyksbik6KE4ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV2ZW50ISIpLG4pfUcoKXt0aGlzLl98fCh0aGlzLl89ITAsdGhpcy5TLmZvckVhY2goKHQ9Pnt0KHRoaXMpfSkpLHRoaXMuXz0hMSl9fWZ1bmN0aW9uIGd0KCl7cmV0dXJue3RyYWNlSWQ6TSgpLHNwYW5JZDpNKCkuc3Vic3RyaW5nKDE2KX19ZnVuY3Rpb24geXQoKXtyZXR1cm4gJHQodXQoKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9Y2xhc3MgYnR7Y29uc3RydWN0b3IodCxlKXtsZXQgbixyO249dHx8bmV3IG10LHI9ZXx8bmV3IG10LHRoaXMuSj1be3Njb3BlOm59XSx0aGlzLkg9cn13aXRoU2NvcGUodCl7Y29uc3QgZT10aGlzLlcoKTtsZXQgbjt0cnl7bj10KGUpfWNhdGNoKHQpe3Rocm93IHRoaXMuWSgpLHR9cmV0dXJuIG0obik/bi50aGVuKCh0PT4odGhpcy5ZKCksdCkpLCh0PT57dGhyb3cgdGhpcy5ZKCksdH0pKToodGhpcy5ZKCksbil9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnR9Z2V0U2NvcGUoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLnNjb3BlfWdldElzb2xhdGlvblNjb3BlKCl7cmV0dXJuIHRoaXMuSH1nZXRTdGFjaygpe3JldHVybiB0aGlzLkp9Z2V0U3RhY2tUb3AoKXtyZXR1cm4gdGhpcy5KW3RoaXMuSi5sZW5ndGgtMV19Vygpe2NvbnN0IHQ9dGhpcy5nZXRTY29wZSgpLmNsb25lKCk7cmV0dXJuIHRoaXMuZ2V0U3RhY2soKS5wdXNoKHtjbGllbnQ6dGhpcy5nZXRDbGllbnQoKSxzY29wZTp0fSksdH1ZKCl7cmV0dXJuISh0aGlzLmdldFN0YWNrKCkubGVuZ3RoPD0xKSYmISF0aGlzLmdldFN0YWNrKCkucG9wKCl9fWZ1bmN0aW9uIHZ0KCl7Y29uc3QgdD1hdCh1dCgpKTtyZXR1cm4gdC5odWJ8fCh0Lmh1Yj1uZXcgYnQoYigiZGVmYXVsdEN1cnJlbnRTY29wZSIsKCgpPT5uZXcgbXQpKSxiKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgoKT0+bmV3IG10KSkpKSx0Lmh1Yn1mdW5jdGlvbiBfdCh0KXtyZXR1cm4gdnQoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gd3QodCxlKXtjb25zdCBuPXZ0KCk7cmV0dXJuIG4ud2l0aFNjb3BlKCgoKT0+KG4uZ2V0U3RhY2tUb3AoKS5zY29wZT10LGUodCkpKSl9ZnVuY3Rpb24gU3QodCl7cmV0dXJuIHZ0KCkud2l0aFNjb3BlKCgoKT0+dCh2dCgpLmdldElzb2xhdGlvblNjb3BlKCkpKSl9ZnVuY3Rpb24gJHQodCl7Y29uc3QgZT1hdCh0KTtyZXR1cm4gZS5hY3M/ZS5hY3M6e3dpdGhJc29sYXRpb25TY29wZTpTdCx3aXRoU2NvcGU6X3Qsd2l0aFNldFNjb3BlOnd0LHdpdGhTZXRJc29sYXRpb25TY29wZToodCxlKT0+U3QoZSksZ2V0Q3VycmVudFNjb3BlOigpPT52dCgpLmdldFNjb3BlKCksZ2V0SXNvbGF0aW9uU2NvcGU6KCk9PnZ0KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKX19Y29uc3QgRXQ9InNlbnRyeS5zb3VyY2UiLHh0PSJzZW50cnkuc2FtcGxlX3JhdGUiLE50PSJzZW50cnkub3AiLGt0PSJzZW50cnkub3JpZ2luIixDdD0wLER0PTEsVHQ9InByb2R1Y3Rpb24iLE90PSJfZnJvemVuRHNjIjtmdW5jdGlvbiBqdCh0KXtjb25zdCBlPXl0KCk7aWYoIWUpcmV0dXJue307Y29uc3Qgbj1mdW5jdGlvbih0LGUpe2NvbnN0IG49ZS5nZXRPcHRpb25zKCkse3B1YmxpY0tleTpyfT1lLmdldERzbigpfHx7fSxvPWooe2Vudmlyb25tZW50Om4uZW52aXJvbm1lbnR8fFR0LHJlbGVhc2U6bi5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0fSk7cmV0dXJuIGUuZW1pdCgiY3JlYXRlRHNjIixvKSxvfShVdCh0KS50cmFjZV9pZHx8IiIsZSkscj1CdCh0KTtpZighcilyZXR1cm4gbjtjb25zdCBvPXJbT3RdO2lmKG8pcmV0dXJuIG87Y29uc3Qgcz1VdChyKSxpPXMuZGF0YXx8e30sYz1pW3h0XTtudWxsIT1jJiYobi5zYW1wbGVfcmF0ZT1gJHtjfWApO2NvbnN0IHU9aVtFdF07cmV0dXJuIHUmJiJ1cmwiIT09dSYmKG4udHJhbnNhY3Rpb249cy5kZXNjcmlwdGlvbiksbi5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOmV9PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gZT09PVJ0fShyKSksZS5lbWl0KCJjcmVhdGVEc2MiLG4pLG59Y29uc3QgUnQ9MTtmdW5jdGlvbiBBdCh0KXtjb25zdHtzcGFuSWQ6ZSx0cmFjZUlkOm59PXQuc3BhbkNvbnRleHQoKSx7cGFyZW50X3NwYW5faWQ6cn09VXQodCk7cmV0dXJuIGooe3BhcmVudF9zcGFuX2lkOnIsc3Bhbl9pZDplLHRyYWNlX2lkOm59KX1mdW5jdGlvbiBJdCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/UHQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlP1B0KHQuZ2V0VGltZSgpKTpaKCl9ZnVuY3Rpb24gUHQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIFV0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO3RyeXtjb25zdHtzcGFuSWQ6ZSx0cmFjZUlkOm59PXQuc3BhbkNvbnRleHQoKTtpZihmdW5jdGlvbih0KXtjb25zdCBlPXQ7cmV0dXJuISEoZS5hdHRyaWJ1dGVzJiZlLnN0YXJ0VGltZSYmZS5uYW1lJiZlLmVuZFRpbWUmJmUuc3RhdHVzKX0odCkpe2NvbnN0e2F0dHJpYnV0ZXM6cixzdGFydFRpbWU6byxuYW1lOnMsZW5kVGltZTppLHBhcmVudFNwYW5JZDpjLHN0YXR1czp1fT10O3JldHVybiBqKHtzcGFuX2lkOmUsdHJhY2VfaWQ6bixkYXRhOnIsZGVzY3JpcHRpb246cyxwYXJlbnRfc3Bhbl9pZDpjLHN0YXJ0X3RpbWVzdGFtcDpJdChvKSx0aW1lc3RhbXA6SXQoaSl8fHZvaWQgMCxzdGF0dXM6TXQodSksb3A6cltOdF0sb3JpZ2luOnJba3RdLHE6dm9pZCAwfSl9cmV0dXJue3NwYW5faWQ6ZSx0cmFjZV9pZDpufX1jYXRjaCh0KXtyZXR1cm57fX19ZnVuY3Rpb24gTXQodCl7aWYodCYmdC5jb2RlIT09Q3QpcmV0dXJuIHQuY29kZT09PUR0PyJvayI6dC5tZXNzYWdlfHwidW5rbm93bl9lcnJvciJ9Y29uc3QgTHQ9Il9zZW50cnlSb290U3BhbiI7ZnVuY3Rpb24gQnQodCl7cmV0dXJuIHRbTHRdfHx0fWZ1bmN0aW9uIEd0KHQsZSxuLHIpe2NvbnN0IG89b3Qobikscz10LnR5cGUmJiJyZXBsYXlfZXZlbnQiIT09dC50eXBlP3QudHlwZToiZXZlbnQiOyFmdW5jdGlvbih0LGUpe2UmJih0LnNkaz10LnNka3x8e30sdC5zZGsubmFtZT10LnNkay5uYW1lfHxlLm5hbWUsdC5zZGsudmVyc2lvbj10LnNkay52ZXJzaW9ufHxlLnZlcnNpb24sdC5zZGsuaW50ZWdyYXRpb25zPVsuLi50LnNkay5pbnRlZ3JhdGlvbnN8fFtdLC4uLmUuaW50ZWdyYXRpb25zfHxbXV0sdC5zZGsucGFja2FnZXM9Wy4uLnQuc2RrLnBhY2thZ2VzfHxbXSwuLi5lLnBhY2thZ2VzfHxbXV0pfSh0LG4mJm4uc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEmJnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4uZSYme3NkazplfSwuLi4hIW4mJnImJntkc246ayhyKX0sLi4ubyYme3RyYWNlOmooey4uLm99KX19fSh0LG8scixlKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIFEoaSxbW3t0eXBlOnN9LHRdXSl9Y29uc3QgSnQ9Il9fU0VOVFJZX1NVUFBSRVNTX1RSQUNJTkdfXyI7ZnVuY3Rpb24genQodCl7Y29uc3QgZT0kdCh1dCgpKTtyZXR1cm4gZS5zdXBwcmVzc1RyYWNpbmc/ZS5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3QgZT0kdCh1dCgpKTtpZigyPT09dC5sZW5ndGgpe2NvbnN0W24scl09dDtyZXR1cm4gbj9lLndpdGhTZXRTY29wZShuLHIpOmUud2l0aFNjb3BlKHIpfXJldHVybiBlLndpdGhTY29wZSh0WzBdKX0oKGU9PihlLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W0p0XTohMH0pLHQoKSkpKX1mdW5jdGlvbiBIdCh0LGUpe2NvbnN0e2ZpbmdlcnByaW50Om4sc3BhbjpyLGJyZWFkY3J1bWJzOm8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnN9PWU7IWZ1bmN0aW9uKHQsZSl7Y29uc3R7ZXh0cmE6bix0YWdzOnIsdXNlcjpvLGNvbnRleHRzOnMsbGV2ZWw6aSx0cmFuc2FjdGlvbk5hbWU6Y309ZSx1PWoobik7dSYmT2JqZWN0LmtleXModSkubGVuZ3RoJiYodC5leHRyYT17Li4udSwuLi50LmV4dHJhfSk7Y29uc3QgYT1qKHIpO2EmJk9iamVjdC5rZXlzKGEpLmxlbmd0aCYmKHQudGFncz17Li4uYSwuLi50LnRhZ3N9KTtjb25zdCBmPWoobyk7ZiYmT2JqZWN0LmtleXMoZikubGVuZ3RoJiYodC51c2VyPXsuLi5mLC4uLnQudXNlcn0pO2NvbnN0IGg9aihzKTtoJiZPYmplY3Qua2V5cyhoKS5sZW5ndGgmJih0LmNvbnRleHRzPXsuLi5oLC4uLnQuY29udGV4dHN9KTtpJiYodC5sZXZlbD1pKTtjJiYidHJhbnNhY3Rpb24iIT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1jKX0odCxlKSxyJiZmdW5jdGlvbih0LGUpe3QuY29udGV4dHM9e3RyYWNlOkF0KGUpLC4uLnQuY29udGV4dHN9LHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXtkeW5hbWljU2FtcGxpbmdDb250ZXh0Omp0KGUpLC4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhfTtjb25zdCBuPUJ0KGUpLHI9VXQobikuZGVzY3JpcHRpb247ciYmIXQudHJhbnNhY3Rpb24mJiJ0cmFuc2FjdGlvbiI9PT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPXIpfSh0LHIpLGZ1bmN0aW9uKHQsZSl7dC5maW5nZXJwcmludD10LmZpbmdlcnByaW50P2Z1bmN0aW9uKHQpe3JldHVybiBBcnJheS5pc0FycmF5KHQpP3Q6W3RdfSh0LmZpbmdlcnByaW50KTpbXSxlJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChlKSk7dC5maW5nZXJwcmludCYmIXQuZmluZ2VycHJpbnQubGVuZ3RoJiZkZWxldGUgdC5maW5nZXJwcmludH0odCxuKSxmdW5jdGlvbih0LGUpe2NvbnN0IG49Wy4uLnQuYnJlYWRjcnVtYnN8fFtdLC4uLmVdO3QuYnJlYWRjcnVtYnM9bi5sZW5ndGg/bjp2b2lkIDB9KHQsbyksZnVuY3Rpb24odCxlKXt0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17Li4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEsLi4uZX19KHQscyl9Y29uc3QgV3Q9IjciO2Z1bmN0aW9uIFl0KHQsZSl7cmV0dXJuIG49e3NlbnRyeV9rZXk6dC5wdWJsaWNLZXksc2VudHJ5X3ZlcnNpb246V3QsLi4uZSYme3NlbnRyeV9jbGllbnQ6YCR7ZS5uYW1lfS8ke2UudmVyc2lvbn1gfX0sT2JqZWN0LmtleXMobikubWFwKCh0PT5gJHtlbmNvZGVVUklDb21wb25lbnQodCl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KG5bdF0pfWApKS5qb2luKCImIik7dmFyIG59Y29uc3QgcXQ9NjQ7ZnVuY3Rpb24gRnQodCxlLG49cSh0LmJ1ZmZlclNpemV8fHF0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24obyl7Y29uc3Qgcz1bXTtpZihYKG8sKChlLG4pPT57Y29uc3Qgbz1ydChuKTtpZihmdW5jdGlvbih0LGUsbj1EYXRlLm5vdygpKXtyZXR1cm4gZnVuY3Rpb24odCxlKXtyZXR1cm4gdFtlXXx8dC5hbGx8fDB9KHQsZSk+bn0ocixvKSl7Y29uc3Qgcj1LdChlLG4pO3QucmVjb3JkRHJvcHBlZEV2ZW50KCJyYXRlbGltaXRfYmFja29mZiIsbyxyKX1lbHNlIHMucHVzaChlKX0pKSwwPT09cy5sZW5ndGgpcmV0dXJuIFcoe30pO2NvbnN0IGk9UShvWzBdLHMpLGM9ZT0+e1goaSwoKG4scik9Pntjb25zdCBvPUt0KG4scik7dC5yZWNvcmREcm9wcGVkRXZlbnQoZSxydChyKSxvKX0pKX07cmV0dXJuIG4uYWRkKCgoKT0+ZSh7Ym9keTpldChpKX0pLnRoZW4oKHQ9Pih2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJmN0JiZOLndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPWl0KHIsdCksdCkpLCh0PT57dGhyb3cgYygibmV0d29ya19lcnJvciIpLHR9KSkpKS50aGVuKCh0PT50KSwodD0+e2lmKHQgaW5zdGFuY2VvZiBDKXJldHVybiBjdCYmTi5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIiksYygicXVldWVfb3ZlcmZsb3ciKSxXKHt9KTt0aHJvdyB0fSkpfSxmbHVzaDp0PT5uLmRyYWluKHQpfX1mdW5jdGlvbiBLdCh0LGUpe2lmKCJldmVudCI9PT1lfHwidHJhbnNhY3Rpb24iPT09ZSlyZXR1cm4gQXJyYXkuaXNBcnJheSh0KT90WzFdOnZvaWQgMH1jb25zdCBWdD1TeW1ib2woIkFnZW50QmFzZUludGVybmFsU3RhdGUiKTtjbGFzcyBadCBleHRlbmRzIGguQWdlbnR7W1Z0XTtvcHRpb25zO2tlZXBBbGl2ZTtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzW1Z0XT17fX1pc1NlY3VyZUVuZHBvaW50KHQpe2lmKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIHQuc2VjdXJlRW5kcG9pbnQpcmV0dXJuIHQuc2VjdXJlRW5kcG9pbnQ7aWYoInN0cmluZyI9PXR5cGVvZiB0LnByb3RvY29sKXJldHVybiJodHRwczoiPT09dC5wcm90b2NvbH1jb25zdHtzdGFjazplfT1uZXcgRXJyb3I7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBlJiZlLnNwbGl0KCJcbiIpLnNvbWUoKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKSl9Y3JlYXRlU29ja2V0KHQsZSxuKXtjb25zdCByPXsuLi5lLHNlY3VyZUVuZHBvaW50OnRoaXMuaXNTZWN1cmVFbmRwb2ludChlKX07UHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKCk9PnRoaXMuY29ubmVjdCh0LHIpKSkudGhlbigobz0+e2lmKG8gaW5zdGFuY2VvZiBoLkFnZW50KXJldHVybiBvLmFkZFJlcXVlc3QodCxyKTt0aGlzW1Z0XS5jdXJyZW50U29ja2V0PW8sc3VwZXIuY3JlYXRlU29ja2V0KHQsZSxuKX0pLG4pfWNyZWF0ZUNvbm5lY3Rpb24oKXtjb25zdCB0PXRoaXNbVnRdLmN1cnJlbnRTb2NrZXQ7aWYodGhpc1tWdF0uY3VycmVudFNvY2tldD12b2lkIDAsIXQpdGhyb3cgbmV3IEVycm9yKCJObyBzb2NrZXQgd2FzIHJldHVybmVkIGluIHRoZSBgY29ubmVjdCgpYCBmdW5jdGlvbiIpO3JldHVybiB0fWdldCBkZWZhdWx0UG9ydCgpe3JldHVybiB0aGlzW1Z0XS5kZWZhdWx0UG9ydD8/KCJodHRwczoiPT09dGhpcy5wcm90b2NvbD80NDM6ODApfXNldCBkZWZhdWx0UG9ydCh0KXt0aGlzW1Z0XSYmKHRoaXNbVnRdLmRlZmF1bHRQb3J0PXQpfWdldCBwcm90b2NvbCgpe3JldHVybiB0aGlzW1Z0XS5wcm90b2NvbD8/KHRoaXMuaXNTZWN1cmVFbmRwb2ludCgpPyJodHRwczoiOiJodHRwOiIpfXNldCBwcm90b2NvbCh0KXt0aGlzW1Z0XSYmKHRoaXNbVnRdLnByb3RvY29sPXQpfX1mdW5jdGlvbiBRdCguLi50KXtOLmxvZygiW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXSIsLi4udCl9ZnVuY3Rpb24gWHQodCl7cmV0dXJuIG5ldyBQcm9taXNlKCgoZSxuKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBzKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIFF0KCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgcygpO2NvbnN0IGY9dS5zbGljZSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLG4obmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGw9K3BbMV0sZD1wLnNsaWNlKDIpLmpvaW4oIiAiKSxtPXt9O2Zvcihjb25zdCBlIG9mIGYpe2lmKCFlKWNvbnRpbnVlO2NvbnN0IHI9ZS5pbmRleE9mKCI6Iik7aWYoLTE9PT1yKXJldHVybiB0LmRlc3Ryb3koKSxuKG5ldyBFcnJvcihgSW52YWxpZCBoZWFkZXIgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlOiAiJHtlfSJgKSk7Y29uc3Qgbz1lLnNsaWNlKDAscikudG9Mb3dlckNhc2UoKSxzPWUuc2xpY2UocisxKS50cmltU3RhcnQoKSxpPW1bb107InN0cmluZyI9PXR5cGVvZiBpP21bb109W2ksc106QXJyYXkuaXNBcnJheShpKT9pLnB1c2gocyk6bVtvXT1zfVF0KCJnb3QgcHJveHkgc2VydmVyIHJlc3BvbnNlOiAlbyAlbyIsaCxtKSxpKCksZSh7Y29ubmVjdDp7c3RhdHVzQ29kZTpsLHN0YXR1c1RleHQ6ZCxoZWFkZXJzOm19LGJ1ZmZlcmVkOnV9KX0oYyk6dC5vbmNlKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gaSgpe3QucmVtb3ZlTGlzdGVuZXIoImVuZCIsYyksdC5yZW1vdmVMaXN0ZW5lcigiZXJyb3IiLHUpLHQucmVtb3ZlTGlzdGVuZXIoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBjKCl7aSgpLFF0KCJvbmVuZCIpLG4obmV3IEVycm9yKCJQcm94eSBjb25uZWN0aW9uIGVuZGVkIGJlZm9yZSByZWNlaXZpbmcgQ09OTkVDVCByZXNwb25zZSIpKX1mdW5jdGlvbiB1KHQpe2koKSxRdCgib25lcnJvciAlbyIsdCksbih0KX10Lm9uKCJlcnJvciIsdSksdC5vbigiZW5kIixjKSxzKCl9KSl9ZnVuY3Rpb24gdGUoLi4udCl7Ti5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIGVlIGV4dGVuZHMgWnR7c3RhdGljIHByb3RvY29scz1bImh0dHAiLCJodHRwcyJdO3Byb3h5O3Byb3h5SGVhZGVycztjb25uZWN0T3B0cztjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKGUpLHRoaXMub3B0aW9ucz17fSx0aGlzLnByb3h5PSJzdHJpbmciPT10eXBlb2YgdD9uZXcgVVJMKHQpOnQsdGhpcy5wcm94eUhlYWRlcnM9ZT8uaGVhZGVycz8/e30sdGUoIkNyZWF0aW5nIG5ldyBIdHRwc1Byb3h5QWdlbnQgaW5zdGFuY2U6ICVvIix0aGlzLnByb3h5LmhyZWYpO2NvbnN0IG49KHRoaXMucHJveHkuaG9zdG5hbWV8fHRoaXMucHJveHkuaG9zdCkucmVwbGFjZSgvXlxbfFxdJC9nLCIiKSxyPXRoaXMucHJveHkucG9ydD9wYXJzZUludCh0aGlzLnByb3h5LnBvcnQsMTApOiJodHRwczoiPT09dGhpcy5wcm94eS5wcm90b2NvbD80NDM6ODA7dGhpcy5jb25uZWN0T3B0cz17QUxQTlByb3RvY29sczpbImh0dHAvMS4xIl0sLi4uZT9yZShlLCJoZWFkZXJzIik6bnVsbCxob3N0Om4scG9ydDpyfX1hc3luYyBjb25uZWN0KHQsZSl7Y29uc3R7cHJveHk6bn09dGhpcztpZighZS5ob3N0KXRocm93IG5ldyBUeXBlRXJyb3IoJ05vICJob3N0IiBwcm92aWRlZCcpO2xldCByO2lmKCJodHRwczoiPT09bi5wcm90b2NvbCl7dGUoIkNyZWF0aW5nIGB0bHMuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IHQ9dGhpcy5jb25uZWN0T3B0cy5zZXJ2ZXJuYW1lfHx0aGlzLmNvbm5lY3RPcHRzLmhvc3Q7cj1mLmNvbm5lY3Qoey4uLnRoaXMuY29ubmVjdE9wdHMsc2VydmVybmFtZTp0JiZhLmlzSVAodCk/dm9pZCAwOnR9KX1lbHNlIHRlKCJDcmVhdGluZyBgbmV0LlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKSxyPWEuY29ubmVjdCh0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCBvPSJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLnByb3h5SGVhZGVycz90aGlzLnByb3h5SGVhZGVycygpOnsuLi50aGlzLnByb3h5SGVhZGVyc30scz1hLmlzSVB2NihlLmhvc3QpP2BbJHtlLmhvc3R9XWA6ZS5ob3N0O2xldCBpPWBDT05ORUNUICR7c306JHtlLnBvcnR9IEhUVFAvMS4xXHJcbmA7aWYobi51c2VybmFtZXx8bi5wYXNzd29yZCl7Y29uc3QgdD1gJHtkZWNvZGVVUklDb21wb25lbnQobi51c2VybmFtZSl9OiR7ZGVjb2RlVVJJQ29tcG9uZW50KG4ucGFzc3dvcmQpfWA7b1siUHJveHktQXV0aG9yaXphdGlvbiJdPWBCYXNpYyAke0J1ZmZlci5mcm9tKHQpLnRvU3RyaW5nKCJiYXNlNjQiKX1gfW8uSG9zdD1gJHtzfToke2UucG9ydH1gLG9bIlByb3h5LUNvbm5lY3Rpb24iXXx8KG9bIlByb3h5LUNvbm5lY3Rpb24iXT10aGlzLmtlZXBBbGl2ZT8iS2VlcC1BbGl2ZSI6ImNsb3NlIik7Zm9yKGNvbnN0IHQgb2YgT2JqZWN0LmtleXMobykpaSs9YCR7dH06ICR7b1t0XX1cclxuYDtjb25zdCBjPVh0KHIpO3Iud3JpdGUoYCR7aX1cclxuYCk7Y29uc3R7Y29ubmVjdDp1LGJ1ZmZlcmVkOmh9PWF3YWl0IGM7aWYodC5lbWl0KCJwcm94eUNvbm5lY3QiLHUpLHRoaXMuZW1pdCgicHJveHlDb25uZWN0Iix1LHQpLDIwMD09PXUuc3RhdHVzQ29kZSl7aWYodC5vbmNlKCJzb2NrZXQiLG5lKSxlLnNlY3VyZUVuZHBvaW50KXt0ZSgiVXBncmFkaW5nIHNvY2tldCBjb25uZWN0aW9uIHRvIFRMUyIpO2NvbnN0IHQ9ZS5zZXJ2ZXJuYW1lfHxlLmhvc3Q7cmV0dXJuIGYuY29ubmVjdCh7Li4ucmUoZSwiaG9zdCIsInBhdGgiLCJwb3J0Iiksc29ja2V0OnIsc2VydmVybmFtZTphLmlzSVAodCk/dm9pZCAwOnR9KX1yZXR1cm4gcn1yLmRlc3Ryb3koKTtjb25zdCBwPW5ldyBhLlNvY2tldCh7d3JpdGFibGU6ITF9KTtyZXR1cm4gcC5yZWFkYWJsZT0hMCx0Lm9uY2UoInNvY2tldCIsKHQ9Pnt0ZSgiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkpLHB9fWZ1bmN0aW9uIG5lKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gcmUodCwuLi5lKXtjb25zdCBuPXt9O2xldCByO2ZvcihyIGluIHQpZS5pbmNsdWRlcyhyKXx8KG5bcl09dFtyXSk7cmV0dXJuIG59Y29uc3Qgb2U9MzI3Njg7ZnVuY3Rpb24gc2UodCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBpZT1uO2xldCBjZSx1ZT0hMTtmdW5jdGlvbiBhZSh0KXtpZS5kZWJ1ZyYmY29uc29sZS5sb2coYFtBTlIgV29ya2VyXSAke3R9YCl9dmFyIGZlLGhlLHBlO2NvbnN0IGxlPWZ1bmN0aW9uKHQpe2xldCBlO3RyeXtlPW5ldyBVUkwodC51cmwpfWNhdGNoKGUpe3JldHVybiB4KCgoKT0+e2NvbnNvbGUud2FybigiW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4iKX0pKSxGdCh0LCgoKT0+UHJvbWlzZS5yZXNvbHZlKHt9KSkpfWNvbnN0IG49Imh0dHBzOiI9PT1lLnByb3RvY29sLHI9ZnVuY3Rpb24odCxlKXtjb25zdHtub19wcm94eTpufT1wcm9jZXNzLmVudjtyZXR1cm4gbiYmbi5zcGxpdCgiLCIpLnNvbWUoKGU9PnQuaG9zdC5lbmRzV2l0aChlKXx8dC5ob3N0bmFtZS5lbmRzV2l0aChlKSkpP3ZvaWQgMDplfShlLHQucHJveHl8fChuP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89bj9pOnMsYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBlZShyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pO3JldHVybiB6dCgoKCk9Pntjb25zdCBlPWZ1bmN0aW9uKHQsZSxuKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDpzLHByb3RvY29sOmksc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKChoLHApPT57bGV0IGw9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBjKHtyZWFkKCl7dGhpcy5wdXNoKHQpLHRoaXMucHVzaChudWxsKX19KX0oZi5ib2R5KTtjb25zdCBkPXsuLi50LmhlYWRlcnN9O2YuYm9keS5sZW5ndGg+b2UmJihkWyJjb250ZW50LWVuY29kaW5nIl09Imd6aXAiLGw9bC5waXBlKHUoKSkpO2NvbnN0IG09ZS5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50Om4saGVhZGVyczpkLGhvc3RuYW1lOnIscGF0aDpgJHtvfSR7YX1gLHBvcnQ6cyxwcm90b2NvbDppLGNhOnQuY2FDZXJ0c30sKHQ9Pnt0Lm9uKCJkYXRhIiwoKCk9Pnt9KSksdC5vbigiZW5kIiwoKCk9Pnt9KSksdC5zZXRFbmNvZGluZygidXRmOCIpO2NvbnN0IGU9dC5oZWFkZXJzWyJyZXRyeS1hZnRlciJdPz9udWxsLG49dC5oZWFkZXJzWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdPz9udWxsO2goe3N0YXR1c0NvZGU6dC5zdGF0dXNDb2RlLGhlYWRlcnM6eyJyZXRyeS1hZnRlciI6ZSwieC1zZW50cnktcmF0ZS1saW1pdHMiOkFycmF5LmlzQXJyYXkobik/blswXTpufX0pfSkpO20ub24oImVycm9yIixwKSxsLnBpcGUobSl9KSl9fSh0LHQuaHR0cE1vZHVsZT8/byxmKTtyZXR1cm4gRnQodCxlKX0pKX0oe3VybDooZmU9aWUuZHNuLGhlPWllLnR1bm5lbCxwZT1pZS5zZGtNZXRhZGF0YS5zZGssaGV8fGAke2Z1bmN0aW9uKHQpe3JldHVybmAke2Z1bmN0aW9uKHQpe2NvbnN0IGU9dC5wcm90b2NvbD9gJHt0LnByb3RvY29sfTpgOiIiLG49dC5wb3J0P2A6JHt0LnBvcnR9YDoiIjtyZXR1cm5gJHtlfS8vJHt0Lmhvc3R9JHtufSR7dC5wYXRoP2AvJHt0LnBhdGh9YDoiIn0vYXBpL2B9KHQpfSR7dC5wcm9qZWN0SWR9L2VudmVsb3BlL2B9KGZlKX0/JHtZdChmZSxwZSl9YCkscmVjb3JkRHJvcHBlZEV2ZW50OigpPT57fX0pO2FzeW5jIGZ1bmN0aW9uIGRlKCl7aWYoY2Upe2FlKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxodChjZSx7c3RhdHVzOiJhYm5vcm1hbCIsYWJub3JtYWxfbWVjaGFuaXNtOiJhbnJfZm9yZWdyb3VuZCJ9KTtjb25zdCB0PWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89b3Qobik7cmV0dXJuIFEoe3NlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZlJiZ7ZHNuOmsoZSl9fSxbImFnZ3JlZ2F0ZXMiaW4gdD9be3R5cGU6InNlc3Npb25zIn0sdF06W3t0eXBlOiJzZXNzaW9uIn0sdC50b0pTT04oKV1dKX0oY2UsaWUuZHNuLGllLnNka01ldGFkYXRhLGllLnR1bm5lbCk7YWUoSlNPTi5zdHJpbmdpZnkodCkpLGF3YWl0IGxlLnNlbmQodCk7dHJ5e2U/LnBvc3RNZXNzYWdlKCJzZXNzaW9uLWVuZGVkIil9Y2F0Y2godCl7fX19ZnVuY3Rpb24gbWUodCl7aWYoIXQpcmV0dXJuO2NvbnN0IGU9ZnVuY3Rpb24odCl7aWYoIXQubGVuZ3RoKXJldHVybltdO2NvbnN0IGU9QXJyYXkuZnJvbSh0KTtyZXR1cm4vc2VudHJ5V3JhcHBlZC8udGVzdChlW2UubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJmUucG9wKCksZS5yZXZlcnNlKCksUC50ZXN0KGVbZS5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmKGUucG9wKCksUC50ZXN0KGVbZS5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmZS5wb3AoKSksZS5zbGljZSgwLEEpLm1hcCgodD0+KHsuLi50LGZpbGVuYW1lOnQuZmlsZW5hbWV8fGVbZS5sZW5ndGgtMV0uZmlsZW5hbWUsZnVuY3Rpb246dC5mdW5jdGlvbnx8SX0pKSl9KHQpO2lmKGllLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIGUpdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9Ryh0LmZpbGVuYW1lLGllLmFwcFJvb3RQYXRoKSk7cmV0dXJuIGV9YXN5bmMgZnVuY3Rpb24gZ2UodCxlKXtpZih1ZSlyZXR1cm47dWU9ITAsYXdhaXQgZGUoKSxhZSgiU2VuZGluZyBldmVudCIpO2NvbnN0IG49e2V2ZW50X2lkOk0oKSxjb250ZXh0czppZS5jb250ZXh0cyxyZWxlYXNlOmllLnJlbGVhc2UsZW52aXJvbm1lbnQ6aWUuZW52aXJvbm1lbnQsZGlzdDppZS5kaXN0LHBsYXRmb3JtOiJub2RlIixsZXZlbDoiZXJyb3IiLGV4Y2VwdGlvbjp7dmFsdWVzOlt7dHlwZToiQXBwbGljYXRpb25Ob3RSZXNwb25kaW5nIix2YWx1ZTpgQXBwbGljYXRpb24gTm90IFJlc3BvbmRpbmcgZm9yIGF0IGxlYXN0ICR7aWUuYW5yVGhyZXNob2xkfSBtc2Asc3RhY2t0cmFjZTp7ZnJhbWVzOm1lKHQpfSxtZWNoYW5pc206e3R5cGU6IkFOUiJ9fV19LHRhZ3M6aWUuc3RhdGljVGFnc307ZSYmZnVuY3Rpb24odCxlKXtpZihIdCh0LGUpLCF0LmNvbnRleHRzPy50cmFjZSl7Y29uc3R7dHJhY2VJZDpuLHNwYW5JZDpyLHBhcmVudFNwYW5JZDpvfT1lLnByb3BhZ2F0aW9uQ29udGV4dDt0LmNvbnRleHRzPXt0cmFjZTp7dHJhY2VfaWQ6bixzcGFuX2lkOnIscGFyZW50X3NwYW5faWQ6b30sLi4udC5jb250ZXh0c319fShuLGUpO2NvbnN0IHI9R3QobixpZS5kc24saWUuc2RrTWV0YWRhdGEsaWUudHVubmVsKTthZShKU09OLnN0cmluZ2lmeShyKSksYXdhaXQgbGUuc2VuZChyKSxhd2FpdCBsZS5mbHVzaCgyZTMpLHNldFRpbWVvdXQoKCgpPT57cHJvY2Vzcy5leGl0KDApfSksNWUzKX1sZXQgeWU7aWYoYWUoIlN0YXJ0ZWQiKSxpZS5jYXB0dXJlU3RhY2tUcmFjZSl7YWUoIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyB0O2UuY29ubmVjdFRvTWFpblRocmVhZCgpLGFlKCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyBNYXA7ZS5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIiwodD0+e24uc2V0KHQucGFyYW1zLnNjcmlwdElkLHQucGFyYW1zLnVybCl9KSksZS5vbigiRGVidWdnZXIucGF1c2VkIiwodD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e2FlKCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPWllLmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT96KHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksZT0iXFwiPT09byl7Y29uc3Qgbj1lP3NlKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1lP3NlKHQpOnQ7bGV0e2RpcjpzLGJhc2U6aSxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChpPWkuc2xpY2UoMCwtMSpjLmxlbmd0aCkpLHN8fChzPSIuIik7Y29uc3QgdT1zLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYodT4tMSlyZXR1cm5gJHtzLnNsaWNlKHUrMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHtpfWA7aWYocy5zdGFydHNXaXRoKG4pKXtsZXQgdD1zLnNsaWNlKG4ubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdCYmKHQrPSI6IiksdCs9aSx0fXJldHVybiBpfX0oaWUuYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKCh0PT5mdW5jdGlvbih0LGUsbil7Y29uc3Qgcj1lP2UucmVwbGFjZSgvXmZpbGU6XC9cLy8sIiIpOnZvaWQgMCxvPXQubG9jYXRpb24uY29sdW1uTnVtYmVyP3QubG9jYXRpb24uY29sdW1uTnVtYmVyKzE6dm9pZCAwLHM9dC5sb2NhdGlvbi5saW5lTnVtYmVyP3QubG9jYXRpb24ubGluZU51bWJlcisxOnZvaWQgMDtyZXR1cm4gaih7ZmlsZW5hbWU6cixtb2R1bGU6bihyKSxmdW5jdGlvbjp0LmZ1bmN0aW9uTmFtZXx8SSxjb2xubzpvLGxpbmVubzpzLGluX2FwcDpyP0Yocik6dm9pZCAwfSl9KHQsbi5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCksaSkpKSx1PXNldFRpbWVvdXQoKCgpPT57Z2UoYykudGhlbihudWxsLCgoKT0+e2FlKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSw1ZTMpO2UucG9zdCgiUnVudGltZS5ldmFsdWF0ZSIse2V4cHJlc3Npb246Imdsb2JhbC5fX1NFTlRSWV9HRVRfU0NPUEVTX18oKTsiLHNpbGVudDohMCxyZXR1cm5CeVZhbHVlOiEwfSwoKHQsbik9Pnt0JiZhZShgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1uJiZuLnJlc3VsdD9uLnJlc3VsdC52YWx1ZTp2b2lkIDA7ZS5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxlLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSxnZShjLHIpLnRoZW4obnVsbCwoKCk9PnthZSgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSkpfWNhdGNoKHQpe3Rocm93IGUucG9zdCgiRGVidWdnZXIucmVzdW1lIiksZS5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksdH19KSkseWU9KCk9Pnt0cnl7ZS5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgoKT0+e2UucG9zdCgiRGVidWdnZXIucGF1c2UiKX0pKX1jYXRjaCh0KXt9fX1jb25zdHtwb2xsOmJlfT1mdW5jdGlvbih0LGUsbixyKXtjb25zdCBvPXQoKTtsZXQgcz0hMSxpPSEwO3JldHVybiBzZXRJbnRlcnZhbCgoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1zJiZ0PmUrbiYmKHM9ITAsaSYmcigpKSx0PGUrbiYmKHM9ITEpfSksMjApLHtwb2xsOigpPT57by5yZXNldCgpfSxlbmFibGVkOnQ9PntpPXR9fX0oKGZ1bmN0aW9uKCl7bGV0IHQ9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm57Z2V0VGltZU1zOigpPT57Y29uc3RbZSxuXT1wcm9jZXNzLmhydGltZSh0KTtyZXR1cm4gTWF0aC5mbG9vcigxZTMqZStuLzFlNil9LHJlc2V0OigpPT57dD1wcm9jZXNzLmhydGltZSgpfX19KSxpZS5wb2xsSW50ZXJ2YWwsaWUuYW5yVGhyZXNob2xkLChmdW5jdGlvbigpe2FlKCJXYXRjaGRvZyB0aW1lb3V0IikseWU/KGFlKCJQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UiKSx5ZSgpKTooYWUoIkNhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UiKSxnZSgpLnRoZW4obnVsbCwoKCk9PnthZSgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkIG9uIHdhdGNoZG9nIHRpbWVvdXQuIil9KSkpfSkpO2U/Lm9uKCJtZXNzYWdlIiwodD0+e3Quc2Vzc2lvbiYmKGNlPWZ0KHQuc2Vzc2lvbikpLGJlKCl9KSk7';
|
|
1791
|
+
const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA4LjAuMC1yYy4yICg3YTNlMTZjKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tImluc3BlY3RvciI7aW1wb3J0e3BhcmVudFBvcnQgYXMgZSx3b3JrZXJEYXRhIGFzIG59ZnJvbSJ3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tInN0cmVhbSI7aW1wb3J0e2NyZWF0ZUd6aXAgYXMgdX1mcm9tInpsaWIiO2ltcG9ydCphcyBhIGZyb20ibmV0IjtpbXBvcnQqYXMgZiBmcm9tInRscyI7aW1wb3J0KmFzIGggZnJvbSJodHRwIjtjb25zdCBwPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gbCh0LGUpe3JldHVybiBwLmNhbGwodCk9PT1gW29iamVjdCAke2V9XWB9ZnVuY3Rpb24gZCh0KXtyZXR1cm4gbCh0LCJPYmplY3QiKX1mdW5jdGlvbiBtKHQpe3JldHVybiBCb29sZWFuKHQmJnQudGhlbiYmImZ1bmN0aW9uIj09dHlwZW9mIHQudGhlbil9ZnVuY3Rpb24gZyh0LGUpe3RyeXtyZXR1cm4gdCBpbnN0YW5jZW9mIGV9Y2F0Y2godCl7cmV0dXJuITF9fWNvbnN0IHk9Z2xvYmFsVGhpcztmdW5jdGlvbiBiKHQsZSxuKXtjb25zdCByPW58fHksbz1yLl9fU0VOVFJZX189ci5fX1NFTlRSWV9ffHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09ZSgpKX1jb25zdCB2PXksXz04MDtmdW5jdGlvbiB3KHQsZSl7Y29uc3Qgbj10LHI9W107bGV0IG8scyxpLGMsdTtpZighbnx8IW4udGFnTmFtZSlyZXR1cm4iIjtpZih2LkhUTUxFbGVtZW50JiZuIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQmJm4uZGF0YXNldCl7aWYobi5kYXRhc2V0LnNlbnRyeUNvbXBvbmVudClyZXR1cm4gbi5kYXRhc2V0LnNlbnRyeUNvbXBvbmVudDtpZihuLmRhdGFzZXQuc2VudHJ5RWxlbWVudClyZXR1cm4gbi5kYXRhc2V0LnNlbnRyeUVsZW1lbnR9ci5wdXNoKG4udGFnTmFtZS50b0xvd2VyQ2FzZSgpKTtjb25zdCBhPWUmJmUubGVuZ3RoP2UuZmlsdGVyKCh0PT5uLmdldEF0dHJpYnV0ZSh0KSkpLm1hcCgodD0+W3Qsbi5nZXRBdHRyaWJ1dGUodCldKSk6bnVsbDtpZihhJiZhLmxlbmd0aClhLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNlIGlmKG4uaWQmJnIucHVzaChgIyR7bi5pZH1gKSxvPW4uY2xhc3NOYW1lLG8mJmwobywiU3RyaW5nIikpZm9yKHM9by5zcGxpdCgvXHMrLyksdT0wO3U8cy5sZW5ndGg7dSsrKXIucHVzaChgLiR7c1t1XX1gKTtjb25zdCBmPVsiYXJpYS1sYWJlbCIsInR5cGUiLCJuYW1lIiwidGl0bGUiLCJhbHQiXTtmb3IodT0wO3U8Zi5sZW5ndGg7dSsrKWk9Zlt1XSxjPW4uZ2V0QXR0cmlidXRlKGkpLGMmJnIucHVzaChgWyR7aX09IiR7Y30iXWApO3JldHVybiByLmpvaW4oIiIpfWNvbnN0IFM9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLCQ9WyJkZWJ1ZyIsImluZm8iLCJ3YXJuIiwiZXJyb3IiLCJsb2ciLCJhc3NlcnQiLCJ0cmFjZSJdLEU9e307ZnVuY3Rpb24geCh0KXtpZighKCJjb25zb2xlImluIHkpKXJldHVybiB0KCk7Y29uc3QgZT15LmNvbnNvbGUsbj17fSxyPU9iamVjdC5rZXlzKEUpO3IuZm9yRWFjaCgodD0+e2NvbnN0IHI9RVt0XTtuW3RdPWVbdF0sZVt0XT1yfSkpO3RyeXtyZXR1cm4gdCgpfWZpbmFsbHl7ci5mb3JFYWNoKCh0PT57ZVt0XT1uW3RdfSkpfX1jb25zdCBOPWZ1bmN0aW9uKCl7bGV0IHQ9ITE7Y29uc3QgZT17ZW5hYmxlOigpPT57dD0hMH0sZGlzYWJsZTooKT0+e3Q9ITF9LGlzRW5hYmxlZDooKT0+dH07cmV0dXJuIFM/JC5mb3JFYWNoKChuPT57ZVtuXT0oLi4uZSk9Pnt0JiZ4KCgoKT0+e3kuY29uc29sZVtuXShgU2VudHJ5IExvZ2dlciBbJHtufV06YCwuLi5lKX0pKX19KSk6JC5mb3JFYWNoKCh0PT57ZVt0XT0oKT0+e319KSksZX0oKTtmdW5jdGlvbiBrKHQsZT0hMSl7Y29uc3R7aG9zdDpuLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtlJiZvP2A6JHtvfWA6IiJ9QCR7bn0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1jbGFzcyBDIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IodCxlPSJ3YXJuIil7c3VwZXIodCksdGhpcy5tZXNzYWdlPXQsdGhpcy5uYW1lPW5ldy50YXJnZXQucHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUsT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsbmV3LnRhcmdldC5wcm90b3R5cGUpLHRoaXMubG9nTGV2ZWw9ZX19ZnVuY3Rpb24gRCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2gocC5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOnJldHVybiEwO2RlZmF1bHQ6cmV0dXJuIGcodCxFcnJvcil9fSh0KSlyZXR1cm57bWVzc2FnZTp0Lm1lc3NhZ2UsbmFtZTp0Lm5hbWUsc3RhY2s6dC5zdGFjaywuLi5PKHQpfTtpZihlPXQsInVuZGVmaW5lZCIhPXR5cGVvZiBFdmVudCYmZyhlLEV2ZW50KSl7Y29uc3QgZT17dHlwZTp0LnR5cGUsdGFyZ2V0OlQodC50YXJnZXQpLGN1cnJlbnRUYXJnZXQ6VCh0LmN1cnJlbnRUYXJnZXQpLC4uLk8odCl9O3JldHVybiJ1bmRlZmluZWQiIT10eXBlb2YgQ3VzdG9tRXZlbnQmJmcodCxDdXN0b21FdmVudCkmJihlLmRldGFpbD10LmRldGFpbCksZX1yZXR1cm4gdDt2YXIgZX1mdW5jdGlvbiBUKHQpe3RyeXtyZXR1cm4gZT10LCJ1bmRlZmluZWQiIT10eXBlb2YgRWxlbWVudCYmZyhlLEVsZW1lbnQpP2Z1bmN0aW9uKHQsZT17fSl7aWYoIXQpcmV0dXJuIjx1bmtub3duPiI7dHJ5e2xldCBuPXQ7Y29uc3Qgcj01LG89W107bGV0IHM9MCxpPTA7Y29uc3QgYz0iID4gIix1PWMubGVuZ3RoO2xldCBhO2NvbnN0IGY9QXJyYXkuaXNBcnJheShlKT9lOmUua2V5QXR0cnMsaD0hQXJyYXkuaXNBcnJheShlKSYmZS5tYXhTdHJpbmdMZW5ndGh8fF87Zm9yKDtuJiZzKys8ciYmKGE9dyhuLGYpLCEoImh0bWwiPT09YXx8cz4xJiZpK28ubGVuZ3RoKnUrYS5sZW5ndGg+PWgpKTspby5wdXNoKGEpLGkrPWEubGVuZ3RoLG49bi5wYXJlbnROb2RlO3JldHVybiBvLnJldmVyc2UoKS5qb2luKGMpfWNhdGNoKHQpe3JldHVybiI8dW5rbm93bj4ifX0odCk6T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHQpfWNhdGNoKHQpe3JldHVybiI8dW5rbm93bj4ifXZhciBlfWZ1bmN0aW9uIE8odCl7aWYoIm9iamVjdCI9PXR5cGVvZiB0JiZudWxsIT09dCl7Y29uc3QgZT17fTtmb3IoY29uc3QgbiBpbiB0KU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0LG4pJiYoZVtuXT10W25dKTtyZXR1cm4gZX1yZXR1cm57fX1mdW5jdGlvbiBqKHQpe3JldHVybiBSKHQsbmV3IE1hcCl9ZnVuY3Rpb24gUih0LGUpe2lmKGZ1bmN0aW9uKHQpe2lmKCFkKHQpKXJldHVybiExO3RyeXtjb25zdCBlPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KS5jb25zdHJ1Y3Rvci5uYW1lO3JldHVybiFlfHwiT2JqZWN0Ij09PWV9Y2F0Y2godCl7cmV0dXJuITB9fSh0KSl7Y29uc3Qgbj1lLmdldCh0KTtpZih2b2lkIDAhPT1uKXJldHVybiBuO2NvbnN0IHI9e307ZS5zZXQodCxyKTtmb3IoY29uc3QgbiBvZiBPYmplY3Qua2V5cyh0KSl2b2lkIDAhPT10W25dJiYocltuXT1SKHRbbl0sZSkpO3JldHVybiByfWlmKEFycmF5LmlzQXJyYXkodCkpe2NvbnN0IG49ZS5nZXQodCk7aWYodm9pZCAwIT09bilyZXR1cm4gbjtjb25zdCByPVtdO3JldHVybiBlLnNldCh0LHIpLHQuZm9yRWFjaCgodD0+e3IucHVzaChSKHQsZSkpfSkpLHJ9cmV0dXJuIHR9Y29uc3QgQT01MCxJPSI/IixQPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztjb25zdCBVPSI8YW5vbnltb3VzPiI7ZnVuY3Rpb24gTSgpe2NvbnN0IHQ9eSxlPXQuY3J5cHRvfHx0Lm1zQ3J5cHRvO2xldCBuPSgpPT4xNipNYXRoLnJhbmRvbSgpO3RyeXtpZihlJiZlLnJhbmRvbVVVSUQpcmV0dXJuIGUucmFuZG9tVVVJRCgpLnJlcGxhY2UoLy0vZywiIik7ZSYmZS5nZXRSYW5kb21WYWx1ZXMmJihuPSgpPT57Y29uc3QgdD1uZXcgVWludDhBcnJheSgxKTtyZXR1cm4gZS5nZXRSYW5kb21WYWx1ZXModCksdFswXX0pfWNhdGNoKHQpe31yZXR1cm4oWzFlN10rMWUzKzRlMys4ZTMrMWUxMSkucmVwbGFjZSgvWzAxOF0vZywodD0+KHReKDE1Jm4oKSk+PnQvNCkudG9TdHJpbmcoMTYpKSl9ZnVuY3Rpb24gTCh0LGU9MTAwLG49MS8wKXt0cnl7cmV0dXJuIEIoIiIsdCxlLG4pfWNhdGNoKHQpe3JldHVybntFUlJPUjpgKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19fWZ1bmN0aW9uIEIodCxlLG49MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PSJmdW5jdGlvbiI9PXR5cGVvZiBXZWFrU2V0LGU9dD9uZXcgV2Vha1NldDpbXTtyZXR1cm5bZnVuY3Rpb24obil7aWYodClyZXR1cm4hIWUuaGFzKG4pfHwoZS5hZGQobiksITEpO2ZvcihsZXQgdD0wO3Q8ZS5sZW5ndGg7dCsrKWlmKGVbdF09PT1uKXJldHVybiEwO3JldHVybiBlLnB1c2gobiksITF9LGZ1bmN0aW9uKG4pe2lmKHQpZS5kZWxldGUobik7ZWxzZSBmb3IobGV0IHQ9MDt0PGUubGVuZ3RoO3QrKylpZihlW3RdPT09bil7ZS5zcGxpY2UodCwxKTticmVha319XX0oKSl7Y29uc3RbcyxpXT1vO2lmKG51bGw9PWV8fFsibnVtYmVyIiwiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBlKSYmIU51bWJlci5pc05hTihlKSlyZXR1cm4gZTtjb25zdCBjPWZ1bmN0aW9uKHQsZSl7dHJ5e2lmKCJkb21haW4iPT09dCYmZSYmIm9iamVjdCI9PXR5cGVvZiBlJiZlLnQpcmV0dXJuIltEb21haW5dIjtpZigiZG9tYWluRW1pdHRlciI9PT10KXJldHVybiJbRG9tYWluRW1pdHRlcl0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZlPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJmU9PT13aW5kb3cpcmV0dXJuIltXaW5kb3ddIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGRvY3VtZW50JiZlPT09ZG9jdW1lbnQpcmV0dXJuIltEb2N1bWVudF0iO2lmKCJvYmplY3QiPT10eXBlb2Yobj1lKSYmbnVsbCE9PW4mJihuLl9faXNWdWV8fG4ubykpcmV0dXJuIltWdWVWaWV3TW9kZWxdIjtpZihmdW5jdGlvbih0KXtyZXR1cm4gZCh0KSYmIm5hdGl2ZUV2ZW50ImluIHQmJiJwcmV2ZW50RGVmYXVsdCJpbiB0JiYic3RvcFByb3BhZ2F0aW9uImluIHR9KGUpKXJldHVybiJbU3ludGhldGljRXZlbnRdIjtpZigibnVtYmVyIj09dHlwZW9mIGUmJmUhPWUpcmV0dXJuIltOYU5dIjtpZigiZnVuY3Rpb24iPT10eXBlb2YgZSlyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8VX1jYXRjaCh0KXtyZXR1cm4gVX19KGUpfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgZSlyZXR1cm5gWyR7U3RyaW5nKGUpfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgZSlyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcoZSl9XWA7Y29uc3Qgcj1mdW5jdGlvbih0KXtjb25zdCBlPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gZT9lLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0oZSk7cmV0dXJuL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChyKT9gW0hUTUxFbGVtZW50OiAke3J9XWA6YFtvYmplY3QgJHtyfV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfXZhciBufSh0LGUpO2lmKCFjLnN0YXJ0c1dpdGgoIltvYmplY3QgIikpcmV0dXJuIGM7aWYoZS5fX3NlbnRyeV9za2lwX25vcm1hbGl6YXRpb25fXylyZXR1cm4gZTtjb25zdCB1PSJudW1iZXIiPT10eXBlb2YgZS5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX18/ZS5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX186bjtpZigwPT09dSlyZXR1cm4gYy5yZXBsYWNlKCJvYmplY3QgIiwiIik7aWYocyhlKSlyZXR1cm4iW0NpcmN1bGFyIH5dIjtjb25zdCBhPWU7aWYoYSYmImZ1bmN0aW9uIj09dHlwZW9mIGEudG9KU09OKXRyeXtyZXR1cm4gQigiIixhLnRvSlNPTigpLHUtMSxyLG8pfWNhdGNoKHQpe31jb25zdCBmPUFycmF5LmlzQXJyYXkoZSk/W106e307bGV0IGg9MDtjb25zdCBwPUQoZSk7Zm9yKGNvbnN0IHQgaW4gcCl7aWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwLHQpKWNvbnRpbnVlO2lmKGg+PXIpe2ZbdF09IltNYXhQcm9wZXJ0aWVzIH5dIjticmVha31jb25zdCBlPXBbdF07Zlt0XT1CKHQsZSx1LTEscixvKSxoKyt9cmV0dXJuIGkoZSksZn1mdW5jdGlvbiBHKHQsZSl7Y29uc3Qgbj1lLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Ll0vZywiXFwkJiIpO2xldCByPXQ7dHJ5e3I9ZGVjb2RlVVJJKHQpfWNhdGNoKHQpe31yZXR1cm4gci5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvd2VicGFjazpcLz8vZywiIikucmVwbGFjZShuZXcgUmVnRXhwKGAoZmlsZTovLyk/Lyoke259LypgLCJpZyIpLCJhcHA6Ly8vIil9Y29uc3QgSj0vXihcUys6XFx8XC8/KShbXHNcU10qPykoKD86XC57MSwyfXxbXi9cXF0rP3wpKFwuW14uL1xcXSp8KSkoPzpbL1xcXSopJC87ZnVuY3Rpb24geih0KXtjb25zdCBlPWZ1bmN0aW9uKHQpe2NvbnN0IGU9dC5sZW5ndGg+MTAyND9gPHRydW5jYXRlZD4ke3Quc2xpY2UoLTEwMjQpfWA6dCxuPUouZXhlYyhlKTtyZXR1cm4gbj9uLnNsaWNlKDEpOltdfSh0KSxuPWVbMF07bGV0IHI9ZVsxXTtyZXR1cm4gbnx8cj8ociYmKHI9ci5zbGljZSgwLHIubGVuZ3RoLTEpKSxuK3IpOiIuIn12YXIgSDtmdW5jdGlvbiBXKHQpe3JldHVybiBuZXcgWSgoZT0+e2UodCl9KSl9IWZ1bmN0aW9uKHQpe3RbdC5QRU5ESU5HPTBdPSJQRU5ESU5HIjt0W3QuUkVTT0xWRUQ9MV09IlJFU09MVkVEIjt0W3QuUkVKRUNURUQ9Ml09IlJFSkVDVEVEIn0oSHx8KEg9e30pKTtjbGFzcyBZe2NvbnN0cnVjdG9yKHQpe1kucHJvdG90eXBlLl9faW5pdC5jYWxsKHRoaXMpLFkucHJvdG90eXBlLl9faW5pdDIuY2FsbCh0aGlzKSxZLnByb3RvdHlwZS5fX2luaXQzLmNhbGwodGhpcyksWS5wcm90b3R5cGUuX19pbml0NC5jYWxsKHRoaXMpLHRoaXMuaT1ILlBFTkRJTkcsdGhpcy51PVtdO3RyeXt0KHRoaXMuaCx0aGlzLnApfWNhdGNoKHQpe3RoaXMucCh0KX19dGhlbih0LGUpe3JldHVybiBuZXcgWSgoKG4scik9Pnt0aGlzLnUucHVzaChbITEsZT0+e2lmKHQpdHJ5e24odChlKSl9Y2F0Y2godCl7cih0KX1lbHNlIG4oZSl9LHQ9PntpZihlKXRyeXtuKGUodCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMubCgpfSkpfWNhdGNoKHQpe3JldHVybiB0aGlzLnRoZW4oKHQ9PnQpLHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBZKCgoZSxuKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbigoZT0+e289ITEscj1lLHQmJnQoKX0pLChlPT57bz0hMCxyPWUsdCYmdCgpfSkpLnRoZW4oKCgpPT57bz9uKHIpOmUocil9KSl9KSl9X19pbml0KCl7dGhpcy5oPXQ9Pnt0aGlzLm0oSC5SRVNPTFZFRCx0KX19X19pbml0Migpe3RoaXMucD10PT57dGhpcy5tKEguUkVKRUNURUQsdCl9fV9faW5pdDMoKXt0aGlzLm09KHQsZSk9Pnt0aGlzLmk9PT1ILlBFTkRJTkcmJihtKGUpP2UudGhlbih0aGlzLmgsdGhpcy5wKToodGhpcy5pPXQsdGhpcy52PWUsdGhpcy5sKCkpKX19X19pbml0NCgpe3RoaXMubD0oKT0+e2lmKHRoaXMuaT09PUguUEVORElORylyZXR1cm47Y29uc3QgdD10aGlzLnUuc2xpY2UoKTt0aGlzLnU9W10sdC5mb3JFYWNoKCh0PT57dFswXXx8KHRoaXMuaT09PUguUkVTT0xWRUQmJnRbMV0odGhpcy52KSx0aGlzLmk9PT1ILlJFSkVDVEVEJiZ0WzJdKHRoaXMudiksdFswXT0hMCl9KSl9fX1mdW5jdGlvbiBxKHQpe2NvbnN0IGU9W107ZnVuY3Rpb24gbih0KXtyZXR1cm4gZS5zcGxpY2UoZS5pbmRleE9mKHQpLDEpWzBdfXJldHVybnskOmUsYWRkOmZ1bmN0aW9uKHIpe2lmKCEodm9pZCAwPT09dHx8ZS5sZW5ndGg8dCkpcmV0dXJuIG89bmV3IEMoIk5vdCBhZGRpbmcgUHJvbWlzZSBiZWNhdXNlIGJ1ZmZlciBsaW1pdCB3YXMgcmVhY2hlZC4iKSxuZXcgWSgoKHQsZSk9PntlKG8pfSkpO3ZhciBvO2NvbnN0IHM9cigpO3JldHVybi0xPT09ZS5pbmRleE9mKHMpJiZlLnB1c2gocykscy50aGVuKCgoKT0+bihzKSkpLnRoZW4obnVsbCwoKCk9Pm4ocykudGhlbihudWxsLCgoKT0+e30pKSkpLHN9LGRyYWluOmZ1bmN0aW9uKHQpe3JldHVybiBuZXcgWSgoKG4scik9PntsZXQgbz1lLmxlbmd0aDtpZighbylyZXR1cm4gbighMCk7Y29uc3Qgcz1zZXRUaW1lb3V0KCgoKT0+e3QmJnQ+MCYmbighMSl9KSx0KTtlLmZvckVhY2goKHQ9PntXKHQpLnRoZW4oKCgpPT57LS1vfHwoY2xlYXJUaW1lb3V0KHMpLG4oITApKX0pLHIpfSkpfSkpfX19ZnVuY3Rpb24gRih0LGU9ITEpe3JldHVybiEoZXx8dCYmIXQuc3RhcnRzV2l0aCgiLyIpJiYhdC5tYXRjaCgvXltBLVpdOi8pJiYhdC5zdGFydHNXaXRoKCIuIikmJiF0Lm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKSYmdm9pZCAwIT09dCYmIXQuaW5jbHVkZXMoIm5vZGVfbW9kdWxlcy8iKX1jb25zdCBLPTFlMztmdW5jdGlvbiBWKCl7cmV0dXJuIERhdGUubm93KCkvS31jb25zdCBaPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09eTtpZighdHx8IXQubm93KXJldHVybiBWO2NvbnN0IGU9RGF0ZS5ub3coKS10Lm5vdygpLG49bnVsbD09dC50aW1lT3JpZ2luP2U6dC50aW1lT3JpZ2luO3JldHVybigpPT4obit0Lm5vdygpKS9LfSgpO2Z1bmN0aW9uIFEodCxlPVtdKXtyZXR1cm5bdCxlXX1mdW5jdGlvbiBYKHQsZSl7Y29uc3Qgbj10WzFdO2Zvcihjb25zdCB0IG9mIG4pe2lmKGUodCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIHR0KHQpe3JldHVybiB5Ll9fU0VOVFJZX18mJnkuX19TRU5UUllfXy5lbmNvZGVQb2x5ZmlsbD95Ll9fU0VOVFJZX18uZW5jb2RlUG9seWZpbGwodCk6KG5ldyBUZXh0RW5jb2RlcikuZW5jb2RlKHQpfWZ1bmN0aW9uIGV0KHQpe2NvbnN0W2Usbl09dDtsZXQgcj1KU09OLnN0cmluZ2lmeShlKTtmdW5jdGlvbiBvKHQpeyJzdHJpbmciPT10eXBlb2Ygcj9yPSJzdHJpbmciPT10eXBlb2YgdD9yK3Q6W3R0KHIpLHRdOnIucHVzaCgic3RyaW5nIj09dHlwZW9mIHQ/dHQodCk6dCl9Zm9yKGNvbnN0IHQgb2Ygbil7Y29uc3RbZSxuXT10O2lmKG8oYFxuJHtKU09OLnN0cmluZ2lmeShlKX1cbmApLCJzdHJpbmciPT10eXBlb2Ygbnx8biBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbyhuKTtlbHNle2xldCB0O3RyeXt0PUpTT04uc3RyaW5naWZ5KG4pfWNhdGNoKGUpe3Q9SlNPTi5zdHJpbmdpZnkoTChuKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3QgZT10LnJlZHVjZSgoKHQsZSk9PnQrZS5sZW5ndGgpLDApLG49bmV3IFVpbnQ4QXJyYXkoZSk7bGV0IHI9MDtmb3IoY29uc3QgZSBvZiB0KW4uc2V0KGUscikscis9ZS5sZW5ndGg7cmV0dXJuIG59KHIpfSgoKT0+e2NvbnN0e3BlcmZvcm1hbmNlOnR9PXk7aWYoIXR8fCF0Lm5vdylyZXR1cm47Y29uc3QgZT0zNmU1LG49dC5ub3coKSxyPURhdGUubm93KCksbz10LnRpbWVPcmlnaW4/TWF0aC5hYnModC50aW1lT3JpZ2luK24tcik6ZSxzPW88ZSxpPXQudGltaW5nJiZ0LnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQsYz0ibnVtYmVyIj09dHlwZW9mIGk/TWF0aC5hYnMoaStuLXIpOmU7KHN8fGM8ZSkmJihvPD1jJiZ0LnRpbWVPcmlnaW4pfSkoKTtjb25zdCBudD17c2Vzc2lvbjoic2Vzc2lvbiIsc2Vzc2lvbnM6InNlc3Npb24iLGF0dGFjaG1lbnQ6ImF0dGFjaG1lbnQiLHRyYW5zYWN0aW9uOiJ0cmFuc2FjdGlvbiIsZXZlbnQ6ImVycm9yIixjbGllbnRfcmVwb3J0OiJpbnRlcm5hbCIsdXNlcl9yZXBvcnQ6ImRlZmF1bHQiLHByb2ZpbGU6InByb2ZpbGUiLHJlcGxheV9ldmVudDoicmVwbGF5IixyZXBsYXlfcmVjb3JkaW5nOiJyZXBsYXkiLGNoZWNrX2luOiJtb25pdG9yIixmZWVkYmFjazoiZmVlZGJhY2siLHNwYW46InNwYW4iLHN0YXRzZDoibWV0cmljX2J1Y2tldCJ9O2Z1bmN0aW9uIHJ0KHQpe3JldHVybiBudFt0XX1mdW5jdGlvbiBvdCh0KXtpZighdHx8IXQuc2RrKXJldHVybjtjb25zdHtuYW1lOmUsdmVyc2lvbjpufT10LnNkaztyZXR1cm57bmFtZTplLHZlcnNpb246bn19Y29uc3Qgc3Q9NmU0O2Z1bmN0aW9uIGl0KHQse3N0YXR1c0NvZGU6ZSxoZWFkZXJzOm59LHI9RGF0ZS5ub3coKSl7Y29uc3Qgbz17Li4udH0scz1uJiZuWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLGk9biYmblsicmV0cnktYWZ0ZXIiXTtpZihzKWZvcihjb25zdCB0IG9mIHMudHJpbSgpLnNwbGl0KCIsIikpe2NvbnN0W2UsbiwsLHNdPXQuc3BsaXQoIjoiLDUpLGk9cGFyc2VJbnQoZSwxMCksYz0xZTMqKGlzTmFOKGkpPzYwOmkpO2lmKG4pZm9yKGNvbnN0IHQgb2Ygbi5zcGxpdCgiOyIpKSJtZXRyaWNfYnVja2V0Ij09PXQmJnMmJiFzLnNwbGl0KCI7IikuaW5jbHVkZXMoImN1c3RvbSIpfHwob1t0XT1yK2MpO2Vsc2Ugby5hbGw9citjfWVsc2UgaT9vLmFsbD1yK2Z1bmN0aW9uKHQsZT1EYXRlLm5vdygpKXtjb25zdCBuPXBhcnNlSW50KGAke3R9YCwxMCk7aWYoIWlzTmFOKG4pKXJldHVybiAxZTMqbjtjb25zdCByPURhdGUucGFyc2UoYCR7dH1gKTtyZXR1cm4gaXNOYU4ocik/c3Q6ci1lfShpLHIpOjQyOT09PWUmJihvLmFsbD1yKzZlNCk7cmV0dXJuIG99Y29uc3QgY3Q9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fO2Z1bmN0aW9uIHV0KCl7cmV0dXJuIGF0KHkpLHl9ZnVuY3Rpb24gYXQodCl7cmV0dXJuIHQuX19TRU5UUllfX3x8KHQuX19TRU5UUllfXz17ZXh0ZW5zaW9uczp7fX0pLHQuX19TRU5UUllfX31mdW5jdGlvbiBmdCh0KXtjb25zdCBlPVooKSxuPXtzaWQ6TSgpLGluaXQ6ITAsdGltZXN0YW1wOmUsc3RhcnRlZDplLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm4gaih7c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fSl9KG4pfTtyZXR1cm4gdCYmaHQobix0KSxufWZ1bmN0aW9uIGh0KHQsZT17fSl7aWYoZS51c2VyJiYoIXQuaXBBZGRyZXNzJiZlLnVzZXIuaXBfYWRkcmVzcyYmKHQuaXBBZGRyZXNzPWUudXNlci5pcF9hZGRyZXNzKSx0LmRpZHx8ZS5kaWR8fCh0LmRpZD1lLnVzZXIuaWR8fGUudXNlci5lbWFpbHx8ZS51c2VyLnVzZXJuYW1lKSksdC50aW1lc3RhbXA9ZS50aW1lc3RhbXB8fFooKSxlLmFibm9ybWFsX21lY2hhbmlzbSYmKHQuYWJub3JtYWxfbWVjaGFuaXNtPWUuYWJub3JtYWxfbWVjaGFuaXNtKSxlLmlnbm9yZUR1cmF0aW9uJiYodC5pZ25vcmVEdXJhdGlvbj1lLmlnbm9yZUR1cmF0aW9uKSxlLnNpZCYmKHQuc2lkPTMyPT09ZS5zaWQubGVuZ3RoP2Uuc2lkOk0oKSksdm9pZCAwIT09ZS5pbml0JiYodC5pbml0PWUuaW5pdCksIXQuZGlkJiZlLmRpZCYmKHQuZGlkPWAke2UuZGlkfWApLCJudW1iZXIiPT10eXBlb2YgZS5zdGFydGVkJiYodC5zdGFydGVkPWUuc3RhcnRlZCksdC5pZ25vcmVEdXJhdGlvbil0LmR1cmF0aW9uPXZvaWQgMDtlbHNlIGlmKCJudW1iZXIiPT10eXBlb2YgZS5kdXJhdGlvbil0LmR1cmF0aW9uPWUuZHVyYXRpb247ZWxzZXtjb25zdCBlPXQudGltZXN0YW1wLXQuc3RhcnRlZDt0LmR1cmF0aW9uPWU+PTA/ZTowfWUucmVsZWFzZSYmKHQucmVsZWFzZT1lLnJlbGVhc2UpLGUuZW52aXJvbm1lbnQmJih0LmVudmlyb25tZW50PWUuZW52aXJvbm1lbnQpLCF0LmlwQWRkcmVzcyYmZS5pcEFkZHJlc3MmJih0LmlwQWRkcmVzcz1lLmlwQWRkcmVzcyksIXQudXNlckFnZW50JiZlLnVzZXJBZ2VudCYmKHQudXNlckFnZW50PWUudXNlckFnZW50KSwibnVtYmVyIj09dHlwZW9mIGUuZXJyb3JzJiYodC5lcnJvcnM9ZS5lcnJvcnMpLGUuc3RhdHVzJiYodC5zdGF0dXM9ZS5zdGF0dXMpfWNvbnN0IHB0PSJfc2VudHJ5U3BhbiI7ZnVuY3Rpb24gbHQodCxlKXtlP2Z1bmN0aW9uKHQsZSxuKXt0cnl7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsZSx7dmFsdWU6bix3cml0YWJsZTohMCxjb25maWd1cmFibGU6ITB9KX1jYXRjaChuKXtTJiZOLmxvZyhgRmFpbGVkIHRvIGFkZCBub24tZW51bWVyYWJsZSBwcm9wZXJ0eSAiJHtlfSIgdG8gb2JqZWN0YCx0KX19KHQscHQsZSk6ZGVsZXRlIHRbcHRdfWZ1bmN0aW9uIGR0KHQpe3JldHVybiB0W3B0XX1jbGFzcyBtdHtjb25zdHJ1Y3Rvcigpe3RoaXMuXz0hMSx0aGlzLlM9W10sdGhpcy5OPVtdLHRoaXMuaz1bXSx0aGlzLkM9W10sdGhpcy5EPXt9LHRoaXMuVD17fSx0aGlzLk89e30sdGhpcy5qPXt9LHRoaXMuUj17fSx0aGlzLkE9Z3QoKX1jbG9uZSgpe2NvbnN0IHQ9bmV3IG10O3JldHVybiB0Lms9Wy4uLnRoaXMua10sdC5UPXsuLi50aGlzLlR9LHQuTz17Li4udGhpcy5PfSx0Lmo9ey4uLnRoaXMuan0sdC5EPXRoaXMuRCx0Lkk9dGhpcy5JLHQuUD10aGlzLlAsdC5VPXRoaXMuVSx0Lk09dGhpcy5NLHQuTj1bLi4udGhpcy5OXSx0Lkw9dGhpcy5MLHQuQz1bLi4udGhpcy5DXSx0LlI9ey4uLnRoaXMuUn0sdC5BPXsuLi50aGlzLkF9LHQuQj10aGlzLkIsbHQodCxkdCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5CPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuQn1hZGRTY29wZUxpc3RlbmVyKHQpe3RoaXMuUy5wdXNoKHQpfWFkZEV2ZW50UHJvY2Vzc29yKHQpe3JldHVybiB0aGlzLk4ucHVzaCh0KSx0aGlzfXNldFVzZXIodCl7cmV0dXJuIHRoaXMuRD10fHx7ZW1haWw6dm9pZCAwLGlkOnZvaWQgMCxpcF9hZGRyZXNzOnZvaWQgMCx1c2VybmFtZTp2b2lkIDB9LHRoaXMuUCYmaHQodGhpcy5QLHt1c2VyOnR9KSx0aGlzLkcoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5EfWdldFJlcXVlc3RTZXNzaW9uKCl7cmV0dXJuIHRoaXMuTH1zZXRSZXF1ZXN0U2Vzc2lvbih0KXtyZXR1cm4gdGhpcy5MPXQsdGhpc31zZXRUYWdzKHQpe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCwuLi50fSx0aGlzLkcoKSx0aGlzfXNldFRhZyh0LGUpe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCxbdF06ZX0sdGhpcy5HKCksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMuTz17Li4udGhpcy5PLC4uLnR9LHRoaXMuRygpLHRoaXN9c2V0RXh0cmEodCxlKXtyZXR1cm4gdGhpcy5PPXsuLi50aGlzLk8sW3RdOmV9LHRoaXMuRygpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuTT10LHRoaXMuRygpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuST10LHRoaXMuRygpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLlU9dCx0aGlzLkcoKSx0aGlzfXNldENvbnRleHQodCxlKXtyZXR1cm4gbnVsbD09PWU/ZGVsZXRlIHRoaXMualt0XTp0aGlzLmpbdF09ZSx0aGlzLkcoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5QPXQ6ZGVsZXRlIHRoaXMuUCx0aGlzLkcoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5QfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBlPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxbbixyXT1lIGluc3RhbmNlb2YgbXQ/W2UuZ2V0U2NvcGVEYXRhKCksZS5nZXRSZXF1ZXN0U2Vzc2lvbigpXTpkKGUpP1t0LHQucmVxdWVzdFNlc3Npb25dOltdLHt0YWdzOm8sZXh0cmE6cyx1c2VyOmksY29udGV4dHM6YyxsZXZlbDp1LGZpbmdlcnByaW50OmE9W10scHJvcGFnYXRpb25Db250ZXh0OmZ9PW58fHt9O3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCwuLi5vfSx0aGlzLk89ey4uLnRoaXMuTywuLi5zfSx0aGlzLmo9ey4uLnRoaXMuaiwuLi5jfSxpJiZPYmplY3Qua2V5cyhpKS5sZW5ndGgmJih0aGlzLkQ9aSksdSYmKHRoaXMuST11KSxhLmxlbmd0aCYmKHRoaXMuTT1hKSxmJiYodGhpcy5BPWYpLHImJih0aGlzLkw9ciksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLms9W10sdGhpcy5UPXt9LHRoaXMuTz17fSx0aGlzLkQ9e30sdGhpcy5qPXt9LHRoaXMuST12b2lkIDAsdGhpcy5VPXZvaWQgMCx0aGlzLk09dm9pZCAwLHRoaXMuTD12b2lkIDAsdGhpcy5QPXZvaWQgMCxsdCh0aGlzLHZvaWQgMCksdGhpcy5DPVtdLHRoaXMuQT1ndCgpLHRoaXMuRygpLHRoaXN9YWRkQnJlYWRjcnVtYih0LGUpe2NvbnN0IG49Im51bWJlciI9PXR5cGVvZiBlP2U6MTAwO2lmKG48PTApcmV0dXJuIHRoaXM7Y29uc3Qgcj17dGltZXN0YW1wOlYoKSwuLi50fSxvPXRoaXMuaztyZXR1cm4gby5wdXNoKHIpLHRoaXMuaz1vLmxlbmd0aD5uP28uc2xpY2UoLW4pOm8sdGhpcy5HKCksdGhpc31nZXRMYXN0QnJlYWRjcnVtYigpe3JldHVybiB0aGlzLmtbdGhpcy5rLmxlbmd0aC0xXX1jbGVhckJyZWFkY3J1bWJzKCl7cmV0dXJuIHRoaXMuaz1bXSx0aGlzLkcoKSx0aGlzfWFkZEF0dGFjaG1lbnQodCl7cmV0dXJuIHRoaXMuQy5wdXNoKHQpLHRoaXN9Y2xlYXJBdHRhY2htZW50cygpe3JldHVybiB0aGlzLkM9W10sdGhpc31nZXRTY29wZURhdGEoKXtyZXR1cm57YnJlYWRjcnVtYnM6dGhpcy5rLGF0dGFjaG1lbnRzOnRoaXMuQyxjb250ZXh0czp0aGlzLmosdGFnczp0aGlzLlQsZXh0cmE6dGhpcy5PLHVzZXI6dGhpcy5ELGxldmVsOnRoaXMuSSxmaW5nZXJwcmludDp0aGlzLk18fFtdLGV2ZW50UHJvY2Vzc29yczp0aGlzLk4scHJvcGFnYXRpb25Db250ZXh0OnRoaXMuQSxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6dGhpcy5SLHRyYW5zYWN0aW9uTmFtZTp0aGlzLlUsc3BhbjpkdCh0aGlzKX19c2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHQpe3JldHVybiB0aGlzLlI9ey4uLnRoaXMuUiwuLi50fSx0aGlzfXNldFByb3BhZ2F0aW9uQ29udGV4dCh0KXtyZXR1cm4gdGhpcy5BPXQsdGhpc31nZXRQcm9wYWdhdGlvbkNvbnRleHQoKXtyZXR1cm4gdGhpcy5BfWNhcHR1cmVFeGNlcHRpb24odCxlKXtjb25zdCBuPWUmJmUuZXZlbnRfaWQ/ZS5ldmVudF9pZDpNKCk7aWYoIXRoaXMuQilyZXR1cm4gTi53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXhjZXB0aW9uISIpLG47Y29uc3Qgcj1uZXcgRXJyb3IoIlNlbnRyeSBzeW50aGV0aWNFeGNlcHRpb24iKTtyZXR1cm4gdGhpcy5CLmNhcHR1cmVFeGNlcHRpb24odCx7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246ciwuLi5lLGV2ZW50X2lkOm59LHRoaXMpLG59Y2FwdHVyZU1lc3NhZ2UodCxlLG4pe2NvbnN0IHI9biYmbi5ldmVudF9pZD9uLmV2ZW50X2lkOk0oKTtpZighdGhpcy5CKXJldHVybiBOLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBtZXNzYWdlISIpLHI7Y29uc3Qgbz1uZXcgRXJyb3IodCk7cmV0dXJuIHRoaXMuQi5jYXB0dXJlTWVzc2FnZSh0LGUse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOm8sLi4ubixldmVudF9pZDpyfSx0aGlzKSxyfWNhcHR1cmVFdmVudCh0LGUpe2NvbnN0IG49ZSYmZS5ldmVudF9pZD9lLmV2ZW50X2lkOk0oKTtyZXR1cm4gdGhpcy5CPyh0aGlzLkIuY2FwdHVyZUV2ZW50KHQsey4uLmUsZXZlbnRfaWQ6bn0sdGhpcyksbik6KE4ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV2ZW50ISIpLG4pfUcoKXt0aGlzLl98fCh0aGlzLl89ITAsdGhpcy5TLmZvckVhY2goKHQ9Pnt0KHRoaXMpfSkpLHRoaXMuXz0hMSl9fWZ1bmN0aW9uIGd0KCl7cmV0dXJue3RyYWNlSWQ6TSgpLHNwYW5JZDpNKCkuc3Vic3RyaW5nKDE2KX19ZnVuY3Rpb24geXQoKXtyZXR1cm4gJHQodXQoKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9Y2xhc3MgYnR7Y29uc3RydWN0b3IodCxlKXtsZXQgbixyO249dHx8bmV3IG10LHI9ZXx8bmV3IG10LHRoaXMuSj1be3Njb3BlOm59XSx0aGlzLkg9cn13aXRoU2NvcGUodCl7Y29uc3QgZT10aGlzLlcoKTtsZXQgbjt0cnl7bj10KGUpfWNhdGNoKHQpe3Rocm93IHRoaXMuWSgpLHR9cmV0dXJuIG0obik/bi50aGVuKCh0PT4odGhpcy5ZKCksdCkpLCh0PT57dGhyb3cgdGhpcy5ZKCksdH0pKToodGhpcy5ZKCksbil9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnR9Z2V0U2NvcGUoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLnNjb3BlfWdldElzb2xhdGlvblNjb3BlKCl7cmV0dXJuIHRoaXMuSH1nZXRTdGFjaygpe3JldHVybiB0aGlzLkp9Z2V0U3RhY2tUb3AoKXtyZXR1cm4gdGhpcy5KW3RoaXMuSi5sZW5ndGgtMV19Vygpe2NvbnN0IHQ9dGhpcy5nZXRTY29wZSgpLmNsb25lKCk7cmV0dXJuIHRoaXMuZ2V0U3RhY2soKS5wdXNoKHtjbGllbnQ6dGhpcy5nZXRDbGllbnQoKSxzY29wZTp0fSksdH1ZKCl7cmV0dXJuISh0aGlzLmdldFN0YWNrKCkubGVuZ3RoPD0xKSYmISF0aGlzLmdldFN0YWNrKCkucG9wKCl9fWZ1bmN0aW9uIHZ0KCl7Y29uc3QgdD1hdCh1dCgpKTtyZXR1cm4gdC5odWJ8fCh0Lmh1Yj1uZXcgYnQoYigiZGVmYXVsdEN1cnJlbnRTY29wZSIsKCgpPT5uZXcgbXQpKSxiKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgoKT0+bmV3IG10KSkpKSx0Lmh1Yn1mdW5jdGlvbiBfdCh0KXtyZXR1cm4gdnQoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gd3QodCxlKXtjb25zdCBuPXZ0KCk7cmV0dXJuIG4ud2l0aFNjb3BlKCgoKT0+KG4uZ2V0U3RhY2tUb3AoKS5zY29wZT10LGUodCkpKSl9ZnVuY3Rpb24gU3QodCl7cmV0dXJuIHZ0KCkud2l0aFNjb3BlKCgoKT0+dCh2dCgpLmdldElzb2xhdGlvblNjb3BlKCkpKSl9ZnVuY3Rpb24gJHQodCl7Y29uc3QgZT1hdCh0KTtyZXR1cm4gZS5hY3M/ZS5hY3M6e3dpdGhJc29sYXRpb25TY29wZTpTdCx3aXRoU2NvcGU6X3Qsd2l0aFNldFNjb3BlOnd0LHdpdGhTZXRJc29sYXRpb25TY29wZToodCxlKT0+U3QoZSksZ2V0Q3VycmVudFNjb3BlOigpPT52dCgpLmdldFNjb3BlKCksZ2V0SXNvbGF0aW9uU2NvcGU6KCk9PnZ0KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKX19Y29uc3QgRXQ9InNlbnRyeS5zb3VyY2UiLHh0PSJzZW50cnkuc2FtcGxlX3JhdGUiLE50PSJzZW50cnkub3AiLGt0PSJzZW50cnkub3JpZ2luIixDdD0wLER0PTEsVHQ9InByb2R1Y3Rpb24iLE90PSJfZnJvemVuRHNjIjtmdW5jdGlvbiBqdCh0KXtjb25zdCBlPXl0KCk7aWYoIWUpcmV0dXJue307Y29uc3Qgbj1mdW5jdGlvbih0LGUpe2NvbnN0IG49ZS5nZXRPcHRpb25zKCkse3B1YmxpY0tleTpyfT1lLmdldERzbigpfHx7fSxvPWooe2Vudmlyb25tZW50Om4uZW52aXJvbm1lbnR8fFR0LHJlbGVhc2U6bi5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0fSk7cmV0dXJuIGUuZW1pdCgiY3JlYXRlRHNjIixvKSxvfShVdCh0KS50cmFjZV9pZHx8IiIsZSkscj1CdCh0KTtpZighcilyZXR1cm4gbjtjb25zdCBvPXJbT3RdO2lmKG8pcmV0dXJuIG87Y29uc3Qgcz1VdChyKSxpPXMuZGF0YXx8e30sYz1pW3h0XTtudWxsIT1jJiYobi5zYW1wbGVfcmF0ZT1gJHtjfWApO2NvbnN0IHU9aVtFdF07cmV0dXJuIHUmJiJ1cmwiIT09dSYmKG4udHJhbnNhY3Rpb249cy5kZXNjcmlwdGlvbiksbi5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOmV9PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gZT09PVJ0fShyKSksZS5lbWl0KCJjcmVhdGVEc2MiLG4pLG59Y29uc3QgUnQ9MTtmdW5jdGlvbiBBdCh0KXtjb25zdHtzcGFuSWQ6ZSx0cmFjZUlkOm59PXQuc3BhbkNvbnRleHQoKSx7cGFyZW50X3NwYW5faWQ6cn09VXQodCk7cmV0dXJuIGooe3BhcmVudF9zcGFuX2lkOnIsc3Bhbl9pZDplLHRyYWNlX2lkOm59KX1mdW5jdGlvbiBJdCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/UHQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlP1B0KHQuZ2V0VGltZSgpKTpaKCl9ZnVuY3Rpb24gUHQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIFV0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO3RyeXtjb25zdHtzcGFuSWQ6ZSx0cmFjZUlkOm59PXQuc3BhbkNvbnRleHQoKTtpZihmdW5jdGlvbih0KXtjb25zdCBlPXQ7cmV0dXJuISEoZS5hdHRyaWJ1dGVzJiZlLnN0YXJ0VGltZSYmZS5uYW1lJiZlLmVuZFRpbWUmJmUuc3RhdHVzKX0odCkpe2NvbnN0e2F0dHJpYnV0ZXM6cixzdGFydFRpbWU6byxuYW1lOnMsZW5kVGltZTppLHBhcmVudFNwYW5JZDpjLHN0YXR1czp1fT10O3JldHVybiBqKHtzcGFuX2lkOmUsdHJhY2VfaWQ6bixkYXRhOnIsZGVzY3JpcHRpb246cyxwYXJlbnRfc3Bhbl9pZDpjLHN0YXJ0X3RpbWVzdGFtcDpJdChvKSx0aW1lc3RhbXA6SXQoaSl8fHZvaWQgMCxzdGF0dXM6TXQodSksb3A6cltOdF0sb3JpZ2luOnJba3RdLHE6dm9pZCAwfSl9cmV0dXJue3NwYW5faWQ6ZSx0cmFjZV9pZDpufX1jYXRjaCh0KXtyZXR1cm57fX19ZnVuY3Rpb24gTXQodCl7aWYodCYmdC5jb2RlIT09Q3QpcmV0dXJuIHQuY29kZT09PUR0PyJvayI6dC5tZXNzYWdlfHwidW5rbm93bl9lcnJvciJ9Y29uc3QgTHQ9Il9zZW50cnlSb290U3BhbiI7ZnVuY3Rpb24gQnQodCl7cmV0dXJuIHRbTHRdfHx0fWZ1bmN0aW9uIEd0KHQsZSxuLHIpe2NvbnN0IG89b3Qobikscz10LnR5cGUmJiJyZXBsYXlfZXZlbnQiIT09dC50eXBlP3QudHlwZToiZXZlbnQiOyFmdW5jdGlvbih0LGUpe2UmJih0LnNkaz10LnNka3x8e30sdC5zZGsubmFtZT10LnNkay5uYW1lfHxlLm5hbWUsdC5zZGsudmVyc2lvbj10LnNkay52ZXJzaW9ufHxlLnZlcnNpb24sdC5zZGsuaW50ZWdyYXRpb25zPVsuLi50LnNkay5pbnRlZ3JhdGlvbnN8fFtdLC4uLmUuaW50ZWdyYXRpb25zfHxbXV0sdC5zZGsucGFja2FnZXM9Wy4uLnQuc2RrLnBhY2thZ2VzfHxbXSwuLi5lLnBhY2thZ2VzfHxbXV0pfSh0LG4mJm4uc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEmJnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4uZSYme3NkazplfSwuLi4hIW4mJnImJntkc246ayhyKX0sLi4ubyYme3RyYWNlOmooey4uLm99KX19fSh0LG8scixlKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIFEoaSxbW3t0eXBlOnN9LHRdXSl9Y29uc3QgSnQ9Il9fU0VOVFJZX1NVUFBSRVNTX1RSQUNJTkdfXyI7ZnVuY3Rpb24genQodCl7Y29uc3QgZT0kdCh1dCgpKTtyZXR1cm4gZS5zdXBwcmVzc1RyYWNpbmc/ZS5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3QgZT0kdCh1dCgpKTtpZigyPT09dC5sZW5ndGgpe2NvbnN0W24scl09dDtyZXR1cm4gbj9lLndpdGhTZXRTY29wZShuLHIpOmUud2l0aFNjb3BlKHIpfXJldHVybiBlLndpdGhTY29wZSh0WzBdKX0oKGU9PihlLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W0p0XTohMH0pLHQoKSkpKX1mdW5jdGlvbiBIdCh0LGUpe2NvbnN0e2ZpbmdlcnByaW50Om4sc3BhbjpyLGJyZWFkY3J1bWJzOm8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnN9PWU7IWZ1bmN0aW9uKHQsZSl7Y29uc3R7ZXh0cmE6bix0YWdzOnIsdXNlcjpvLGNvbnRleHRzOnMsbGV2ZWw6aSx0cmFuc2FjdGlvbk5hbWU6Y309ZSx1PWoobik7dSYmT2JqZWN0LmtleXModSkubGVuZ3RoJiYodC5leHRyYT17Li4udSwuLi50LmV4dHJhfSk7Y29uc3QgYT1qKHIpO2EmJk9iamVjdC5rZXlzKGEpLmxlbmd0aCYmKHQudGFncz17Li4uYSwuLi50LnRhZ3N9KTtjb25zdCBmPWoobyk7ZiYmT2JqZWN0LmtleXMoZikubGVuZ3RoJiYodC51c2VyPXsuLi5mLC4uLnQudXNlcn0pO2NvbnN0IGg9aihzKTtoJiZPYmplY3Qua2V5cyhoKS5sZW5ndGgmJih0LmNvbnRleHRzPXsuLi5oLC4uLnQuY29udGV4dHN9KTtpJiYodC5sZXZlbD1pKTtjJiYidHJhbnNhY3Rpb24iIT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1jKX0odCxlKSxyJiZmdW5jdGlvbih0LGUpe3QuY29udGV4dHM9e3RyYWNlOkF0KGUpLC4uLnQuY29udGV4dHN9LHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXtkeW5hbWljU2FtcGxpbmdDb250ZXh0Omp0KGUpLC4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhfTtjb25zdCBuPUJ0KGUpLHI9VXQobikuZGVzY3JpcHRpb247ciYmIXQudHJhbnNhY3Rpb24mJiJ0cmFuc2FjdGlvbiI9PT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPXIpfSh0LHIpLGZ1bmN0aW9uKHQsZSl7dC5maW5nZXJwcmludD10LmZpbmdlcnByaW50P2Z1bmN0aW9uKHQpe3JldHVybiBBcnJheS5pc0FycmF5KHQpP3Q6W3RdfSh0LmZpbmdlcnByaW50KTpbXSxlJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChlKSk7dC5maW5nZXJwcmludCYmIXQuZmluZ2VycHJpbnQubGVuZ3RoJiZkZWxldGUgdC5maW5nZXJwcmludH0odCxuKSxmdW5jdGlvbih0LGUpe2NvbnN0IG49Wy4uLnQuYnJlYWRjcnVtYnN8fFtdLC4uLmVdO3QuYnJlYWRjcnVtYnM9bi5sZW5ndGg/bjp2b2lkIDB9KHQsbyksZnVuY3Rpb24odCxlKXt0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17Li4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEsLi4uZX19KHQscyl9Y29uc3QgV3Q9IjciO2Z1bmN0aW9uIFl0KHQsZSl7cmV0dXJuIG49e3NlbnRyeV9rZXk6dC5wdWJsaWNLZXksc2VudHJ5X3ZlcnNpb246V3QsLi4uZSYme3NlbnRyeV9jbGllbnQ6YCR7ZS5uYW1lfS8ke2UudmVyc2lvbn1gfX0sT2JqZWN0LmtleXMobikubWFwKCh0PT5gJHtlbmNvZGVVUklDb21wb25lbnQodCl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KG5bdF0pfWApKS5qb2luKCImIik7dmFyIG59Y29uc3QgcXQ9NjQ7ZnVuY3Rpb24gRnQodCxlLG49cSh0LmJ1ZmZlclNpemV8fHF0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24obyl7Y29uc3Qgcz1bXTtpZihYKG8sKChlLG4pPT57Y29uc3Qgbz1ydChuKTtpZihmdW5jdGlvbih0LGUsbj1EYXRlLm5vdygpKXtyZXR1cm4gZnVuY3Rpb24odCxlKXtyZXR1cm4gdFtlXXx8dC5hbGx8fDB9KHQsZSk+bn0ocixvKSl7Y29uc3Qgcj1LdChlLG4pO3QucmVjb3JkRHJvcHBlZEV2ZW50KCJyYXRlbGltaXRfYmFja29mZiIsbyxyKX1lbHNlIHMucHVzaChlKX0pKSwwPT09cy5sZW5ndGgpcmV0dXJuIFcoe30pO2NvbnN0IGk9UShvWzBdLHMpLGM9ZT0+e1goaSwoKG4scik9Pntjb25zdCBvPUt0KG4scik7dC5yZWNvcmREcm9wcGVkRXZlbnQoZSxydChyKSxvKX0pKX07cmV0dXJuIG4uYWRkKCgoKT0+ZSh7Ym9keTpldChpKX0pLnRoZW4oKHQ9Pih2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJmN0JiZOLndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPWl0KHIsdCksdCkpLCh0PT57dGhyb3cgYygibmV0d29ya19lcnJvciIpLHR9KSkpKS50aGVuKCh0PT50KSwodD0+e2lmKHQgaW5zdGFuY2VvZiBDKXJldHVybiBjdCYmTi5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIiksYygicXVldWVfb3ZlcmZsb3ciKSxXKHt9KTt0aHJvdyB0fSkpfSxmbHVzaDp0PT5uLmRyYWluKHQpfX1mdW5jdGlvbiBLdCh0LGUpe2lmKCJldmVudCI9PT1lfHwidHJhbnNhY3Rpb24iPT09ZSlyZXR1cm4gQXJyYXkuaXNBcnJheSh0KT90WzFdOnZvaWQgMH1jb25zdCBWdD1TeW1ib2woIkFnZW50QmFzZUludGVybmFsU3RhdGUiKTtjbGFzcyBadCBleHRlbmRzIGguQWdlbnR7W1Z0XTtvcHRpb25zO2tlZXBBbGl2ZTtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzW1Z0XT17fX1pc1NlY3VyZUVuZHBvaW50KHQpe2lmKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIHQuc2VjdXJlRW5kcG9pbnQpcmV0dXJuIHQuc2VjdXJlRW5kcG9pbnQ7aWYoInN0cmluZyI9PXR5cGVvZiB0LnByb3RvY29sKXJldHVybiJodHRwczoiPT09dC5wcm90b2NvbH1jb25zdHtzdGFjazplfT1uZXcgRXJyb3I7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBlJiZlLnNwbGl0KCJcbiIpLnNvbWUoKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKSl9Y3JlYXRlU29ja2V0KHQsZSxuKXtjb25zdCByPXsuLi5lLHNlY3VyZUVuZHBvaW50OnRoaXMuaXNTZWN1cmVFbmRwb2ludChlKX07UHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKCk9PnRoaXMuY29ubmVjdCh0LHIpKSkudGhlbigobz0+e2lmKG8gaW5zdGFuY2VvZiBoLkFnZW50KXJldHVybiBvLmFkZFJlcXVlc3QodCxyKTt0aGlzW1Z0XS5jdXJyZW50U29ja2V0PW8sc3VwZXIuY3JlYXRlU29ja2V0KHQsZSxuKX0pLG4pfWNyZWF0ZUNvbm5lY3Rpb24oKXtjb25zdCB0PXRoaXNbVnRdLmN1cnJlbnRTb2NrZXQ7aWYodGhpc1tWdF0uY3VycmVudFNvY2tldD12b2lkIDAsIXQpdGhyb3cgbmV3IEVycm9yKCJObyBzb2NrZXQgd2FzIHJldHVybmVkIGluIHRoZSBgY29ubmVjdCgpYCBmdW5jdGlvbiIpO3JldHVybiB0fWdldCBkZWZhdWx0UG9ydCgpe3JldHVybiB0aGlzW1Z0XS5kZWZhdWx0UG9ydD8/KCJodHRwczoiPT09dGhpcy5wcm90b2NvbD80NDM6ODApfXNldCBkZWZhdWx0UG9ydCh0KXt0aGlzW1Z0XSYmKHRoaXNbVnRdLmRlZmF1bHRQb3J0PXQpfWdldCBwcm90b2NvbCgpe3JldHVybiB0aGlzW1Z0XS5wcm90b2NvbD8/KHRoaXMuaXNTZWN1cmVFbmRwb2ludCgpPyJodHRwczoiOiJodHRwOiIpfXNldCBwcm90b2NvbCh0KXt0aGlzW1Z0XSYmKHRoaXNbVnRdLnByb3RvY29sPXQpfX1mdW5jdGlvbiBRdCguLi50KXtOLmxvZygiW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXSIsLi4udCl9ZnVuY3Rpb24gWHQodCl7cmV0dXJuIG5ldyBQcm9taXNlKCgoZSxuKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBzKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIFF0KCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgcygpO2NvbnN0IGY9dS5zbGljZSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLG4obmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGw9K3BbMV0sZD1wLnNsaWNlKDIpLmpvaW4oIiAiKSxtPXt9O2Zvcihjb25zdCBlIG9mIGYpe2lmKCFlKWNvbnRpbnVlO2NvbnN0IHI9ZS5pbmRleE9mKCI6Iik7aWYoLTE9PT1yKXJldHVybiB0LmRlc3Ryb3koKSxuKG5ldyBFcnJvcihgSW52YWxpZCBoZWFkZXIgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlOiAiJHtlfSJgKSk7Y29uc3Qgbz1lLnNsaWNlKDAscikudG9Mb3dlckNhc2UoKSxzPWUuc2xpY2UocisxKS50cmltU3RhcnQoKSxpPW1bb107InN0cmluZyI9PXR5cGVvZiBpP21bb109W2ksc106QXJyYXkuaXNBcnJheShpKT9pLnB1c2gocyk6bVtvXT1zfVF0KCJnb3QgcHJveHkgc2VydmVyIHJlc3BvbnNlOiAlbyAlbyIsaCxtKSxpKCksZSh7Y29ubmVjdDp7c3RhdHVzQ29kZTpsLHN0YXR1c1RleHQ6ZCxoZWFkZXJzOm19LGJ1ZmZlcmVkOnV9KX0oYyk6dC5vbmNlKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gaSgpe3QucmVtb3ZlTGlzdGVuZXIoImVuZCIsYyksdC5yZW1vdmVMaXN0ZW5lcigiZXJyb3IiLHUpLHQucmVtb3ZlTGlzdGVuZXIoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBjKCl7aSgpLFF0KCJvbmVuZCIpLG4obmV3IEVycm9yKCJQcm94eSBjb25uZWN0aW9uIGVuZGVkIGJlZm9yZSByZWNlaXZpbmcgQ09OTkVDVCByZXNwb25zZSIpKX1mdW5jdGlvbiB1KHQpe2koKSxRdCgib25lcnJvciAlbyIsdCksbih0KX10Lm9uKCJlcnJvciIsdSksdC5vbigiZW5kIixjKSxzKCl9KSl9ZnVuY3Rpb24gdGUoLi4udCl7Ti5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIGVlIGV4dGVuZHMgWnR7c3RhdGljIHByb3RvY29scz1bImh0dHAiLCJodHRwcyJdO3Byb3h5O3Byb3h5SGVhZGVycztjb25uZWN0T3B0cztjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKGUpLHRoaXMub3B0aW9ucz17fSx0aGlzLnByb3h5PSJzdHJpbmciPT10eXBlb2YgdD9uZXcgVVJMKHQpOnQsdGhpcy5wcm94eUhlYWRlcnM9ZT8uaGVhZGVycz8/e30sdGUoIkNyZWF0aW5nIG5ldyBIdHRwc1Byb3h5QWdlbnQgaW5zdGFuY2U6ICVvIix0aGlzLnByb3h5LmhyZWYpO2NvbnN0IG49KHRoaXMucHJveHkuaG9zdG5hbWV8fHRoaXMucHJveHkuaG9zdCkucmVwbGFjZSgvXlxbfFxdJC9nLCIiKSxyPXRoaXMucHJveHkucG9ydD9wYXJzZUludCh0aGlzLnByb3h5LnBvcnQsMTApOiJodHRwczoiPT09dGhpcy5wcm94eS5wcm90b2NvbD80NDM6ODA7dGhpcy5jb25uZWN0T3B0cz17QUxQTlByb3RvY29sczpbImh0dHAvMS4xIl0sLi4uZT9yZShlLCJoZWFkZXJzIik6bnVsbCxob3N0Om4scG9ydDpyfX1hc3luYyBjb25uZWN0KHQsZSl7Y29uc3R7cHJveHk6bn09dGhpcztpZighZS5ob3N0KXRocm93IG5ldyBUeXBlRXJyb3IoJ05vICJob3N0IiBwcm92aWRlZCcpO2xldCByO2lmKCJodHRwczoiPT09bi5wcm90b2NvbCl7dGUoIkNyZWF0aW5nIGB0bHMuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IHQ9dGhpcy5jb25uZWN0T3B0cy5zZXJ2ZXJuYW1lfHx0aGlzLmNvbm5lY3RPcHRzLmhvc3Q7cj1mLmNvbm5lY3Qoey4uLnRoaXMuY29ubmVjdE9wdHMsc2VydmVybmFtZTp0JiZhLmlzSVAodCk/dm9pZCAwOnR9KX1lbHNlIHRlKCJDcmVhdGluZyBgbmV0LlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKSxyPWEuY29ubmVjdCh0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCBvPSJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLnByb3h5SGVhZGVycz90aGlzLnByb3h5SGVhZGVycygpOnsuLi50aGlzLnByb3h5SGVhZGVyc30scz1hLmlzSVB2NihlLmhvc3QpP2BbJHtlLmhvc3R9XWA6ZS5ob3N0O2xldCBpPWBDT05ORUNUICR7c306JHtlLnBvcnR9IEhUVFAvMS4xXHJcbmA7aWYobi51c2VybmFtZXx8bi5wYXNzd29yZCl7Y29uc3QgdD1gJHtkZWNvZGVVUklDb21wb25lbnQobi51c2VybmFtZSl9OiR7ZGVjb2RlVVJJQ29tcG9uZW50KG4ucGFzc3dvcmQpfWA7b1siUHJveHktQXV0aG9yaXphdGlvbiJdPWBCYXNpYyAke0J1ZmZlci5mcm9tKHQpLnRvU3RyaW5nKCJiYXNlNjQiKX1gfW8uSG9zdD1gJHtzfToke2UucG9ydH1gLG9bIlByb3h5LUNvbm5lY3Rpb24iXXx8KG9bIlByb3h5LUNvbm5lY3Rpb24iXT10aGlzLmtlZXBBbGl2ZT8iS2VlcC1BbGl2ZSI6ImNsb3NlIik7Zm9yKGNvbnN0IHQgb2YgT2JqZWN0LmtleXMobykpaSs9YCR7dH06ICR7b1t0XX1cclxuYDtjb25zdCBjPVh0KHIpO3Iud3JpdGUoYCR7aX1cclxuYCk7Y29uc3R7Y29ubmVjdDp1LGJ1ZmZlcmVkOmh9PWF3YWl0IGM7aWYodC5lbWl0KCJwcm94eUNvbm5lY3QiLHUpLHRoaXMuZW1pdCgicHJveHlDb25uZWN0Iix1LHQpLDIwMD09PXUuc3RhdHVzQ29kZSl7aWYodC5vbmNlKCJzb2NrZXQiLG5lKSxlLnNlY3VyZUVuZHBvaW50KXt0ZSgiVXBncmFkaW5nIHNvY2tldCBjb25uZWN0aW9uIHRvIFRMUyIpO2NvbnN0IHQ9ZS5zZXJ2ZXJuYW1lfHxlLmhvc3Q7cmV0dXJuIGYuY29ubmVjdCh7Li4ucmUoZSwiaG9zdCIsInBhdGgiLCJwb3J0Iiksc29ja2V0OnIsc2VydmVybmFtZTphLmlzSVAodCk/dm9pZCAwOnR9KX1yZXR1cm4gcn1yLmRlc3Ryb3koKTtjb25zdCBwPW5ldyBhLlNvY2tldCh7d3JpdGFibGU6ITF9KTtyZXR1cm4gcC5yZWFkYWJsZT0hMCx0Lm9uY2UoInNvY2tldCIsKHQ9Pnt0ZSgiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkpLHB9fWZ1bmN0aW9uIG5lKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gcmUodCwuLi5lKXtjb25zdCBuPXt9O2xldCByO2ZvcihyIGluIHQpZS5pbmNsdWRlcyhyKXx8KG5bcl09dFtyXSk7cmV0dXJuIG59Y29uc3Qgb2U9MzI3Njg7ZnVuY3Rpb24gc2UodCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBpZT1uO2xldCBjZSx1ZT0hMTtmdW5jdGlvbiBhZSh0KXtpZS5kZWJ1ZyYmY29uc29sZS5sb2coYFtBTlIgV29ya2VyXSAke3R9YCl9dmFyIGZlLGhlLHBlO2NvbnN0IGxlPWZ1bmN0aW9uKHQpe2xldCBlO3RyeXtlPW5ldyBVUkwodC51cmwpfWNhdGNoKGUpe3JldHVybiB4KCgoKT0+e2NvbnNvbGUud2FybigiW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4iKX0pKSxGdCh0LCgoKT0+UHJvbWlzZS5yZXNvbHZlKHt9KSkpfWNvbnN0IG49Imh0dHBzOiI9PT1lLnByb3RvY29sLHI9ZnVuY3Rpb24odCxlKXtjb25zdHtub19wcm94eTpufT1wcm9jZXNzLmVudjtyZXR1cm4gbiYmbi5zcGxpdCgiLCIpLnNvbWUoKGU9PnQuaG9zdC5lbmRzV2l0aChlKXx8dC5ob3N0bmFtZS5lbmRzV2l0aChlKSkpP3ZvaWQgMDplfShlLHQucHJveHl8fChuP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89bj9pOnMsYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBlZShyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pO3JldHVybiB6dCgoKCk9Pntjb25zdCBlPWZ1bmN0aW9uKHQsZSxuKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDpzLHByb3RvY29sOmksc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKChoLHApPT57bGV0IGw9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBjKHtyZWFkKCl7dGhpcy5wdXNoKHQpLHRoaXMucHVzaChudWxsKX19KX0oZi5ib2R5KTtjb25zdCBkPXsuLi50LmhlYWRlcnN9O2YuYm9keS5sZW5ndGg+b2UmJihkWyJjb250ZW50LWVuY29kaW5nIl09Imd6aXAiLGw9bC5waXBlKHUoKSkpO2NvbnN0IG09ZS5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50Om4saGVhZGVyczpkLGhvc3RuYW1lOnIscGF0aDpgJHtvfSR7YX1gLHBvcnQ6cyxwcm90b2NvbDppLGNhOnQuY2FDZXJ0c30sKHQ9Pnt0Lm9uKCJkYXRhIiwoKCk9Pnt9KSksdC5vbigiZW5kIiwoKCk9Pnt9KSksdC5zZXRFbmNvZGluZygidXRmOCIpO2NvbnN0IGU9dC5oZWFkZXJzWyJyZXRyeS1hZnRlciJdPz9udWxsLG49dC5oZWFkZXJzWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdPz9udWxsO2goe3N0YXR1c0NvZGU6dC5zdGF0dXNDb2RlLGhlYWRlcnM6eyJyZXRyeS1hZnRlciI6ZSwieC1zZW50cnktcmF0ZS1saW1pdHMiOkFycmF5LmlzQXJyYXkobik/blswXTpufX0pfSkpO20ub24oImVycm9yIixwKSxsLnBpcGUobSl9KSl9fSh0LHQuaHR0cE1vZHVsZT8/byxmKTtyZXR1cm4gRnQodCxlKX0pKX0oe3VybDooZmU9aWUuZHNuLGhlPWllLnR1bm5lbCxwZT1pZS5zZGtNZXRhZGF0YS5zZGssaGV8fGAke2Z1bmN0aW9uKHQpe3JldHVybmAke2Z1bmN0aW9uKHQpe2NvbnN0IGU9dC5wcm90b2NvbD9gJHt0LnByb3RvY29sfTpgOiIiLG49dC5wb3J0P2A6JHt0LnBvcnR9YDoiIjtyZXR1cm5gJHtlfS8vJHt0Lmhvc3R9JHtufSR7dC5wYXRoP2AvJHt0LnBhdGh9YDoiIn0vYXBpL2B9KHQpfSR7dC5wcm9qZWN0SWR9L2VudmVsb3BlL2B9KGZlKX0/JHtZdChmZSxwZSl9YCkscmVjb3JkRHJvcHBlZEV2ZW50OigpPT57fX0pO2FzeW5jIGZ1bmN0aW9uIGRlKCl7aWYoY2Upe2FlKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxodChjZSx7c3RhdHVzOiJhYm5vcm1hbCIsYWJub3JtYWxfbWVjaGFuaXNtOiJhbnJfZm9yZWdyb3VuZCJ9KTtjb25zdCB0PWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89b3Qobik7cmV0dXJuIFEoe3NlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZlJiZ7ZHNuOmsoZSl9fSxbImFnZ3JlZ2F0ZXMiaW4gdD9be3R5cGU6InNlc3Npb25zIn0sdF06W3t0eXBlOiJzZXNzaW9uIn0sdC50b0pTT04oKV1dKX0oY2UsaWUuZHNuLGllLnNka01ldGFkYXRhLGllLnR1bm5lbCk7YWUoSlNPTi5zdHJpbmdpZnkodCkpLGF3YWl0IGxlLnNlbmQodCk7dHJ5e2U/LnBvc3RNZXNzYWdlKCJzZXNzaW9uLWVuZGVkIil9Y2F0Y2godCl7fX19ZnVuY3Rpb24gbWUodCl7aWYoIXQpcmV0dXJuO2NvbnN0IGU9ZnVuY3Rpb24odCl7aWYoIXQubGVuZ3RoKXJldHVybltdO2NvbnN0IGU9QXJyYXkuZnJvbSh0KTtyZXR1cm4vc2VudHJ5V3JhcHBlZC8udGVzdChlW2UubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJmUucG9wKCksZS5yZXZlcnNlKCksUC50ZXN0KGVbZS5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmKGUucG9wKCksUC50ZXN0KGVbZS5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmZS5wb3AoKSksZS5zbGljZSgwLEEpLm1hcCgodD0+KHsuLi50LGZpbGVuYW1lOnQuZmlsZW5hbWV8fGVbZS5sZW5ndGgtMV0uZmlsZW5hbWUsZnVuY3Rpb246dC5mdW5jdGlvbnx8SX0pKSl9KHQpO2lmKGllLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIGUpdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9Ryh0LmZpbGVuYW1lLGllLmFwcFJvb3RQYXRoKSk7cmV0dXJuIGV9YXN5bmMgZnVuY3Rpb24gZ2UodCxlKXtpZih1ZSlyZXR1cm47dWU9ITAsYXdhaXQgZGUoKSxhZSgiU2VuZGluZyBldmVudCIpO2NvbnN0IG49e2V2ZW50X2lkOk0oKSxjb250ZXh0czppZS5jb250ZXh0cyxyZWxlYXNlOmllLnJlbGVhc2UsZW52aXJvbm1lbnQ6aWUuZW52aXJvbm1lbnQsZGlzdDppZS5kaXN0LHBsYXRmb3JtOiJub2RlIixsZXZlbDoiZXJyb3IiLGV4Y2VwdGlvbjp7dmFsdWVzOlt7dHlwZToiQXBwbGljYXRpb25Ob3RSZXNwb25kaW5nIix2YWx1ZTpgQXBwbGljYXRpb24gTm90IFJlc3BvbmRpbmcgZm9yIGF0IGxlYXN0ICR7aWUuYW5yVGhyZXNob2xkfSBtc2Asc3RhY2t0cmFjZTp7ZnJhbWVzOm1lKHQpfSxtZWNoYW5pc206e3R5cGU6IkFOUiJ9fV19LHRhZ3M6aWUuc3RhdGljVGFnc307ZSYmZnVuY3Rpb24odCxlKXtpZihIdCh0LGUpLCF0LmNvbnRleHRzPy50cmFjZSl7Y29uc3R7dHJhY2VJZDpuLHNwYW5JZDpyLHBhcmVudFNwYW5JZDpvfT1lLnByb3BhZ2F0aW9uQ29udGV4dDt0LmNvbnRleHRzPXt0cmFjZTp7dHJhY2VfaWQ6bixzcGFuX2lkOnIscGFyZW50X3NwYW5faWQ6b30sLi4udC5jb250ZXh0c319fShuLGUpO2NvbnN0IHI9R3QobixpZS5kc24saWUuc2RrTWV0YWRhdGEsaWUudHVubmVsKTthZShKU09OLnN0cmluZ2lmeShyKSksYXdhaXQgbGUuc2VuZChyKSxhd2FpdCBsZS5mbHVzaCgyZTMpLHNldFRpbWVvdXQoKCgpPT57cHJvY2Vzcy5leGl0KDApfSksNWUzKX1sZXQgeWU7aWYoYWUoIlN0YXJ0ZWQiKSxpZS5jYXB0dXJlU3RhY2tUcmFjZSl7YWUoIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyB0O2UuY29ubmVjdFRvTWFpblRocmVhZCgpLGFlKCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyBNYXA7ZS5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIiwodD0+e24uc2V0KHQucGFyYW1zLnNjcmlwdElkLHQucGFyYW1zLnVybCl9KSksZS5vbigiRGVidWdnZXIucGF1c2VkIiwodD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e2FlKCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPWllLmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT96KHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksZT0iXFwiPT09byl7Y29uc3Qgbj1lP3NlKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1lP3NlKHQpOnQ7bGV0e2RpcjpzLGJhc2U6aSxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChpPWkuc2xpY2UoMCwtMSpjLmxlbmd0aCkpLHN8fChzPSIuIik7Y29uc3QgdT1zLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYodT4tMSlyZXR1cm5gJHtzLnNsaWNlKHUrMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHtpfWA7aWYocy5zdGFydHNXaXRoKG4pKXtsZXQgdD1zLnNsaWNlKG4ubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdCYmKHQrPSI6IiksdCs9aSx0fXJldHVybiBpfX0oaWUuYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKCh0PT5mdW5jdGlvbih0LGUsbil7Y29uc3Qgcj1lP2UucmVwbGFjZSgvXmZpbGU6XC9cLy8sIiIpOnZvaWQgMCxvPXQubG9jYXRpb24uY29sdW1uTnVtYmVyP3QubG9jYXRpb24uY29sdW1uTnVtYmVyKzE6dm9pZCAwLHM9dC5sb2NhdGlvbi5saW5lTnVtYmVyP3QubG9jYXRpb24ubGluZU51bWJlcisxOnZvaWQgMDtyZXR1cm4gaih7ZmlsZW5hbWU6cixtb2R1bGU6bihyKSxmdW5jdGlvbjp0LmZ1bmN0aW9uTmFtZXx8SSxjb2xubzpvLGxpbmVubzpzLGluX2FwcDpyP0Yocik6dm9pZCAwfSl9KHQsbi5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCksaSkpKSx1PXNldFRpbWVvdXQoKCgpPT57Z2UoYykudGhlbihudWxsLCgoKT0+e2FlKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSw1ZTMpO2UucG9zdCgiUnVudGltZS5ldmFsdWF0ZSIse2V4cHJlc3Npb246Imdsb2JhbC5fX1NFTlRSWV9HRVRfU0NPUEVTX18oKTsiLHNpbGVudDohMCxyZXR1cm5CeVZhbHVlOiEwfSwoKHQsbik9Pnt0JiZhZShgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1uJiZuLnJlc3VsdD9uLnJlc3VsdC52YWx1ZTp2b2lkIDA7ZS5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxlLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSxnZShjLHIpLnRoZW4obnVsbCwoKCk9PnthZSgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSkpfWNhdGNoKHQpe3Rocm93IGUucG9zdCgiRGVidWdnZXIucmVzdW1lIiksZS5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksdH19KSkseWU9KCk9Pnt0cnl7ZS5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgoKT0+e2UucG9zdCgiRGVidWdnZXIucGF1c2UiKX0pKX1jYXRjaCh0KXt9fX1jb25zdHtwb2xsOmJlfT1mdW5jdGlvbih0LGUsbixyKXtjb25zdCBvPXQoKTtsZXQgcz0hMSxpPSEwO3JldHVybiBzZXRJbnRlcnZhbCgoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1zJiZ0PmUrbiYmKHM9ITAsaSYmcigpKSx0PGUrbiYmKHM9ITEpfSksMjApLHtwb2xsOigpPT57by5yZXNldCgpfSxlbmFibGVkOnQ9PntpPXR9fX0oKGZ1bmN0aW9uKCl7bGV0IHQ9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm57Z2V0VGltZU1zOigpPT57Y29uc3RbZSxuXT1wcm9jZXNzLmhydGltZSh0KTtyZXR1cm4gTWF0aC5mbG9vcigxZTMqZStuLzFlNil9LHJlc2V0OigpPT57dD1wcm9jZXNzLmhydGltZSgpfX19KSxpZS5wb2xsSW50ZXJ2YWwsaWUuYW5yVGhyZXNob2xkLChmdW5jdGlvbigpe2FlKCJXYXRjaGRvZyB0aW1lb3V0IikseWU/KGFlKCJQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UiKSx5ZSgpKTooYWUoIkNhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UiKSxnZSgpLnRoZW4obnVsbCwoKCk9PnthZSgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkIG9uIHdhdGNoZG9nIHRpbWVvdXQuIil9KSkpfSkpO2U/Lm9uKCJtZXNzYWdlIiwodD0+e3Quc2Vzc2lvbiYmKGNlPWZ0KHQuc2Vzc2lvbikpLGJlKCl9KSk7';
|
|
1790
1792
|
|
|
1791
1793
|
const DEFAULT_INTERVAL = 50;
|
|
1792
1794
|
const DEFAULT_HANG_THRESHOLD = 5000;
|
|
@@ -1825,7 +1827,7 @@ async function getContexts(client) {
|
|
|
1825
1827
|
event = await processor(event, eventHint);
|
|
1826
1828
|
}
|
|
1827
1829
|
|
|
1828
|
-
return _optionalChain$
|
|
1830
|
+
return _optionalChain$9([event, 'optionalAccess', _2 => _2.contexts]) || {};
|
|
1829
1831
|
}
|
|
1830
1832
|
|
|
1831
1833
|
const INTEGRATION_NAME$1 = 'Anr';
|
|
@@ -1978,7 +1980,7 @@ async function _startWorker(
|
|
|
1978
1980
|
};
|
|
1979
1981
|
}
|
|
1980
1982
|
|
|
1981
|
-
function _optionalChain$
|
|
1983
|
+
function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1982
1984
|
|
|
1983
1985
|
const _expressIntegration = (() => {
|
|
1984
1986
|
return {
|
|
@@ -2029,7 +2031,7 @@ function expressErrorHandler(options
|
|
|
2029
2031
|
res,
|
|
2030
2032
|
next,
|
|
2031
2033
|
) {
|
|
2032
|
-
const shouldHandleError = _optionalChain$
|
|
2034
|
+
const shouldHandleError = _optionalChain$8([options, 'optionalAccess', _ => _.shouldHandleError]) || defaultShouldHandleError;
|
|
2033
2035
|
|
|
2034
2036
|
if (shouldHandleError(error)) {
|
|
2035
2037
|
const client = getClient$1();
|
|
@@ -2067,6 +2069,15 @@ function expressErrorHandler(options
|
|
|
2067
2069
|
*/
|
|
2068
2070
|
function setupExpressErrorHandler(app) {
|
|
2069
2071
|
app.use(expressErrorHandler());
|
|
2072
|
+
|
|
2073
|
+
if (!isWrapped$1(app.use)) {
|
|
2074
|
+
consoleSandbox(() => {
|
|
2075
|
+
// eslint-disable-next-line no-console
|
|
2076
|
+
console.warn(
|
|
2077
|
+
'[Sentry] Express is not instrumented. This is likely because you required/imported express before calling `Sentry.init()`.',
|
|
2078
|
+
);
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2070
2081
|
}
|
|
2071
2082
|
|
|
2072
2083
|
function getStatusCodeFromResponse(error) {
|
|
@@ -2080,7 +2091,7 @@ function defaultShouldHandleError(error) {
|
|
|
2080
2091
|
return status >= 500;
|
|
2081
2092
|
}
|
|
2082
2093
|
|
|
2083
|
-
function _optionalChain$
|
|
2094
|
+
function _optionalChain$7(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2084
2095
|
const _fastifyIntegration = (() => {
|
|
2085
2096
|
return {
|
|
2086
2097
|
name: 'Fastify',
|
|
@@ -2123,8 +2134,8 @@ function setupFastifyErrorHandler(fastify) {
|
|
|
2123
2134
|
|
|
2124
2135
|
// Taken from Otel Fastify instrumentation:
|
|
2125
2136
|
// https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts#L94-L96
|
|
2126
|
-
const routeName = _optionalChain$
|
|
2127
|
-
const method = _optionalChain$
|
|
2137
|
+
const routeName = _optionalChain$7([reqWithRouteInfo, 'access', _ => _.routeOptions, 'optionalAccess', _2 => _2.url]) || reqWithRouteInfo.routerPath;
|
|
2138
|
+
const method = _optionalChain$7([reqWithRouteInfo, 'access', _3 => _3.routeOptions, 'optionalAccess', _4 => _4.method]) || 'GET';
|
|
2128
2139
|
|
|
2129
2140
|
getIsolationScope().setTransactionName(`${method} ${routeName}`);
|
|
2130
2141
|
});
|
|
@@ -2138,6 +2149,15 @@ function setupFastifyErrorHandler(fastify) {
|
|
|
2138
2149
|
);
|
|
2139
2150
|
|
|
2140
2151
|
fastify.register(plugin);
|
|
2152
|
+
|
|
2153
|
+
if (!isWrapped$1(fastify.addHook)) {
|
|
2154
|
+
consoleSandbox(() => {
|
|
2155
|
+
// eslint-disable-next-line no-console
|
|
2156
|
+
console.warn(
|
|
2157
|
+
'[Sentry] Fastify is not instrumented. This is likely because you required/imported fastify before calling `Sentry.init()`.',
|
|
2158
|
+
);
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2141
2161
|
}
|
|
2142
2162
|
|
|
2143
2163
|
const _graphqlIntegration = (() => {
|
|
@@ -2266,7 +2286,7 @@ const _redisIntegration = (() => {
|
|
|
2266
2286
|
*/
|
|
2267
2287
|
const redisIntegration = defineIntegration(_redisIntegration);
|
|
2268
2288
|
|
|
2269
|
-
function _optionalChain$
|
|
2289
|
+
function _optionalChain$6(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2270
2290
|
const _nestIntegration = (() => {
|
|
2271
2291
|
return {
|
|
2272
2292
|
name: 'Nest',
|
|
@@ -2297,7 +2317,7 @@ function setupNestErrorHandler(app, baseFilter) {
|
|
|
2297
2317
|
if (context.getType() === 'http') {
|
|
2298
2318
|
const req = context.switchToHttp().getRequest();
|
|
2299
2319
|
if (req.route) {
|
|
2300
|
-
getIsolationScope().setTransactionName(`${_optionalChain$
|
|
2320
|
+
getIsolationScope().setTransactionName(`${_optionalChain$6([req, 'access', _ => _.method, 'optionalAccess', _2 => _2.toUpperCase, 'call', _3 => _3()]) || 'GET'} ${req.route.path}`);
|
|
2301
2321
|
}
|
|
2302
2322
|
}
|
|
2303
2323
|
|
|
@@ -2345,7 +2365,7 @@ const _postgresIntegration = (() => {
|
|
|
2345
2365
|
*/
|
|
2346
2366
|
const postgresIntegration = defineIntegration(_postgresIntegration);
|
|
2347
2367
|
|
|
2348
|
-
function _optionalChain$
|
|
2368
|
+
function _optionalChain$5(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// When importing CJS modules into an ESM module, we cannot import the named exports directly.
|
|
2349
2369
|
|
|
2350
2370
|
const _prismaIntegration = (() => {
|
|
2351
2371
|
return {
|
|
@@ -2360,7 +2380,7 @@ const _prismaIntegration = (() => {
|
|
|
2360
2380
|
setup(client) {
|
|
2361
2381
|
client.on('spanStart', span => {
|
|
2362
2382
|
const spanJSON = spanToJSON(span);
|
|
2363
|
-
if (_optionalChain$
|
|
2383
|
+
if (_optionalChain$5([spanJSON, 'access', _ => _.description, 'optionalAccess', _2 => _2.startsWith, 'call', _3 => _3('prisma:')])) {
|
|
2364
2384
|
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.prisma');
|
|
2365
2385
|
}
|
|
2366
2386
|
|
|
@@ -2383,7 +2403,7 @@ const _prismaIntegration = (() => {
|
|
|
2383
2403
|
*/
|
|
2384
2404
|
const prismaIntegration = defineIntegration(_prismaIntegration);
|
|
2385
2405
|
|
|
2386
|
-
function _optionalChain$
|
|
2406
|
+
function _optionalChain$4(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2387
2407
|
const _hapiIntegration = (() => {
|
|
2388
2408
|
return {
|
|
2389
2409
|
name: 'Hapi',
|
|
@@ -2432,7 +2452,7 @@ const hapiErrorPlugin = {
|
|
|
2432
2452
|
if (getIsolationScope() !== getDefaultIsolationScope()) {
|
|
2433
2453
|
const route = request.route;
|
|
2434
2454
|
if (route && route.path) {
|
|
2435
|
-
getIsolationScope().setTransactionName(`${_optionalChain$
|
|
2455
|
+
getIsolationScope().setTransactionName(`${_optionalChain$4([route, 'access', _ => _.method, 'optionalAccess', _2 => _2.toUpperCase, 'call', _3 => _3()]) || 'GET'} ${route.path}`);
|
|
2436
2456
|
}
|
|
2437
2457
|
} else {
|
|
2438
2458
|
DEBUG_BUILD &&
|
|
@@ -2461,6 +2481,16 @@ const hapiErrorPlugin = {
|
|
|
2461
2481
|
*/
|
|
2462
2482
|
async function setupHapiErrorHandler(server) {
|
|
2463
2483
|
await server.register(hapiErrorPlugin);
|
|
2484
|
+
|
|
2485
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
2486
|
+
if (!isWrapped$1(server.register)) {
|
|
2487
|
+
consoleSandbox(() => {
|
|
2488
|
+
// eslint-disable-next-line no-console
|
|
2489
|
+
console.warn(
|
|
2490
|
+
'[Sentry] Hapi is not instrumented. This is likely because you required/imported hapi before calling `Sentry.init()`.',
|
|
2491
|
+
);
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2464
2494
|
}
|
|
2465
2495
|
|
|
2466
2496
|
const _koaIntegration = (() => {
|
|
@@ -2499,6 +2529,15 @@ const setupKoaErrorHandler = (app) => {
|
|
|
2499
2529
|
captureException(error);
|
|
2500
2530
|
}
|
|
2501
2531
|
});
|
|
2532
|
+
|
|
2533
|
+
if (!isWrapped$1(app.use)) {
|
|
2534
|
+
consoleSandbox(() => {
|
|
2535
|
+
// eslint-disable-next-line no-console
|
|
2536
|
+
console.warn(
|
|
2537
|
+
'[Sentry] Koa is not instrumented. This is likely because you required/imported koa before calling `Sentry.init()`.',
|
|
2538
|
+
);
|
|
2539
|
+
});
|
|
2540
|
+
}
|
|
2502
2541
|
};
|
|
2503
2542
|
|
|
2504
2543
|
const _connectIntegration = (() => {
|
|
@@ -2520,6 +2559,15 @@ function connectErrorMiddleware(err, req, res, next) {
|
|
|
2520
2559
|
|
|
2521
2560
|
const setupConnectErrorHandler = (app) => {
|
|
2522
2561
|
app.use(connectErrorMiddleware);
|
|
2562
|
+
|
|
2563
|
+
if (!isWrapped$1(app.use)) {
|
|
2564
|
+
consoleSandbox(() => {
|
|
2565
|
+
// eslint-disable-next-line no-console
|
|
2566
|
+
console.warn(
|
|
2567
|
+
'[Sentry] Connect is not instrumented. This is likely because you required/imported connect before calling `Sentry.init()`.',
|
|
2568
|
+
);
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2523
2571
|
};
|
|
2524
2572
|
|
|
2525
2573
|
const INTEGRATION_NAME = 'Spotlight';
|
|
@@ -2860,7 +2908,7 @@ function parseProxyResponse(socket) {
|
|
|
2860
2908
|
});
|
|
2861
2909
|
}
|
|
2862
2910
|
|
|
2863
|
-
function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }function _optionalChain$
|
|
2911
|
+
function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }function _optionalChain$3(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2864
2912
|
|
|
2865
2913
|
function debug(...args) {
|
|
2866
2914
|
logger.log('[https-proxy-agent]', ...args);
|
|
@@ -2885,7 +2933,7 @@ class HttpsProxyAgent extends Agent {
|
|
|
2885
2933
|
super(opts);
|
|
2886
2934
|
this.options = {};
|
|
2887
2935
|
this.proxy = typeof proxy === 'string' ? new URL(proxy) : proxy;
|
|
2888
|
-
this.proxyHeaders = _nullishCoalesce$1(_optionalChain$
|
|
2936
|
+
this.proxyHeaders = _nullishCoalesce$1(_optionalChain$3([opts, 'optionalAccess', _2 => _2.headers]), () => ( {}));
|
|
2889
2937
|
debug('Creating new HttpsProxyAgent instance: %o', this.proxy.href);
|
|
2890
2938
|
|
|
2891
2939
|
// Trim off the brackets from IPv6 addresses
|
|
@@ -3264,7 +3312,7 @@ function getSentryRelease(fallback) {
|
|
|
3264
3312
|
/** Node.js stack parser */
|
|
3265
3313
|
const defaultStackParser = createStackParser(nodeStackLineParser(createGetModuleFromFilename()));
|
|
3266
3314
|
|
|
3267
|
-
function _optionalChain$
|
|
3315
|
+
function _optionalChain$2(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
3268
3316
|
/** A client for using Sentry with Node & OpenTelemetry. */
|
|
3269
3317
|
class NodeClient extends ServerRuntimeClient {
|
|
3270
3318
|
|
|
@@ -3300,7 +3348,7 @@ class NodeClient extends ServerRuntimeClient {
|
|
|
3300
3348
|
*/
|
|
3301
3349
|
async flush(timeout) {
|
|
3302
3350
|
const provider = this.traceProvider;
|
|
3303
|
-
const spanProcessor = _optionalChain$
|
|
3351
|
+
const spanProcessor = _optionalChain$2([provider, 'optionalAccess', _ => _.activeSpanProcessor]);
|
|
3304
3352
|
|
|
3305
3353
|
if (spanProcessor) {
|
|
3306
3354
|
await spanProcessor.forceFlush();
|
|
@@ -3414,13 +3462,27 @@ function init(options = {}) {
|
|
|
3414
3462
|
}
|
|
3415
3463
|
|
|
3416
3464
|
if (!isCjs()) {
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3465
|
+
const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number);
|
|
3466
|
+
|
|
3467
|
+
// Register hook was added in v20.6.0 and v18.19.0
|
|
3468
|
+
if (nodeMajor >= 22 || (nodeMajor === 20 && nodeMinor >= 6) || (nodeMajor === 18 && nodeMinor >= 19)) {
|
|
3469
|
+
// We need to work around using import.meta.url directly because jest complains about it.
|
|
3470
|
+
const importMetaUrl =
|
|
3471
|
+
typeof import.meta.url !== 'undefined' ? import.meta.url : undefined;
|
|
3472
|
+
|
|
3473
|
+
if (!GLOBAL_OBJ._sentryEsmLoaderHookRegistered && importMetaUrl) {
|
|
3474
|
+
// @ts-expect-error register is available in these versions
|
|
3475
|
+
moduleModule.register('@opentelemetry/instrumentation/hook.mjs', importMetaUrl);
|
|
3476
|
+
GLOBAL_OBJ._sentryEsmLoaderHookRegistered = true;
|
|
3477
|
+
}
|
|
3478
|
+
} else {
|
|
3479
|
+
consoleSandbox(() => {
|
|
3480
|
+
// eslint-disable-next-line no-console
|
|
3481
|
+
console.warn(
|
|
3482
|
+
'[Sentry] You are using Node.js in ESM mode ("import syntax"). The Sentry Node.js SDK is not compatible with ESM in Node.js versions before 18.19.0 or before 20.6.0. Please either build your application with CommonJS ("require() syntax"), or use version 7.x of the Sentry Node.js SDK.',
|
|
3483
|
+
);
|
|
3484
|
+
});
|
|
3485
|
+
}
|
|
3424
3486
|
}
|
|
3425
3487
|
|
|
3426
3488
|
setOpenTelemetryContextAsyncContextStrategy();
|
|
@@ -3698,11 +3760,16 @@ function instrumentCron(lib, monitorSlug) {
|
|
|
3698
3760
|
|
|
3699
3761
|
const cronString = replaceCronNames(cronTime);
|
|
3700
3762
|
|
|
3701
|
-
function monitoredTick(context, onComplete) {
|
|
3763
|
+
async function monitoredTick(context, onComplete) {
|
|
3702
3764
|
return withMonitor(
|
|
3703
3765
|
monitorSlug,
|
|
3704
|
-
() => {
|
|
3705
|
-
|
|
3766
|
+
async () => {
|
|
3767
|
+
try {
|
|
3768
|
+
await onTick(context, onComplete);
|
|
3769
|
+
} catch (e) {
|
|
3770
|
+
captureException(e);
|
|
3771
|
+
throw e;
|
|
3772
|
+
}
|
|
3706
3773
|
},
|
|
3707
3774
|
{
|
|
3708
3775
|
schedule: { type: 'crontab', value: cronString },
|
|
@@ -3730,11 +3797,16 @@ function instrumentCron(lib, monitorSlug) {
|
|
|
3730
3797
|
|
|
3731
3798
|
const cronString = replaceCronNames(cronTime);
|
|
3732
3799
|
|
|
3733
|
-
param.onTick = (context, onComplete) => {
|
|
3800
|
+
param.onTick = async (context, onComplete) => {
|
|
3734
3801
|
return withMonitor(
|
|
3735
3802
|
monitorSlug,
|
|
3736
|
-
() => {
|
|
3737
|
-
|
|
3803
|
+
async () => {
|
|
3804
|
+
try {
|
|
3805
|
+
await onTick(context, onComplete);
|
|
3806
|
+
} catch (e) {
|
|
3807
|
+
captureException(e);
|
|
3808
|
+
throw e;
|
|
3809
|
+
}
|
|
3738
3810
|
},
|
|
3739
3811
|
{
|
|
3740
3812
|
schedule: { type: 'crontab', value: cronString },
|
|
@@ -3752,12 +3824,13 @@ function instrumentCron(lib, monitorSlug) {
|
|
|
3752
3824
|
});
|
|
3753
3825
|
}
|
|
3754
3826
|
|
|
3827
|
+
function _optionalChain$1(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
3755
3828
|
/**
|
|
3756
3829
|
* Wraps the `node-cron` library with check-in monitoring.
|
|
3757
3830
|
*
|
|
3758
3831
|
* ```ts
|
|
3759
3832
|
* import * as Sentry from "@sentry/node";
|
|
3760
|
-
* import cron from "node-cron";
|
|
3833
|
+
* import * as cron from "node-cron";
|
|
3761
3834
|
*
|
|
3762
3835
|
* const cronWithCheckIn = Sentry.cron.instrumentNodeCron(cron);
|
|
3763
3836
|
*
|
|
@@ -3777,22 +3850,33 @@ function instrumentNodeCron(lib) {
|
|
|
3777
3850
|
// When 'get' is called for schedule, return a proxied version of the schedule function
|
|
3778
3851
|
return new Proxy(target.schedule, {
|
|
3779
3852
|
apply(target, thisArg, argArray) {
|
|
3780
|
-
const [expression, , options] = argArray;
|
|
3853
|
+
const [expression, callback, options] = argArray;
|
|
3781
3854
|
|
|
3782
|
-
if (!_optionalChain([options, 'optionalAccess', _ => _.name])) {
|
|
3855
|
+
if (!_optionalChain$1([options, 'optionalAccess', _ => _.name])) {
|
|
3783
3856
|
throw new Error('Missing "name" for scheduled job. A name is required for Sentry check-in monitoring.');
|
|
3784
3857
|
}
|
|
3785
3858
|
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3859
|
+
async function monitoredCallback() {
|
|
3860
|
+
return withMonitor(
|
|
3861
|
+
options.name,
|
|
3862
|
+
async () => {
|
|
3863
|
+
// We have to manually catch here and capture the exception because node-cron swallows errors
|
|
3864
|
+
// https://github.com/node-cron/node-cron/issues/399
|
|
3865
|
+
try {
|
|
3866
|
+
return await callback();
|
|
3867
|
+
} catch (e) {
|
|
3868
|
+
captureException(e);
|
|
3869
|
+
throw e;
|
|
3870
|
+
}
|
|
3871
|
+
},
|
|
3872
|
+
{
|
|
3873
|
+
schedule: { type: 'crontab', value: replaceCronNames(expression) },
|
|
3874
|
+
timezone: _optionalChain$1([options, 'optionalAccess', _2 => _2.timezone]),
|
|
3875
|
+
},
|
|
3876
|
+
);
|
|
3877
|
+
}
|
|
3878
|
+
|
|
3879
|
+
return target.apply(thisArg, [expression, monitoredCallback, options]);
|
|
3796
3880
|
},
|
|
3797
3881
|
});
|
|
3798
3882
|
} else {
|
|
@@ -3823,9 +3907,13 @@ function instrumentNodeSchedule(lib) {
|
|
|
3823
3907
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
3824
3908
|
return new Proxy(target.scheduleJob, {
|
|
3825
3909
|
apply(target, thisArg, argArray) {
|
|
3826
|
-
const [nameOrExpression, expressionOrCallback] = argArray;
|
|
3910
|
+
const [nameOrExpression, expressionOrCallback, callback] = argArray;
|
|
3827
3911
|
|
|
3828
|
-
if (
|
|
3912
|
+
if (
|
|
3913
|
+
typeof nameOrExpression !== 'string' ||
|
|
3914
|
+
typeof expressionOrCallback !== 'string' ||
|
|
3915
|
+
typeof callback !== 'function'
|
|
3916
|
+
) {
|
|
3829
3917
|
throw new Error(
|
|
3830
3918
|
"Automatic instrumentation of 'node-schedule' requires the first parameter of 'scheduleJob' to be a job name string and the second parameter to be a crontab string",
|
|
3831
3919
|
);
|
|
@@ -3834,15 +3922,19 @@ function instrumentNodeSchedule(lib) {
|
|
|
3834
3922
|
const monitorSlug = nameOrExpression;
|
|
3835
3923
|
const expression = expressionOrCallback;
|
|
3836
3924
|
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3925
|
+
async function monitoredCallback() {
|
|
3926
|
+
return withMonitor(
|
|
3927
|
+
monitorSlug,
|
|
3928
|
+
async () => {
|
|
3929
|
+
await _optionalChain([callback, 'optionalCall', _ => _()]);
|
|
3930
|
+
},
|
|
3931
|
+
{
|
|
3932
|
+
schedule: { type: 'crontab', value: replaceCronNames(expression) },
|
|
3933
|
+
},
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
return target.apply(thisArg, [monitorSlug, expression, monitoredCallback]);
|
|
3846
3938
|
},
|
|
3847
3939
|
});
|
|
3848
3940
|
}
|