1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.AsyncOrderedQueue = exports.AsyncIterableQueue = exports.AsyncQueue = exports.throttle = exports.cacheFn = exports.memoizeFn = exports.RateLimiter = exports.Pump = exports.Funnel = exports.retryOp = exports.DeferredWorker = exports.Deferred = void 0;
|
4 | const assert = require("assert");
|
5 | const crypto_1 = require("crypto");
|
6 | const error_1 = require("./error");
|
7 | const serialize_1 = require("./serialize");
|
8 | const shared_1 = require("./shared");
|
9 | class Deferred {
|
10 | constructor() {
|
11 | this.promise = new Promise((resolve, reject) => {
|
12 | this.resolve = resolve;
|
13 | this.reject = reject;
|
14 | });
|
15 | }
|
16 | }
|
17 | exports.Deferred = Deferred;
|
18 | class DeferredWorker extends Deferred {
|
19 | constructor(worker, cancel) {
|
20 | super();
|
21 | this.worker = worker;
|
22 | this.cancel = cancel;
|
23 | }
|
24 | async execute() {
|
25 | const cancelMessage = this.cancel?.();
|
26 | if (cancelMessage) {
|
27 | this.reject(new error_1.FaastError({ name: error_1.FaastErrorNames.ECANCEL }, cancelMessage));
|
28 | }
|
29 | else {
|
30 | try {
|
31 | const rv = await this.worker();
|
32 | this.resolve(rv);
|
33 | }
|
34 | catch (err) {
|
35 | this.reject(err);
|
36 | }
|
37 | }
|
38 | }
|
39 | }
|
40 | exports.DeferredWorker = DeferredWorker;
|
41 | function popFirst(set) {
|
42 | let firstElem;
|
43 | for (const elem of set) {
|
44 | firstElem = elem;
|
45 | break;
|
46 | }
|
47 | if (firstElem) {
|
48 | set.delete(firstElem);
|
49 | }
|
50 | return firstElem;
|
51 | }
|
52 | async function retryOp(retryN, fn) {
|
53 | const retryTest = typeof retryN === "function" ? retryN : (_, i) => i < retryN;
|
54 | for (let i = 0; true; i++) {
|
55 | try {
|
56 | return await fn(i);
|
57 | }
|
58 | catch (err) {
|
59 | if (!retryTest(err, i)) {
|
60 | throw err;
|
61 | }
|
62 | await (0, shared_1.sleep)(Math.min(30 * 1000, 1000 * (1 + Math.random()) * 2 ** i) + Math.random());
|
63 | }
|
64 | }
|
65 | }
|
66 | exports.retryOp = retryOp;
|
67 | class Funnel {
|
68 | constructor(concurrency = 0, shouldRetry) {
|
69 | this.concurrency = concurrency;
|
70 | this.shouldRetry = shouldRetry;
|
71 | this.pendingQueue = new Set();
|
72 | this.executingQueue = new Set();
|
73 | this.processed = 0;
|
74 | this.errors = 0;
|
75 | }
|
76 | push(worker, shouldRetry, cancel) {
|
77 | const retryTest = shouldRetry || this.shouldRetry || 0;
|
78 | const retryWorker = () => retryOp(retryTest, worker);
|
79 | const future = new DeferredWorker(retryWorker, cancel);
|
80 | this.pendingQueue.add(future);
|
81 | setImmediate(() => this.doWork());
|
82 | return future.promise;
|
83 | }
|
84 | clear() {
|
85 | this.pendingQueue.clear();
|
86 | this.executingQueue.clear();
|
87 | }
|
88 | promises() {
|
89 | return [...this.executingQueue, ...this.pendingQueue].map(p => p.promise);
|
90 | }
|
91 | all() {
|
92 | return Promise.all(this.promises().map(p => p.catch(_ => { })));
|
93 | }
|
94 | size() {
|
95 | return this.pendingQueue.size + this.executingQueue.size;
|
96 | }
|
97 | setMaxConcurrency(maxConcurrency) {
|
98 | this.concurrency = maxConcurrency;
|
99 | }
|
100 | getConcurrency() {
|
101 | return this.executingQueue.size;
|
102 | }
|
103 | doWork() {
|
104 | const { pendingQueue } = this;
|
105 | while (pendingQueue.size > 0 &&
|
106 | (!this.concurrency || this.executingQueue.size < this.concurrency)) {
|
107 | const worker = popFirst(pendingQueue);
|
108 | this.executingQueue.add(worker);
|
109 | worker.promise
|
110 | .then(_ => this.processed++)
|
111 | .catch(_ => this.errors++)
|
112 | .then(_ => {
|
113 | this.executingQueue.delete(worker);
|
114 | this.doWork();
|
115 | });
|
116 | worker.execute();
|
117 | }
|
118 | }
|
119 | }
|
120 | exports.Funnel = Funnel;
|
121 | /**
|
122 | * @internal
|
123 | */
|
124 | class Pump extends Funnel {
|
125 | constructor(options, worker) {
|
126 | super(options.concurrency);
|
127 | this.options = options;
|
128 | this.worker = worker;
|
129 | this.stopped = false;
|
130 | options.verbose = options.verbose ?? true;
|
131 | }
|
132 | start() {
|
133 | const restart = () => {
|
134 | if (this.stopped) {
|
135 | return;
|
136 | }
|
137 | while (this.executingQueue.size + this.pendingQueue.size < this.concurrency) {
|
138 | this.push(async () => {
|
139 | try {
|
140 | return await this.worker();
|
141 | }
|
142 | catch (err) {
|
143 | this.options.verbose && console.error(err);
|
144 | return;
|
145 | }
|
146 | finally {
|
147 | setImmediate(restart);
|
148 | }
|
149 | });
|
150 | }
|
151 | };
|
152 | this.stopped = false;
|
153 | restart();
|
154 | }
|
155 | stop() {
|
156 | this.stopped = true;
|
157 | }
|
158 | drain() {
|
159 | this.stop();
|
160 | return this.all();
|
161 | }
|
162 | setMaxConcurrency(concurrency) {
|
163 | super.setMaxConcurrency(concurrency);
|
164 | if (!this.stopped) {
|
165 | this.start();
|
166 | }
|
167 | }
|
168 | }
|
169 | exports.Pump = Pump;
|
170 | class RateLimiter {
|
171 | constructor(targetRequestsPerSecond, burst = 1) {
|
172 | this.targetRequestsPerSecond = targetRequestsPerSecond;
|
173 | this.burst = burst;
|
174 | this.lastTick = 0;
|
175 | this.bucket = 0;
|
176 | this.queue = new Set();
|
177 | assert(targetRequestsPerSecond > 0);
|
178 | assert(this.burst >= 1);
|
179 | }
|
180 | push(worker, cancel) {
|
181 | this.updateBucket();
|
182 | if (this.queue.size === 0 && this.bucket <= this.burst - 1) {
|
183 | this.bucket++;
|
184 | return worker();
|
185 | }
|
186 | const future = new DeferredWorker(worker, cancel);
|
187 | this.queue.add(future);
|
188 | if (this.queue.size === 1) {
|
189 | this.drainQueue();
|
190 | }
|
191 | return future.promise;
|
192 | }
|
193 | updateBucket() {
|
194 | const now = Date.now();
|
195 | const secondsElapsed = (now - this.lastTick) / 1000;
|
196 | this.bucket -= secondsElapsed * this.targetRequestsPerSecond;
|
197 | this.bucket = Math.max(this.bucket, 0);
|
198 | this.lastTick = now;
|
199 | }
|
200 | async drainQueue() {
|
201 | const requestAmountToDrain = 1 - (this.burst - this.bucket);
|
202 | const secondsToDrain = requestAmountToDrain / this.targetRequestsPerSecond;
|
203 | if (secondsToDrain > 0) {
|
204 | await (0, shared_1.sleep)(Math.ceil(secondsToDrain * 1000));
|
205 | }
|
206 | this.updateBucket();
|
207 | while (this.bucket <= this.burst - 1) {
|
208 | const next = popFirst(this.queue);
|
209 | if (!next) {
|
210 | break;
|
211 | }
|
212 | this.bucket++;
|
213 | next.execute();
|
214 | }
|
215 | if (this.queue.size > 0) {
|
216 | this.drainQueue();
|
217 | }
|
218 | }
|
219 | clear() {
|
220 | this.queue.clear();
|
221 | }
|
222 | }
|
223 | exports.RateLimiter = RateLimiter;
|
224 | function memoizeFn(fn, cache = new Map()) {
|
225 | return (...args) => {
|
226 | const key = JSON.stringify(args);
|
227 | const prev = cache.get(key);
|
228 | if (prev) {
|
229 | return prev;
|
230 | }
|
231 | const value = fn(...args);
|
232 | cache.set(key, value);
|
233 | return value;
|
234 | };
|
235 | }
|
236 | exports.memoizeFn = memoizeFn;
|
237 | function cacheFn(cache, fn) {
|
238 | return async (...args) => {
|
239 | const key = (0, serialize_1.serialize)(args, true);
|
240 | const hasher = (0, crypto_1.createHash)("sha256");
|
241 | hasher.update(key);
|
242 | const cacheKey = hasher.digest("hex");
|
243 | const prev = await cache.get(cacheKey);
|
244 | if (prev) {
|
245 | const str = prev.toString();
|
246 | if (str === "undefined") {
|
247 | return undefined;
|
248 | }
|
249 | return (0, serialize_1.deserialize)(str);
|
250 | }
|
251 | const value = await fn(...args);
|
252 | await cache.set(cacheKey, (0, serialize_1.serialize)(value, true));
|
253 | return value;
|
254 | };
|
255 | }
|
256 | exports.cacheFn = cacheFn;
|
257 | /**
|
258 | * A decorator for rate limiting, concurrency limiting, retry, memoization, and
|
259 | * on-disk caching. See {@link Limits}.
|
260 | * @remarks
|
261 | * When programming against cloud services, databases, and other resources, it
|
262 | * is often necessary to control the rate of request issuance to avoid
|
263 | * overwhelming the service provider. In many cases the provider has built-in
|
264 | * safeguards against abuse, which automatically fail requests if they are
|
265 | * coming in too fast. Some systems don't have safeguards and precipitously
|
266 | * degrade their service level or fail outright when faced with excessive load.
|
267 | *
|
268 | * With faast.js it becomes very easy to (accidentally) generate requests from
|
269 | * thousands of cloud functions. The `throttle` function can help manage request
|
270 | * flow without resorting to setting up a separate service. This is in keeping
|
271 | * with faast.js' zero-ops philosophy.
|
272 | *
|
273 | * Usage is simple:
|
274 | *
|
275 | * ```typescript
|
276 | * async function operation() { ... }
|
277 | * const throttledOperation = throttle({ concurrency: 10, rate: 5 }, operation);
|
278 | * for(let i = 0; i < 100; i++) {
|
279 | * // at most 10 concurrent executions at a rate of 5 invocations per second.
|
280 | * throttledOperation();
|
281 | * }
|
282 | * ```
|
283 | *
|
284 | * Note that each invocation to `throttle` creates a separate function with a
|
285 | * separate limits. Therefore it is likely that you want to use `throttle` in a
|
286 | * global context, not within a dynamic context:
|
287 | *
|
288 | * ```typescript
|
289 | * async function operation() { ... }
|
290 | * for(let i = 0; i < 100; i++) {
|
291 | * // WRONG - each iteration creates a separate throttled function that's only called once.
|
292 | * const throttledOperation = throttle({ concurrency: 10, rate: 5 }, operation);
|
293 | * throttledOperation();
|
294 | * }
|
295 | * ```
|
296 | *
|
297 | * A better way to use throttle avoids creating a named `operation` function
|
298 | * altogether, ensuring it cannot be accidentally called without throttling:
|
299 | *
|
300 | * ```typescript
|
301 | * const operation = throttle({ concurrency: 10, rate: 5 }, async () => {
|
302 | * ...
|
303 | * });
|
304 | * ```
|
305 | *
|
306 | * Throttle supports functions with arguments automatically infers the correct
|
307 | * type for the returned function:
|
308 | *
|
309 | * ```typescript
|
310 | * // `operation` inferred to have type (str: string) => Promise<string>
|
311 | * const operation = throttle({ concurrency: 10, rate: 5 }, async (str: string) => {
|
312 | * return string;
|
313 | * });
|
314 | * ```
|
315 | *
|
316 | * In addition to limiting concurrency and invocation rate, `throttle` also
|
317 | * supports retrying failed invocations, memoizing calls, and on-disk caching.
|
318 | * See {@link Limits} for details.
|
319 | *
|
320 | * @param limits - see {@link Limits}.
|
321 | * @param fn - The function to throttle. It can take any arguments, but must
|
322 | * return a Promise (which includes `async` functions).
|
323 | * @returns Returns a throttled function with the same signature as the argument
|
324 | * `fn`.
|
325 | * @public
|
326 | */
|
327 | function throttle(limits, fn) {
|
328 | const { concurrency, retry, rate, burst, memoize, cache, cancel } = limits;
|
329 | const funnel = new Funnel(concurrency, retry);
|
330 | const cancellationQueue = [() => funnel.clear()];
|
331 | let conditionedFunc;
|
332 | if (rate) {
|
333 | const rateLimiter = new RateLimiter(rate, burst);
|
334 | cancellationQueue.push(() => rateLimiter.clear());
|
335 | conditionedFunc = (...args) => funnel.push(() => rateLimiter.push(() => fn(...args)));
|
336 | }
|
337 | else {
|
338 | conditionedFunc = (...args) => funnel.push(() => fn(...args));
|
339 | }
|
340 | if (cache) {
|
341 | conditionedFunc = cacheFn(cache, conditionedFunc);
|
342 | }
|
343 | if (memoize) {
|
344 | const mcache = new Map();
|
345 | cancellationQueue.push(() => mcache.clear());
|
346 | conditionedFunc = memoizeFn(conditionedFunc, mcache);
|
347 | }
|
348 | cancel?.then(() => cancellationQueue.forEach(cleanupFn => cleanupFn()));
|
349 | return conditionedFunc;
|
350 | }
|
351 | exports.throttle = throttle;
|
352 | function iteratorResult(value) {
|
353 | return Promise.resolve(value).then(v => ({ done: false, value: v }));
|
354 | }
|
355 | const done = Promise.resolve({ done: true, value: undefined });
|
356 | class AsyncQueue {
|
357 | constructor() {
|
358 | this.deferred = [];
|
359 | this.enqueued = [];
|
360 | }
|
361 | enqueue(value) {
|
362 | if (this.deferred.length > 0) {
|
363 | const d = this.deferred.shift();
|
364 | d.resolve(value);
|
365 | }
|
366 | else {
|
367 | this.enqueued.push(Promise.resolve(value));
|
368 | }
|
369 | }
|
370 | next() {
|
371 | if (this.enqueued.length > 0) {
|
372 | return this.enqueued.shift();
|
373 | }
|
374 | const d = new Deferred();
|
375 | this.deferred.push(d);
|
376 | return d.promise;
|
377 | }
|
378 | clear() {
|
379 | this.deferred = [];
|
380 | this.enqueued = [];
|
381 | }
|
382 | }
|
383 | exports.AsyncQueue = AsyncQueue;
|
384 | class AsyncIterableQueue extends AsyncQueue {
|
385 | push(value) {
|
386 | super.enqueue(iteratorResult(value));
|
387 | }
|
388 | done() {
|
389 | super.enqueue(done);
|
390 | }
|
391 | [Symbol.asyncIterator]() {
|
392 | return this;
|
393 | }
|
394 | }
|
395 | exports.AsyncIterableQueue = AsyncIterableQueue;
|
396 | class AsyncOrderedQueue {
|
397 | constructor() {
|
398 | this.queue = new AsyncQueue();
|
399 | this.arrived = new Map();
|
400 | this.current = 0;
|
401 | }
|
402 | push(value, sequence) {
|
403 | this.enqueue(Promise.resolve(value), sequence);
|
404 | }
|
405 | pushImmediate(value) {
|
406 | this.queue.enqueue(value);
|
407 | }
|
408 | enqueue(value, sequence) {
|
409 | if (sequence < this.current) {
|
410 | return;
|
411 | }
|
412 | if (!this.arrived.has(sequence)) {
|
413 | this.arrived.set(sequence, value);
|
414 | }
|
415 | while (this.arrived.has(this.current)) {
|
416 | this.queue.enqueue(this.arrived.get(this.current));
|
417 | this.arrived.delete(this.current);
|
418 | this.current++;
|
419 | }
|
420 | }
|
421 | next() {
|
422 | return this.queue.next();
|
423 | }
|
424 | clear() {
|
425 | this.arrived.clear();
|
426 | this.queue.clear();
|
427 | this.current = 0;
|
428 | }
|
429 | }
|
430 | exports.AsyncOrderedQueue = AsyncOrderedQueue;
|
431 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhyb3R0bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGhyb3R0bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaUNBQWlDO0FBQ2pDLG1DQUFvQztBQUVwQyxtQ0FBc0Q7QUFDdEQsMkNBQXFEO0FBQ3JELHFDQUFpQztBQUVqQyxNQUFhLFFBQVE7SUFJakI7UUFDSSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksT0FBTyxDQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzlDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3pCLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztDQUNKO0FBVkQsNEJBVUM7QUFFRCxNQUFhLGNBQXlCLFNBQVEsUUFBVztJQUNyRCxZQUNZLE1BQXdCLEVBQ3hCLE1BQWlDO1FBRXpDLEtBQUssRUFBRSxDQUFDO1FBSEEsV0FBTSxHQUFOLE1BQU0sQ0FBa0I7UUFDeEIsV0FBTSxHQUFOLE1BQU0sQ0FBMkI7SUFHN0MsQ0FBQztJQUNELEtBQUssQ0FBQyxPQUFPO1FBQ1QsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDdEMsSUFBSSxhQUFhLEVBQUU7WUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksa0JBQVUsQ0FBQyxFQUFFLElBQUksRUFBRSx1QkFBZSxDQUFDLE9BQU8sRUFBRSxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUM7U0FDakY7YUFBTTtZQUNILElBQUk7Z0JBQ0EsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEI7WUFBQyxPQUFPLEdBQVEsRUFBRTtnQkFDZixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFD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QUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBRSxDQUFDLENBQUM7WUFDcEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNsQjtJQUNMLENBQUM7SUFFRCxJQUFJO1FBQ0EsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxLQUFLO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBQ3JCLENBQUM7Q0FDSjtBQXBDRCw4Q0FvQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJjcnlwdG9cIjtcbmltcG9ydCB7IFBlcnNpc3RlbnRDYWNoZSB9IGZyb20gXCIuL2NhY2hlXCI7XG5pbXBvcnQgeyBGYWFzdEVycm9yLCBGYWFzdEVycm9yTmFtZXMgfSBmcm9tIFwiLi9lcnJvclwiO1xuaW1wb3J0IHsgZGVzZXJpYWxpemUsIHNlcmlhbGl6ZSB9IGZyb20gXCIuL3NlcmlhbGl6ZVwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi9zaGFyZWRcIjtcblxuZXhwb3J0IGNsYXNzIERlZmVycmVkPFQgPSB2b2lkPiB7XG4gICAgcHJvbWlzZTogUHJvbWlzZTxUPjtcbiAgICByZXNvbHZlITogKGFyZzogVCB8IFByb21pc2VMaWtlPFQ+KSA9PiB2b2lkO1xuICAgIHJlamVjdCE6IChlcnI/OiBhbnkpID0+IHZvaWQ7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMucHJvbWlzZSA9IG5ldyBQcm9taXNlPFQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICB0aGlzLnJlamVjdCA9IHJlamVjdDtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgRGVmZXJyZWRXb3JrZXI8VCA9IHZvaWQ+IGV4dGVuZHMgRGVmZXJyZWQ8VD4ge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIHdvcmtlcjogKCkgPT4gUHJvbWlzZTxUPixcbiAgICAgICAgcHJpdmF0ZSBjYW5jZWw/OiAoKSA9PiBzdHJpbmcgfCB1bmRlZmluZWRcbiAgICApIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICB9XG4gICAgYXN5bmMgZXhlY3V0ZSgpIHtcbiAgICAgICAgY29uc3QgY2FuY2VsTWVzc2FnZSA9IHRoaXMuY2FuY2VsPy4oKTtcbiAgICAgICAgaWYgKGNhbmNlbE1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHRoaXMucmVqZWN0KG5ldyBGYWFzdEVycm9yKHsgbmFtZTogRmFhc3RFcnJvck5hbWVzLkVDQU5DRUwgfSwgY2FuY2VsTWVzc2FnZSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBydiA9IGF3YWl0IHRoaXMud29ya2VyKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvbHZlKHJ2KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gcG9wRmlyc3Q8VD4oc2V0OiBTZXQ8VD4pOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBsZXQgZmlyc3RFbGVtOiBUIHwgdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3QgZWxlbSBvZiBzZXQpIHtcbiAgICAgICAgZmlyc3RFbGVtID0gZWxlbTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGlmIChmaXJzdEVsZW0pIHtcbiAgICAgICAgc2V0LmRlbGV0ZShmaXJzdEVsZW0pO1xuICAgIH1cbiAgICByZXR1cm4gZmlyc3RFbGVtO1xufVxuXG5leHBvcnQgdHlwZSBSZXRyeVR5cGUgPSBudW1iZXIgfCAoKGVycjogYW55LCByZXRyaWVzOiBudW1iZXIpID0+IGJvb2xlYW4pO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmV0cnlPcDxUPihyZXRyeU46IFJldHJ5VHlwZSwgZm46IChyZXRyaWVzOiBudW1iZXIpID0+IFByb21pc2U8VD4pIHtcbiAgICBjb25zdCByZXRyeVRlc3QgPVxuICAgICAgICB0eXBlb2YgcmV0cnlOID09PSBcImZ1bmN0aW9uXCIgPyByZXRyeU4gOiAoXzogYW55LCBpOiBudW1iZXIpID0+IGkgPCByZXRyeU47XG4gICAgZm9yIChsZXQgaSA9IDA7IHRydWU7IGkrKykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGZuKGkpO1xuICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgaWYgKCFyZXRyeVRlc3QoZXJyLCBpKSkge1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IHNsZWVwKFxuICAgICAgICAgICAgICAgIE1hdGgubWluKDMwICogMTAwMCwgMTAwMCAqICgxICsgTWF0aC5yYW5kb20oKSkgKiAyICoqIGkpICsgTWF0aC5yYW5kb20oKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEZ1bm5lbDxUID0gdm9pZD4ge1xuICAgIHByb3RlY3RlZCBwZW5kaW5nUXVldWU6IFNldDxEZWZlcnJlZFdvcmtlcjxUPj4gPSBuZXcgU2V0KCk7XG4gICAgcHJvdGVjdGVkIGV4ZWN1dGluZ1F1ZXVlOiBTZXQ8RGVmZXJyZWRXb3JrZXI8VD4+ID0gbmV3IFNldCgpO1xuICAgIHB1YmxpYyBwcm9jZXNzZWQgPSAwO1xuICAgIHB1YmxpYyBlcnJvcnMgPSAwO1xuXG4gICAgY29uc3RydWN0b3IocHVibGljIGNvbmN1cnJlbmN5OiBudW1iZXIgPSAwLCBwcm90ZWN0ZWQgc2hvdWxkUmV0cnk/OiBSZXRyeVR5cGUpIHt9XG5cbiAgICBwdXNoKFxuICAgICAgICB3b3JrZXI6ICgpID0+IFByb21pc2U8VD4sXG4gICAgICAgIHNob3VsZFJldHJ5PzogUmV0cnlUeXBlLFxuICAgICAgICBjYW5jZWw/OiAoKSA9PiBzdHJpbmcgfCB1bmRlZmluZWRcbiAgICApIHtcbiAgICAgICAgY29uc3QgcmV0cnlUZXN0ID0gc2hvdWxkUmV0cnkgfHwgdGhpcy5zaG91bGRSZXRyeSB8fCAwO1xuICAgICAgICBjb25zdCByZXRyeVdvcmtlciA9ICgpID0+IHJldHJ5T3AocmV0cnlUZXN0LCB3b3JrZXIpO1xuICAgICAgICBjb25zdCBmdXR1cmUgPSBuZXcgRGVmZXJyZWRXb3JrZXIocmV0cnlXb3JrZXIsIGNhbmNlbCk7XG4gICAgICAgIHRoaXMucGVuZGluZ1F1ZXVlLmFkZChmdXR1cmUpO1xuICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5kb1dvcmsoKSk7XG4gICAgICAgIHJldHVybiBmdXR1cmUucHJvbWlzZTtcbiAgICB9XG5cbiAgICBjbGVhcigpIHtcbiAgICAgICAgdGhpcy5wZW5kaW5nUXVldWUuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5leGVjdXRpbmdRdWV1ZS5jbGVhcigpO1xuICAgIH1cblxuICAgIHByb21pc2VzKCkge1xuICAgICAgICByZXR1cm4gWy4uLnRoaXMuZXhlY3V0aW5nUXVldWUsIC4uLnRoaXMucGVuZGluZ1F1ZXVlXS5tYXAocCA9PiBwLnByb21pc2UpO1xuICAgIH1cblxuICAgIGFsbCgpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHRoaXMucHJvbWlzZXMoKS5tYXAocCA9PiBwLmNhdGNoKF8gPT4ge30pKSk7XG4gICAgfVxuXG4gICAgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGVuZGluZ1F1ZXVlLnNpemUgKyB0aGlzLmV4ZWN1dGluZ1F1ZXVlLnNpemU7XG4gICAgfVxuXG4gICAgc2V0TWF4Q29uY3VycmVuY3kobWF4Q29uY3VycmVuY3k6IG51bWJlcikge1xuICAgICAgICB0aGlzLmNvbmN1cnJlbmN5ID0gbWF4Q29uY3VycmVuY3k7XG4gICAgfVxuXG4gICAgZ2V0Q29uY3VycmVuY3koKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGluZ1F1ZXVlLnNpemU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGRvV29yaygpIHtcbiAgICAgICAgY29uc3QgeyBwZW5kaW5nUXVldWUgfSA9IHRoaXM7XG4gICAgICAgIHdoaWxlIChcbiAgICAgICAgICAgIHBlbmRpbmdRdWV1ZS5zaXplID4gMCAmJlxuICAgICAgICAgICAgKCF0aGlzLmNvbmN1cnJlbmN5IHx8IHRoaXMuZXhlY3V0aW5nUXVldWUuc2l6ZSA8IHRoaXMuY29uY3VycmVuY3kpXG4gICAgICAgICkge1xuICAgICAgICAgICAgY29uc3Qgd29ya2VyID0gcG9wRmlyc3QocGVuZGluZ1F1ZXVlKSE7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGluZ1F1ZXVlLmFkZCh3b3JrZXIpO1xuXG4gICAgICAgICAgICB3b3JrZXIucHJvbWlzZVxuICAgICAgICAgICAgICAgIC50aGVuKF8gPT4gdGhpcy5wcm9jZXNzZWQrKylcbiAgICAgICAgICAgICAgICAuY2F0Y2goXyA9PiB0aGlzLmVycm9ycysrKVxuICAgICAgICAgICAgICAgIC50aGVuKF8gPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4ZWN1dGluZ1F1ZXVlLmRlbGV0ZSh3b3JrZXIpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvV29yaygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgd29ya2VyLmV4ZWN1dGUoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQdW1wT3B0aW9ucyB7XG4gICAgY29uY3VycmVuY3k6IG51bWJlcjtcbiAgICB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIFB1bXA8VCA9IHZvaWQ+IGV4dGVuZHMgRnVubmVsPFQgfCB2b2lkPiB7XG4gICAgc3RvcHBlZDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBvcHRpb25zOiBQdW1wT3B0aW9ucywgcHJvdGVjdGVkIHdvcmtlcjogKCkgPT4gUHJvbWlzZTxUPikge1xuICAgICAgICBzdXBlcihvcHRpb25zLmNvbmN1cnJlbmN5KTtcbiAgICAgICAgb3B0aW9ucy52ZXJib3NlID0gb3B0aW9ucy52ZXJib3NlID8/IHRydWU7XG4gICAgfVxuXG4gICAgc3RhcnQoKSB7XG4gICAgICAgIGNvbnN0IHJlc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdG9wcGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKHRoaXMuZXhlY3V0aW5nUXVldWUuc2l6ZSArIHRoaXMucGVuZGluZ1F1ZXVlLnNpemUgPCB0aGlzLmNvbmN1cnJlbmN5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wdXNoKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLndvcmtlcigpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnZlcmJvc2UgJiYgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0SW1tZWRpYXRlKHJlc3RhcnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3RvcHBlZCA9IGZhbHNlO1xuICAgICAgICByZXN0YXJ0KCk7XG4gICAgfVxuXG4gICAgc3RvcCgpIHtcbiAgICAgICAgdGhpcy5zdG9wcGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBkcmFpbigpIHtcbiAgICAgICAgdGhpcy5zdG9wKCk7XG4gICAgICAgIHJldHVybiB0aGlzLmFsbCgpO1xuICAgIH1cblxuICAgIHNldE1heENvbmN1cnJlbmN5KGNvbmN1cnJlbmN5OiBudW1iZXIpIHtcbiAgICAgICAgc3VwZXIuc2V0TWF4Q29uY3VycmVuY3koY29uY3VycmVuY3kpO1xuICAgICAgICBpZiAoIXRoaXMuc3RvcHBlZCkge1xuICAgICAgICAgICAgdGhpcy5zdGFydCgpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgUmF0ZUxpbWl0ZXI8VCA9IHZvaWQ+IHtcbiAgICBwcm90ZWN0ZWQgbGFzdFRpY2sgPSAwO1xuICAgIHByb3RlY3RlZCBidWNrZXQgPSAwO1xuICAgIHByb3RlY3RlZCBxdWV1ZTogU2V0PERlZmVycmVkV29ya2VyPFQ+PiA9IG5ldyBTZXQoKTtcblxuICAgIGNvbnN0cnVjdG9yKHByb3RlY3RlZCB0YXJnZXRSZXF1ZXN0c1BlclNlY29uZDogbnVtYmVyLCBwcm90ZWN0ZWQgYnVyc3Q6IG51bWJlciA9IDEpIHtcbiAgICAgICAgYXNzZXJ0KHRhcmdldFJlcXVlc3RzUGVyU2Vjb25kID4gMCk7XG4gICAgICAgIGFzc2VydCh0aGlzLmJ1cnN0ID49IDEpO1xuICAgIH1cblxuICAgIHB1c2god29ya2VyOiAoKSA9PiBQcm9taXNlPFQ+LCBjYW5jZWw/OiAoKSA9PiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy51cGRhdGVCdWNrZXQoKTtcbiAgICAgICAgaWYgKHRoaXMucXVldWUuc2l6ZSA9PT0gMCAmJiB0aGlzLmJ1Y2tldCA8PSB0aGlzLmJ1cnN0IC0gMSkge1xuICAgICAgICAgICAgdGhpcy5idWNrZXQrKztcbiAgICAgICAgICAgIHJldHVybiB3b3JrZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZ1dHVyZSA9IG5ldyBEZWZlcnJlZFdvcmtlcih3b3JrZXIsIGNhbmNlbCk7XG4gICAgICAgIHRoaXMucXVldWUuYWRkKGZ1dHVyZSk7XG4gICAgICAgIGlmICh0aGlzLnF1ZXVlLnNpemUgPT09IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhaW5RdWV1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdXR1cmUucHJvbWlzZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgdXBkYXRlQnVja2V0KCkge1xuICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCBzZWNvbmRzRWxhcHNlZCA9IChub3cgLSB0aGlzLmxhc3RUaWNrKSAvIDEwMDA7XG4gICAgICAgIHRoaXMuYnVja2V0IC09IHNlY29uZHNFbGFwc2VkICogdGhpcy50YXJnZXRSZXF1ZXN0c1BlclNlY29uZDtcbiAgICAgICAgdGhpcy5idWNrZXQgPSBNYXRoLm1heCh0aGlzLmJ1Y2tldCwgMCk7XG4gICAgICAgIHRoaXMubGFzdFRpY2sgPSBub3c7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFzeW5jIGRyYWluUXVldWUoKSB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RBbW91bnRUb0RyYWluID0gMSAtICh0aGlzLmJ1cnN0IC0gdGhpcy5idWNrZXQpO1xuICAgICAgICBjb25zdCBzZWNvbmRzVG9EcmFpbiA9IHJlcXVlc3RBbW91bnRUb0RyYWluIC8gdGhpcy50YXJnZXRSZXF1ZXN0c1BlclNlY29uZDtcbiAgICAgICAgaWYgKHNlY29uZHNUb0RyYWluID4gMCkge1xuICAgICAgICAgICAgYXdhaXQgc2xlZXAoTWF0aC5jZWlsKHNlY29uZHNUb0RyYWluICogMTAwMCkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlQnVja2V0KCk7XG4gICAgICAgIHdoaWxlICh0aGlzLmJ1Y2tldCA8PSB0aGlzLmJ1cnN0IC0gMSkge1xuICAgICAgICAgICAgY29uc3QgbmV4dCA9IHBvcEZpcnN0KHRoaXMucXVldWUpO1xuICAgICAgICAgICAgaWYgKCFuZXh0KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJ1Y2tldCsrO1xuICAgICAgICAgICAgbmV4dC5leGVjdXRlKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucXVldWUuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuZHJhaW5RdWV1ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xlYXIoKSB7XG4gICAgICAgIHRoaXMucXVldWUuY2xlYXIoKTtcbiAgICB9XG59XG5cbi8qKlxuICogU3BlY2lmeSB7QGxpbmsgdGhyb3R0bGV9IGxpbWl0cy4gVGhlc2UgbGltaXRzIHNoYXBlIHRoZSB3YXkgdGhyb3R0bGUgaW52b2tlc1xuICogdGhlIHVuZGVybHlpbmcgZnVuY3Rpb24uXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGltaXRzIHtcbiAgICAvKipcbiAgICAgKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgY29uY3VycmVudCBleGVjdXRpb25zIG9mIHRoZSB1bmRlcmx5aW5nIGZ1bmN0aW9uIHRvXG4gICAgICogYWxsb3cuIE11c3QgYmUgc3VwcGxpZWQsIHRoZXJlIGlzIG5vIGRlZmF1bHQuIFNwZWNpZnlpbmcgYDBgIG9yXG4gICAgICogYEluZmluaXR5YCBpcyBhbGxvd2VkIGFuZCBtZWFucyB0aGVyZSBpcyBubyBjb25jdXJyZW5jeSBsaW1pdC5cbiAgICAgKi9cbiAgICBjb25jdXJyZW5jeTogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBjYWxscyBwZXIgc2Vjb25kIHRvIGFsbG93IHRvIHRoZSB1bmRlcmx5aW5nXG4gICAgICogZnVuY3Rpb24uIERlZmF1bHQ6IG5vIHJhdGUgbGltaXQuXG4gICAgICovXG4gICAgcmF0ZT86IG51bWJlcjtcbiAgICAvKipcbiAgICAgKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgY2FsbHMgdG8gdGhlIHVuZGVybHlpbmcgZnVuY3Rpb24gdG8gXCJidXJzdFwiIC0tIGUuZy5cbiAgICAgKiB0aGUgbnVtYmVyIHRoYXQgY2FuIGJlIGlzc3VlZCBpbW1lZGlhdGVseSBhcyBsb25nIGFzIHRoZSByYXRlIGxpbWl0IGlzXG4gICAgICogbm90IGV4Y2VlZGVkLiBGb3IgZXhhbXBsZSwgaWYgcmF0ZSBpcyA1IGFuZCBidXJzdCBpcyA1LCBhbmQgMTAgY2FsbHMgYXJlXG4gICAgICogbWFkZSB0byB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uLCA1IGNhbGxzIGFyZSBtYWRlIGltbWVkaWF0ZWx5IGFuZCB0aGVuXG4gICAgICogYWZ0ZXIgMSBzZWNvbmQsIGFub3RoZXIgNSBjYWxscyBhcmUgbWFkZSBpbW1lZGlhdGVseS4gU2V0dGluZyBidXJzdCB0byAxXG4gICAgICogbWVhbnMgY2FsbHMgYXJlIGlzc3VlZCB1bmlmb3JtbHkgZXZlcnkgYDEvcmF0ZWAgc2Vjb25kcy4gSWYgYHJhdGVgIGlzIG5vdFxuICAgICAqIHNwZWNpZmllZCwgdGhlbiBgYnVyc3RgIGRvZXMgbm90IGFwcGx5LiBEZWZhdWx0OiAxLlxuICAgICAqL1xuICAgIGJ1cnN0PzogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFJldHJ5IGlmIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gcmV0dXJucyBhIHJlamVjdGVkIHByb21pc2UuIGByZXRyeWAgY2FuXG4gICAgICogYmUgYSBudW1iZXIgb3IgYSBmdW5jdGlvbi4gSWYgaXQgaXMgYSBudW1iZXIgYE5gLCB0aGVuIHVwIHRvIGBOYFxuICAgICAqIGFkZGl0aW9uYWwgYXR0ZW1wdHMgYXJlIG1hZGUgaW4gYWRkaXRpb24gdG8gdGhlIGluaXRpYWwgY2FsbC4gSWYgcmV0cnkgaXNcbiAgICAgKiBhIGZ1bmN0aW9uLCBpdCBzaG91bGQgcmV0dXJuIGB0cnVlYCBpZiBhbm90aGVyIHJldHJ5IGF0dGVtcHQgc2hvdWxkIGJlXG4gICAgICogbWFkZSwgb3RoZXJ3aXNlIGBmYWxzZWAuIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGJlIHRoZSB2YWx1ZSBvZiB0aGVcbiAgICAgKiByZWplY3RlZCBwcm9taXNlIGZyb20gdGhlIHByZXZpb3VzIGNhbGwgYXR0ZW1wdCwgYW5kIHRoZSBzZWNvbmQgYXJndW1lbnRcbiAgICAgKiB3aWxsIGJlIHRoZSBudW1iZXIgb2YgcHJldmlvdXMgcmV0cnkgYXR0ZW1wdHMgKGUuZy4gdGhlIGZpcnN0IGNhbGwgd2lsbFxuICAgICAqIGhhdmUgdmFsdWUgMCkuIERlZmF1bHQ6IDAgKG5vIHJldHJ5IGF0dGVtcHRzKS5cbiAgICAgKi9cbiAgICByZXRyeT86IG51bWJlciB8ICgoZXJyOiBhbnksIHJldHJpZXM6IG51bWJlcikgPT4gYm9vbGVhbik7XG4gICAgLyoqXG4gICAgICogSWYgYG1lbW9pemVgIGlzIGB0cnVlYCwgdGhlbiBldmVyeSBjYWxsIHRvIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gd2lsbCBiZVxuICAgICAqIHNhdmVkIGFzIGFuIGVudHJ5IGluIGEgbWFwIGZyb20gYXJndW1lbnRzIHRvIHJldHVybiB2YWx1ZS4gSWYgc2FtZVxuICAgICAqIGFyZ3VtZW50cyBhcmUgc2VlbiBhZ2FpbiBpbiBhIGZ1dHVyZSBjYWxsLCB0aGUgcmV0dXJuIHZhbHVlIGlzIHJldHJpZXZlZFxuICAgICAqIGZyb20gdGhlIE1hcCByYXRoZXIgdGhhbiBjYWxsaW5nIHRoZSBmdW5jdGlvbiBhZ2Fpbi4gVGhpcyBjYW4gYmUgdXNlZnVsXG4gICAgICogZm9yIGF2b2lkaW5nIHJlZHVuZGFudCBjYWxscyB0aGF0IGFyZSBleHBlY3RlZCB0byByZXR1cm4gdGhlIHNhbWUgcmVzdWx0c1xuICAgICAqIGdpdmVuIHRoZSBzYW1lIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBhcmd1bWVudHMgd2lsbCBiZSBjYXB0dXJlZCB3aXRoIGBKU09OLnN0cmluZ2lmeWAsIHRoZXJlZm9yZSB0eXBlc1xuICAgICAqIHRoYXQgZG8gbm90IHN0cmluZ2lmeSB1bmlxdWVseSB3b24ndCBiZSBkaXN0aW5ndWlzaGVkIGZyb20gZWFjaCBvdGhlci5cbiAgICAgKiBDYXJlIG11c3QgYmUgdGFrZW4gd2hlbiBzcGVjaWZ5aW5nIGBtZW1vaXplYCB0byBlbnN1cmUgYXZvaWQgaW5jb3JyZWN0XG4gICAgICogcmVzdWx0cy5cbiAgICAgKi9cbiAgICBtZW1vaXplPzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBTaW1pbGFyIHRvIGBtZW1vaXplYCBleGNlcHQgdGhlIG1hcCBmcm9tIGZ1bmN0aW9uIGFyZ3VtZW50cyB0byByZXN1bHRzIGlzXG4gICAgICogc3RvcmVkIGluIGEgcGVyc2lzdGVudCBjYWNoZSBvbiBkaXNrLiBUaGlzIGlzIHVzZWZ1bCB0byBwcmV2ZW50IHJlZHVuZGFudFxuICAgICAqIGNhbGxzIHRvIEFQSXMgd2hpY2ggYXJlIGV4cGVjdGVkIHRvIHJldHVybiB0aGUgc2FtZSByZXN1bHRzIGZvciB0aGUgc2FtZVxuICAgICAqIGFyZ3VtZW50cywgYW5kIHdoaWNoIGFyZSBsaWtlbHkgdG8gYmUgY2FsbGVkIGFjcm9zcyBtYW55IGZhYXN0LmpzIG1vZHVsZVxuICAgICAqIGluc3RhbnRpYXRpb25zLiBUaGlzIGlzIHVzZWQgaW50ZXJuYWxseSBieSBmYWFzdC5qcyBmb3IgY2FjaGluZyBjbG91ZFxuICAgICAqIHByaWNlcyBmb3IgQVdTIGFuZCBHb29nbGUsIGFuZCBmb3Igc2F2aW5nIHRoZSBsYXN0IGdhcmJhZ2UgY29sbGVjdGlvblxuICAgICAqIGRhdGUgZm9yIEFXUy4gUGVyc2lzdGVudCBjYWNoZSBlbnRyaWVzIGV4cGlyZSBhZnRlciBhIHBlcmlvZCBvZiB0aW1lLiBTZWVcbiAgICAgKiB7QGxpbmsgUGVyc2lzdGVudENhY2hlfS5cbiAgICAgKi9cbiAgICBjYWNoZT86IFBlcnNpc3RlbnRDYWNoZTtcbiAgICAvKipcbiAgICAgKiBBIHByb21pc2UgdGhhdCwgaWYgcmVzb2x2ZWQsIGNhdXNlcyBjYW5jZWxsYXRpb24gb2YgcGVuZGluZyB0aHJvdHRsZWRcbiAgICAgKiBpbnZvY2F0aW9ucy4gVGhpcyBpcyB0eXBpY2FsbHkgY3JlYXRlZCB1c2luZyBgRGVmZXJyZWRgLiBUaGUgaWRlYSBpcyB0b1xuICAgICAqIHVzZSB0aGUgcmVzb2x2aW5nIG9mIHRoZSBwcm9taXNlIGFzIGFuIGFzeW5jaHJvbm91cyBzaWduYWwgdGhhdCBhbnlcbiAgICAgKiBwZW5kaW5nIGludm9jYXRpb25zIGluIHRoaXMgdGhyb3R0bGVkIGZ1bmN0aW9uIHNob3VsZCBiZSBjbGVhcmVkLlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNhbmNlbD86IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZW1vaXplRm48QSBleHRlbmRzIGFueVtdLCBSPihcbiAgICBmbjogKC4uLmFyZ3M6IEEpID0+IFIsXG4gICAgY2FjaGU6IE1hcDxzdHJpbmcsIFI+ID0gbmV3IE1hcCgpXG4pIHtcbiAgICByZXR1cm4gKC4uLmFyZ3M6IEEpID0+IHtcbiAgICAgICAgY29uc3Qga2V5ID0gSlNPTi5zdHJpbmdpZnkoYXJncyk7XG4gICAgICAgIGNvbnN0IHByZXYgPSBjYWNoZS5nZXQoa2V5KTtcbiAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICAgIHJldHVybiBwcmV2O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZm4oLi4uYXJncyk7XG4gICAgICAgIGNhY2hlLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWNoZUZuPEEgZXh0ZW5kcyBhbnlbXSwgUj4oXG4gICAgY2FjaGU6IFBlcnNpc3RlbnRDYWNoZSxcbiAgICBmbjogKC4uLmFyZ3M6IEEpID0+IFByb21pc2U8Uj5cbikge1xuICAgIHJldHVybiBhc3luYyAoLi4uYXJnczogQSkgPT4ge1xuICAgICAgICBjb25zdCBrZXkgPSBzZXJpYWxpemUoYXJncywgdHJ1ZSk7XG4gICAgICAgIGNvbnN0IGhhc2hlciA9IGNyZWF0ZUhhc2goXCJzaGEyNTZcIik7XG4gICAgICAgIGhhc2hlci51cGRhdGUoa2V5KTtcbiAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBoYXNoZXIuZGlnZXN0KFwiaGV4XCIpO1xuICAgICAgICBjb25zdCBwcmV2ID0gYXdhaXQgY2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IHByZXYudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGlmIChzdHIgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRlc2VyaWFsaXplKHN0cik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBmbiguLi5hcmdzKTtcbiAgICAgICAgYXdhaXQgY2FjaGUuc2V0KGNhY2hlS2V5LCBzZXJpYWxpemUodmFsdWUsIHRydWUpKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG59XG5cbi8qKlxuICogQSBkZWNvcmF0b3IgZm9yIHJhdGUgbGltaXRpbmcsIGNvbmN1cnJlbmN5IGxpbWl0aW5nLCByZXRyeSwgbWVtb2l6YXRpb24sIGFuZFxuICogb24tZGlzayBjYWNoaW5nLiBTZWUge0BsaW5rIExpbWl0c30uXG4gKiBAcmVtYXJrc1xuICogV2hlbiBwcm9ncmFtbWluZyBhZ2FpbnN0IGNsb3VkIHNlcnZpY2VzLCBkYXRhYmFzZXMsIGFuZCBvdGhlciByZXNvdXJjZXMsIGl0XG4gKiBpcyBvZnRlbiBuZWNlc3NhcnkgdG8gY29udHJvbCB0aGUgcmF0ZSBvZiByZXF1ZXN0IGlzc3VhbmNlIHRvIGF2b2lkXG4gKiBvdmVyd2hlbG1pbmcgdGhlIHNlcnZpY2UgcHJvdmlkZXIuIEluIG1hbnkgY2FzZXMgdGhlIHByb3ZpZGVyIGhhcyBidWlsdC1pblxuICogc2FmZWd1YXJkcyBhZ2FpbnN0IGFidXNlLCB3aGljaCBhdXRvbWF0aWNhbGx5IGZhaWwgcmVxdWVzdHMgaWYgdGhleSBhcmVcbiAqIGNvbWluZyBpbiB0b28gZmFzdC4gU29tZSBzeXN0ZW1zIGRvbid0IGhhdmUgc2FmZWd1YXJkcyBhbmQgcHJlY2lwaXRvdXNseVxuICogZGVncmFkZSB0aGVpciBzZXJ2aWNlIGxldmVsIG9yIGZhaWwgb3V0cmlnaHQgd2hlbiBmYWNlZCB3aXRoIGV4Y2Vzc2l2ZSBsb2FkLlxuICpcbiAqIFdpdGggZmFhc3QuanMgaXQgYmVjb21lcyB2ZXJ5IGVhc3kgdG8gKGFjY2lkZW50YWxseSkgZ2VuZXJhdGUgcmVxdWVzdHMgZnJvbVxuICogdGhvdXNhbmRzIG9mIGNsb3VkIGZ1bmN0aW9ucy4gVGhlIGB0aHJvdHRsZWAgZnVuY3Rpb24gY2FuIGhlbHAgbWFuYWdlIHJlcXVlc3RcbiAqIGZsb3cgd2l0aG91dCByZXNvcnRpbmcgdG8gc2V0dGluZyB1cCBhIHNlcGFyYXRlIHNlcnZpY2UuIFRoaXMgaXMgaW4ga2VlcGluZ1xuICogd2l0aCBmYWFzdC5qcycgemVyby1vcHMgcGhpbG9zb3BoeS5cbiAqXG4gKiBVc2FnZSBpcyBzaW1wbGU6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogYXN5bmMgZnVuY3Rpb24gb3BlcmF0aW9uKCkgeyAuLi4gfVxuICogY29uc3QgdGhyb3R0bGVkT3BlcmF0aW9uID0gdGhyb3R0bGUoeyBjb25jdXJyZW5jeTogMTAsIHJhdGU6IDUgfSwgb3BlcmF0aW9uKTtcbiAqIGZvcihsZXQgaSA9IDA7IGkgPCAxMDA7IGkrKykge1xuICogICAgIC8vIGF0IG1vc3QgMTAgY29uY3VycmVudCBleGVjdXRpb25zIGF0IGEgcmF0ZSBvZiA1IGludm9jYXRpb25zIHBlciBzZWNvbmQuXG4gKiAgICAgdGhyb3R0bGVkT3BlcmF0aW9uKCk7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBOb3RlIHRoYXQgZWFjaCBpbnZvY2F0aW9uIHRvIGB0aHJvdHRsZWAgY3JlYXRlcyBhIHNlcGFyYXRlIGZ1bmN0aW9uIHdpdGggYVxuICogc2VwYXJhdGUgbGltaXRzLiBUaGVyZWZvcmUgaXQgaXMgbGlrZWx5IHRoYXQgeW91IHdhbnQgdG8gdXNlIGB0aHJvdHRsZWAgaW4gYVxuICogZ2xvYmFsIGNvbnRleHQsIG5vdCB3aXRoaW4gYSBkeW5hbWljIGNvbnRleHQ6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogYXN5bmMgZnVuY3Rpb24gb3BlcmF0aW9uKCkgeyAuLi4gfVxuICogZm9yKGxldCBpID0gMDsgaSA8IDEwMDsgaSsrKSB7XG4gKiAgICAgLy8gV1JPTkcgLSBlYWNoIGl0ZXJhdGlvbiBjcmVhdGVzIGEgc2VwYXJhdGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHRoYXQncyBvbmx5IGNhbGxlZCBvbmNlLlxuICogICAgIGNvbnN0IHRocm90dGxlZE9wZXJhdGlvbiA9IHRocm90dGxlKHsgY29uY3VycmVuY3k6IDEwLCByYXRlOiA1IH0sIG9wZXJhdGlvbik7XG4gKiAgICAgdGhyb3R0bGVkT3BlcmF0aW9uKCk7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBBIGJldHRlciB3YXkgdG8gdXNlIHRocm90dGxlIGF2b2lkcyBjcmVhdGluZyBhIG5hbWVkIGBvcGVyYXRpb25gIGZ1bmN0aW9uXG4gKiBhbHRvZ2V0aGVyLCBlbnN1cmluZyBpdCBjYW5ub3QgYmUgYWNjaWRlbnRhbGx5IGNhbGxlZCB3aXRob3V0IHRocm90dGxpbmc6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3Qgb3BlcmF0aW9uID0gdGhyb3R0bGUoeyBjb25jdXJyZW5jeTogMTAsIHJhdGU6IDUgfSwgYXN5bmMgKCkgPT4ge1xuICogICAgIC4uLlxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBUaHJvdHRsZSBzdXBwb3J0cyBmdW5jdGlvbnMgd2l0aCBhcmd1bWVudHMgYXV0b21hdGljYWxseSBpbmZlcnMgdGhlIGNvcnJlY3RcbiAqIHR5cGUgZm9yIHRoZSByZXR1cm5lZCBmdW5jdGlvbjpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBgb3BlcmF0aW9uYCBpbmZlcnJlZCB0byBoYXZlIHR5cGUgKHN0cjogc3RyaW5nKSA9PiBQcm9taXNlPHN0cmluZz5cbiAqIGNvbnN0IG9wZXJhdGlvbiA9IHRocm90dGxlKHsgY29uY3VycmVuY3k6IDEwLCByYXRlOiA1IH0sIGFzeW5jIChzdHI6IHN0cmluZykgPT4ge1xuICogICAgIHJldHVybiBzdHJpbmc7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEluIGFkZGl0aW9uIHRvIGxpbWl0aW5nIGNvbmN1cnJlbmN5IGFuZCBpbnZvY2F0aW9uIHJhdGUsIGB0aHJvdHRsZWAgYWxzb1xuICogc3VwcG9ydHMgcmV0cnlpbmcgZmFpbGVkIGludm9jYXRpb25zLCBtZW1vaXppbmcgY2FsbHMsIGFuZCBvbi1kaXNrIGNhY2hpbmcuXG4gKiBTZWUge0BsaW5rIExpbWl0c30gZm9yIGRldGFpbHMuXG4gKlxuICogQHBhcmFtIGxpbWl0cyAtIHNlZSB7QGxpbmsgTGltaXRzfS5cbiAqIEBwYXJhbSBmbiAtIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS4gSXQgY2FuIHRha2UgYW55IGFyZ3VtZW50cywgYnV0IG11c3RcbiAqIHJldHVybiBhIFByb21pc2UgKHdoaWNoIGluY2x1ZGVzIGBhc3luY2AgZnVuY3Rpb25zKS5cbiAqIEByZXR1cm5zIFJldHVybnMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gd2l0aCB0aGUgc2FtZSBzaWduYXR1cmUgYXMgdGhlIGFyZ3VtZW50XG4gKiBgZm5gLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gdGhyb3R0bGU8QSBleHRlbmRzIGFueVtdLCBSPihcbiAgICBsaW1pdHM6IExpbWl0cyxcbiAgICBmbjogKC4uLmFyZ3M6IEEpID0+IFByb21pc2U8Uj5cbik6ICguLi5hcmdzOiBBKSA9PiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCB7IGNvbmN1cnJlbmN5LCByZXRyeSwgcmF0ZSwgYnVyc3QsIG1lbW9pemUsIGNhY2hlLCBjYW5jZWwgfSA9IGxpbWl0cztcbiAgICBjb25zdCBmdW5uZWwgPSBuZXcgRnVubmVsPFI+KGNvbmN1cnJlbmN5LCByZXRyeSk7XG4gICAgY29uc3QgY2FuY2VsbGF0aW9uUXVldWUgPSBbKCkgPT4gZnVubmVsLmNsZWFyKCldO1xuXG4gICAgbGV0IGNvbmRpdGlvbmVkRnVuYzogKC4uLmFyZ3M6IEEpID0+IFByb21pc2U8Uj47XG5cbiAgICBpZiAocmF0ZSkge1xuICAgICAgICBjb25zdCByYXRlTGltaXRlciA9IG5ldyBSYXRlTGltaXRlcjxSPihyYXRlLCBidXJzdCk7XG4gICAgICAgIGNhbmNlbGxhdGlvblF1ZXVlLnB1c2goKCkgPT4gcmF0ZUxpbWl0ZXIuY2xlYXIoKSk7XG4gICAgICAgIGNvbmRpdGlvbmVkRnVuYyA9ICguLi5hcmdzOiBBKSA9PlxuICAgICAgICAgICAgZnVubmVsLnB1c2goKCkgPT4gcmF0ZUxpbWl0ZXIucHVzaCgoKSA9PiBmbiguLi5hcmdzKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbmRpdGlvbmVkRnVuYyA9ICguLi5hcmdzOiBBKSA9PiBmdW5uZWwucHVzaCgoKSA9PiBmbiguLi5hcmdzKSk7XG4gICAgfVxuXG4gICAgaWYgKGNhY2hlKSB7XG4gICAgICAgIGNvbmRpdGlvbmVkRnVuYyA9IGNhY2hlRm4oY2FjaGUsIGNvbmRpdGlvbmVkRnVuYyk7XG4gICAgfVxuICAgIGlmIChtZW1vaXplKSB7XG4gICAgICAgIGNvbnN0IG1jYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPFI+PigpO1xuICAgICAgICBjYW5jZWxsYXRpb25RdWV1ZS5wdXNoKCgpID0+IG1jYWNoZS5jbGVhcigpKTtcbiAgICAgICAgY29uZGl0aW9uZWRGdW5jID0gbWVtb2l6ZUZuKGNvbmRpdGlvbmVkRnVuYywgbWNhY2hlKTtcbiAgICB9XG4gICAgY2FuY2VsPy50aGVuKCgpID0+IGNhbmNlbGxhdGlvblF1ZXVlLmZvckVhY2goY2xlYW51cEZuID0+IGNsZWFudXBGbigpKSk7XG4gICAgcmV0dXJuIGNvbmRpdGlvbmVkRnVuYztcbn1cblxuZnVuY3Rpb24gaXRlcmF0b3JSZXN1bHQ8VD4odmFsdWU6IFQgfCBQcm9taXNlPFQ+KSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2YWx1ZSkudGhlbih2ID0+ICh7IGRvbmU6IGZhbHNlLCB2YWx1ZTogdiB9IGFzIGNvbnN0KSk7XG59XG5cbmNvbnN0IGRvbmUgPSBQcm9taXNlLnJlc29sdmUoeyBkb25lOiB0cnVlLCB2YWx1ZTogdW5kZWZpbmVkIH0gYXMgY29uc3QpO1xuXG5leHBvcnQgY2xhc3MgQXN5bmNRdWV1ZTxUPiB7XG4gICAgcHJvdGVjdGVkIGRlZmVycmVkOiBBcnJheTxEZWZlcnJlZDxUPj4gPSBbXTtcbiAgICBwcm90ZWN0ZWQgZW5xdWV1ZWQ6IFByb21pc2U8VD5bXSA9IFtdO1xuXG4gICAgZW5xdWV1ZSh2YWx1ZTogVCB8IFByb21pc2U8VD4pIHtcbiAgICAgICAgaWYgKHRoaXMuZGVmZXJyZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgZCA9IHRoaXMuZGVmZXJyZWQuc2hpZnQoKTtcbiAgICAgICAgICAgIGQhLnJlc29sdmUodmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lbnF1ZXVlZC5wdXNoKFByb21pc2UucmVzb2x2ZSh2YWx1ZSkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV4dCgpOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgaWYgKHRoaXMuZW5xdWV1ZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5xdWV1ZWQuc2hpZnQoKSE7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZCA9IG5ldyBEZWZlcnJlZDxUPigpO1xuICAgICAgICB0aGlzLmRlZmVycmVkLnB1c2goZCk7XG4gICAgICAgIHJldHVybiBkLnByb21pc2U7XG4gICAgfVxuXG4gICAgY2xlYXIoKSB7XG4gICAgICAgIHRoaXMuZGVmZXJyZWQgPSBbXTtcbiAgICAgICAgdGhpcy5lbnF1ZXVlZCA9IFtdO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEFzeW5jSXRlcmFibGVRdWV1ZTxUPiBleHRlbmRzIEFzeW5jUXVldWU8SXRlcmF0b3JSZXN1bHQ8VD4+IHtcbiAgICBwdXNoKHZhbHVlOiBUIHwgUHJvbWlzZTxUPikge1xuICAgICAgICBzdXBlci5lbnF1ZXVlKGl0ZXJhdG9yUmVzdWx0KHZhbHVlKSk7XG4gICAgfVxuXG4gICAgZG9uZSgpIHtcbiAgICAgICAgc3VwZXIuZW5xdWV1ZShkb25lKTtcbiAgICB9XG5cbiAgICBbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCkge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBBc3luY09yZGVyZWRRdWV1ZTxUPiB7XG4gICAgcHJvdGVjdGVkIHF1ZXVlID0gbmV3IEFzeW5jUXVldWU8VD4oKTtcbiAgICBwcm90ZWN0ZWQgYXJyaXZlZDogTWFwPG51bWJlciwgUHJvbWlzZTxUPj4gPSBuZXcgTWFwKCk7XG4gICAgcHJvdGVjdGVkIGN1cnJlbnQgPSAwO1xuXG4gICAgcHVzaCh2YWx1ZTogVCB8IFByb21pc2U8VD4sIHNlcXVlbmNlOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5lbnF1ZXVlKFByb21pc2UucmVzb2x2ZSh2YWx1ZSksIHNlcXVlbmNlKTtcbiAgICB9XG5cbiAgICBwdXNoSW1tZWRpYXRlKHZhbHVlOiBUIHwgUHJvbWlzZTxUPikge1xuICAgICAgICB0aGlzLnF1ZXVlLmVucXVldWUodmFsdWUpO1xuICAgIH1cblxuICAgIGVucXVldWUodmFsdWU6IFByb21pc2U8VD4sIHNlcXVlbmNlOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKHNlcXVlbmNlIDwgdGhpcy5jdXJyZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmFycml2ZWQuaGFzKHNlcXVlbmNlKSkge1xuICAgICAgICAgICAgdGhpcy5hcnJpdmVkLnNldChzZXF1ZW5jZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICh0aGlzLmFycml2ZWQuaGFzKHRoaXMuY3VycmVudCkpIHtcbiAgICAgICAgICAgIHRoaXMucXVldWUuZW5xdWV1ZSh0aGlzLmFycml2ZWQuZ2V0KHRoaXMuY3VycmVudCkhKTtcbiAgICAgICAgICAgIHRoaXMuYXJyaXZlZC5kZWxldGUodGhpcy5jdXJyZW50KTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudCsrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV4dCgpOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVldWUubmV4dCgpO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLmFycml2ZWQuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5xdWV1ZS5jbGVhcigpO1xuICAgICAgICB0aGlzLmN1cnJlbnQgPSAwO1xuICAgIH1cbn1cbiJdfQ== |
\ | No newline at end of file |