cdk-nextjs 0.7.6 → 0.7.7

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.
Files changed (43) hide show
  1. package/.jsii +3 -3
  2. package/.jsii.tabl.json +1 -1
  3. package/README.md +12 -3
  4. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +31 -13
  5. package/docs/caching-guide.md +11 -1
  6. package/docs/harness-coverage.md +2 -1
  7. package/lib/adapter/aws-cache-store.d.ts +214 -3
  8. package/lib/adapter/aws-cache-store.js +470 -35
  9. package/lib/adapter/aws-cache-store.test.js +675 -3
  10. package/lib/adapter/cache-handler.mjs +421 -30
  11. package/lib/adapter/use-cache-common.d.ts +53 -1
  12. package/lib/adapter/use-cache-common.js +121 -14
  13. package/lib/adapter/use-cache-common.test.js +138 -1
  14. package/lib/adapter/use-cache-default-handler.js +36 -6
  15. package/lib/adapter/use-cache-default-handler.mjs +525 -42
  16. package/lib/adapter/use-cache-handlers.test.js +247 -7
  17. package/lib/adapter/use-cache-remote-handler.js +9 -7
  18. package/lib/adapter/use-cache-remote-handler.mjs +516 -40
  19. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +2 -1
  20. package/lib/lambdas/post-deploy/prune-revalidation-table.js +35 -13
  21. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +19 -1
  22. package/lib/nextjs-api.js +1 -1
  23. package/lib/nextjs-build/nextjs-build.js +1 -1
  24. package/lib/nextjs-cache.js +1 -1
  25. package/lib/nextjs-compute/nextjs-containers.js +1 -1
  26. package/lib/nextjs-compute/nextjs-functions.js +1 -1
  27. package/lib/nextjs-distribution.js +1 -1
  28. package/lib/nextjs-post-deploy.js +1 -1
  29. package/lib/nextjs-static-assets.js +1 -1
  30. package/lib/root-constructs/nextjs-base-construct.js +1 -1
  31. package/lib/root-constructs/nextjs-global-containers.js +1 -1
  32. package/lib/root-constructs/nextjs-global-functions.js +1 -1
  33. package/lib/root-constructs/nextjs-regional-containers.js +1 -1
  34. package/lib/root-constructs/nextjs-regional-functions.js +1 -1
  35. package/lib/runtime/core.js +18 -4
  36. package/lib/runtime/core.test.js +17 -1
  37. package/lib/runtime/lambda.mjs +16 -3
  38. package/lib/runtime/server.mjs +16 -3
  39. package/lib/runtime/tag-manifest.d.ts +15 -0
  40. package/lib/runtime/tag-manifest.js +24 -0
  41. package/lib/runtime/tag-manifest.test.d.ts +1 -0
  42. package/lib/runtime/tag-manifest.test.js +21 -0
  43. package/package.json +1 -1
@@ -57,19 +57,71 @@ export declare class EntryLru {
57
57
  private readonly maxBytes;
58
58
  private readonly entries;
59
59
  private bytes;
60
+ /**
61
+ * No later than the oldest entry's `timestamp`: the last scan's answer, less
62
+ * whatever was set since. Entries dropped since only make it early. See
63
+ * {@link oldestBound}.
64
+ */
65
+ private lowest;
60
66
  constructor(maxBytes: number);
61
67
  get(key: string): StoredEntry | undefined;
62
68
  set(key: string, entry: StoredEntry): void;
63
69
  delete(key: string): void;
70
+ /**
71
+ * The `timestamp` of the oldest entry held, `Infinity` with none, dropping
72
+ * on the way the entries past `revalidate` at `at` (`now()`): a handler
73
+ * that drops them when next read would otherwise hold them until then, and
74
+ * they would count here meanwhile. A scan, so asked once in a while: in
75
+ * between, {@link oldestBound} answers.
76
+ */
77
+ oldestTimestamp(at?: number): number;
78
+ /**
79
+ * No later than {@link oldestTimestamp}, without its scan: as of the last
80
+ * one, less the entries set since. `Infinity` with none held. Drops the
81
+ * entries past `revalidate` at `at` from the least recently used end, up to
82
+ * the first that isn't, so {@link holdsLive} doesn't walk past them on every
83
+ * request until the next scan.
84
+ */
85
+ oldestBound(at?: number): number;
86
+ /**
87
+ * Whether an entry not past `revalidate` at `at` is held. Usually the first
88
+ * entry answers; the expired ones it passes are dropped by the scan
89
+ * {@link oldestTimestamp} makes, not here, so asking changes nothing.
90
+ */
91
+ holdsLive(at: number): boolean;
64
92
  get size(): number;
65
93
  }
94
+ /** Whether `stored` is past `revalidate` at `at` (`now()`). */
95
+ export declare function isPastRevalidate(stored: StoredEntry, at: number): boolean;
66
96
  /** Default size of each handler's memory store: Next.js's default, 50 MB. */
67
97
  export declare const DEFAULT_MEMORY_BYTES: number;
98
+ /**
99
+ * How long one revalidation table request may take, per attempt. The SDK sets
100
+ * no limit, and a refresh left in flight across a Lambda freeze can sit on a
101
+ * connection that died meanwhile without a reset: every request that waits
102
+ * for the refresh (an instance `behind`, ISR) would wait with it. The SDK
103
+ * retries a timed-out attempt, so a dead connection costs up to its attempts
104
+ * times this.
105
+ */
106
+ export declare const TAG_TABLE_REQUEST_TIMEOUT_MS = 3000;
107
+ /**
108
+ * Wait for `work` if `wait`, or else let it run on: either way a rejection is
109
+ * logged with `failure` rather than thrown.
110
+ */
111
+ export declare function awaitIf(wait: boolean, work: Promise<void>, failure: string): Promise<void>;
112
+ export interface TagMethodsOptions {
113
+ /**
114
+ * Whether `refreshTags` always waits for the revalidation log query, rather
115
+ * than only when the instance is `behind`.
116
+ * @default false
117
+ */
118
+ readonly blocking?: boolean;
119
+ }
68
120
  /**
69
121
  * The `cacheHandlers` methods that only go through `tags`, the same for the
70
122
  * `default` and `remote` handlers.
71
123
  */
72
- export declare function tagMethods(tags: TrackedTagMarkers): Pick<CacheHandler, "refreshTags" | "getExpiration" | "updateTags">;
124
+ export declare function tagMethods(tags: TrackedTagMarkers, options?: TagMethodsOptions): Pick<CacheHandler, "refreshTags" | "updateTags">;
73
125
  /**
74
126
  * A handler built by `create` on first use rather than on import, so loading
75
127
  * the module - which jest, and Next.js's config validation, do without using
@@ -3,13 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_MEMORY_BYTES = exports.EntryLru = exports.PendingSets = exports.now = void 0;
6
+ exports.TAG_TABLE_REQUEST_TIMEOUT_MS = exports.DEFAULT_MEMORY_BYTES = exports.EntryLru = exports.PendingSets = exports.now = void 0;
7
7
  exports.isBuildPhase = isBuildPhase;
8
8
  exports.numberFromEnv = numberFromEnv;
9
9
  exports.readStream = readStream;
10
10
  exports.storedEntryOf = storedEntryOf;
11
11
  exports.cacheEntryOf = cacheEntryOf;
12
12
  exports.isDynamicEntry = isDynamicEntry;
13
+ exports.isPastRevalidate = isPastRevalidate;
14
+ exports.awaitIf = awaitIf;
13
15
  exports.tagMethods = tagMethods;
14
16
  exports.lazyHandler = lazyHandler;
15
17
  exports.sharedTagManifest = sharedTagManifest;
@@ -24,6 +26,7 @@ exports.sharedTagManifest = sharedTagManifest;
24
26
  const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
25
27
  const debug_1 = __importDefault(require("debug"));
26
28
  const aws_cache_store_1 = require("./aws-cache-store");
29
+ const tag_manifest_1 = require("../runtime/tag-manifest");
27
30
  var aws_cache_store_2 = require("./aws-cache-store");
28
31
  Object.defineProperty(exports, "now", { enumerable: true, get: function () { return aws_cache_store_2.markerClock; } });
29
32
  /** Whether this process is `next build` rather than a deployed server. */
@@ -133,6 +136,12 @@ class EntryLru {
133
136
  maxBytes;
134
137
  entries = new Map();
135
138
  bytes = 0;
139
+ /**
140
+ * No later than the oldest entry's `timestamp`: the last scan's answer, less
141
+ * whatever was set since. Entries dropped since only make it early. See
142
+ * {@link oldestBound}.
143
+ */
144
+ lowest = Infinity;
136
145
  constructor(maxBytes) {
137
146
  this.maxBytes = maxBytes;
138
147
  }
@@ -153,6 +162,7 @@ class EntryLru {
153
162
  }
154
163
  this.entries.set(key, entry);
155
164
  this.bytes += size;
165
+ this.lowest = Math.min(this.lowest, entry.timestamp);
156
166
  for (const [oldestKey, oldest] of this.entries) {
157
167
  if (this.bytes <= this.maxBytes) {
158
168
  break;
@@ -166,7 +176,59 @@ class EntryLru {
166
176
  if (existing) {
167
177
  this.entries.delete(key);
168
178
  this.bytes -= sizeOf(key, existing);
179
+ if (this.entries.size === 0) {
180
+ this.lowest = Infinity;
181
+ }
182
+ }
183
+ }
184
+ /**
185
+ * The `timestamp` of the oldest entry held, `Infinity` with none, dropping
186
+ * on the way the entries past `revalidate` at `at` (`now()`): a handler
187
+ * that drops them when next read would otherwise hold them until then, and
188
+ * they would count here meanwhile. A scan, so asked once in a while: in
189
+ * between, {@link oldestBound} answers.
190
+ */
191
+ oldestTimestamp(at = -Infinity) {
192
+ let oldest = Infinity;
193
+ for (const [key, entry] of this.entries) {
194
+ if (isPastRevalidate(entry, at)) {
195
+ this.delete(key);
196
+ }
197
+ else {
198
+ oldest = Math.min(oldest, entry.timestamp);
199
+ }
200
+ }
201
+ this.lowest = oldest;
202
+ return oldest;
203
+ }
204
+ /**
205
+ * No later than {@link oldestTimestamp}, without its scan: as of the last
206
+ * one, less the entries set since. `Infinity` with none held. Drops the
207
+ * entries past `revalidate` at `at` from the least recently used end, up to
208
+ * the first that isn't, so {@link holdsLive} doesn't walk past them on every
209
+ * request until the next scan.
210
+ */
211
+ oldestBound(at = -Infinity) {
212
+ for (const [key, entry] of this.entries) {
213
+ if (!isPastRevalidate(entry, at)) {
214
+ break;
215
+ }
216
+ this.delete(key);
169
217
  }
218
+ return this.entries.size === 0 ? Infinity : this.lowest;
219
+ }
220
+ /**
221
+ * Whether an entry not past `revalidate` at `at` is held. Usually the first
222
+ * entry answers; the expired ones it passes are dropped by the scan
223
+ * {@link oldestTimestamp} makes, not here, so asking changes nothing.
224
+ */
225
+ holdsLive(at) {
226
+ for (const entry of this.entries.values()) {
227
+ if (!isPastRevalidate(entry, at)) {
228
+ return true;
229
+ }
230
+ }
231
+ return false;
170
232
  }
171
233
  get size() {
172
234
  return this.entries.size;
@@ -176,19 +238,53 @@ exports.EntryLru = EntryLru;
176
238
  function sizeOf(key, entry) {
177
239
  return entry.value.byteLength + key.length;
178
240
  }
241
+ /** Whether `stored` is past `revalidate` at `at` (`now()`). */
242
+ function isPastRevalidate(stored, at) {
243
+ return at > stored.timestamp + stored.revalidate * 1000;
244
+ }
179
245
  /** Default size of each handler's memory store: Next.js's default, 50 MB. */
180
246
  exports.DEFAULT_MEMORY_BYTES = 50 * 1024 * 1024;
247
+ /**
248
+ * How long one revalidation table request may take, per attempt. The SDK sets
249
+ * no limit, and a refresh left in flight across a Lambda freeze can sit on a
250
+ * connection that died meanwhile without a reset: every request that waits
251
+ * for the refresh (an instance `behind`, ISR) would wait with it. The SDK
252
+ * retries a timed-out attempt, so a dead connection costs up to its attempts
253
+ * times this.
254
+ */
255
+ exports.TAG_TABLE_REQUEST_TIMEOUT_MS = 3000;
256
+ /**
257
+ * Wait for `work` if `wait`, or else let it run on: either way a rejection is
258
+ * logged with `failure` rather than thrown.
259
+ */
260
+ async function awaitIf(wait, work, failure) {
261
+ const logged = work.catch((error) => {
262
+ console.error(failure, error);
263
+ });
264
+ if (wait) {
265
+ await logged;
266
+ }
267
+ }
181
268
  /**
182
269
  * The `cacheHandlers` methods that only go through `tags`, the same for the
183
270
  * `default` and `remote` handlers.
184
271
  */
185
- function tagMethods(tags) {
272
+ function tagMethods(tags, options = {}) {
186
273
  return {
187
- refreshTags: () => tags.refresh(),
188
- async getExpiration(implicitTags) {
189
- await tags.ensure(implicitTags);
190
- return tags.expiration(implicitTags);
191
- },
274
+ // Started, not awaited, while the instance keeps up, unless `blocking`.
275
+ // Next.js awaits `refreshTags` inside the first `'use cache'` lookup of a
276
+ // request (`use-cache-wrapper`), and a staged render ends its static stage
277
+ // on a timer: a log `Query` there pushed the entry out of the static
278
+ // stage, so a cached navigation stored the page segment without it. What
279
+ // the query finds applies from the next request. Awaited once the instance
280
+ // is `behind`, which the runtime settles before a page render starts
281
+ // (`catchUp`): the first request after an idle or frozen spell would
282
+ // otherwise serve whatever was revalidated elsewhere meanwhile. A page's
283
+ // render just after `catchUp` gets a grace more (`behindInRender`), so a
284
+ // request that came in just short of the line doesn't cross it inside
285
+ // the render. Not even then while the instance holds no entry the query
286
+ // could expire (`holdsEntries`), with a `refreshIntervalMs` of `0` too.
287
+ refreshTags: () => awaitIf(options.blocking === true || (tags.behindInRender && tags.holdsEntries), tags.refresh(), "Error refreshing cache tags:"),
192
288
  async updateTags(revalidatedTags, durations) {
193
289
  await tags.update(revalidatedTags, durations);
194
290
  },
@@ -210,7 +306,6 @@ function lazyHandler(create) {
210
306
  updateTags: (tags, durations) => instance().updateTags(tags, durations),
211
307
  };
212
308
  }
213
- const TAG_MANIFEST_SYMBOL = Symbol.for("cdk-nextjs.use-cache.tag-manifest");
214
309
  /**
215
310
  * The process's one {@link TrackedTagMarkers}, from the environment.
216
311
  *
@@ -224,27 +319,39 @@ const TAG_MANIFEST_SYMBOL = Symbol.for("cdk-nextjs.use-cache.tag-manifest");
224
319
  */
225
320
  function sharedTagManifest() {
226
321
  const global = globalThis;
227
- if (!global[TAG_MANIFEST_SYMBOL]) {
322
+ if (!global[tag_manifest_1.TAG_MANIFEST_SYMBOL]) {
228
323
  const config = (0, aws_cache_store_1.resolveAwsCacheConfig)();
229
324
  const refreshIntervalMs = numberFromEnv("CDK_NEXTJS_TAG_REFRESH_MS", aws_cache_store_1.DEFAULT_TAG_REFRESH_MS);
230
325
  if (config.tableName && !isBuildPhase()) {
231
- const client = new client_dynamodb_1.DynamoDBClient({ region: config.region });
232
- global[TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
326
+ const client = new client_dynamodb_1.DynamoDBClient({
327
+ region: config.region,
328
+ // Without `throwOnRequestTimeout` the timeout only logs a warning. It
329
+ // ends once the response headers arrive: `socketTimeout`, an
330
+ // inactivity timer kept until the request closes, covers the body.
331
+ requestHandler: {
332
+ requestTimeout: exports.TAG_TABLE_REQUEST_TIMEOUT_MS,
333
+ throwOnRequestTimeout: true,
334
+ socketTimeout: exports.TAG_TABLE_REQUEST_TIMEOUT_MS,
335
+ },
336
+ });
337
+ global[tag_manifest_1.TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
233
338
  markers: new aws_cache_store_1.TagMarkerTable(client, config.tableName, config.buildId),
234
339
  log: new aws_cache_store_1.RevalidationLog(client, config.tableName, config.buildId),
235
340
  refreshIntervalMs,
236
341
  debug: (0, debug_1.default)("cdk-nextjs:cache-handler:tags"),
342
+ // Set in every Lambda runtime; a container is never frozen.
343
+ canFreeze: process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined,
237
344
  });
238
345
  }
239
346
  else {
240
347
  if (!isBuildPhase()) {
241
348
  console.warn("CDK_NEXTJS_REVALIDATION_TABLE_NAME environment variable not set, cache tags are local to each instance");
242
349
  }
243
- global[TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
350
+ global[tag_manifest_1.TAG_MANIFEST_SYMBOL] = new aws_cache_store_1.TrackedTagMarkers({
244
351
  refreshIntervalMs,
245
352
  });
246
353
  }
247
354
  }
248
- return global[TAG_MANIFEST_SYMBOL];
355
+ return global[tag_manifest_1.TAG_MANIFEST_SYMBOL];
249
356
  }
250
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlLWNhY2hlLWNvbW1vbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL3VzZS1jYWNoZS1jb21tb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBeUJBLG9DQUVDO0FBR0Qsc0NBSUM7QUFrQkQsZ0NBcUJDO0FBR0Qsc0NBS0M7QUFHRCxvQ0FnQkM7QUFPRCx3Q0FFQztBQWtHRCxnQ0FhQztBQU9ELGtDQVVDO0FBZUQsOENBNEJDO0FBeFJEOzs7Ozs7RUFNRTtBQUNGLHNEQUFzRDtBQUN0RCw4REFBMEQ7QUFDMUQsa0RBQTZCO0FBSzdCLHVEQU0yQjtBQUUzQixxREFBdUQ7QUFBOUMsc0dBQUEsV0FBVyxPQUFPO0FBRTNCLDBFQUEwRTtBQUMxRSxTQUFnQixZQUFZO0lBQzFCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEtBQUssd0JBQXdCLENBQUM7QUFDN0QsQ0FBQztBQUVELDhEQUE4RDtBQUM5RCxTQUFnQixhQUFhLENBQUMsSUFBWSxFQUFFLFFBQWdCO0lBQzFELE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUIsTUFBTSxLQUFLLEdBQUcsR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsRSxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7QUFDakUsQ0FBQztBQVVEOzs7Ozs7O0dBT0c7QUFDSSxLQUFLLFVBQVUsVUFBVSxDQUM5QixNQUFrQztJQUVsQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbEMsTUFBTSxNQUFNLEdBQWlCLEVBQUUs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QUFBLHVDQUFxQixHQUFFLENBQUM7UUFDdkMsTUFBTSxpQkFBaUIsR0FBRyxhQUFhLENBQ3JDLDJCQUEyQixFQUMzQix3Q0FBc0IsQ0FDdkIsQ0FBQztRQUNGLElBQUksTUFBTSxDQUFDLFNBQVMsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7WUFDeEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxnQ0FBYyxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzdELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLElBQUksbUNBQWlCLENBQUM7Z0JBQ2xELE9BQU8sRUFBRSxJQUFJLGdDQUFjLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQztnQkFDckUsR0FBRyxFQUFFLElBQUksaUNBQWUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDO2dCQUNsRSxpQkFBaUI7Z0JBQ2pCLEtBQUssRUFBRSxJQUFBLGVBQVEsRUFBQywrQkFBK0IsQ0FBQzthQUNqRCxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO2dCQUNwQixPQUFPLENBQUMsSUFBSSxDQUNWLHdHQUF3RyxDQUN6RyxDQUFDO1lBQ0osQ0FBQztZQUNELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLElBQUksbUNBQWlCLENBQUM7Z0JBQ2xELGlCQUFpQjthQUNsQixDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIFdoYXQgdGhlIHR3byBgY2FjaGVIYW5kbGVyc2AgKGAndXNlIGNhY2hlJ2AgYW5kIGAndXNlIGNhY2hlOiByZW1vdGUnYCkgc2hhcmU6XG4gIHRoZSBpbi1tZW1vcnkgZW50cnkgc3RvcmUsIHRoZSBwZW5kaW5nLWBzZXRgIGJvb2trZWVwaW5nIE5leHQuanMgcmVxdWlyZXMgb2ZcbiAgZXZlcnkgaGFuZGxlciwgYW5kIHRoZSBwcm9jZXNzJ3Mgb25lIHRhZyBtYW5pZmVzdCAoYFRyYWNrZWRUYWdNYXJrZXJzYCksXG4gIHdoaWNoIG1ha2VzIGByZXZhbGlkYXRlVGFnYCByZWFjaCBldmVyeSBpbnN0YW5jZSB0aHJvdWdoIHRoZSByZXZhbGlkYXRpb25cbiAgdGFibGUncyBtYXJrZXIgcm93cy5cbiovXG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCB7IER5bmFtb0RCQ2xpZW50IH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1keW5hbW9kYlwiO1xuaW1wb3J0IGdldERlYnVnIGZyb20gXCJkZWJ1Z1wiO1xuaW1wb3J0IHR5cGUge1xuICBDYWNoZUVudHJ5LFxuICBDYWNoZUhhbmRsZXIsXG59IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL2xpYi9jYWNoZS1oYW5kbGVycy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9UQUdfUkVGUkVTSF9NUyxcbiAgcmVzb2x2ZUF3c0NhY2hlQ29uZmlnLFxuICBSZXZhbGlkYXRpb25Mb2csXG4gIFRhZ01hcmtlclRhYmxlLFxuICBUcmFja2VkVGFnTWFya2Vycyxcbn0gZnJvbSBcIi4vYXdzLWNhY2hlLXN0b3JlXCI7XG5cbmV4cG9ydCB7IG1hcmtlckNsb2NrIGFzIG5vdyB9IGZyb20gXCIuL2F3cy1jYWNoZS1zdG9yZVwiO1xuXG4vKiogV2hldGhlciB0aGlzIHByb2Nlc3MgaXMgYG5leHQgYnVpbGRgIHJhdGhlciB0aGFuIGEgZGVwbG95ZWQgc2VydmVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQnVpbGRQaGFzZSgpOiBib29sZWFuIHtcbiAgcmV0dXJuIHByb2Nlc3MuZW52Lk5FWFRfUEhBU0UgPT09IFwicGhhc2UtcHJvZHVjdGlvbi1idWlsZFwiO1xufVxuXG4vKiogQSBwb3NpdGl2ZSBpbnRlZ2VyIGVudmlyb25tZW50IHZhcmlhYmxlLCBvciBgZmFsbGJhY2tgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG51bWJlckZyb21FbnYobmFtZTogc3RyaW5nLCBmYWxsYmFjazogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnZbbmFtZV07XG4gIGNvbnN0IHZhbHVlID0gcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSBcIlwiID8gTmFOIDogTnVtYmVyKHJhdyk7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpICYmIHZhbHVlID49IDAgPyB2YWx1ZSA6IGZhbGxiYWNrO1xufVxuXG4vKipcbiAqIEEgYENhY2hlRW50cnlgIHdpdGggaXRzIHZhbHVlIHJlYWQgdG8gdGhlIGVuZDogdGhlIGJ5dGVzIGFyZSB3aGF0IGlzIGtlcHQsXG4gKiBhbmQgZXZlcnkgYGdldGAgaGFuZHMgb3V0IGEgZnJlc2ggc3RyZWFtIG92ZXIgdGhlbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdG9yZWRFbnRyeSBleHRlbmRzIE9taXQ8Q2FjaGVFbnRyeSwgXCJ2YWx1ZVwiPiB7XG4gIHZhbHVlOiBVaW50OEFycmF5O1xufVxuXG4vKipcbiAqIFJlYWQgYHN0cmVhbWAgdG8gdGhlIGVuZCwgb3IgdGhyb3cgaWYgaXQgZXJyb3JzLlxuICpcbiAqIGBDYWNoZUVudHJ5LnZhbHVlYCBcImNhbiBlcnJvciBhbmQgb25seSBoYXZlIHBhcnRpYWwgZGF0YVwiIChOZXh0LmpzJ3NcbiAqIGBjYWNoZS1oYW5kbGVycy90eXBlcy5kLnRzYCkuIFRocm93aW5nIGlzIGhvdyBhIHBhcnRpYWwgZW50cnkgaXMga2VwdCBvdXQ6XG4gKiBib3RoIGhhbmRsZXJzIHN0b3JlIG5vdGhpbmcgd2hlbiB0aGlzIHJlamVjdHMsIHdoaWNoIGlzIHdoYXQgTmV4dC5qcydzIG93blxuICogZGVmYXVsdCBoYW5kbGVyIGRvZXMgdG9vLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFN0cmVhbShcbiAgc3RyZWFtOiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pixcbik6IFByb21pc2U8VWludDhBcnJheT4ge1xuICBjb25zdCByZWFkZXIgPSBzdHJlYW0uZ2V0UmVhZGVyKCk7XG4gIGNvbnN0IGNodW5rczogVWludDhBcnJheVtdID0gW107XG4gIGxldCBzaXplID0gMDtcbiAgZm9yICg7Oykge1xuICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjaHVua3MucHVzaCh2YWx1ZSk7XG4gICAgc2l6ZSArPSB2YWx1ZS5ieXRlTGVuZ3RoO1xuICB9XG4gIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gIGxldCBvZmZzZXQgPSAwO1xuICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykge1xuICAgIGJ5dGVzLnNldChjaHVuaywgb2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gY2h1bmsuYnl0ZUxlbmd0aDtcbiAgfVxuICByZXR1cm4gYnl0ZXM7XG59XG5cbi8qKiBgcGVuZGluZ0VudHJ5YCByZXNvbHZlZCBhbmQgcmVhZCB0byB0aGUgZW5kLiBTZWUge0BsaW5rIHJlYWRTdHJlYW19LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0b3JlZEVudHJ5T2YoXG4gIHBlbmRpbmdFbnRyeTogUHJvbWlzZTxDYWNoZUVudHJ5Pixcbik6IFByb21pc2U8U3RvcmVkRW50cnk+IHtcbiAgY29uc3QgZW50cnkgPSBhd2FpdCBwZW5kaW5nRW50cnk7XG4gIHJldHVybiB7IC4uLmVudHJ5LCB2YWx1ZTogYXdhaXQgcmVhZFN0cmVhbShlbnRyeS52YWx1ZSkgfTtcbn1cblxuLyoqIGBzdG9yZWRgIGFzIHRoZSBgQ2FjaGVFbnRyeWAgYSBgZ2V0YCByZXR1cm5zLCB3aXRoIGl0cyBvd24gc3RyZWFtLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhY2hlRW50cnlPZihcbiAgc3RvcmVkOiBTdG9yZWRFbnRyeSxcbiAgcmV2YWxpZGF0ZTogbnVtYmVyID0gc3RvcmVkLnJldmFsaWRhdGUsXG4pOiBDYWNoZUVudHJ5IHtcbiAgY29uc3QgYnl0ZXMgPSBzdG9yZWQudmFsdWU7XG4gIHJldHVybiB7XG4gICAgLi4uc3RvcmVkLFxuICAgIHJldmFsaWRhdGUsXG4gICAgdmFsdWU6IG5ldyBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pih7XG4gICAgICBzdGFydChjb250cm9sbGVyKSB7XG4gICAgICAgIC8vIEEgY29weTogd2hvZXZlciByZWFkcyB0aGUgc3RyZWFtIG1heSB0cmFuc2ZlciBvciBtdXRhdGUgdGhlIGNodW5rLlxuICAgICAgICBjb250cm9sbGVyLmVucXVldWUoYnl0ZXMuc2xpY2UoKSk7XG4gICAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICAgIH0sXG4gICAgfSksXG4gIH07XG59XG5cbi8qKlxuICogV2hldGhlciBOZXh0LmpzIHdvdWxkIHJlZ2VuZXJhdGUgYGVudHJ5YCBvbiBldmVyeSByZWFkIGFueXdheSwgc28gc3RvcmluZyBpdFxuICogaXMgYSB3cml0ZSBub3RoaW5nIHJlYWRzIGJhY2suIE5leHQuanMncyBkZWZhdWx0IGhhbmRsZXIgc2tpcHMgdGhlc2UgdGhlIHNhbWVcbiAqIHdheSwgb3V0c2lkZSB0aGUgZGV2IHNlcnZlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRHluYW1pY0VudHJ5KGVudHJ5OiBQaWNrPENhY2hlRW50cnksIFwiZXhwaXJlXCI+KTogYm9vbGVhbiB7XG4gIHJldHVybiBlbnRyeS5leHBpcmUgPT09IDA7XG59XG5cbi8qKlxuICogVGhlIGluLWZsaWdodCBgc2V0YHMsIGJ5IGNhY2hlIGtleS4gYENhY2hlSGFuZGxlci5zZXRgIHJlY2VpdmVzIGFuIGVudHJ5IHRoYXRcbiAqIG1heSBzdGlsbCBiZSBzdHJlYW1pbmcsIGFuZCBcImlmIGEgYGdldGAgZm9yIHRoZSBzYW1lIGNhY2hlIGtleSBpcyBjYWxsZWRcbiAqIGJlZm9yZSB0aGUgcGVuZGluZyBlbnRyeSBpcyBjb21wbGV0ZSwgdGhlIGNhY2hlIGhhbmRsZXIgbXVzdCB3YWl0IGZvciB0aGVcbiAqIGBzZXRgIG9wZXJhdGlvbiB0byBmaW5pc2hcIiAoYGNhY2hlLWhhbmRsZXJzL3R5cGVzLmQudHNgKS5cbiAqL1xuZXhwb3J0IGNsYXNzIFBlbmRpbmdTZXRzIHtcbiAgcHJpdmF0ZSByZWFkb25seSBwZW5kaW5nID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG5cbiAgLyoqIFJlc29sdmVzIG9uY2Ugbm8gYHNldGAgZm9yIGBrZXlgIGlzIGluIGZsaWdodC4gKi9cbiAgYXN5bmMgd2FpdChrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAobGV0IHAgPSB0aGlzLnBlbmRpbmcuZ2V0KGtleSk7IHA7IHAgPSB0aGlzLnBlbmRpbmcuZ2V0KGtleSkpIHtcbiAgICAgIGF3YWl0IHA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgYHNldGAgZm9yIGBrZXlgIGFuZCByZXR1cm4gdGhlIGZ1bmN0aW9uIHRoYXQgZW5kcyBpdC4gU2FmZSB0b1xuICAgKiBjYWxsIG1vcmUgdGhhbiBvbmNlOiBvbmx5IHRoZSByZWdpc3RyYXRpb24gaXQgbWFkZSBpcyByZW1vdmVkLlxuICAgKi9cbiAgYmVnaW4oa2V5OiBzdHJpbmcpOiAoKSA9PiB2b2lkIHtcbiAgICBsZXQgcmVzb2x2ZTogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocikgPT4gKHJlc29sdmUgPSByKSk7XG4gICAgdGhpcy5wZW5kaW5nLnNldChrZXksIHByb21pc2UpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5wZW5kaW5nLmdldChrZXkpID09PSBwcm9taXNlKSB7XG4gICAgICAgIHRoaXMucGVuZGluZy5kZWxldGUoa2V5KTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogU3RvcmVkIGVudHJpZXMgYnkgY2FjaGUga2V5LCBsZWFzdCByZWNlbnRseSB1c2VkIGV2aWN0ZWQgZmlyc3Qgb25jZSB0aGVpclxuICogYnl0ZXMgcGFzcyBgbWF4Qnl0ZXNgLiBTaXplZCBieSBieXRlcyByYXRoZXIgdGhhbiBlbnRyaWVzLCBsaWtlIE5leHQuanMnc1xuICogZGVmYXVsdCBoYW5kbGVyIChgY2FjaGVNYXhNZW1vcnlTaXplYCwgNTAgTUIpLCBzaW5jZSBhIGAndXNlIGNhY2hlJ2AgZW50cnkgaXNcbiAqIGFuIFJTQyBwYXlsb2FkIG9mIGFueSBzaXplLlxuICovXG5leHBvcnQgY2xhc3MgRW50cnlMcnUge1xuICBwcml2YXRlIHJlYWRvbmx5IGVudHJpZXMgPSBuZXcgTWFwPHN0cmluZywgU3RvcmVkRW50cnk+KCk7XG4gIHByaXZhdGUgYnl0ZXMgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgbWF4Qnl0ZXM6IG51bWJlcikge31cblxuICBnZXQoa2V5OiBzdHJpbmcpOiBTdG9yZWRFbnRyeSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gICAgaWYgKGVudHJ5KSB7XG4gICAgICAvLyBSZS1pbnNlcnRlZCB0byBtYXJrIGl0IG1vc3QgcmVjZW50bHkgdXNlZC5cbiAgICAgIHRoaXMuZW50cmllcy5kZWxldGUoa2V5KTtcbiAgICAgIHRoaXMuZW50cmllcy5zZXQoa2V5LCBlbnRyeSk7XG4gICAgfVxuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIHNldChrZXk6IHN0cmluZywgZW50cnk6IFN0b3JlZEVudHJ5KTogdm9pZCB7XG4gICAgdGhpcy5kZWxldGUoa2V5KTtcbiAgICBjb25zdCBzaXplID0gc2l6ZU9mKGtleSwgZW50cnkpO1xuICAgIGlmIChzaXplID4gdGhpcy5tYXhCeXRlcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmVudHJpZXMuc2V0KGtleSwgZW50cnkpO1xuICAgIHRoaXMuYnl0ZXMgKz0gc2l6ZTtcbiAgICBmb3IgKGNvbnN0IFtvbGRlc3RLZXksIG9sZGVzdF0gb2YgdGhpcy5lbnRyaWVzKSB7XG4gICAgICBpZiAodGhpcy5ieXRlcyA8PSB0aGlzLm1heEJ5dGVzKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShvbGRlc3RLZXkpO1xuICAgICAgdGhpcy5ieXRlcyAtPSBzaXplT2Yob2xkZXN0S2V5LCBvbGRlc3QpO1xuICAgIH1cbiAgfVxuXG4gIGRlbGV0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5lbnRyaWVzLmdldChrZXkpO1xuICAgIGlmIChleGlzdGluZykge1xuICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShrZXkpO1xuICAgICAgdGhpcy5ieXRlcyAtPSBzaXplT2Yoa2V5LCBleGlzdGluZyk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IHNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5lbnRyaWVzLnNpemU7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2l6ZU9mKGtleTogc3RyaW5nLCBlbnRyeTogU3RvcmVkRW50cnkpOiBudW1iZXIge1xuICByZXR1cm4gZW50cnkudmFsdWUuYnl0ZUxlbmd0aCArIGtleS5sZW5ndGg7XG59XG5cbi8qKiBEZWZhdWx0IHNpemUgb2YgZWFjaCBoYW5kbGVyJ3MgbWVtb3J5IHN0b3JlOiBOZXh0LmpzJ3MgZGVmYXVsdCwgNTAgTUIuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NRU1PUllfQllURVMgPSA1MCAqIDEwMjQgKiAxMDI0O1xuXG4vKipcbiAqIFRoZSBgY2FjaGVIYW5kbGVyc2AgbWV0aG9kcyB0aGF0IG9ubHkgZ28gdGhyb3VnaCBgdGFnc2AsIHRoZSBzYW1lIGZvciB0aGVcbiAqIGBkZWZhdWx0YCBhbmQgYHJlbW90ZWAgaGFuZGxlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0YWdNZXRob2RzKFxuICB0YWdzOiBUcmFja2VkVGFnTWFya2Vycyxcbik6IFBpY2s8Q2FjaGVIYW5kbGVyLCBcInJlZnJlc2hUYWdzXCIgfCBcImdldEV4cGlyYXRpb25cIiB8IFwidXBkYXRlVGFnc1wiPiB7XG4gIHJldHVybiB7XG4gICAgcmVmcmVzaFRhZ3M6ICgpID0+IHRhZ3MucmVmcmVzaCgpLFxuICAgIGFzeW5jIGdldEV4cGlyYXRpb24oaW1wbGljaXRUYWdzKSB7XG4gICAgICBhd2FpdCB0YWdzLmVuc3VyZShpbXBsaWNpdFRhZ3MpO1xuICAgICAgcmV0dXJuIHRhZ3MuZXhwaXJhdGlvbihpbXBsaWNpdFRhZ3MpO1xuICAgIH0sXG4gICAgYXN5bmMgdXBkYXRlVGFncyhyZXZhbGlkYXRlZFRhZ3MsIGR1cmF0aW9ucykge1xuICAgICAgYXdhaXQgdGFncy51cGRhdGUocmV2YWxpZGF0ZWRUYWdzLCBkdXJhdGlvbnMpO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogQSBoYW5kbGVyIGJ1aWx0IGJ5IGBjcmVhdGVgIG9uIGZpcnN0IHVzZSByYXRoZXIgdGhhbiBvbiBpbXBvcnQsIHNvIGxvYWRpbmdcbiAqIHRoZSBtb2R1bGUgLSB3aGljaCBqZXN0LCBhbmQgTmV4dC5qcydzIGNvbmZpZyB2YWxpZGF0aW9uLCBkbyB3aXRob3V0IHVzaW5nXG4gKiBpdCAtIG5laXRoZXIgY29uc3RydWN0cyBBV1MgY2xpZW50cyBub3Igd2FybnMgYWJvdXQgbWlzc2luZyBjb25maWd1cmF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGF6eUhhbmRsZXIoY3JlYXRlOiAoKSA9PiBDYWNoZUhhbmRsZXIpOiBDYWNoZUhhbmRsZXIge1xuICBsZXQgaGFuZGxlcjogQ2FjaGVIYW5kbGVyIHwgdW5kZWZpbmVkO1xuICBjb25zdCBpbnN0YW5jZSA9ICgpID0+IChoYW5kbGVyID8/PSBjcmVhdGUoKSk7XG4gIHJldHVybiB7XG4gICAgZ2V0OiAoY2FjaGVLZXksIHNvZnRUYWdzKSA9PiBpbnN0YW5jZSgpLmdldChjYWNoZUtleSwgc29mdFRhZ3MpLFxuICAgIHNldDogKGNhY2hlS2V5LCBwZW5kaW5nRW50cnkpID0+IGluc3RhbmNlKCkuc2V0KGNhY2hlS2V5LCBwZW5kaW5nRW50cnkpLFxuICAgIHJlZnJlc2hUYWdzOiAoKSA9PiBpbnN0YW5jZSgpLnJlZnJlc2hUYWdzKCksXG4gICAgZ2V0RXhwaXJhdGlvbjogKHRhZ3MpID0+IGluc3RhbmNlKCkuZ2V0RXhwaXJhdGlvbih0YWdzKSxcbiAgICB1cGRhdGVUYWdzOiAodGFncywgZHVyYXRpb25zKSA9PiBpbnN0YW5jZSgpLnVwZGF0ZVRhZ3ModGFncywgZHVyYXRpb25zKSxcbiAgfTtcbn1cblxuY29uc3QgVEFHX01BTklGRVNUX1NZTUJPTCA9IFN5bWJvbC5mb3IoXCJjZGstbmV4dGpzLnVzZS1jYWNoZS50YWctbWFuaWZlc3RcIik7XG5cbi8qKlxuICogVGhlIHByb2Nlc3MncyBvbmUge0BsaW5rIFRyYWNrZWRUYWdNYXJrZXJzfSwgZnJvbSB0aGUgZW52aXJvbm1lbnQuXG4gKlxuICogS2VwdCBvbiBgZ2xvYmFsVGhpc2AgYmVjYXVzZSB0aGUgaW5jcmVtZW50YWwgY2FjaGUgaGFuZGxlciBhbmQgdGhlIGBkZWZhdWx0YFxuICogYW5kIGByZW1vdGVgIGhhbmRsZXJzIGFyZSBzZXBhcmF0ZSBidW5kbGVzIC0gc2VwYXJhdGUgbW9kdWxlIGluc3RhbmNlcyAtIGFuZFxuICogc2hvdWxkIHNoYXJlIG9uZSBtYW5pZmVzdDogb25lIHJlZnJlc2ggcmVhZCBmb3IgYWxsIG9mIHRoZW0sIGFuZCBvbmUgbWFya2VyXG4gKiB3cml0ZSBwZXIgYHJldmFsaWRhdGVUYWdgLlxuICpcbiAqIEF0IGJ1aWxkIHRpbWUgdGhlcmUgaXMgbm8gdGFibGUgdG8gcmVhZCAoYW5kIG5vIGNyZWRlbnRpYWxzIHRvIHJlYWQgaXRcbiAqIHdpdGgpLCBzbyB0YWdzIHN0YXkgbG9jYWwgdG8gdGhlIHByb2Nlc3MgdGhlcmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFyZWRUYWdNYW5pZmVzdCgpOiBUcmFja2VkVGFnTWFya2VycyB7XG4gIGNvbnN0IGdsb2JhbCA9IGdsb2JhbFRoaXMgYXMgeyBbVEFHX01BTklGRVNUX1NZTUJPTF0/OiBUcmFja2VkVGFnTWFya2VycyB9O1xuICBpZiAoIWdsb2JhbFtUQUdfTUFOSUZFU1RfU1lNQk9MXSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlc29sdmVBd3NDYWNoZUNvbmZpZygpO1xuICAgIGNvbnN0IHJlZnJlc2hJbnRlcnZhbE1zID0gbnVtYmVyRnJvbUVudihcbiAgICAgIFwiQ0RLX05FWFRKU19UQUdfUkVGUkVTSF9NU1wiLFxuICAgICAgREVGQVVMVF9UQUdfUkVGUkVTSF9NUyxcbiAgICApO1xuICAgIGlmIChjb25maWcudGFibGVOYW1lICYmICFpc0J1aWxkUGhhc2UoKSkge1xuICAgICAgY29uc3QgY2xpZW50ID0gbmV3IER5bmFtb0RCQ2xpZW50KHsgcmVnaW9uOiBjb25maWcucmVnaW9uIH0pO1xuICAgICAgZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdID0gbmV3IFRyYWNrZWRUYWdNYXJrZXJzKHtcbiAgICAgICAgbWFya2VyczogbmV3IFRhZ01hcmtlclRhYmxlKGNsaWVudCwgY29uZmlnLnRhYmxlTmFtZSwgY29uZmlnLmJ1aWxkSWQpLFxuICAgICAgICBsb2c6IG5ldyBSZXZhbGlkYXRpb25Mb2coY2xpZW50LCBjb25maWcudGFibGVOYW1lLCBjb25maWcuYnVpbGRJZCksXG4gICAgICAgIHJlZnJlc2hJbnRlcnZhbE1zLFxuICAgICAgICBkZWJ1ZzogZ2V0RGVidWcoXCJjZGstbmV4dGpzOmNhY2hlLWhhbmRsZXI6dGFnc1wiKSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWlzQnVpbGRQaGFzZSgpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBcIkNES19ORVhUSlNfUkVWQUxJREFUSU9OX1RBQkxFX05BTUUgZW52aXJvbm1lbnQgdmFyaWFibGUgbm90IHNldCwgY2FjaGUgdGFncyBhcmUgbG9jYWwgdG8gZWFjaCBpbnN0YW5jZVwiLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdID0gbmV3IFRyYWNrZWRUYWdNYXJrZXJzKHtcbiAgICAgICAgcmVmcmVzaEludGVydmFsTXMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGdsb2JhbFtUQUdfTUFOSUZFU1RfU1lNQk9MXTtcbn1cbiJdfQ==
357
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlLWNhY2hlLWNvbW1vbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL3VzZS1jYWNoZS1jb21tb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBMEJBLG9DQUVDO0FBR0Qsc0NBSUM7QUFrQkQsZ0NBcUJDO0FBR0Qsc0NBS0M7QUFHRCxvQ0FnQkM7QUFPRCx3Q0FFQztBQXlKRCw0Q0FFQztBQW1CRCwwQkFXQztBQWVELGdDQTRCQztBQU9ELGtDQVVDO0FBYUQsOENBd0NDO0FBeFpEOzs7Ozs7RUFNRTtBQUNGLHNEQUFzRDtBQUN0RCw4REFBMEQ7QUFDMUQsa0RBQTZCO0FBSzdCLHVEQU0yQjtBQUMzQiwwREFBOEQ7QUFFOUQscURBQXVEO0FBQTlDLHNHQUFBLFdBQVcsT0FBTztBQUUzQiwwRUFBMEU7QUFDMUUsU0FBZ0IsWUFBWTtJQUMxQixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxLQUFLLHdCQUF3QixDQUFDO0FBQzdELENBQUM7QUFFRCw4REFBOEQ7QUFDOUQsU0FBZ0IsYUFBYSxDQUFDLElBQVksRUFBRSxRQUFnQjtJQUMxRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlCLE1BQU0sS0FBSyxHQUFHLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEUsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0FBQ2pFLENBQUM7QUFVRDs7Ozs7OztHQU9HO0FBQ0ksS0FBSyxVQUFVLFVBQVUsQ0FDOUIsTUFBa0M7SUFFbEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFNBQVMs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QUksbUNBQWlCLENBQUM7Z0JBQ2xELGlCQUFpQjthQUNsQixDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLGtDQUFtQixDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIFdoYXQgdGhlIHR3byBgY2FjaGVIYW5kbGVyc2AgKGAndXNlIGNhY2hlJ2AgYW5kIGAndXNlIGNhY2hlOiByZW1vdGUnYCkgc2hhcmU6XG4gIHRoZSBpbi1tZW1vcnkgZW50cnkgc3RvcmUsIHRoZSBwZW5kaW5nLWBzZXRgIGJvb2trZWVwaW5nIE5leHQuanMgcmVxdWlyZXMgb2ZcbiAgZXZlcnkgaGFuZGxlciwgYW5kIHRoZSBwcm9jZXNzJ3Mgb25lIHRhZyBtYW5pZmVzdCAoYFRyYWNrZWRUYWdNYXJrZXJzYCksXG4gIHdoaWNoIG1ha2VzIGByZXZhbGlkYXRlVGFnYCByZWFjaCBldmVyeSBpbnN0YW5jZSB0aHJvdWdoIHRoZSByZXZhbGlkYXRpb25cbiAgdGFibGUncyBtYXJrZXIgcm93cy5cbiovXG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCB7IER5bmFtb0RCQ2xpZW50IH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1keW5hbW9kYlwiO1xuaW1wb3J0IGdldERlYnVnIGZyb20gXCJkZWJ1Z1wiO1xuaW1wb3J0IHR5cGUge1xuICBDYWNoZUVudHJ5LFxuICBDYWNoZUhhbmRsZXIsXG59IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL2xpYi9jYWNoZS1oYW5kbGVycy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9UQUdfUkVGUkVTSF9NUyxcbiAgcmVzb2x2ZUF3c0NhY2hlQ29uZmlnLFxuICBSZXZhbGlkYXRpb25Mb2csXG4gIFRhZ01hcmtlclRhYmxlLFxuICBUcmFja2VkVGFnTWFya2Vycyxcbn0gZnJvbSBcIi4vYXdzLWNhY2hlLXN0b3JlXCI7XG5pbXBvcnQgeyBUQUdfTUFOSUZFU1RfU1lNQk9MIH0gZnJvbSBcIi4uL3J1bnRpbWUvdGFnLW1hbmlmZXN0XCI7XG5cbmV4cG9ydCB7IG1hcmtlckNsb2NrIGFzIG5vdyB9IGZyb20gXCIuL2F3cy1jYWNoZS1zdG9yZVwiO1xuXG4vKiogV2hldGhlciB0aGlzIHByb2Nlc3MgaXMgYG5leHQgYnVpbGRgIHJhdGhlciB0aGFuIGEgZGVwbG95ZWQgc2VydmVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQnVpbGRQaGFzZSgpOiBib29sZWFuIHtcbiAgcmV0dXJuIHByb2Nlc3MuZW52Lk5FWFRfUEhBU0UgPT09IFwicGhhc2UtcHJvZHVjdGlvbi1idWlsZFwiO1xufVxuXG4vKiogQSBwb3NpdGl2ZSBpbnRlZ2VyIGVudmlyb25tZW50IHZhcmlhYmxlLCBvciBgZmFsbGJhY2tgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG51bWJlckZyb21FbnYobmFtZTogc3RyaW5nLCBmYWxsYmFjazogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnZbbmFtZV07XG4gIGNvbnN0IHZhbHVlID0gcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSBcIlwiID8gTmFOIDogTnVtYmVyKHJhdyk7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpICYmIHZhbHVlID49IDAgPyB2YWx1ZSA6IGZhbGxiYWNrO1xufVxuXG4vKipcbiAqIEEgYENhY2hlRW50cnlgIHdpdGggaXRzIHZhbHVlIHJlYWQgdG8gdGhlIGVuZDogdGhlIGJ5dGVzIGFyZSB3aGF0IGlzIGtlcHQsXG4gKiBhbmQgZXZlcnkgYGdldGAgaGFuZHMgb3V0IGEgZnJlc2ggc3RyZWFtIG92ZXIgdGhlbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdG9yZWRFbnRyeSBleHRlbmRzIE9taXQ8Q2FjaGVFbnRyeSwgXCJ2YWx1ZVwiPiB7XG4gIHZhbHVlOiBVaW50OEFycmF5O1xufVxuXG4vKipcbiAqIFJlYWQgYHN0cmVhbWAgdG8gdGhlIGVuZCwgb3IgdGhyb3cgaWYgaXQgZXJyb3JzLlxuICpcbiAqIGBDYWNoZUVudHJ5LnZhbHVlYCBcImNhbiBlcnJvciBhbmQgb25seSBoYXZlIHBhcnRpYWwgZGF0YVwiIChOZXh0LmpzJ3NcbiAqIGBjYWNoZS1oYW5kbGVycy90eXBlcy5kLnRzYCkuIFRocm93aW5nIGlzIGhvdyBhIHBhcnRpYWwgZW50cnkgaXMga2VwdCBvdXQ6XG4gKiBib3RoIGhhbmRsZXJzIHN0b3JlIG5vdGhpbmcgd2hlbiB0aGlzIHJlamVjdHMsIHdoaWNoIGlzIHdoYXQgTmV4dC5qcydzIG93blxuICogZGVmYXVsdCBoYW5kbGVyIGRvZXMgdG9vLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFN0cmVhbShcbiAgc3RyZWFtOiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pixcbik6IFByb21pc2U8VWludDhBcnJheT4ge1xuICBjb25zdCByZWFkZXIgPSBzdHJlYW0uZ2V0UmVhZGVyKCk7XG4gIGNvbnN0IGNodW5rczogVWludDhBcnJheVtdID0gW107XG4gIGxldCBzaXplID0gMDtcbiAgZm9yICg7Oykge1xuICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjaHVua3MucHVzaCh2YWx1ZSk7XG4gICAgc2l6ZSArPSB2YWx1ZS5ieXRlTGVuZ3RoO1xuICB9XG4gIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7XG4gIGxldCBvZmZzZXQgPSAwO1xuICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykge1xuICAgIGJ5dGVzLnNldChjaHVuaywgb2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gY2h1bmsuYnl0ZUxlbmd0aDtcbiAgfVxuICByZXR1cm4gYnl0ZXM7XG59XG5cbi8qKiBgcGVuZGluZ0VudHJ5YCByZXNvbHZlZCBhbmQgcmVhZCB0byB0aGUgZW5kLiBTZWUge0BsaW5rIHJlYWRTdHJlYW19LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0b3JlZEVudHJ5T2YoXG4gIHBlbmRpbmdFbnRyeTogUHJvbWlzZTxDYWNoZUVudHJ5Pixcbik6IFByb21pc2U8U3RvcmVkRW50cnk+IHtcbiAgY29uc3QgZW50cnkgPSBhd2FpdCBwZW5kaW5nRW50cnk7XG4gIHJldHVybiB7IC4uLmVudHJ5LCB2YWx1ZTogYXdhaXQgcmVhZFN0cmVhbShlbnRyeS52YWx1ZSkgfTtcbn1cblxuLyoqIGBzdG9yZWRgIGFzIHRoZSBgQ2FjaGVFbnRyeWAgYSBgZ2V0YCByZXR1cm5zLCB3aXRoIGl0cyBvd24gc3RyZWFtLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhY2hlRW50cnlPZihcbiAgc3RvcmVkOiBTdG9yZWRFbnRyeSxcbiAgcmV2YWxpZGF0ZTogbnVtYmVyID0gc3RvcmVkLnJldmFsaWRhdGUsXG4pOiBDYWNoZUVudHJ5IHtcbiAgY29uc3QgYnl0ZXMgPSBzdG9yZWQudmFsdWU7XG4gIHJldHVybiB7XG4gICAgLi4uc3RvcmVkLFxuICAgIHJldmFsaWRhdGUsXG4gICAgdmFsdWU6IG5ldyBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pih7XG4gICAgICBzdGFydChjb250cm9sbGVyKSB7XG4gICAgICAgIC8vIEEgY29weTogd2hvZXZlciByZWFkcyB0aGUgc3RyZWFtIG1heSB0cmFuc2ZlciBvciBtdXRhdGUgdGhlIGNodW5rLlxuICAgICAgICBjb250cm9sbGVyLmVucXVldWUoYnl0ZXMuc2xpY2UoKSk7XG4gICAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICAgIH0sXG4gICAgfSksXG4gIH07XG59XG5cbi8qKlxuICogV2hldGhlciBOZXh0LmpzIHdvdWxkIHJlZ2VuZXJhdGUgYGVudHJ5YCBvbiBldmVyeSByZWFkIGFueXdheSwgc28gc3RvcmluZyBpdFxuICogaXMgYSB3cml0ZSBub3RoaW5nIHJlYWRzIGJhY2suIE5leHQuanMncyBkZWZhdWx0IGhhbmRsZXIgc2tpcHMgdGhlc2UgdGhlIHNhbWVcbiAqIHdheSwgb3V0c2lkZSB0aGUgZGV2IHNlcnZlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRHluYW1pY0VudHJ5KGVudHJ5OiBQaWNrPENhY2hlRW50cnksIFwiZXhwaXJlXCI+KTogYm9vbGVhbiB7XG4gIHJldHVybiBlbnRyeS5leHBpcmUgPT09IDA7XG59XG5cbi8qKlxuICogVGhlIGluLWZsaWdodCBgc2V0YHMsIGJ5IGNhY2hlIGtleS4gYENhY2hlSGFuZGxlci5zZXRgIHJlY2VpdmVzIGFuIGVudHJ5IHRoYXRcbiAqIG1heSBzdGlsbCBiZSBzdHJlYW1pbmcsIGFuZCBcImlmIGEgYGdldGAgZm9yIHRoZSBzYW1lIGNhY2hlIGtleSBpcyBjYWxsZWRcbiAqIGJlZm9yZSB0aGUgcGVuZGluZyBlbnRyeSBpcyBjb21wbGV0ZSwgdGhlIGNhY2hlIGhhbmRsZXIgbXVzdCB3YWl0IGZvciB0aGVcbiAqIGBzZXRgIG9wZXJhdGlvbiB0byBmaW5pc2hcIiAoYGNhY2hlLWhhbmRsZXJzL3R5cGVzLmQudHNgKS5cbiAqL1xuZXhwb3J0IGNsYXNzIFBlbmRpbmdTZXRzIHtcbiAgcHJpdmF0ZSByZWFkb25seSBwZW5kaW5nID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG5cbiAgLyoqIFJlc29sdmVzIG9uY2Ugbm8gYHNldGAgZm9yIGBrZXlgIGlzIGluIGZsaWdodC4gKi9cbiAgYXN5bmMgd2FpdChrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAobGV0IHAgPSB0aGlzLnBlbmRpbmcuZ2V0KGtleSk7IHA7IHAgPSB0aGlzLnBlbmRpbmcuZ2V0KGtleSkpIHtcbiAgICAgIGF3YWl0IHA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgYHNldGAgZm9yIGBrZXlgIGFuZCByZXR1cm4gdGhlIGZ1bmN0aW9uIHRoYXQgZW5kcyBpdC4gU2FmZSB0b1xuICAgKiBjYWxsIG1vcmUgdGhhbiBvbmNlOiBvbmx5IHRoZSByZWdpc3RyYXRpb24gaXQgbWFkZSBpcyByZW1vdmVkLlxuICAgKi9cbiAgYmVnaW4oa2V5OiBzdHJpbmcpOiAoKSA9PiB2b2lkIHtcbiAgICBsZXQgcmVzb2x2ZTogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocikgPT4gKHJlc29sdmUgPSByKSk7XG4gICAgdGhpcy5wZW5kaW5nLnNldChrZXksIHByb21pc2UpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5wZW5kaW5nLmdldChrZXkpID09PSBwcm9taXNlKSB7XG4gICAgICAgIHRoaXMucGVuZGluZy5kZWxldGUoa2V5KTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogU3RvcmVkIGVudHJpZXMgYnkgY2FjaGUga2V5LCBsZWFzdCByZWNlbnRseSB1c2VkIGV2aWN0ZWQgZmlyc3Qgb25jZSB0aGVpclxuICogYnl0ZXMgcGFzcyBgbWF4Qnl0ZXNgLiBTaXplZCBieSBieXRlcyByYXRoZXIgdGhhbiBlbnRyaWVzLCBsaWtlIE5leHQuanMnc1xuICogZGVmYXVsdCBoYW5kbGVyIChgY2FjaGVNYXhNZW1vcnlTaXplYCwgNTAgTUIpLCBzaW5jZSBhIGAndXNlIGNhY2hlJ2AgZW50cnkgaXNcbiAqIGFuIFJTQyBwYXlsb2FkIG9mIGFueSBzaXplLlxuICovXG5leHBvcnQgY2xhc3MgRW50cnlMcnUge1xuICBwcml2YXRlIHJlYWRvbmx5IGVudHJpZXMgPSBuZXcgTWFwPHN0cmluZywgU3RvcmVkRW50cnk+KCk7XG4gIHByaXZhdGUgYnl0ZXMgPSAwO1xuICAvKipcbiAgICogTm8gbGF0ZXIgdGhhbiB0aGUgb2xkZXN0IGVudHJ5J3MgYHRpbWVzdGFtcGA6IHRoZSBsYXN0IHNjYW4ncyBhbnN3ZXIsIGxlc3NcbiAgICogd2hhdGV2ZXIgd2FzIHNldCBzaW5jZS4gRW50cmllcyBkcm9wcGVkIHNpbmNlIG9ubHkgbWFrZSBpdCBlYXJseS4gU2VlXG4gICAqIHtAbGluayBvbGRlc3RCb3VuZH0uXG4gICAqL1xuICBwcml2YXRlIGxvd2VzdCA9IEluZmluaXR5O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgbWF4Qnl0ZXM6IG51bWJlcikge31cblxuICBnZXQoa2V5OiBzdHJpbmcpOiBTdG9yZWRFbnRyeSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gICAgaWYgKGVudHJ5KSB7XG4gICAgICAvLyBSZS1pbnNlcnRlZCB0byBtYXJrIGl0IG1vc3QgcmVjZW50bHkgdXNlZC5cbiAgICAgIHRoaXMuZW50cmllcy5kZWxldGUoa2V5KTtcbiAgICAgIHRoaXMuZW50cmllcy5zZXQoa2V5LCBlbnRyeSk7XG4gICAgfVxuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIHNldChrZXk6IHN0cmluZywgZW50cnk6IFN0b3JlZEVudHJ5KTogdm9pZCB7XG4gICAgdGhpcy5kZWxldGUoa2V5KTtcbiAgICBjb25zdCBzaXplID0gc2l6ZU9mKGtleSwgZW50cnkpO1xuICAgIGlmIChzaXplID4gdGhpcy5tYXhCeXRlcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmVudHJpZXMuc2V0KGtleSwgZW50cnkpO1xuICAgIHRoaXMuYnl0ZXMgKz0gc2l6ZTtcbiAgICB0aGlzLmxvd2VzdCA9IE1hdGgubWluKHRoaXMubG93ZXN0LCBlbnRyeS50aW1lc3RhbXApO1xuICAgIGZvciAoY29uc3QgW29sZGVzdEtleSwgb2xkZXN0XSBvZiB0aGlzLmVudHJpZXMpIHtcbiAgICAgIGlmICh0aGlzLmJ5dGVzIDw9IHRoaXMubWF4Qnl0ZXMpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB0aGlzLmVudHJpZXMuZGVsZXRlKG9sZGVzdEtleSk7XG4gICAgICB0aGlzLmJ5dGVzIC09IHNpemVPZihvbGRlc3RLZXksIG9sZGVzdCk7XG4gICAgfVxuICB9XG5cbiAgZGVsZXRlKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICB0aGlzLmVudHJpZXMuZGVsZXRlKGtleSk7XG4gICAgICB0aGlzLmJ5dGVzIC09IHNpemVPZihrZXksIGV4aXN0aW5nKTtcbiAgICAgIGlmICh0aGlzLmVudHJpZXMuc2l6ZSA9PT0gMCkge1xuICAgICAgICB0aGlzLmxvd2VzdCA9IEluZmluaXR5O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYHRpbWVzdGFtcGAgb2YgdGhlIG9sZGVzdCBlbnRyeSBoZWxkLCBgSW5maW5pdHlgIHdpdGggbm9uZSwgZHJvcHBpbmdcbiAgICogb24gdGhlIHdheSB0aGUgZW50cmllcyBwYXN0IGByZXZhbGlkYXRlYCBhdCBgYXRgIChgbm93KClgKTogYSBoYW5kbGVyXG4gICAqIHRoYXQgZHJvcHMgdGhlbSB3aGVuIG5leHQgcmVhZCB3b3VsZCBvdGhlcndpc2UgaG9sZCB0aGVtIHVudGlsIHRoZW4sIGFuZFxuICAgKiB0aGV5IHdvdWxkIGNvdW50IGhlcmUgbWVhbndoaWxlLiBBIHNjYW4sIHNvIGFza2VkIG9uY2UgaW4gYSB3aGlsZTogaW5cbiAgICogYmV0d2Vlbiwge0BsaW5rIG9sZGVzdEJvdW5kfSBhbnN3ZXJzLlxuICAgKi9cbiAgb2xkZXN0VGltZXN0YW1wKGF0ID0gLUluZmluaXR5KTogbnVtYmVyIHtcbiAgICBsZXQgb2xkZXN0ID0gSW5maW5pdHk7XG4gICAgZm9yIChjb25zdCBba2V5LCBlbnRyeV0gb2YgdGhpcy5lbnRyaWVzKSB7XG4gICAgICBpZiAoaXNQYXN0UmV2YWxpZGF0ZShlbnRyeSwgYXQpKSB7XG4gICAgICAgIHRoaXMuZGVsZXRlKGtleSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvbGRlc3QgPSBNYXRoLm1pbihvbGRlc3QsIGVudHJ5LnRpbWVzdGFtcCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMubG93ZXN0ID0gb2xkZXN0O1xuICAgIHJldHVybiBvbGRlc3Q7XG4gIH1cblxuICAvKipcbiAgICogTm8gbGF0ZXIgdGhhbiB7QGxpbmsgb2xkZXN0VGltZXN0YW1wfSwgd2l0aG91dCBpdHMgc2NhbjogYXMgb2YgdGhlIGxhc3RcbiAgICogb25lLCBsZXNzIHRoZSBlbnRyaWVzIHNldCBzaW5jZS4gYEluZmluaXR5YCB3aXRoIG5vbmUgaGVsZC4gRHJvcHMgdGhlXG4gICAqIGVudHJpZXMgcGFzdCBgcmV2YWxpZGF0ZWAgYXQgYGF0YCBmcm9tIHRoZSBsZWFzdCByZWNlbnRseSB1c2VkIGVuZCwgdXAgdG9cbiAgICogdGhlIGZpcnN0IHRoYXQgaXNuJ3QsIHNvIHtAbGluayBob2xkc0xpdmV9IGRvZXNuJ3Qgd2FsayBwYXN0IHRoZW0gb24gZXZlcnlcbiAgICogcmVxdWVzdCB1bnRpbCB0aGUgbmV4dCBzY2FuLlxuICAgKi9cbiAgb2xkZXN0Qm91bmQoYXQgPSAtSW5maW5pdHkpOiBudW1iZXIge1xuICAgIGZvciAoY29uc3QgW2tleSwgZW50cnldIG9mIHRoaXMuZW50cmllcykge1xuICAgICAgaWYgKCFpc1Bhc3RSZXZhbGlkYXRlKGVudHJ5LCBhdCkpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB0aGlzLmRlbGV0ZShrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnRyaWVzLnNpemUgPT09IDAgPyBJbmZpbml0eSA6IHRoaXMubG93ZXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgYW4gZW50cnkgbm90IHBhc3QgYHJldmFsaWRhdGVgIGF0IGBhdGAgaXMgaGVsZC4gVXN1YWxseSB0aGUgZmlyc3RcbiAgICogZW50cnkgYW5zd2VyczsgdGhlIGV4cGlyZWQgb25lcyBpdCBwYXNzZXMgYXJlIGRyb3BwZWQgYnkgdGhlIHNjYW5cbiAgICoge0BsaW5rIG9sZGVzdFRpbWVzdGFtcH0gbWFrZXMsIG5vdCBoZXJlLCBzbyBhc2tpbmcgY2hhbmdlcyBub3RoaW5nLlxuICAgKi9cbiAgaG9sZHNMaXZlKGF0OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHRoaXMuZW50cmllcy52YWx1ZXMoKSkge1xuICAgICAgaWYgKCFpc1Bhc3RSZXZhbGlkYXRlKGVudHJ5LCBhdCkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGdldCBzaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZW50cmllcy5zaXplO1xuICB9XG59XG5cbmZ1bmN0aW9uIHNpemVPZihrZXk6IHN0cmluZywgZW50cnk6IFN0b3JlZEVudHJ5KTogbnVtYmVyIHtcbiAgcmV0dXJuIGVudHJ5LnZhbHVlLmJ5dGVMZW5ndGggKyBrZXkubGVuZ3RoO1xufVxuXG4vKiogV2hldGhlciBgc3RvcmVkYCBpcyBwYXN0IGByZXZhbGlkYXRlYCBhdCBgYXRgIChgbm93KClgKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1Bhc3RSZXZhbGlkYXRlKHN0b3JlZDogU3RvcmVkRW50cnksIGF0OiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIGF0ID4gc3RvcmVkLnRpbWVzdGFtcCArIHN0b3JlZC5yZXZhbGlkYXRlICogMTAwMDtcbn1cblxuLyoqIERlZmF1bHQgc2l6ZSBvZiBlYWNoIGhhbmRsZXIncyBtZW1vcnkgc3RvcmU6IE5leHQuanMncyBkZWZhdWx0LCA1MCBNQi4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX01FTU9SWV9CWVRFUyA9IDUwICogMTAyNCAqIDEwMjQ7XG5cbi8qKlxuICogSG93IGxvbmcgb25lIHJldmFsaWRhdGlvbiB0YWJsZSByZXF1ZXN0IG1heSB0YWtlLCBwZXIgYXR0ZW1wdC4gVGhlIFNESyBzZXRzXG4gKiBubyBsaW1pdCwgYW5kIGEgcmVmcmVzaCBsZWZ0IGluIGZsaWdodCBhY3Jvc3MgYSBMYW1iZGEgZnJlZXplIGNhbiBzaXQgb24gYVxuICogY29ubmVjdGlvbiB0aGF0IGRpZWQgbWVhbndoaWxlIHdpdGhvdXQgYSByZXNldDogZXZlcnkgcmVxdWVzdCB0aGF0IHdhaXRzXG4gKiBmb3IgdGhlIHJlZnJlc2ggKGFuIGluc3RhbmNlIGBiZWhpbmRgLCBJU1IpIHdvdWxkIHdhaXQgd2l0aCBpdC4gVGhlIFNES1xuICogcmV0cmllcyBhIHRpbWVkLW91dCBhdHRlbXB0LCBzbyBhIGRlYWQgY29ubmVjdGlvbiBjb3N0cyB1cCB0byBpdHMgYXR0ZW1wdHNcbiAqIHRpbWVzIHRoaXMuXG4gKi9cbmV4cG9ydCBjb25zdCBUQUdfVEFCTEVfUkVRVUVTVF9USU1FT1VUX01TID0gMzAwMDtcblxuLyoqXG4gKiBXYWl0IGZvciBgd29ya2AgaWYgYHdhaXRgLCBvciBlbHNlIGxldCBpdCBydW4gb246IGVpdGhlciB3YXkgYSByZWplY3Rpb24gaXNcbiAqIGxvZ2dlZCB3aXRoIGBmYWlsdXJlYCByYXRoZXIgdGhhbiB0aHJvd24uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhd2FpdElmKFxuICB3YWl0OiBib29sZWFuLFxuICB3b3JrOiBQcm9taXNlPHZvaWQ+LFxuICBmYWlsdXJlOiBzdHJpbmcsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgbG9nZ2VkID0gd29yay5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICBjb25zb2xlLmVycm9yKGZhaWx1cmUsIGVycm9yKTtcbiAgfSk7XG4gIGlmICh3YWl0KSB7XG4gICAgYXdhaXQgbG9nZ2VkO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFnTWV0aG9kc09wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciBgcmVmcmVzaFRhZ3NgIGFsd2F5cyB3YWl0cyBmb3IgdGhlIHJldmFsaWRhdGlvbiBsb2cgcXVlcnksIHJhdGhlclxuICAgKiB0aGFuIG9ubHkgd2hlbiB0aGUgaW5zdGFuY2UgaXMgYGJlaGluZGAuXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBibG9ja2luZz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogVGhlIGBjYWNoZUhhbmRsZXJzYCBtZXRob2RzIHRoYXQgb25seSBnbyB0aHJvdWdoIGB0YWdzYCwgdGhlIHNhbWUgZm9yIHRoZVxuICogYGRlZmF1bHRgIGFuZCBgcmVtb3RlYCBoYW5kbGVycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRhZ01ldGhvZHMoXG4gIHRhZ3M6IFRyYWNrZWRUYWdNYXJrZXJzLFxuICBvcHRpb25zOiBUYWdNZXRob2RzT3B0aW9ucyA9IHt9LFxuKTogUGljazxDYWNoZUhhbmRsZXIsIFwicmVmcmVzaFRhZ3NcIiB8IFwidXBkYXRlVGFnc1wiPiB7XG4gIHJldHVybiB7XG4gICAgLy8gU3RhcnRlZCwgbm90IGF3YWl0ZWQsIHdoaWxlIHRoZSBpbnN0YW5jZSBrZWVwcyB1cCwgdW5sZXNzIGBibG9ja2luZ2AuXG4gICAgLy8gTmV4dC5qcyBhd2FpdHMgYHJlZnJlc2hUYWdzYCBpbnNpZGUgdGhlIGZpcnN0IGAndXNlIGNhY2hlJ2AgbG9va3VwIG9mIGFcbiAgICAvLyByZXF1ZXN0IChgdXNlLWNhY2hlLXdyYXBwZXJgKSwgYW5kIGEgc3RhZ2VkIHJlbmRlciBlbmRzIGl0cyBzdGF0aWMgc3RhZ2VcbiAgICAvLyBvbiBhIHRpbWVyOiBhIGxvZyBgUXVlcnlgIHRoZXJlIHB1c2hlZCB0aGUgZW50cnkgb3V0IG9mIHRoZSBzdGF0aWNcbiAgICAvLyBzdGFnZSwgc28gYSBjYWNoZWQgbmF2aWdhdGlvbiBzdG9yZWQgdGhlIHBhZ2Ugc2VnbWVudCB3aXRob3V0IGl0LiBXaGF0XG4gICAgLy8gdGhlIHF1ZXJ5IGZpbmRzIGFwcGxpZXMgZnJvbSB0aGUgbmV4dCByZXF1ZXN0LiBBd2FpdGVkIG9uY2UgdGhlIGluc3RhbmNlXG4gICAgLy8gaXMgYGJlaGluZGAsIHdoaWNoIHRoZSBydW50aW1lIHNldHRsZXMgYmVmb3JlIGEgcGFnZSByZW5kZXIgc3RhcnRzXG4gICAgLy8gKGBjYXRjaFVwYCk6IHRoZSBmaXJzdCByZXF1ZXN0IGFmdGVyIGFuIGlkbGUgb3IgZnJvemVuIHNwZWxsIHdvdWxkXG4gICAgLy8gb3RoZXJ3aXNlIHNlcnZlIHdoYXRldmVyIHdhcyByZXZhbGlkYXRlZCBlbHNld2hlcmUgbWVhbndoaWxlLiBBIHBhZ2Unc1xuICAgIC8vIHJlbmRlciBqdXN0IGFmdGVyIGBjYXRjaFVwYCBnZXRzIGEgZ3JhY2UgbW9yZSAoYGJlaGluZEluUmVuZGVyYCksIHNvIGFcbiAgICAvLyByZXF1ZXN0IHRoYXQgY2FtZSBpbiBqdXN0IHNob3J0IG9mIHRoZSBsaW5lIGRvZXNuJ3QgY3Jvc3MgaXQgaW5zaWRlXG4gICAgLy8gdGhlIHJlbmRlci4gTm90IGV2ZW4gdGhlbiB3aGlsZSB0aGUgaW5zdGFuY2UgaG9sZHMgbm8gZW50cnkgdGhlIHF1ZXJ5XG4gICAgLy8gY291bGQgZXhwaXJlIChgaG9sZHNFbnRyaWVzYCksIHdpdGggYSBgcmVmcmVzaEludGVydmFsTXNgIG9mIGAwYCB0b28uXG4gICAgcmVmcmVzaFRhZ3M6ICgpID0+XG4gICAgICBhd2FpdElmKFxuICAgICAgICBvcHRpb25zLmJsb2NraW5nID09PSB0cnVlIHx8ICh0YWdzLmJlaGluZEluUmVuZGVyICYmIHRhZ3MuaG9sZHNFbnRyaWVzKSxcbiAgICAgICAgdGFncy5yZWZyZXNoKCksXG4gICAgICAgIFwiRXJyb3IgcmVmcmVzaGluZyBjYWNoZSB0YWdzOlwiLFxuICAgICAgKSxcbiAgICBhc3luYyB1cGRhdGVUYWdzKHJldmFsaWRhdGVkVGFncywgZHVyYXRpb25zKSB7XG4gICAgICBhd2FpdCB0YWdzLnVwZGF0ZShyZXZhbGlkYXRlZFRhZ3MsIGR1cmF0aW9ucyk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBBIGhhbmRsZXIgYnVpbHQgYnkgYGNyZWF0ZWAgb24gZmlyc3QgdXNlIHJhdGhlciB0aGFuIG9uIGltcG9ydCwgc28gbG9hZGluZ1xuICogdGhlIG1vZHVsZSAtIHdoaWNoIGplc3QsIGFuZCBOZXh0LmpzJ3MgY29uZmlnIHZhbGlkYXRpb24sIGRvIHdpdGhvdXQgdXNpbmdcbiAqIGl0IC0gbmVpdGhlciBjb25zdHJ1Y3RzIEFXUyBjbGllbnRzIG5vciB3YXJucyBhYm91dCBtaXNzaW5nIGNvbmZpZ3VyYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXp5SGFuZGxlcihjcmVhdGU6ICgpID0+IENhY2hlSGFuZGxlcik6IENhY2hlSGFuZGxlciB7XG4gIGxldCBoYW5kbGVyOiBDYWNoZUhhbmRsZXIgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IGluc3RhbmNlID0gKCkgPT4gKGhhbmRsZXIgPz89IGNyZWF0ZSgpKTtcbiAgcmV0dXJuIHtcbiAgICBnZXQ6IChjYWNoZUtleSwgc29mdFRhZ3MpID0+IGluc3RhbmNlKCkuZ2V0KGNhY2hlS2V5LCBzb2Z0VGFncyksXG4gICAgc2V0OiAoY2FjaGVLZXksIHBlbmRpbmdFbnRyeSkgPT4gaW5zdGFuY2UoKS5zZXQoY2FjaGVLZXksIHBlbmRpbmdFbnRyeSksXG4gICAgcmVmcmVzaFRhZ3M6ICgpID0+IGluc3RhbmNlKCkucmVmcmVzaFRhZ3MoKSxcbiAgICBnZXRFeHBpcmF0aW9uOiAodGFncykgPT4gaW5zdGFuY2UoKS5nZXRFeHBpcmF0aW9uKHRhZ3MpLFxuICAgIHVwZGF0ZVRhZ3M6ICh0YWdzLCBkdXJhdGlvbnMpID0+IGluc3RhbmNlKCkudXBkYXRlVGFncyh0YWdzLCBkdXJhdGlvbnMpLFxuICB9O1xufVxuXG4vKipcbiAqIFRoZSBwcm9jZXNzJ3Mgb25lIHtAbGluayBUcmFja2VkVGFnTWFya2Vyc30sIGZyb20gdGhlIGVudmlyb25tZW50LlxuICpcbiAqIEtlcHQgb24gYGdsb2JhbFRoaXNgIGJlY2F1c2UgdGhlIGluY3JlbWVudGFsIGNhY2hlIGhhbmRsZXIgYW5kIHRoZSBgZGVmYXVsdGBcbiAqIGFuZCBgcmVtb3RlYCBoYW5kbGVycyBhcmUgc2VwYXJhdGUgYnVuZGxlcyAtIHNlcGFyYXRlIG1vZHVsZSBpbnN0YW5jZXMgLSBhbmRcbiAqIHNob3VsZCBzaGFyZSBvbmUgbWFuaWZlc3Q6IG9uZSByZWZyZXNoIHJlYWQgZm9yIGFsbCBvZiB0aGVtLCBhbmQgb25lIG1hcmtlclxuICogd3JpdGUgcGVyIGByZXZhbGlkYXRlVGFnYC5cbiAqXG4gKiBBdCBidWlsZCB0aW1lIHRoZXJlIGlzIG5vIHRhYmxlIHRvIHJlYWQgKGFuZCBubyBjcmVkZW50aWFscyB0byByZWFkIGl0XG4gKiB3aXRoKSwgc28gdGFncyBzdGF5IGxvY2FsIHRvIHRoZSBwcm9jZXNzIHRoZXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hhcmVkVGFnTWFuaWZlc3QoKTogVHJhY2tlZFRhZ01hcmtlcnMge1xuICBjb25zdCBnbG9iYWwgPSBnbG9iYWxUaGlzIGFzIHsgW1RBR19NQU5JRkVTVF9TWU1CT0xdPzogVHJhY2tlZFRhZ01hcmtlcnMgfTtcbiAgaWYgKCFnbG9iYWxbVEFHX01BTklGRVNUX1NZTUJPTF0pIHtcbiAgICBjb25zdCBjb25maWcgPSByZXNvbHZlQXdzQ2FjaGVDb25maWcoKTtcbiAgICBjb25zdCByZWZyZXNoSW50ZXJ2YWxNcyA9IG51bWJlckZyb21FbnYoXG4gICAgICBcIkNES19ORVhUSlNfVEFHX1JFRlJFU0hfTVNcIixcbiAgICAgIERFRkFVTFRfVEFHX1JFRlJFU0hfTVMsXG4gICAgKTtcbiAgICBpZiAoY29uZmlnLnRhYmxlTmFtZSAmJiAhaXNCdWlsZFBoYXNlKCkpIHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IG5ldyBEeW5hbW9EQkNsaWVudCh7XG4gICAgICAgIHJlZ2lvbjogY29uZmlnLnJlZ2lvbixcbiAgICAgICAgLy8gV2l0aG91dCBgdGhyb3dPblJlcXVlc3RUaW1lb3V0YCB0aGUgdGltZW91dCBvbmx5IGxvZ3MgYSB3YXJuaW5nLiBJdFxuICAgICAgICAvLyBlbmRzIG9uY2UgdGhlIHJlc3BvbnNlIGhlYWRlcnMgYXJyaXZlOiBgc29ja2V0VGltZW91dGAsIGFuXG4gICAgICAgIC8vIGluYWN0aXZpdHkgdGltZXIga2VwdCB1bnRpbCB0aGUgcmVxdWVzdCBjbG9zZXMsIGNvdmVycyB0aGUgYm9keS5cbiAgICAgICAgcmVxdWVzdEhhbmRsZXI6IHtcbiAgICAgICAgICByZXF1ZXN0VGltZW91dDogVEFHX1RBQkxFX1JFUVVFU1RfVElNRU9VVF9NUyxcbiAgICAgICAgICB0aHJvd09uUmVxdWVzdFRpbWVvdXQ6IHRydWUsXG4gICAgICAgICAgc29ja2V0VGltZW91dDogVEFHX1RBQkxFX1JFUVVFU1RfVElNRU9VVF9NUyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgZ2xvYmFsW1RBR19NQU5JRkVTVF9TWU1CT0xdID0gbmV3IFRyYWNrZWRUYWdNYXJrZXJzKHtcbiAgICAgICAgbWFya2VyczogbmV3IFRhZ01hcmtlclRhYmxlKGNsaWVudCwgY29uZmlnLnRhYmxlTmFtZSwgY29uZmlnLmJ1aWxkSWQpLFxuICAgICAgICBsb2c6IG5ldyBSZXZhbGlkYXRpb25Mb2coY2xpZW50LCBjb25maWcudGFibGVOYW1lLCBjb25maWcuYnVpbGRJZCksXG4gICAgICAgIHJlZnJlc2hJbnRlcnZhbE1zLFxuICAgICAgICBkZWJ1ZzogZ2V0RGVidWcoXCJjZGstbmV4dGpzOmNhY2hlLWhhbmRsZXI6dGFnc1wiKSxcbiAgICAgICAgLy8gU2V0IGluIGV2ZXJ5IExhbWJkYSBydW50aW1lOyBhIGNvbnRhaW5lciBpcyBuZXZlciBmcm96ZW4uXG4gICAgICAgIGNhbkZyZWV6ZTogcHJvY2Vzcy5lbnYuQVdTX0xBTUJEQV9GVU5DVElPTl9OQU1FICE9PSB1bmRlZmluZWQsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFpc0J1aWxkUGhhc2UoKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgXCJDREtfTkVYVEpTX1JFVkFMSURBVElPTl9UQUJMRV9OQU1FIGVudmlyb25tZW50IHZhcmlhYmxlIG5vdCBzZXQsIGNhY2hlIHRhZ3MgYXJlIGxvY2FsIHRvIGVhY2ggaW5zdGFuY2VcIixcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGdsb2JhbFtUQUdfTUFOSUZFU1RfU1lNQk9MXSA9IG5ldyBUcmFja2VkVGFnTWFya2Vycyh7XG4gICAgICAgIHJlZnJlc2hJbnRlcnZhbE1zLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBnbG9iYWxbVEFHX01BTklGRVNUX1NZTUJPTF07XG59XG4iXX0=