@cartanova/qgrid-cli 1.0.1 → 1.0.3
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/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
- package/bundle/dist/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
- package/bundle/dist/dist/_virtual/_rolldown/runtime.js +15 -0
- package/bundle/dist/dist/application/qgrid/oauth.js +140 -0
- package/bundle/dist/dist/application/qgrid/pool.js +100 -0
- package/bundle/dist/dist/application/qgrid/qgrid.frame.js +280 -0
- package/bundle/dist/dist/application/qgrid/qgrid.types.js +79 -0
- package/bundle/dist/dist/application/qgrid/worker.js +183 -0
- package/bundle/dist/dist/application/queries.generated.js +31 -0
- package/bundle/dist/dist/application/request-log/request-log.model.js +113 -0
- package/bundle/dist/dist/application/request-log/request-log.types.js +13 -0
- package/bundle/dist/dist/application/sonamu.generated.js +99 -0
- package/bundle/dist/dist/application/sonamu.generated.sso.js +34 -0
- package/bundle/dist/dist/application/token/token.model.js +157 -0
- package/bundle/dist/dist/application/token/token.types.js +22 -0
- package/bundle/dist/dist/i18n/en.js +63 -0
- package/bundle/dist/dist/i18n/ko.js +62 -0
- package/bundle/dist/dist/i18n/sd.generated.js +272 -0
- package/bundle/dist/dist/index.js +11 -0
- package/bundle/dist/dist/migrations/20260410171405_create__request_logs.js +26 -0
- package/bundle/dist/dist/migrations/20260410171406_create__tokens.js +24 -0
- package/bundle/dist/dist/migrations/20260411120624_alter_tokens_alter2.js +16 -0
- package/bundle/dist/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +155 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js +1484 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js +887 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js +2746 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js +8 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js +8 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js +662 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js +386 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/constants.js +48 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js +1307 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js +558 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js +33 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js +226 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js +27 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/serialize.js +77 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js +374 -0
- package/bundle/dist/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js +37 -0
- package/bundle/dist/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +2886 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +109 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +10 -0
- package/bundle/dist/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +1127 -0
- package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +21 -0
- package/bundle/dist/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +432 -0
- package/bundle/dist/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +506 -0
- package/bundle/dist/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +86 -0
- package/bundle/dist/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.9.2_@emnapi_runtime@1.9.2_@types_node@25.0.7_esbuild@0.27.4_jiti@2.6.1_sass@1.98.0_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js +426 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +41 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +19 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +202 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/index.DOa3dzoN.js +16 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +59 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/test.p_J6dB8a.js +2910 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +44 -0
- package/bundle/dist/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_vite@8.0.3_@emnapi_core@1.9.2__bb31087278f97a39b31b92010beab980/node_modules/vitest/dist/index.js +28 -0
- package/bundle/dist/dist/sonamu.config.js +196 -0
- package/bundle/dist/dist/testing/fixture.js +8 -0
- package/bundle/dist/dist/testing/global.js +9 -0
- package/bundle/dist/dist/testing/setup-mocks.js +17 -0
- package/bundle/dist/dist/utils/subset-loaders.js +12 -0
- package/bundle/src/application/qgrid/oauth.ts +181 -0
- package/bundle/src/application/qgrid/pool.ts +132 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +275 -0
- package/bundle/src/application/qgrid/qgrid.types.ts +117 -0
- package/bundle/src/application/qgrid/worker.ts +234 -0
- package/bundle/src/application/queries.generated.ts +59 -0
- package/bundle/src/application/request-log/request-log.model.ts +155 -0
- package/bundle/src/application/request-log/request-log.types.ts +15 -0
- package/bundle/src/application/sonamu.generated.http +187 -0
- package/bundle/src/application/sonamu.generated.sso.ts +66 -0
- package/bundle/src/application/sonamu.generated.ts +135 -0
- package/bundle/src/application/token/token.model.ts +160 -0
- package/bundle/src/application/token/token.types.ts +26 -0
- package/bundle/src/i18n/en.ts +59 -0
- package/bundle/src/i18n/ko.ts +59 -0
- package/bundle/src/i18n/sd.generated.ts +384 -0
- package/bundle/src/index.ts +6 -0
- package/bundle/src/sonamu.config.ts +248 -0
- package/bundle/src/src/application/qgrid/oauth.ts +181 -0
- package/bundle/src/src/application/qgrid/pool.ts +132 -0
- package/bundle/src/src/application/qgrid/qgrid.frame.ts +275 -0
- package/bundle/src/src/application/qgrid/qgrid.types.ts +117 -0
- package/bundle/src/src/application/qgrid/worker.ts +234 -0
- package/bundle/src/src/application/queries.generated.ts +59 -0
- package/bundle/src/src/application/request-log/request-log.entity.json +75 -0
- package/bundle/src/src/application/request-log/request-log.model.ts +155 -0
- package/bundle/src/src/application/request-log/request-log.types.ts +15 -0
- package/bundle/src/src/application/sonamu.generated.http +187 -0
- package/bundle/src/src/application/sonamu.generated.sso.ts +66 -0
- package/bundle/src/src/application/sonamu.generated.ts +135 -0
- package/bundle/src/src/application/token/token.entity.json +37 -0
- package/bundle/src/src/application/token/token.model.ts +160 -0
- package/bundle/src/src/application/token/token.types.ts +26 -0
- package/bundle/src/src/i18n/en.ts +59 -0
- package/bundle/src/src/i18n/ko.ts +59 -0
- package/bundle/src/src/i18n/sd.generated.ts +384 -0
- package/bundle/src/src/index.ts +6 -0
- package/bundle/src/src/migrations/20260410171405_create__request_logs.ts +23 -0
- package/bundle/src/src/migrations/20260410171406_create__tokens.ts +21 -0
- package/bundle/src/src/migrations/20260411120624_alter_tokens_alter2.ts +15 -0
- package/bundle/src/src/sonamu.config.ts +248 -0
- package/bundle/src/src/testing/fixture.ts +6 -0
- package/bundle/src/src/testing/global.ts +6 -0
- package/bundle/src/src/testing/setup-mocks.ts +44 -0
- package/bundle/src/src/typings/fastify.d.ts +8 -0
- package/bundle/src/src/typings/sonamu.d.ts +17 -0
- package/bundle/src/src/utils/subset-loaders.ts +11 -0
- package/bundle/src/testing/fixture.ts +6 -0
- package/bundle/src/testing/global.ts +6 -0
- package/bundle/src/testing/setup-mocks.ts +44 -0
- package/bundle/src/typings/fastify.d.ts +8 -0
- package/bundle/src/typings/sonamu.d.ts +17 -0
- package/bundle/src/utils/subset-loaders.ts +11 -0
- package/bundle/web-dist/web-dist/client/assets/index-DlPchHBY.js +116 -0
- package/bundle/web-dist/web-dist/client/assets/index-vZsvyuFn.css +1 -0
- package/bundle/web-dist/web-dist/client/assets/rolldown-runtime-Dw2cE7zH.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/routes-CagDz23B.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/sd.generated-BrQoQXvv.js +47 -0
- package/bundle/web-dist/web-dist/client/assets/services.generated-BspO2L0j.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/show-aXUGa0gm.js +29 -0
- package/bundle/web-dist/web-dist/client/assets/tokens-DRkXtZ3Q.js +1 -0
- package/bundle/web-dist/web-dist/client/assets/vendor-react-DH4kUfK2.js +9 -0
- package/bundle/web-dist/web-dist/client/assets/vendor-tanstack-CUxlo6YN.js +1 -0
- package/bundle/web-dist/web-dist/client/index.html +18 -0
- package/bundle/web-dist/web-dist/server/assets/react-dom-CGIzOSuj.js +335 -0
- package/bundle/web-dist/web-dist/server/assets/routes-ClzReRep.js +490 -0
- package/bundle/web-dist/web-dist/server/assets/sd.generated-BnonqqKr.js +21694 -0
- package/bundle/web-dist/web-dist/server/assets/services.generated-D5ABD5fr.js +836 -0
- package/bundle/web-dist/web-dist/server/assets/show-C9pcdSxc.js +23364 -0
- package/bundle/web-dist/web-dist/server/assets/tokens-JH6FsnWZ.js +860 -0
- package/bundle/web-dist/web-dist/server/entry-server.generated.js +44646 -0
- package/package.json +11 -10
|
@@ -0,0 +1,1484 @@
|
|
|
1
|
+
import { y } from "../../../../../tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js";
|
|
2
|
+
import { stringify } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js";
|
|
3
|
+
import { assertTypes, getType, isObject, noop, ordinal } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js";
|
|
4
|
+
import { diff, printDiffOrStringify } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js";
|
|
5
|
+
import { processError } from "../../../../../@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js";
|
|
6
|
+
import { isMockFunction } from "../../../../../@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js";
|
|
7
|
+
import { use, utils_exports } from "../../../../../chai@6.2.2/node_modules/chai/index.js";
|
|
8
|
+
//#region ../../node_modules/.pnpm/@vitest+expect@4.1.2/node_modules/@vitest/expect/dist/index.js
|
|
9
|
+
const ChaiStyleAssertions = (chai, utils) => {
|
|
10
|
+
function defProperty(name, delegateTo) {
|
|
11
|
+
utils.addProperty(chai.Assertion.prototype, name, function() {
|
|
12
|
+
const jestMethod = chai.Assertion.prototype[delegateTo];
|
|
13
|
+
if (!jestMethod) throw new Error(`Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`);
|
|
14
|
+
return jestMethod.call(this);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function defPropertyWithArgs(name, delegateTo, ...args) {
|
|
18
|
+
utils.addProperty(chai.Assertion.prototype, name, function() {
|
|
19
|
+
const jestMethod = chai.Assertion.prototype[delegateTo];
|
|
20
|
+
if (!jestMethod) throw new Error(`Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`);
|
|
21
|
+
return jestMethod.call(this, ...args);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function defMethod(name, delegateTo) {
|
|
25
|
+
utils.addMethod(chai.Assertion.prototype, name, function(...args) {
|
|
26
|
+
const jestMethod = chai.Assertion.prototype[delegateTo];
|
|
27
|
+
if (!jestMethod) throw new Error(`Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`);
|
|
28
|
+
return jestMethod.call(this, ...args);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
defProperty("called", "toHaveBeenCalled");
|
|
32
|
+
defProperty("calledOnce", "toHaveBeenCalledOnce");
|
|
33
|
+
defPropertyWithArgs("calledTwice", "toHaveBeenCalledTimes", 2);
|
|
34
|
+
defPropertyWithArgs("calledThrice", "toHaveBeenCalledTimes", 3);
|
|
35
|
+
defMethod("callCount", "toHaveBeenCalledTimes");
|
|
36
|
+
defMethod("calledWith", "toHaveBeenCalledWith");
|
|
37
|
+
defMethod("calledOnceWith", "toHaveBeenCalledExactlyOnceWith");
|
|
38
|
+
defMethod("lastCalledWith", "toHaveBeenLastCalledWith");
|
|
39
|
+
defMethod("nthCalledWith", "toHaveBeenNthCalledWith");
|
|
40
|
+
defMethod("returned", "toHaveReturned");
|
|
41
|
+
defMethod("returnedWith", "toHaveReturnedWith");
|
|
42
|
+
defMethod("returnedTimes", "toHaveReturnedTimes");
|
|
43
|
+
defMethod("lastReturnedWith", "toHaveLastReturnedWith");
|
|
44
|
+
defMethod("nthReturnedWith", "toHaveNthReturnedWith");
|
|
45
|
+
defMethod("calledBefore", "toHaveBeenCalledBefore");
|
|
46
|
+
defMethod("calledAfter", "toHaveBeenCalledAfter");
|
|
47
|
+
};
|
|
48
|
+
const MATCHERS_OBJECT = Symbol.for("matchers-object");
|
|
49
|
+
const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object");
|
|
50
|
+
const GLOBAL_EXPECT = Symbol.for("expect-global");
|
|
51
|
+
const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for("asymmetric-matchers-object");
|
|
52
|
+
const customMatchers = {
|
|
53
|
+
toSatisfy(actual, expected, message) {
|
|
54
|
+
const { printReceived, printExpected, matcherHint } = this.utils;
|
|
55
|
+
const pass = expected(actual);
|
|
56
|
+
return {
|
|
57
|
+
pass,
|
|
58
|
+
message: () => pass ? `\
|
|
59
|
+
${matcherHint(".not.toSatisfy", "received", "")}
|
|
60
|
+
|
|
61
|
+
Expected value to not satisfy:
|
|
62
|
+
${message || printExpected(expected)}
|
|
63
|
+
Received:
|
|
64
|
+
${printReceived(actual)}` : `\
|
|
65
|
+
${matcherHint(".toSatisfy", "received", "")}
|
|
66
|
+
|
|
67
|
+
Expected value to satisfy:
|
|
68
|
+
${message || printExpected(expected)}
|
|
69
|
+
|
|
70
|
+
Received:
|
|
71
|
+
${printReceived(actual)}`
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
toBeOneOf(actual, expected) {
|
|
75
|
+
const { equals, customTesters } = this;
|
|
76
|
+
const { printReceived, printExpected, matcherHint } = this.utils;
|
|
77
|
+
let pass;
|
|
78
|
+
if (Array.isArray(expected)) pass = expected.length === 0 || expected.some((item) => equals(item, actual, customTesters));
|
|
79
|
+
else if (expected instanceof Set) pass = expected.size === 0 || expected.has(actual) || [...expected].some((item) => equals(item, actual, customTesters));
|
|
80
|
+
else throw new TypeError(`You must provide an array or set to ${matcherHint(".toBeOneOf")}, not '${typeof expected}'.`);
|
|
81
|
+
return {
|
|
82
|
+
pass,
|
|
83
|
+
message: () => pass ? `\
|
|
84
|
+
${matcherHint(".not.toBeOneOf", "received", "")}
|
|
85
|
+
|
|
86
|
+
Expected value to not be one of:
|
|
87
|
+
${printExpected(expected)}
|
|
88
|
+
Received:
|
|
89
|
+
${printReceived(actual)}` : `\
|
|
90
|
+
${matcherHint(".toBeOneOf", "received", "")}
|
|
91
|
+
|
|
92
|
+
Expected value to be one of:
|
|
93
|
+
${printExpected(expected)}
|
|
94
|
+
|
|
95
|
+
Received:
|
|
96
|
+
${printReceived(actual)}`
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const EXPECTED_COLOR = y.green;
|
|
101
|
+
const RECEIVED_COLOR = y.red;
|
|
102
|
+
const INVERTED_COLOR = y.inverse;
|
|
103
|
+
const BOLD_WEIGHT = y.bold;
|
|
104
|
+
const DIM_COLOR = y.dim;
|
|
105
|
+
function matcherHint(matcherName, received = "received", expected = "expected", options = {}) {
|
|
106
|
+
const { comment = "", isDirectExpectCall = false, isNot = false, promise = "", secondArgument = "", expectedColor = EXPECTED_COLOR, receivedColor = RECEIVED_COLOR, secondArgumentColor = EXPECTED_COLOR } = options;
|
|
107
|
+
let hint = "";
|
|
108
|
+
let dimString = "expect";
|
|
109
|
+
if (!isDirectExpectCall && received !== "") {
|
|
110
|
+
hint += DIM_COLOR(`${dimString}(`) + receivedColor(received);
|
|
111
|
+
dimString = ")";
|
|
112
|
+
}
|
|
113
|
+
if (promise !== "") {
|
|
114
|
+
hint += DIM_COLOR(`${dimString}.`) + promise;
|
|
115
|
+
dimString = "";
|
|
116
|
+
}
|
|
117
|
+
if (isNot) {
|
|
118
|
+
hint += `${DIM_COLOR(`${dimString}.`)}not`;
|
|
119
|
+
dimString = "";
|
|
120
|
+
}
|
|
121
|
+
if (matcherName.includes(".")) dimString += matcherName;
|
|
122
|
+
else {
|
|
123
|
+
hint += DIM_COLOR(`${dimString}.`) + matcherName;
|
|
124
|
+
dimString = "";
|
|
125
|
+
}
|
|
126
|
+
if (expected === "") dimString += "()";
|
|
127
|
+
else {
|
|
128
|
+
hint += DIM_COLOR(`${dimString}(`) + expectedColor(expected);
|
|
129
|
+
if (secondArgument) hint += DIM_COLOR(", ") + secondArgumentColor(secondArgument);
|
|
130
|
+
dimString = ")";
|
|
131
|
+
}
|
|
132
|
+
if (comment !== "") dimString += ` // ${comment}`;
|
|
133
|
+
if (dimString !== "") hint += DIM_COLOR(dimString);
|
|
134
|
+
return hint;
|
|
135
|
+
}
|
|
136
|
+
const SPACE_SYMBOL = "·";
|
|
137
|
+
function replaceTrailingSpaces(text) {
|
|
138
|
+
return text.replace(/\s+$/gm, (spaces) => SPACE_SYMBOL.repeat(spaces.length));
|
|
139
|
+
}
|
|
140
|
+
function printReceived(object) {
|
|
141
|
+
return RECEIVED_COLOR(replaceTrailingSpaces(stringify(object)));
|
|
142
|
+
}
|
|
143
|
+
function printExpected(value) {
|
|
144
|
+
return EXPECTED_COLOR(replaceTrailingSpaces(stringify(value)));
|
|
145
|
+
}
|
|
146
|
+
function getMatcherUtils() {
|
|
147
|
+
return {
|
|
148
|
+
EXPECTED_COLOR,
|
|
149
|
+
RECEIVED_COLOR,
|
|
150
|
+
INVERTED_COLOR,
|
|
151
|
+
BOLD_WEIGHT,
|
|
152
|
+
DIM_COLOR,
|
|
153
|
+
diff,
|
|
154
|
+
matcherHint,
|
|
155
|
+
printReceived,
|
|
156
|
+
printExpected,
|
|
157
|
+
printDiffOrStringify,
|
|
158
|
+
printWithType
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function printWithType(name, value, print) {
|
|
162
|
+
const type = getType(value);
|
|
163
|
+
return (type !== "null" && type !== "undefined" ? `${name} has type: ${type}\n` : "") + `${name} has value: ${print(value)}`;
|
|
164
|
+
}
|
|
165
|
+
function addCustomEqualityTesters(newTesters) {
|
|
166
|
+
if (!Array.isArray(newTesters)) throw new TypeError(`expect.customEqualityTesters: Must be set to an array of Testers. Was given "${getType(newTesters)}"`);
|
|
167
|
+
globalThis[JEST_MATCHERS_OBJECT].customEqualityTesters.push(...newTesters);
|
|
168
|
+
}
|
|
169
|
+
function getCustomEqualityTesters() {
|
|
170
|
+
return globalThis[JEST_MATCHERS_OBJECT].customEqualityTesters;
|
|
171
|
+
}
|
|
172
|
+
function equals(a, b, customTesters, strictCheck) {
|
|
173
|
+
customTesters = customTesters || [];
|
|
174
|
+
return eq(a, b, [], [], customTesters, strictCheck ? hasKey : hasDefinedKey);
|
|
175
|
+
}
|
|
176
|
+
Function.prototype.toString;
|
|
177
|
+
function isAsymmetric(obj) {
|
|
178
|
+
return !!obj && typeof obj === "object" && "asymmetricMatch" in obj && isA("Function", obj.asymmetricMatch);
|
|
179
|
+
}
|
|
180
|
+
function hasAsymmetric(obj, seen = /* @__PURE__ */ new Set()) {
|
|
181
|
+
if (seen.has(obj)) return false;
|
|
182
|
+
seen.add(obj);
|
|
183
|
+
if (isAsymmetric(obj)) return true;
|
|
184
|
+
if (Array.isArray(obj)) return obj.some((i) => hasAsymmetric(i, seen));
|
|
185
|
+
if (obj instanceof Set) return Array.from(obj).some((i) => hasAsymmetric(i, seen));
|
|
186
|
+
if (isObject(obj)) return Object.values(obj).some((v) => hasAsymmetric(v, seen));
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
function asymmetricMatch(a, b, customTesters) {
|
|
190
|
+
const asymmetricA = isAsymmetric(a);
|
|
191
|
+
const asymmetricB = isAsymmetric(b);
|
|
192
|
+
if (asymmetricA && asymmetricB) return;
|
|
193
|
+
if (asymmetricA) return a.asymmetricMatch(b, customTesters);
|
|
194
|
+
if (asymmetricB) return b.asymmetricMatch(a, customTesters);
|
|
195
|
+
}
|
|
196
|
+
function isError(value) {
|
|
197
|
+
if (typeof Error.isError === "function") return Error.isError(value);
|
|
198
|
+
switch (Object.prototype.toString.call(value)) {
|
|
199
|
+
case "[object Error]":
|
|
200
|
+
case "[object Exception]":
|
|
201
|
+
case "[object DOMException]": return true;
|
|
202
|
+
default: return value instanceof Error;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function eq(a, b, aStack, bStack, customTesters, hasKey) {
|
|
206
|
+
let result = true;
|
|
207
|
+
const asymmetricResult = asymmetricMatch(a, b, customTesters);
|
|
208
|
+
if (asymmetricResult !== void 0) return asymmetricResult;
|
|
209
|
+
const testerContext = { equals };
|
|
210
|
+
for (let i = 0; i < customTesters.length; i++) {
|
|
211
|
+
const customTesterResult = customTesters[i].call(testerContext, a, b, customTesters);
|
|
212
|
+
if (customTesterResult !== void 0) return customTesterResult;
|
|
213
|
+
}
|
|
214
|
+
if (typeof URL === "function" && a instanceof URL && b instanceof URL) return a.href === b.href;
|
|
215
|
+
if (Object.is(a, b)) return true;
|
|
216
|
+
if (a === null || b === null) return a === b;
|
|
217
|
+
const className = Object.prototype.toString.call(a);
|
|
218
|
+
if (className !== Object.prototype.toString.call(b)) return false;
|
|
219
|
+
switch (className) {
|
|
220
|
+
case "[object Boolean]":
|
|
221
|
+
case "[object String]":
|
|
222
|
+
case "[object Number]": if (typeof a !== typeof b) return false;
|
|
223
|
+
else if (typeof a !== "object" && typeof b !== "object") return Object.is(a, b);
|
|
224
|
+
else return Object.is(a.valueOf(), b.valueOf());
|
|
225
|
+
case "[object Date]": {
|
|
226
|
+
const numA = +a;
|
|
227
|
+
const numB = +b;
|
|
228
|
+
return numA === numB || Number.isNaN(numA) && Number.isNaN(numB);
|
|
229
|
+
}
|
|
230
|
+
case "[object RegExp]": return a.source === b.source && a.flags === b.flags;
|
|
231
|
+
case "[object Temporal.Instant]":
|
|
232
|
+
case "[object Temporal.ZonedDateTime]":
|
|
233
|
+
case "[object Temporal.PlainDateTime]":
|
|
234
|
+
case "[object Temporal.PlainDate]":
|
|
235
|
+
case "[object Temporal.PlainTime]":
|
|
236
|
+
case "[object Temporal.PlainYearMonth]":
|
|
237
|
+
case "[object Temporal.PlainMonthDay]": return a.equals(b);
|
|
238
|
+
case "[object Temporal.Duration]": return a.toString() === b.toString();
|
|
239
|
+
}
|
|
240
|
+
if (typeof a !== "object" || typeof b !== "object") return false;
|
|
241
|
+
if (isDomNode(a) && isDomNode(b)) return a.isEqualNode(b);
|
|
242
|
+
let length = aStack.length;
|
|
243
|
+
while (length--) if (aStack[length] === a) return bStack[length] === b;
|
|
244
|
+
else if (bStack[length] === b) return false;
|
|
245
|
+
aStack.push(a);
|
|
246
|
+
bStack.push(b);
|
|
247
|
+
if (className === "[object Array]" && a.length !== b.length) return false;
|
|
248
|
+
if (isError(a) && isError(b)) try {
|
|
249
|
+
return isErrorEqual(a, b, aStack, bStack, customTesters, hasKey);
|
|
250
|
+
} finally {
|
|
251
|
+
aStack.pop();
|
|
252
|
+
bStack.pop();
|
|
253
|
+
}
|
|
254
|
+
const aKeys = keys(a, hasKey);
|
|
255
|
+
let key;
|
|
256
|
+
let size = aKeys.length;
|
|
257
|
+
if (keys(b, hasKey).length !== size) return false;
|
|
258
|
+
while (size--) {
|
|
259
|
+
key = aKeys[size];
|
|
260
|
+
result = hasKey(b, key) && eq(a[key], b[key], aStack, bStack, customTesters, hasKey);
|
|
261
|
+
if (!result) return false;
|
|
262
|
+
}
|
|
263
|
+
aStack.pop();
|
|
264
|
+
bStack.pop();
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
function isErrorEqual(a, b, aStack, bStack, customTesters, hasKey) {
|
|
268
|
+
let result = Object.prototype.toString.call(a) === Object.prototype.toString.call(b) && a.name === b.name && a.message === b.message;
|
|
269
|
+
if (typeof b.cause !== "undefined") result &&= eq(a.cause, b.cause, aStack, bStack, customTesters, hasKey);
|
|
270
|
+
if (a instanceof AggregateError && b instanceof AggregateError) result &&= eq(a.errors, b.errors, aStack, bStack, customTesters, hasKey);
|
|
271
|
+
result &&= eq({ ...a }, { ...b }, aStack, bStack, customTesters, hasKey);
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
function keys(obj, hasKey) {
|
|
275
|
+
const keys = [];
|
|
276
|
+
for (const key in obj) if (hasKey(obj, key)) keys.push(key);
|
|
277
|
+
return keys.concat(Object.getOwnPropertySymbols(obj).filter((symbol) => Object.getOwnPropertyDescriptor(obj, symbol).enumerable));
|
|
278
|
+
}
|
|
279
|
+
function hasDefinedKey(obj, key) {
|
|
280
|
+
return hasKey(obj, key) && obj[key] !== void 0;
|
|
281
|
+
}
|
|
282
|
+
function hasKey(obj, key) {
|
|
283
|
+
return Object.hasOwn(obj, key);
|
|
284
|
+
}
|
|
285
|
+
function isA(typeName, value) {
|
|
286
|
+
return Object.prototype.toString.apply(value) === `[object ${typeName}]`;
|
|
287
|
+
}
|
|
288
|
+
function isDomNode(obj) {
|
|
289
|
+
return obj !== null && typeof obj === "object" && "nodeType" in obj && typeof obj.nodeType === "number" && "nodeName" in obj && typeof obj.nodeName === "string" && "isEqualNode" in obj && typeof obj.isEqualNode === "function";
|
|
290
|
+
}
|
|
291
|
+
function getPrototype(obj) {
|
|
292
|
+
if (Object.getPrototypeOf) return Object.getPrototypeOf(obj);
|
|
293
|
+
if (obj.constructor.prototype === obj) return null;
|
|
294
|
+
return obj.constructor.prototype;
|
|
295
|
+
}
|
|
296
|
+
function hasProperty(obj, property) {
|
|
297
|
+
if (!obj) return false;
|
|
298
|
+
if (Object.hasOwn(obj, property)) return true;
|
|
299
|
+
return hasProperty(getPrototype(obj), property);
|
|
300
|
+
}
|
|
301
|
+
const IS_KEYED_SENTINEL = "@@__IMMUTABLE_KEYED__@@";
|
|
302
|
+
const IS_SET_SENTINEL = "@@__IMMUTABLE_SET__@@";
|
|
303
|
+
const IS_LIST_SENTINEL = "@@__IMMUTABLE_LIST__@@";
|
|
304
|
+
const IS_ORDERED_SENTINEL = "@@__IMMUTABLE_ORDERED__@@";
|
|
305
|
+
const IS_RECORD_SYMBOL = "@@__IMMUTABLE_RECORD__@@";
|
|
306
|
+
function isImmutableUnorderedKeyed(maybeKeyed) {
|
|
307
|
+
return !!(maybeKeyed && maybeKeyed[IS_KEYED_SENTINEL] && !maybeKeyed[IS_ORDERED_SENTINEL]);
|
|
308
|
+
}
|
|
309
|
+
function isImmutableUnorderedSet(maybeSet) {
|
|
310
|
+
return !!(maybeSet && maybeSet[IS_SET_SENTINEL] && !maybeSet[IS_ORDERED_SENTINEL]);
|
|
311
|
+
}
|
|
312
|
+
function isObjectLiteral(source) {
|
|
313
|
+
return source != null && typeof source === "object" && !Array.isArray(source);
|
|
314
|
+
}
|
|
315
|
+
function isImmutableList(source) {
|
|
316
|
+
return Boolean(source && isObjectLiteral(source) && source[IS_LIST_SENTINEL]);
|
|
317
|
+
}
|
|
318
|
+
function isImmutableOrderedKeyed(source) {
|
|
319
|
+
return Boolean(source && isObjectLiteral(source) && source[IS_KEYED_SENTINEL] && source[IS_ORDERED_SENTINEL]);
|
|
320
|
+
}
|
|
321
|
+
function isImmutableOrderedSet(source) {
|
|
322
|
+
return Boolean(source && isObjectLiteral(source) && source[IS_SET_SENTINEL] && source[IS_ORDERED_SENTINEL]);
|
|
323
|
+
}
|
|
324
|
+
function isImmutableRecord(source) {
|
|
325
|
+
return Boolean(source && isObjectLiteral(source) && source[IS_RECORD_SYMBOL]);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
|
329
|
+
*
|
|
330
|
+
* This source code is licensed under the MIT license found in the
|
|
331
|
+
* LICENSE file in the root directory of this source tree.
|
|
332
|
+
*
|
|
333
|
+
*/
|
|
334
|
+
const IteratorSymbol = Symbol.iterator;
|
|
335
|
+
function hasIterator(object) {
|
|
336
|
+
return !!(object != null && object[IteratorSymbol]);
|
|
337
|
+
}
|
|
338
|
+
function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
339
|
+
if (typeof a !== "object" || typeof b !== "object" || Array.isArray(a) || Array.isArray(b) || !hasIterator(a) || !hasIterator(b)) return;
|
|
340
|
+
if (a.constructor !== b.constructor) return false;
|
|
341
|
+
let length = aStack.length;
|
|
342
|
+
while (length--) if (aStack[length] === a) return bStack[length] === b;
|
|
343
|
+
aStack.push(a);
|
|
344
|
+
bStack.push(b);
|
|
345
|
+
const filteredCustomTesters = [...customTesters.filter((t) => t !== iterableEquality), iterableEqualityWithStack];
|
|
346
|
+
function iterableEqualityWithStack(a, b) {
|
|
347
|
+
return iterableEquality(a, b, [...customTesters], [...aStack], [...bStack]);
|
|
348
|
+
}
|
|
349
|
+
if (a.size !== void 0) {
|
|
350
|
+
if (a.size !== b.size) return false;
|
|
351
|
+
else if (isA("Set", a) || isImmutableUnorderedSet(a)) {
|
|
352
|
+
let allFound = true;
|
|
353
|
+
for (const aValue of a) if (!b.has(aValue)) {
|
|
354
|
+
let has = false;
|
|
355
|
+
for (const bValue of b) if (equals(aValue, bValue, filteredCustomTesters) === true) has = true;
|
|
356
|
+
if (has === false) {
|
|
357
|
+
allFound = false;
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
aStack.pop();
|
|
362
|
+
bStack.pop();
|
|
363
|
+
return allFound;
|
|
364
|
+
} else if (isA("Map", a) || isImmutableUnorderedKeyed(a)) {
|
|
365
|
+
let allFound = true;
|
|
366
|
+
for (const aEntry of a) if (!b.has(aEntry[0]) || !equals(aEntry[1], b.get(aEntry[0]), filteredCustomTesters)) {
|
|
367
|
+
let has = false;
|
|
368
|
+
for (const bEntry of b) {
|
|
369
|
+
const matchedKey = equals(aEntry[0], bEntry[0], filteredCustomTesters);
|
|
370
|
+
let matchedValue = false;
|
|
371
|
+
if (matchedKey === true) matchedValue = equals(aEntry[1], bEntry[1], filteredCustomTesters);
|
|
372
|
+
if (matchedValue === true) has = true;
|
|
373
|
+
}
|
|
374
|
+
if (has === false) {
|
|
375
|
+
allFound = false;
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
aStack.pop();
|
|
380
|
+
bStack.pop();
|
|
381
|
+
return allFound;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const bIterator = b[IteratorSymbol]();
|
|
385
|
+
for (const aValue of a) {
|
|
386
|
+
const nextB = bIterator.next();
|
|
387
|
+
if (nextB.done || !equals(aValue, nextB.value, filteredCustomTesters)) return false;
|
|
388
|
+
}
|
|
389
|
+
if (!bIterator.next().done) return false;
|
|
390
|
+
if (!isImmutableList(a) && !isImmutableOrderedKeyed(a) && !isImmutableOrderedSet(a) && !isImmutableRecord(a)) {
|
|
391
|
+
if (!equals(Object.entries(a), Object.entries(b), filteredCustomTesters)) return false;
|
|
392
|
+
}
|
|
393
|
+
aStack.pop();
|
|
394
|
+
bStack.pop();
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Checks if `hasOwnProperty(object, key)` up the prototype chain, stopping at `Object.prototype`.
|
|
399
|
+
*/
|
|
400
|
+
function hasPropertyInObject(object, key) {
|
|
401
|
+
if (!object || typeof object !== "object" || object === Object.prototype) return false;
|
|
402
|
+
return Object.hasOwn(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
|
|
403
|
+
}
|
|
404
|
+
function isObjectWithKeys(a) {
|
|
405
|
+
return isObject(a) && !isError(a) && !Array.isArray(a) && !(a instanceof Date) && !(a instanceof Set) && !(a instanceof Map);
|
|
406
|
+
}
|
|
407
|
+
function subsetEquality(object, subset, customTesters = []) {
|
|
408
|
+
const filteredCustomTesters = customTesters.filter((t) => t !== subsetEquality);
|
|
409
|
+
const subsetEqualityWithContext = (seenReferences = /* @__PURE__ */ new WeakMap()) => (object, subset) => {
|
|
410
|
+
if (!isObjectWithKeys(subset)) return;
|
|
411
|
+
return Object.keys(subset).every((key) => {
|
|
412
|
+
if (subset[key] != null && typeof subset[key] === "object") {
|
|
413
|
+
if (seenReferences.has(subset[key])) return equals(object[key], subset[key], filteredCustomTesters);
|
|
414
|
+
seenReferences.set(subset[key], true);
|
|
415
|
+
}
|
|
416
|
+
const result = object != null && hasPropertyInObject(object, key) && equals(object[key], subset[key], [...filteredCustomTesters, subsetEqualityWithContext(seenReferences)]);
|
|
417
|
+
seenReferences.delete(subset[key]);
|
|
418
|
+
return result;
|
|
419
|
+
});
|
|
420
|
+
};
|
|
421
|
+
return subsetEqualityWithContext()(object, subset);
|
|
422
|
+
}
|
|
423
|
+
function typeEquality(a, b) {
|
|
424
|
+
if (a == null || b == null || a.constructor === b.constructor) return;
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
function arrayBufferEquality(a, b) {
|
|
428
|
+
let dataViewA = a;
|
|
429
|
+
let dataViewB = b;
|
|
430
|
+
if (!(a instanceof DataView && b instanceof DataView)) {
|
|
431
|
+
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) return;
|
|
432
|
+
try {
|
|
433
|
+
dataViewA = new DataView(a);
|
|
434
|
+
dataViewB = new DataView(b);
|
|
435
|
+
} catch {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (dataViewA.byteLength !== dataViewB.byteLength) return false;
|
|
440
|
+
for (let i = 0; i < dataViewA.byteLength; i++) if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) return false;
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
function sparseArrayEquality(a, b, customTesters = []) {
|
|
444
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return;
|
|
445
|
+
const aKeys = Object.keys(a);
|
|
446
|
+
const bKeys = Object.keys(b);
|
|
447
|
+
return equals(a, b, customTesters.filter((t) => t !== sparseArrayEquality), true) && equals(aKeys, bKeys);
|
|
448
|
+
}
|
|
449
|
+
function generateToBeMessage(deepEqualityName, expected = "#{this}", actual = "#{exp}") {
|
|
450
|
+
const toBeMessage = `expected ${expected} to be ${actual} // Object.is equality`;
|
|
451
|
+
if (["toStrictEqual", "toEqual"].includes(deepEqualityName)) return `${toBeMessage}\n\nIf it should pass with deep equality, replace "toBe" with "${deepEqualityName}"\n\nExpected: ${expected}\nReceived: serializes to the same string\n`;
|
|
452
|
+
return toBeMessage;
|
|
453
|
+
}
|
|
454
|
+
function pluralize(word, count) {
|
|
455
|
+
return `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
456
|
+
}
|
|
457
|
+
function getObjectKeys(object) {
|
|
458
|
+
return [...Object.keys(object), ...Object.getOwnPropertySymbols(object).filter((s) => Object.getOwnPropertyDescriptor(object, s)?.enumerable)];
|
|
459
|
+
}
|
|
460
|
+
function getObjectSubset(object, subset, customTesters) {
|
|
461
|
+
let stripped = 0;
|
|
462
|
+
const getObjectSubsetWithContext = (seenReferences = /* @__PURE__ */ new WeakMap()) => (object, subset) => {
|
|
463
|
+
if (Array.isArray(object)) {
|
|
464
|
+
if (Array.isArray(subset) && subset.length === object.length) return subset.map((sub, i) => getObjectSubsetWithContext(seenReferences)(object[i], sub));
|
|
465
|
+
} else if (object instanceof Date) return object;
|
|
466
|
+
else if (isObject(object) && isObject(subset)) {
|
|
467
|
+
if (equals(object, subset, [
|
|
468
|
+
...customTesters,
|
|
469
|
+
iterableEquality,
|
|
470
|
+
subsetEquality
|
|
471
|
+
])) return subset;
|
|
472
|
+
const trimmed = {};
|
|
473
|
+
seenReferences.set(object, trimmed);
|
|
474
|
+
if (typeof object.constructor === "function" && typeof object.constructor.name === "string") Object.defineProperty(trimmed, "constructor", {
|
|
475
|
+
enumerable: false,
|
|
476
|
+
value: object.constructor
|
|
477
|
+
});
|
|
478
|
+
for (const key of getObjectKeys(object)) if (hasPropertyInObject(subset, key)) trimmed[key] = seenReferences.has(object[key]) ? seenReferences.get(object[key]) : getObjectSubsetWithContext(seenReferences)(object[key], subset[key]);
|
|
479
|
+
else if (!seenReferences.has(object[key])) {
|
|
480
|
+
stripped += 1;
|
|
481
|
+
if (isObject(object[key])) stripped += getObjectKeys(object[key]).length;
|
|
482
|
+
getObjectSubsetWithContext(seenReferences)(object[key], subset[key]);
|
|
483
|
+
}
|
|
484
|
+
if (getObjectKeys(trimmed).length > 0) return trimmed;
|
|
485
|
+
}
|
|
486
|
+
return object;
|
|
487
|
+
};
|
|
488
|
+
return {
|
|
489
|
+
subset: getObjectSubsetWithContext()(object, subset),
|
|
490
|
+
stripped
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Detects if an object is a Standard Schema V1 compatible schema
|
|
495
|
+
*/
|
|
496
|
+
function isStandardSchema(obj) {
|
|
497
|
+
return !!obj && (typeof obj === "object" || typeof obj === "function") && obj["~standard"] && typeof obj["~standard"].validate === "function";
|
|
498
|
+
}
|
|
499
|
+
if (!Object.hasOwn(globalThis, MATCHERS_OBJECT)) {
|
|
500
|
+
const globalState = /* @__PURE__ */ new WeakMap();
|
|
501
|
+
const matchers = Object.create(null);
|
|
502
|
+
const customEqualityTesters = [];
|
|
503
|
+
const asymmetricMatchers = Object.create(null);
|
|
504
|
+
Object.defineProperty(globalThis, MATCHERS_OBJECT, { get: () => globalState });
|
|
505
|
+
Object.defineProperty(globalThis, JEST_MATCHERS_OBJECT, {
|
|
506
|
+
configurable: true,
|
|
507
|
+
get: () => ({
|
|
508
|
+
state: globalState.get(globalThis[GLOBAL_EXPECT]),
|
|
509
|
+
matchers,
|
|
510
|
+
customEqualityTesters
|
|
511
|
+
})
|
|
512
|
+
});
|
|
513
|
+
Object.defineProperty(globalThis, ASYMMETRIC_MATCHERS_OBJECT, { get: () => asymmetricMatchers });
|
|
514
|
+
}
|
|
515
|
+
function getState(expect) {
|
|
516
|
+
return globalThis[MATCHERS_OBJECT].get(expect);
|
|
517
|
+
}
|
|
518
|
+
function setState(state, expect) {
|
|
519
|
+
const map = globalThis[MATCHERS_OBJECT];
|
|
520
|
+
const current = map.get(expect) || {};
|
|
521
|
+
const results = Object.defineProperties(current, {
|
|
522
|
+
...Object.getOwnPropertyDescriptors(current),
|
|
523
|
+
...Object.getOwnPropertyDescriptors(state)
|
|
524
|
+
});
|
|
525
|
+
map.set(expect, results);
|
|
526
|
+
}
|
|
527
|
+
var AsymmetricMatcher = class {
|
|
528
|
+
$$typeof = Symbol.for("jest.asymmetricMatcher");
|
|
529
|
+
constructor(sample, inverse = false) {
|
|
530
|
+
this.sample = sample;
|
|
531
|
+
this.inverse = inverse;
|
|
532
|
+
}
|
|
533
|
+
getMatcherContext(expect) {
|
|
534
|
+
return {
|
|
535
|
+
...getState(expect || globalThis[GLOBAL_EXPECT]),
|
|
536
|
+
equals,
|
|
537
|
+
isNot: this.inverse,
|
|
538
|
+
customTesters: getCustomEqualityTesters(),
|
|
539
|
+
utils: {
|
|
540
|
+
...getMatcherUtils(),
|
|
541
|
+
diff,
|
|
542
|
+
stringify,
|
|
543
|
+
iterableEquality,
|
|
544
|
+
subsetEquality
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
AsymmetricMatcher.prototype[Symbol.for("chai/inspect")] = function(options) {
|
|
550
|
+
const result = stringify(this, options.depth, { min: true });
|
|
551
|
+
if (result.length <= options.truncate) return result;
|
|
552
|
+
return `${this.toString()}{…}`;
|
|
553
|
+
};
|
|
554
|
+
var StringContaining = class extends AsymmetricMatcher {
|
|
555
|
+
constructor(sample, inverse = false) {
|
|
556
|
+
if (!isA("String", sample)) throw new Error("Expected is not a string");
|
|
557
|
+
super(sample, inverse);
|
|
558
|
+
}
|
|
559
|
+
asymmetricMatch(other) {
|
|
560
|
+
const result = isA("String", other) && other.includes(this.sample);
|
|
561
|
+
return this.inverse ? !result : result;
|
|
562
|
+
}
|
|
563
|
+
toString() {
|
|
564
|
+
return `String${this.inverse ? "Not" : ""}Containing`;
|
|
565
|
+
}
|
|
566
|
+
getExpectedType() {
|
|
567
|
+
return "string";
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var Anything = class extends AsymmetricMatcher {
|
|
571
|
+
asymmetricMatch(other) {
|
|
572
|
+
return other != null;
|
|
573
|
+
}
|
|
574
|
+
toString() {
|
|
575
|
+
return "Anything";
|
|
576
|
+
}
|
|
577
|
+
toAsymmetricMatcher() {
|
|
578
|
+
return "Anything";
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
var ObjectContaining = class extends AsymmetricMatcher {
|
|
582
|
+
constructor(sample, inverse = false) {
|
|
583
|
+
super(sample, inverse);
|
|
584
|
+
}
|
|
585
|
+
getPrototype(obj) {
|
|
586
|
+
if (Object.getPrototypeOf) return Object.getPrototypeOf(obj);
|
|
587
|
+
if (obj.constructor.prototype === obj) return null;
|
|
588
|
+
return obj.constructor.prototype;
|
|
589
|
+
}
|
|
590
|
+
hasProperty(obj, property) {
|
|
591
|
+
if (!obj) return false;
|
|
592
|
+
if (Object.hasOwn(obj, property)) return true;
|
|
593
|
+
return this.hasProperty(this.getPrototype(obj), property);
|
|
594
|
+
}
|
|
595
|
+
getProperties(obj) {
|
|
596
|
+
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj).filter((s) => Object.getOwnPropertyDescriptor(obj, s)?.enumerable)];
|
|
597
|
+
}
|
|
598
|
+
asymmetricMatch(other, customTesters) {
|
|
599
|
+
if (typeof this.sample !== "object") throw new TypeError(`You must provide an object to ${this.toString()}, not '${typeof this.sample}'.`);
|
|
600
|
+
let result = true;
|
|
601
|
+
const properties = this.getProperties(this.sample);
|
|
602
|
+
for (const property of properties) {
|
|
603
|
+
if (!this.hasProperty(other, property)) {
|
|
604
|
+
result = false;
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
const value = this.sample[property];
|
|
608
|
+
const otherValue = other[property];
|
|
609
|
+
if (!equals(value, otherValue, customTesters)) {
|
|
610
|
+
result = false;
|
|
611
|
+
break;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return this.inverse ? !result : result;
|
|
615
|
+
}
|
|
616
|
+
toString() {
|
|
617
|
+
return `Object${this.inverse ? "Not" : ""}Containing`;
|
|
618
|
+
}
|
|
619
|
+
getExpectedType() {
|
|
620
|
+
return "object";
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
var ArrayContaining = class extends AsymmetricMatcher {
|
|
624
|
+
constructor(sample, inverse = false) {
|
|
625
|
+
super(sample, inverse);
|
|
626
|
+
}
|
|
627
|
+
asymmetricMatch(other, customTesters) {
|
|
628
|
+
if (!Array.isArray(this.sample)) throw new TypeError(`You must provide an array to ${this.toString()}, not '${typeof this.sample}'.`);
|
|
629
|
+
const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every((item) => other.some((another) => equals(item, another, customTesters)));
|
|
630
|
+
return this.inverse ? !result : result;
|
|
631
|
+
}
|
|
632
|
+
toString() {
|
|
633
|
+
return `Array${this.inverse ? "Not" : ""}Containing`;
|
|
634
|
+
}
|
|
635
|
+
getExpectedType() {
|
|
636
|
+
return "array";
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
var Any = class extends AsymmetricMatcher {
|
|
640
|
+
constructor(sample) {
|
|
641
|
+
if (typeof sample === "undefined") throw new TypeError("any() expects to be passed a constructor function. Please pass one or use anything() to match any object.");
|
|
642
|
+
super(sample);
|
|
643
|
+
}
|
|
644
|
+
fnNameFor(func) {
|
|
645
|
+
if (func.name) return func.name;
|
|
646
|
+
const matches = Function.prototype.toString.call(func).match(/^(?:async)?\s*function\s*(?:\*\s*)?([\w$]+)\s*\(/);
|
|
647
|
+
return matches ? matches[1] : "<anonymous>";
|
|
648
|
+
}
|
|
649
|
+
asymmetricMatch(other) {
|
|
650
|
+
if (this.sample === String) return typeof other == "string" || other instanceof String;
|
|
651
|
+
if (this.sample === Number) return typeof other == "number" || other instanceof Number;
|
|
652
|
+
if (this.sample === Function) return typeof other == "function" || typeof other === "function";
|
|
653
|
+
if (this.sample === Boolean) return typeof other == "boolean" || other instanceof Boolean;
|
|
654
|
+
if (this.sample === BigInt) return typeof other == "bigint" || other instanceof BigInt;
|
|
655
|
+
if (this.sample === Symbol) return typeof other == "symbol" || other instanceof Symbol;
|
|
656
|
+
if (this.sample === Object) return typeof other == "object";
|
|
657
|
+
return other instanceof this.sample;
|
|
658
|
+
}
|
|
659
|
+
toString() {
|
|
660
|
+
return "Any";
|
|
661
|
+
}
|
|
662
|
+
getExpectedType() {
|
|
663
|
+
if (this.sample === String) return "string";
|
|
664
|
+
if (this.sample === Number) return "number";
|
|
665
|
+
if (this.sample === Function) return "function";
|
|
666
|
+
if (this.sample === Object) return "object";
|
|
667
|
+
if (this.sample === Boolean) return "boolean";
|
|
668
|
+
return this.fnNameFor(this.sample);
|
|
669
|
+
}
|
|
670
|
+
toAsymmetricMatcher() {
|
|
671
|
+
return `Any<${this.fnNameFor(this.sample)}>`;
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
var StringMatching = class extends AsymmetricMatcher {
|
|
675
|
+
constructor(sample, inverse = false) {
|
|
676
|
+
if (!isA("String", sample) && !isA("RegExp", sample)) throw new Error("Expected is not a String or a RegExp");
|
|
677
|
+
super(new RegExp(sample), inverse);
|
|
678
|
+
}
|
|
679
|
+
asymmetricMatch(other) {
|
|
680
|
+
const result = isA("String", other) && this.sample.test(other);
|
|
681
|
+
return this.inverse ? !result : result;
|
|
682
|
+
}
|
|
683
|
+
toString() {
|
|
684
|
+
return `String${this.inverse ? "Not" : ""}Matching`;
|
|
685
|
+
}
|
|
686
|
+
getExpectedType() {
|
|
687
|
+
return "string";
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
var CloseTo = class extends AsymmetricMatcher {
|
|
691
|
+
precision;
|
|
692
|
+
constructor(sample, precision = 2, inverse = false) {
|
|
693
|
+
if (!isA("Number", sample)) throw new Error("Expected is not a Number");
|
|
694
|
+
if (!isA("Number", precision)) throw new Error("Precision is not a Number");
|
|
695
|
+
super(sample);
|
|
696
|
+
this.inverse = inverse;
|
|
697
|
+
this.precision = precision;
|
|
698
|
+
}
|
|
699
|
+
asymmetricMatch(other) {
|
|
700
|
+
if (!isA("Number", other)) return false;
|
|
701
|
+
let result = false;
|
|
702
|
+
if (other === Number.POSITIVE_INFINITY && this.sample === Number.POSITIVE_INFINITY) result = true;
|
|
703
|
+
else if (other === Number.NEGATIVE_INFINITY && this.sample === Number.NEGATIVE_INFINITY) result = true;
|
|
704
|
+
else result = Math.abs(this.sample - other) < 10 ** -this.precision / 2;
|
|
705
|
+
return this.inverse ? !result : result;
|
|
706
|
+
}
|
|
707
|
+
toString() {
|
|
708
|
+
return `Number${this.inverse ? "Not" : ""}CloseTo`;
|
|
709
|
+
}
|
|
710
|
+
getExpectedType() {
|
|
711
|
+
return "number";
|
|
712
|
+
}
|
|
713
|
+
toAsymmetricMatcher() {
|
|
714
|
+
return [
|
|
715
|
+
this.toString(),
|
|
716
|
+
this.sample,
|
|
717
|
+
`(${pluralize("digit", this.precision)})`
|
|
718
|
+
].join(" ");
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
var SchemaMatching = class extends AsymmetricMatcher {
|
|
722
|
+
result;
|
|
723
|
+
constructor(sample, inverse = false) {
|
|
724
|
+
if (!isStandardSchema(sample)) throw new TypeError("SchemaMatching expected to receive a Standard Schema.");
|
|
725
|
+
super(sample, inverse);
|
|
726
|
+
}
|
|
727
|
+
asymmetricMatch(other) {
|
|
728
|
+
const result = this.sample["~standard"].validate(other);
|
|
729
|
+
if (result instanceof Promise) throw new TypeError("Async schema validation is not supported in asymmetric matchers.");
|
|
730
|
+
this.result = result;
|
|
731
|
+
const pass = !this.result.issues || this.result.issues.length === 0;
|
|
732
|
+
return this.inverse ? !pass : pass;
|
|
733
|
+
}
|
|
734
|
+
toString() {
|
|
735
|
+
return `Schema${this.inverse ? "Not" : ""}Matching`;
|
|
736
|
+
}
|
|
737
|
+
getExpectedType() {
|
|
738
|
+
return "object";
|
|
739
|
+
}
|
|
740
|
+
toAsymmetricMatcher() {
|
|
741
|
+
const { utils } = this.getMatcherContext();
|
|
742
|
+
if ((this.result?.issues || []).length > 0) return `${this.toString()} ${utils.stringify(this.result, void 0, { printBasicPrototype: false })}`;
|
|
743
|
+
return this.toString();
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
const JestAsymmetricMatchers = (chai, utils) => {
|
|
747
|
+
utils.addMethod(chai.expect, "anything", () => new Anything());
|
|
748
|
+
utils.addMethod(chai.expect, "any", (expected) => new Any(expected));
|
|
749
|
+
utils.addMethod(chai.expect, "stringContaining", (expected) => new StringContaining(expected));
|
|
750
|
+
utils.addMethod(chai.expect, "objectContaining", (expected) => new ObjectContaining(expected));
|
|
751
|
+
utils.addMethod(chai.expect, "arrayContaining", (expected) => new ArrayContaining(expected));
|
|
752
|
+
utils.addMethod(chai.expect, "stringMatching", (expected) => new StringMatching(expected));
|
|
753
|
+
utils.addMethod(chai.expect, "closeTo", (expected, precision) => new CloseTo(expected, precision));
|
|
754
|
+
utils.addMethod(chai.expect, "schemaMatching", (expected) => new SchemaMatching(expected));
|
|
755
|
+
chai.expect.not = {
|
|
756
|
+
stringContaining: (expected) => new StringContaining(expected, true),
|
|
757
|
+
objectContaining: (expected) => new ObjectContaining(expected, true),
|
|
758
|
+
arrayContaining: (expected) => new ArrayContaining(expected, true),
|
|
759
|
+
stringMatching: (expected) => new StringMatching(expected, true),
|
|
760
|
+
closeTo: (expected, precision) => new CloseTo(expected, precision, true),
|
|
761
|
+
schemaMatching: (expected) => new SchemaMatching(expected, true)
|
|
762
|
+
};
|
|
763
|
+
};
|
|
764
|
+
function createAssertionMessage(util, assertion, hasArgs) {
|
|
765
|
+
const soft = util.flag(assertion, "soft") ? ".soft" : "";
|
|
766
|
+
const not = util.flag(assertion, "negate") ? "not." : "";
|
|
767
|
+
const name = `${util.flag(assertion, "_name")}(${hasArgs ? "expected" : ""})`;
|
|
768
|
+
const promiseName = util.flag(assertion, "promise");
|
|
769
|
+
return `expect${soft}(actual)${promiseName ? `.${promiseName}` : ""}.${not}${name}`;
|
|
770
|
+
}
|
|
771
|
+
function recordAsyncExpect(_test, promise, assertion, error, isSoft) {
|
|
772
|
+
const test = _test;
|
|
773
|
+
if (test && promise instanceof Promise) {
|
|
774
|
+
promise = promise.finally(() => {
|
|
775
|
+
if (!test.promises) return;
|
|
776
|
+
const index = test.promises.indexOf(promise);
|
|
777
|
+
if (index !== -1) test.promises.splice(index, 1);
|
|
778
|
+
});
|
|
779
|
+
if (!test.promises) test.promises = [];
|
|
780
|
+
if (isSoft) promise = promise.then(noop, (err) => {
|
|
781
|
+
handleTestError(test, err);
|
|
782
|
+
});
|
|
783
|
+
test.promises.push(promise);
|
|
784
|
+
let resolved = false;
|
|
785
|
+
test.onFinished ??= [];
|
|
786
|
+
test.onFinished.push(() => {
|
|
787
|
+
if (!resolved) {
|
|
788
|
+
const stack = (globalThis.__vitest_worker__?.onFilterStackTrace || ((s) => s || ""))(error.stack);
|
|
789
|
+
console.warn([
|
|
790
|
+
`Promise returned by \`${assertion}\` was not awaited. `,
|
|
791
|
+
"Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. ",
|
|
792
|
+
"Please remember to await the assertion.\n",
|
|
793
|
+
stack
|
|
794
|
+
].join(""));
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
return {
|
|
798
|
+
then(onFulfilled, onRejected) {
|
|
799
|
+
resolved = true;
|
|
800
|
+
return promise.then(onFulfilled, onRejected);
|
|
801
|
+
},
|
|
802
|
+
catch(onRejected) {
|
|
803
|
+
resolved = true;
|
|
804
|
+
return promise.catch(onRejected);
|
|
805
|
+
},
|
|
806
|
+
finally(onFinally) {
|
|
807
|
+
resolved = true;
|
|
808
|
+
return promise.finally(onFinally);
|
|
809
|
+
},
|
|
810
|
+
[Symbol.toStringTag]: "Promise"
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
return promise;
|
|
814
|
+
}
|
|
815
|
+
function handleTestError(test, err) {
|
|
816
|
+
test.result ||= { state: "fail" };
|
|
817
|
+
test.result.state = "fail";
|
|
818
|
+
test.result.errors ||= [];
|
|
819
|
+
test.result.errors.push(processError(err));
|
|
820
|
+
}
|
|
821
|
+
function wrapAssertion(utils, name, fn) {
|
|
822
|
+
return function(...args) {
|
|
823
|
+
if (name !== "withTest") utils.flag(this, "_name", name);
|
|
824
|
+
if (!utils.flag(this, "soft")) try {
|
|
825
|
+
return fn.apply(this, args);
|
|
826
|
+
} finally {}
|
|
827
|
+
const test = utils.flag(this, "vitest-test");
|
|
828
|
+
if (!test) throw new Error("expect.soft() can only be used inside a test");
|
|
829
|
+
try {
|
|
830
|
+
const result = fn.apply(this, args);
|
|
831
|
+
if (result && typeof result === "object" && typeof result.then === "function") return result.then(noop, (err) => {
|
|
832
|
+
handleTestError(test, err);
|
|
833
|
+
});
|
|
834
|
+
return result;
|
|
835
|
+
} catch (err) {
|
|
836
|
+
handleTestError(test, err);
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
const JestChaiExpect = (chai, utils) => {
|
|
841
|
+
const { AssertionError } = chai;
|
|
842
|
+
const customTesters = getCustomEqualityTesters();
|
|
843
|
+
function def(name, fn) {
|
|
844
|
+
const addMethod = (n) => {
|
|
845
|
+
const softWrapper = wrapAssertion(utils, n, fn);
|
|
846
|
+
utils.addMethod(chai.Assertion.prototype, n, softWrapper);
|
|
847
|
+
utils.addMethod(globalThis[JEST_MATCHERS_OBJECT].matchers, n, softWrapper);
|
|
848
|
+
};
|
|
849
|
+
if (Array.isArray(name)) name.forEach((n) => addMethod(n));
|
|
850
|
+
else addMethod(name);
|
|
851
|
+
}
|
|
852
|
+
[
|
|
853
|
+
"throw",
|
|
854
|
+
"throws",
|
|
855
|
+
"Throw"
|
|
856
|
+
].forEach((m) => {
|
|
857
|
+
utils.overwriteMethod(chai.Assertion.prototype, m, (_super) => {
|
|
858
|
+
return function(...args) {
|
|
859
|
+
const promise = utils.flag(this, "promise");
|
|
860
|
+
const object = utils.flag(this, "object");
|
|
861
|
+
const isNot = utils.flag(this, "negate");
|
|
862
|
+
if (promise === "rejects") utils.flag(this, "object", () => {
|
|
863
|
+
throw object;
|
|
864
|
+
});
|
|
865
|
+
else if (promise === "resolves" && typeof object !== "function") if (!isNot) throw new AssertionError(utils.flag(this, "message") || "expected promise to throw an error, but it didn't", { showDiff: false }, utils.flag(this, "ssfi"));
|
|
866
|
+
else return;
|
|
867
|
+
_super.apply(this, args);
|
|
868
|
+
};
|
|
869
|
+
});
|
|
870
|
+
});
|
|
871
|
+
def("withTest", function(test) {
|
|
872
|
+
utils.flag(this, "vitest-test", test);
|
|
873
|
+
return this;
|
|
874
|
+
});
|
|
875
|
+
def("toEqual", function(expected) {
|
|
876
|
+
const actual = utils.flag(this, "object");
|
|
877
|
+
const equal = equals(actual, expected, [...customTesters, iterableEquality]);
|
|
878
|
+
return this.assert(equal, "expected #{this} to deeply equal #{exp}", "expected #{this} to not deeply equal #{exp}", expected, actual);
|
|
879
|
+
});
|
|
880
|
+
def("toStrictEqual", function(expected) {
|
|
881
|
+
const obj = utils.flag(this, "object");
|
|
882
|
+
const equal = equals(obj, expected, [
|
|
883
|
+
...customTesters,
|
|
884
|
+
iterableEquality,
|
|
885
|
+
typeEquality,
|
|
886
|
+
sparseArrayEquality,
|
|
887
|
+
arrayBufferEquality
|
|
888
|
+
], true);
|
|
889
|
+
return this.assert(equal, "expected #{this} to strictly equal #{exp}", "expected #{this} to not strictly equal #{exp}", expected, obj);
|
|
890
|
+
});
|
|
891
|
+
def("toBe", function(expected) {
|
|
892
|
+
const actual = this._obj;
|
|
893
|
+
const pass = Object.is(actual, expected);
|
|
894
|
+
let deepEqualityName = "";
|
|
895
|
+
if (!pass) {
|
|
896
|
+
if (equals(actual, expected, [
|
|
897
|
+
...customTesters,
|
|
898
|
+
iterableEquality,
|
|
899
|
+
typeEquality,
|
|
900
|
+
sparseArrayEquality,
|
|
901
|
+
arrayBufferEquality
|
|
902
|
+
], true)) deepEqualityName = "toStrictEqual";
|
|
903
|
+
else if (equals(actual, expected, [...customTesters, iterableEquality])) deepEqualityName = "toEqual";
|
|
904
|
+
}
|
|
905
|
+
return this.assert(pass, generateToBeMessage(deepEqualityName), "expected #{this} not to be #{exp} // Object.is equality", expected, actual);
|
|
906
|
+
});
|
|
907
|
+
def("toMatchObject", function(expected) {
|
|
908
|
+
const actual = this._obj;
|
|
909
|
+
const pass = equals(actual, expected, [
|
|
910
|
+
...customTesters,
|
|
911
|
+
iterableEquality,
|
|
912
|
+
subsetEquality
|
|
913
|
+
]);
|
|
914
|
+
const isNot = utils.flag(this, "negate");
|
|
915
|
+
const { subset: actualSubset, stripped } = getObjectSubset(actual, expected, customTesters);
|
|
916
|
+
if (pass && isNot || !pass && !isNot) {
|
|
917
|
+
const msg = utils.getMessage(this, [
|
|
918
|
+
pass,
|
|
919
|
+
"expected #{this} to match object #{exp}",
|
|
920
|
+
"expected #{this} to not match object #{exp}",
|
|
921
|
+
expected,
|
|
922
|
+
actualSubset,
|
|
923
|
+
false
|
|
924
|
+
]);
|
|
925
|
+
throw new AssertionError(stripped === 0 ? msg : `${msg}\n(${stripped} matching ${stripped === 1 ? "property" : "properties"} omitted from actual)`, {
|
|
926
|
+
showDiff: true,
|
|
927
|
+
expected,
|
|
928
|
+
actual: actualSubset
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
def("toMatch", function(expected) {
|
|
933
|
+
const actual = this._obj;
|
|
934
|
+
if (typeof actual !== "string") throw new TypeError(`.toMatch() expects to receive a string, but got ${typeof actual}`);
|
|
935
|
+
return this.assert(typeof expected === "string" ? actual.includes(expected) : actual.match(expected), `expected #{this} to match #{exp}`, `expected #{this} not to match #{exp}`, expected, actual);
|
|
936
|
+
});
|
|
937
|
+
def("toContain", function(item) {
|
|
938
|
+
const actual = this._obj;
|
|
939
|
+
if (typeof Node !== "undefined" && actual instanceof Node) {
|
|
940
|
+
if (!(item instanceof Node)) throw new TypeError(`toContain() expected a DOM node as the argument, but got ${typeof item}`);
|
|
941
|
+
return this.assert(actual.contains(item), "expected #{this} to contain element #{exp}", "expected #{this} not to contain element #{exp}", item, actual);
|
|
942
|
+
}
|
|
943
|
+
if (typeof DOMTokenList !== "undefined" && actual instanceof DOMTokenList) {
|
|
944
|
+
assertTypes(item, "class name", ["string"]);
|
|
945
|
+
const expectedClassList = utils.flag(this, "negate") ? actual.value.replace(item, "").trim() : `${actual.value} ${item}`;
|
|
946
|
+
return this.assert(actual.contains(item), `expected "${actual.value}" to contain "${item}"`, `expected "${actual.value}" not to contain "${item}"`, expectedClassList, actual.value);
|
|
947
|
+
}
|
|
948
|
+
if (typeof actual === "string" && typeof item === "string") return this.assert(actual.includes(item), `expected #{this} to contain #{exp}`, `expected #{this} not to contain #{exp}`, item, actual);
|
|
949
|
+
if (actual != null && typeof actual !== "string") utils.flag(this, "object", Array.from(actual));
|
|
950
|
+
return this.contain(item);
|
|
951
|
+
});
|
|
952
|
+
def("toContainEqual", function(expected) {
|
|
953
|
+
const obj = utils.flag(this, "object");
|
|
954
|
+
const index = Array.from(obj).findIndex((item) => {
|
|
955
|
+
return equals(item, expected, customTesters);
|
|
956
|
+
});
|
|
957
|
+
this.assert(index !== -1, "expected #{this} to deep equally contain #{exp}", "expected #{this} to not deep equally contain #{exp}", expected);
|
|
958
|
+
});
|
|
959
|
+
def("toBeTruthy", function() {
|
|
960
|
+
const obj = utils.flag(this, "object");
|
|
961
|
+
this.assert(Boolean(obj), "expected #{this} to be truthy", "expected #{this} to not be truthy", true, obj);
|
|
962
|
+
});
|
|
963
|
+
def("toBeFalsy", function() {
|
|
964
|
+
const obj = utils.flag(this, "object");
|
|
965
|
+
this.assert(!obj, "expected #{this} to be falsy", "expected #{this} to not be falsy", false, obj);
|
|
966
|
+
});
|
|
967
|
+
def("toBeGreaterThan", function(expected) {
|
|
968
|
+
const actual = this._obj;
|
|
969
|
+
assertTypes(actual, "actual", ["number", "bigint"]);
|
|
970
|
+
assertTypes(expected, "expected", ["number", "bigint"]);
|
|
971
|
+
return this.assert(actual > expected, `expected ${actual} to be greater than ${expected}`, `expected ${actual} to be not greater than ${expected}`, expected, actual, false);
|
|
972
|
+
});
|
|
973
|
+
def("toBeGreaterThanOrEqual", function(expected) {
|
|
974
|
+
const actual = this._obj;
|
|
975
|
+
assertTypes(actual, "actual", ["number", "bigint"]);
|
|
976
|
+
assertTypes(expected, "expected", ["number", "bigint"]);
|
|
977
|
+
return this.assert(actual >= expected, `expected ${actual} to be greater than or equal to ${expected}`, `expected ${actual} to be not greater than or equal to ${expected}`, expected, actual, false);
|
|
978
|
+
});
|
|
979
|
+
def("toBeLessThan", function(expected) {
|
|
980
|
+
const actual = this._obj;
|
|
981
|
+
assertTypes(actual, "actual", ["number", "bigint"]);
|
|
982
|
+
assertTypes(expected, "expected", ["number", "bigint"]);
|
|
983
|
+
return this.assert(actual < expected, `expected ${actual} to be less than ${expected}`, `expected ${actual} to be not less than ${expected}`, expected, actual, false);
|
|
984
|
+
});
|
|
985
|
+
def("toBeLessThanOrEqual", function(expected) {
|
|
986
|
+
const actual = this._obj;
|
|
987
|
+
assertTypes(actual, "actual", ["number", "bigint"]);
|
|
988
|
+
assertTypes(expected, "expected", ["number", "bigint"]);
|
|
989
|
+
return this.assert(actual <= expected, `expected ${actual} to be less than or equal to ${expected}`, `expected ${actual} to be not less than or equal to ${expected}`, expected, actual, false);
|
|
990
|
+
});
|
|
991
|
+
def("toBeNaN", function() {
|
|
992
|
+
const obj = utils.flag(this, "object");
|
|
993
|
+
this.assert(Number.isNaN(obj), "expected #{this} to be NaN", "expected #{this} not to be NaN", NaN, obj);
|
|
994
|
+
});
|
|
995
|
+
def("toBeUndefined", function() {
|
|
996
|
+
const obj = utils.flag(this, "object");
|
|
997
|
+
this.assert(void 0 === obj, "expected #{this} to be undefined", "expected #{this} not to be undefined", void 0, obj);
|
|
998
|
+
});
|
|
999
|
+
def("toBeNull", function() {
|
|
1000
|
+
const obj = utils.flag(this, "object");
|
|
1001
|
+
this.assert(obj === null, "expected #{this} to be null", "expected #{this} not to be null", null, obj);
|
|
1002
|
+
});
|
|
1003
|
+
def("toBeNullable", function() {
|
|
1004
|
+
const obj = utils.flag(this, "object");
|
|
1005
|
+
this.assert(obj == null, "expected #{this} to be nullish", "expected #{this} not to be nullish", null, obj);
|
|
1006
|
+
});
|
|
1007
|
+
def("toBeDefined", function() {
|
|
1008
|
+
const obj = utils.flag(this, "object");
|
|
1009
|
+
this.assert(typeof obj !== "undefined", "expected #{this} to be defined", "expected #{this} to be undefined", obj);
|
|
1010
|
+
});
|
|
1011
|
+
def("toBeTypeOf", function(expected) {
|
|
1012
|
+
const actual = typeof this._obj;
|
|
1013
|
+
const equal = expected === actual;
|
|
1014
|
+
return this.assert(equal, "expected #{this} to be type of #{exp}", "expected #{this} not to be type of #{exp}", expected, actual);
|
|
1015
|
+
});
|
|
1016
|
+
def("toBeInstanceOf", function(obj) {
|
|
1017
|
+
return this.instanceOf(obj);
|
|
1018
|
+
});
|
|
1019
|
+
def("toHaveLength", function(length) {
|
|
1020
|
+
return this.have.length(length);
|
|
1021
|
+
});
|
|
1022
|
+
def("toHaveProperty", function(...args) {
|
|
1023
|
+
if (Array.isArray(args[0])) args[0] = args[0].map((key) => String(key).replace(/([.[\]])/g, "\\$1")).join(".");
|
|
1024
|
+
const actual = this._obj;
|
|
1025
|
+
const [propertyName, expected] = args;
|
|
1026
|
+
const getValue = () => {
|
|
1027
|
+
if (Object.hasOwn(actual, propertyName)) return {
|
|
1028
|
+
value: actual[propertyName],
|
|
1029
|
+
exists: true
|
|
1030
|
+
};
|
|
1031
|
+
return utils.getPathInfo(actual, propertyName);
|
|
1032
|
+
};
|
|
1033
|
+
const { value, exists } = getValue();
|
|
1034
|
+
const pass = exists && (args.length === 1 || equals(expected, value, customTesters));
|
|
1035
|
+
const valueString = args.length === 1 ? "" : ` with value ${utils.objDisplay(expected)}`;
|
|
1036
|
+
return this.assert(pass, `expected #{this} to have property "${propertyName}"${valueString}`, `expected #{this} to not have property "${propertyName}"${valueString}`, expected, exists ? value : void 0);
|
|
1037
|
+
});
|
|
1038
|
+
def("toBeCloseTo", function(received, precision = 2) {
|
|
1039
|
+
const expected = this._obj;
|
|
1040
|
+
let pass = false;
|
|
1041
|
+
let expectedDiff = 0;
|
|
1042
|
+
let receivedDiff = 0;
|
|
1043
|
+
if (received === Number.POSITIVE_INFINITY && expected === Number.POSITIVE_INFINITY) pass = true;
|
|
1044
|
+
else if (received === Number.NEGATIVE_INFINITY && expected === Number.NEGATIVE_INFINITY) pass = true;
|
|
1045
|
+
else {
|
|
1046
|
+
expectedDiff = 10 ** -precision / 2;
|
|
1047
|
+
receivedDiff = Math.abs(expected - received);
|
|
1048
|
+
pass = receivedDiff < expectedDiff;
|
|
1049
|
+
}
|
|
1050
|
+
return this.assert(pass, `expected #{this} to be close to #{exp}, received difference is ${receivedDiff}, but expected ${expectedDiff}`, `expected #{this} to not be close to #{exp}, received difference is ${receivedDiff}, but expected ${expectedDiff}`, received, expected, false);
|
|
1051
|
+
});
|
|
1052
|
+
function assertIsMock(assertion) {
|
|
1053
|
+
if (!isMockFunction(assertion._obj)) throw new TypeError(`${utils.inspect(assertion._obj)} is not a spy or a call to a spy!`);
|
|
1054
|
+
}
|
|
1055
|
+
function getSpy(assertion) {
|
|
1056
|
+
assertIsMock(assertion);
|
|
1057
|
+
return assertion._obj;
|
|
1058
|
+
}
|
|
1059
|
+
def(["toHaveBeenCalledTimes", "toBeCalledTimes"], function(number) {
|
|
1060
|
+
const spy = getSpy(this);
|
|
1061
|
+
const spyName = spy.getMockName();
|
|
1062
|
+
const callCount = spy.mock.calls.length;
|
|
1063
|
+
return this.assert(callCount === number, `expected "${spyName}" to be called #{exp} times, but got ${callCount} times`, `expected "${spyName}" to not be called #{exp} times`, number, callCount, false);
|
|
1064
|
+
});
|
|
1065
|
+
def("toHaveBeenCalledOnce", function() {
|
|
1066
|
+
const spy = getSpy(this);
|
|
1067
|
+
const spyName = spy.getMockName();
|
|
1068
|
+
const callCount = spy.mock.calls.length;
|
|
1069
|
+
return this.assert(callCount === 1, `expected "${spyName}" to be called once, but got ${callCount} times`, `expected "${spyName}" to not be called once`, 1, callCount, false);
|
|
1070
|
+
});
|
|
1071
|
+
def(["toHaveBeenCalled", "toBeCalled"], function() {
|
|
1072
|
+
const spy = getSpy(this);
|
|
1073
|
+
const spyName = spy.getMockName();
|
|
1074
|
+
const callCount = spy.mock.calls.length;
|
|
1075
|
+
const called = callCount > 0;
|
|
1076
|
+
const isNot = utils.flag(this, "negate");
|
|
1077
|
+
let msg = utils.getMessage(this, [
|
|
1078
|
+
called,
|
|
1079
|
+
`expected "${spyName}" to be called at least once`,
|
|
1080
|
+
`expected "${spyName}" to not be called at all, but actually been called ${callCount} times`,
|
|
1081
|
+
true,
|
|
1082
|
+
called
|
|
1083
|
+
]);
|
|
1084
|
+
if (called && isNot) msg = formatCalls(spy, msg);
|
|
1085
|
+
if (called && isNot || !called && !isNot) throw new AssertionError(msg);
|
|
1086
|
+
});
|
|
1087
|
+
function equalsArgumentArray(a, b) {
|
|
1088
|
+
return a.length === b.length && a.every((aItem, i) => equals(aItem, b[i], [...customTesters, iterableEquality]));
|
|
1089
|
+
}
|
|
1090
|
+
def(["toHaveBeenCalledWith", "toBeCalledWith"], function(...args) {
|
|
1091
|
+
const spy = getSpy(this);
|
|
1092
|
+
const spyName = spy.getMockName();
|
|
1093
|
+
const pass = spy.mock.calls.some((callArg) => equalsArgumentArray(callArg, args));
|
|
1094
|
+
const isNot = utils.flag(this, "negate");
|
|
1095
|
+
const msg = utils.getMessage(this, [
|
|
1096
|
+
pass,
|
|
1097
|
+
`expected "${spyName}" to be called with arguments: #{exp}`,
|
|
1098
|
+
`expected "${spyName}" to not be called with arguments: #{exp}`,
|
|
1099
|
+
args
|
|
1100
|
+
]);
|
|
1101
|
+
if (pass && isNot || !pass && !isNot) throw new AssertionError(formatCalls(spy, msg, args));
|
|
1102
|
+
});
|
|
1103
|
+
def("toHaveBeenCalledExactlyOnceWith", function(...args) {
|
|
1104
|
+
const spy = getSpy(this);
|
|
1105
|
+
const spyName = spy.getMockName();
|
|
1106
|
+
const callCount = spy.mock.calls.length;
|
|
1107
|
+
const pass = spy.mock.calls.some((callArg) => equalsArgumentArray(callArg, args)) && callCount === 1;
|
|
1108
|
+
const isNot = utils.flag(this, "negate");
|
|
1109
|
+
const msg = utils.getMessage(this, [
|
|
1110
|
+
pass,
|
|
1111
|
+
`expected "${spyName}" to be called once with arguments: #{exp}`,
|
|
1112
|
+
`expected "${spyName}" to not be called once with arguments: #{exp}`,
|
|
1113
|
+
args
|
|
1114
|
+
]);
|
|
1115
|
+
if (pass && isNot || !pass && !isNot) throw new AssertionError(formatCalls(spy, msg, args));
|
|
1116
|
+
});
|
|
1117
|
+
def("toHaveBeenNthCalledWith", function(times, ...args) {
|
|
1118
|
+
const spy = getSpy(this);
|
|
1119
|
+
const spyName = spy.getMockName();
|
|
1120
|
+
const nthCall = spy.mock.calls[times - 1];
|
|
1121
|
+
const callCount = spy.mock.calls.length;
|
|
1122
|
+
const isCalled = times <= callCount;
|
|
1123
|
+
this.assert(nthCall && equalsArgumentArray(nthCall, args), `expected ${ordinal(times)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`, `expected ${ordinal(times)} "${spyName}" call to not have been called with #{exp}`, args, nthCall, isCalled);
|
|
1124
|
+
});
|
|
1125
|
+
def("toHaveBeenLastCalledWith", function(...args) {
|
|
1126
|
+
const spy = getSpy(this);
|
|
1127
|
+
const spyName = spy.getMockName();
|
|
1128
|
+
const lastCall = spy.mock.calls.at(-1);
|
|
1129
|
+
this.assert(lastCall && equalsArgumentArray(lastCall, args), `expected last "${spyName}" call to have been called with #{exp}`, `expected last "${spyName}" call to not have been called with #{exp}`, args, lastCall);
|
|
1130
|
+
});
|
|
1131
|
+
/**
|
|
1132
|
+
* Used for `toHaveBeenCalledBefore` and `toHaveBeenCalledAfter` to determine if the expected spy was called before the result spy.
|
|
1133
|
+
*/
|
|
1134
|
+
function isSpyCalledBeforeAnotherSpy(beforeSpy, afterSpy, failIfNoFirstInvocation) {
|
|
1135
|
+
const beforeInvocationCallOrder = beforeSpy.mock.invocationCallOrder;
|
|
1136
|
+
const afterInvocationCallOrder = afterSpy.mock.invocationCallOrder;
|
|
1137
|
+
if (beforeInvocationCallOrder.length === 0) return !failIfNoFirstInvocation;
|
|
1138
|
+
if (afterInvocationCallOrder.length === 0) return false;
|
|
1139
|
+
return beforeInvocationCallOrder[0] < afterInvocationCallOrder[0];
|
|
1140
|
+
}
|
|
1141
|
+
def(["toHaveBeenCalledBefore"], function(resultSpy, failIfNoFirstInvocation = true) {
|
|
1142
|
+
const expectSpy = getSpy(this);
|
|
1143
|
+
if (!isMockFunction(resultSpy)) throw new TypeError(`${utils.inspect(resultSpy)} is not a spy or a call to a spy`);
|
|
1144
|
+
this.assert(isSpyCalledBeforeAnotherSpy(expectSpy, resultSpy, failIfNoFirstInvocation), `expected "${expectSpy.getMockName()}" to have been called before "${resultSpy.getMockName()}"`, `expected "${expectSpy.getMockName()}" to not have been called before "${resultSpy.getMockName()}"`, resultSpy, expectSpy);
|
|
1145
|
+
});
|
|
1146
|
+
def(["toHaveBeenCalledAfter"], function(resultSpy, failIfNoFirstInvocation = true) {
|
|
1147
|
+
const expectSpy = getSpy(this);
|
|
1148
|
+
if (!isMockFunction(resultSpy)) throw new TypeError(`${utils.inspect(resultSpy)} is not a spy or a call to a spy`);
|
|
1149
|
+
this.assert(isSpyCalledBeforeAnotherSpy(resultSpy, expectSpy, failIfNoFirstInvocation), `expected "${expectSpy.getMockName()}" to have been called after "${resultSpy.getMockName()}"`, `expected "${expectSpy.getMockName()}" to not have been called after "${resultSpy.getMockName()}"`, resultSpy, expectSpy);
|
|
1150
|
+
});
|
|
1151
|
+
def(["toThrow", "toThrowError"], function(expected) {
|
|
1152
|
+
if (typeof expected === "string" || typeof expected === "undefined" || expected instanceof RegExp) return this.throws(expected === "" ? /^$/ : expected);
|
|
1153
|
+
const obj = this._obj;
|
|
1154
|
+
const promise = utils.flag(this, "promise");
|
|
1155
|
+
const isNot = utils.flag(this, "negate");
|
|
1156
|
+
let thrown = null;
|
|
1157
|
+
if (promise === "rejects") thrown = obj;
|
|
1158
|
+
else if (promise === "resolves" && typeof obj !== "function") if (!isNot) throw new AssertionError(utils.flag(this, "message") || "expected promise to throw an error, but it didn't", { showDiff: false }, utils.flag(this, "ssfi"));
|
|
1159
|
+
else return;
|
|
1160
|
+
else {
|
|
1161
|
+
let isThrow = false;
|
|
1162
|
+
try {
|
|
1163
|
+
obj();
|
|
1164
|
+
} catch (err) {
|
|
1165
|
+
isThrow = true;
|
|
1166
|
+
thrown = err;
|
|
1167
|
+
}
|
|
1168
|
+
if (!isThrow && !isNot) throw new AssertionError(utils.flag(this, "message") || "expected function to throw an error, but it didn't", { showDiff: false }, utils.flag(this, "ssfi"));
|
|
1169
|
+
}
|
|
1170
|
+
if (typeof expected === "function") {
|
|
1171
|
+
const name = expected.name || expected.prototype.constructor.name;
|
|
1172
|
+
return this.assert(thrown && thrown instanceof expected, `expected error to be instance of ${name}`, `expected error not to be instance of ${name}`, expected, thrown);
|
|
1173
|
+
}
|
|
1174
|
+
if (isError(expected)) {
|
|
1175
|
+
const equal = equals(thrown, expected, [...customTesters, iterableEquality]);
|
|
1176
|
+
return this.assert(equal, "expected a thrown error to be #{exp}", "expected a thrown error not to be #{exp}", expected, thrown);
|
|
1177
|
+
}
|
|
1178
|
+
if (typeof expected === "object" && "asymmetricMatch" in expected && typeof expected.asymmetricMatch === "function") {
|
|
1179
|
+
const matcher = expected;
|
|
1180
|
+
return this.assert(thrown && matcher.asymmetricMatch(thrown), "expected error to match asymmetric matcher", "expected error not to match asymmetric matcher", matcher, thrown);
|
|
1181
|
+
}
|
|
1182
|
+
const equal = equals(thrown, expected, [...customTesters, iterableEquality]);
|
|
1183
|
+
return this.assert(equal, "expected a thrown value to equal #{exp}", "expected a thrown value not to equal #{exp}", expected, thrown);
|
|
1184
|
+
});
|
|
1185
|
+
[{
|
|
1186
|
+
name: "toHaveResolved",
|
|
1187
|
+
condition: (spy) => spy.mock.settledResults.length > 0 && spy.mock.settledResults.some(({ type }) => type === "fulfilled"),
|
|
1188
|
+
action: "resolved"
|
|
1189
|
+
}, {
|
|
1190
|
+
name: ["toHaveReturned", "toReturn"],
|
|
1191
|
+
condition: (spy) => spy.mock.calls.length > 0 && spy.mock.results.some(({ type }) => type !== "throw"),
|
|
1192
|
+
action: "called"
|
|
1193
|
+
}].forEach(({ name, condition, action }) => {
|
|
1194
|
+
def(name, function() {
|
|
1195
|
+
const spy = getSpy(this);
|
|
1196
|
+
const spyName = spy.getMockName();
|
|
1197
|
+
const pass = condition(spy);
|
|
1198
|
+
this.assert(pass, `expected "${spyName}" to be successfully ${action} at least once`, `expected "${spyName}" to not be successfully ${action}`, pass, !pass, false);
|
|
1199
|
+
});
|
|
1200
|
+
});
|
|
1201
|
+
[{
|
|
1202
|
+
name: "toHaveResolvedTimes",
|
|
1203
|
+
condition: (spy, times) => spy.mock.settledResults.reduce((s, { type }) => type === "fulfilled" ? ++s : s, 0) === times,
|
|
1204
|
+
action: "resolved"
|
|
1205
|
+
}, {
|
|
1206
|
+
name: ["toHaveReturnedTimes", "toReturnTimes"],
|
|
1207
|
+
condition: (spy, times) => spy.mock.results.reduce((s, { type }) => type === "throw" ? s : ++s, 0) === times,
|
|
1208
|
+
action: "called"
|
|
1209
|
+
}].forEach(({ name, condition, action }) => {
|
|
1210
|
+
def(name, function(times) {
|
|
1211
|
+
const spy = getSpy(this);
|
|
1212
|
+
const spyName = spy.getMockName();
|
|
1213
|
+
const pass = condition(spy, times);
|
|
1214
|
+
this.assert(pass, `expected "${spyName}" to be successfully ${action} ${times} times`, `expected "${spyName}" to not be successfully ${action} ${times} times`, `expected resolved times: ${times}`, `received resolved times: ${pass}`, false);
|
|
1215
|
+
});
|
|
1216
|
+
});
|
|
1217
|
+
[{
|
|
1218
|
+
name: "toHaveResolvedWith",
|
|
1219
|
+
condition: (spy, value) => spy.mock.settledResults.some(({ type, value: result }) => type === "fulfilled" && equals(value, result)),
|
|
1220
|
+
action: "resolve"
|
|
1221
|
+
}, {
|
|
1222
|
+
name: ["toHaveReturnedWith", "toReturnWith"],
|
|
1223
|
+
condition: (spy, value) => spy.mock.results.some(({ type, value: result }) => type === "return" && equals(value, result)),
|
|
1224
|
+
action: "return"
|
|
1225
|
+
}].forEach(({ name, condition, action }) => {
|
|
1226
|
+
def(name, function(value) {
|
|
1227
|
+
const spy = getSpy(this);
|
|
1228
|
+
const pass = condition(spy, value);
|
|
1229
|
+
const isNot = utils.flag(this, "negate");
|
|
1230
|
+
if (pass && isNot || !pass && !isNot) {
|
|
1231
|
+
const spyName = spy.getMockName();
|
|
1232
|
+
const msg = utils.getMessage(this, [
|
|
1233
|
+
pass,
|
|
1234
|
+
`expected "${spyName}" to ${action} with: #{exp} at least once`,
|
|
1235
|
+
`expected "${spyName}" to not ${action} with: #{exp}`,
|
|
1236
|
+
value
|
|
1237
|
+
]);
|
|
1238
|
+
throw new AssertionError(formatReturns(spy, action === "return" ? spy.mock.results : spy.mock.settledResults, msg, value));
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1241
|
+
});
|
|
1242
|
+
[{
|
|
1243
|
+
name: "toHaveLastResolvedWith",
|
|
1244
|
+
condition: (spy, value) => {
|
|
1245
|
+
const result = spy.mock.settledResults.at(-1);
|
|
1246
|
+
return Boolean(result && result.type === "fulfilled" && equals(result.value, value));
|
|
1247
|
+
},
|
|
1248
|
+
action: "resolve"
|
|
1249
|
+
}, {
|
|
1250
|
+
name: "toHaveLastReturnedWith",
|
|
1251
|
+
condition: (spy, value) => {
|
|
1252
|
+
const result = spy.mock.results.at(-1);
|
|
1253
|
+
return Boolean(result && result.type === "return" && equals(result.value, value));
|
|
1254
|
+
},
|
|
1255
|
+
action: "return"
|
|
1256
|
+
}].forEach(({ name, condition, action }) => {
|
|
1257
|
+
def(name, function(value) {
|
|
1258
|
+
const spy = getSpy(this);
|
|
1259
|
+
const result = (action === "return" ? spy.mock.results : spy.mock.settledResults).at(-1);
|
|
1260
|
+
const spyName = spy.getMockName();
|
|
1261
|
+
this.assert(condition(spy, value), `expected last "${spyName}" call to ${action} #{exp}`, `expected last "${spyName}" call to not ${action} #{exp}`, value, result?.value);
|
|
1262
|
+
});
|
|
1263
|
+
});
|
|
1264
|
+
[{
|
|
1265
|
+
name: "toHaveNthResolvedWith",
|
|
1266
|
+
condition: (spy, index, value) => {
|
|
1267
|
+
const result = spy.mock.settledResults[index - 1];
|
|
1268
|
+
return result && result.type === "fulfilled" && equals(result.value, value);
|
|
1269
|
+
},
|
|
1270
|
+
action: "resolve"
|
|
1271
|
+
}, {
|
|
1272
|
+
name: "toHaveNthReturnedWith",
|
|
1273
|
+
condition: (spy, index, value) => {
|
|
1274
|
+
const result = spy.mock.results[index - 1];
|
|
1275
|
+
return result && result.type === "return" && equals(result.value, value);
|
|
1276
|
+
},
|
|
1277
|
+
action: "return"
|
|
1278
|
+
}].forEach(({ name, condition, action }) => {
|
|
1279
|
+
def(name, function(nthCall, value) {
|
|
1280
|
+
const spy = getSpy(this);
|
|
1281
|
+
const spyName = spy.getMockName();
|
|
1282
|
+
const result = (action === "return" ? spy.mock.results : spy.mock.settledResults)[nthCall - 1];
|
|
1283
|
+
const ordinalCall = `${ordinal(nthCall)} call`;
|
|
1284
|
+
this.assert(condition(spy, nthCall, value), `expected ${ordinalCall} "${spyName}" call to ${action} #{exp}`, `expected ${ordinalCall} "${spyName}" call to not ${action} #{exp}`, value, result?.value);
|
|
1285
|
+
});
|
|
1286
|
+
});
|
|
1287
|
+
def("withContext", function(context) {
|
|
1288
|
+
for (const key in context) utils.flag(this, key, context[key]);
|
|
1289
|
+
return this;
|
|
1290
|
+
});
|
|
1291
|
+
utils.addProperty(chai.Assertion.prototype, "resolves", function __VITEST_RESOLVES__() {
|
|
1292
|
+
const error = /* @__PURE__ */ new Error("resolves");
|
|
1293
|
+
utils.flag(this, "promise", "resolves");
|
|
1294
|
+
utils.flag(this, "error", error);
|
|
1295
|
+
const test = utils.flag(this, "vitest-test");
|
|
1296
|
+
const obj = utils.flag(this, "object");
|
|
1297
|
+
if (utils.flag(this, "poll")) throw new SyntaxError(`expect.poll() is not supported in combination with .resolves`);
|
|
1298
|
+
if (typeof obj?.then !== "function") throw new TypeError(`You must provide a Promise to expect() when using .resolves, not '${typeof obj}'.`);
|
|
1299
|
+
const proxy = new Proxy(this, { get: (target, key, receiver) => {
|
|
1300
|
+
const result = Reflect.get(target, key, receiver);
|
|
1301
|
+
if (typeof result !== "function") return result instanceof chai.Assertion ? proxy : result;
|
|
1302
|
+
return (...args) => {
|
|
1303
|
+
utils.flag(this, "_name", key);
|
|
1304
|
+
return recordAsyncExpect(test, Promise.resolve(obj).then((value) => {
|
|
1305
|
+
utils.flag(this, "object", value);
|
|
1306
|
+
return result.call(this, ...args);
|
|
1307
|
+
}, (err) => {
|
|
1308
|
+
const _error = new AssertionError(`promise rejected "${utils.inspect(err)}" instead of resolving`, { showDiff: false });
|
|
1309
|
+
_error.cause = err;
|
|
1310
|
+
throw _error;
|
|
1311
|
+
}).catch((err) => {
|
|
1312
|
+
if (isError(err) && error.stack) err.stack = error.stack.replace(error.message, err.message);
|
|
1313
|
+
throw err;
|
|
1314
|
+
}), createAssertionMessage(utils, this, !!args.length), error, utils.flag(this, "soft"));
|
|
1315
|
+
};
|
|
1316
|
+
} });
|
|
1317
|
+
return proxy;
|
|
1318
|
+
});
|
|
1319
|
+
utils.addProperty(chai.Assertion.prototype, "rejects", function __VITEST_REJECTS__() {
|
|
1320
|
+
const error = /* @__PURE__ */ new Error("rejects");
|
|
1321
|
+
utils.flag(this, "promise", "rejects");
|
|
1322
|
+
utils.flag(this, "error", error);
|
|
1323
|
+
const test = utils.flag(this, "vitest-test");
|
|
1324
|
+
const obj = utils.flag(this, "object");
|
|
1325
|
+
const wrapper = typeof obj === "function" ? obj() : obj;
|
|
1326
|
+
if (utils.flag(this, "poll")) throw new SyntaxError(`expect.poll() is not supported in combination with .rejects`);
|
|
1327
|
+
if (typeof wrapper?.then !== "function") throw new TypeError(`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`);
|
|
1328
|
+
const proxy = new Proxy(this, { get: (target, key, receiver) => {
|
|
1329
|
+
const result = Reflect.get(target, key, receiver);
|
|
1330
|
+
if (typeof result !== "function") return result instanceof chai.Assertion ? proxy : result;
|
|
1331
|
+
return (...args) => {
|
|
1332
|
+
utils.flag(this, "_name", key);
|
|
1333
|
+
return recordAsyncExpect(test, Promise.resolve(wrapper).then((value) => {
|
|
1334
|
+
throw new AssertionError(`promise resolved "${utils.inspect(value)}" instead of rejecting`, {
|
|
1335
|
+
showDiff: true,
|
|
1336
|
+
expected: /* @__PURE__ */ new Error("rejected promise"),
|
|
1337
|
+
actual: value
|
|
1338
|
+
});
|
|
1339
|
+
}, (err) => {
|
|
1340
|
+
utils.flag(this, "object", err);
|
|
1341
|
+
return result.call(this, ...args);
|
|
1342
|
+
}).catch((err) => {
|
|
1343
|
+
if (isError(err) && error.stack) err.stack = error.stack.replace(error.message, err.message);
|
|
1344
|
+
throw err;
|
|
1345
|
+
}), createAssertionMessage(utils, this, !!args.length), error, utils.flag(this, "soft"));
|
|
1346
|
+
};
|
|
1347
|
+
} });
|
|
1348
|
+
return proxy;
|
|
1349
|
+
});
|
|
1350
|
+
};
|
|
1351
|
+
function formatCalls(spy, msg, showActualCall) {
|
|
1352
|
+
if (spy.mock.calls.length) msg += y.gray(`\n\nReceived:\n\n${spy.mock.calls.map((callArg, i) => {
|
|
1353
|
+
let methodCall = y.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call:\n\n`);
|
|
1354
|
+
if (showActualCall) methodCall += diff(showActualCall, callArg, { omitAnnotationLines: true });
|
|
1355
|
+
else methodCall += stringify(callArg).split("\n").map((line) => ` ${line}`).join("\n");
|
|
1356
|
+
methodCall += "\n";
|
|
1357
|
+
return methodCall;
|
|
1358
|
+
}).join("\n")}`);
|
|
1359
|
+
msg += y.gray(`\n\nNumber of calls: ${y.bold(spy.mock.calls.length)}\n`);
|
|
1360
|
+
return msg;
|
|
1361
|
+
}
|
|
1362
|
+
function formatReturns(spy, results, msg, showActualReturn) {
|
|
1363
|
+
if (results.length) msg += y.gray(`\n\nReceived:\n\n${results.map((callReturn, i) => {
|
|
1364
|
+
let methodCall = y.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call return:\n\n`);
|
|
1365
|
+
if (showActualReturn) methodCall += diff(showActualReturn, callReturn.value, { omitAnnotationLines: true });
|
|
1366
|
+
else methodCall += stringify(callReturn).split("\n").map((line) => ` ${line}`).join("\n");
|
|
1367
|
+
methodCall += "\n";
|
|
1368
|
+
return methodCall;
|
|
1369
|
+
}).join("\n")}`);
|
|
1370
|
+
msg += y.gray(`\n\nNumber of calls: ${y.bold(spy.mock.calls.length)}\n`);
|
|
1371
|
+
return msg;
|
|
1372
|
+
}
|
|
1373
|
+
function getMatcherState(assertion, expect) {
|
|
1374
|
+
const obj = assertion._obj;
|
|
1375
|
+
const isNot = utils_exports.flag(assertion, "negate");
|
|
1376
|
+
const promise = utils_exports.flag(assertion, "promise") || "";
|
|
1377
|
+
const customMessage = utils_exports.flag(assertion, "message");
|
|
1378
|
+
const jestUtils = {
|
|
1379
|
+
...getMatcherUtils(),
|
|
1380
|
+
diff,
|
|
1381
|
+
stringify,
|
|
1382
|
+
iterableEquality,
|
|
1383
|
+
subsetEquality
|
|
1384
|
+
};
|
|
1385
|
+
let task = utils_exports.flag(assertion, "vitest-test");
|
|
1386
|
+
const currentTestName = task?.fullTestName ?? "";
|
|
1387
|
+
if (task?.type !== "test") task = void 0;
|
|
1388
|
+
return {
|
|
1389
|
+
state: {
|
|
1390
|
+
...getState(expect),
|
|
1391
|
+
task,
|
|
1392
|
+
currentTestName,
|
|
1393
|
+
customTesters: getCustomEqualityTesters(),
|
|
1394
|
+
isNot,
|
|
1395
|
+
utils: jestUtils,
|
|
1396
|
+
promise,
|
|
1397
|
+
equals,
|
|
1398
|
+
suppressedErrors: [],
|
|
1399
|
+
soft: utils_exports.flag(assertion, "soft"),
|
|
1400
|
+
poll: utils_exports.flag(assertion, "poll")
|
|
1401
|
+
},
|
|
1402
|
+
isNot,
|
|
1403
|
+
obj,
|
|
1404
|
+
customMessage
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
var JestExtendError = class extends Error {
|
|
1408
|
+
constructor(message, actual, expected, context) {
|
|
1409
|
+
super(message);
|
|
1410
|
+
this.actual = actual;
|
|
1411
|
+
this.expected = expected;
|
|
1412
|
+
this.context = context;
|
|
1413
|
+
}
|
|
1414
|
+
};
|
|
1415
|
+
function JestExtendPlugin(c, expect, matchers) {
|
|
1416
|
+
return (_, utils) => {
|
|
1417
|
+
Object.entries(matchers).forEach(([expectAssertionName, expectAssertion]) => {
|
|
1418
|
+
function expectWrapper(...args) {
|
|
1419
|
+
const { state, isNot, obj, customMessage } = getMatcherState(this, expect);
|
|
1420
|
+
const result = expectAssertion.call(state, obj, ...args);
|
|
1421
|
+
if (result && typeof result === "object" && typeof result.then === "function") return result.then(({ pass, message, actual, expected, meta }) => {
|
|
1422
|
+
if (pass && isNot || !pass && !isNot) throw new JestExtendError(customMessage != null ? customMessage : message(), actual, expected, {
|
|
1423
|
+
assertionName: expectAssertionName,
|
|
1424
|
+
meta
|
|
1425
|
+
});
|
|
1426
|
+
});
|
|
1427
|
+
const { pass, message, actual, expected, meta } = result;
|
|
1428
|
+
if (pass && isNot || !pass && !isNot) throw new JestExtendError(customMessage != null ? customMessage : message(), actual, expected, {
|
|
1429
|
+
assertionName: expectAssertionName,
|
|
1430
|
+
meta
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
const softWrapper = wrapAssertion(utils, expectAssertionName, expectWrapper);
|
|
1434
|
+
utils.addMethod(globalThis[JEST_MATCHERS_OBJECT].matchers, expectAssertionName, softWrapper);
|
|
1435
|
+
utils.addMethod(c.Assertion.prototype, expectAssertionName, softWrapper);
|
|
1436
|
+
class CustomMatcher extends AsymmetricMatcher {
|
|
1437
|
+
constructor(inverse = false, ...sample) {
|
|
1438
|
+
super(sample, inverse);
|
|
1439
|
+
}
|
|
1440
|
+
asymmetricMatch(other) {
|
|
1441
|
+
const { pass } = expectAssertion.call(this.getMatcherContext(expect), other, ...this.sample);
|
|
1442
|
+
return this.inverse ? !pass : pass;
|
|
1443
|
+
}
|
|
1444
|
+
toString() {
|
|
1445
|
+
return `${this.inverse ? "not." : ""}${expectAssertionName}`;
|
|
1446
|
+
}
|
|
1447
|
+
getExpectedType() {
|
|
1448
|
+
return "any";
|
|
1449
|
+
}
|
|
1450
|
+
toAsymmetricMatcher() {
|
|
1451
|
+
return `${this.toString()}<${this.sample.map((item) => stringify(item)).join(", ")}>`;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
const customMatcher = (...sample) => new CustomMatcher(false, ...sample);
|
|
1455
|
+
Object.defineProperty(expect, expectAssertionName, {
|
|
1456
|
+
configurable: true,
|
|
1457
|
+
enumerable: true,
|
|
1458
|
+
value: customMatcher,
|
|
1459
|
+
writable: true
|
|
1460
|
+
});
|
|
1461
|
+
Object.defineProperty(expect.not, expectAssertionName, {
|
|
1462
|
+
configurable: true,
|
|
1463
|
+
enumerable: true,
|
|
1464
|
+
value: (...sample) => new CustomMatcher(true, ...sample),
|
|
1465
|
+
writable: true
|
|
1466
|
+
});
|
|
1467
|
+
Object.defineProperty(globalThis[ASYMMETRIC_MATCHERS_OBJECT], expectAssertionName, {
|
|
1468
|
+
configurable: true,
|
|
1469
|
+
enumerable: true,
|
|
1470
|
+
value: customMatcher,
|
|
1471
|
+
writable: true
|
|
1472
|
+
});
|
|
1473
|
+
});
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
const JestExtend = (chai, utils) => {
|
|
1477
|
+
utils.addMethod(chai.expect, "extend", (expect, expects) => {
|
|
1478
|
+
use(JestExtendPlugin(chai, expect, expects));
|
|
1479
|
+
});
|
|
1480
|
+
};
|
|
1481
|
+
//#endregion
|
|
1482
|
+
export { ASYMMETRIC_MATCHERS_OBJECT, ChaiStyleAssertions, GLOBAL_EXPECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, addCustomEqualityTesters, createAssertionMessage, customMatchers, equals, getState, iterableEquality, recordAsyncExpect, setState, subsetEquality, wrapAssertion };
|
|
1483
|
+
|
|
1484
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6WyJjIiwidXRpbCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy8ucG5wbS9Adml0ZXN0K2V4cGVjdEA0LjEuMi9ub2RlX21vZHVsZXMvQHZpdGVzdC9leHBlY3QvZGlzdC9pbmRleC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwcmludERpZmZPclN0cmluZ2lmeSwgZGlmZiB9IGZyb20gJ0B2aXRlc3QvdXRpbHMvZGlmZic7XG5pbXBvcnQgeyBzdHJpbmdpZnkgfSBmcm9tICdAdml0ZXN0L3V0aWxzL2Rpc3BsYXknO1xuaW1wb3J0IHsgZ2V0VHlwZSwgaXNPYmplY3QsIG5vb3AsIGFzc2VydFR5cGVzLCBvcmRpbmFsIH0gZnJvbSAnQHZpdGVzdC91dGlscy9oZWxwZXJzJztcbmltcG9ydCBjIGZyb20gJ3RpbnlyYWluYm93JztcbmltcG9ydCB7IGlzTW9ja0Z1bmN0aW9uIH0gZnJvbSAnQHZpdGVzdC9zcHknO1xuaW1wb3J0IHsgcHJvY2Vzc0Vycm9yIH0gZnJvbSAnQHZpdGVzdC91dGlscy9lcnJvcic7XG5pbXBvcnQgeyB1c2UsIHV0aWwgfSBmcm9tICdjaGFpJztcbmltcG9ydCAqIGFzIGNoYWkgZnJvbSAnY2hhaSc7XG5leHBvcnQgeyBjaGFpIH07XG5cbmNvbnN0IENoYWlTdHlsZUFzc2VydGlvbnMgPSAoY2hhaSwgdXRpbHMpID0+IHtcblx0ZnVuY3Rpb24gZGVmUHJvcGVydHkobmFtZSwgZGVsZWdhdGVUbykge1xuXHRcdHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRjb25zdCBqZXN0TWV0aG9kID0gY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlW2RlbGVnYXRlVG9dO1xuXHRcdFx0aWYgKCFqZXN0TWV0aG9kKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGRlbGVnYXRlIHRvICR7U3RyaW5nKGRlbGVnYXRlVG8pfTogbWV0aG9kIG5vdCBmb3VuZC4gRW5zdXJlIEplc3RDaGFpRXhwZWN0IHBsdWdpbiBpcyBsb2FkZWQgZmlyc3QuYCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gamVzdE1ldGhvZC5jYWxsKHRoaXMpO1xuXHRcdH0pO1xuXHR9XG5cdGZ1bmN0aW9uIGRlZlByb3BlcnR5V2l0aEFyZ3MobmFtZSwgZGVsZWdhdGVUbywgLi4uYXJncykge1xuXHRcdHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRjb25zdCBqZXN0TWV0aG9kID0gY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlW2RlbGVnYXRlVG9dO1xuXHRcdFx0aWYgKCFqZXN0TWV0aG9kKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGRlbGVnYXRlIHRvICR7U3RyaW5nKGRlbGVnYXRlVG8pfTogbWV0aG9kIG5vdCBmb3VuZC4gRW5zdXJlIEplc3RDaGFpRXhwZWN0IHBsdWdpbiBpcyBsb2FkZWQgZmlyc3QuYCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gamVzdE1ldGhvZC5jYWxsKHRoaXMsIC4uLmFyZ3MpO1xuXHRcdH0pO1xuXHR9XG5cdGZ1bmN0aW9uIGRlZk1ldGhvZChuYW1lLCBkZWxlZ2F0ZVRvKSB7XG5cdFx0dXRpbHMuYWRkTWV0aG9kKGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgZnVuY3Rpb24oLi4uYXJncykge1xuXHRcdFx0Y29uc3QgamVzdE1ldGhvZCA9IGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZVtkZWxlZ2F0ZVRvXTtcblx0XHRcdGlmICghamVzdE1ldGhvZCkge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBkZWxlZ2F0ZSB0byAke1N0cmluZyhkZWxlZ2F0ZVRvKX06IG1ldGhvZCBub3QgZm91bmQuIEVuc3VyZSBKZXN0Q2hhaUV4cGVjdCBwbHVnaW4gaXMgbG9hZGVkIGZpcnN0LmApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGplc3RNZXRob2QuY2FsbCh0aGlzLCAuLi5hcmdzKTtcblx0XHR9KTtcblx0fVxuXHQvLyBBUEkgdG8gKHNvbWV3aGF0KSBtaXJyb3Igc2lub24tY2hhaVxuXHQvLyBodHRwczovL2dpdGh1Yi5jb20vY2hhaWpzL3Npbm9uLWNoYWlcblx0ZGVmUHJvcGVydHkoXCJjYWxsZWRcIiwgXCJ0b0hhdmVCZWVuQ2FsbGVkXCIpO1xuXHRkZWZQcm9wZXJ0eShcImNhbGxlZE9uY2VcIiwgXCJ0b0hhdmVCZWVuQ2FsbGVkT25jZVwiKTtcblx0ZGVmUHJvcGVydHlXaXRoQXJncyhcImNhbGxlZFR3aWNlXCIsIFwidG9IYXZlQmVlbkNhbGxlZFRpbWVzXCIsIDIpO1xuXHRkZWZQcm9wZXJ0eVdpdGhBcmdzKFwiY2FsbGVkVGhyaWNlXCIsIFwidG9IYXZlQmVlbkNhbGxlZFRpbWVzXCIsIDMpO1xuXHRkZWZNZXRob2QoXCJjYWxsQ291bnRcIiwgXCJ0b0hhdmVCZWVuQ2FsbGVkVGltZXNcIik7XG5cdGRlZk1ldGhvZChcImNhbGxlZFdpdGhcIiwgXCJ0b0hhdmVCZWVuQ2FsbGVkV2l0aFwiKTtcblx0ZGVmTWV0aG9kKFwiY2FsbGVkT25jZVdpdGhcIiwgXCJ0b0hhdmVCZWVuQ2FsbGVkRXhhY3RseU9uY2VXaXRoXCIpO1xuXHRkZWZNZXRob2QoXCJsYXN0Q2FsbGVkV2l0aFwiLCBcInRvSGF2ZUJlZW5MYXN0Q2FsbGVkV2l0aFwiKTtcblx0ZGVmTWV0aG9kKFwibnRoQ2FsbGVkV2l0aFwiLCBcInRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoXCIpO1xuXHRkZWZNZXRob2QoXCJyZXR1cm5lZFwiLCBcInRvSGF2ZVJldHVybmVkXCIpO1xuXHRkZWZNZXRob2QoXCJyZXR1cm5lZFdpdGhcIiwgXCJ0b0hhdmVSZXR1cm5lZFdpdGhcIik7XG5cdGRlZk1ldGhvZChcInJldHVybmVkVGltZXNcIiwgXCJ0b0hhdmVSZXR1cm5lZFRpbWVzXCIpO1xuXHRkZWZNZXRob2QoXCJsYXN0UmV0dXJuZWRXaXRoXCIsIFwidG9IYXZlTGFzdFJldHVybmVkV2l0aFwiKTtcblx0ZGVmTWV0aG9kKFwibnRoUmV0dXJuZWRXaXRoXCIsIFwidG9IYXZlTnRoUmV0dXJuZWRXaXRoXCIpO1xuXHRkZWZNZXRob2QoXCJjYWxsZWRCZWZvcmVcIiwgXCJ0b0hhdmVCZWVuQ2FsbGVkQmVmb3JlXCIpO1xuXHRkZWZNZXRob2QoXCJjYWxsZWRBZnRlclwiLCBcInRvSGF2ZUJlZW5DYWxsZWRBZnRlclwiKTtcblx0Ly8gVE9ETzogaW1wbGVtZW50XG5cdC8vIGRlZk1ldGhvZCgndGhyb3duJywgJ3RvSGF2ZVRocm93bicpXG59O1xuXG5jb25zdCBNQVRDSEVSU19PQkpFQ1QgPSBTeW1ib2wuZm9yKFwibWF0Y2hlcnMtb2JqZWN0XCIpO1xuY29uc3QgSkVTVF9NQVRDSEVSU19PQkpFQ1QgPSBTeW1ib2wuZm9yKFwiJCRqZXN0LW1hdGNoZXJzLW9iamVjdFwiKTtcbmNvbnN0IEdMT0JBTF9FWFBFQ1QgPSBTeW1ib2wuZm9yKFwiZXhwZWN0LWdsb2JhbFwiKTtcbmNvbnN0IEFTWU1NRVRSSUNfTUFUQ0hFUlNfT0JKRUNUID0gU3ltYm9sLmZvcihcImFzeW1tZXRyaWMtbWF0Y2hlcnMtb2JqZWN0XCIpO1xuXG4vLyBzZWxlY3RpdmVseSBwb3J0ZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vamVzdC1jb21tdW5pdHkvamVzdC1leHRlbmRlZFxuY29uc3QgY3VzdG9tTWF0Y2hlcnMgPSB7XG5cdHRvU2F0aXNmeShhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG5cdFx0Y29uc3QgeyBwcmludFJlY2VpdmVkLCBwcmludEV4cGVjdGVkLCBtYXRjaGVySGludCB9ID0gdGhpcy51dGlscztcblx0XHRjb25zdCBwYXNzID0gZXhwZWN0ZWQoYWN0dWFsKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFzcyxcblx0XHRcdG1lc3NhZ2U6ICgpID0+IHBhc3MgPyBgXFxcbiR7bWF0Y2hlckhpbnQoXCIubm90LnRvU2F0aXNmeVwiLCBcInJlY2VpdmVkXCIsIFwiXCIpfVxuXG5FeHBlY3RlZCB2YWx1ZSB0byBub3Qgc2F0aXNmeTpcbiR7bWVzc2FnZSB8fCBwcmludEV4cGVjdGVkKGV4cGVjdGVkKX1cblJlY2VpdmVkOlxuJHtwcmludFJlY2VpdmVkKGFjdHVhbCl9YCA6IGBcXFxuJHttYXRjaGVySGludChcIi50b1NhdGlzZnlcIiwgXCJyZWNlaXZlZFwiLCBcIlwiKX1cblxuRXhwZWN0ZWQgdmFsdWUgdG8gc2F0aXNmeTpcbiR7bWVzc2FnZSB8fCBwcmludEV4cGVjdGVkKGV4cGVjdGVkKX1cblxuUmVjZWl2ZWQ6XG4ke3ByaW50UmVjZWl2ZWQoYWN0dWFsKX1gXG5cdFx0fTtcblx0fSxcblx0dG9CZU9uZU9mKGFjdHVhbCwgZXhwZWN0ZWQpIHtcblx0XHRjb25zdCB7IGVxdWFscywgY3VzdG9tVGVzdGVycyB9ID0gdGhpcztcblx0XHRjb25zdCB7IHByaW50UmVjZWl2ZWQsIHByaW50RXhwZWN0ZWQsIG1hdGNoZXJIaW50IH0gPSB0aGlzLnV0aWxzO1xuXHRcdGxldCBwYXNzO1xuXHRcdGlmIChBcnJheS5pc0FycmF5KGV4cGVjdGVkKSkge1xuXHRcdFx0cGFzcyA9IGV4cGVjdGVkLmxlbmd0aCA9PT0gMCB8fCBleHBlY3RlZC5zb21lKChpdGVtKSA9PiBlcXVhbHMoaXRlbSwgYWN0dWFsLCBjdXN0b21UZXN0ZXJzKSk7XG5cdFx0fSBlbHNlIGlmIChleHBlY3RlZCBpbnN0YW5jZW9mIFNldCkge1xuXHRcdFx0cGFzcyA9IGV4cGVjdGVkLnNpemUgPT09IDAgfHwgZXhwZWN0ZWQuaGFzKGFjdHVhbCkgfHwgWy4uLmV4cGVjdGVkXS5zb21lKChpdGVtKSA9PiBlcXVhbHMoaXRlbSwgYWN0dWFsLCBjdXN0b21UZXN0ZXJzKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYFlvdSBtdXN0IHByb3ZpZGUgYW4gYXJyYXkgb3Igc2V0IHRvICR7bWF0Y2hlckhpbnQoXCIudG9CZU9uZU9mXCIpfSwgbm90ICcke3R5cGVvZiBleHBlY3RlZH0nLmApO1xuXHRcdH1cblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFzcyxcblx0XHRcdG1lc3NhZ2U6ICgpID0+IHBhc3MgPyBgXFxcbiR7bWF0Y2hlckhpbnQoXCIubm90LnRvQmVPbmVPZlwiLCBcInJlY2VpdmVkXCIsIFwiXCIpfVxuXG5FeHBlY3RlZCB2YWx1ZSB0byBub3QgYmUgb25lIG9mOlxuJHtwcmludEV4cGVjdGVkKGV4cGVjdGVkKX1cblJlY2VpdmVkOlxuJHtwcmludFJlY2VpdmVkKGFjdHVhbCl9YCA6IGBcXFxuJHttYXRjaGVySGludChcIi50b0JlT25lT2ZcIiwgXCJyZWNlaXZlZFwiLCBcIlwiKX1cblxuRXhwZWN0ZWQgdmFsdWUgdG8gYmUgb25lIG9mOlxuJHtwcmludEV4cGVjdGVkKGV4cGVjdGVkKX1cblxuUmVjZWl2ZWQ6XG4ke3ByaW50UmVjZWl2ZWQoYWN0dWFsKX1gXG5cdFx0fTtcblx0fVxufTtcblxuY29uc3QgRVhQRUNURURfQ09MT1IgPSBjLmdyZWVuO1xuY29uc3QgUkVDRUlWRURfQ09MT1IgPSBjLnJlZDtcbmNvbnN0IElOVkVSVEVEX0NPTE9SID0gYy5pbnZlcnNlO1xuY29uc3QgQk9MRF9XRUlHSFQgPSBjLmJvbGQ7XG5jb25zdCBESU1fQ09MT1IgPSBjLmRpbTtcbmZ1bmN0aW9uIG1hdGNoZXJIaW50KG1hdGNoZXJOYW1lLCByZWNlaXZlZCA9IFwicmVjZWl2ZWRcIiwgZXhwZWN0ZWQgPSBcImV4cGVjdGVkXCIsIG9wdGlvbnMgPSB7fSkge1xuXHRjb25zdCB7IGNvbW1lbnQgPSBcIlwiLCBpc0RpcmVjdEV4cGVjdENhbGwgPSBmYWxzZSwgaXNOb3QgPSBmYWxzZSwgcHJvbWlzZSA9IFwiXCIsIHNlY29uZEFyZ3VtZW50ID0gXCJcIiwgZXhwZWN0ZWRDb2xvciA9IEVYUEVDVEVEX0NPTE9SLCByZWNlaXZlZENvbG9yID0gUkVDRUlWRURfQ09MT1IsIHNlY29uZEFyZ3VtZW50Q29sb3IgPSBFWFBFQ1RFRF9DT0xPUiB9ID0gb3B0aW9ucztcblx0bGV0IGhpbnQgPSBcIlwiO1xuXHRsZXQgZGltU3RyaW5nID0gXCJleHBlY3RcIjtcblx0aWYgKCFpc0RpcmVjdEV4cGVjdENhbGwgJiYgcmVjZWl2ZWQgIT09IFwiXCIpIHtcblx0XHRoaW50ICs9IERJTV9DT0xPUihgJHtkaW1TdHJpbmd9KGApICsgcmVjZWl2ZWRDb2xvcihyZWNlaXZlZCk7XG5cdFx0ZGltU3RyaW5nID0gXCIpXCI7XG5cdH1cblx0aWYgKHByb21pc2UgIT09IFwiXCIpIHtcblx0XHRoaW50ICs9IERJTV9DT0xPUihgJHtkaW1TdHJpbmd9LmApICsgcHJvbWlzZTtcblx0XHRkaW1TdHJpbmcgPSBcIlwiO1xuXHR9XG5cdGlmIChpc05vdCkge1xuXHRcdGhpbnQgKz0gYCR7RElNX0NPTE9SKGAke2RpbVN0cmluZ30uYCl9bm90YDtcblx0XHRkaW1TdHJpbmcgPSBcIlwiO1xuXHR9XG5cdGlmIChtYXRjaGVyTmFtZS5pbmNsdWRlcyhcIi5cIikpIHtcblx0XHQvLyBPbGQgZm9ybWF0OiBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSxcblx0XHQvLyBlc3BlY2lhbGx5IHdpdGhvdXQgcHJvbWlzZSBvciBpc05vdCBvcHRpb25zXG5cdFx0ZGltU3RyaW5nICs9IG1hdGNoZXJOYW1lO1xuXHR9IGVsc2Uge1xuXHRcdC8vIE5ldyBmb3JtYXQ6IG9taXQgcGVyaW9kIGZyb20gbWF0Y2hlck5hbWUgYXJnXG5cdFx0aGludCArPSBESU1fQ09MT1IoYCR7ZGltU3RyaW5nfS5gKSArIG1hdGNoZXJOYW1lO1xuXHRcdGRpbVN0cmluZyA9IFwiXCI7XG5cdH1cblx0aWYgKGV4cGVjdGVkID09PSBcIlwiKSB7XG5cdFx0ZGltU3RyaW5nICs9IFwiKClcIjtcblx0fSBlbHNlIHtcblx0XHRoaW50ICs9IERJTV9DT0xPUihgJHtkaW1TdHJpbmd9KGApICsgZXhwZWN0ZWRDb2xvcihleHBlY3RlZCk7XG5cdFx0aWYgKHNlY29uZEFyZ3VtZW50KSB7XG5cdFx0XHRoaW50ICs9IERJTV9DT0xPUihcIiwgXCIpICsgc2Vjb25kQXJndW1lbnRDb2xvcihzZWNvbmRBcmd1bWVudCk7XG5cdFx0fVxuXHRcdGRpbVN0cmluZyA9IFwiKVwiO1xuXHR9XG5cdGlmIChjb21tZW50ICE9PSBcIlwiKSB7XG5cdFx0ZGltU3RyaW5nICs9IGAgLy8gJHtjb21tZW50fWA7XG5cdH1cblx0aWYgKGRpbVN0cmluZyAhPT0gXCJcIikge1xuXHRcdGhpbnQgKz0gRElNX0NPTE9SKGRpbVN0cmluZyk7XG5cdH1cblx0cmV0dXJuIGhpbnQ7XG59XG5jb25zdCBTUEFDRV9TWU1CT0wgPSBcIsK3XCI7XG4vLyBJbnN0ZWFkIG9mIGludmVyc2UgaGlnaGxpZ2h0IHdoaWNoIG5vdyBpbXBsaWVzIGEgY2hhbmdlLFxuLy8gcmVwbGFjZSBjb21tb24gc3BhY2VzIHdpdGggbWlkZGxlIGRvdCBhdCB0aGUgZW5kIG9mIGFueSBsaW5lLlxuZnVuY3Rpb24gcmVwbGFjZVRyYWlsaW5nU3BhY2VzKHRleHQpIHtcblx0cmV0dXJuIHRleHQucmVwbGFjZSgvXFxzKyQvZ20sIChzcGFjZXMpID0+IFNQQUNFX1NZTUJPTC5yZXBlYXQoc3BhY2VzLmxlbmd0aCkpO1xufVxuZnVuY3Rpb24gcHJpbnRSZWNlaXZlZChvYmplY3QpIHtcblx0cmV0dXJuIFJFQ0VJVkVEX0NPTE9SKHJlcGxhY2VUcmFpbGluZ1NwYWNlcyhzdHJpbmdpZnkob2JqZWN0KSkpO1xufVxuZnVuY3Rpb24gcHJpbnRFeHBlY3RlZCh2YWx1ZSkge1xuXHRyZXR1cm4gRVhQRUNURURfQ09MT1IocmVwbGFjZVRyYWlsaW5nU3BhY2VzKHN0cmluZ2lmeSh2YWx1ZSkpKTtcbn1cbmZ1bmN0aW9uIGdldE1hdGNoZXJVdGlscygpIHtcblx0cmV0dXJuIHtcblx0XHRFWFBFQ1RFRF9DT0xPUixcblx0XHRSRUNFSVZFRF9DT0xPUixcblx0XHRJTlZFUlRFRF9DT0xPUixcblx0XHRCT0xEX1dFSUdIVCxcblx0XHRESU1fQ09MT1IsXG5cdFx0ZGlmZixcblx0XHRtYXRjaGVySGludCxcblx0XHRwcmludFJlY2VpdmVkLFxuXHRcdHByaW50RXhwZWN0ZWQsXG5cdFx0cHJpbnREaWZmT3JTdHJpbmdpZnksXG5cdFx0cHJpbnRXaXRoVHlwZVxuXHR9O1xufVxuZnVuY3Rpb24gcHJpbnRXaXRoVHlwZShuYW1lLCB2YWx1ZSwgcHJpbnQpIHtcblx0Y29uc3QgdHlwZSA9IGdldFR5cGUodmFsdWUpO1xuXHRjb25zdCBoYXNUeXBlID0gdHlwZSAhPT0gXCJudWxsXCIgJiYgdHlwZSAhPT0gXCJ1bmRlZmluZWRcIiA/IGAke25hbWV9IGhhcyB0eXBlOiAgJHt0eXBlfVxcbmAgOiBcIlwiO1xuXHRjb25zdCBoYXNWYWx1ZSA9IGAke25hbWV9IGhhcyB2YWx1ZTogJHtwcmludCh2YWx1ZSl9YDtcblx0cmV0dXJuIGhhc1R5cGUgKyBoYXNWYWx1ZTtcbn1cbmZ1bmN0aW9uIGFkZEN1c3RvbUVxdWFsaXR5VGVzdGVycyhuZXdUZXN0ZXJzKSB7XG5cdGlmICghQXJyYXkuaXNBcnJheShuZXdUZXN0ZXJzKSkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYGV4cGVjdC5jdXN0b21FcXVhbGl0eVRlc3RlcnM6IE11c3QgYmUgc2V0IHRvIGFuIGFycmF5IG9mIFRlc3RlcnMuIFdhcyBnaXZlbiBcIiR7Z2V0VHlwZShuZXdUZXN0ZXJzKX1cImApO1xuXHR9XG5cdGdsb2JhbFRoaXNbSkVTVF9NQVRDSEVSU19PQkpFQ1RdLmN1c3RvbUVxdWFsaXR5VGVzdGVycy5wdXNoKC4uLm5ld1Rlc3RlcnMpO1xufVxuZnVuY3Rpb24gZ2V0Q3VzdG9tRXF1YWxpdHlUZXN0ZXJzKCkge1xuXHRyZXR1cm4gZ2xvYmFsVGhpc1tKRVNUX01BVENIRVJTX09CSkVDVF0uY3VzdG9tRXF1YWxpdHlUZXN0ZXJzO1xufVxuXG4vLyBFeHRyYWN0ZWQgb3V0IG9mIGphc21pbmUgMi41LjJcbmZ1bmN0aW9uIGVxdWFscyhhLCBiLCBjdXN0b21UZXN0ZXJzLCBzdHJpY3RDaGVjaykge1xuXHRjdXN0b21UZXN0ZXJzID0gY3VzdG9tVGVzdGVycyB8fCBbXTtcblx0cmV0dXJuIGVxKGEsIGIsIFtdLCBbXSwgY3VzdG9tVGVzdGVycywgc3RyaWN0Q2hlY2sgPyBoYXNLZXkgOiBoYXNEZWZpbmVkS2V5KTtcbn1cbmNvbnN0IGZ1bmN0aW9uVG9TdHJpbmcgPSBGdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmc7XG5mdW5jdGlvbiBpc0FzeW1tZXRyaWMob2JqKSB7XG5cdHJldHVybiAhIW9iaiAmJiB0eXBlb2Ygb2JqID09PSBcIm9iamVjdFwiICYmIFwiYXN5bW1ldHJpY01hdGNoXCIgaW4gb2JqICYmIGlzQShcIkZ1bmN0aW9uXCIsIG9iai5hc3ltbWV0cmljTWF0Y2gpO1xufVxuZnVuY3Rpb24gaGFzQXN5bW1ldHJpYyhvYmosIHNlZW4gPSBuZXcgU2V0KCkpIHtcblx0aWYgKHNlZW4uaGFzKG9iaikpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0c2Vlbi5hZGQob2JqKTtcblx0aWYgKGlzQXN5bW1ldHJpYyhvYmopKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0aWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuXHRcdHJldHVybiBvYmouc29tZSgoaSkgPT4gaGFzQXN5bW1ldHJpYyhpLCBzZWVuKSk7XG5cdH1cblx0aWYgKG9iaiBpbnN0YW5jZW9mIFNldCkge1xuXHRcdHJldHVybiBBcnJheS5mcm9tKG9iaikuc29tZSgoaSkgPT4gaGFzQXN5bW1ldHJpYyhpLCBzZWVuKSk7XG5cdH1cblx0aWYgKGlzT2JqZWN0KG9iaikpIHtcblx0XHRyZXR1cm4gT2JqZWN0LnZhbHVlcyhvYmopLnNvbWUoKHYpID0+IGhhc0FzeW1tZXRyaWModiwgc2VlbikpO1xuXHR9XG5cdHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGFzeW1tZXRyaWNNYXRjaChhLCBiLCBjdXN0b21UZXN0ZXJzKSB7XG5cdGNvbnN0IGFzeW1tZXRyaWNBID0gaXNBc3ltbWV0cmljKGEpO1xuXHRjb25zdCBhc3ltbWV0cmljQiA9IGlzQXN5bW1ldHJpYyhiKTtcblx0aWYgKGFzeW1tZXRyaWNBICYmIGFzeW1tZXRyaWNCKSB7XG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXHRpZiAoYXN5bW1ldHJpY0EpIHtcblx0XHRyZXR1cm4gYS5hc3ltbWV0cmljTWF0Y2goYiwgY3VzdG9tVGVzdGVycyk7XG5cdH1cblx0aWYgKGFzeW1tZXRyaWNCKSB7XG5cdFx0cmV0dXJuIGIuYXN5bW1ldHJpY01hdGNoKGEsIGN1c3RvbVRlc3RlcnMpO1xuXHR9XG59XG4vLyBodHRwczovL2dpdGh1Yi5jb20vamVzdGpzL2plc3QvYmxvYi85MDViY2JjZWQzZDQwY2RmN2FhZGM0Y2RmNmZiNzMxYzRiYjNkYmUzL3BhY2thZ2VzL2V4cGVjdC11dGlscy9zcmMvdXRpbHMudHMjTDUwOVxuZnVuY3Rpb24gaXNFcnJvcih2YWx1ZSkge1xuXHRpZiAodHlwZW9mIEVycm9yLmlzRXJyb3IgPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdHJldHVybiBFcnJvci5pc0Vycm9yKHZhbHVlKTtcblx0fVxuXHRzd2l0Y2ggKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkpIHtcblx0XHRjYXNlIFwiW29iamVjdCBFcnJvcl1cIjpcblx0XHRjYXNlIFwiW29iamVjdCBFeGNlcHRpb25dXCI6XG5cdFx0Y2FzZSBcIltvYmplY3QgRE9NRXhjZXB0aW9uXVwiOiByZXR1cm4gdHJ1ZTtcblx0XHRkZWZhdWx0OiByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBFcnJvcjtcblx0fVxufVxuLy8gRXF1YWxpdHkgZnVuY3Rpb24gbG92aW5nbHkgYWRhcHRlZCBmcm9tIGlzRXF1YWwgaW5cbi8vICAgW1VuZGVyc2NvcmVdKGh0dHA6Ly91bmRlcnNjb3JlanMub3JnKVxuZnVuY3Rpb24gZXEoYSwgYiwgYVN0YWNrLCBiU3RhY2ssIGN1c3RvbVRlc3RlcnMsIGhhc0tleSkge1xuXHRsZXQgcmVzdWx0ID0gdHJ1ZTtcblx0Y29uc3QgYXN5bW1ldHJpY1Jlc3VsdCA9IGFzeW1tZXRyaWNNYXRjaChhLCBiLCBjdXN0b21UZXN0ZXJzKTtcblx0aWYgKGFzeW1tZXRyaWNSZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBhc3ltbWV0cmljUmVzdWx0O1xuXHR9XG5cdGNvbnN0IHRlc3RlckNvbnRleHQgPSB7IGVxdWFscyB9O1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IGN1c3RvbVRlc3RlcnMubGVuZ3RoOyBpKyspIHtcblx0XHRjb25zdCBjdXN0b21UZXN0ZXJSZXN1bHQgPSBjdXN0b21UZXN0ZXJzW2ldLmNhbGwodGVzdGVyQ29udGV4dCwgYSwgYiwgY3VzdG9tVGVzdGVycyk7XG5cdFx0aWYgKGN1c3RvbVRlc3RlclJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gY3VzdG9tVGVzdGVyUmVzdWx0O1xuXHRcdH1cblx0fVxuXHRpZiAodHlwZW9mIFVSTCA9PT0gXCJmdW5jdGlvblwiICYmIGEgaW5zdGFuY2VvZiBVUkwgJiYgYiBpbnN0YW5jZW9mIFVSTCkge1xuXHRcdHJldHVybiBhLmhyZWYgPT09IGIuaHJlZjtcblx0fVxuXHRpZiAoT2JqZWN0LmlzKGEsIGIpKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0Ly8gQSBzdHJpY3QgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkgYmVjYXVzZSBgbnVsbCA9PSB1bmRlZmluZWRgLlxuXHRpZiAoYSA9PT0gbnVsbCB8fCBiID09PSBudWxsKSB7XG5cdFx0cmV0dXJuIGEgPT09IGI7XG5cdH1cblx0Y29uc3QgY2xhc3NOYW1lID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGEpO1xuXHRpZiAoY2xhc3NOYW1lICE9PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYikpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0c3dpdGNoIChjbGFzc05hbWUpIHtcblx0XHRjYXNlIFwiW29iamVjdCBCb29sZWFuXVwiOlxuXHRcdGNhc2UgXCJbb2JqZWN0IFN0cmluZ11cIjpcblx0XHRjYXNlIFwiW29iamVjdCBOdW1iZXJdXCI6IGlmICh0eXBlb2YgYSAhPT0gdHlwZW9mIGIpIHtcblx0XHRcdC8vIE9uZSBpcyBhIHByaW1pdGl2ZSwgb25lIGEgYG5ldyBQcmltaXRpdmUoKWBcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9IGVsc2UgaWYgKHR5cGVvZiBhICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBiICE9PSBcIm9iamVjdFwiKSB7XG5cdFx0XHQvLyBib3RoIGFyZSBwcm9wZXIgcHJpbWl0aXZlc1xuXHRcdFx0cmV0dXJuIE9iamVjdC5pcyhhLCBiKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gYm90aCBhcmUgYG5ldyBQcmltaXRpdmUoKWBzXG5cdFx0XHRyZXR1cm4gT2JqZWN0LmlzKGEudmFsdWVPZigpLCBiLnZhbHVlT2YoKSk7XG5cdFx0fVxuXHRcdGNhc2UgXCJbb2JqZWN0IERhdGVdXCI6IHtcblx0XHRcdGNvbnN0IG51bUEgPSArYTtcblx0XHRcdGNvbnN0IG51bUIgPSArYjtcblx0XHRcdC8vIENvZXJjZSBkYXRlcyB0byBudW1lcmljIHByaW1pdGl2ZSB2YWx1ZXMuIERhdGVzIGFyZSBjb21wYXJlZCBieSB0aGVpclxuXHRcdFx0Ly8gbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zLiBOb3RlIHRoYXQgaW52YWxpZCBkYXRlcyB3aXRoIG1pbGxpc2Vjb25kIHJlcHJlc2VudGF0aW9uc1xuXHRcdFx0Ly8gb2YgYE5hTmAgYXJlIGVxdWl2YWxlbnQuXG5cdFx0XHRyZXR1cm4gbnVtQSA9PT0gbnVtQiB8fCBOdW1iZXIuaXNOYU4obnVtQSkgJiYgTnVtYmVyLmlzTmFOKG51bUIpO1xuXHRcdH1cblx0XHRjYXNlIFwiW29iamVjdCBSZWdFeHBdXCI6IHJldHVybiBhLnNvdXJjZSA9PT0gYi5zb3VyY2UgJiYgYS5mbGFncyA9PT0gYi5mbGFncztcblx0XHRjYXNlIFwiW29iamVjdCBUZW1wb3JhbC5JbnN0YW50XVwiOlxuXHRcdGNhc2UgXCJbb2JqZWN0IFRlbXBvcmFsLlpvbmVkRGF0ZVRpbWVdXCI6XG5cdFx0Y2FzZSBcIltvYmplY3QgVGVtcG9yYWwuUGxhaW5EYXRlVGltZV1cIjpcblx0XHRjYXNlIFwiW29iamVjdCBUZW1wb3JhbC5QbGFpbkRhdGVdXCI6XG5cdFx0Y2FzZSBcIltvYmplY3QgVGVtcG9yYWwuUGxhaW5UaW1lXVwiOlxuXHRcdGNhc2UgXCJbb2JqZWN0IFRlbXBvcmFsLlBsYWluWWVhck1vbnRoXVwiOlxuXHRcdGNhc2UgXCJbb2JqZWN0IFRlbXBvcmFsLlBsYWluTW9udGhEYXldXCI6IHJldHVybiBhLmVxdWFscyhiKTtcblx0XHRjYXNlIFwiW29iamVjdCBUZW1wb3JhbC5EdXJhdGlvbl1cIjogcmV0dXJuIGEudG9TdHJpbmcoKSA9PT0gYi50b1N0cmluZygpO1xuXHR9XG5cdGlmICh0eXBlb2YgYSAhPT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgYiAhPT0gXCJvYmplY3RcIikge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHQvLyBVc2UgRE9NMyBtZXRob2QgaXNFcXVhbE5vZGUgKElFPj05KVxuXHRpZiAoaXNEb21Ob2RlKGEpICYmIGlzRG9tTm9kZShiKSkge1xuXHRcdHJldHVybiBhLmlzRXF1YWxOb2RlKGIpO1xuXHR9XG5cdC8vIFVzZWQgdG8gZGV0ZWN0IGNpcmN1bGFyIHJlZmVyZW5jZXMuXG5cdGxldCBsZW5ndGggPSBhU3RhY2subGVuZ3RoO1xuXHR3aGlsZSAobGVuZ3RoLS0pIHtcblx0XHQvLyBMaW5lYXIgc2VhcmNoLiBQZXJmb3JtYW5jZSBpcyBpbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2Zcblx0XHQvLyB1bmlxdWUgbmVzdGVkIHN0cnVjdHVyZXMuXG5cdFx0Ly8gY2lyY3VsYXIgcmVmZXJlbmNlcyBhdCBzYW1lIGRlcHRoIGFyZSBlcXVhbFxuXHRcdC8vIGNpcmN1bGFyIHJlZmVyZW5jZSBpcyBub3QgZXF1YWwgdG8gbm9uLWNpcmN1bGFyIG9uZVxuXHRcdGlmIChhU3RhY2tbbGVuZ3RoXSA9PT0gYSkge1xuXHRcdFx0cmV0dXJuIGJTdGFja1tsZW5ndGhdID09PSBiO1xuXHRcdH0gZWxzZSBpZiAoYlN0YWNrW2xlbmd0aF0gPT09IGIpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblx0Ly8gQWRkIHRoZSBmaXJzdCBvYmplY3QgdG8gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuXHRhU3RhY2sucHVzaChhKTtcblx0YlN0YWNrLnB1c2goYik7XG5cdC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyBhbmQgYXJyYXlzLlxuXHQvLyBDb21wYXJlIGFycmF5IGxlbmd0aHMgdG8gZGV0ZXJtaW5lIGlmIGEgZGVlcCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeS5cblx0aWYgKGNsYXNzTmFtZSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiICYmIGEubGVuZ3RoICE9PSBiLmxlbmd0aCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRpZiAoaXNFcnJvcihhKSAmJiBpc0Vycm9yKGIpKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHJldHVybiBpc0Vycm9yRXF1YWwoYSwgYiwgYVN0YWNrLCBiU3RhY2ssIGN1c3RvbVRlc3RlcnMsIGhhc0tleSk7XG5cdFx0fSBmaW5hbGx5IHtcblx0XHRcdGFTdGFjay5wb3AoKTtcblx0XHRcdGJTdGFjay5wb3AoKTtcblx0XHR9XG5cdH1cblx0Ly8gRGVlcCBjb21wYXJlIG9iamVjdHMuXG5cdGNvbnN0IGFLZXlzID0ga2V5cyhhLCBoYXNLZXkpO1xuXHRsZXQga2V5O1xuXHRsZXQgc2l6ZSA9IGFLZXlzLmxlbmd0aDtcblx0Ly8gRW5zdXJlIHRoYXQgYm90aCBvYmplY3RzIGNvbnRhaW4gdGhlIHNhbWUgbnVtYmVyIG9mIHByb3BlcnRpZXMgYmVmb3JlIGNvbXBhcmluZyBkZWVwIGVxdWFsaXR5LlxuXHRpZiAoa2V5cyhiLCBoYXNLZXkpLmxlbmd0aCAhPT0gc2l6ZSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHR3aGlsZSAoc2l6ZS0tKSB7XG5cdFx0a2V5ID0gYUtleXNbc2l6ZV07XG5cdFx0Ly8gRGVlcCBjb21wYXJlIGVhY2ggbWVtYmVyXG5cdFx0cmVzdWx0ID0gaGFzS2V5KGIsIGtleSkgJiYgZXEoYVtrZXldLCBiW2tleV0sIGFTdGFjaywgYlN0YWNrLCBjdXN0b21UZXN0ZXJzLCBoYXNLZXkpO1xuXHRcdGlmICghcmVzdWx0KSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cdC8vIFJlbW92ZSB0aGUgZmlyc3Qgb2JqZWN0IGZyb20gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuXHRhU3RhY2sucG9wKCk7XG5cdGJTdGFjay5wb3AoKTtcblx0cmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGlzRXJyb3JFcXVhbChhLCBiLCBhU3RhY2ssIGJTdGFjaywgY3VzdG9tVGVzdGVycywgaGFzS2V5KSB7XG5cdC8vIGh0dHBzOi8vbm9kZWpzLm9yZy9kb2NzL2xhdGVzdC12MjIueC9hcGkvYXNzZXJ0Lmh0bWwjY29tcGFyaXNvbi1kZXRhaWxzXG5cdC8vIC0gW1tQcm90b3R5cGVdXSBvZiBvYmplY3RzIGFyZSBjb21wYXJlZCB1c2luZyB0aGUgPT09IG9wZXJhdG9yLlxuXHQvLyAtIE9ubHkgZW51bWVyYWJsZSBcIm93blwiIHByb3BlcnRpZXMgYXJlIGNvbnNpZGVyZWQuXG5cdC8vIC0gRXJyb3IgbmFtZXMsIG1lc3NhZ2VzLCBjYXVzZXMsIGFuZCBlcnJvcnMgYXJlIGFsd2F5cyBjb21wYXJlZCwgZXZlbiBpZiB0aGVzZSBhcmUgbm90IGVudW1lcmFibGUgcHJvcGVydGllcy4gZXJyb3JzIGlzIGFsc28gY29tcGFyZWQuXG5cdGxldCByZXN1bHQgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYSkgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChiKSAmJiBhLm5hbWUgPT09IGIubmFtZSAmJiBhLm1lc3NhZ2UgPT09IGIubWVzc2FnZTtcblx0Ly8gY2hlY2sgRXJyb3IuY2F1c2UgYXN5bW1ldHJpY2FsbHlcblx0aWYgKHR5cGVvZiBiLmNhdXNlICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0cmVzdWx0ICYmPSBlcShhLmNhdXNlLCBiLmNhdXNlLCBhU3RhY2ssIGJTdGFjaywgY3VzdG9tVGVzdGVycywgaGFzS2V5KTtcblx0fVxuXHQvLyBBZ2dyZWdhdGVFcnJvci5lcnJvcnNcblx0aWYgKGEgaW5zdGFuY2VvZiBBZ2dyZWdhdGVFcnJvciAmJiBiIGluc3RhbmNlb2YgQWdncmVnYXRlRXJyb3IpIHtcblx0XHRyZXN1bHQgJiY9IGVxKGEuZXJyb3JzLCBiLmVycm9ycywgYVN0YWNrLCBiU3RhY2ssIGN1c3RvbVRlc3RlcnMsIGhhc0tleSk7XG5cdH1cblx0Ly8gc3ByZWFkIHRvIGNvbXBhcmUgZW51bWVyYWJsZSBwcm9wZXJ0aWVzXG5cdHJlc3VsdCAmJj0gZXEoeyAuLi5hIH0sIHsgLi4uYiB9LCBhU3RhY2ssIGJTdGFjaywgY3VzdG9tVGVzdGVycywgaGFzS2V5KTtcblx0cmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGtleXMob2JqLCBoYXNLZXkpIHtcblx0Y29uc3Qga2V5cyA9IFtdO1xuXHRmb3IgKGNvbnN0IGtleSBpbiBvYmopIHtcblx0XHRpZiAoaGFzS2V5KG9iaiwga2V5KSkge1xuXHRcdFx0a2V5cy5wdXNoKGtleSk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBrZXlzLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikuZmlsdGVyKChzeW1ib2wpID0+IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqLCBzeW1ib2wpLmVudW1lcmFibGUpKTtcbn1cbmZ1bmN0aW9uIGhhc0RlZmluZWRLZXkob2JqLCBrZXkpIHtcblx0cmV0dXJuIGhhc0tleShvYmosIGtleSkgJiYgb2JqW2tleV0gIT09IHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGhhc0tleShvYmosIGtleSkge1xuXHRyZXR1cm4gT2JqZWN0Lmhhc093bihvYmosIGtleSk7XG59XG5mdW5jdGlvbiBpc0EodHlwZU5hbWUsIHZhbHVlKSB7XG5cdHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmFwcGx5KHZhbHVlKSA9PT0gYFtvYmplY3QgJHt0eXBlTmFtZX1dYDtcbn1cbmZ1bmN0aW9uIGlzRG9tTm9kZShvYmopIHtcblx0cmV0dXJuIG9iaiAhPT0gbnVsbCAmJiB0eXBlb2Ygb2JqID09PSBcIm9iamVjdFwiICYmIFwibm9kZVR5cGVcIiBpbiBvYmogJiYgdHlwZW9mIG9iai5ub2RlVHlwZSA9PT0gXCJudW1iZXJcIiAmJiBcIm5vZGVOYW1lXCIgaW4gb2JqICYmIHR5cGVvZiBvYmoubm9kZU5hbWUgPT09IFwic3RyaW5nXCIgJiYgXCJpc0VxdWFsTm9kZVwiIGluIG9iaiAmJiB0eXBlb2Ygb2JqLmlzRXF1YWxOb2RlID09PSBcImZ1bmN0aW9uXCI7XG59XG5mdW5jdGlvbiBmbk5hbWVGb3IoZnVuYykge1xuXHRpZiAoZnVuYy5uYW1lKSB7XG5cdFx0cmV0dXJuIGZ1bmMubmFtZTtcblx0fVxuXHRjb25zdCBtYXRjaGVzID0gZnVuY3Rpb25Ub1N0cmluZy5jYWxsKGZ1bmMpLm1hdGNoKC9eKD86YXN5bmMpP1xccypmdW5jdGlvblxccyooPzpcXCpcXHMqKT8oW1xcdyRdKylcXHMqXFwoLyk7XG5cdHJldHVybiBtYXRjaGVzID8gbWF0Y2hlc1sxXSA6IFwiPGFub255bW91cz5cIjtcbn1cbmZ1bmN0aW9uIGdldFByb3RvdHlwZShvYmopIHtcblx0aWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuXHRcdHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqKTtcblx0fVxuXHRpZiAob2JqLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gb2JqKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0cmV0dXJuIG9iai5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG59XG5mdW5jdGlvbiBoYXNQcm9wZXJ0eShvYmosIHByb3BlcnR5KSB7XG5cdGlmICghb2JqKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cdGlmIChPYmplY3QuaGFzT3duKG9iaiwgcHJvcGVydHkpKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0cmV0dXJuIGhhc1Byb3BlcnR5KGdldFByb3RvdHlwZShvYmopLCBwcm9wZXJ0eSk7XG59XG4vLyBTRU5USU5FTCBjb25zdGFudHMgYXJlIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL2ltbXV0YWJsZS1qc1xuY29uc3QgSVNfS0VZRURfU0VOVElORUwgPSBcIkBAX19JTU1VVEFCTEVfS0VZRURfX0BAXCI7XG5jb25zdCBJU19TRVRfU0VOVElORUwgPSBcIkBAX19JTU1VVEFCTEVfU0VUX19AQFwiO1xuY29uc3QgSVNfTElTVF9TRU5USU5FTCA9IFwiQEBfX0lNTVVUQUJMRV9MSVNUX19AQFwiO1xuY29uc3QgSVNfT1JERVJFRF9TRU5USU5FTCA9IFwiQEBfX0lNTVVUQUJMRV9PUkRFUkVEX19AQFwiO1xuY29uc3QgSVNfUkVDT1JEX1NZTUJPTCA9IFwiQEBfX0lNTVVUQUJMRV9SRUNPUkRfX0BAXCI7XG5mdW5jdGlvbiBpc0ltbXV0YWJsZVVub3JkZXJlZEtleWVkKG1heWJlS2V5ZWQpIHtcblx0cmV0dXJuICEhKG1heWJlS2V5ZWQgJiYgbWF5YmVLZXllZFtJU19LRVlFRF9TRU5USU5FTF0gJiYgIW1heWJlS2V5ZWRbSVNfT1JERVJFRF9TRU5USU5FTF0pO1xufVxuZnVuY3Rpb24gaXNJbW11dGFibGVVbm9yZGVyZWRTZXQobWF5YmVTZXQpIHtcblx0cmV0dXJuICEhKG1heWJlU2V0ICYmIG1heWJlU2V0W0lTX1NFVF9TRU5USU5FTF0gJiYgIW1heWJlU2V0W0lTX09SREVSRURfU0VOVElORUxdKTtcbn1cbmZ1bmN0aW9uIGlzT2JqZWN0TGl0ZXJhbChzb3VyY2UpIHtcblx0cmV0dXJuIHNvdXJjZSAhPSBudWxsICYmIHR5cGVvZiBzb3VyY2UgPT09IFwib2JqZWN0XCIgJiYgIUFycmF5LmlzQXJyYXkoc291cmNlKTtcbn1cbmZ1bmN0aW9uIGlzSW1tdXRhYmxlTGlzdChzb3VyY2UpIHtcblx0cmV0dXJuIEJvb2xlYW4oc291cmNlICYmIGlzT2JqZWN0TGl0ZXJhbChzb3VyY2UpICYmIHNvdXJjZVtJU19MSVNUX1NFTlRJTkVMXSk7XG59XG5mdW5jdGlvbiBpc0ltbXV0YWJsZU9yZGVyZWRLZXllZChzb3VyY2UpIHtcblx0cmV0dXJuIEJvb2xlYW4oc291cmNlICYmIGlzT2JqZWN0TGl0ZXJhbChzb3VyY2UpICYmIHNvdXJjZVtJU19LRVlFRF9TRU5USU5FTF0gJiYgc291cmNlW0lTX09SREVSRURfU0VOVElORUxdKTtcbn1cbmZ1bmN0aW9uIGlzSW1tdXRhYmxlT3JkZXJlZFNldChzb3VyY2UpIHtcblx0cmV0dXJuIEJvb2xlYW4oc291cmNlICYmIGlzT2JqZWN0TGl0ZXJhbChzb3VyY2UpICYmIHNvdXJjZVtJU19TRVRfU0VOVElORUxdICYmIHNvdXJjZVtJU19PUkRFUkVEX1NFTlRJTkVMXSk7XG59XG5mdW5jdGlvbiBpc0ltbXV0YWJsZVJlY29yZChzb3VyY2UpIHtcblx0cmV0dXJuIEJvb2xlYW4oc291cmNlICYmIGlzT2JqZWN0TGl0ZXJhbChzb3VyY2UpICYmIHNvdXJjZVtJU19SRUNPUkRfU1lNQk9MXSk7XG59XG4vKipcbiogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qXG4qL1xuY29uc3QgSXRlcmF0b3JTeW1ib2wgPSBTeW1ib2wuaXRlcmF0b3I7XG5mdW5jdGlvbiBoYXNJdGVyYXRvcihvYmplY3QpIHtcblx0cmV0dXJuICEhKG9iamVjdCAhPSBudWxsICYmIG9iamVjdFtJdGVyYXRvclN5bWJvbF0pO1xufVxuZnVuY3Rpb24gaXRlcmFibGVFcXVhbGl0eShhLCBiLCBjdXN0b21UZXN0ZXJzID0gW10sIGFTdGFjayA9IFtdLCBiU3RhY2sgPSBbXSkge1xuXHRpZiAodHlwZW9mIGEgIT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGIgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShhKSB8fCBBcnJheS5pc0FycmF5KGIpIHx8ICFoYXNJdGVyYXRvcihhKSB8fCAhaGFzSXRlcmF0b3IoYikpIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cdGlmIChhLmNvbnN0cnVjdG9yICE9PSBiLmNvbnN0cnVjdG9yKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cdGxldCBsZW5ndGggPSBhU3RhY2subGVuZ3RoO1xuXHR3aGlsZSAobGVuZ3RoLS0pIHtcblx0XHQvLyBMaW5lYXIgc2VhcmNoLiBQZXJmb3JtYW5jZSBpcyBpbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2Zcblx0XHQvLyB1bmlxdWUgbmVzdGVkIHN0cnVjdHVyZXMuXG5cdFx0Ly8gY2lyY3VsYXIgcmVmZXJlbmNlcyBhdCBzYW1lIGRlcHRoIGFyZSBlcXVhbFxuXHRcdC8vIGNpcmN1bGFyIHJlZmVyZW5jZSBpcyBub3QgZXF1YWwgdG8gbm9uLWNpcmN1bGFyIG9uZVxuXHRcdGlmIChhU3RhY2tbbGVuZ3RoXSA9PT0gYSkge1xuXHRcdFx0cmV0dXJuIGJTdGFja1tsZW5ndGhdID09PSBiO1xuXHRcdH1cblx0fVxuXHRhU3RhY2sucHVzaChhKTtcblx0YlN0YWNrLnB1c2goYik7XG5cdGNvbnN0IGZpbHRlcmVkQ3VzdG9tVGVzdGVycyA9IFsuLi5jdXN0b21UZXN0ZXJzLmZpbHRlcigodCkgPT4gdCAhPT0gaXRlcmFibGVFcXVhbGl0eSksIGl0ZXJhYmxlRXF1YWxpdHlXaXRoU3RhY2tdO1xuXHRmdW5jdGlvbiBpdGVyYWJsZUVxdWFsaXR5V2l0aFN0YWNrKGEsIGIpIHtcblx0XHRyZXR1cm4gaXRlcmFibGVFcXVhbGl0eShhLCBiLCBbLi4uY3VzdG9tVGVzdGVyc10sIFsuLi5hU3RhY2tdLCBbLi4uYlN0YWNrXSk7XG5cdH1cblx0aWYgKGEuc2l6ZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0aWYgKGEuc2l6ZSAhPT0gYi5zaXplKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSBlbHNlIGlmIChpc0EoXCJTZXRcIiwgYSkgfHwgaXNJbW11dGFibGVVbm9yZGVyZWRTZXQoYSkpIHtcblx0XHRcdGxldCBhbGxGb3VuZCA9IHRydWU7XG5cdFx0XHRmb3IgKGNvbnN0IGFWYWx1ZSBvZiBhKSB7XG5cdFx0XHRcdGlmICghYi5oYXMoYVZhbHVlKSkge1xuXHRcdFx0XHRcdGxldCBoYXMgPSBmYWxzZTtcblx0XHRcdFx0XHRmb3IgKGNvbnN0IGJWYWx1ZSBvZiBiKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBpc0VxdWFsID0gZXF1YWxzKGFWYWx1ZSwgYlZhbHVlLCBmaWx0ZXJlZEN1c3RvbVRlc3RlcnMpO1xuXHRcdFx0XHRcdFx0aWYgKGlzRXF1YWwgPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFx0aGFzID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKGhhcyA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdGFsbEZvdW5kID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdC8vIFJlbW92ZSB0aGUgZmlyc3QgdmFsdWUgZnJvbSB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIHZhbHVlcy5cblx0XHRcdGFTdGFjay5wb3AoKTtcblx0XHRcdGJTdGFjay5wb3AoKTtcblx0XHRcdHJldHVybiBhbGxGb3VuZDtcblx0XHR9IGVsc2UgaWYgKGlzQShcIk1hcFwiLCBhKSB8fCBpc0ltbXV0YWJsZVVub3JkZXJlZEtleWVkKGEpKSB7XG5cdFx0XHRsZXQgYWxsRm91bmQgPSB0cnVlO1xuXHRcdFx0Zm9yIChjb25zdCBhRW50cnkgb2YgYSkge1xuXHRcdFx0XHRpZiAoIWIuaGFzKGFFbnRyeVswXSkgfHwgIWVxdWFscyhhRW50cnlbMV0sIGIuZ2V0KGFFbnRyeVswXSksIGZpbHRlcmVkQ3VzdG9tVGVzdGVycykpIHtcblx0XHRcdFx0XHRsZXQgaGFzID0gZmFsc2U7XG5cdFx0XHRcdFx0Zm9yIChjb25zdCBiRW50cnkgb2YgYikge1xuXHRcdFx0XHRcdFx0Y29uc3QgbWF0Y2hlZEtleSA9IGVxdWFscyhhRW50cnlbMF0sIGJFbnRyeVswXSwgZmlsdGVyZWRDdXN0b21UZXN0ZXJzKTtcblx0XHRcdFx0XHRcdGxldCBtYXRjaGVkVmFsdWUgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGlmIChtYXRjaGVkS2V5ID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0XHRcdG1hdGNoZWRWYWx1ZSA9IGVxdWFscyhhRW50cnlbMV0sIGJFbnRyeVsxXSwgZmlsdGVyZWRDdXN0b21UZXN0ZXJzKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChtYXRjaGVkVmFsdWUgPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFx0aGFzID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKGhhcyA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdGFsbEZvdW5kID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdC8vIFJlbW92ZSB0aGUgZmlyc3QgdmFsdWUgZnJvbSB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIHZhbHVlcy5cblx0XHRcdGFTdGFjay5wb3AoKTtcblx0XHRcdGJTdGFjay5wb3AoKTtcblx0XHRcdHJldHVybiBhbGxGb3VuZDtcblx0XHR9XG5cdH1cblx0Y29uc3QgYkl0ZXJhdG9yID0gYltJdGVyYXRvclN5bWJvbF0oKTtcblx0Zm9yIChjb25zdCBhVmFsdWUgb2YgYSkge1xuXHRcdGNvbnN0IG5leHRCID0gYkl0ZXJhdG9yLm5leHQoKTtcblx0XHRpZiAobmV4dEIuZG9uZSB8fCAhZXF1YWxzKGFWYWx1ZSwgbmV4dEIudmFsdWUsIGZpbHRlcmVkQ3VzdG9tVGVzdGVycykpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblx0aWYgKCFiSXRlcmF0b3IubmV4dCgpLmRvbmUpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0aWYgKCFpc0ltbXV0YWJsZUxpc3QoYSkgJiYgIWlzSW1tdXRhYmxlT3JkZXJlZEtleWVkKGEpICYmICFpc0ltbXV0YWJsZU9yZGVyZWRTZXQoYSkgJiYgIWlzSW1tdXRhYmxlUmVjb3JkKGEpKSB7XG5cdFx0Y29uc3QgYUVudHJpZXMgPSBPYmplY3QuZW50cmllcyhhKTtcblx0XHRjb25zdCBiRW50cmllcyA9IE9iamVjdC5lbnRyaWVzKGIpO1xuXHRcdGlmICghZXF1YWxzKGFFbnRyaWVzLCBiRW50cmllcywgZmlsdGVyZWRDdXN0b21UZXN0ZXJzKSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXHQvLyBSZW1vdmUgdGhlIGZpcnN0IHZhbHVlIGZyb20gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCB2YWx1ZXMuXG5cdGFTdGFjay5wb3AoKTtcblx0YlN0YWNrLnBvcCgpO1xuXHRyZXR1cm4gdHJ1ZTtcbn1cbi8qKlxuKiBDaGVja3MgaWYgYGhhc093blByb3BlcnR5KG9iamVjdCwga2V5KWAgdXAgdGhlIHByb3RvdHlwZSBjaGFpbiwgc3RvcHBpbmcgYXQgYE9iamVjdC5wcm90b3R5cGVgLlxuKi9cbmZ1bmN0aW9uIGhhc1Byb3BlcnR5SW5PYmplY3Qob2JqZWN0LCBrZXkpIHtcblx0Y29uc3Qgc2hvdWxkVGVybWluYXRlID0gIW9iamVjdCB8fCB0eXBlb2Ygb2JqZWN0ICE9PSBcIm9iamVjdFwiIHx8IG9iamVjdCA9PT0gT2JqZWN0LnByb3RvdHlwZTtcblx0aWYgKHNob3VsZFRlcm1pbmF0ZSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRyZXR1cm4gT2JqZWN0Lmhhc093bihvYmplY3QsIGtleSkgfHwgaGFzUHJvcGVydHlJbk9iamVjdChPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KSwga2V5KTtcbn1cbmZ1bmN0aW9uIGlzT2JqZWN0V2l0aEtleXMoYSkge1xuXHRyZXR1cm4gaXNPYmplY3QoYSkgJiYgIWlzRXJyb3IoYSkgJiYgIUFycmF5LmlzQXJyYXkoYSkgJiYgIShhIGluc3RhbmNlb2YgRGF0ZSkgJiYgIShhIGluc3RhbmNlb2YgU2V0KSAmJiAhKGEgaW5zdGFuY2VvZiBNYXApO1xufVxuZnVuY3Rpb24gc3Vic2V0RXF1YWxpdHkob2JqZWN0LCBzdWJzZXQsIGN1c3RvbVRlc3RlcnMgPSBbXSkge1xuXHRjb25zdCBmaWx0ZXJlZEN1c3RvbVRlc3RlcnMgPSBjdXN0b21UZXN0ZXJzLmZpbHRlcigodCkgPT4gdCAhPT0gc3Vic2V0RXF1YWxpdHkpO1xuXHQvLyBzdWJzZXRFcXVhbGl0eSBuZWVkcyB0byBrZWVwIHRyYWNrIG9mIHRoZSByZWZlcmVuY2VzXG5cdC8vIGl0IGhhcyBhbHJlYWR5IHZpc2l0ZWQgdG8gYXZvaWQgaW5maW5pdGUgbG9vcHMgaW4gY2FzZVxuXHQvLyB0aGVyZSBhcmUgY2lyY3VsYXIgcmVmZXJlbmNlcyBpbiB0aGUgc3Vic2V0IHBhc3NlZCB0byBpdC5cblx0Y29uc3Qgc3Vic2V0RXF1YWxpdHlXaXRoQ29udGV4dCA9IChzZWVuUmVmZXJlbmNlcyA9IG5ldyBXZWFrTWFwKCkpID0+IChvYmplY3QsIHN1YnNldCkgPT4ge1xuXHRcdGlmICghaXNPYmplY3RXaXRoS2V5cyhzdWJzZXQpKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRyZXR1cm4gT2JqZWN0LmtleXMoc3Vic2V0KS5ldmVyeSgoa2V5KSA9PiB7XG5cdFx0XHRpZiAoc3Vic2V0W2tleV0gIT0gbnVsbCAmJiB0eXBlb2Ygc3Vic2V0W2tleV0gPT09IFwib2JqZWN0XCIpIHtcblx0XHRcdFx0aWYgKHNlZW5SZWZlcmVuY2VzLmhhcyhzdWJzZXRba2V5XSkpIHtcblx0XHRcdFx0XHRyZXR1cm4gZXF1YWxzKG9iamVjdFtrZXldLCBzdWJzZXRba2V5XSwgZmlsdGVyZWRDdXN0b21UZXN0ZXJzKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRzZWVuUmVmZXJlbmNlcy5zZXQoc3Vic2V0W2tleV0sIHRydWUpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgcmVzdWx0ID0gb2JqZWN0ICE9IG51bGwgJiYgaGFzUHJvcGVydHlJbk9iamVjdChvYmplY3QsIGtleSkgJiYgZXF1YWxzKG9iamVjdFtrZXldLCBzdWJzZXRba2V5XSwgWy4uLmZpbHRlcmVkQ3VzdG9tVGVzdGVycywgc3Vic2V0RXF1YWxpdHlXaXRoQ29udGV4dChzZWVuUmVmZXJlbmNlcyldKTtcblx0XHRcdC8vIFRoZSBtYWluIGdvYWwgb2YgdXNpbmcgc2VlblJlZmVyZW5jZSBpcyB0byBhdm9pZCBjaXJjdWxhciBub2RlIG9uIHRyZWUuXG5cdFx0XHQvLyBJdCB3aWxsIG9ubHkgaGFwcGVuIHdpdGhpbiBhIHBhcmVudCBhbmQgaXRzIGNoaWxkLCBub3QgYSBub2RlIGFuZCBub2RlcyBuZXh0IHRvIGl0IChzYW1lIGxldmVsKVxuXHRcdFx0Ly8gV2Ugc2hvdWxkIGtlZXAgdGhlIHJlZmVyZW5jZSBmb3IgYSBwYXJlbnQgYW5kIGl0cyBjaGlsZCBvbmx5XG5cdFx0XHQvLyBUaHVzIHdlIHNob3VsZCBkZWxldGUgdGhlIHJlZmVyZW5jZSBpbW1lZGlhdGVseSBzbyB0aGF0IGl0IGRvZXNuJ3QgaW50ZXJmZXJlXG5cdFx0XHQvLyBvdGhlciBub2RlcyB3aXRoaW4gdGhlIHNhbWUgbGV2ZWwgb24gdHJlZS5cblx0XHRcdHNlZW5SZWZlcmVuY2VzLmRlbGV0ZShzdWJzZXRba2V5XSk7XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH0pO1xuXHR9O1xuXHRyZXR1cm4gc3Vic2V0RXF1YWxpdHlXaXRoQ29udGV4dCgpKG9iamVjdCwgc3Vic2V0KTtcbn1cbmZ1bmN0aW9uIHR5cGVFcXVhbGl0eShhLCBiKSB7XG5cdGlmIChhID09IG51bGwgfHwgYiA9PSBudWxsIHx8IGEuY29uc3RydWN0b3IgPT09IGIuY29uc3RydWN0b3IpIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cdHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGFycmF5QnVmZmVyRXF1YWxpdHkoYSwgYikge1xuXHRsZXQgZGF0YVZpZXdBID0gYTtcblx0bGV0IGRhdGFWaWV3QiA9IGI7XG5cdGlmICghKGEgaW5zdGFuY2VvZiBEYXRhVmlldyAmJiBiIGluc3RhbmNlb2YgRGF0YVZpZXcpKSB7XG5cdFx0aWYgKCEoYSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB8fCAhKGIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikpIHtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdHRyeSB7XG5cdFx0XHRkYXRhVmlld0EgPSBuZXcgRGF0YVZpZXcoYSk7XG5cdFx0XHRkYXRhVmlld0IgPSBuZXcgRGF0YVZpZXcoYik7XG5cdFx0fSBjYXRjaCB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHQvLyBCdWZmZXJzIGFyZSBub3QgZXF1YWwgd2hlbiB0aGV5IGRvIG5vdCBoYXZlIHRoZSBzYW1lIGJ5dGUgbGVuZ3RoXG5cdGlmIChkYXRhVmlld0EuYnl0ZUxlbmd0aCAhPT0gZGF0YVZpZXdCLmJ5dGVMZW5ndGgpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0Ly8gQ2hlY2sgaWYgZXZlcnkgYnl0ZSB2YWx1ZSBpcyBlcXVhbCB0byBlYWNoIG90aGVyXG5cdGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YVZpZXdBLmJ5dGVMZW5ndGg7IGkrKykge1xuXHRcdGlmIChkYXRhVmlld0EuZ2V0VWludDgoaSkgIT09IGRhdGFWaWV3Qi5nZXRVaW50OChpKSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gdHJ1ZTtcbn1cbmZ1bmN0aW9uIHNwYXJzZUFycmF5RXF1YWxpdHkoYSwgYiwgY3VzdG9tVGVzdGVycyA9IFtdKSB7XG5cdGlmICghQXJyYXkuaXNBcnJheShhKSB8fCAhQXJyYXkuaXNBcnJheShiKSkge1xuXHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdH1cblx0Ly8gQSBzcGFyc2UgYXJyYXkgWywgLCAxXSB3aWxsIGhhdmUga2V5cyBbXCIyXCJdIHdoZXJlYXMgW3VuZGVmaW5lZCwgdW5kZWZpbmVkLCAxXSB3aWxsIGhhdmUga2V5cyBbXCIwXCIsIFwiMVwiLCBcIjJcIl1cblx0Y29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKTtcblx0Y29uc3QgYktleXMgPSBPYmplY3Qua2V5cyhiKTtcblx0Y29uc3QgZmlsdGVyZWRDdXN0b21UZXN0ZXJzID0gY3VzdG9tVGVzdGVycy5maWx0ZXIoKHQpID0+IHQgIT09IHNwYXJzZUFycmF5RXF1YWxpdHkpO1xuXHRyZXR1cm4gZXF1YWxzKGEsIGIsIGZpbHRlcmVkQ3VzdG9tVGVzdGVycywgdHJ1ZSkgJiYgZXF1YWxzKGFLZXlzLCBiS2V5cyk7XG59XG5mdW5jdGlvbiBnZW5lcmF0ZVRvQmVNZXNzYWdlKGRlZXBFcXVhbGl0eU5hbWUsIGV4cGVjdGVkID0gXCIje3RoaXN9XCIsIGFjdHVhbCA9IFwiI3tleHB9XCIpIHtcblx0Y29uc3QgdG9CZU1lc3NhZ2UgPSBgZXhwZWN0ZWQgJHtleHBlY3RlZH0gdG8gYmUgJHthY3R1YWx9IC8vIE9iamVjdC5pcyBlcXVhbGl0eWA7XG5cdGlmIChbXCJ0b1N0cmljdEVxdWFsXCIsIFwidG9FcXVhbFwiXS5pbmNsdWRlcyhkZWVwRXF1YWxpdHlOYW1lKSkge1xuXHRcdHJldHVybiBgJHt0b0JlTWVzc2FnZX1cXG5cXG5JZiBpdCBzaG91bGQgcGFzcyB3aXRoIGRlZXAgZXF1YWxpdHksIHJlcGxhY2UgXCJ0b0JlXCIgd2l0aCBcIiR7ZGVlcEVxdWFsaXR5TmFtZX1cIlxcblxcbkV4cGVjdGVkOiAke2V4cGVjdGVkfVxcblJlY2VpdmVkOiBzZXJpYWxpemVzIHRvIHRoZSBzYW1lIHN0cmluZ1xcbmA7XG5cdH1cblx0cmV0dXJuIHRvQmVNZXNzYWdlO1xufVxuZnVuY3Rpb24gcGx1cmFsaXplKHdvcmQsIGNvdW50KSB7XG5cdHJldHVybiBgJHtjb3VudH0gJHt3b3JkfSR7Y291bnQgPT09IDEgPyBcIlwiIDogXCJzXCJ9YDtcbn1cbmZ1bmN0aW9uIGdldE9iamVjdEtleXMob2JqZWN0KSB7XG5cdHJldHVybiBbLi4uT2JqZWN0LmtleXMob2JqZWN0KSwgLi4uT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmplY3QpLmZpbHRlcigocykgPT4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHMpPy5lbnVtZXJhYmxlKV07XG59XG5mdW5jdGlvbiBnZXRPYmplY3RTdWJzZXQob2JqZWN0LCBzdWJzZXQsIGN1c3RvbVRlc3RlcnMpIHtcblx0bGV0IHN0cmlwcGVkID0gMDtcblx0Y29uc3QgZ2V0T2JqZWN0U3Vic2V0V2l0aENvbnRleHQgPSAoc2VlblJlZmVyZW5jZXMgPSBuZXcgV2Vha01hcCgpKSA9PiAob2JqZWN0LCBzdWJzZXQpID0+IHtcblx0XHRpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7XG5cdFx0XHRpZiAoQXJyYXkuaXNBcnJheShzdWJzZXQpICYmIHN1YnNldC5sZW5ndGggPT09IG9iamVjdC5sZW5ndGgpIHtcblx0XHRcdFx0Ly8gVGhlIG1hcCBtZXRob2QgcmV0dXJucyBjb3JyZWN0IHN1YmNsYXNzIG9mIHN1YnNldC5cblx0XHRcdFx0cmV0dXJuIHN1YnNldC5tYXAoKHN1YiwgaSkgPT4gZ2V0T2JqZWN0U3Vic2V0V2l0aENvbnRleHQoc2VlblJlZmVyZW5jZXMpKG9iamVjdFtpXSwgc3ViKSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChvYmplY3QgaW5zdGFuY2VvZiBEYXRlKSB7XG5cdFx0XHRyZXR1cm4gb2JqZWN0O1xuXHRcdH0gZWxzZSBpZiAoaXNPYmplY3Qob2JqZWN0KSAmJiBpc09iamVjdChzdWJzZXQpKSB7XG5cdFx0XHRpZiAoZXF1YWxzKG9iamVjdCwgc3Vic2V0LCBbXG5cdFx0XHRcdC4uLmN1c3RvbVRlc3RlcnMsXG5cdFx0XHRcdGl0ZXJhYmxlRXF1YWxpdHksXG5cdFx0XHRcdHN1YnNldEVxdWFsaXR5XG5cdFx0XHRdKSkge1xuXHRcdFx0XHQvLyByZXR1cm4gXCJleHBlY3RlZFwiIHN1YnNldCB0byBhdm9pZCBzaG93aW5nIGlycmVsZXZhbnQgdG9NYXRjaE9iamVjdCBkaWZmXG5cdFx0XHRcdHJldHVybiBzdWJzZXQ7XG5cdFx0XHR9XG5cdFx0XHRjb25zdCB0cmltbWVkID0ge307XG5cdFx0XHRzZWVuUmVmZXJlbmNlcy5zZXQob2JqZWN0LCB0cmltbWVkKTtcblx0XHRcdC8vIHByZXNlcnZlIGNvbnN0cnVjdG9yIGZvciB0b01hdGNoT2JqZWN0IGRpZmZcblx0XHRcdGlmICh0eXBlb2Ygb2JqZWN0LmNvbnN0cnVjdG9yID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIG9iamVjdC5jb25zdHJ1Y3Rvci5uYW1lID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0cmltbWVkLCBcImNvbnN0cnVjdG9yXCIsIHtcblx0XHRcdFx0XHRlbnVtZXJhYmxlOiBmYWxzZSxcblx0XHRcdFx0XHR2YWx1ZTogb2JqZWN0LmNvbnN0cnVjdG9yXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0Zm9yIChjb25zdCBrZXkgb2YgZ2V0T2JqZWN0S2V5cyhvYmplY3QpKSB7XG5cdFx0XHRcdGlmIChoYXNQcm9wZXJ0eUluT2JqZWN0KHN1YnNldCwga2V5KSkge1xuXHRcdFx0XHRcdHRyaW1tZWRba2V5XSA9IHNlZW5SZWZlcmVuY2VzLmhhcyhvYmplY3Rba2V5XSkgPyBzZWVuUmVmZXJlbmNlcy5nZXQob2JqZWN0W2tleV0pIDogZ2V0T2JqZWN0U3Vic2V0V2l0aENvbnRleHQoc2VlblJlZmVyZW5jZXMpKG9iamVjdFtrZXldLCBzdWJzZXRba2V5XSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKCFzZWVuUmVmZXJlbmNlcy5oYXMob2JqZWN0W2tleV0pKSB7XG5cdFx0XHRcdFx0XHRzdHJpcHBlZCArPSAxO1xuXHRcdFx0XHRcdFx0aWYgKGlzT2JqZWN0KG9iamVjdFtrZXldKSkge1xuXHRcdFx0XHRcdFx0XHRzdHJpcHBlZCArPSBnZXRPYmplY3RLZXlzKG9iamVjdFtrZXldKS5sZW5ndGg7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRnZXRPYmplY3RTdWJzZXRXaXRoQ29udGV4dChzZWVuUmVmZXJlbmNlcykob2JqZWN0W2tleV0sIHN1YnNldFtrZXldKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmIChnZXRPYmplY3RLZXlzKHRyaW1tZWQpLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0cmV0dXJuIHRyaW1tZWQ7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBvYmplY3Q7XG5cdH07XG5cdHJldHVybiB7XG5cdFx0c3Vic2V0OiBnZXRPYmplY3RTdWJzZXRXaXRoQ29udGV4dCgpKG9iamVjdCwgc3Vic2V0KSxcblx0XHRzdHJpcHBlZFxuXHR9O1xufVxuLyoqXG4qIERldGVjdHMgaWYgYW4gb2JqZWN0IGlzIGEgU3RhbmRhcmQgU2NoZW1hIFYxIGNvbXBhdGlibGUgc2NoZW1hXG4qL1xuZnVuY3Rpb24gaXNTdGFuZGFyZFNjaGVtYShvYmopIHtcblx0cmV0dXJuICEhb2JqICYmICh0eXBlb2Ygb2JqID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIikgJiYgb2JqW1wifnN0YW5kYXJkXCJdICYmIHR5cGVvZiBvYmpbXCJ+c3RhbmRhcmRcIl0udmFsaWRhdGUgPT09IFwiZnVuY3Rpb25cIjtcbn1cblxuaWYgKCFPYmplY3QuaGFzT3duKGdsb2JhbFRoaXMsIE1BVENIRVJTX09CSkVDVCkpIHtcblx0Y29uc3QgZ2xvYmFsU3RhdGUgPSBuZXcgV2Vha01hcCgpO1xuXHRjb25zdCBtYXRjaGVycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cdGNvbnN0IGN1c3RvbUVxdWFsaXR5VGVzdGVycyA9IFtdO1xuXHRjb25zdCBhc3ltbWV0cmljTWF0Y2hlcnMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZ2xvYmFsVGhpcywgTUFUQ0hFUlNfT0JKRUNULCB7IGdldDogKCkgPT4gZ2xvYmFsU3RhdGUgfSk7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShnbG9iYWxUaGlzLCBKRVNUX01BVENIRVJTX09CSkVDVCwge1xuXHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0XHRnZXQ6ICgpID0+ICh7XG5cdFx0XHRzdGF0ZTogZ2xvYmFsU3RhdGUuZ2V0KGdsb2JhbFRoaXNbR0xPQkFMX0VYUEVDVF0pLFxuXHRcdFx0bWF0Y2hlcnMsXG5cdFx0XHRjdXN0b21FcXVhbGl0eVRlc3RlcnNcblx0XHR9KVxuXHR9KTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGdsb2JhbFRoaXMsIEFTWU1NRVRSSUNfTUFUQ0hFUlNfT0JKRUNULCB7IGdldDogKCkgPT4gYXN5bW1ldHJpY01hdGNoZXJzIH0pO1xufVxuZnVuY3Rpb24gZ2V0U3RhdGUoZXhwZWN0KSB7XG5cdHJldHVybiBnbG9iYWxUaGlzW01BVENIRVJTX09CSkVDVF0uZ2V0KGV4cGVjdCk7XG59XG5mdW5jdGlvbiBzZXRTdGF0ZShzdGF0ZSwgZXhwZWN0KSB7XG5cdGNvbnN0IG1hcCA9IGdsb2JhbFRoaXNbTUFUQ0hFUlNfT0JKRUNUXTtcblx0Y29uc3QgY3VycmVudCA9IG1hcC5nZXQoZXhwZWN0KSB8fCB7fTtcblx0Ly8gc28gaXQga2VlcHMgZ2V0dGVycyBmcm9tIGB0ZXN0UGF0aGBcblx0Y29uc3QgcmVzdWx0cyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGN1cnJlbnQsIHtcblx0XHQuLi5PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhjdXJyZW50KSxcblx0XHQuLi5PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhzdGF0ZSlcblx0fSk7XG5cdG1hcC5zZXQoZXhwZWN0LCByZXN1bHRzKTtcbn1cblxuY2xhc3MgQXN5bW1ldHJpY01hdGNoZXIge1xuXHQvLyBzaG91bGQgaGF2ZSBcImplc3RcIiB0byBiZSBjb21wYXRpYmxlIHdpdGggaXRzIGVjb3N5c3RlbVxuXHQkJHR5cGVvZiA9IFN5bWJvbC5mb3IoXCJqZXN0LmFzeW1tZXRyaWNNYXRjaGVyXCIpO1xuXHRjb25zdHJ1Y3RvcihzYW1wbGUsIGludmVyc2UgPSBmYWxzZSkge1xuXHRcdHRoaXMuc2FtcGxlID0gc2FtcGxlO1xuXHRcdHRoaXMuaW52ZXJzZSA9IGludmVyc2U7XG5cdH1cblx0Z2V0TWF0Y2hlckNvbnRleHQoZXhwZWN0KSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdC4uLmdldFN0YXRlKGV4cGVjdCB8fCBnbG9iYWxUaGlzW0dMT0JBTF9FWFBFQ1RdKSxcblx0XHRcdGVxdWFscyxcblx0XHRcdGlzTm90OiB0aGlzLmludmVyc2UsXG5cdFx0XHRjdXN0b21UZXN0ZXJzOiBnZXRDdXN0b21FcXVhbGl0eVRlc3RlcnMoKSxcblx0XHRcdHV0aWxzOiB7XG5cdFx0XHRcdC4uLmdldE1hdGNoZXJVdGlscygpLFxuXHRcdFx0XHRkaWZmLFxuXHRcdFx0XHRzdHJpbmdpZnksXG5cdFx0XHRcdGl0ZXJhYmxlRXF1YWxpdHksXG5cdFx0XHRcdHN1YnNldEVxdWFsaXR5XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxufVxuLy8gaW1wbGVtZW50IGN1c3RvbSBjaGFpL2xvdXBlIGluc3BlY3QgZm9yIGJldHRlciBBc3NlcnRpb25FcnJvci5tZXNzYWdlIGZvcm1hdHRpbmdcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFpanMvbG91cGUvYmxvYi85YjhhNmRlYWJjZDUwYWRjMDU2YTY0ZmI3MDU4OTYxOTQ3MTBjNWM2L3NyYy9pbmRleC50cyNMMjlcbi8vIEB0cy1leHBlY3QtZXJyb3IgY29tcHV0ZWQgcHJvcGVydGllcyBpcyBub3Qgc3VwcG9ydGVkIHdoZW4gaXNvbGF0ZWREZWNsYXJhdGlvbnMgaXMgZW5hYmxlZFxuLy8gRklYTUU6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvVHlwZVNjcmlwdC9pc3N1ZXMvNjEwNjhcbkFzeW1tZXRyaWNNYXRjaGVyLnByb3RvdHlwZVtTeW1ib2wuZm9yKFwiY2hhaS9pbnNwZWN0XCIpXSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblx0Ly8gbWluaW1hbCBwcmV0dHktZm9ybWF0IHdpdGggc2ltcGxlIG1hbnVhbCB0cnVuY2F0aW9uXG5cdGNvbnN0IHJlc3VsdCA9IHN0cmluZ2lmeSh0aGlzLCBvcHRpb25zLmRlcHRoLCB7IG1pbjogdHJ1ZSB9KTtcblx0aWYgKHJlc3VsdC5sZW5ndGggPD0gb3B0aW9ucy50cnVuY2F0ZSkge1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblx0cmV0dXJuIGAke3RoaXMudG9TdHJpbmcoKX174oCmfWA7XG59O1xuY2xhc3MgU3RyaW5nQ29udGFpbmluZyBleHRlbmRzIEFzeW1tZXRyaWNNYXRjaGVyIHtcblx0Y29uc3RydWN0b3Ioc2FtcGxlLCBpbnZlcnNlID0gZmFsc2UpIHtcblx0XHRpZiAoIWlzQShcIlN0cmluZ1wiLCBzYW1wbGUpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJFeHBlY3RlZCBpcyBub3QgYSBzdHJpbmdcIik7XG5cdFx0fVxuXHRcdHN1cGVyKHNhbXBsZSwgaW52ZXJzZSk7XG5cdH1cblx0YXN5bW1ldHJpY01hdGNoKG90aGVyKSB7XG5cdFx0Y29uc3QgcmVzdWx0ID0gaXNBKFwiU3RyaW5nXCIsIG90aGVyKSAmJiBvdGhlci5pbmNsdWRlcyh0aGlzLnNhbXBsZSk7XG5cdFx0cmV0dXJuIHRoaXMuaW52ZXJzZSA/ICFyZXN1bHQgOiByZXN1bHQ7XG5cdH1cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIGBTdHJpbmcke3RoaXMuaW52ZXJzZSA/IFwiTm90XCIgOiBcIlwifUNvbnRhaW5pbmdgO1xuXHR9XG5cdGdldEV4cGVjdGVkVHlwZSgpIHtcblx0XHRyZXR1cm4gXCJzdHJpbmdcIjtcblx0fVxufVxuY2xhc3MgQW55dGhpbmcgZXh0ZW5kcyBBc3ltbWV0cmljTWF0Y2hlciB7XG5cdGFzeW1tZXRyaWNNYXRjaChvdGhlcikge1xuXHRcdHJldHVybiBvdGhlciAhPSBudWxsO1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiBcIkFueXRoaW5nXCI7XG5cdH1cblx0dG9Bc3ltbWV0cmljTWF0Y2hlcigpIHtcblx0XHRyZXR1cm4gXCJBbnl0aGluZ1wiO1xuXHR9XG59XG5jbGFzcyBPYmplY3RDb250YWluaW5nIGV4dGVuZHMgQXN5bW1ldHJpY01hdGNoZXIge1xuXHRjb25zdHJ1Y3RvcihzYW1wbGUsIGludmVyc2UgPSBmYWxzZSkge1xuXHRcdHN1cGVyKHNhbXBsZSwgaW52ZXJzZSk7XG5cdH1cblx0Z2V0UHJvdG90eXBlKG9iaikge1xuXHRcdGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcblx0XHRcdHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqKTtcblx0XHR9XG5cdFx0aWYgKG9iai5jb25zdHJ1Y3Rvci5wcm90b3R5cGUgPT09IG9iaikge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHRcdHJldHVybiBvYmouY29uc3RydWN0b3IucHJvdG90eXBlO1xuXHR9XG5cdGhhc1Byb3BlcnR5KG9iaiwgcHJvcGVydHkpIHtcblx0XHRpZiAoIW9iaikge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRpZiAoT2JqZWN0Lmhhc093bihvYmosIHByb3BlcnR5KSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmhhc1Byb3BlcnR5KHRoaXMuZ2V0UHJvdG90eXBlKG9iaiksIHByb3BlcnR5KTtcblx0fVxuXHRnZXRQcm9wZXJ0aWVzKG9iaikge1xuXHRcdHJldHVybiBbLi4uT2JqZWN0LmtleXMob2JqKSwgLi4uT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopLmZpbHRlcigocykgPT4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmosIHMpPy5lbnVtZXJhYmxlKV07XG5cdH1cblx0YXN5bW1ldHJpY01hdGNoKG90aGVyLCBjdXN0b21UZXN0ZXJzKSB7XG5cdFx0aWYgKHR5cGVvZiB0aGlzLnNhbXBsZSAhPT0gXCJvYmplY3RcIikge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgWW91IG11c3QgcHJvdmlkZSBhbiBvYmplY3QgdG8gJHt0aGlzLnRvU3RyaW5nKCl9LCBub3QgJyR7dHlwZW9mIHRoaXMuc2FtcGxlfScuYCk7XG5cdFx0fVxuXHRcdGxldCByZXN1bHQgPSB0cnVlO1xuXHRcdGNvbnN0IHByb3BlcnRpZXMgPSB0aGlzLmdldFByb3BlcnRpZXModGhpcy5zYW1wbGUpO1xuXHRcdGZvciAoY29uc3QgcHJvcGVydHkgb2YgcHJvcGVydGllcykge1xuXHRcdFx0aWYgKCF0aGlzLmhhc1Byb3BlcnR5KG90aGVyLCBwcm9wZXJ0eSkpIHtcblx0XHRcdFx0cmVzdWx0ID0gZmFsc2U7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgdmFsdWUgPSB0aGlzLnNhbXBsZVtwcm9wZXJ0eV07XG5cdFx0XHRjb25zdCBvdGhlclZhbHVlID0gb3RoZXJbcHJvcGVydHldO1xuXHRcdFx0aWYgKCFlcXVhbHModmFsdWUsIG90aGVyVmFsdWUsIGN1c3RvbVRlc3RlcnMpKSB7XG5cdFx0XHRcdHJlc3VsdCA9IGZhbHNlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuaW52ZXJzZSA/ICFyZXN1bHQgOiByZXN1bHQ7XG5cdH1cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIGBPYmplY3Qke3RoaXMuaW52ZXJzZSA/IFwiTm90XCIgOiBcIlwifUNvbnRhaW5pbmdgO1xuXHR9XG5cdGdldEV4cGVjdGVkVHlwZSgpIHtcblx0XHRyZXR1cm4gXCJvYmplY3RcIjtcblx0fVxufVxuY2xhc3MgQXJyYXlDb250YWluaW5nIGV4dGVuZHMgQXN5bW1ldHJpY01hdGNoZXIge1xuXHRjb25zdHJ1Y3RvcihzYW1wbGUsIGludmVyc2UgPSBmYWxzZSkge1xuXHRcdHN1cGVyKHNhbXBsZSwgaW52ZXJzZSk7XG5cdH1cblx0YXN5bW1ldHJpY01hdGNoKG90aGVyLCBjdXN0b21UZXN0ZXJzKSB7XG5cdFx0aWYgKCFBcnJheS5pc0FycmF5KHRoaXMuc2FtcGxlKSkge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgWW91IG11c3QgcHJvdmlkZSBhbiBhcnJheSB0byAke3RoaXMudG9TdHJpbmcoKX0sIG5vdCAnJHt0eXBlb2YgdGhpcy5zYW1wbGV9Jy5gKTtcblx0XHR9XG5cdFx0Y29uc3QgcmVzdWx0ID0gdGhpcy5zYW1wbGUubGVuZ3RoID09PSAwIHx8IEFycmF5LmlzQXJyYXkob3RoZXIpICYmIHRoaXMuc2FtcGxlLmV2ZXJ5KChpdGVtKSA9PiBvdGhlci5zb21lKChhbm90aGVyKSA9PiBlcXVhbHMoaXRlbSwgYW5vdGhlciwgY3VzdG9tVGVzdGVycykpKTtcblx0XHRyZXR1cm4gdGhpcy5pbnZlcnNlID8gIXJlc3VsdCA6IHJlc3VsdDtcblx0fVxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYEFycmF5JHt0aGlzLmludmVyc2UgPyBcIk5vdFwiIDogXCJcIn1Db250YWluaW5nYDtcblx0fVxuXHRnZXRFeHBlY3RlZFR5cGUoKSB7XG5cdFx0cmV0dXJuIFwiYXJyYXlcIjtcblx0fVxufVxuY2xhc3MgQW55IGV4dGVuZHMgQXN5bW1ldHJpY01hdGNoZXIge1xuXHRjb25zdHJ1Y3RvcihzYW1wbGUpIHtcblx0XHRpZiAodHlwZW9mIHNhbXBsZSA9PT0gXCJ1bmRlZmluZWRcIikge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihcImFueSgpIGV4cGVjdHMgdG8gYmUgcGFzc2VkIGEgY29uc3RydWN0b3IgZnVuY3Rpb24uIFwiICsgXCJQbGVhc2UgcGFzcyBvbmUgb3IgdXNlIGFueXRoaW5nKCkgdG8gbWF0Y2ggYW55IG9iamVjdC5cIik7XG5cdFx0fVxuXHRcdHN1cGVyKHNhbXBsZSk7XG5cdH1cblx0Zm5OYW1lRm9yKGZ1bmMpIHtcblx0XHRpZiAoZnVuYy5uYW1lKSB7XG5cdFx0XHRyZXR1cm4gZnVuYy5uYW1lO1xuXHRcdH1cblx0XHRjb25zdCBmdW5jdGlvblRvU3RyaW5nID0gRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nO1xuXHRcdGNvbnN0IG1hdGNoZXMgPSBmdW5jdGlvblRvU3RyaW5nLmNhbGwoZnVuYykubWF0Y2goL14oPzphc3luYyk/XFxzKmZ1bmN0aW9uXFxzKig/OlxcKlxccyopPyhbXFx3JF0rKVxccypcXCgvKTtcblx0XHRyZXR1cm4gbWF0Y2hlcyA/IG1hdGNoZXNbMV0gOiBcIjxhbm9ueW1vdXM+XCI7XG5cdH1cblx0YXN5bW1ldHJpY01hdGNoKG90aGVyKSB7XG5cdFx0aWYgKHRoaXMuc2FtcGxlID09PSBTdHJpbmcpIHtcblx0XHRcdHJldHVybiB0eXBlb2Ygb3RoZXIgPT0gXCJzdHJpbmdcIiB8fCBvdGhlciBpbnN0YW5jZW9mIFN0cmluZztcblx0XHR9XG5cdFx0aWYgKHRoaXMuc2FtcGxlID09PSBOdW1iZXIpIHtcblx0XHRcdHJldHVybiB0eXBlb2Ygb3RoZXIgPT0gXCJudW1iZXJcIiB8fCBvdGhlciBpbnN0YW5jZW9mIE51bWJlcjtcblx0XHR9XG5cdFx0aWYgKHRoaXMuc2FtcGxlID09PSBGdW5jdGlvbikge1xuXHRcdFx0cmV0dXJuIHR5cGVvZiBvdGhlciA9PSBcImZ1bmN0aW9uXCIgfHwgdHlwZW9mIG90aGVyID09PSBcImZ1bmN0aW9uXCI7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnNhbXBsZSA9PT0gQm9vbGVhbikge1xuXHRcdFx0cmV0dXJuIHR5cGVvZiBvdGhlciA9PSBcImJvb2xlYW5cIiB8fCBvdGhlciBpbnN0YW5jZW9mIEJvb2xlYW47XG5cdFx0fVxuXHRcdGlmICh0aGlzLnNhbXBsZSA9PT0gQmlnSW50KSB7XG5cdFx0XHRyZXR1cm4gdHlwZW9mIG90aGVyID09IFwiYmlnaW50XCIgfHwgb3RoZXIgaW5zdGFuY2VvZiBCaWdJbnQ7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnNhbXBsZSA9PT0gU3ltYm9sKSB7XG5cdFx0XHRyZXR1cm4gdHlwZW9mIG90aGVyID09IFwic3ltYm9sXCIgfHwgb3RoZXIgaW5zdGFuY2VvZiBTeW1ib2w7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnNhbXBsZSA9PT0gT2JqZWN0KSB7XG5cdFx0XHRyZXR1cm4gdHlwZW9mIG90aGVyID09IFwib2JqZWN0XCI7XG5cdFx0fVxuXHRcdHJldHVybiBvdGhlciBpbnN0YW5jZW9mIHRoaXMuc2FtcGxlO1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiBcIkFueVwiO1xuXHR9XG5cdGdldEV4cGVjdGVkVHlwZSgpIHtcblx0XHRpZiAodGhpcy5zYW1wbGUgPT09IFN0cmluZykge1xuXHRcdFx0cmV0dXJuIFwic3RyaW5nXCI7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnNhbXBsZSA9PT0gTnVtYmVyKSB7XG5cdFx0XHRyZXR1cm4gXCJudW1iZXJcIjtcblx0XHR9XG5cdFx0aWYgKHRoaXMuc2FtcGxlID09PSBGdW5jdGlvbikge1xuXHRcdFx0cmV0dXJuIFwiZnVuY3Rpb25cIjtcblx0XHR9XG5cdFx0aWYgKHRoaXMuc2FtcGxlID09PSBPYmplY3QpIHtcblx0XHRcdHJldHVybiBcIm9iamVjdFwiO1xuXHRcdH1cblx0XHRpZiAodGhpcy5zYW1wbGUgPT09IEJvb2xlYW4pIHtcblx0XHRcdHJldHVybiBcImJvb2xlYW5cIjtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZm5OYW1lRm9yKHRoaXMuc2FtcGxlKTtcblx0fVxuXHR0b0FzeW1tZXRyaWNNYXRjaGVyKCkge1xuXHRcdHJldHVybiBgQW55PCR7dGhpcy5mbk5hbWVGb3IodGhpcy5zYW1wbGUpfT5gO1xuXHR9XG59XG5jbGFzcyBTdHJpbmdNYXRjaGluZyBleHRlbmRzIEFzeW1tZXRyaWNNYXRjaGVyIHtcblx0Y29uc3RydWN0b3Ioc2FtcGxlLCBpbnZlcnNlID0gZmFsc2UpIHtcblx0XHRpZiAoIWlzQShcIlN0cmluZ1wiLCBzYW1wbGUpICYmICFpc0EoXCJSZWdFeHBcIiwgc2FtcGxlKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiRXhwZWN0ZWQgaXMgbm90IGEgU3RyaW5nIG9yIGEgUmVnRXhwXCIpO1xuXHRcdH1cblx0XHRzdXBlcihuZXcgUmVnRXhwKHNhbXBsZSksIGludmVyc2UpO1xuXHR9XG5cdGFzeW1tZXRyaWNNYXRjaChvdGhlcikge1xuXHRcdGNvbnN0IHJlc3VsdCA9IGlzQShcIlN0cmluZ1wiLCBvdGhlcikgJiYgdGhpcy5zYW1wbGUudGVzdChvdGhlcik7XG5cdFx0cmV0dXJuIHRoaXMuaW52ZXJzZSA/ICFyZXN1bHQgOiByZXN1bHQ7XG5cdH1cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIGBTdHJpbmcke3RoaXMuaW52ZXJzZSA/IFwiTm90XCIgOiBcIlwifU1hdGNoaW5nYDtcblx0fVxuXHRnZXRFeHBlY3RlZFR5cGUoKSB7XG5cdFx0cmV0dXJuIFwic3RyaW5nXCI7XG5cdH1cbn1cbmNsYXNzIENsb3NlVG8gZXh0ZW5kcyBBc3ltbWV0cmljTWF0Y2hlciB7XG5cdHByZWNpc2lvbjtcblx0Y29uc3RydWN0b3Ioc2FtcGxlLCBwcmVjaXNpb24gPSAyLCBpbnZlcnNlID0gZmFsc2UpIHtcblx0XHRpZiAoIWlzQShcIk51bWJlclwiLCBzYW1wbGUpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJFeHBlY3RlZCBpcyBub3QgYSBOdW1iZXJcIik7XG5cdFx0fVxuXHRcdGlmICghaXNBKFwiTnVtYmVyXCIsIHByZWNpc2lvbikpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlByZWNpc2lvbiBpcyBub3QgYSBOdW1iZXJcIik7XG5cdFx0fVxuXHRcdHN1cGVyKHNhbXBsZSk7XG5cdFx0dGhpcy5pbnZlcnNlID0gaW52ZXJzZTtcblx0XHR0aGlzLnByZWNpc2lvbiA9IHByZWNpc2lvbjtcblx0fVxuXHRhc3ltbWV0cmljTWF0Y2gob3RoZXIpIHtcblx0XHRpZiAoIWlzQShcIk51bWJlclwiLCBvdGhlcikpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0bGV0IHJlc3VsdCA9IGZhbHNlO1xuXHRcdGlmIChvdGhlciA9PT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZICYmIHRoaXMuc2FtcGxlID09PSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpIHtcblx0XHRcdHJlc3VsdCA9IHRydWU7XG5cdFx0fSBlbHNlIGlmIChvdGhlciA9PT0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZICYmIHRoaXMuc2FtcGxlID09PSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkpIHtcblx0XHRcdHJlc3VsdCA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlc3VsdCA9IE1hdGguYWJzKHRoaXMuc2FtcGxlIC0gb3RoZXIpIDwgMTAgKiogLXRoaXMucHJlY2lzaW9uIC8gMjtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuaW52ZXJzZSA/ICFyZXN1bHQgOiByZXN1bHQ7XG5cdH1cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIGBOdW1iZXIke3RoaXMuaW52ZXJzZSA/IFwiTm90XCIgOiBcIlwifUNsb3NlVG9gO1xuXHR9XG5cdGdldEV4cGVjdGVkVHlwZSgpIHtcblx0XHRyZXR1cm4gXCJudW1iZXJcIjtcblx0fVxuXHR0b0FzeW1tZXRyaWNNYXRjaGVyKCkge1xuXHRcdHJldHVybiBbXG5cdFx0XHR0aGlzLnRvU3RyaW5nKCksXG5cdFx0XHR0aGlzLnNhbXBsZSxcblx0XHRcdGAoJHtwbHVyYWxpemUoXCJkaWdpdFwiLCB0aGlzLnByZWNpc2lvbil9KWBcblx0XHRdLmpvaW4oXCIgXCIpO1xuXHR9XG59XG5jbGFzcyBTY2hlbWFNYXRjaGluZyBleHRlbmRzIEFzeW1tZXRyaWNNYXRjaGVyIHtcblx0cmVzdWx0O1xuXHRjb25zdHJ1Y3RvcihzYW1wbGUsIGludmVyc2UgPSBmYWxzZSkge1xuXHRcdGlmICghaXNTdGFuZGFyZFNjaGVtYShzYW1wbGUpKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKFwiU2NoZW1hTWF0Y2hpbmcgZXhwZWN0ZWQgdG8gcmVjZWl2ZSBhIFN0YW5kYXJkIFNjaGVtYS5cIik7XG5cdFx0fVxuXHRcdHN1cGVyKHNhbXBsZSwgaW52ZXJzZSk7XG5cdH1cblx0YXN5bW1ldHJpY01hdGNoKG90aGVyKSB7XG5cdFx0Y29uc3QgcmVzdWx0ID0gdGhpcy5zYW1wbGVbXCJ+c3RhbmRhcmRcIl0udmFsaWRhdGUob3RoZXIpO1xuXHRcdC8vIENoZWNrIGlmIHRoZSByZXN1bHQgaXMgYSBQcm9taXNlIChhc3luYyB2YWxpZGF0aW9uKVxuXHRcdGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKFwiQXN5bmMgc2NoZW1hIHZhbGlkYXRpb24gaXMgbm90IHN1cHBvcnRlZCBpbiBhc3ltbWV0cmljIG1hdGNoZXJzLlwiKTtcblx0XHR9XG5cdFx0dGhpcy5yZXN1bHQgPSByZXN1bHQ7XG5cdFx0Y29uc3QgcGFzcyA9ICF0aGlzLnJlc3VsdC5pc3N1ZXMgfHwgdGhpcy5yZXN1bHQuaXNzdWVzLmxlbmd0aCA9PT0gMDtcblx0XHRyZXR1cm4gdGhpcy5pbnZlcnNlID8gIXBhc3MgOiBwYXNzO1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiBgU2NoZW1hJHt0aGlzLmludmVyc2UgPyBcIk5vdFwiIDogXCJcIn1NYXRjaGluZ2A7XG5cdH1cblx0Z2V0RXhwZWN0ZWRUeXBlKCkge1xuXHRcdHJldHVybiBcIm9iamVjdFwiO1xuXHR9XG5cdHRvQXN5bW1ldHJpY01hdGNoZXIoKSB7XG5cdFx0Y29uc3QgeyB1dGlscyB9ID0gdGhpcy5nZXRNYXRjaGVyQ29udGV4dCgpO1xuXHRcdGNvbnN0IGlzc3VlcyA9IHRoaXMucmVzdWx0Py5pc3N1ZXMgfHwgW107XG5cdFx0aWYgKGlzc3Vlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRyZXR1cm4gYCR7dGhpcy50b1N0cmluZygpfSAke3V0aWxzLnN0cmluZ2lmeSh0aGlzLnJlc3VsdCwgdW5kZWZpbmVkLCB7IHByaW50QmFzaWNQcm90b3R5cGU6IGZhbHNlIH0pfWA7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLnRvU3RyaW5nKCk7XG5cdH1cbn1cbmNvbnN0IEplc3RBc3ltbWV0cmljTWF0Y2hlcnMgPSAoY2hhaSwgdXRpbHMpID0+IHtcblx0dXRpbHMuYWRkTWV0aG9kKGNoYWkuZXhwZWN0LCBcImFueXRoaW5nXCIsICgpID0+IG5ldyBBbnl0aGluZygpKTtcblx0dXRpbHMuYWRkTWV0aG9kKGNoYWkuZXhwZWN0LCBcImFueVwiLCAoZXhwZWN0ZWQpID0+IG5ldyBBbnkoZXhwZWN0ZWQpKTtcblx0dXRpbHMuYWRkTWV0aG9kKGNoYWkuZXhwZWN0LCBcInN0cmluZ0NvbnRhaW5pbmdcIiwgKGV4cGVjdGVkKSA9PiBuZXcgU3RyaW5nQ29udGFpbmluZyhleHBlY3RlZCkpO1xuXHR1dGlscy5hZGRNZXRob2QoY2hhaS5leHBlY3QsIFwib2JqZWN0Q29udGFpbmluZ1wiLCAoZXhwZWN0ZWQpID0+IG5ldyBPYmplY3RDb250YWluaW5nKGV4cGVjdGVkKSk7XG5cdHV0aWxzLmFkZE1ldGhvZChjaGFpLmV4cGVjdCwgXCJhcnJheUNvbnRhaW5pbmdcIiwgKGV4cGVjdGVkKSA9PiBuZXcgQXJyYXlDb250YWluaW5nKGV4cGVjdGVkKSk7XG5cdHV0aWxzLmFkZE1ldGhvZChjaGFpLmV4cGVjdCwgXCJzdHJpbmdNYXRjaGluZ1wiLCAoZXhwZWN0ZWQpID0+IG5ldyBTdHJpbmdNYXRjaGluZyhleHBlY3RlZCkpO1xuXHR1dGlscy5hZGRNZXRob2QoY2hhaS5leHBlY3QsIFwiY2xvc2VUb1wiLCAoZXhwZWN0ZWQsIHByZWNpc2lvbikgPT4gbmV3IENsb3NlVG8oZXhwZWN0ZWQsIHByZWNpc2lvbikpO1xuXHR1dGlscy5hZGRNZXRob2QoY2hhaS5leHBlY3QsIFwic2NoZW1hTWF0Y2hpbmdcIiwgKGV4cGVjdGVkKSA9PiBuZXcgU2NoZW1hTWF0Y2hpbmcoZXhwZWN0ZWQpKTtcblx0Ly8gZGVmaW5lUHJvcGVydHkgZG9lcyBub3Qgd29ya1xuXHRjaGFpLmV4cGVjdC5ub3QgPSB7XG5cdFx0c3RyaW5nQ29udGFpbmluZzogKGV4cGVjdGVkKSA9PiBuZXcgU3RyaW5nQ29udGFpbmluZyhleHBlY3RlZCwgdHJ1ZSksXG5cdFx0b2JqZWN0Q29udGFpbmluZzogKGV4cGVjdGVkKSA9PiBuZXcgT2JqZWN0Q29udGFpbmluZyhleHBlY3RlZCwgdHJ1ZSksXG5cdFx0YXJyYXlDb250YWluaW5nOiAoZXhwZWN0ZWQpID0+IG5ldyBBcnJheUNvbnRhaW5pbmcoZXhwZWN0ZWQsIHRydWUpLFxuXHRcdHN0cmluZ01hdGNoaW5nOiAoZXhwZWN0ZWQpID0+IG5ldyBTdHJpbmdNYXRjaGluZyhleHBlY3RlZCwgdHJ1ZSksXG5cdFx0Y2xvc2VUbzogKGV4cGVjdGVkLCBwcmVjaXNpb24pID0+IG5ldyBDbG9zZVRvKGV4cGVjdGVkLCBwcmVjaXNpb24sIHRydWUpLFxuXHRcdHNjaGVtYU1hdGNoaW5nOiAoZXhwZWN0ZWQpID0+IG5ldyBTY2hlbWFNYXRjaGluZyhleHBlY3RlZCwgdHJ1ZSlcblx0fTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZUFzc2VydGlvbk1lc3NhZ2UodXRpbCwgYXNzZXJ0aW9uLCBoYXNBcmdzKSB7XG5cdGNvbnN0IHNvZnQgPSB1dGlsLmZsYWcoYXNzZXJ0aW9uLCBcInNvZnRcIikgPyBcIi5zb2Z0XCIgOiBcIlwiO1xuXHRjb25zdCBub3QgPSB1dGlsLmZsYWcoYXNzZXJ0aW9uLCBcIm5lZ2F0ZVwiKSA/IFwibm90LlwiIDogXCJcIjtcblx0Y29uc3QgbmFtZSA9IGAke3V0aWwuZmxhZyhhc3NlcnRpb24sIFwiX25hbWVcIil9KCR7aGFzQXJncyA/IFwiZXhwZWN0ZWRcIiA6IFwiXCJ9KWA7XG5cdGNvbnN0IHByb21pc2VOYW1lID0gdXRpbC5mbGFnKGFzc2VydGlvbiwgXCJwcm9taXNlXCIpO1xuXHRjb25zdCBwcm9taXNlID0gcHJvbWlzZU5hbWUgPyBgLiR7cHJvbWlzZU5hbWV9YCA6IFwiXCI7XG5cdHJldHVybiBgZXhwZWN0JHtzb2Z0fShhY3R1YWwpJHtwcm9taXNlfS4ke25vdH0ke25hbWV9YDtcbn1cbmZ1bmN0aW9uIHJlY29yZEFzeW5jRXhwZWN0KF90ZXN0LCBwcm9taXNlLCBhc3NlcnRpb24sIGVycm9yLCBpc1NvZnQpIHtcblx0Y29uc3QgdGVzdCA9IF90ZXN0O1xuXHQvLyByZWNvcmQgcHJvbWlzZSBmb3IgdGVzdCwgdGhhdCByZXNvbHZlcyBiZWZvcmUgdGVzdCBlbmRzXG5cdGlmICh0ZXN0ICYmIHByb21pc2UgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG5cdFx0Ly8gaWYgcHJvbWlzZSBpcyBleHBsaWNpdGx5IGF3YWl0ZWQsIHJlbW92ZSBpdCBmcm9tIHRoZSBsaXN0XG5cdFx0cHJvbWlzZSA9IHByb21pc2UuZmluYWxseSgoKSA9PiB7XG5cdFx0XHRpZiAoIXRlc3QucHJvbWlzZXMpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgaW5kZXggPSB0ZXN0LnByb21pc2VzLmluZGV4T2YocHJvbWlzZSk7XG5cdFx0XHRpZiAoaW5kZXggIT09IC0xKSB7XG5cdFx0XHRcdHRlc3QucHJvbWlzZXMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHQvLyByZWNvcmQgcHJvbWlzZVxuXHRcdGlmICghdGVzdC5wcm9taXNlcykge1xuXHRcdFx0dGVzdC5wcm9taXNlcyA9IFtdO1xuXHRcdH1cblx0XHQvLyBzZXR1cCBgZXhwZWN0LnNvZnRgIGhhbmRsZXIgaGVyZSBpbnN0ZWFkIG9mIGB3cmFwQXNzZXJ0aW9uYFxuXHRcdC8vIHRvIGF2b2lkIGRvdWJsZSBlcnJvciB0cmFja2luZyB3aGlsZSBrZWVwaW5nIG5vbi1hd2FpdCBwcm9taXNlIGRldGVjdGlvbi5cblx0XHRpZiAoaXNTb2Z0KSB7XG5cdFx0XHRwcm9taXNlID0gcHJvbWlzZS50aGVuKG5vb3AsIChlcnIpID0+IHtcblx0XHRcdFx0aGFuZGxlVGVzdEVycm9yKHRlc3QsIGVycik7XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0dGVzdC5wcm9taXNlcy5wdXNoKHByb21pc2UpO1xuXHRcdGxldCByZXNvbHZlZCA9IGZhbHNlO1xuXHRcdHRlc3Qub25GaW5pc2hlZCA/Pz0gW107XG5cdFx0dGVzdC5vbkZpbmlzaGVkLnB1c2goKCkgPT4ge1xuXHRcdFx0aWYgKCFyZXNvbHZlZCkge1xuXHRcdFx0XHRjb25zdCBwcm9jZXNzb3IgPSBnbG9iYWxUaGlzLl9fdml0ZXN0X3dvcmtlcl9fPy5vbkZpbHRlclN0YWNrVHJhY2UgfHwgKChzKSA9PiBzIHx8IFwiXCIpO1xuXHRcdFx0XHRjb25zdCBzdGFjayA9IHByb2Nlc3NvcihlcnJvci5zdGFjayk7XG5cdFx0XHRcdGNvbnNvbGUud2FybihbXG5cdFx0XHRcdFx0YFByb21pc2UgcmV0dXJuZWQgYnkgXFxgJHthc3NlcnRpb259XFxgIHdhcyBub3QgYXdhaXRlZC4gYCxcblx0XHRcdFx0XHRcIlZpdGVzdCBjdXJyZW50bHkgYXV0by1hd2FpdHMgaGFuZ2luZyBhc3NlcnRpb25zIGF0IHRoZSBlbmQgb2YgdGhlIHRlc3QsIGJ1dCB0aGlzIHdpbGwgY2F1c2UgdGhlIHRlc3QgdG8gZmFpbCBpbiB0aGUgbmV4dCBWaXRlc3QgbWFqb3IuIFwiLFxuXHRcdFx0XHRcdFwiUGxlYXNlIHJlbWVtYmVyIHRvIGF3YWl0IHRoZSBhc3NlcnRpb24uXFxuXCIsXG5cdFx0XHRcdFx0c3RhY2tcblx0XHRcdFx0XS5qb2luKFwiXCIpKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0dGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkge1xuXHRcdFx0XHRyZXNvbHZlZCA9IHRydWU7XG5cdFx0XHRcdHJldHVybiBwcm9taXNlLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpO1xuXHRcdFx0fSxcblx0XHRcdGNhdGNoKG9uUmVqZWN0ZWQpIHtcblx0XHRcdFx0cmVzb2x2ZWQgPSB0cnVlO1xuXHRcdFx0XHRyZXR1cm4gcHJvbWlzZS5jYXRjaChvblJlamVjdGVkKTtcblx0XHRcdH0sXG5cdFx0XHRmaW5hbGx5KG9uRmluYWxseSkge1xuXHRcdFx0XHRyZXNvbHZlZCA9IHRydWU7XG5cdFx0XHRcdHJldHVybiBwcm9taXNlLmZpbmFsbHkob25GaW5hbGx5KTtcblx0XHRcdH0sXG5cdFx0XHRbU3ltYm9sLnRvU3RyaW5nVGFnXTogXCJQcm9taXNlXCJcblx0XHR9O1xuXHR9XG5cdHJldHVybiBwcm9taXNlO1xufVxuZnVuY3Rpb24gaGFuZGxlVGVzdEVycm9yKHRlc3QsIGVycikge1xuXHR0ZXN0LnJlc3VsdCB8fD0geyBzdGF0ZTogXCJmYWlsXCIgfTtcblx0dGVzdC5yZXN1bHQuc3RhdGUgPSBcImZhaWxcIjtcblx0dGVzdC5yZXN1bHQuZXJyb3JzIHx8PSBbXTtcblx0dGVzdC5yZXN1bHQuZXJyb3JzLnB1c2gocHJvY2Vzc0Vycm9yKGVycikpO1xufVxuZnVuY3Rpb24gd3JhcEFzc2VydGlvbih1dGlscywgbmFtZSwgZm4pIHtcblx0cmV0dXJuIGZ1bmN0aW9uKC4uLmFyZ3MpIHtcblx0XHQvLyBwcml2YXRlXG5cdFx0aWYgKG5hbWUgIT09IFwid2l0aFRlc3RcIikge1xuXHRcdFx0dXRpbHMuZmxhZyh0aGlzLCBcIl9uYW1lXCIsIG5hbWUpO1xuXHRcdH1cblx0XHRpZiAoIXV0aWxzLmZsYWcodGhpcywgXCJzb2Z0XCIpKSB7XG5cdFx0XHQvLyBhdm9pZCBXZWJLaXQncyBwcm9wZXIgdGFpbCBjYWxsIHRvIHByZXNlcnZlIHN0YWNrdHJhY2Ugb2Zmc2V0IGZvciBpbmxpbmUgc25hcHNob3Rcblx0XHRcdC8vIGh0dHBzOi8vd2Via2l0Lm9yZy9ibG9nLzYyNDAvZWNtYXNjcmlwdC02LXByb3Blci10YWlsLWNhbGxzLWluLXdlYmtpdFxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0cmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0fSBmaW5hbGx5IHt9XG5cdFx0fVxuXHRcdGNvbnN0IHRlc3QgPSB1dGlscy5mbGFnKHRoaXMsIFwidml0ZXN0LXRlc3RcIik7XG5cdFx0aWYgKCF0ZXN0KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJleHBlY3Quc29mdCgpIGNhbiBvbmx5IGJlIHVzZWQgaW5zaWRlIGEgdGVzdFwiKTtcblx0XHR9XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHJlc3VsdCA9IGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdFx0aWYgKHJlc3VsdCAmJiB0eXBlb2YgcmVzdWx0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiByZXN1bHQudGhlbiA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdHJldHVybiByZXN1bHQudGhlbihub29wLCAoZXJyKSA9PiB7XG5cdFx0XHRcdFx0aGFuZGxlVGVzdEVycm9yKHRlc3QsIGVycik7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3VsdDtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGhhbmRsZVRlc3RFcnJvcih0ZXN0LCBlcnIpO1xuXHRcdH1cblx0fTtcbn1cblxuLy8gSmVzdCBFeHBlY3QgQ29tcGFjdFxuY29uc3QgSmVzdENoYWlFeHBlY3QgPSAoY2hhaSwgdXRpbHMpID0+IHtcblx0Y29uc3QgeyBBc3NlcnRpb25FcnJvciB9ID0gY2hhaTtcblx0Y29uc3QgY3VzdG9tVGVzdGVycyA9IGdldEN1c3RvbUVxdWFsaXR5VGVzdGVycygpO1xuXHRmdW5jdGlvbiBkZWYobmFtZSwgZm4pIHtcblx0XHRjb25zdCBhZGRNZXRob2QgPSAobikgPT4ge1xuXHRcdFx0Y29uc3Qgc29mdFdyYXBwZXIgPSB3cmFwQXNzZXJ0aW9uKHV0aWxzLCBuLCBmbik7XG5cdFx0XHR1dGlscy5hZGRNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBuLCBzb2Z0V3JhcHBlcik7XG5cdFx0XHR1dGlscy5hZGRNZXRob2QoZ2xvYmFsVGhpc1tKRVNUX01BVENIRVJTX09CSkVDVF0ubWF0Y2hlcnMsIG4sIHNvZnRXcmFwcGVyKTtcblx0XHR9O1xuXHRcdGlmIChBcnJheS5pc0FycmF5KG5hbWUpKSB7XG5cdFx0XHRuYW1lLmZvckVhY2goKG4pID0+IGFkZE1ldGhvZChuKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFkZE1ldGhvZChuYW1lKTtcblx0XHR9XG5cdH1cblx0W1xuXHRcdFwidGhyb3dcIixcblx0XHRcInRocm93c1wiLFxuXHRcdFwiVGhyb3dcIlxuXHRdLmZvckVhY2goKG0pID0+IHtcblx0XHR1dGlscy5vdmVyd3JpdGVNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBtLCAoX3N1cGVyKSA9PiB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oLi4uYXJncykge1xuXHRcdFx0XHRjb25zdCBwcm9taXNlID0gdXRpbHMuZmxhZyh0aGlzLCBcInByb21pc2VcIik7XG5cdFx0XHRcdGNvbnN0IG9iamVjdCA9IHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIik7XG5cdFx0XHRcdGNvbnN0IGlzTm90ID0gdXRpbHMuZmxhZyh0aGlzLCBcIm5lZ2F0ZVwiKTtcblx0XHRcdFx0aWYgKHByb21pc2UgPT09IFwicmVqZWN0c1wiKSB7XG5cdFx0XHRcdFx0dXRpbHMuZmxhZyh0aGlzLCBcIm9iamVjdFwiLCAoKSA9PiB7XG5cdFx0XHRcdFx0XHR0aHJvdyBvYmplY3Q7XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gZWxzZSBpZiAocHJvbWlzZSA9PT0gXCJyZXNvbHZlc1wiICYmIHR5cGVvZiBvYmplY3QgIT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0XHRcdGlmICghaXNOb3QpIHtcblx0XHRcdFx0XHRcdGNvbnN0IG1lc3NhZ2UgPSB1dGlscy5mbGFnKHRoaXMsIFwibWVzc2FnZVwiKSB8fCBcImV4cGVjdGVkIHByb21pc2UgdG8gdGhyb3cgYW4gZXJyb3IsIGJ1dCBpdCBkaWRuJ3RcIjtcblx0XHRcdFx0XHRcdGNvbnN0IGVycm9yID0geyBzaG93RGlmZjogZmFsc2UgfTtcblx0XHRcdFx0XHRcdHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihtZXNzYWdlLCBlcnJvciwgdXRpbHMuZmxhZyh0aGlzLCBcInNzZmlcIikpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdF9zdXBlci5hcHBseSh0aGlzLCBhcmdzKTtcblx0XHRcdH07XG5cdFx0fSk7XG5cdH0pO1xuXHQvLyBAdHMtZXhwZWN0LWVycm9yIEBpbnRlcm5hbFxuXHRkZWYoXCJ3aXRoVGVzdFwiLCBmdW5jdGlvbih0ZXN0KSB7XG5cdFx0dXRpbHMuZmxhZyh0aGlzLCBcInZpdGVzdC10ZXN0XCIsIHRlc3QpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9KTtcblx0ZGVmKFwidG9FcXVhbFwiLCBmdW5jdGlvbihleHBlY3RlZCkge1xuXHRcdGNvbnN0IGFjdHVhbCA9IHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIik7XG5cdFx0Y29uc3QgZXF1YWwgPSBlcXVhbHMoYWN0dWFsLCBleHBlY3RlZCwgWy4uLmN1c3RvbVRlc3RlcnMsIGl0ZXJhYmxlRXF1YWxpdHldKTtcblx0XHRyZXR1cm4gdGhpcy5hc3NlcnQoZXF1YWwsIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBkZWVwbHkgZXF1YWwgI3tleHB9XCIsIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZGVlcGx5IGVxdWFsICN7ZXhwfVwiLCBleHBlY3RlZCwgYWN0dWFsKTtcblx0fSk7XG5cdGRlZihcInRvU3RyaWN0RXF1YWxcIiwgZnVuY3Rpb24oZXhwZWN0ZWQpIHtcblx0XHRjb25zdCBvYmogPSB1dGlscy5mbGFnKHRoaXMsIFwib2JqZWN0XCIpO1xuXHRcdGNvbnN0IGVxdWFsID0gZXF1YWxzKG9iaiwgZXhwZWN0ZWQsIFtcblx0XHRcdC4uLmN1c3RvbVRlc3RlcnMsXG5cdFx0XHRpdGVyYWJsZUVxdWFsaXR5LFxuXHRcdFx0dHlwZUVxdWFsaXR5LFxuXHRcdFx0c3BhcnNlQXJyYXlFcXVhbGl0eSxcblx0XHRcdGFycmF5QnVmZmVyRXF1YWxpdHlcblx0XHRdLCB0cnVlKTtcblx0XHRyZXR1cm4gdGhpcy5hc3NlcnQoZXF1YWwsIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBzdHJpY3RseSBlcXVhbCAje2V4cH1cIiwgXCJleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBzdHJpY3RseSBlcXVhbCAje2V4cH1cIiwgZXhwZWN0ZWQsIG9iaik7XG5cdH0pO1xuXHRkZWYoXCJ0b0JlXCIsIGZ1bmN0aW9uKGV4cGVjdGVkKSB7XG5cdFx0Y29uc3QgYWN0dWFsID0gdGhpcy5fb2JqO1xuXHRcdGNvbnN0IHBhc3MgPSBPYmplY3QuaXMoYWN0dWFsLCBleHBlY3RlZCk7XG5cdFx0bGV0IGRlZXBFcXVhbGl0eU5hbWUgPSBcIlwiO1xuXHRcdGlmICghcGFzcykge1xuXHRcdFx0Y29uc3QgdG9TdHJpY3RFcXVhbFBhc3MgPSBlcXVhbHMoYWN0dWFsLCBleHBlY3RlZCwgW1xuXHRcdFx0XHQuLi5jdXN0b21UZXN0ZXJzLFxuXHRcdFx0XHRpdGVyYWJsZUVxdWFsaXR5LFxuXHRcdFx0XHR0eXBlRXF1YWxpdHksXG5cdFx0XHRcdHNwYXJzZUFycmF5RXF1YWxpdHksXG5cdFx0XHRcdGFycmF5QnVmZmVyRXF1YWxpdHlcblx0XHRcdF0sIHRydWUpO1xuXHRcdFx0aWYgKHRvU3RyaWN0RXF1YWxQYXNzKSB7XG5cdFx0XHRcdGRlZXBFcXVhbGl0eU5hbWUgPSBcInRvU3RyaWN0RXF1YWxcIjtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnN0IHRvRXF1YWxQYXNzID0gZXF1YWxzKGFjdHVhbCwgZXhwZWN0ZWQsIFsuLi5jdXN0b21UZXN0ZXJzLCBpdGVyYWJsZUVxdWFsaXR5XSk7XG5cdFx0XHRcdGlmICh0b0VxdWFsUGFzcykge1xuXHRcdFx0XHRcdGRlZXBFcXVhbGl0eU5hbWUgPSBcInRvRXF1YWxcIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5hc3NlcnQocGFzcywgZ2VuZXJhdGVUb0JlTWVzc2FnZShkZWVwRXF1YWxpdHlOYW1lKSwgXCJleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSAje2V4cH0gLy8gT2JqZWN0LmlzIGVxdWFsaXR5XCIsIGV4cGVjdGVkLCBhY3R1YWwpO1xuXHR9KTtcblx0ZGVmKFwidG9NYXRjaE9iamVjdFwiLCBmdW5jdGlvbihleHBlY3RlZCkge1xuXHRcdGNvbnN0IGFjdHVhbCA9IHRoaXMuX29iajtcblx0XHRjb25zdCBwYXNzID0gZXF1YWxzKGFjdHVhbCwgZXhwZWN0ZWQsIFtcblx0XHRcdC4uLmN1c3RvbVRlc3RlcnMsXG5cdFx0XHRpdGVyYWJsZUVxdWFsaXR5LFxuXHRcdFx0c3Vic2V0RXF1YWxpdHlcblx0XHRdKTtcblx0XHRjb25zdCBpc05vdCA9IHV0aWxzLmZsYWcodGhpcywgXCJuZWdhdGVcIik7XG5cdFx0Y29uc3QgeyBzdWJzZXQ6IGFjdHVhbFN1YnNldCwgc3RyaXBwZWQgfSA9IGdldE9iamVjdFN1YnNldChhY3R1YWwsIGV4cGVjdGVkLCBjdXN0b21UZXN0ZXJzKTtcblx0XHRpZiAocGFzcyAmJiBpc05vdCB8fCAhcGFzcyAmJiAhaXNOb3QpIHtcblx0XHRcdGNvbnN0IG1zZyA9IHV0aWxzLmdldE1lc3NhZ2UodGhpcywgW1xuXHRcdFx0XHRwYXNzLFxuXHRcdFx0XHRcImV4cGVjdGVkICN7dGhpc30gdG8gbWF0Y2ggb2JqZWN0ICN7ZXhwfVwiLFxuXHRcdFx0XHRcImV4cGVjdGVkICN7dGhpc30gdG8gbm90IG1hdGNoIG9iamVjdCAje2V4cH1cIixcblx0XHRcdFx0ZXhwZWN0ZWQsXG5cdFx0XHRcdGFjdHVhbFN1YnNldCxcblx0XHRcdFx0ZmFsc2Vcblx0XHRcdF0pO1xuXHRcdFx0Y29uc3QgbWVzc2FnZSA9IHN0cmlwcGVkID09PSAwID8gbXNnIDogYCR7bXNnfVxcbigke3N0cmlwcGVkfSBtYXRjaGluZyAke3N0cmlwcGVkID09PSAxID8gXCJwcm9wZXJ0eVwiIDogXCJwcm9wZXJ0aWVzXCJ9IG9taXR0ZWQgZnJvbSBhY3R1YWwpYDtcblx0XHRcdHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihtZXNzYWdlLCB7XG5cdFx0XHRcdHNob3dEaWZmOiB0cnVlLFxuXHRcdFx0XHRleHBlY3RlZCxcblx0XHRcdFx0YWN0dWFsOiBhY3R1YWxTdWJzZXRcblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cdGRlZihcInRvTWF0Y2hcIiwgZnVuY3Rpb24oZXhwZWN0ZWQpIHtcblx0XHRjb25zdCBhY3R1YWwgPSB0aGlzLl9vYmo7XG5cdFx0aWYgKHR5cGVvZiBhY3R1YWwgIT09IFwic3RyaW5nXCIpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYC50b01hdGNoKCkgZXhwZWN0cyB0byByZWNlaXZlIGEgc3RyaW5nLCBidXQgZ290ICR7dHlwZW9mIGFjdHVhbH1gKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KHR5cGVvZiBleHBlY3RlZCA9PT0gXCJzdHJpbmdcIiA/IGFjdHVhbC5pbmNsdWRlcyhleHBlY3RlZCkgOiBhY3R1YWwubWF0Y2goZXhwZWN0ZWQpLCBgZXhwZWN0ZWQgI3t0aGlzfSB0byBtYXRjaCAje2V4cH1gLCBgZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gbWF0Y2ggI3tleHB9YCwgZXhwZWN0ZWQsIGFjdHVhbCk7XG5cdH0pO1xuXHRkZWYoXCJ0b0NvbnRhaW5cIiwgZnVuY3Rpb24oaXRlbSkge1xuXHRcdGNvbnN0IGFjdHVhbCA9IHRoaXMuX29iajtcblx0XHRpZiAodHlwZW9mIE5vZGUgIT09IFwidW5kZWZpbmVkXCIgJiYgYWN0dWFsIGluc3RhbmNlb2YgTm9kZSkge1xuXHRcdFx0aWYgKCEoaXRlbSBpbnN0YW5jZW9mIE5vZGUpKSB7XG5cdFx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYHRvQ29udGFpbigpIGV4cGVjdGVkIGEgRE9NIG5vZGUgYXMgdGhlIGFyZ3VtZW50LCBidXQgZ290ICR7dHlwZW9mIGl0ZW19YCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdGhpcy5hc3NlcnQoYWN0dWFsLmNvbnRhaW5zKGl0ZW0pLCBcImV4cGVjdGVkICN7dGhpc30gdG8gY29udGFpbiBlbGVtZW50ICN7ZXhwfVwiLCBcImV4cGVjdGVkICN7dGhpc30gbm90IHRvIGNvbnRhaW4gZWxlbWVudCAje2V4cH1cIiwgaXRlbSwgYWN0dWFsKTtcblx0XHR9XG5cdFx0aWYgKHR5cGVvZiBET01Ub2tlbkxpc3QgIT09IFwidW5kZWZpbmVkXCIgJiYgYWN0dWFsIGluc3RhbmNlb2YgRE9NVG9rZW5MaXN0KSB7XG5cdFx0XHRhc3NlcnRUeXBlcyhpdGVtLCBcImNsYXNzIG5hbWVcIiwgW1wic3RyaW5nXCJdKTtcblx0XHRcdGNvbnN0IGlzTm90ID0gdXRpbHMuZmxhZyh0aGlzLCBcIm5lZ2F0ZVwiKTtcblx0XHRcdGNvbnN0IGV4cGVjdGVkQ2xhc3NMaXN0ID0gaXNOb3QgPyBhY3R1YWwudmFsdWUucmVwbGFjZShpdGVtLCBcIlwiKS50cmltKCkgOiBgJHthY3R1YWwudmFsdWV9ICR7aXRlbX1gO1xuXHRcdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KGFjdHVhbC5jb250YWlucyhpdGVtKSwgYGV4cGVjdGVkIFwiJHthY3R1YWwudmFsdWV9XCIgdG8gY29udGFpbiBcIiR7aXRlbX1cImAsIGBleHBlY3RlZCBcIiR7YWN0dWFsLnZhbHVlfVwiIG5vdCB0byBjb250YWluIFwiJHtpdGVtfVwiYCwgZXhwZWN0ZWRDbGFzc0xpc3QsIGFjdHVhbC52YWx1ZSk7XG5cdFx0fVxuXHRcdC8vIGhhbmRsZSBzaW1wbGUgY2FzZSBvbiBvdXIgb3duIHVzaW5nIGB0aGlzLmFzc2VydGAgdG8gaW5jbHVkZSBkaWZmIGluIGVycm9yIG1lc3NhZ2Vcblx0XHRpZiAodHlwZW9mIGFjdHVhbCA9PT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KGFjdHVhbC5pbmNsdWRlcyhpdGVtKSwgYGV4cGVjdGVkICN7dGhpc30gdG8gY29udGFpbiAje2V4cH1gLCBgZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gY29udGFpbiAje2V4cH1gLCBpdGVtLCBhY3R1YWwpO1xuXHRcdH1cblx0XHQvLyBtYWtlIFwiYWN0dWFsXCIgaW5kZXhhYmxlIHRvIGhhdmUgY29tcGF0aWJpbGl0eSB3aXRoIGplc3Rcblx0XHRpZiAoYWN0dWFsICE9IG51bGwgJiYgdHlwZW9mIGFjdHVhbCAhPT0gXCJzdHJpbmdcIikge1xuXHRcdFx0dXRpbHMuZmxhZyh0aGlzLCBcIm9iamVjdFwiLCBBcnJheS5mcm9tKGFjdHVhbCkpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5jb250YWluKGl0ZW0pO1xuXHR9KTtcblx0ZGVmKFwidG9Db250YWluRXF1YWxcIiwgZnVuY3Rpb24oZXhwZWN0ZWQpIHtcblx0XHRjb25zdCBvYmogPSB1dGlscy5mbGFnKHRoaXMsIFwib2JqZWN0XCIpO1xuXHRcdGNvbnN0IGluZGV4ID0gQXJyYXkuZnJvbShvYmopLmZpbmRJbmRleCgoaXRlbSkgPT4ge1xuXHRcdFx0cmV0dXJuIGVxdWFscyhpdGVtLCBleHBlY3RlZCwgY3VzdG9tVGVzdGVycyk7XG5cdFx0fSk7XG5cdFx0dGhpcy5hc3NlcnQoaW5kZXggIT09IC0xLCBcImV4cGVjdGVkICN7dGhpc30gdG8gZGVlcCBlcXVhbGx5IGNvbnRhaW4gI3tleHB9XCIsIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZGVlcCBlcXVhbGx5IGNvbnRhaW4gI3tleHB9XCIsIGV4cGVjdGVkKTtcblx0fSk7XG5cdGRlZihcInRvQmVUcnV0aHlcIiwgZnVuY3Rpb24oKSB7XG5cdFx0Y29uc3Qgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCBcIm9iamVjdFwiKTtcblx0XHR0aGlzLmFzc2VydChCb29sZWFuKG9iaiksIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB0cnV0aHlcIiwgXCJleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBiZSB0cnV0aHlcIiwgdHJ1ZSwgb2JqKTtcblx0fSk7XG5cdGRlZihcInRvQmVGYWxzeVwiLCBmdW5jdGlvbigpIHtcblx0XHRjb25zdCBvYmogPSB1dGlscy5mbGFnKHRoaXMsIFwib2JqZWN0XCIpO1xuXHRcdHRoaXMuYXNzZXJ0KCFvYmosIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBmYWxzeVwiLCBcImV4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGZhbHN5XCIsIGZhbHNlLCBvYmopO1xuXHR9KTtcblx0ZGVmKFwidG9CZUdyZWF0ZXJUaGFuXCIsIGZ1bmN0aW9uKGV4cGVjdGVkKSB7XG5cdFx0Y29uc3QgYWN0dWFsID0gdGhpcy5fb2JqO1xuXHRcdGFzc2VydFR5cGVzKGFjdHVhbCwgXCJhY3R1YWxcIiwgW1wibnVtYmVyXCIsIFwiYmlnaW50XCJdKTtcblx0XHRhc3NlcnRUeXBlcyhleHBlY3RlZCwgXCJleHBlY3RlZFwiLCBbXCJudW1iZXJcIiwgXCJiaWdpbnRcIl0pO1xuXHRcdHJldHVybiB0aGlzLmFzc2VydChhY3R1YWwgPiBleHBlY3RlZCwgYGV4cGVjdGVkICR7YWN0dWFsfSB0byBiZSBncmVhdGVyIHRoYW4gJHtleHBlY3RlZH1gLCBgZXhwZWN0ZWQgJHthY3R1YWx9IHRvIGJlIG5vdCBncmVhdGVyIHRoYW4gJHtleHBlY3RlZH1gLCBleHBlY3RlZCwgYWN0dWFsLCBmYWxzZSk7XG5cdH0pO1xuXHRkZWYoXCJ0b0JlR3JlYXRlclRoYW5PckVxdWFsXCIsIGZ1bmN0aW9uKGV4cGVjdGVkKSB7XG5cdFx0Y29uc3QgYWN0dWFsID0gdGhpcy5fb2JqO1xuXHRcdGFzc2VydFR5cGVzKGFjdHVhbCwgXCJhY3R1YWxcIiwgW1wibnVtYmVyXCIsIFwiYmlnaW50XCJdKTtcblx0XHRhc3NlcnRUeXBlcyhleHBlY3RlZCwgXCJleHBlY3RlZFwiLCBbXCJudW1iZXJcIiwgXCJiaWdpbnRcIl0pO1xuXHRcdHJldHVybiB0aGlzLmFzc2VydChhY3R1YWwgPj0gZXhwZWN0ZWQsIGBleHBlY3RlZCAke2FjdHVhbH0gdG8gYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvICR7ZXhwZWN0ZWR9YCwgYGV4cGVjdGVkICR7YWN0dWFsfSB0byBiZSBub3QgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvICR7ZXhwZWN0ZWR9YCwgZXhwZWN0ZWQsIGFjdHVhbCwgZmFsc2UpO1xuXHR9KTtcblx0ZGVmKFwidG9CZUxlc3NUaGFuXCIsIGZ1bmN0aW9uKGV4cGVjdGVkKSB7XG5cdFx0Y29uc3QgYWN0dWFsID0gdGhpcy5fb2JqO1xuXHRcdGFzc2VydFR5cGVzKGFjdHVhbCwgXCJhY3R1YWxcIiwgW1wibnVtYmVyXCIsIFwiYmlnaW50XCJdKTtcblx0XHRhc3NlcnRUeXBlcyhleHBlY3RlZCwgXCJleHBlY3RlZFwiLCBbXCJudW1iZXJcIiwgXCJiaWdpbnRcIl0pO1xuXHRcdHJldHVybiB0aGlzLmFzc2VydChhY3R1YWwgPCBleHBlY3RlZCwgYGV4cGVjdGVkICR7YWN0dWFsfSB0byBiZSBsZXNzIHRoYW4gJHtleHBlY3RlZH1gLCBgZXhwZWN0ZWQgJHthY3R1YWx9IHRvIGJlIG5vdCBsZXNzIHRoYW4gJHtleHBlY3RlZH1gLCBleHBlY3RlZCwgYWN0dWFsLCBmYWxzZSk7XG5cdH0pO1xuXHRkZWYoXCJ0b0JlTGVzc1RoYW5PckVxdWFsXCIsIGZ1bmN0aW9uKGV4cGVjdGVkKSB7XG5cdFx0Y29uc3QgYWN0dWFsID0gdGhpcy5fb2JqO1xuXHRcdGFzc2VydFR5cGVzKGFjdHVhbCwgXCJhY3R1YWxcIiwgW1wibnVtYmVyXCIsIFwiYmlnaW50XCJdKTtcblx0XHRhc3NlcnRUeXBlcyhleHBlY3RlZCwgXCJleHBlY3RlZFwiLCBbXCJudW1iZXJcIiwgXCJiaWdpbnRcIl0pO1xuXHRcdHJldHVybiB0aGlzLmFzc2VydChhY3R1YWwgPD0gZXhwZWN0ZWQsIGBleHBlY3RlZCAke2FjdHVhbH0gdG8gYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICR7ZXhwZWN0ZWR9YCwgYGV4cGVjdGVkICR7YWN0dWFsfSB0byBiZSBub3QgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICR7ZXhwZWN0ZWR9YCwgZXhwZWN0ZWQsIGFjdHVhbCwgZmFsc2UpO1xuXHR9KTtcblx0ZGVmKFwidG9CZU5hTlwiLCBmdW5jdGlvbigpIHtcblx0XHRjb25zdCBvYmogPSB1dGlscy5mbGFnKHRoaXMsIFwib2JqZWN0XCIpO1xuXHRcdHRoaXMuYXNzZXJ0KE51bWJlci5pc05hTihvYmopLCBcImV4cGVjdGVkICN7dGhpc30gdG8gYmUgTmFOXCIsIFwiZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgTmFOXCIsIE51bWJlci5OYU4sIG9iaik7XG5cdH0pO1xuXHRkZWYoXCJ0b0JlVW5kZWZpbmVkXCIsIGZ1bmN0aW9uKCkge1xuXHRcdGNvbnN0IG9iaiA9IHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIik7XG5cdFx0dGhpcy5hc3NlcnQodW5kZWZpbmVkID09PSBvYmosIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB1bmRlZmluZWRcIiwgXCJleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSB1bmRlZmluZWRcIiwgdW5kZWZpbmVkLCBvYmopO1xuXHR9KTtcblx0ZGVmKFwidG9CZU51bGxcIiwgZnVuY3Rpb24oKSB7XG5cdFx0Y29uc3Qgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCBcIm9iamVjdFwiKTtcblx0XHR0aGlzLmFzc2VydChvYmogPT09IG51bGwsIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBudWxsXCIsIFwiZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgbnVsbFwiLCBudWxsLCBvYmopO1xuXHR9KTtcblx0ZGVmKFwidG9CZU51bGxhYmxlXCIsIGZ1bmN0aW9uKCkge1xuXHRcdGNvbnN0IG9iaiA9IHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIik7XG5cdFx0dGhpcy5hc3NlcnQob2JqID09IG51bGwsIFwiZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBudWxsaXNoXCIsIFwiZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgbnVsbGlzaFwiLCBudWxsLCBvYmopO1xuXHR9KTtcblx0ZGVmKFwidG9CZURlZmluZWRcIiwgZnVuY3Rpb24oKSB7XG5cdFx0Y29uc3Qgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCBcIm9iamVjdFwiKTtcblx0XHR0aGlzLmFzc2VydCh0eXBlb2Ygb2JqICE9PSBcInVuZGVmaW5lZFwiLCBcImV4cGVjdGVkICN7dGhpc30gdG8gYmUgZGVmaW5lZFwiLCBcImV4cGVjdGVkICN7dGhpc30gdG8gYmUgdW5kZWZpbmVkXCIsIG9iaik7XG5cdH0pO1xuXHRkZWYoXCJ0b0JlVHlwZU9mXCIsIGZ1bmN0aW9uKGV4cGVjdGVkKSB7XG5cdFx0Y29uc3QgYWN0dWFsID0gdHlwZW9mIHRoaXMuX29iajtcblx0XHRjb25zdCBlcXVhbCA9IGV4cGVjdGVkID09PSBhY3R1YWw7XG5cdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KGVxdWFsLCBcImV4cGVjdGVkICN7dGhpc30gdG8gYmUgdHlwZSBvZiAje2V4cH1cIiwgXCJleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSB0eXBlIG9mICN7ZXhwfVwiLCBleHBlY3RlZCwgYWN0dWFsKTtcblx0fSk7XG5cdGRlZihcInRvQmVJbnN0YW5jZU9mXCIsIGZ1bmN0aW9uKG9iaikge1xuXHRcdHJldHVybiB0aGlzLmluc3RhbmNlT2Yob2JqKTtcblx0fSk7XG5cdGRlZihcInRvSGF2ZUxlbmd0aFwiLCBmdW5jdGlvbihsZW5ndGgpIHtcblx0XHRyZXR1cm4gdGhpcy5oYXZlLmxlbmd0aChsZW5ndGgpO1xuXHR9KTtcblx0Ly8gZGVzdHJ1Y3R1cmluZywgYmVjYXVzZSBpdCBjaGVja3MgYGFyZ3VtZW50c2AgaW5zaWRlLCBhbmQgdmFsdWUgaXMgcGFzc2luZyBhcyBgdW5kZWZpbmVkYFxuXHRkZWYoXCJ0b0hhdmVQcm9wZXJ0eVwiLCBmdW5jdGlvbiguLi5hcmdzKSB7XG5cdFx0aWYgKEFycmF5LmlzQXJyYXkoYXJnc1swXSkpIHtcblx0XHRcdGFyZ3NbMF0gPSBhcmdzWzBdLm1hcCgoa2V5KSA9PiBTdHJpbmcoa2V5KS5yZXBsYWNlKC8oWy5bXFxdXSkvZywgXCJcXFxcJDFcIikpLmpvaW4oXCIuXCIpO1xuXHRcdH1cblx0XHRjb25zdCBhY3R1YWwgPSB0aGlzLl9vYmo7XG5cdFx0Y29uc3QgW3Byb3BlcnR5TmFtZSwgZXhwZWN0ZWRdID0gYXJncztcblx0XHRjb25zdCBnZXRWYWx1ZSA9ICgpID0+IHtcblx0XHRcdGNvbnN0IGhhc093biA9IE9iamVjdC5oYXNPd24oYWN0dWFsLCBwcm9wZXJ0eU5hbWUpO1xuXHRcdFx0aWYgKGhhc093bikge1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdHZhbHVlOiBhY3R1YWxbcHJvcGVydHlOYW1lXSxcblx0XHRcdFx0XHRleGlzdHM6IHRydWVcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB1dGlscy5nZXRQYXRoSW5mbyhhY3R1YWwsIHByb3BlcnR5TmFtZSk7XG5cdFx0fTtcblx0XHRjb25zdCB7IHZhbHVlLCBleGlzdHMgfSA9IGdldFZhbHVlKCk7XG5cdFx0Y29uc3QgcGFzcyA9IGV4aXN0cyAmJiAoYXJncy5sZW5ndGggPT09IDEgfHwgZXF1YWxzKGV4cGVjdGVkLCB2YWx1ZSwgY3VzdG9tVGVzdGVycykpO1xuXHRcdGNvbnN0IHZhbHVlU3RyaW5nID0gYXJncy5sZW5ndGggPT09IDEgPyBcIlwiIDogYCB3aXRoIHZhbHVlICR7dXRpbHMub2JqRGlzcGxheShleHBlY3RlZCl9YDtcblx0XHRyZXR1cm4gdGhpcy5hc3NlcnQocGFzcywgYGV4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBwcm9wZXJ0eSBcIiR7cHJvcGVydHlOYW1lfVwiJHt2YWx1ZVN0cmluZ31gLCBgZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBwcm9wZXJ0eSBcIiR7cHJvcGVydHlOYW1lfVwiJHt2YWx1ZVN0cmluZ31gLCBleHBlY3RlZCwgZXhpc3RzID8gdmFsdWUgOiB1bmRlZmluZWQpO1xuXHR9KTtcblx0ZGVmKFwidG9CZUNsb3NlVG9cIiwgZnVuY3Rpb24ocmVjZWl2ZWQsIHByZWNpc2lvbiA9IDIpIHtcblx0XHRjb25zdCBleHBlY3RlZCA9IHRoaXMuX29iajtcblx0XHRsZXQgcGFzcyA9IGZhbHNlO1xuXHRcdGxldCBleHBlY3RlZERpZmYgPSAwO1xuXHRcdGxldCByZWNlaXZlZERpZmYgPSAwO1xuXHRcdGlmIChyZWNlaXZlZCA9PT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZICYmIGV4cGVjdGVkID09PSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpIHtcblx0XHRcdHBhc3MgPSB0cnVlO1xuXHRcdH0gZWxzZSBpZiAocmVjZWl2ZWQgPT09IE51bWJlci5ORUdBVElWRV9JTkZJTklUWSAmJiBleHBlY3RlZCA9PT0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZKSB7XG5cdFx0XHRwYXNzID0gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZXhwZWN0ZWREaWZmID0gMTAgKiogLXByZWNpc2lvbiAvIDI7XG5cdFx0XHRyZWNlaXZlZERpZmYgPSBNYXRoLmFicyhleHBlY3RlZCAtIHJlY2VpdmVkKTtcblx0XHRcdHBhc3MgPSByZWNlaXZlZERpZmYgPCBleHBlY3RlZERpZmY7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmFzc2VydChwYXNzLCBgZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBjbG9zZSB0byAje2V4cH0sIHJlY2VpdmVkIGRpZmZlcmVuY2UgaXMgJHtyZWNlaXZlZERpZmZ9LCBidXQgZXhwZWN0ZWQgJHtleHBlY3RlZERpZmZ9YCwgYGV4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGNsb3NlIHRvICN7ZXhwfSwgcmVjZWl2ZWQgZGlmZmVyZW5jZSBpcyAke3JlY2VpdmVkRGlmZn0sIGJ1dCBleHBlY3RlZCAke2V4cGVjdGVkRGlmZn1gLCByZWNlaXZlZCwgZXhwZWN0ZWQsIGZhbHNlKTtcblx0fSk7XG5cdGZ1bmN0aW9uIGFzc2VydElzTW9jayhhc3NlcnRpb24pIHtcblx0XHRpZiAoIWlzTW9ja0Z1bmN0aW9uKGFzc2VydGlvbi5fb2JqKSkge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgJHt1dGlscy5pbnNwZWN0KGFzc2VydGlvbi5fb2JqKX0gaXMgbm90IGEgc3B5IG9yIGEgY2FsbCB0byBhIHNweSFgKTtcblx0XHR9XG5cdH1cblx0ZnVuY3Rpb24gZ2V0U3B5KGFzc2VydGlvbikge1xuXHRcdGFzc2VydElzTW9jayhhc3NlcnRpb24pO1xuXHRcdHJldHVybiBhc3NlcnRpb24uX29iajtcblx0fVxuXHRkZWYoW1widG9IYXZlQmVlbkNhbGxlZFRpbWVzXCIsIFwidG9CZUNhbGxlZFRpbWVzXCJdLCBmdW5jdGlvbihudW1iZXIpIHtcblx0XHRjb25zdCBzcHkgPSBnZXRTcHkodGhpcyk7XG5cdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdGNvbnN0IGNhbGxDb3VudCA9IHNweS5tb2NrLmNhbGxzLmxlbmd0aDtcblx0XHRyZXR1cm4gdGhpcy5hc3NlcnQoY2FsbENvdW50ID09PSBudW1iZXIsIGBleHBlY3RlZCBcIiR7c3B5TmFtZX1cIiB0byBiZSBjYWxsZWQgI3tleHB9IHRpbWVzLCBidXQgZ290ICR7Y2FsbENvdW50fSB0aW1lc2AsIGBleHBlY3RlZCBcIiR7c3B5TmFtZX1cIiB0byBub3QgYmUgY2FsbGVkICN7ZXhwfSB0aW1lc2AsIG51bWJlciwgY2FsbENvdW50LCBmYWxzZSk7XG5cdH0pO1xuXHRkZWYoXCJ0b0hhdmVCZWVuQ2FsbGVkT25jZVwiLCBmdW5jdGlvbigpIHtcblx0XHRjb25zdCBzcHkgPSBnZXRTcHkodGhpcyk7XG5cdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdGNvbnN0IGNhbGxDb3VudCA9IHNweS5tb2NrLmNhbGxzLmxlbmd0aDtcblx0XHRyZXR1cm4gdGhpcy5hc3NlcnQoY2FsbENvdW50ID09PSAxLCBgZXhwZWN0ZWQgXCIke3NweU5hbWV9XCIgdG8gYmUgY2FsbGVkIG9uY2UsIGJ1dCBnb3QgJHtjYWxsQ291bnR9IHRpbWVzYCwgYGV4cGVjdGVkIFwiJHtzcHlOYW1lfVwiIHRvIG5vdCBiZSBjYWxsZWQgb25jZWAsIDEsIGNhbGxDb3VudCwgZmFsc2UpO1xuXHR9KTtcblx0ZGVmKFtcInRvSGF2ZUJlZW5DYWxsZWRcIiwgXCJ0b0JlQ2FsbGVkXCJdLCBmdW5jdGlvbigpIHtcblx0XHRjb25zdCBzcHkgPSBnZXRTcHkodGhpcyk7XG5cdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdGNvbnN0IGNhbGxDb3VudCA9IHNweS5tb2NrLmNhbGxzLmxlbmd0aDtcblx0XHRjb25zdCBjYWxsZWQgPSBjYWxsQ291bnQgPiAwO1xuXHRcdGNvbnN0IGlzTm90ID0gdXRpbHMuZmxhZyh0aGlzLCBcIm5lZ2F0ZVwiKTtcblx0XHRsZXQgbXNnID0gdXRpbHMuZ2V0TWVzc2FnZSh0aGlzLCBbXG5cdFx0XHRjYWxsZWQsXG5cdFx0XHRgZXhwZWN0ZWQgXCIke3NweU5hbWV9XCIgdG8gYmUgY2FsbGVkIGF0IGxlYXN0IG9uY2VgLFxuXHRcdFx0YGV4cGVjdGVkIFwiJHtzcHlOYW1lfVwiIHRvIG5vdCBiZSBjYWxsZWQgYXQgYWxsLCBidXQgYWN0dWFsbHkgYmVlbiBjYWxsZWQgJHtjYWxsQ291bnR9IHRpbWVzYCxcblx0XHRcdHRydWUsXG5cdFx0XHRjYWxsZWRcblx0XHRdKTtcblx0XHRpZiAoY2FsbGVkICYmIGlzTm90KSB7XG5cdFx0XHRtc2cgPSBmb3JtYXRDYWxscyhzcHksIG1zZyk7XG5cdFx0fVxuXHRcdGlmIChjYWxsZWQgJiYgaXNOb3QgfHwgIWNhbGxlZCAmJiAhaXNOb3QpIHtcblx0XHRcdHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihtc2cpO1xuXHRcdH1cblx0fSk7XG5cdC8vIG1hbnVhbGx5IGNvbXBhcmUgYXJyYXkgZWxlbWVudHMgc2luY2UgYGplc3RFcXVhbHNgIGNhbm5vdFxuXHQvLyBhcHBseSBhc3ltbWV0cmljIG1hdGNoZXIgdG8gYHVuZGVmaW5lZGAgYXJyYXkgZWxlbWVudC5cblx0ZnVuY3Rpb24gZXF1YWxzQXJndW1lbnRBcnJheShhLCBiKSB7XG5cdFx0cmV0dXJuIGEubGVuZ3RoID09PSBiLmxlbmd0aCAmJiBhLmV2ZXJ5KChhSXRlbSwgaSkgPT4gZXF1YWxzKGFJdGVtLCBiW2ldLCBbLi4uY3VzdG9tVGVzdGVycywgaXRlcmFibGVFcXVhbGl0eV0pKTtcblx0fVxuXHRkZWYoW1widG9IYXZlQmVlbkNhbGxlZFdpdGhcIiwgXCJ0b0JlQ2FsbGVkV2l0aFwiXSwgZnVuY3Rpb24oLi4uYXJncykge1xuXHRcdGNvbnN0IHNweSA9IGdldFNweSh0aGlzKTtcblx0XHRjb25zdCBzcHlOYW1lID0gc3B5LmdldE1vY2tOYW1lKCk7XG5cdFx0Y29uc3QgcGFzcyA9IHNweS5tb2NrLmNhbGxzLnNvbWUoKGNhbGxBcmcpID0+IGVxdWFsc0FyZ3VtZW50QXJyYXkoY2FsbEFyZywgYXJncykpO1xuXHRcdGNvbnN0IGlzTm90ID0gdXRpbHMuZmxhZyh0aGlzLCBcIm5lZ2F0ZVwiKTtcblx0XHRjb25zdCBtc2cgPSB1dGlscy5nZXRNZXNzYWdlKHRoaXMsIFtcblx0XHRcdHBhc3MsXG5cdFx0XHRgZXhwZWN0ZWQgXCIke3NweU5hbWV9XCIgdG8gYmUgY2FsbGVkIHdpdGggYXJndW1lbnRzOiAje2V4cH1gLFxuXHRcdFx0YGV4cGVjdGVkIFwiJHtzcHlOYW1lfVwiIHRvIG5vdCBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHM6ICN7ZXhwfWAsXG5cdFx0XHRhcmdzXG5cdFx0XSk7XG5cdFx0aWYgKHBhc3MgJiYgaXNOb3QgfHwgIXBhc3MgJiYgIWlzTm90KSB7XG5cdFx0XHR0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoZm9ybWF0Q2FsbHMoc3B5LCBtc2csIGFyZ3MpKTtcblx0XHR9XG5cdH0pO1xuXHRkZWYoXCJ0b0hhdmVCZWVuQ2FsbGVkRXhhY3RseU9uY2VXaXRoXCIsIGZ1bmN0aW9uKC4uLmFyZ3MpIHtcblx0XHRjb25zdCBzcHkgPSBnZXRTcHkodGhpcyk7XG5cdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdGNvbnN0IGNhbGxDb3VudCA9IHNweS5tb2NrLmNhbGxzLmxlbmd0aDtcblx0XHRjb25zdCBoYXNDYWxsV2l0aEFyZ3MgPSBzcHkubW9jay5jYWxscy5zb21lKChjYWxsQXJnKSA9PiBlcXVhbHNBcmd1bWVudEFycmF5KGNhbGxBcmcsIGFyZ3MpKTtcblx0XHRjb25zdCBwYXNzID0gaGFzQ2FsbFdpdGhBcmdzICYmIGNhbGxDb3VudCA9PT0gMTtcblx0XHRjb25zdCBpc05vdCA9IHV0aWxzLmZsYWcodGhpcywgXCJuZWdhdGVcIik7XG5cdFx0Y29uc3QgbXNnID0gdXRpbHMuZ2V0TWVzc2FnZSh0aGlzLCBbXG5cdFx0XHRwYXNzLFxuXHRcdFx0YGV4cGVjdGVkIFwiJHtzcHlOYW1lfVwiIHRvIGJlIGNhbGxlZCBvbmNlIHdpdGggYXJndW1lbnRzOiAje2V4cH1gLFxuXHRcdFx0YGV4cGVjdGVkIFwiJHtzcHlOYW1lfVwiIHRvIG5vdCBiZSBjYWxsZWQgb25jZSB3aXRoIGFyZ3VtZW50czogI3tleHB9YCxcblx0XHRcdGFyZ3Ncblx0XHRdKTtcblx0XHRpZiAocGFzcyAmJiBpc05vdCB8fCAhcGFzcyAmJiAhaXNOb3QpIHtcblx0XHRcdHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihmb3JtYXRDYWxscyhzcHksIG1zZywgYXJncykpO1xuXHRcdH1cblx0fSk7XG5cdGRlZihcInRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoXCIsIGZ1bmN0aW9uKHRpbWVzLCAuLi5hcmdzKSB7XG5cdFx0Y29uc3Qgc3B5ID0gZ2V0U3B5KHRoaXMpO1xuXHRcdGNvbnN0IHNweU5hbWUgPSBzcHkuZ2V0TW9ja05hbWUoKTtcblx0XHRjb25zdCBudGhDYWxsID0gc3B5Lm1vY2suY2FsbHNbdGltZXMgLSAxXTtcblx0XHRjb25zdCBjYWxsQ291bnQgPSBzcHkubW9jay5jYWxscy5sZW5ndGg7XG5cdFx0Y29uc3QgaXNDYWxsZWQgPSB0aW1lcyA8PSBjYWxsQ291bnQ7XG5cdFx0dGhpcy5hc3NlcnQobnRoQ2FsbCAmJiBlcXVhbHNBcmd1bWVudEFycmF5KG50aENhbGwsIGFyZ3MpLCBgZXhwZWN0ZWQgJHtvcmRpbmFsKHRpbWVzKX0gXCIke3NweU5hbWV9XCIgY2FsbCB0byBoYXZlIGJlZW4gY2FsbGVkIHdpdGggI3tleHB9JHtpc0NhbGxlZCA/IGBgIDogYCwgYnV0IGNhbGxlZCBvbmx5ICR7Y2FsbENvdW50fSB0aW1lc2B9YCwgYGV4cGVjdGVkICR7b3JkaW5hbCh0aW1lcyl9IFwiJHtzcHlOYW1lfVwiIGNhbGwgdG8gbm90IGhhdmUgYmVlbiBjYWxsZWQgd2l0aCAje2V4cH1gLCBhcmdzLCBudGhDYWxsLCBpc0NhbGxlZCk7XG5cdH0pO1xuXHRkZWYoXCJ0b0hhdmVCZWVuTGFzdENhbGxlZFdpdGhcIiwgZnVuY3Rpb24oLi4uYXJncykge1xuXHRcdGNvbnN0IHNweSA9IGdldFNweSh0aGlzKTtcblx0XHRjb25zdCBzcHlOYW1lID0gc3B5LmdldE1vY2tOYW1lKCk7XG5cdFx0Y29uc3QgbGFzdENhbGwgPSBzcHkubW9jay5jYWxscy5hdCgtMSk7XG5cdFx0dGhpcy5hc3NlcnQobGFzdENhbGwgJiYgZXF1YWxzQXJndW1lbnRBcnJheShsYXN0Q2FsbCwgYXJncyksIGBleHBlY3RlZCBsYXN0IFwiJHtzcHlOYW1lfVwiIGNhbGwgdG8gaGF2ZSBiZWVuIGNhbGxlZCB3aXRoICN7ZXhwfWAsIGBleHBlY3RlZCBsYXN0IFwiJHtzcHlOYW1lfVwiIGNhbGwgdG8gbm90IGhhdmUgYmVlbiBjYWxsZWQgd2l0aCAje2V4cH1gLCBhcmdzLCBsYXN0Q2FsbCk7XG5cdH0pO1xuXHQvKipcblx0KiBVc2VkIGZvciBgdG9IYXZlQmVlbkNhbGxlZEJlZm9yZWAgYW5kIGB0b0hhdmVCZWVuQ2FsbGVkQWZ0ZXJgIHRvIGRldGVybWluZSBpZiB0aGUgZXhwZWN0ZWQgc3B5IHdhcyBjYWxsZWQgYmVmb3JlIHRoZSByZXN1bHQgc3B5LlxuXHQqL1xuXHRmdW5jdGlvbiBpc1NweUNhbGxlZEJlZm9yZUFub3RoZXJTcHkoYmVmb3JlU3B5LCBhZnRlclNweSwgZmFpbElmTm9GaXJzdEludm9jYXRpb24pIHtcblx0XHRjb25zdCBiZWZvcmVJbnZvY2F0aW9uQ2FsbE9yZGVyID0gYmVmb3JlU3B5Lm1vY2suaW52b2NhdGlvbkNhbGxPcmRlcjtcblx0XHRjb25zdCBhZnRlckludm9jYXRpb25DYWxsT3JkZXIgPSBhZnRlclNweS5tb2NrLmludm9jYXRpb25DYWxsT3JkZXI7XG5cdFx0aWYgKGJlZm9yZUludm9jYXRpb25DYWxsT3JkZXIubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gIWZhaWxJZk5vRmlyc3RJbnZvY2F0aW9uO1xuXHRcdH1cblx0XHRpZiAoYWZ0ZXJJbnZvY2F0aW9uQ2FsbE9yZGVyLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gYmVmb3JlSW52b2NhdGlvbkNhbGxPcmRlclswXSA8IGFmdGVySW52b2NhdGlvbkNhbGxPcmRlclswXTtcblx0fVxuXHRkZWYoW1widG9IYXZlQmVlbkNhbGxlZEJlZm9yZVwiXSwgZnVuY3Rpb24ocmVzdWx0U3B5LCBmYWlsSWZOb0ZpcnN0SW52b2NhdGlvbiA9IHRydWUpIHtcblx0XHRjb25zdCBleHBlY3RTcHkgPSBnZXRTcHkodGhpcyk7XG5cdFx0aWYgKCFpc01vY2tGdW5jdGlvbihyZXN1bHRTcHkpKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKGAke3V0aWxzLmluc3BlY3QocmVzdWx0U3B5KX0gaXMgbm90IGEgc3B5IG9yIGEgY2FsbCB0byBhIHNweWApO1xuXHRcdH1cblx0XHR0aGlzLmFzc2VydChpc1NweUNhbGxlZEJlZm9yZUFub3RoZXJTcHkoZXhwZWN0U3B5LCByZXN1bHRTcHksIGZhaWxJZk5vRmlyc3RJbnZvY2F0aW9uKSwgYGV4cGVjdGVkIFwiJHtleHBlY3RTcHkuZ2V0TW9ja05hbWUoKX1cIiB0byBoYXZlIGJlZW4gY2FsbGVkIGJlZm9yZSBcIiR7cmVzdWx0U3B5LmdldE1vY2tOYW1lKCl9XCJgLCBgZXhwZWN0ZWQgXCIke2V4cGVjdFNweS5nZXRNb2NrTmFtZSgpfVwiIHRvIG5vdCBoYXZlIGJlZW4gY2FsbGVkIGJlZm9yZSBcIiR7cmVzdWx0U3B5LmdldE1vY2tOYW1lKCl9XCJgLCByZXN1bHRTcHksIGV4cGVjdFNweSk7XG5cdH0pO1xuXHRkZWYoW1widG9IYXZlQmVlbkNhbGxlZEFmdGVyXCJdLCBmdW5jdGlvbihyZXN1bHRTcHksIGZhaWxJZk5vRmlyc3RJbnZvY2F0aW9uID0gdHJ1ZSkge1xuXHRcdGNvbnN0IGV4cGVjdFNweSA9IGdldFNweSh0aGlzKTtcblx0XHRpZiAoIWlzTW9ja0Z1bmN0aW9uKHJlc3VsdFNweSkpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYCR7dXRpbHMuaW5zcGVjdChyZXN1bHRTcHkpfSBpcyBub3QgYSBzcHkgb3IgYSBjYWxsIHRvIGEgc3B5YCk7XG5cdFx0fVxuXHRcdHRoaXMuYXNzZXJ0KGlzU3B5Q2FsbGVkQmVmb3JlQW5vdGhlclNweShyZXN1bHRTcHksIGV4cGVjdFNweSwgZmFpbElmTm9GaXJzdEludm9jYXRpb24pLCBgZXhwZWN0ZWQgXCIke2V4cGVjdFNweS5nZXRNb2NrTmFtZSgpfVwiIHRvIGhhdmUgYmVlbiBjYWxsZWQgYWZ0ZXIgXCIke3Jlc3VsdFNweS5nZXRNb2NrTmFtZSgpfVwiYCwgYGV4cGVjdGVkIFwiJHtleHBlY3RTcHkuZ2V0TW9ja05hbWUoKX1cIiB0byBub3QgaGF2ZSBiZWVuIGNhbGxlZCBhZnRlciBcIiR7cmVzdWx0U3B5LmdldE1vY2tOYW1lKCl9XCJgLCByZXN1bHRTcHksIGV4cGVjdFNweSk7XG5cdH0pO1xuXHRkZWYoW1widG9UaHJvd1wiLCBcInRvVGhyb3dFcnJvclwiXSwgZnVuY3Rpb24oZXhwZWN0ZWQpIHtcblx0XHRpZiAodHlwZW9mIGV4cGVjdGVkID09PSBcInN0cmluZ1wiIHx8IHR5cGVvZiBleHBlY3RlZCA9PT0gXCJ1bmRlZmluZWRcIiB8fCBleHBlY3RlZCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuXHRcdFx0Ly8gRml4ZXMgdGhlIGlzc3VlIHJlbGF0ZWQgdG8gYGNoYWlgIDxodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzLzY2MTg+XG5cdFx0XHRyZXR1cm4gdGhpcy50aHJvd3MoZXhwZWN0ZWQgPT09IFwiXCIgPyAvXiQvIDogZXhwZWN0ZWQpO1xuXHRcdH1cblx0XHRjb25zdCBvYmogPSB0aGlzLl9vYmo7XG5cdFx0Y29uc3QgcHJvbWlzZSA9IHV0aWxzLmZsYWcodGhpcywgXCJwcm9taXNlXCIpO1xuXHRcdGNvbnN0IGlzTm90ID0gdXRpbHMuZmxhZyh0aGlzLCBcIm5lZ2F0ZVwiKTtcblx0XHRsZXQgdGhyb3duID0gbnVsbDtcblx0XHRpZiAocHJvbWlzZSA9PT0gXCJyZWplY3RzXCIpIHtcblx0XHRcdHRocm93biA9IG9iajtcblx0XHR9IGVsc2UgaWYgKHByb21pc2UgPT09IFwicmVzb2x2ZXNcIiAmJiB0eXBlb2Ygb2JqICE9PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdGlmICghaXNOb3QpIHtcblx0XHRcdFx0Y29uc3QgbWVzc2FnZSA9IHV0aWxzLmZsYWcodGhpcywgXCJtZXNzYWdlXCIpIHx8IFwiZXhwZWN0ZWQgcHJvbWlzZSB0byB0aHJvdyBhbiBlcnJvciwgYnV0IGl0IGRpZG4ndFwiO1xuXHRcdFx0XHRjb25zdCBlcnJvciA9IHsgc2hvd0RpZmY6IGZhbHNlIH07XG5cdFx0XHRcdHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihtZXNzYWdlLCBlcnJvciwgdXRpbHMuZmxhZyh0aGlzLCBcInNzZmlcIikpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgaXNUaHJvdyA9IGZhbHNlO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0b2JqKCk7XG5cdFx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdFx0aXNUaHJvdyA9IHRydWU7XG5cdFx0XHRcdHRocm93biA9IGVycjtcblx0XHRcdH1cblx0XHRcdGlmICghaXNUaHJvdyAmJiAhaXNOb3QpIHtcblx0XHRcdFx0Y29uc3QgbWVzc2FnZSA9IHV0aWxzLmZsYWcodGhpcywgXCJtZXNzYWdlXCIpIHx8IFwiZXhwZWN0ZWQgZnVuY3Rpb24gdG8gdGhyb3cgYW4gZXJyb3IsIGJ1dCBpdCBkaWRuJ3RcIjtcblx0XHRcdFx0Y29uc3QgZXJyb3IgPSB7IHNob3dEaWZmOiBmYWxzZSB9O1xuXHRcdFx0XHR0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IobWVzc2FnZSwgZXJyb3IsIHV0aWxzLmZsYWcodGhpcywgXCJzc2ZpXCIpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHR5cGVvZiBleHBlY3RlZCA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRjb25zdCBuYW1lID0gZXhwZWN0ZWQubmFtZSB8fCBleHBlY3RlZC5wcm90b3R5cGUuY29uc3RydWN0b3IubmFtZTtcblx0XHRcdHJldHVybiB0aGlzLmFzc2VydCh0aHJvd24gJiYgdGhyb3duIGluc3RhbmNlb2YgZXhwZWN0ZWQsIGBleHBlY3RlZCBlcnJvciB0byBiZSBpbnN0YW5jZSBvZiAke25hbWV9YCwgYGV4cGVjdGVkIGVycm9yIG5vdCB0byBiZSBpbnN0YW5jZSBvZiAke25hbWV9YCwgZXhwZWN0ZWQsIHRocm93bik7XG5cdFx0fVxuXHRcdGlmIChpc0Vycm9yKGV4cGVjdGVkKSkge1xuXHRcdFx0Y29uc3QgZXF1YWwgPSBlcXVhbHModGhyb3duLCBleHBlY3RlZCwgWy4uLmN1c3RvbVRlc3RlcnMsIGl0ZXJhYmxlRXF1YWxpdHldKTtcblx0XHRcdHJldHVybiB0aGlzLmFzc2VydChlcXVhbCwgXCJleHBlY3RlZCBhIHRocm93biBlcnJvciB0byBiZSAje2V4cH1cIiwgXCJleHBlY3RlZCBhIHRocm93biBlcnJvciBub3QgdG8gYmUgI3tleHB9XCIsIGV4cGVjdGVkLCB0aHJvd24pO1xuXHRcdH1cblx0XHRpZiAodHlwZW9mIGV4cGVjdGVkID09PSBcIm9iamVjdFwiICYmIFwiYXN5bW1ldHJpY01hdGNoXCIgaW4gZXhwZWN0ZWQgJiYgdHlwZW9mIGV4cGVjdGVkLmFzeW1tZXRyaWNNYXRjaCA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRjb25zdCBtYXRjaGVyID0gZXhwZWN0ZWQ7XG5cdFx0XHRyZXR1cm4gdGhpcy5hc3NlcnQodGhyb3duICYmIG1hdGNoZXIuYXN5bW1ldHJpY01hdGNoKHRocm93biksIFwiZXhwZWN0ZWQgZXJyb3IgdG8gbWF0Y2ggYXN5bW1ldHJpYyBtYXRjaGVyXCIsIFwiZXhwZWN0ZWQgZXJyb3Igbm90IHRvIG1hdGNoIGFzeW1tZXRyaWMgbWF0Y2hlclwiLCBtYXRjaGVyLCB0aHJvd24pO1xuXHRcdH1cblx0XHRjb25zdCBlcXVhbCA9IGVxdWFscyh0aHJvd24sIGV4cGVjdGVkLCBbLi4uY3VzdG9tVGVzdGVycywgaXRlcmFibGVFcXVhbGl0eV0pO1xuXHRcdHJldHVybiB0aGlzLmFzc2VydChlcXVhbCwgXCJleHBlY3RlZCBhIHRocm93biB2YWx1ZSB0byBlcXVhbCAje2V4cH1cIiwgXCJleHBlY3RlZCBhIHRocm93biB2YWx1ZSBub3QgdG8gZXF1YWwgI3tleHB9XCIsIGV4cGVjdGVkLCB0aHJvd24pO1xuXHR9KTtcblx0W3tcblx0XHRuYW1lOiBcInRvSGF2ZVJlc29sdmVkXCIsXG5cdFx0Y29uZGl0aW9uOiAoc3B5KSA9PiBzcHkubW9jay5zZXR0bGVkUmVzdWx0cy5sZW5ndGggPiAwICYmIHNweS5tb2NrLnNldHRsZWRSZXN1bHRzLnNvbWUoKHsgdHlwZSB9KSA9PiB0eXBlID09PSBcImZ1bGZpbGxlZFwiKSxcblx0XHRhY3Rpb246IFwicmVzb2x2ZWRcIlxuXHR9LCB7XG5cdFx0bmFtZTogW1widG9IYXZlUmV0dXJuZWRcIiwgXCJ0b1JldHVyblwiXSxcblx0XHRjb25kaXRpb246IChzcHkpID0+IHNweS5tb2NrLmNhbGxzLmxlbmd0aCA+IDAgJiYgc3B5Lm1vY2sucmVzdWx0cy5zb21lKCh7IHR5cGUgfSkgPT4gdHlwZSAhPT0gXCJ0aHJvd1wiKSxcblx0XHRhY3Rpb246IFwiY2FsbGVkXCJcblx0fV0uZm9yRWFjaCgoeyBuYW1lLCBjb25kaXRpb24sIGFjdGlvbiB9KSA9PiB7XG5cdFx0ZGVmKG5hbWUsIGZ1bmN0aW9uKCkge1xuXHRcdFx0Y29uc3Qgc3B5ID0gZ2V0U3B5KHRoaXMpO1xuXHRcdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdFx0Y29uc3QgcGFzcyA9IGNvbmRpdGlvbihzcHkpO1xuXHRcdFx0dGhpcy5hc3NlcnQocGFzcywgYGV4cGVjdGVkIFwiJHtzcHlOYW1lfVwiIHRvIGJlIHN1Y2Nlc3NmdWxseSAke2FjdGlvbn0gYXQgbGVhc3Qgb25jZWAsIGBleHBlY3RlZCBcIiR7c3B5TmFtZX1cIiB0byBub3QgYmUgc3VjY2Vzc2Z1bGx5ICR7YWN0aW9ufWAsIHBhc3MsICFwYXNzLCBmYWxzZSk7XG5cdFx0fSk7XG5cdH0pO1xuXHRbe1xuXHRcdG5hbWU6IFwidG9IYXZlUmVzb2x2ZWRUaW1lc1wiLFxuXHRcdGNvbmRpdGlvbjogKHNweSwgdGltZXMpID0+IHNweS5tb2NrLnNldHRsZWRSZXN1bHRzLnJlZHVjZSgocywgeyB0eXBlIH0pID0+IHR5cGUgPT09IFwiZnVsZmlsbGVkXCIgPyArK3MgOiBzLCAwKSA9PT0gdGltZXMsXG5cdFx0YWN0aW9uOiBcInJlc29sdmVkXCJcblx0fSwge1xuXHRcdG5hbWU6IFtcInRvSGF2ZVJldHVybmVkVGltZXNcIiwgXCJ0b1JldHVyblRpbWVzXCJdLFxuXHRcdGNvbmRpdGlvbjogKHNweSwgdGltZXMpID0+IHNweS5tb2NrLnJlc3VsdHMucmVkdWNlKChzLCB7IHR5cGUgfSkgPT4gdHlwZSA9PT0gXCJ0aHJvd1wiID8gcyA6ICsrcywgMCkgPT09IHRpbWVzLFxuXHRcdGFjdGlvbjogXCJjYWxsZWRcIlxuXHR9XS5mb3JFYWNoKCh7IG5hbWUsIGNvbmRpdGlvbiwgYWN0aW9uIH0pID0+IHtcblx0XHRkZWYobmFtZSwgZnVuY3Rpb24odGltZXMpIHtcblx0XHRcdGNvbnN0IHNweSA9IGdldFNweSh0aGlzKTtcblx0XHRcdGNvbnN0IHNweU5hbWUgPSBzcHkuZ2V0TW9ja05hbWUoKTtcblx0XHRcdGNvbnN0IHBhc3MgPSBjb25kaXRpb24oc3B5LCB0aW1lcyk7XG5cdFx0XHR0aGlzLmFzc2VydChwYXNzLCBgZXhwZWN0ZWQgXCIke3NweU5hbWV9XCIgdG8gYmUgc3VjY2Vzc2Z1bGx5ICR7YWN0aW9ufSAke3RpbWVzfSB0aW1lc2AsIGBleHBlY3RlZCBcIiR7c3B5TmFtZX1cIiB0byBub3QgYmUgc3VjY2Vzc2Z1bGx5ICR7YWN0aW9ufSAke3RpbWVzfSB0aW1lc2AsIGBleHBlY3RlZCByZXNvbHZlZCB0aW1lczogJHt0aW1lc31gLCBgcmVjZWl2ZWQgcmVzb2x2ZWQgdGltZXM6ICR7cGFzc31gLCBmYWxzZSk7XG5cdFx0fSk7XG5cdH0pO1xuXHRbe1xuXHRcdG5hbWU6IFwidG9IYXZlUmVzb2x2ZWRXaXRoXCIsXG5cdFx0Y29uZGl0aW9uOiAoc3B5LCB2YWx1ZSkgPT4gc3B5Lm1vY2suc2V0dGxlZFJlc3VsdHMuc29tZSgoeyB0eXBlLCB2YWx1ZTogcmVzdWx0IH0pID0+IHR5cGUgPT09IFwiZnVsZmlsbGVkXCIgJiYgZXF1YWxzKHZhbHVlLCByZXN1bHQpKSxcblx0XHRhY3Rpb246IFwicmVzb2x2ZVwiXG5cdH0sIHtcblx0XHRuYW1lOiBbXCJ0b0hhdmVSZXR1cm5lZFdpdGhcIiwgXCJ0b1JldHVybldpdGhcIl0sXG5cdFx0Y29uZGl0aW9uOiAoc3B5LCB2YWx1ZSkgPT4gc3B5Lm1vY2sucmVzdWx0cy5zb21lKCh7IHR5cGUsIHZhbHVlOiByZXN1bHQgfSkgPT4gdHlwZSA9PT0gXCJyZXR1cm5cIiAmJiBlcXVhbHModmFsdWUsIHJlc3VsdCkpLFxuXHRcdGFjdGlvbjogXCJyZXR1cm5cIlxuXHR9XS5mb3JFYWNoKCh7IG5hbWUsIGNvbmRpdGlvbiwgYWN0aW9uIH0pID0+IHtcblx0XHRkZWYobmFtZSwgZnVuY3Rpb24odmFsdWUpIHtcblx0XHRcdGNvbnN0IHNweSA9IGdldFNweSh0aGlzKTtcblx0XHRcdGNvbnN0IHBhc3MgPSBjb25kaXRpb24oc3B5LCB2YWx1ZSk7XG5cdFx0XHRjb25zdCBpc05vdCA9IHV0aWxzLmZsYWcodGhpcywgXCJuZWdhdGVcIik7XG5cdFx0XHRpZiAocGFzcyAmJiBpc05vdCB8fCAhcGFzcyAmJiAhaXNOb3QpIHtcblx0XHRcdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdFx0XHRjb25zdCBtc2cgPSB1dGlscy5nZXRNZXNzYWdlKHRoaXMsIFtcblx0XHRcdFx0XHRwYXNzLFxuXHRcdFx0XHRcdGBleHBlY3RlZCBcIiR7c3B5TmFtZX1cIiB0byAke2FjdGlvbn0gd2l0aDogI3tleHB9IGF0IGxlYXN0IG9uY2VgLFxuXHRcdFx0XHRcdGBleHBlY3RlZCBcIiR7c3B5TmFtZX1cIiB0byBub3QgJHthY3Rpb259IHdpdGg6ICN7ZXhwfWAsXG5cdFx0XHRcdFx0dmFsdWVcblx0XHRcdFx0XSk7XG5cdFx0XHRcdGNvbnN0IHJlc3VsdHMgPSBhY3Rpb24gPT09IFwicmV0dXJuXCIgPyBzcHkubW9jay5yZXN1bHRzIDogc3B5Lm1vY2suc2V0dGxlZFJlc3VsdHM7XG5cdFx0XHRcdHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihmb3JtYXRSZXR1cm5zKHNweSwgcmVzdWx0cywgbXNnLCB2YWx1ZSkpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblx0W3tcblx0XHRuYW1lOiBcInRvSGF2ZUxhc3RSZXNvbHZlZFdpdGhcIixcblx0XHRjb25kaXRpb246IChzcHksIHZhbHVlKSA9PiB7XG5cdFx0XHRjb25zdCByZXN1bHQgPSBzcHkubW9jay5zZXR0bGVkUmVzdWx0cy5hdCgtMSk7XG5cdFx0XHRyZXR1cm4gQm9vbGVhbihyZXN1bHQgJiYgcmVzdWx0LnR5cGUgPT09IFwiZnVsZmlsbGVkXCIgJiYgZXF1YWxzKHJlc3VsdC52YWx1ZSwgdmFsdWUpKTtcblx0XHR9LFxuXHRcdGFjdGlvbjogXCJyZXNvbHZlXCJcblx0fSwge1xuXHRcdG5hbWU6IFwidG9IYXZlTGFzdFJldHVybmVkV2l0aFwiLFxuXHRcdGNvbmRpdGlvbjogKHNweSwgdmFsdWUpID0+IHtcblx0XHRcdGNvbnN0IHJlc3VsdCA9IHNweS5tb2NrLnJlc3VsdHMuYXQoLTEpO1xuXHRcdFx0cmV0dXJuIEJvb2xlYW4ocmVzdWx0ICYmIHJlc3VsdC50eXBlID09PSBcInJldHVyblwiICYmIGVxdWFscyhyZXN1bHQudmFsdWUsIHZhbHVlKSk7XG5cdFx0fSxcblx0XHRhY3Rpb246IFwicmV0dXJuXCJcblx0fV0uZm9yRWFjaCgoeyBuYW1lLCBjb25kaXRpb24sIGFjdGlvbiB9KSA9PiB7XG5cdFx0ZGVmKG5hbWUsIGZ1bmN0aW9uKHZhbHVlKSB7XG5cdFx0XHRjb25zdCBzcHkgPSBnZXRTcHkodGhpcyk7XG5cdFx0XHRjb25zdCByZXN1bHRzID0gYWN0aW9uID09PSBcInJldHVyblwiID8gc3B5Lm1vY2sucmVzdWx0cyA6IHNweS5tb2NrLnNldHRsZWRSZXN1bHRzO1xuXHRcdFx0Y29uc3QgcmVzdWx0ID0gcmVzdWx0cy5hdCgtMSk7XG5cdFx0XHRjb25zdCBzcHlOYW1lID0gc3B5LmdldE1vY2tOYW1lKCk7XG5cdFx0XHR0aGlzLmFzc2VydChjb25kaXRpb24oc3B5LCB2YWx1ZSksIGBleHBlY3RlZCBsYXN0IFwiJHtzcHlOYW1lfVwiIGNhbGwgdG8gJHthY3Rpb259ICN7ZXhwfWAsIGBleHBlY3RlZCBsYXN0IFwiJHtzcHlOYW1lfVwiIGNhbGwgdG8gbm90ICR7YWN0aW9ufSAje2V4cH1gLCB2YWx1ZSwgcmVzdWx0Py52YWx1ZSk7XG5cdFx0fSk7XG5cdH0pO1xuXHRbe1xuXHRcdG5hbWU6IFwidG9IYXZlTnRoUmVzb2x2ZWRXaXRoXCIsXG5cdFx0Y29uZGl0aW9uOiAoc3B5LCBpbmRleCwgdmFsdWUpID0+IHtcblx0XHRcdGNvbnN0IHJlc3VsdCA9IHNweS5tb2NrLnNldHRsZWRSZXN1bHRzW2luZGV4IC0gMV07XG5cdFx0XHRyZXR1cm4gcmVzdWx0ICYmIHJlc3VsdC50eXBlID09PSBcImZ1bGZpbGxlZFwiICYmIGVxdWFscyhyZXN1bHQudmFsdWUsIHZhbHVlKTtcblx0XHR9LFxuXHRcdGFjdGlvbjogXCJyZXNvbHZlXCJcblx0fSwge1xuXHRcdG5hbWU6IFwidG9IYXZlTnRoUmV0dXJuZWRXaXRoXCIsXG5cdFx0Y29uZGl0aW9uOiAoc3B5LCBpbmRleCwgdmFsdWUpID0+IHtcblx0XHRcdGNvbnN0IHJlc3VsdCA9IHNweS5tb2NrLnJlc3VsdHNbaW5kZXggLSAxXTtcblx0XHRcdHJldHVybiByZXN1bHQgJiYgcmVzdWx0LnR5cGUgPT09IFwicmV0dXJuXCIgJiYgZXF1YWxzKHJlc3VsdC52YWx1ZSwgdmFsdWUpO1xuXHRcdH0sXG5cdFx0YWN0aW9uOiBcInJldHVyblwiXG5cdH1dLmZvckVhY2goKHsgbmFtZSwgY29uZGl0aW9uLCBhY3Rpb24gfSkgPT4ge1xuXHRcdGRlZihuYW1lLCBmdW5jdGlvbihudGhDYWxsLCB2YWx1ZSkge1xuXHRcdFx0Y29uc3Qgc3B5ID0gZ2V0U3B5KHRoaXMpO1xuXHRcdFx0Y29uc3Qgc3B5TmFtZSA9IHNweS5nZXRNb2NrTmFtZSgpO1xuXHRcdFx0Y29uc3QgcmVzdWx0cyA9IGFjdGlvbiA9PT0gXCJyZXR1cm5cIiA/IHNweS5tb2NrLnJlc3VsdHMgOiBzcHkubW9jay5zZXR0bGVkUmVzdWx0cztcblx0XHRcdGNvbnN0IHJlc3VsdCA9IHJlc3VsdHNbbnRoQ2FsbCAtIDFdO1xuXHRcdFx0Y29uc3Qgb3JkaW5hbENhbGwgPSBgJHtvcmRpbmFsKG50aENhbGwpfSBjYWxsYDtcblx0XHRcdHRoaXMuYXNzZXJ0KGNvbmRpdGlvbihzcHksIG50aENhbGwsIHZhbHVlKSwgYGV4cGVjdGVkICR7b3JkaW5hbENhbGx9IFwiJHtzcHlOYW1lfVwiIGNhbGwgdG8gJHthY3Rpb259ICN7ZXhwfWAsIGBleHBlY3RlZCAke29yZGluYWxDYWxsfSBcIiR7c3B5TmFtZX1cIiBjYWxsIHRvIG5vdCAke2FjdGlvbn0gI3tleHB9YCwgdmFsdWUsIHJlc3VsdD8udmFsdWUpO1xuXHRcdH0pO1xuXHR9KTtcblx0Ly8gQHRzLWV4cGVjdC1lcnJvciBAaW50ZXJuYWxcblx0ZGVmKFwid2l0aENvbnRleHRcIiwgZnVuY3Rpb24oY29udGV4dCkge1xuXHRcdGZvciAoY29uc3Qga2V5IGluIGNvbnRleHQpIHtcblx0XHRcdHV0aWxzLmZsYWcodGhpcywga2V5LCBjb250ZXh0W2tleV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSk7XG5cdHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgXCJyZXNvbHZlc1wiLCBmdW5jdGlvbiBfX1ZJVEVTVF9SRVNPTFZFU19fKCkge1xuXHRcdGNvbnN0IGVycm9yID0gbmV3IEVycm9yKFwicmVzb2x2ZXNcIik7XG5cdFx0dXRpbHMuZmxhZyh0aGlzLCBcInByb21pc2VcIiwgXCJyZXNvbHZlc1wiKTtcblx0XHR1dGlscy5mbGFnKHRoaXMsIFwiZXJyb3JcIiwgZXJyb3IpO1xuXHRcdGNvbnN0IHRlc3QgPSB1dGlscy5mbGFnKHRoaXMsIFwidml0ZXN0LXRlc3RcIik7XG5cdFx0Y29uc3Qgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCBcIm9iamVjdFwiKTtcblx0XHRpZiAodXRpbHMuZmxhZyh0aGlzLCBcInBvbGxcIikpIHtcblx0XHRcdHRocm93IG5ldyBTeW50YXhFcnJvcihgZXhwZWN0LnBvbGwoKSBpcyBub3Qgc3VwcG9ydGVkIGluIGNvbWJpbmF0aW9uIHdpdGggLnJlc29sdmVzYCk7XG5cdFx0fVxuXHRcdGlmICh0eXBlb2Ygb2JqPy50aGVuICE9PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYFlvdSBtdXN0IHByb3ZpZGUgYSBQcm9taXNlIHRvIGV4cGVjdCgpIHdoZW4gdXNpbmcgLnJlc29sdmVzLCBub3QgJyR7dHlwZW9mIG9ian0nLmApO1xuXHRcdH1cblx0XHRjb25zdCBwcm94eSA9IG5ldyBQcm94eSh0aGlzLCB7IGdldDogKHRhcmdldCwga2V5LCByZWNlaXZlcikgPT4ge1xuXHRcdFx0Y29uc3QgcmVzdWx0ID0gUmVmbGVjdC5nZXQodGFyZ2V0LCBrZXksIHJlY2VpdmVyKTtcblx0XHRcdGlmICh0eXBlb2YgcmVzdWx0ICE9PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdCBpbnN0YW5jZW9mIGNoYWkuQXNzZXJ0aW9uID8gcHJveHkgOiByZXN1bHQ7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gKC4uLmFyZ3MpID0+IHtcblx0XHRcdFx0dXRpbHMuZmxhZyh0aGlzLCBcIl9uYW1lXCIsIGtleSk7XG5cdFx0XHRcdGNvbnN0IHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUob2JqKS50aGVuKCh2YWx1ZSkgPT4ge1xuXHRcdFx0XHRcdHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIiwgdmFsdWUpO1xuXHRcdFx0XHRcdHJldHVybiByZXN1bHQuY2FsbCh0aGlzLCAuLi5hcmdzKTtcblx0XHRcdFx0fSwgKGVycikgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IF9lcnJvciA9IG5ldyBBc3NlcnRpb25FcnJvcihgcHJvbWlzZSByZWplY3RlZCBcIiR7dXRpbHMuaW5zcGVjdChlcnIpfVwiIGluc3RlYWQgb2YgcmVzb2x2aW5nYCwgeyBzaG93RGlmZjogZmFsc2UgfSk7XG5cdFx0XHRcdFx0X2Vycm9yLmNhdXNlID0gZXJyO1xuXHRcdFx0XHRcdHRocm93IF9lcnJvcjtcblx0XHRcdFx0fSkuY2F0Y2goKGVycikgPT4ge1xuXHRcdFx0XHRcdGlmIChpc0Vycm9yKGVycikgJiYgZXJyb3Iuc3RhY2spIHtcblx0XHRcdFx0XHRcdGVyci5zdGFjayA9IGVycm9yLnN0YWNrLnJlcGxhY2UoZXJyb3IubWVzc2FnZSwgZXJyLm1lc3NhZ2UpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0aHJvdyBlcnI7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm4gcmVjb3JkQXN5bmNFeHBlY3QodGVzdCwgcHJvbWlzZSwgY3JlYXRlQXNzZXJ0aW9uTWVzc2FnZSh1dGlscywgdGhpcywgISFhcmdzLmxlbmd0aCksIGVycm9yLCB1dGlscy5mbGFnKHRoaXMsIFwic29mdFwiKSk7XG5cdFx0XHR9O1xuXHRcdH0gfSk7XG5cdFx0cmV0dXJuIHByb3h5O1xuXHR9KTtcblx0dXRpbHMuYWRkUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBcInJlamVjdHNcIiwgZnVuY3Rpb24gX19WSVRFU1RfUkVKRUNUU19fKCkge1xuXHRcdGNvbnN0IGVycm9yID0gbmV3IEVycm9yKFwicmVqZWN0c1wiKTtcblx0XHR1dGlscy5mbGFnKHRoaXMsIFwicHJvbWlzZVwiLCBcInJlamVjdHNcIik7XG5cdFx0dXRpbHMuZmxhZyh0aGlzLCBcImVycm9yXCIsIGVycm9yKTtcblx0XHRjb25zdCB0ZXN0ID0gdXRpbHMuZmxhZyh0aGlzLCBcInZpdGVzdC10ZXN0XCIpO1xuXHRcdGNvbnN0IG9iaiA9IHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIik7XG5cdFx0Y29uc3Qgd3JhcHBlciA9IHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiA/IG9iaigpIDogb2JqO1xuXHRcdGlmICh1dGlscy5mbGFnKHRoaXMsIFwicG9sbFwiKSkge1xuXHRcdFx0dGhyb3cgbmV3IFN5bnRheEVycm9yKGBleHBlY3QucG9sbCgpIGlzIG5vdCBzdXBwb3J0ZWQgaW4gY29tYmluYXRpb24gd2l0aCAucmVqZWN0c2ApO1xuXHRcdH1cblx0XHRpZiAodHlwZW9mIHdyYXBwZXI/LnRoZW4gIT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgWW91IG11c3QgcHJvdmlkZSBhIFByb21pc2UgdG8gZXhwZWN0KCkgd2hlbiB1c2luZyAucmVqZWN0cywgbm90ICcke3R5cGVvZiB3cmFwcGVyfScuYCk7XG5cdFx0fVxuXHRcdGNvbnN0IHByb3h5ID0gbmV3IFByb3h5KHRoaXMsIHsgZ2V0OiAodGFyZ2V0LCBrZXksIHJlY2VpdmVyKSA9PiB7XG5cdFx0XHRjb25zdCByZXN1bHQgPSBSZWZsZWN0LmdldCh0YXJnZXQsIGtleSwgcmVjZWl2ZXIpO1xuXHRcdFx0aWYgKHR5cGVvZiByZXN1bHQgIT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0XHRyZXR1cm4gcmVzdWx0IGluc3RhbmNlb2YgY2hhaS5Bc3NlcnRpb24gPyBwcm94eSA6IHJlc3VsdDtcblx0XHRcdH1cblx0XHRcdHJldHVybiAoLi4uYXJncykgPT4ge1xuXHRcdFx0XHR1dGlscy5mbGFnKHRoaXMsIFwiX25hbWVcIiwga2V5KTtcblx0XHRcdFx0Y29uc3QgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSh3cmFwcGVyKS50aGVuKCh2YWx1ZSkgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IF9lcnJvciA9IG5ldyBBc3NlcnRpb25FcnJvcihgcHJvbWlzZSByZXNvbHZlZCBcIiR7dXRpbHMuaW5zcGVjdCh2YWx1ZSl9XCIgaW5zdGVhZCBvZiByZWplY3RpbmdgLCB7XG5cdFx0XHRcdFx0XHRzaG93RGlmZjogdHJ1ZSxcblx0XHRcdFx0XHRcdGV4cGVjdGVkOiBuZXcgRXJyb3IoXCJyZWplY3RlZCBwcm9taXNlXCIpLFxuXHRcdFx0XHRcdFx0YWN0dWFsOiB2YWx1ZVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdHRocm93IF9lcnJvcjtcblx0XHRcdFx0fSwgKGVycikgPT4ge1xuXHRcdFx0XHRcdHV0aWxzLmZsYWcodGhpcywgXCJvYmplY3RcIiwgZXJyKTtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0LmNhbGwodGhpcywgLi4uYXJncyk7XG5cdFx0XHRcdH0pLmNhdGNoKChlcnIpID0+IHtcblx0XHRcdFx0XHRpZiAoaXNFcnJvcihlcnIpICYmIGVycm9yLnN0YWNrKSB7XG5cdFx0XHRcdFx0XHRlcnIuc3RhY2sgPSBlcnJvci5zdGFjay5yZXBsYWNlKGVycm9yLm1lc3NhZ2UsIGVyci5tZXNzYWdlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGhyb3cgZXJyO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0cmV0dXJuIHJlY29yZEFzeW5jRXhwZWN0KHRlc3QsIHByb21pc2UsIGNyZWF0ZUFzc2VydGlvbk1lc3NhZ2UodXRpbHMsIHRoaXMsICEhYXJncy5sZW5ndGgpLCBlcnJvciwgdXRpbHMuZmxhZyh0aGlzLCBcInNvZnRcIikpO1xuXHRcdFx0fTtcblx0XHR9IH0pO1xuXHRcdHJldHVybiBwcm94eTtcblx0fSk7XG59O1xuZnVuY3Rpb24gZm9ybWF0Q2FsbHMoc3B5LCBtc2csIHNob3dBY3R1YWxDYWxsKSB7XG5cdGlmIChzcHkubW9jay5jYWxscy5sZW5ndGgpIHtcblx0XHRtc2cgKz0gYy5ncmF5KGBcXG5cXG5SZWNlaXZlZDpcXG5cXG4ke3NweS5tb2NrLmNhbGxzLm1hcCgoY2FsbEFyZywgaSkgPT4ge1xuXHRcdFx0bGV0IG1ldGhvZENhbGwgPSBjLmJvbGQoYCAgJHtvcmRpbmFsKGkgKyAxKX0gJHtzcHkuZ2V0TW9ja05hbWUoKX0gY2FsbDpcXG5cXG5gKTtcblx0XHRcdGlmIChzaG93QWN0dWFsQ2FsbCkge1xuXHRcdFx0XHRtZXRob2RDYWxsICs9IGRpZmYoc2hvd0FjdHVhbENhbGwsIGNhbGxBcmcsIHsgb21pdEFubm90YXRpb25MaW5lczogdHJ1ZSB9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG1ldGhvZENhbGwgKz0gc3RyaW5naWZ5KGNhbGxBcmcpLnNwbGl0KFwiXFxuXCIpLm1hcCgobGluZSkgPT4gYCAgICAke2xpbmV9YCkuam9pbihcIlxcblwiKTtcblx0XHRcdH1cblx0XHRcdG1ldGhvZENhbGwgKz0gXCJcXG5cIjtcblx0XHRcdHJldHVybiBtZXRob2RDYWxsO1xuXHRcdH0pLmpvaW4oXCJcXG5cIil9YCk7XG5cdH1cblx0bXNnICs9IGMuZ3JheShgXFxuXFxuTnVtYmVyIG9mIGNhbGxzOiAke2MuYm9sZChzcHkubW9jay5jYWxscy5sZW5ndGgpfVxcbmApO1xuXHRyZXR1cm4gbXNnO1xufVxuZnVuY3Rpb24gZm9ybWF0UmV0dXJucyhzcHksIHJlc3VsdHMsIG1zZywgc2hvd0FjdHVhbFJldHVybikge1xuXHRpZiAocmVzdWx0cy5sZW5ndGgpIHtcblx0XHRtc2cgKz0gYy5ncmF5KGBcXG5cXG5SZWNlaXZlZDpcXG5cXG4ke3Jlc3VsdHMubWFwKChjYWxsUmV0dXJuLCBpKSA9PiB7XG5cdFx0XHRsZXQgbWV0aG9kQ2FsbCA9IGMuYm9sZChgICAke29yZGluYWwoaSArIDEpfSAke3NweS5nZXRNb2NrTmFtZSgpfSBjYWxsIHJldHVybjpcXG5cXG5gKTtcblx0XHRcdGlmIChzaG93QWN0dWFsUmV0dXJuKSB7XG5cdFx0XHRcdG1ldGhvZENhbGwgKz0gZGlmZihzaG93QWN0dWFsUmV0dXJuLCBjYWxsUmV0dXJuLnZhbHVlLCB7IG9taXRBbm5vdGF0aW9uTGluZXM6IHRydWUgfSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtZXRob2RDYWxsICs9IHN0cmluZ2lmeShjYWxsUmV0dXJuKS5zcGxpdChcIlxcblwiKS5tYXAoKGxpbmUpID0+IGAgICAgJHtsaW5lfWApLmpvaW4oXCJcXG5cIik7XG5cdFx0XHR9XG5cdFx0XHRtZXRob2RDYWxsICs9IFwiXFxuXCI7XG5cdFx0XHRyZXR1cm4gbWV0aG9kQ2FsbDtcblx0XHR9KS5qb2luKFwiXFxuXCIpfWApO1xuXHR9XG5cdG1zZyArPSBjLmdyYXkoYFxcblxcbk51bWJlciBvZiBjYWxsczogJHtjLmJvbGQoc3B5Lm1vY2suY2FsbHMubGVuZ3RoKX1cXG5gKTtcblx0cmV0dXJuIG1zZztcbn1cblxuZnVuY3Rpb24gZ2V0TWF0Y2hlclN0YXRlKGFzc2VydGlvbiwgZXhwZWN0KSB7XG5cdGNvbnN0IG9iaiA9IGFzc2VydGlvbi5fb2JqO1xuXHRjb25zdCBpc05vdCA9IHV0aWwuZmxhZyhhc3NlcnRpb24sIFwibmVnYXRlXCIpO1xuXHRjb25zdCBwcm9taXNlID0gdXRpbC5mbGFnKGFzc2VydGlvbiwgXCJwcm9taXNlXCIpIHx8IFwiXCI7XG5cdGNvbnN0IGN1c3RvbU1lc3NhZ2UgPSB1dGlsLmZsYWcoYXNzZXJ0aW9uLCBcIm1lc3NhZ2VcIik7XG5cdGNvbnN0IGplc3RVdGlscyA9IHtcblx0XHQuLi5nZXRNYXRjaGVyVXRpbHMoKSxcblx0XHRkaWZmLFxuXHRcdHN0cmluZ2lmeSxcblx0XHRpdGVyYWJsZUVxdWFsaXR5LFxuXHRcdHN1YnNldEVxdWFsaXR5XG5cdH07XG5cdGxldCB0YXNrID0gdXRpbC5mbGFnKGFzc2VydGlvbiwgXCJ2aXRlc3QtdGVzdFwiKTtcblx0Y29uc3QgY3VycmVudFRlc3ROYW1lID0gdGFzaz8uZnVsbFRlc3ROYW1lID8/IFwiXCI7XG5cdGlmICh0YXNrPy50eXBlICE9PSBcInRlc3RcIikge1xuXHRcdHRhc2sgPSB1bmRlZmluZWQ7XG5cdH1cblx0Y29uc3QgbWF0Y2hlclN0YXRlID0ge1xuXHRcdC4uLmdldFN0YXRlKGV4cGVjdCksXG5cdFx0dGFzayxcblx0XHRjdXJyZW50VGVzdE5hbWUsXG5cdFx0Y3VzdG9tVGVzdGVyczogZ2V0Q3VzdG9tRXF1YWxpdHlUZXN0ZXJzKCksXG5cdFx0aXNOb3QsXG5cdFx0dXRpbHM6IGplc3RVdGlscyxcblx0XHRwcm9taXNlLFxuXHRcdGVxdWFscyxcblx0XHRzdXBwcmVzc2VkRXJyb3JzOiBbXSxcblx0XHRzb2Z0OiB1dGlsLmZsYWcoYXNzZXJ0aW9uLCBcInNvZnRcIiksXG5cdFx0cG9sbDogdXRpbC5mbGFnKGFzc2VydGlvbiwgXCJwb2xsXCIpXG5cdH07XG5cdHJldHVybiB7XG5cdFx0c3RhdGU6IG1hdGNoZXJTdGF0ZSxcblx0XHRpc05vdCxcblx0XHRvYmosXG5cdFx0Y3VzdG9tTWVzc2FnZVxuXHR9O1xufVxuY2xhc3MgSmVzdEV4dGVuZEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRjb25zdHJ1Y3RvcihtZXNzYWdlLCBhY3R1YWwsIGV4cGVjdGVkLCBjb250ZXh0KSB7XG5cdFx0c3VwZXIobWVzc2FnZSk7XG5cdFx0dGhpcy5hY3R1YWwgPSBhY3R1YWw7XG5cdFx0dGhpcy5leHBlY3RlZCA9IGV4cGVjdGVkO1xuXHRcdHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG5cdH1cbn1cbmZ1bmN0aW9uIEplc3RFeHRlbmRQbHVnaW4oYywgZXhwZWN0LCBtYXRjaGVycykge1xuXHRyZXR1cm4gKF8sIHV0aWxzKSA9PiB7XG5cdFx0T2JqZWN0LmVudHJpZXMobWF0Y2hlcnMpLmZvckVhY2goKFtleHBlY3RBc3NlcnRpb25OYW1lLCBleHBlY3RBc3NlcnRpb25dKSA9PiB7XG5cdFx0XHRmdW5jdGlvbiBleHBlY3RXcmFwcGVyKC4uLmFyZ3MpIHtcblx0XHRcdFx0Y29uc3QgeyBzdGF0ZSwgaXNOb3QsIG9iaiwgY3VzdG9tTWVzc2FnZSB9ID0gZ2V0TWF0Y2hlclN0YXRlKHRoaXMsIGV4cGVjdCk7XG5cdFx0XHRcdGNvbnN0IHJlc3VsdCA9IGV4cGVjdEFzc2VydGlvbi5jYWxsKHN0YXRlLCBvYmosIC4uLmFyZ3MpO1xuXHRcdFx0XHRpZiAocmVzdWx0ICYmIHR5cGVvZiByZXN1bHQgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHJlc3VsdC50aGVuID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHRjb25zdCB0aGVuYWJsZSA9IHJlc3VsdDtcblx0XHRcdFx0XHRyZXR1cm4gdGhlbmFibGUudGhlbigoeyBwYXNzLCBtZXNzYWdlLCBhY3R1YWwsIGV4cGVjdGVkLCBtZXRhIH0pID0+IHtcblx0XHRcdFx0XHRcdGlmIChwYXNzICYmIGlzTm90IHx8ICFwYXNzICYmICFpc05vdCkge1xuXHRcdFx0XHRcdFx0XHRjb25zdCBlcnJvck1lc3NhZ2UgPSBjdXN0b21NZXNzYWdlICE9IG51bGwgPyBjdXN0b21NZXNzYWdlIDogbWVzc2FnZSgpO1xuXHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgSmVzdEV4dGVuZEVycm9yKGVycm9yTWVzc2FnZSwgYWN0dWFsLCBleHBlY3RlZCwge1xuXHRcdFx0XHRcdFx0XHRcdGFzc2VydGlvbk5hbWU6IGV4cGVjdEFzc2VydGlvbk5hbWUsXG5cdFx0XHRcdFx0XHRcdFx0bWV0YVxuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCB7IHBhc3MsIG1lc3NhZ2UsIGFjdHVhbCwgZXhwZWN0ZWQsIG1ldGEgfSA9IHJlc3VsdDtcblx0XHRcdFx0aWYgKHBhc3MgJiYgaXNOb3QgfHwgIXBhc3MgJiYgIWlzTm90KSB7XG5cdFx0XHRcdFx0Y29uc3QgZXJyb3JNZXNzYWdlID0gY3VzdG9tTWVzc2FnZSAhPSBudWxsID8gY3VzdG9tTWVzc2FnZSA6IG1lc3NhZ2UoKTtcblx0XHRcdFx0XHR0aHJvdyBuZXcgSmVzdEV4dGVuZEVycm9yKGVycm9yTWVzc2FnZSwgYWN0dWFsLCBleHBlY3RlZCwge1xuXHRcdFx0XHRcdFx0YXNzZXJ0aW9uTmFtZTogZXhwZWN0QXNzZXJ0aW9uTmFtZSxcblx0XHRcdFx0XHRcdG1ldGFcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Y29uc3Qgc29mdFdyYXBwZXIgPSB3cmFwQXNzZXJ0aW9uKHV0aWxzLCBleHBlY3RBc3NlcnRpb25OYW1lLCBleHBlY3RXcmFwcGVyKTtcblx0XHRcdHV0aWxzLmFkZE1ldGhvZChnbG9iYWxUaGlzW0pFU1RfTUFUQ0hFUlNfT0JKRUNUXS5tYXRjaGVycywgZXhwZWN0QXNzZXJ0aW9uTmFtZSwgc29mdFdyYXBwZXIpO1xuXHRcdFx0dXRpbHMuYWRkTWV0aG9kKGMuQXNzZXJ0aW9uLnByb3RvdHlwZSwgZXhwZWN0QXNzZXJ0aW9uTmFtZSwgc29mdFdyYXBwZXIpO1xuXHRcdFx0Y2xhc3MgQ3VzdG9tTWF0Y2hlciBleHRlbmRzIEFzeW1tZXRyaWNNYXRjaGVyIHtcblx0XHRcdFx0Y29uc3RydWN0b3IoaW52ZXJzZSA9IGZhbHNlLCAuLi5zYW1wbGUpIHtcblx0XHRcdFx0XHRzdXBlcihzYW1wbGUsIGludmVyc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGFzeW1tZXRyaWNNYXRjaChvdGhlcikge1xuXHRcdFx0XHRcdGNvbnN0IHsgcGFzcyB9ID0gZXhwZWN0QXNzZXJ0aW9uLmNhbGwodGhpcy5nZXRNYXRjaGVyQ29udGV4dChleHBlY3QpLCBvdGhlciwgLi4udGhpcy5zYW1wbGUpO1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmludmVyc2UgPyAhcGFzcyA6IHBhc3M7XG5cdFx0XHRcdH1cblx0XHRcdFx0dG9TdHJpbmcoKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGAke3RoaXMuaW52ZXJzZSA/IFwibm90LlwiIDogXCJcIn0ke2V4cGVjdEFzc2VydGlvbk5hbWV9YDtcblx0XHRcdFx0fVxuXHRcdFx0XHRnZXRFeHBlY3RlZFR5cGUoKSB7XG5cdFx0XHRcdFx0cmV0dXJuIFwiYW55XCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0dG9Bc3ltbWV0cmljTWF0Y2hlcigpIHtcblx0XHRcdFx0XHRyZXR1cm4gYCR7dGhpcy50b1N0cmluZygpfTwke3RoaXMuc2FtcGxlLm1hcCgoaXRlbSkgPT4gc3RyaW5naWZ5KGl0ZW0pKS5qb2luKFwiLCBcIil9PmA7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGNvbnN0IGN1c3RvbU1hdGNoZXIgPSAoLi4uc2FtcGxlKSA9PiBuZXcgQ3VzdG9tTWF0Y2hlcihmYWxzZSwgLi4uc2FtcGxlKTtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBlY3QsIGV4cGVjdEFzc2VydGlvbk5hbWUsIHtcblx0XHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHR2YWx1ZTogY3VzdG9tTWF0Y2hlcixcblx0XHRcdFx0d3JpdGFibGU6IHRydWVcblx0XHRcdH0pO1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cGVjdC5ub3QsIGV4cGVjdEFzc2VydGlvbk5hbWUsIHtcblx0XHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHR2YWx1ZTogKC4uLnNhbXBsZSkgPT4gbmV3IEN1c3RvbU1hdGNoZXIodHJ1ZSwgLi4uc2FtcGxlKSxcblx0XHRcdFx0d3JpdGFibGU6IHRydWVcblx0XHRcdH0pO1xuXHRcdFx0Ly8ga2VlcCB0cmFjayBvZiBhc3ltbWV0cmljIG1hdGNoZXJzIG9uIGdsb2JhbCBzbyB0aGF0IGl0IGNhbiBiZSBjb3BpZWQgb3ZlciB0byBsb2NhbCBjb250ZXh0J3MgYGV4cGVjdGAuXG5cdFx0XHQvLyBub3RlIHRoYXQgdGhlIG5lZ2F0ZWQgdmFyaWFudCBpcyBhdXRvbWF0aWNhbGx5IHNoYXJlZCBzaW5jZSBpdCdzIGFzc2lnbmVkIG9uIHRoZSBzaW5nbGUgYGV4cGVjdC5ub3RgIG9iamVjdC5cblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShnbG9iYWxUaGlzW0FTWU1NRVRSSUNfTUFUQ0hFUlNfT0JKRUNUXSwgZXhwZWN0QXNzZXJ0aW9uTmFtZSwge1xuXHRcdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0XHRcdHZhbHVlOiBjdXN0b21NYXRjaGVyLFxuXHRcdFx0XHR3cml0YWJsZTogdHJ1ZVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH07XG59XG5jb25zdCBKZXN0RXh0ZW5kID0gKGNoYWksIHV0aWxzKSA9PiB7XG5cdHV0aWxzLmFkZE1ldGhvZChjaGFpLmV4cGVjdCwgXCJleHRlbmRcIiwgKGV4cGVjdCwgZXhwZWN0cykgPT4ge1xuXHRcdHVzZShKZXN0RXh0ZW5kUGx1Z2luKGNoYWksIGV4cGVjdCwgZXhwZWN0cykpO1xuXHR9KTtcbn07XG5cbmV4cG9ydCB7IEFTWU1NRVRSSUNfTUFUQ0hFUlNfT0JKRUNULCBBbnksIEFueXRoaW5nLCBBcnJheUNvbnRhaW5pbmcsIEFzeW1tZXRyaWNNYXRjaGVyLCBDaGFpU3R5bGVBc3NlcnRpb25zLCBHTE9CQUxfRVhQRUNULCBKRVNUX01BVENIRVJTX09CSkVDVCwgSmVzdEFzeW1tZXRyaWNNYXRjaGVycywgSmVzdENoYWlFeHBlY3QsIEplc3RFeHRlbmQsIE1BVENIRVJTX09CSkVDVCwgT2JqZWN0Q29udGFpbmluZywgU2NoZW1hTWF0Y2hpbmcsIFN0cmluZ0NvbnRhaW5pbmcsIFN0cmluZ01hdGNoaW5nLCBhZGRDdXN0b21FcXVhbGl0eVRlc3RlcnMsIGFycmF5QnVmZmVyRXF1YWxpdHksIGNyZWF0ZUFzc2VydGlvbk1lc3NhZ2UsIGN1c3RvbU1hdGNoZXJzLCBlcXVhbHMsIGZuTmFtZUZvciwgZ2VuZXJhdGVUb0JlTWVzc2FnZSwgZ2V0T2JqZWN0S2V5cywgZ2V0T2JqZWN0U3Vic2V0LCBnZXRTdGF0ZSwgaGFzQXN5bW1ldHJpYywgaGFzUHJvcGVydHksIGlzQSwgaXNBc3ltbWV0cmljLCBpc0Vycm9yLCBpc0ltbXV0YWJsZVVub3JkZXJlZEtleWVkLCBpc0ltbXV0YWJsZVVub3JkZXJlZFNldCwgaXNTdGFuZGFyZFNjaGVtYSwgaXRlcmFibGVFcXVhbGl0eSwgcGx1cmFsaXplLCByZWNvcmRBc3luY0V4cGVjdCwgc2V0U3RhdGUsIHNwYXJzZUFycmF5RXF1YWxpdHksIHN1YnNldEVxdWFsaXR5LCB0eXBlRXF1YWxpdHksIHdyYXBBc3NlcnRpb24gfTtcbiJdLCJ4X2dvb2dsZV9pZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVVBLE1BQU0sdUJBQXVCLE1BQU0sVUFBVTtDQUM1QyxTQUFTLFlBQVksTUFBTSxZQUFZO0FBQ3RDLFFBQU0sWUFBWSxLQUFLLFVBQVUsV0FBVyxNQUFNLFdBQVc7R0FDNUQsTUFBTSxhQUFhLEtBQUssVUFBVSxVQUFVO0FBQzVDLE9BQUksQ0FBQyxXQUNKLE9BQU0sSUFBSSxNQUFNLHNCQUFzQixPQUFPLFdBQVcsQ0FBQyxtRUFBbUU7QUFFN0gsVUFBTyxXQUFXLEtBQUssS0FBSztJQUMzQjs7Q0FFSCxTQUFTLG9CQUFvQixNQUFNLFlBQVksR0FBRyxNQUFNO0FBQ3ZELFFBQU0sWUFBWSxLQUFLLFVBQVUsV0FBVyxNQUFNLFdBQVc7R0FDNUQsTUFBTSxhQUFhLEtBQUssVUFBVSxVQUFVO0FBQzVDLE9BQUksQ0FBQyxXQUNKLE9BQU0sSUFBSSxNQUFNLHNCQUFzQixPQUFPLFdB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
|