tryharder 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +468 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.js +17 -0
- package/dist/index.d.ts +269 -0
- package/dist/index.js +1223 -0
- package/dist/shared/chunk-996eswzx.js +105 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.js +3 -0
- package/package.json +71 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1223 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CancellationError,
|
|
3
|
+
ControlError,
|
|
4
|
+
Panic,
|
|
5
|
+
RetryExhaustedError,
|
|
6
|
+
TimeoutError,
|
|
7
|
+
UnhandledException,
|
|
8
|
+
__callDispose,
|
|
9
|
+
__using
|
|
10
|
+
} from "./shared/chunk-996eswzx.js";
|
|
11
|
+
|
|
12
|
+
// src/lib/utils.ts
|
|
13
|
+
function assertUnreachable(value, code) {
|
|
14
|
+
throw new Panic(code, { message: `Unreachable case: ${String(value)}` });
|
|
15
|
+
}
|
|
16
|
+
function invariant(condition, error) {
|
|
17
|
+
if (!condition) {
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function sleep(ms) {
|
|
22
|
+
if (ms <= 0) {
|
|
23
|
+
return Promise.resolve();
|
|
24
|
+
}
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
setTimeout(resolve, ms);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function checkIsPromiseLike(value) {
|
|
30
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
|
|
31
|
+
}
|
|
32
|
+
async function resolveWithAbort(signal, promise, createAbortResult) {
|
|
33
|
+
let __stack = [];
|
|
34
|
+
try {
|
|
35
|
+
const disposer = __using(__stack, new DisposableStack, 0);
|
|
36
|
+
const abortPromise = new Promise((resolve) => {
|
|
37
|
+
const onAbort = () => {
|
|
38
|
+
resolve(createAbortResult());
|
|
39
|
+
};
|
|
40
|
+
if (signal.aborted) {
|
|
41
|
+
onAbort();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
45
|
+
disposer.defer(() => {
|
|
46
|
+
signal.removeEventListener("abort", onAbort);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
return await Promise.race([Promise.resolve(promise), abortPromise]);
|
|
50
|
+
} catch (_catch) {
|
|
51
|
+
var _err = _catch, _hasErr = 1;
|
|
52
|
+
} finally {
|
|
53
|
+
__callDispose(__stack, _err, _hasErr);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/lib/modifiers/retry.ts
|
|
58
|
+
function retryOptions(policy) {
|
|
59
|
+
const limit = typeof policy === "number" ? policy : policy.limit;
|
|
60
|
+
invariant(Number.isFinite(limit), new Panic("RETRY_INVALID_LIMIT"));
|
|
61
|
+
invariant(limit >= 0, new Panic("RETRY_INVALID_LIMIT"));
|
|
62
|
+
if (typeof policy === "number") {
|
|
63
|
+
return {
|
|
64
|
+
backoff: "constant",
|
|
65
|
+
delayMs: 0,
|
|
66
|
+
limit: policy
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const base = {
|
|
70
|
+
delayMs: policy.delayMs ?? 0,
|
|
71
|
+
jitter: policy.jitter,
|
|
72
|
+
limit: policy.limit,
|
|
73
|
+
shouldRetry: policy.shouldRetry
|
|
74
|
+
};
|
|
75
|
+
switch (policy.backoff) {
|
|
76
|
+
case "constant":
|
|
77
|
+
case "linear":
|
|
78
|
+
return { ...base, backoff: policy.backoff };
|
|
79
|
+
case "exponential":
|
|
80
|
+
return { ...base, backoff: policy.backoff, maxDelayMs: policy.maxDelayMs };
|
|
81
|
+
default:
|
|
82
|
+
return assertUnreachable(policy, "UNREACHABLE_RETRY_POLICY_BACKOFF");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function calculateRetryDelay(attempt, config) {
|
|
86
|
+
const policy = config.retry;
|
|
87
|
+
if (!policy) {
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
const baseDelay = policy.delayMs ?? 0;
|
|
91
|
+
let delay = 0;
|
|
92
|
+
switch (policy.backoff) {
|
|
93
|
+
case "constant":
|
|
94
|
+
delay = baseDelay;
|
|
95
|
+
break;
|
|
96
|
+
case "linear":
|
|
97
|
+
delay = baseDelay * attempt;
|
|
98
|
+
break;
|
|
99
|
+
case "exponential":
|
|
100
|
+
delay = baseDelay * 2 ** (attempt - 1);
|
|
101
|
+
if (policy.maxDelayMs !== undefined) {
|
|
102
|
+
delay = Math.min(delay, policy.maxDelayMs);
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
if (!policy.jitter || delay <= 0) {
|
|
107
|
+
return delay;
|
|
108
|
+
}
|
|
109
|
+
return Math.floor(Math.random() * delay);
|
|
110
|
+
}
|
|
111
|
+
function checkShouldAttemptRetry(error, ctx, config) {
|
|
112
|
+
const policy = config.retry;
|
|
113
|
+
if (!policy) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (ctx.retry.attempt >= policy.limit) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (!policy.shouldRetry) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return policy.shouldRetry(error, ctx);
|
|
123
|
+
}
|
|
124
|
+
function checkIsRetryExhausted(attempt, config) {
|
|
125
|
+
return config.retry !== undefined && attempt >= config.retry.limit;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/lib/modifiers/signal.ts
|
|
129
|
+
class SignalController {
|
|
130
|
+
signal;
|
|
131
|
+
constructor(signals = []) {
|
|
132
|
+
if (signals.length > 0) {
|
|
133
|
+
this.signal = AbortSignal.any([...signals]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
checkDidCancel(cause) {
|
|
137
|
+
if (!this.signal?.aborted) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (this.signal.reason instanceof TimeoutError) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
return new CancellationError(undefined, { cause: cause ?? this.signal.reason });
|
|
144
|
+
}
|
|
145
|
+
async race(promise, cause) {
|
|
146
|
+
const cancelled = this.checkDidCancel(cause);
|
|
147
|
+
if (cancelled) {
|
|
148
|
+
return cancelled;
|
|
149
|
+
}
|
|
150
|
+
if (!this.signal) {
|
|
151
|
+
return promise;
|
|
152
|
+
}
|
|
153
|
+
return await resolveWithAbort(this.signal, promise, () => new CancellationError(undefined, { cause: cause ?? this.signal?.reason }));
|
|
154
|
+
}
|
|
155
|
+
[Symbol.dispose]() {
|
|
156
|
+
this.signal;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/lib/modifiers/timeout.ts
|
|
161
|
+
class TimeoutController {
|
|
162
|
+
signal;
|
|
163
|
+
#controller;
|
|
164
|
+
#startedAt = Date.now();
|
|
165
|
+
#timeoutMs;
|
|
166
|
+
#timeoutId;
|
|
167
|
+
constructor(timeoutMs) {
|
|
168
|
+
this.#timeoutMs = timeoutMs ?? -1;
|
|
169
|
+
if (timeoutMs === undefined) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
invariant(Number.isFinite(timeoutMs), new Panic("TIMEOUT_INVALID_MS"));
|
|
173
|
+
invariant(timeoutMs >= 0, new Panic("TIMEOUT_INVALID_MS"));
|
|
174
|
+
this.#controller = new AbortController;
|
|
175
|
+
this.signal = this.#controller.signal;
|
|
176
|
+
if (this.#timeoutMs <= 0) {
|
|
177
|
+
this.#abort();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this.#timeoutId = setTimeout(() => {
|
|
181
|
+
this.#abort();
|
|
182
|
+
}, this.#timeoutMs);
|
|
183
|
+
}
|
|
184
|
+
#abort(cause) {
|
|
185
|
+
const timeoutError = new TimeoutError(`Execution exceeded timeout of ${this.#timeoutMs}ms`, {
|
|
186
|
+
cause
|
|
187
|
+
});
|
|
188
|
+
if (!this.signal?.aborted) {
|
|
189
|
+
this.#controller?.abort(timeoutError);
|
|
190
|
+
}
|
|
191
|
+
return timeoutError;
|
|
192
|
+
}
|
|
193
|
+
get #remaining() {
|
|
194
|
+
const elapsed = Date.now() - this.#startedAt;
|
|
195
|
+
return this.#timeoutMs - elapsed;
|
|
196
|
+
}
|
|
197
|
+
checkDidTimeout(cause) {
|
|
198
|
+
if (!this.signal) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (this.signal.aborted) {
|
|
202
|
+
const reason = this.signal.reason;
|
|
203
|
+
if (reason instanceof TimeoutError) {
|
|
204
|
+
return reason;
|
|
205
|
+
}
|
|
206
|
+
return new TimeoutError(`Execution exceeded timeout of ${this.#timeoutMs}ms`, {
|
|
207
|
+
cause: cause ?? reason
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
if (this.#remaining > 0) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
return this.#abort(cause);
|
|
214
|
+
}
|
|
215
|
+
async race(promise, cause) {
|
|
216
|
+
if (!this.signal) {
|
|
217
|
+
return promise;
|
|
218
|
+
}
|
|
219
|
+
if (this.#remaining <= 0) {
|
|
220
|
+
return this.#abort(cause);
|
|
221
|
+
}
|
|
222
|
+
const timedOut = this.checkDidTimeout(cause);
|
|
223
|
+
if (timedOut) {
|
|
224
|
+
return timedOut;
|
|
225
|
+
}
|
|
226
|
+
return await resolveWithAbort(this.signal, promise, () => this.checkDidTimeout(cause) ?? new TimeoutError(`Execution exceeded timeout of ${this.#timeoutMs}ms`, { cause }));
|
|
227
|
+
}
|
|
228
|
+
[Symbol.dispose]() {
|
|
229
|
+
if (this.#timeoutId !== undefined) {
|
|
230
|
+
clearTimeout(this.#timeoutId);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/lib/executors/base.ts
|
|
236
|
+
class RetryDirective {
|
|
237
|
+
decision;
|
|
238
|
+
constructor(decision) {
|
|
239
|
+
this.decision = decision;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
class BaseExecution {
|
|
244
|
+
config;
|
|
245
|
+
ctx;
|
|
246
|
+
executionSignal;
|
|
247
|
+
#wrapCtx;
|
|
248
|
+
#signalController;
|
|
249
|
+
#timeoutController;
|
|
250
|
+
constructor(config, options = {}) {
|
|
251
|
+
this.config = config;
|
|
252
|
+
this.#timeoutController = BaseExecution.createTimeoutController(config.timeout);
|
|
253
|
+
this.#signalController = BaseExecution.createSignalController(config.signals, this.#timeoutController?.signal);
|
|
254
|
+
this.executionSignal = this.#signalController?.signal;
|
|
255
|
+
this.ctx = BaseExecution.createContext(config, this.executionSignal, options.retryLimit);
|
|
256
|
+
this.#wrapCtx = BaseExecution.createWrapContext(this.ctx);
|
|
257
|
+
}
|
|
258
|
+
execute() {
|
|
259
|
+
const wraps = this.config.wraps;
|
|
260
|
+
if (!wraps || wraps.length === 0) {
|
|
261
|
+
return this.executeCore();
|
|
262
|
+
}
|
|
263
|
+
let next = () => this.executeCore();
|
|
264
|
+
for (const wrap of wraps.toReversed()) {
|
|
265
|
+
const previous = next;
|
|
266
|
+
next = () => wrap(this.#wrapCtx, previous);
|
|
267
|
+
}
|
|
268
|
+
return next();
|
|
269
|
+
}
|
|
270
|
+
[Symbol.dispose]() {
|
|
271
|
+
let __stack = [];
|
|
272
|
+
try {
|
|
273
|
+
const disposer = __using(__stack, new DisposableStack, 0);
|
|
274
|
+
if (this.#timeoutController) {
|
|
275
|
+
disposer.use(this.#timeoutController);
|
|
276
|
+
}
|
|
277
|
+
if (this.#signalController) {
|
|
278
|
+
disposer.use(this.#signalController);
|
|
279
|
+
}
|
|
280
|
+
} catch (_catch) {
|
|
281
|
+
var _err = _catch, _hasErr = 1;
|
|
282
|
+
} finally {
|
|
283
|
+
__callDispose(__stack, _err, _hasErr);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
static createContext(config, signal, retryLimit) {
|
|
287
|
+
return {
|
|
288
|
+
retry: {
|
|
289
|
+
attempt: 1,
|
|
290
|
+
limit: retryLimit ?? config.retry?.limit ?? 1
|
|
291
|
+
},
|
|
292
|
+
signal
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
static createTimeoutController(timeoutMs) {
|
|
296
|
+
return timeoutMs === undefined ? undefined : new TimeoutController(timeoutMs);
|
|
297
|
+
}
|
|
298
|
+
static createSignalController(signals, timeoutSignal) {
|
|
299
|
+
const composedSignals = [...signals ?? [], timeoutSignal].filter((value) => value !== undefined);
|
|
300
|
+
return composedSignals.length > 0 ? new SignalController(composedSignals) : undefined;
|
|
301
|
+
}
|
|
302
|
+
static createWrapContext(ctx) {
|
|
303
|
+
const retry = new Proxy(ctx.retry, {
|
|
304
|
+
defineProperty: () => false,
|
|
305
|
+
deleteProperty: () => false,
|
|
306
|
+
getOwnPropertyDescriptor(target, property) {
|
|
307
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, property);
|
|
308
|
+
if (!descriptor) {
|
|
309
|
+
return descriptor;
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
...descriptor,
|
|
313
|
+
writable: false
|
|
314
|
+
};
|
|
315
|
+
},
|
|
316
|
+
set: () => false
|
|
317
|
+
});
|
|
318
|
+
return new Proxy(ctx, {
|
|
319
|
+
defineProperty: () => false,
|
|
320
|
+
deleteProperty: () => false,
|
|
321
|
+
get(target, property, receiver) {
|
|
322
|
+
if (property === "retry") {
|
|
323
|
+
return retry;
|
|
324
|
+
}
|
|
325
|
+
return Reflect.get(target, property, receiver);
|
|
326
|
+
},
|
|
327
|
+
getOwnPropertyDescriptor(target, property) {
|
|
328
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, property);
|
|
329
|
+
if (!descriptor) {
|
|
330
|
+
return descriptor;
|
|
331
|
+
}
|
|
332
|
+
if (property === "retry") {
|
|
333
|
+
return {
|
|
334
|
+
...descriptor,
|
|
335
|
+
value: retry,
|
|
336
|
+
writable: false
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
...descriptor,
|
|
341
|
+
writable: false
|
|
342
|
+
};
|
|
343
|
+
},
|
|
344
|
+
set: () => false
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
checkDidCancel(cause) {
|
|
348
|
+
return this.#signalController?.checkDidCancel(cause);
|
|
349
|
+
}
|
|
350
|
+
raceWithCancellation(promise, cause) {
|
|
351
|
+
return this.#signalController ? this.#signalController.race(promise, cause) : promise;
|
|
352
|
+
}
|
|
353
|
+
checkDidControlFail(cause) {
|
|
354
|
+
return this.checkDidCancel(cause) ?? this.#timeoutController?.checkDidTimeout(cause);
|
|
355
|
+
}
|
|
356
|
+
resolveSyncSuccess(value) {
|
|
357
|
+
return this.checkDidControlFail() ?? value;
|
|
358
|
+
}
|
|
359
|
+
race(promise, cause) {
|
|
360
|
+
const timeoutController = this.#timeoutController;
|
|
361
|
+
if (!timeoutController) {
|
|
362
|
+
return this.raceWithCancellation(promise, cause);
|
|
363
|
+
}
|
|
364
|
+
return Promise.resolve(timeoutController.race(this.raceWithCancellation(promise, cause), cause)).then((raced) => {
|
|
365
|
+
if (raced instanceof TimeoutError) {
|
|
366
|
+
return this.checkDidCancel(cause) ?? raced;
|
|
367
|
+
}
|
|
368
|
+
return raced;
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
async waitForRetryDelay(delay) {
|
|
372
|
+
if (delay <= 0) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const sleepResult = await this.race(sleep(delay));
|
|
376
|
+
if (sleepResult instanceof CancellationError || sleepResult instanceof TimeoutError) {
|
|
377
|
+
return sleepResult;
|
|
378
|
+
}
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
shouldAttemptRetry(error) {
|
|
382
|
+
return checkShouldAttemptRetry(error, this.ctx, this.config);
|
|
383
|
+
}
|
|
384
|
+
retryDelayForCurrentAttempt() {
|
|
385
|
+
return calculateRetryDelay(this.ctx.retry.attempt, this.config);
|
|
386
|
+
}
|
|
387
|
+
checkIsRetryExhaustedCurrentAttempt() {
|
|
388
|
+
return checkIsRetryExhausted(this.ctx.retry.attempt, this.config);
|
|
389
|
+
}
|
|
390
|
+
buildRetryDecision(error) {
|
|
391
|
+
const shouldAttemptRetry = this.shouldAttemptRetry(error);
|
|
392
|
+
return {
|
|
393
|
+
delay: shouldAttemptRetry ? this.retryDelayForCurrentAttempt() : 0,
|
|
394
|
+
isRetryExhausted: this.checkIsRetryExhaustedCurrentAttempt(),
|
|
395
|
+
shouldAttemptRetry
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/lib/executors/shared.ts
|
|
401
|
+
class OrchestrationExecution extends BaseExecution {
|
|
402
|
+
constructor(config) {
|
|
403
|
+
const unsupportedPolicies = [
|
|
404
|
+
config.retry === undefined ? undefined : "retry",
|
|
405
|
+
config.timeout === undefined ? undefined : "timeout"
|
|
406
|
+
].filter((value) => value !== undefined);
|
|
407
|
+
invariant(unsupportedPolicies.length === 0, new Panic("ORCHESTRATION_UNSUPPORTED_POLICY", {
|
|
408
|
+
message: `Orchestration does not support ${unsupportedPolicies.join(" or ")} policies.`
|
|
409
|
+
}));
|
|
410
|
+
super({
|
|
411
|
+
signals: config.signals,
|
|
412
|
+
wraps: config.wraps
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
async executeCore() {
|
|
416
|
+
const controlBeforeExecution = this.checkDidControlFail();
|
|
417
|
+
if (controlBeforeExecution) {
|
|
418
|
+
throw controlBeforeExecution;
|
|
419
|
+
}
|
|
420
|
+
return await this.executeTasks();
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
class TaskGraphExecutionBase {
|
|
425
|
+
tasks;
|
|
426
|
+
taskNames;
|
|
427
|
+
results;
|
|
428
|
+
errors;
|
|
429
|
+
resolvers;
|
|
430
|
+
internalController = new AbortController;
|
|
431
|
+
taskSignal;
|
|
432
|
+
disposer = new AsyncDisposableStack;
|
|
433
|
+
firstRejection;
|
|
434
|
+
constructor(signal, tasks) {
|
|
435
|
+
this.tasks = tasks;
|
|
436
|
+
this.taskNames = Object.keys(tasks);
|
|
437
|
+
this.results = new Map;
|
|
438
|
+
this.errors = new Map;
|
|
439
|
+
this.resolvers = new Map;
|
|
440
|
+
this.taskSignal = signal ? AbortSignal.any([signal, this.internalController.signal]) : this.internalController.signal;
|
|
441
|
+
}
|
|
442
|
+
async[Symbol.asyncDispose]() {
|
|
443
|
+
await this.disposer.disposeAsync();
|
|
444
|
+
}
|
|
445
|
+
getTaskHandler(taskName) {
|
|
446
|
+
const taskFn = this.tasks[taskName];
|
|
447
|
+
invariant(typeof taskFn === "function", new Panic("TASK_INVALID_HANDLER", {
|
|
448
|
+
message: `Task "${String(taskName)}" is not a function`
|
|
449
|
+
}));
|
|
450
|
+
return taskFn;
|
|
451
|
+
}
|
|
452
|
+
createResultProxy(requesterTaskName) {
|
|
453
|
+
return new Proxy({}, {
|
|
454
|
+
get: (_, referencedTaskName) => this.waitForResult(referencedTaskName, requesterTaskName)
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
waitForResult(taskName, requesterTaskName) {
|
|
458
|
+
if (requesterTaskName === taskName) {
|
|
459
|
+
return Promise.reject(new Panic("TASK_SELF_REFERENCE", {
|
|
460
|
+
message: `Task "${String(taskName)}" cannot await its own result`
|
|
461
|
+
}));
|
|
462
|
+
}
|
|
463
|
+
if (!Object.hasOwn(this.tasks, taskName)) {
|
|
464
|
+
return Promise.reject(new Panic("TASK_UNKNOWN_REFERENCE", {
|
|
465
|
+
message: `Unknown task "${String(taskName)}"`
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
if (this.results.has(taskName)) {
|
|
469
|
+
return Promise.resolve(this.results.get(taskName));
|
|
470
|
+
}
|
|
471
|
+
if (this.errors.has(taskName)) {
|
|
472
|
+
const storedError = this.mapStoredError(this.errors.get(taskName));
|
|
473
|
+
return Promise.reject(storedError);
|
|
474
|
+
}
|
|
475
|
+
return new Promise((resolve, reject) => {
|
|
476
|
+
const queue = this.resolvers.get(taskName);
|
|
477
|
+
if (queue) {
|
|
478
|
+
queue.push([resolve, reject]);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
this.resolvers.set(taskName, [[resolve, reject]]);
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
storeResult(taskName, value) {
|
|
485
|
+
this.results.set(taskName, value);
|
|
486
|
+
this.resolveWaiters(taskName, value);
|
|
487
|
+
}
|
|
488
|
+
storeError(taskName, error) {
|
|
489
|
+
const mappedError = this.mapStoredError(error);
|
|
490
|
+
this.errors.set(taskName, mappedError);
|
|
491
|
+
this.rejectWaiters(taskName, mappedError);
|
|
492
|
+
}
|
|
493
|
+
resolveWaiters(taskName, value) {
|
|
494
|
+
const fulfilled = this.resolvers.get(taskName);
|
|
495
|
+
if (fulfilled) {
|
|
496
|
+
for (const [resolve] of fulfilled) {
|
|
497
|
+
resolve(value);
|
|
498
|
+
}
|
|
499
|
+
this.resolvers.delete(taskName);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
rejectWaiters(taskName, error) {
|
|
503
|
+
const rejected = this.resolvers.get(taskName);
|
|
504
|
+
if (rejected) {
|
|
505
|
+
for (const [, reject] of rejected) {
|
|
506
|
+
reject(error);
|
|
507
|
+
}
|
|
508
|
+
this.resolvers.delete(taskName);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
abortInternal(error) {
|
|
512
|
+
if (!this.internalController.signal.aborted) {
|
|
513
|
+
this.internalController.abort(error);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
onTaskResult(_taskName, _value) {
|
|
517
|
+
this.tasks;
|
|
518
|
+
}
|
|
519
|
+
onTaskError(_taskName, _error) {
|
|
520
|
+
this.tasks;
|
|
521
|
+
}
|
|
522
|
+
mapStoredError(error) {
|
|
523
|
+
this.tasks;
|
|
524
|
+
return error instanceof Error ? error : new UnhandledException(undefined, { cause: error });
|
|
525
|
+
}
|
|
526
|
+
shouldAbortOnTaskError(_error) {
|
|
527
|
+
this.tasks;
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
shouldRethrowTaskError(_error) {
|
|
531
|
+
this.tasks;
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
setFirstRejection(error) {
|
|
535
|
+
this.firstRejection ??= error;
|
|
536
|
+
}
|
|
537
|
+
async runTask(taskName) {
|
|
538
|
+
try {
|
|
539
|
+
const taskFn = this.getTaskHandler(taskName);
|
|
540
|
+
const resultProxy = this.createResultProxy(taskName);
|
|
541
|
+
const context = this.createTaskContext(resultProxy);
|
|
542
|
+
const result = await taskFn.call(context);
|
|
543
|
+
this.storeResult(taskName, result);
|
|
544
|
+
this.onTaskResult(taskName, result);
|
|
545
|
+
} catch (error) {
|
|
546
|
+
this.setFirstRejection(error);
|
|
547
|
+
this.storeError(taskName, error);
|
|
548
|
+
this.onTaskError(taskName, error);
|
|
549
|
+
if (this.shouldAbortOnTaskError(error)) {
|
|
550
|
+
this.abortInternal(error);
|
|
551
|
+
}
|
|
552
|
+
if (this.shouldRethrowTaskError(error)) {
|
|
553
|
+
throw error;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
class TaskExecution extends TaskGraphExecutionBase {
|
|
560
|
+
#mode;
|
|
561
|
+
#returnValue = {};
|
|
562
|
+
#failedTask;
|
|
563
|
+
settledPromise;
|
|
564
|
+
constructor(signal, tasks, mode) {
|
|
565
|
+
super(signal, tasks);
|
|
566
|
+
this.#mode = mode;
|
|
567
|
+
}
|
|
568
|
+
get failedTask() {
|
|
569
|
+
return this.#failedTask;
|
|
570
|
+
}
|
|
571
|
+
get signal() {
|
|
572
|
+
return this.taskSignal;
|
|
573
|
+
}
|
|
574
|
+
get returnValue() {
|
|
575
|
+
return this.#returnValue;
|
|
576
|
+
}
|
|
577
|
+
async execute() {
|
|
578
|
+
const promises = this.taskNames.map(async (name) => this.runTask(name));
|
|
579
|
+
this.settledPromise = Promise.allSettled(promises);
|
|
580
|
+
if (this.#mode === "settled") {
|
|
581
|
+
await this.settledPromise;
|
|
582
|
+
return this.#returnValue;
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
await Promise.all(promises);
|
|
586
|
+
} catch {
|
|
587
|
+
throw this.mapStoredError(this.firstRejection);
|
|
588
|
+
}
|
|
589
|
+
return this.#returnValue;
|
|
590
|
+
}
|
|
591
|
+
async waitForTasksToSettle() {
|
|
592
|
+
await this.settledPromise;
|
|
593
|
+
}
|
|
594
|
+
createTaskContext(resultProxy) {
|
|
595
|
+
return {
|
|
596
|
+
$disposer: this.disposer,
|
|
597
|
+
$result: resultProxy,
|
|
598
|
+
$signal: this.taskSignal
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
onTaskResult(taskName, value) {
|
|
602
|
+
if (this.#mode === "settled") {
|
|
603
|
+
this.#returnValue[taskName] = { status: "fulfilled", value };
|
|
604
|
+
} else {
|
|
605
|
+
this.#returnValue[taskName] = value;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
onTaskError(taskName, error) {
|
|
609
|
+
this.#failedTask ??= taskName;
|
|
610
|
+
if (this.#mode === "settled") {
|
|
611
|
+
this.#returnValue[taskName] = { reason: error, status: "rejected" };
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
shouldAbortOnTaskError() {
|
|
615
|
+
return this.#mode === "fail-fast";
|
|
616
|
+
}
|
|
617
|
+
shouldRethrowTaskError() {
|
|
618
|
+
return this.#mode === "fail-fast";
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// src/lib/executors/all.ts
|
|
623
|
+
class AllExecution extends OrchestrationExecution {
|
|
624
|
+
#tasks;
|
|
625
|
+
#options;
|
|
626
|
+
constructor(config, tasks, options) {
|
|
627
|
+
super(config);
|
|
628
|
+
this.#tasks = tasks;
|
|
629
|
+
this.#options = options;
|
|
630
|
+
}
|
|
631
|
+
async executeTasks() {
|
|
632
|
+
let __stack = [];
|
|
633
|
+
try {
|
|
634
|
+
const execution = __using(__stack, new TaskExecution(this.executionSignal, this.#tasks, "fail-fast"), 1);
|
|
635
|
+
let result;
|
|
636
|
+
let threw = false;
|
|
637
|
+
let thrownError;
|
|
638
|
+
try {
|
|
639
|
+
result = await this.raceWithCancellation(execution.execute());
|
|
640
|
+
} catch (error) {
|
|
641
|
+
const controlAfterFailure = this.checkDidControlFail(error);
|
|
642
|
+
const catchFn = this.#options?.catch;
|
|
643
|
+
if (controlAfterFailure) {
|
|
644
|
+
threw = true;
|
|
645
|
+
thrownError = controlAfterFailure;
|
|
646
|
+
} else if (catchFn) {
|
|
647
|
+
const context = {
|
|
648
|
+
failedTask: execution.failedTask,
|
|
649
|
+
partial: execution.returnValue,
|
|
650
|
+
signal: execution.signal
|
|
651
|
+
};
|
|
652
|
+
try {
|
|
653
|
+
const mapped = catchFn(error, context);
|
|
654
|
+
if (checkIsPromiseLike(mapped)) {
|
|
655
|
+
try {
|
|
656
|
+
result = await this.raceWithCancellation(Promise.resolve(mapped).catch((catchError) => {
|
|
657
|
+
if (catchError instanceof CancellationError) {
|
|
658
|
+
throw catchError;
|
|
659
|
+
}
|
|
660
|
+
throw new Panic("ALL_CATCH_HANDLER_REJECT", { cause: catchError });
|
|
661
|
+
}), error);
|
|
662
|
+
} catch (mappedError) {
|
|
663
|
+
threw = true;
|
|
664
|
+
thrownError = mappedError;
|
|
665
|
+
}
|
|
666
|
+
} else {
|
|
667
|
+
result = mapped;
|
|
668
|
+
}
|
|
669
|
+
} catch (catchError) {
|
|
670
|
+
threw = true;
|
|
671
|
+
thrownError = new Panic("ALL_CATCH_HANDLER_THROW", { cause: catchError });
|
|
672
|
+
}
|
|
673
|
+
} else {
|
|
674
|
+
threw = true;
|
|
675
|
+
thrownError = error;
|
|
676
|
+
}
|
|
677
|
+
} finally {
|
|
678
|
+
await execution.waitForTasksToSettle();
|
|
679
|
+
}
|
|
680
|
+
const cancellation = this.checkDidCancel(thrownError);
|
|
681
|
+
if (cancellation) {
|
|
682
|
+
throw cancellation;
|
|
683
|
+
}
|
|
684
|
+
if (threw) {
|
|
685
|
+
throw thrownError;
|
|
686
|
+
}
|
|
687
|
+
return result;
|
|
688
|
+
} catch (_catch) {
|
|
689
|
+
var _err = _catch, _hasErr = 1;
|
|
690
|
+
} finally {
|
|
691
|
+
var _promise = __callDispose(__stack, _err, _hasErr);
|
|
692
|
+
_promise && await _promise;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
async function executeAll(config, tasks, options) {
|
|
697
|
+
let __stack = [];
|
|
698
|
+
try {
|
|
699
|
+
const execution = __using(__stack, new AllExecution(config, tasks, options), 0);
|
|
700
|
+
return await execution.execute();
|
|
701
|
+
} catch (_catch) {
|
|
702
|
+
var _err = _catch, _hasErr = 1;
|
|
703
|
+
} finally {
|
|
704
|
+
__callDispose(__stack, _err, _hasErr);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/lib/executors/all-settled.ts
|
|
709
|
+
class AllSettledExecution extends OrchestrationExecution {
|
|
710
|
+
#tasks;
|
|
711
|
+
constructor(config, tasks) {
|
|
712
|
+
super(config);
|
|
713
|
+
this.#tasks = tasks;
|
|
714
|
+
}
|
|
715
|
+
async executeTasks() {
|
|
716
|
+
let __stack = [];
|
|
717
|
+
try {
|
|
718
|
+
const execution = __using(__stack, new TaskExecution(this.executionSignal, this.#tasks, "settled"), 1);
|
|
719
|
+
const result = await this.raceWithCancellation(execution.execute());
|
|
720
|
+
const cancellation = this.checkDidCancel();
|
|
721
|
+
if (cancellation) {
|
|
722
|
+
throw cancellation;
|
|
723
|
+
}
|
|
724
|
+
return result;
|
|
725
|
+
} catch (_catch) {
|
|
726
|
+
var _err = _catch, _hasErr = 1;
|
|
727
|
+
} finally {
|
|
728
|
+
var _promise = __callDispose(__stack, _err, _hasErr);
|
|
729
|
+
_promise && await _promise;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
async function executeAllSettled(config, tasks) {
|
|
734
|
+
let __stack = [];
|
|
735
|
+
try {
|
|
736
|
+
const execution = __using(__stack, new AllSettledExecution(config, tasks), 0);
|
|
737
|
+
return await execution.execute();
|
|
738
|
+
} catch (_catch) {
|
|
739
|
+
var _err = _catch, _hasErr = 1;
|
|
740
|
+
} finally {
|
|
741
|
+
__callDispose(__stack, _err, _hasErr);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// src/lib/executors/flow.ts
|
|
746
|
+
class FlowExitSignal extends Error {
|
|
747
|
+
value;
|
|
748
|
+
constructor(value) {
|
|
749
|
+
super("Flow exited");
|
|
750
|
+
this.name = "FlowExitSignal";
|
|
751
|
+
this.value = value;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
class FlowExecution extends TaskGraphExecutionBase {
|
|
756
|
+
#firstRejectionWaiters = [];
|
|
757
|
+
#settledPromise;
|
|
758
|
+
async execute() {
|
|
759
|
+
const promises = this.taskNames.map(async (name) => this.runTask(name));
|
|
760
|
+
this.#settledPromise = Promise.allSettled(promises);
|
|
761
|
+
await Promise.race([this.#settledPromise, this.waitForFirstRejection()]);
|
|
762
|
+
if (this.firstRejection !== undefined) {
|
|
763
|
+
if (this.firstRejection instanceof FlowExitSignal) {
|
|
764
|
+
return this.firstRejection.value;
|
|
765
|
+
}
|
|
766
|
+
throw this.firstRejection;
|
|
767
|
+
}
|
|
768
|
+
throw new Panic("FLOW_NO_EXIT");
|
|
769
|
+
}
|
|
770
|
+
async waitForTasksToSettle() {
|
|
771
|
+
await this.#settledPromise;
|
|
772
|
+
}
|
|
773
|
+
setFirstRejection(error) {
|
|
774
|
+
const hadFirstRejection = this.firstRejection !== undefined;
|
|
775
|
+
super.setFirstRejection(error);
|
|
776
|
+
if (hadFirstRejection || this.firstRejection === undefined) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
for (const resolve of this.#firstRejectionWaiters) {
|
|
780
|
+
resolve();
|
|
781
|
+
}
|
|
782
|
+
this.#firstRejectionWaiters = [];
|
|
783
|
+
}
|
|
784
|
+
createTaskContext(resultProxy) {
|
|
785
|
+
return {
|
|
786
|
+
$disposer: this.disposer,
|
|
787
|
+
$exit: (value) => {
|
|
788
|
+
throw new FlowExitSignal(value);
|
|
789
|
+
},
|
|
790
|
+
$result: resultProxy,
|
|
791
|
+
$signal: this.taskSignal
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
mapStoredError(error) {
|
|
795
|
+
if (error instanceof FlowExitSignal) {
|
|
796
|
+
return error;
|
|
797
|
+
}
|
|
798
|
+
return super.mapStoredError(error);
|
|
799
|
+
}
|
|
800
|
+
shouldAbortOnTaskError() {
|
|
801
|
+
this.taskNames;
|
|
802
|
+
return true;
|
|
803
|
+
}
|
|
804
|
+
waitForFirstRejection() {
|
|
805
|
+
if (this.firstRejection !== undefined) {
|
|
806
|
+
return Promise.resolve();
|
|
807
|
+
}
|
|
808
|
+
return new Promise((resolve) => {
|
|
809
|
+
this.#firstRejectionWaiters.push(resolve);
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
class FlowRunnerExecution extends OrchestrationExecution {
|
|
815
|
+
#tasks;
|
|
816
|
+
constructor(config, tasks) {
|
|
817
|
+
super(config);
|
|
818
|
+
this.#tasks = tasks;
|
|
819
|
+
}
|
|
820
|
+
async executeTasks() {
|
|
821
|
+
let __stack = [];
|
|
822
|
+
try {
|
|
823
|
+
const execution = __using(__stack, new FlowExecution(this.executionSignal, this.#tasks), 1);
|
|
824
|
+
let result;
|
|
825
|
+
let threw = false;
|
|
826
|
+
let thrownError;
|
|
827
|
+
try {
|
|
828
|
+
result = await this.raceWithCancellation(execution.execute());
|
|
829
|
+
} catch (error) {
|
|
830
|
+
threw = true;
|
|
831
|
+
thrownError = error;
|
|
832
|
+
} finally {
|
|
833
|
+
await execution.waitForTasksToSettle();
|
|
834
|
+
}
|
|
835
|
+
const cancellation = this.checkDidCancel(thrownError);
|
|
836
|
+
if (cancellation) {
|
|
837
|
+
throw cancellation;
|
|
838
|
+
}
|
|
839
|
+
if (threw) {
|
|
840
|
+
throw thrownError;
|
|
841
|
+
}
|
|
842
|
+
return result;
|
|
843
|
+
} catch (_catch) {
|
|
844
|
+
var _err = _catch, _hasErr = 1;
|
|
845
|
+
} finally {
|
|
846
|
+
var _promise = __callDispose(__stack, _err, _hasErr);
|
|
847
|
+
_promise && await _promise;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
async function executeFlow(config, tasks) {
|
|
852
|
+
let __stack = [];
|
|
853
|
+
try {
|
|
854
|
+
const execution = __using(__stack, new FlowRunnerExecution(config, tasks), 0);
|
|
855
|
+
return await execution.execute();
|
|
856
|
+
} catch (_catch) {
|
|
857
|
+
var _err = _catch, _hasErr = 1;
|
|
858
|
+
} finally {
|
|
859
|
+
__callDispose(__stack, _err, _hasErr);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/lib/executors/run.ts
|
|
864
|
+
class RunExecution extends BaseExecution {
|
|
865
|
+
#catchFn;
|
|
866
|
+
#tryFn;
|
|
867
|
+
constructor(config, input) {
|
|
868
|
+
super(config);
|
|
869
|
+
this.#catchFn = typeof input === "function" ? undefined : input.catch;
|
|
870
|
+
this.#tryFn = typeof input === "function" ? input : input.try;
|
|
871
|
+
}
|
|
872
|
+
executeCore() {
|
|
873
|
+
return this.#runAttemptLoop(1);
|
|
874
|
+
}
|
|
875
|
+
async#resolveFailure(error) {
|
|
876
|
+
if (error instanceof Panic) {
|
|
877
|
+
throw error;
|
|
878
|
+
}
|
|
879
|
+
if (error instanceof ControlError) {
|
|
880
|
+
return error;
|
|
881
|
+
}
|
|
882
|
+
const controlError = this.checkDidControlFail(error);
|
|
883
|
+
if (controlError) {
|
|
884
|
+
return controlError;
|
|
885
|
+
}
|
|
886
|
+
const retryDecision = this.buildRetryDecision(error);
|
|
887
|
+
if (retryDecision.shouldAttemptRetry) {
|
|
888
|
+
return new RetryDirective(retryDecision);
|
|
889
|
+
}
|
|
890
|
+
if (retryDecision.isRetryExhausted) {
|
|
891
|
+
return new RetryExhaustedError(undefined, { cause: error });
|
|
892
|
+
}
|
|
893
|
+
if (!this.#catchFn) {
|
|
894
|
+
const finalizeControlError = this.checkDidControlFail(error);
|
|
895
|
+
if (finalizeControlError) {
|
|
896
|
+
return finalizeControlError;
|
|
897
|
+
}
|
|
898
|
+
return new UnhandledException(undefined, { cause: error });
|
|
899
|
+
}
|
|
900
|
+
let mapped;
|
|
901
|
+
try {
|
|
902
|
+
mapped = this.#catchFn(error);
|
|
903
|
+
} catch (catchError) {
|
|
904
|
+
throw new Panic("RUN_CATCH_HANDLER_THROW", { cause: catchError });
|
|
905
|
+
}
|
|
906
|
+
if (checkIsPromiseLike(mapped)) {
|
|
907
|
+
try {
|
|
908
|
+
return await this.race(mapped, error);
|
|
909
|
+
} catch (catchError) {
|
|
910
|
+
throw new Panic("RUN_CATCH_HANDLER_REJECT", { cause: catchError });
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
const catchControlError = this.checkDidControlFail(error);
|
|
914
|
+
if (catchControlError) {
|
|
915
|
+
return catchControlError;
|
|
916
|
+
}
|
|
917
|
+
return mapped;
|
|
918
|
+
}
|
|
919
|
+
async#runAttemptLoop(attempt) {
|
|
920
|
+
let currentAttempt = attempt;
|
|
921
|
+
let currentDecision;
|
|
922
|
+
while (true) {
|
|
923
|
+
const controlBeforeAttempt = this.checkDidControlFail();
|
|
924
|
+
if (controlBeforeAttempt) {
|
|
925
|
+
return controlBeforeAttempt;
|
|
926
|
+
}
|
|
927
|
+
if (currentDecision) {
|
|
928
|
+
const delayControlResult = await this.waitForRetryDelay(currentDecision.delay);
|
|
929
|
+
if (delayControlResult) {
|
|
930
|
+
return delayControlResult;
|
|
931
|
+
}
|
|
932
|
+
currentDecision = undefined;
|
|
933
|
+
}
|
|
934
|
+
this.ctx.retry.attempt = currentAttempt;
|
|
935
|
+
try {
|
|
936
|
+
const result = this.#tryFn(this.ctx);
|
|
937
|
+
if (checkIsPromiseLike(result)) {
|
|
938
|
+
const raced = await this.race(Promise.resolve(result));
|
|
939
|
+
return raced;
|
|
940
|
+
}
|
|
941
|
+
return this.resolveSyncSuccess(result);
|
|
942
|
+
} catch (attemptError) {
|
|
943
|
+
const resolved = await this.#resolveFailure(attemptError);
|
|
944
|
+
if (!(resolved instanceof RetryDirective)) {
|
|
945
|
+
return resolved;
|
|
946
|
+
}
|
|
947
|
+
currentDecision = resolved.decision;
|
|
948
|
+
currentAttempt += 1;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
async function executeRun(config, input) {
|
|
954
|
+
let __stack = [];
|
|
955
|
+
try {
|
|
956
|
+
const execution = __using(__stack, new RunExecution(config, input), 0);
|
|
957
|
+
return await execution.execute();
|
|
958
|
+
} catch (_catch) {
|
|
959
|
+
var _err = _catch, _hasErr = 1;
|
|
960
|
+
} finally {
|
|
961
|
+
__callDispose(__stack, _err, _hasErr);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// src/lib/executors/run-sync.ts
|
|
966
|
+
function assertNotPromiseLike(value, code, message) {
|
|
967
|
+
invariant(!checkIsPromiseLike(value), new Panic(code, message === undefined ? undefined : { message }));
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
class RunSyncExecution extends BaseExecution {
|
|
971
|
+
#catchFn;
|
|
972
|
+
#tryFn;
|
|
973
|
+
constructor(config, input) {
|
|
974
|
+
super(config);
|
|
975
|
+
this.#catchFn = typeof input === "function" ? undefined : input.catch;
|
|
976
|
+
this.#tryFn = typeof input === "function" ? input : input.try;
|
|
977
|
+
}
|
|
978
|
+
execute() {
|
|
979
|
+
const result = super.execute();
|
|
980
|
+
assertNotPromiseLike(result, "RUN_SYNC_WRAPPED_RESULT_PROMISE");
|
|
981
|
+
return result;
|
|
982
|
+
}
|
|
983
|
+
executeCore() {
|
|
984
|
+
return this.#runAttemptLoop(1);
|
|
985
|
+
}
|
|
986
|
+
#resolveFailure(error) {
|
|
987
|
+
if (error instanceof Panic) {
|
|
988
|
+
throw error;
|
|
989
|
+
}
|
|
990
|
+
if (error instanceof ControlError) {
|
|
991
|
+
return error;
|
|
992
|
+
}
|
|
993
|
+
const controlError = this.checkDidControlFail(error);
|
|
994
|
+
if (controlError) {
|
|
995
|
+
return controlError;
|
|
996
|
+
}
|
|
997
|
+
const retryDecision = this.buildRetryDecision(error);
|
|
998
|
+
if (retryDecision.shouldAttemptRetry) {
|
|
999
|
+
return new RetryDirective(retryDecision);
|
|
1000
|
+
}
|
|
1001
|
+
if (retryDecision.isRetryExhausted) {
|
|
1002
|
+
return new RetryExhaustedError(undefined, { cause: error });
|
|
1003
|
+
}
|
|
1004
|
+
if (!this.#catchFn) {
|
|
1005
|
+
const finalizeControlError = this.checkDidControlFail(error);
|
|
1006
|
+
if (finalizeControlError) {
|
|
1007
|
+
return finalizeControlError;
|
|
1008
|
+
}
|
|
1009
|
+
return new UnhandledException(undefined, { cause: error });
|
|
1010
|
+
}
|
|
1011
|
+
let mapped;
|
|
1012
|
+
try {
|
|
1013
|
+
mapped = this.#catchFn(error);
|
|
1014
|
+
} catch (catchError) {
|
|
1015
|
+
throw new Panic("RUN_SYNC_CATCH_HANDLER_THROW", { cause: catchError });
|
|
1016
|
+
}
|
|
1017
|
+
assertNotPromiseLike(mapped, "RUN_SYNC_CATCH_PROMISE");
|
|
1018
|
+
const catchControlError = this.checkDidControlFail(error);
|
|
1019
|
+
if (catchControlError) {
|
|
1020
|
+
return catchControlError;
|
|
1021
|
+
}
|
|
1022
|
+
return mapped;
|
|
1023
|
+
}
|
|
1024
|
+
#runAttemptLoop(attempt) {
|
|
1025
|
+
let currentAttempt = attempt;
|
|
1026
|
+
while (true) {
|
|
1027
|
+
const controlBeforeAttempt = this.checkDidControlFail();
|
|
1028
|
+
if (controlBeforeAttempt) {
|
|
1029
|
+
return controlBeforeAttempt;
|
|
1030
|
+
}
|
|
1031
|
+
this.ctx.retry.attempt = currentAttempt;
|
|
1032
|
+
let result;
|
|
1033
|
+
try {
|
|
1034
|
+
result = this.#tryFn(this.ctx);
|
|
1035
|
+
} catch (error) {
|
|
1036
|
+
const resolved = this.#resolveFailure(error);
|
|
1037
|
+
if (resolved instanceof RetryDirective) {
|
|
1038
|
+
if (resolved.decision.delay > 0) {
|
|
1039
|
+
throw new Panic("RUN_SYNC_ASYNC_RETRY_POLICY");
|
|
1040
|
+
}
|
|
1041
|
+
currentAttempt += 1;
|
|
1042
|
+
continue;
|
|
1043
|
+
}
|
|
1044
|
+
return resolved;
|
|
1045
|
+
}
|
|
1046
|
+
assertNotPromiseLike(result, "RUN_SYNC_TRY_PROMISE");
|
|
1047
|
+
return this.resolveSyncSuccess(result);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
function executeRunSync(config, input) {
|
|
1052
|
+
let __stack = [];
|
|
1053
|
+
try {
|
|
1054
|
+
const isSyncSafeRetryPolicy = config.retry === undefined || config.retry.backoff === "constant" && !config.retry.jitter && (config.retry.delayMs ?? 0) <= 0;
|
|
1055
|
+
invariant(isSyncSafeRetryPolicy, new Panic("RUN_SYNC_ASYNC_RETRY_POLICY"));
|
|
1056
|
+
const execution = __using(__stack, new RunSyncExecution(config, input), 0);
|
|
1057
|
+
return execution.execute();
|
|
1058
|
+
} catch (_catch) {
|
|
1059
|
+
var _err = _catch, _hasErr = 1;
|
|
1060
|
+
} finally {
|
|
1061
|
+
__callDispose(__stack, _err, _hasErr);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// src/lib/builder.ts
|
|
1066
|
+
class RunBuilder {
|
|
1067
|
+
config;
|
|
1068
|
+
constructor(config = {}) {
|
|
1069
|
+
this.config = config;
|
|
1070
|
+
}
|
|
1071
|
+
buildRetryConfig(policy) {
|
|
1072
|
+
const limit = typeof policy === "number" ? policy : policy.limit;
|
|
1073
|
+
invariant(Number.isFinite(limit), new Panic("RETRY_INVALID_LIMIT"));
|
|
1074
|
+
invariant(limit >= 0, new Panic("RETRY_INVALID_LIMIT"));
|
|
1075
|
+
return {
|
|
1076
|
+
...this.config,
|
|
1077
|
+
retry: retryOptions(policy)
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
buildTimeoutConfig(ms) {
|
|
1081
|
+
invariant(Number.isFinite(ms), new Panic("TIMEOUT_INVALID_MS"));
|
|
1082
|
+
invariant(ms >= 0, new Panic("TIMEOUT_INVALID_MS"));
|
|
1083
|
+
return {
|
|
1084
|
+
...this.config,
|
|
1085
|
+
timeout: ms
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
buildSignalConfig(signal) {
|
|
1089
|
+
return {
|
|
1090
|
+
...this.config,
|
|
1091
|
+
signals: [...this.config.signals ?? [], signal]
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
retry(policy) {
|
|
1095
|
+
return new ExecutionBuilder(this.buildRetryConfig(policy));
|
|
1096
|
+
}
|
|
1097
|
+
timeout(ms) {
|
|
1098
|
+
return new ExecutionBuilder(this.buildTimeoutConfig(ms));
|
|
1099
|
+
}
|
|
1100
|
+
signal(signal) {
|
|
1101
|
+
if (this instanceof ExecutionBuilder) {
|
|
1102
|
+
return new ExecutionBuilder(this.buildSignalConfig(signal));
|
|
1103
|
+
}
|
|
1104
|
+
return new RunBuilder(this.buildSignalConfig(signal));
|
|
1105
|
+
}
|
|
1106
|
+
wrap(fn) {
|
|
1107
|
+
return new RunBuilder({
|
|
1108
|
+
...this.config,
|
|
1109
|
+
wraps: [...this.config.wraps ?? [], fn]
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
run(input) {
|
|
1113
|
+
return executeRun(this.config, input);
|
|
1114
|
+
}
|
|
1115
|
+
runSync(input) {
|
|
1116
|
+
return executeRunSync(this.config, input);
|
|
1117
|
+
}
|
|
1118
|
+
all(tasks, options) {
|
|
1119
|
+
return executeAll(this.config, tasks, options);
|
|
1120
|
+
}
|
|
1121
|
+
allSettled(tasks) {
|
|
1122
|
+
return executeAllSettled(this.config, tasks);
|
|
1123
|
+
}
|
|
1124
|
+
flow(tasks) {
|
|
1125
|
+
return executeFlow(this.config, tasks);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
class ExecutionBuilder extends RunBuilder {
|
|
1130
|
+
constructor(config = {}) {
|
|
1131
|
+
super(config);
|
|
1132
|
+
Object.defineProperties(this, {
|
|
1133
|
+
all: { configurable: true, value: undefined, writable: false },
|
|
1134
|
+
allSettled: { configurable: true, value: undefined, writable: false },
|
|
1135
|
+
flow: { configurable: true, value: undefined, writable: false },
|
|
1136
|
+
wrap: { configurable: true, value: undefined, writable: false }
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// src/lib/dispose.ts
|
|
1142
|
+
function dispose() {
|
|
1143
|
+
return new AsyncDisposableStack;
|
|
1144
|
+
}
|
|
1145
|
+
// src/lib/gen.ts
|
|
1146
|
+
function* use(value) {
|
|
1147
|
+
return yield value;
|
|
1148
|
+
}
|
|
1149
|
+
async function executeAsyncGenerator(iterator, initialStep) {
|
|
1150
|
+
let currentStep = initialStep;
|
|
1151
|
+
while (true) {
|
|
1152
|
+
if (currentStep.done) {
|
|
1153
|
+
if (checkIsPromiseLike(currentStep.value)) {
|
|
1154
|
+
return await currentStep.value;
|
|
1155
|
+
}
|
|
1156
|
+
return currentStep.value;
|
|
1157
|
+
}
|
|
1158
|
+
let currentValue;
|
|
1159
|
+
if (checkIsPromiseLike(currentStep.value)) {
|
|
1160
|
+
try {
|
|
1161
|
+
currentValue = await currentStep.value;
|
|
1162
|
+
} catch (error) {
|
|
1163
|
+
currentStep = iterator.throw(error);
|
|
1164
|
+
continue;
|
|
1165
|
+
}
|
|
1166
|
+
} else {
|
|
1167
|
+
currentValue = currentStep.value;
|
|
1168
|
+
}
|
|
1169
|
+
if (currentValue instanceof Error) {
|
|
1170
|
+
return currentValue;
|
|
1171
|
+
}
|
|
1172
|
+
currentStep = iterator.next(currentValue);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
function driveGen(factory) {
|
|
1176
|
+
const iterator = factory(use);
|
|
1177
|
+
let currentValue = undefined;
|
|
1178
|
+
while (true) {
|
|
1179
|
+
const step = iterator.next(currentValue);
|
|
1180
|
+
if (step.done) {
|
|
1181
|
+
if (checkIsPromiseLike(step.value)) {
|
|
1182
|
+
return Promise.resolve(step.value);
|
|
1183
|
+
}
|
|
1184
|
+
return step.value;
|
|
1185
|
+
}
|
|
1186
|
+
if (checkIsPromiseLike(step.value)) {
|
|
1187
|
+
return executeAsyncGenerator(iterator, step);
|
|
1188
|
+
}
|
|
1189
|
+
if (step.value instanceof Error) {
|
|
1190
|
+
return step.value;
|
|
1191
|
+
}
|
|
1192
|
+
currentValue = step.value;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
// src/index.ts
|
|
1197
|
+
var root = new RunBuilder;
|
|
1198
|
+
var all = root.all.bind(root);
|
|
1199
|
+
var allSettled = root.allSettled.bind(root);
|
|
1200
|
+
var flow = root.flow.bind(root);
|
|
1201
|
+
var retry = root.retry.bind(root);
|
|
1202
|
+
var run = root.run.bind(root);
|
|
1203
|
+
var runSync = root.runSync.bind(root);
|
|
1204
|
+
var signal = root.signal.bind(root);
|
|
1205
|
+
var timeout = root.timeout.bind(root);
|
|
1206
|
+
var wrap = root.wrap.bind(root);
|
|
1207
|
+
export {
|
|
1208
|
+
wrap,
|
|
1209
|
+
timeout,
|
|
1210
|
+
signal,
|
|
1211
|
+
runSync,
|
|
1212
|
+
run,
|
|
1213
|
+
retryOptions,
|
|
1214
|
+
retry,
|
|
1215
|
+
driveGen as gen,
|
|
1216
|
+
flow,
|
|
1217
|
+
dispose,
|
|
1218
|
+
allSettled,
|
|
1219
|
+
all
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
//# debugId=DACEA87E974540E264756E2164756E21
|
|
1223
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2xpYi91dGlscy50cyIsICJzcmMvbGliL21vZGlmaWVycy9yZXRyeS50cyIsICJzcmMvbGliL21vZGlmaWVycy9zaWduYWwudHMiLCAic3JjL2xpYi9tb2RpZmllcnMvdGltZW91dC50cyIsICJzcmMvbGliL2V4ZWN1dG9ycy9iYXNlLnRzIiwgInNyYy9saWIvZXhlY3V0b3JzL3NoYXJlZC50cyIsICJzcmMvbGliL2V4ZWN1dG9ycy9hbGwudHMiLCAic3JjL2xpYi9leGVjdXRvcnMvYWxsLXNldHRsZWQudHMiLCAic3JjL2xpYi9leGVjdXRvcnMvZmxvdy50cyIsICJzcmMvbGliL2V4ZWN1dG9ycy9ydW4udHMiLCAic3JjL2xpYi9leGVjdXRvcnMvcnVuLXN5bmMudHMiLCAic3JjL2xpYi9idWlsZGVyLnRzIiwgInNyYy9saWIvZGlzcG9zZS50cyIsICJzcmMvbGliL2dlbi50cyIsICJzcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbCiAgICAiaW1wb3J0IHsgUGFuaWMsIHR5cGUgUGFuaWNDb2RlIH0gZnJvbSBcIi4vZXJyb3JzXCJcblxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFVucmVhY2hhYmxlKHZhbHVlOiBuZXZlciwgY29kZTogUGFuaWNDb2RlKTogbmV2ZXIge1xuICB0aHJvdyBuZXcgUGFuaWMoY29kZSwgeyBtZXNzYWdlOiBgVW5yZWFjaGFibGUgY2FzZTogJHtTdHJpbmcodmFsdWUpfWAgfSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGludmFyaWFudChjb25kaXRpb246IHVua25vd24sIGVycm9yOiBFcnJvcik6IGFzc2VydHMgY29uZGl0aW9uIHtcbiAgaWYgKCFjb25kaXRpb24pIHtcbiAgICB0aHJvdyBlcnJvclxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChtcyA8PSAwKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKVxuICB9KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tJc1Byb21pc2VMaWtlKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUHJvbWlzZUxpa2U8dW5rbm93bj4ge1xuICByZXR1cm4gKFxuICAgICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIpICYmXG4gICAgdmFsdWUgIT09IG51bGwgJiZcbiAgICB0eXBlb2YgKHZhbHVlIGFzIHsgdGhlbj86IHVua25vd24gfSkudGhlbiA9PT0gXCJmdW5jdGlvblwiXG4gIClcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVXaXRoQWJvcnQ8ViwgRT4oXG4gIHNpZ25hbDogQWJvcnRTaWduYWwsXG4gIHByb21pc2U6IFByb21pc2VMaWtlPFY+LFxuICBjcmVhdGVBYm9ydFJlc3VsdDogKCkgPT4gRVxuKTogUHJvbWlzZTxWIHwgRT4ge1xuICB1c2luZyBkaXNwb3NlciA9IG5ldyBEaXNwb3NhYmxlU3RhY2soKVxuXG4gIGNvbnN0IGFib3J0UHJvbWlzZSA9IG5ldyBQcm9taXNlPEU+KChyZXNvbHZlKSA9PiB7XG4gICAgY29uc3Qgb25BYm9ydCA9ICgpID0+IHtcbiAgICAgIHJlc29sdmUoY3JlYXRlQWJvcnRSZXN1bHQoKSlcbiAgICB9XG5cbiAgICBpZiAoc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgIG9uQWJvcnQoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0LCB7IG9uY2U6IHRydWUgfSlcbiAgICBkaXNwb3Nlci5kZWZlcigoKSA9PiB7XG4gICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQpXG4gICAgfSlcbiAgfSlcblxuICByZXR1cm4gYXdhaXQgUHJvbWlzZS5yYWNlKFtQcm9taXNlLnJlc29sdmUocHJvbWlzZSksIGFib3J0UHJvbWlzZV0pXG59XG4iLAogICAgImltcG9ydCB0eXBlIHsgQnVpbGRlckNvbmZpZyB9IGZyb20gXCIuLi9idWlsZGVyXCJcbmltcG9ydCB0eXBlIHsgVHJ5Q3R4IH0gZnJvbSBcIi4uL2V4ZWN1dG9ycy9zaGFyZWRcIlxuaW1wb3J0IHsgUGFuaWMgfSBmcm9tIFwiLi4vZXJyb3JzXCJcbmltcG9ydCB7IGFzc2VydFVucmVhY2hhYmxlLCBpbnZhcmlhbnQgfSBmcm9tIFwiLi4vdXRpbHNcIlxuXG5pbnRlcmZhY2UgQmFzZVJldHJ5UG9saWN5IHtcbiAgLyoqXG4gICAqIE1heGltdW0gbnVtYmVyIG9mIGF0dGVtcHRzLCBpbmNsdWRpbmcgdGhlIGZpcnN0IHJ1bi5cbiAgICovXG4gIGxpbWl0OiBudW1iZXJcbiAgLyoqXG4gICAqIERlbGF5IGluIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIGF0dGVtcHRzLiBEZWZhdWx0cyB0byAwLlxuICAgKi9cbiAgZGVsYXlNcz86IG51bWJlclxuICAvKipcbiAgICogQWRkcyByYW5kb20gaml0dGVyIHRvIGRlbGF5cyB3aGVuIGVuYWJsZWQuXG4gICAqL1xuICBqaXR0ZXI/OiBib29sZWFuXG4gIC8qKlxuICAgKiBSZXR1cm4gdHJ1ZSB0byByZXRyeSBhZnRlciBhbiBlcnJvciwgZmFsc2UgdG8gc3RvcC5cbiAgICovXG4gIHNob3VsZFJldHJ5PzogKGVycm9yOiB1bmtub3duLCBjdHg6IFRyeUN0eCkgPT4gYm9vbGVhblxufVxuXG5pbnRlcmZhY2UgTGluZWFyQmFja29mZlJldHJ5UG9saWN5IGV4dGVuZHMgQmFzZVJldHJ5UG9saWN5IHtcbiAgLyoqXG4gICAqIFVzZSBsaW5lYXJseSBpbmNyZWFzaW5nIGRlbGF5IGJldHdlZW4gYXR0ZW1wdHMuXG4gICAqL1xuICBiYWNrb2ZmOiBcImxpbmVhclwiXG4gIC8qKlxuICAgKiBOb3Qgc3VwcG9ydGVkIGZvciBsaW5lYXIgYmFja29mZi5cbiAgICovXG4gIG1heERlbGF5TXM/OiBuZXZlclxufVxuXG5pbnRlcmZhY2UgRXhwb25lbnRpYWxCYWNrb2ZmUmV0cnlQb2xpY3kgZXh0ZW5kcyBCYXNlUmV0cnlQb2xpY3kge1xuICAvKipcbiAgICogVXNlIGV4cG9uZW50aWFsIGRlbGF5IGdyb3d0aCBiZXR3ZWVuIGF0dGVtcHRzLlxuICAgKi9cbiAgYmFja29mZjogXCJleHBvbmVudGlhbFwiXG4gIC8qKlxuICAgKiBPcHRpb25hbCBjYXAgZm9yIGV4cG9uZW50aWFsIGRlbGF5IGluIG1pbGxpc2Vjb25kcy5cbiAgICovXG4gIG1heERlbGF5TXM/OiBudW1iZXJcbn1cblxuLyoqXG4gKiBSZXRyeSBwb2xpY3kgdXNpbmcgYSBjb25zdGFudCBkZWxheSBzdHJhdGVneS5cbiAqL1xuaW50ZXJmYWNlIENvbnN0YW50QmFja29mZlJldHJ5UG9saWN5IGV4dGVuZHMgQmFzZVJldHJ5UG9saWN5IHtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGRpc2NyaW1pbmFudDogdXNlIGEgZml4ZWQgZGVsYXkgYmV0d2VlbiBhdHRlbXB0cy5cbiAgICovXG4gIGJhY2tvZmY6IFwiY29uc3RhbnRcIlxuICAvKipcbiAgICogTm90IHN1cHBvcnRlZCBmb3IgY29uc3RhbnQgYmFja29mZi5cbiAgICovXG4gIG1heERlbGF5TXM/OiBuZXZlclxufVxuXG4vKipcbiAqIFJldHJ5IGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxuICovXG5leHBvcnQgdHlwZSBSZXRyeVBvbGljeSA9XG4gIHwgTGluZWFyQmFja29mZlJldHJ5UG9saWN5XG4gIHwgRXhwb25lbnRpYWxCYWNrb2ZmUmV0cnlQb2xpY3lcbiAgfCBDb25zdGFudEJhY2tvZmZSZXRyeVBvbGljeVxuXG4vKipcbiAqIFJldHJ5IHNob3J0aGFuZCBvciBmdWxsIHJldHJ5IGNvbmZpZ3VyYXRpb24uXG4gKlxuICogLSBgbnVtYmVyYDogYXR0ZW1wdCBsaW1pdFxuICogLSBgUmV0cnlQb2xpY3lgOiBkZXRhaWxlZCByZXRyeSBzZXR0aW5nc1xuICovXG5leHBvcnQgdHlwZSBSZXRyeU9wdGlvbnMgPSBudW1iZXIgfCBSZXRyeVBvbGljeVxuXG5leHBvcnQgZnVuY3Rpb24gcmV0cnlPcHRpb25zKHBvbGljeTogUmV0cnlPcHRpb25zKTogUmV0cnlQb2xpY3kge1xuICBjb25zdCBsaW1pdCA9IHR5cGVvZiBwb2xpY3kgPT09IFwibnVtYmVyXCIgPyBwb2xpY3kgOiBwb2xpY3kubGltaXRcblxuICBpbnZhcmlhbnQoTnVtYmVyLmlzRmluaXRlKGxpbWl0KSwgbmV3IFBhbmljKFwiUkVUUllfSU5WQUxJRF9MSU1JVFwiKSlcbiAgaW52YXJpYW50KGxpbWl0ID49IDAsIG5ldyBQYW5pYyhcIlJFVFJZX0lOVkFMSURfTElNSVRcIikpXG5cbiAgaWYgKHR5cGVvZiBwb2xpY3kgPT09IFwibnVtYmVyXCIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmFja29mZjogXCJjb25zdGFudFwiLFxuICAgICAgZGVsYXlNczogMCxcbiAgICAgIGxpbWl0OiBwb2xpY3ksXG4gICAgfVxuICB9XG5cbiAgY29uc3QgYmFzZSA9IHtcbiAgICBkZWxheU1zOiBwb2xpY3kuZGVsYXlNcyA/PyAwLFxuICAgIGppdHRlcjogcG9saWN5LmppdHRlcixcbiAgICBsaW1pdDogcG9saWN5LmxpbWl0LFxuICAgIHNob3VsZFJldHJ5OiBwb2xpY3kuc2hvdWxkUmV0cnksXG4gIH1cblxuICBzd2l0Y2ggKHBvbGljeS5iYWNrb2ZmKSB7XG4gICAgY2FzZSBcImNvbnN0YW50XCI6XG4gICAgY2FzZSBcImxpbmVhclwiOlxuICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgYmFja29mZjogcG9saWN5LmJhY2tvZmYgfVxuICAgIGNhc2UgXCJleHBvbmVudGlhbFwiOlxuICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgYmFja29mZjogcG9saWN5LmJhY2tvZmYsIG1heERlbGF5TXM6IHBvbGljeS5tYXhEZWxheU1zIH1cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGFzc2VydFVucmVhY2hhYmxlKHBvbGljeSwgXCJVTlJFQUNIQUJMRV9SRVRSWV9QT0xJQ1lfQkFDS09GRlwiKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVSZXRyeURlbGF5KGF0dGVtcHQ6IG51bWJlciwgY29uZmlnOiBCdWlsZGVyQ29uZmlnKTogbnVtYmVyIHtcbiAgY29uc3QgcG9saWN5ID0gY29uZmlnLnJldHJ5XG5cbiAgaWYgKCFwb2xpY3kpIHtcbiAgICByZXR1cm4gMFxuICB9XG5cbiAgY29uc3QgYmFzZURlbGF5ID0gcG9saWN5LmRlbGF5TXMgPz8gMFxuICBsZXQgZGVsYXkgPSAwXG5cbiAgc3dpdGNoIChwb2xpY3kuYmFja29mZikge1xuICAgIGNhc2UgXCJjb25zdGFudFwiOlxuICAgICAgZGVsYXkgPSBiYXNlRGVsYXlcbiAgICAgIGJyZWFrXG4gICAgY2FzZSBcImxpbmVhclwiOlxuICAgICAgZGVsYXkgPSBiYXNlRGVsYXkgKiBhdHRlbXB0XG4gICAgICBicmVha1xuICAgIGNhc2UgXCJleHBvbmVudGlhbFwiOlxuICAgICAgZGVsYXkgPSBiYXNlRGVsYXkgKiAyICoqIChhdHRlbXB0IC0gMSlcblxuICAgICAgaWYgKHBvbGljeS5tYXhEZWxheU1zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZGVsYXkgPSBNYXRoLm1pbihkZWxheSwgcG9saWN5Lm1heERlbGF5TXMpXG4gICAgICB9XG5cbiAgICAgIGJyZWFrXG4gIH1cblxuICBpZiAoIXBvbGljeS5qaXR0ZXIgfHwgZGVsYXkgPD0gMCkge1xuICAgIHJldHVybiBkZWxheVxuICB9XG5cbiAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGRlbGF5KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tTaG91bGRBdHRlbXB0UmV0cnkoXG4gIGVycm9yOiB1bmtub3duLFxuICBjdHg6IFRyeUN0eCxcbiAgY29uZmlnOiBCdWlsZGVyQ29uZmlnXG4pOiBib29sZWFuIHtcbiAgY29uc3QgcG9saWN5ID0gY29uZmlnLnJldHJ5XG5cbiAgaWYgKCFwb2xpY3kpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIGlmIChjdHgucmV0cnkuYXR0ZW1wdCA+PSBwb2xpY3kubGltaXQpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIGlmICghcG9saWN5LnNob3VsZFJldHJ5KSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIHJldHVybiBwb2xpY3kuc2hvdWxkUmV0cnkoZXJyb3IsIGN0eClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNSZXRyeUV4aGF1c3RlZChhdHRlbXB0OiBudW1iZXIsIGNvbmZpZzogQnVpbGRlckNvbmZpZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gY29uZmlnLnJldHJ5ICE9PSB1bmRlZmluZWQgJiYgYXR0ZW1wdCA+PSBjb25maWcucmV0cnkubGltaXRcbn1cbiIsCiAgICAiaW1wb3J0IHsgQ2FuY2VsbGF0aW9uRXJyb3IsIFRpbWVvdXRFcnJvciB9IGZyb20gXCIuLi9lcnJvcnNcIlxuaW1wb3J0IHsgcmVzb2x2ZVdpdGhBYm9ydCB9IGZyb20gXCIuLi91dGlsc1wiXG5cbmV4cG9ydCBjbGFzcyBTaWduYWxDb250cm9sbGVyIHtcbiAgcmVhZG9ubHkgc2lnbmFsPzogQWJvcnRTaWduYWxcblxuICBjb25zdHJ1Y3RvcihzaWduYWxzOiByZWFkb25seSBBYm9ydFNpZ25hbFtdID0gW10pIHtcbiAgICBpZiAoc2lnbmFscy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnNpZ25hbCA9IEFib3J0U2lnbmFsLmFueShbLi4uc2lnbmFsc10pXG4gICAgfVxuICB9XG5cbiAgY2hlY2tEaWRDYW5jZWwoY2F1c2U/OiB1bmtub3duKTogQ2FuY2VsbGF0aW9uRXJyb3IgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5zaWduYWw/LmFib3J0ZWQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICh0aGlzLnNpZ25hbC5yZWFzb24gaW5zdGFuY2VvZiBUaW1lb3V0RXJyb3IpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ2FuY2VsbGF0aW9uRXJyb3IodW5kZWZpbmVkLCB7IGNhdXNlOiBjYXVzZSA/PyB0aGlzLnNpZ25hbC5yZWFzb24gfSlcbiAgfVxuXG4gIGFzeW5jIHJhY2U8Vj4ocHJvbWlzZTogUHJvbWlzZUxpa2U8Vj4sIGNhdXNlPzogdW5rbm93bik6IFByb21pc2U8ViB8IENhbmNlbGxhdGlvbkVycm9yPiB7XG4gICAgY29uc3QgY2FuY2VsbGVkID0gdGhpcy5jaGVja0RpZENhbmNlbChjYXVzZSlcblxuICAgIGlmIChjYW5jZWxsZWQpIHtcbiAgICAgIHJldHVybiBjYW5jZWxsZWRcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuc2lnbmFsKSB7XG4gICAgICByZXR1cm4gcHJvbWlzZVxuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCByZXNvbHZlV2l0aEFib3J0KFxuICAgICAgdGhpcy5zaWduYWwsXG4gICAgICBwcm9taXNlLFxuICAgICAgKCkgPT4gbmV3IENhbmNlbGxhdGlvbkVycm9yKHVuZGVmaW5lZCwgeyBjYXVzZTogY2F1c2UgPz8gdGhpcy5zaWduYWw/LnJlYXNvbiB9KVxuICAgIClcbiAgfVxuXG4gIFtTeW1ib2wuZGlzcG9zZV0oKTogdm9pZCB7XG4gICAgdm9pZCB0aGlzLnNpZ25hbFxuICB9XG59XG4iLAogICAgImltcG9ydCB7IFBhbmljLCBUaW1lb3V0RXJyb3IgfSBmcm9tIFwiLi4vZXJyb3JzXCJcbmltcG9ydCB7IGludmFyaWFudCwgcmVzb2x2ZVdpdGhBYm9ydCB9IGZyb20gXCIuLi91dGlsc1wiXG5cbmV4cG9ydCBjbGFzcyBUaW1lb3V0Q29udHJvbGxlciB7XG4gIHJlYWRvbmx5IHNpZ25hbD86IEFib3J0U2lnbmFsXG4gIHJlYWRvbmx5ICNjb250cm9sbGVyPzogQWJvcnRDb250cm9sbGVyXG4gIHJlYWRvbmx5ICNzdGFydGVkQXQgPSBEYXRlLm5vdygpXG4gIHJlYWRvbmx5ICN0aW1lb3V0TXM6IG51bWJlclxuICAjdGltZW91dElkOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IHVuZGVmaW5lZFxuXG4gIGNvbnN0cnVjdG9yKHRpbWVvdXRNcz86IG51bWJlcikge1xuICAgIHRoaXMuI3RpbWVvdXRNcyA9IHRpbWVvdXRNcyA/PyAtMVxuXG4gICAgaWYgKHRpbWVvdXRNcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpbnZhcmlhbnQoTnVtYmVyLmlzRmluaXRlKHRpbWVvdXRNcyksIG5ldyBQYW5pYyhcIlRJTUVPVVRfSU5WQUxJRF9NU1wiKSlcbiAgICBpbnZhcmlhbnQodGltZW91dE1zID49IDAsIG5ldyBQYW5pYyhcIlRJTUVPVVRfSU5WQUxJRF9NU1wiKSlcblxuICAgIHRoaXMuI2NvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcbiAgICB0aGlzLnNpZ25hbCA9IHRoaXMuI2NvbnRyb2xsZXIuc2lnbmFsXG5cbiAgICBpZiAodGhpcy4jdGltZW91dE1zIDw9IDApIHtcbiAgICAgIHRoaXMuI2Fib3J0KClcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHRoaXMuI3RpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy4jYWJvcnQoKVxuICAgIH0sIHRoaXMuI3RpbWVvdXRNcylcbiAgfVxuXG4gICNhYm9ydChjYXVzZT86IHVua25vd24pIHtcbiAgICBjb25zdCB0aW1lb3V0RXJyb3IgPSBuZXcgVGltZW91dEVycm9yKGBFeGVjdXRpb24gZXhjZWVkZWQgdGltZW91dCBvZiAke3RoaXMuI3RpbWVvdXRNc31tc2AsIHtcbiAgICAgIGNhdXNlLFxuICAgIH0pXG5cbiAgICBpZiAoIXRoaXMuc2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICB0aGlzLiNjb250cm9sbGVyPy5hYm9ydCh0aW1lb3V0RXJyb3IpXG4gICAgfVxuXG4gICAgcmV0dXJuIHRpbWVvdXRFcnJvclxuICB9XG5cbiAgZ2V0ICNyZW1haW5pbmcoKSB7XG4gICAgY29uc3QgZWxhcHNlZCA9IERhdGUubm93KCkgLSB0aGlzLiNzdGFydGVkQXRcblxuICAgIHJldHVybiB0aGlzLiN0aW1lb3V0TXMgLSBlbGFwc2VkXG4gIH1cblxuICBjaGVja0RpZFRpbWVvdXQoY2F1c2U/OiB1bmtub3duKTogVGltZW91dEVycm9yIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMuc2lnbmFsKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgY29uc3QgcmVhc29uID0gdGhpcy5zaWduYWwucmVhc29uXG5cbiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBUaW1lb3V0RXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHJlYXNvblxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFRpbWVvdXRFcnJvcihgRXhlY3V0aW9uIGV4Y2VlZGVkIHRpbWVvdXQgb2YgJHt0aGlzLiN0aW1lb3V0TXN9bXNgLCB7XG4gICAgICAgIGNhdXNlOiBjYXVzZSA/PyByZWFzb24sXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmICh0aGlzLiNyZW1haW5pbmcgPiAwKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy4jYWJvcnQoY2F1c2UpXG4gIH1cblxuICBhc3luYyByYWNlPFY+KHByb21pc2U6IFByb21pc2VMaWtlPFY+LCBjYXVzZT86IHVua25vd24pOiBQcm9taXNlPFYgfCBUaW1lb3V0RXJyb3I+IHtcbiAgICBpZiAoIXRoaXMuc2lnbmFsKSB7XG4gICAgICByZXR1cm4gcHJvbWlzZVxuICAgIH1cblxuICAgIGlmICh0aGlzLiNyZW1haW5pbmcgPD0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuI2Fib3J0KGNhdXNlKVxuICAgIH1cblxuICAgIGNvbnN0IHRpbWVkT3V0ID0gdGhpcy5jaGVja0RpZFRpbWVvdXQoY2F1c2UpXG5cbiAgICBpZiAodGltZWRPdXQpIHtcbiAgICAgIHJldHVybiB0aW1lZE91dFxuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCByZXNvbHZlV2l0aEFib3J0KFxuICAgICAgdGhpcy5zaWduYWwsXG4gICAgICBwcm9taXNlLFxuICAgICAgKCkgPT5cbiAgICAgICAgdGhpcy5jaGVja0RpZFRpbWVvdXQoY2F1c2UpID8/XG4gICAgICAgIG5ldyBUaW1lb3V0RXJyb3IoYEV4ZWN1dGlvbiBleGNlZWRlZCB0aW1lb3V0IG9mICR7dGhpcy4jdGltZW91dE1zfW1zYCwgeyBjYXVzZSB9KVxuICAgIClcbiAgfVxuXG4gIFtTeW1ib2wuZGlzcG9zZV0oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuI3RpbWVvdXRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy4jdGltZW91dElkKVxuICAgIH1cbiAgfVxufVxuIiwKICAgICJpbXBvcnQgdHlwZSB7IEJ1aWxkZXJDb25maWcsIFdyYXBDdHggfSBmcm9tIFwiLi4vYnVpbGRlclwiXG5pbXBvcnQgdHlwZSB7IFJldHJ5RXhoYXVzdGVkRXJyb3IsIFVuaGFuZGxlZEV4Y2VwdGlvbiB9IGZyb20gXCIuLi9lcnJvcnNcIlxuaW1wb3J0IHR5cGUgeyBUcnlDdHggfSBmcm9tIFwiLi9zaGFyZWRcIlxuaW1wb3J0IHsgQ2FuY2VsbGF0aW9uRXJyb3IsIFRpbWVvdXRFcnJvciB9IGZyb20gXCIuLi9lcnJvcnNcIlxuaW1wb3J0IHtcbiAgY2FsY3VsYXRlUmV0cnlEZWxheSxcbiAgY2hlY2tJc1JldHJ5RXhoYXVzdGVkLFxuICBjaGVja1Nob3VsZEF0dGVtcHRSZXRyeSxcbn0gZnJvbSBcIi4uL21vZGlmaWVycy9yZXRyeVwiXG5pbXBvcnQgeyBTaWduYWxDb250cm9sbGVyIH0gZnJvbSBcIi4uL21vZGlmaWVycy9zaWduYWxcIlxuaW1wb3J0IHsgVGltZW91dENvbnRyb2xsZXIgfSBmcm9tIFwiLi4vbW9kaWZpZXJzL3RpbWVvdXRcIlxuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi4vdXRpbHNcIlxuXG5pbnRlcmZhY2UgQmFzZUV4ZWN1dGlvbk9wdGlvbnMge1xuICByZXRyeUxpbWl0PzogbnVtYmVyXG59XG5cbmV4cG9ydCB0eXBlIFJldHJ5RGVjaXNpb24gPSB7XG4gIGRlbGF5OiBudW1iZXJcbiAgaXNSZXRyeUV4aGF1c3RlZDogYm9vbGVhblxuICBzaG91bGRBdHRlbXB0UmV0cnk6IGJvb2xlYW5cbn1cblxuZXhwb3J0IHR5cGUgUnVubmVyRXJyb3IgPVxuICB8IENhbmNlbGxhdGlvbkVycm9yXG4gIHwgUmV0cnlFeGhhdXN0ZWRFcnJvclxuICB8IFRpbWVvdXRFcnJvclxuICB8IFVuaGFuZGxlZEV4Y2VwdGlvblxuXG5leHBvcnQgY2xhc3MgUmV0cnlEaXJlY3RpdmUge1xuICByZWFkb25seSBkZWNpc2lvbjogUmV0cnlEZWNpc2lvblxuXG4gIGNvbnN0cnVjdG9yKGRlY2lzaW9uOiBSZXRyeURlY2lzaW9uKSB7XG4gICAgdGhpcy5kZWNpc2lvbiA9IGRlY2lzaW9uXG4gIH1cbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VFeGVjdXRpb248VFJlc3VsdCA9IHVua25vd24+IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbmZpZzogQnVpbGRlckNvbmZpZ1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY3R4OiBUcnlDdHhcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGV4ZWN1dGlvblNpZ25hbDogQWJvcnRTaWduYWwgfCB1bmRlZmluZWRcbiAgcmVhZG9ubHkgI3dyYXBDdHg6IFdyYXBDdHhcbiAgcmVhZG9ubHkgI3NpZ25hbENvbnRyb2xsZXI6IFNpZ25hbENvbnRyb2xsZXIgfCB1bmRlZmluZWRcbiAgcmVhZG9ubHkgI3RpbWVvdXRDb250cm9sbGVyOiBUaW1lb3V0Q29udHJvbGxlciB8IHVuZGVmaW5lZFxuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihjb25maWc6IEJ1aWxkZXJDb25maWcsIG9wdGlvbnM6IEJhc2VFeGVjdXRpb25PcHRpb25zID0ge30pIHtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZ1xuICAgIHRoaXMuI3RpbWVvdXRDb250cm9sbGVyID0gQmFzZUV4ZWN1dGlvbi5jcmVhdGVUaW1lb3V0Q29udHJvbGxlcihjb25maWcudGltZW91dClcbiAgICB0aGlzLiNzaWduYWxDb250cm9sbGVyID0gQmFzZUV4ZWN1dGlvbi5jcmVhdGVTaWduYWxDb250cm9sbGVyKFxuICAgICAgY29uZmlnLnNpZ25hbHMsXG4gICAgICB0aGlzLiN0aW1lb3V0Q29udHJvbGxlcj8uc2lnbmFsXG4gICAgKVxuICAgIHRoaXMuZXhlY3V0aW9uU2lnbmFsID0gdGhpcy4jc2lnbmFsQ29udHJvbGxlcj8uc2lnbmFsXG4gICAgdGhpcy5jdHggPSBCYXNlRXhlY3V0aW9uLmNyZWF0ZUNvbnRleHQoY29uZmlnLCB0aGlzLmV4ZWN1dGlvblNpZ25hbCwgb3B0aW9ucy5yZXRyeUxpbWl0KVxuICAgIHRoaXMuI3dyYXBDdHggPSBCYXNlRXhlY3V0aW9uLmNyZWF0ZVdyYXBDb250ZXh0KHRoaXMuY3R4KVxuICB9XG5cbiAgZXhlY3V0ZSgpOiBUUmVzdWx0IHtcbiAgICAvLyBXcmFwcyBjb3ZlciB0aGUgZnVsbCByZXRyeSBzY29wZTsgYGN0eC5yZXRyeS5hdHRlbXB0YCBtYXkgcmVmbGVjdCB0aGUgZmluYWxcbiAgICAvLyBhdHRlbXB0IHdoZW4gb2JzZXJ2ZWQgYWZ0ZXIgYG5leHQoKWAgcmVzb2x2ZXMuXG4gICAgY29uc3Qgd3JhcHMgPSB0aGlzLmNvbmZpZy53cmFwc1xuXG4gICAgaWYgKCF3cmFwcyB8fCB3cmFwcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVDb3JlKClcbiAgICB9XG5cbiAgICBsZXQgbmV4dCA9ICgpOiB1bmtub3duID0+IHRoaXMuZXhlY3V0ZUNvcmUoKVxuXG4gICAgZm9yIChjb25zdCB3cmFwIG9mIHdyYXBzLnRvUmV2ZXJzZWQoKSkge1xuICAgICAgY29uc3QgcHJldmlvdXMgPSBuZXh0XG4gICAgICBuZXh0ID0gKCkgPT4gd3JhcCh0aGlzLiN3cmFwQ3R4LCBwcmV2aW91cylcbiAgICB9XG5cbiAgICByZXR1cm4gbmV4dCgpIGFzIFRSZXN1bHRcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBleGVjdXRlQ29yZSgpOiBUUmVzdWx0XG5cbiAgW1N5bWJvbC5kaXNwb3NlXSgpOiB2b2lkIHtcbiAgICB1c2luZyBkaXNwb3NlciA9IG5ldyBEaXNwb3NhYmxlU3RhY2soKVxuICAgIGlmICh0aGlzLiN0aW1lb3V0Q29udHJvbGxlcikge1xuICAgICAgZGlzcG9zZXIudXNlKHRoaXMuI3RpbWVvdXRDb250cm9sbGVyKVxuICAgIH1cblxuICAgIGlmICh0aGlzLiNzaWduYWxDb250cm9sbGVyKSB7XG4gICAgICBkaXNwb3Nlci51c2UodGhpcy4jc2lnbmFsQ29udHJvbGxlcilcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIGNyZWF0ZUNvbnRleHQoXG4gICAgY29uZmlnOiBCdWlsZGVyQ29uZmlnLFxuICAgIHNpZ25hbDogQWJvcnRTaWduYWwgfCB1bmRlZmluZWQsXG4gICAgcmV0cnlMaW1pdD86IG51bWJlclxuICApOiBUcnlDdHgge1xuICAgIHJldHVybiB7XG4gICAgICByZXRyeToge1xuICAgICAgICBhdHRlbXB0OiAxLFxuICAgICAgICBsaW1pdDogcmV0cnlMaW1pdCA/PyBjb25maWcucmV0cnk/LmxpbWl0ID8/IDEsXG4gICAgICB9LFxuICAgICAgc2lnbmFsLFxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBzdGF0aWMgY3JlYXRlVGltZW91dENvbnRyb2xsZXIoXG4gICAgdGltZW91dE1zOiBudW1iZXIgfCB1bmRlZmluZWRcbiAgKTogVGltZW91dENvbnRyb2xsZXIgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aW1lb3V0TXMgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IG5ldyBUaW1lb3V0Q29udHJvbGxlcih0aW1lb3V0TXMpXG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIGNyZWF0ZVNpZ25hbENvbnRyb2xsZXIoXG4gICAgc2lnbmFsczogcmVhZG9ubHkgQWJvcnRTaWduYWxbXSB8IHVuZGVmaW5lZCxcbiAgICB0aW1lb3V0U2lnbmFsOiBBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZFxuICApOiBTaWduYWxDb250cm9sbGVyIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjb21wb3NlZFNpZ25hbHMgPSBbLi4uKHNpZ25hbHMgPz8gW10pLCB0aW1lb3V0U2lnbmFsXS5maWx0ZXIoXG4gICAgICAodmFsdWUpOiB2YWx1ZSBpcyBBYm9ydFNpZ25hbCA9PiB2YWx1ZSAhPT0gdW5kZWZpbmVkXG4gICAgKVxuXG4gICAgcmV0dXJuIGNvbXBvc2VkU2lnbmFscy5sZW5ndGggPiAwID8gbmV3IFNpZ25hbENvbnRyb2xsZXIoY29tcG9zZWRTaWduYWxzKSA6IHVuZGVmaW5lZFxuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXRpYyBjcmVhdGVXcmFwQ29udGV4dChjdHg6IFRyeUN0eCk6IFdyYXBDdHgge1xuICAgIGNvbnN0IHJldHJ5ID0gbmV3IFByb3h5KGN0eC5yZXRyeSwge1xuICAgICAgZGVmaW5lUHJvcGVydHk6ICgpID0+IGZhbHNlLFxuICAgICAgZGVsZXRlUHJvcGVydHk6ICgpID0+IGZhbHNlLFxuICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcGVydHkpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IFJlZmxlY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcGVydHkpXG5cbiAgICAgICAgaWYgKCFkZXNjcmlwdG9yKSB7XG4gICAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3JcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4uZGVzY3JpcHRvcixcbiAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBzZXQ6ICgpID0+IGZhbHNlLFxuICAgIH0pIGFzIFdyYXBDdHhbXCJyZXRyeVwiXVxuXG4gICAgcmV0dXJuIG5ldyBQcm94eShjdHgsIHtcbiAgICAgIGRlZmluZVByb3BlcnR5OiAoKSA9PiBmYWxzZSxcbiAgICAgIGRlbGV0ZVByb3BlcnR5OiAoKSA9PiBmYWxzZSxcbiAgICAgIGdldCh0YXJnZXQsIHByb3BlcnR5LCByZWNlaXZlcikge1xuICAgICAgICBpZiAocHJvcGVydHkgPT09IFwicmV0cnlcIikge1xuICAgICAgICAgIHJldHVybiByZXRyeVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcGVydHksIHJlY2VpdmVyKSBhcyB1bmtub3duXG4gICAgICB9LFxuICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcGVydHkpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IFJlZmxlY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgcHJvcGVydHkpXG5cbiAgICAgICAgaWYgKCFkZXNjcmlwdG9yKSB7XG4gICAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3JcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcm9wZXJ0eSA9PT0gXCJyZXRyeVwiKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmRlc2NyaXB0b3IsXG4gICAgICAgICAgICB2YWx1ZTogcmV0cnksXG4gICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5kZXNjcmlwdG9yLFxuICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHNldDogKCkgPT4gZmFsc2UsXG4gICAgfSkgYXMgV3JhcEN0eFxuICB9XG5cbiAgcHJvdGVjdGVkIGNoZWNrRGlkQ2FuY2VsKGNhdXNlPzogdW5rbm93bik6IENhbmNlbGxhdGlvbkVycm9yIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy4jc2lnbmFsQ29udHJvbGxlcj8uY2hlY2tEaWRDYW5jZWwoY2F1c2UpXG4gIH1cblxuICBwcm90ZWN0ZWQgcmFjZVdpdGhDYW5jZWxsYXRpb248Vj4oXG4gICAgcHJvbWlzZTogUHJvbWlzZUxpa2U8Vj4sXG4gICAgY2F1c2U/OiB1bmtub3duXG4gICk6IFByb21pc2VMaWtlPFYgfCBDYW5jZWxsYXRpb25FcnJvcj4ge1xuICAgIHJldHVybiB0aGlzLiNzaWduYWxDb250cm9sbGVyID8gdGhpcy4jc2lnbmFsQ29udHJvbGxlci5yYWNlKHByb21pc2UsIGNhdXNlKSA6IHByb21pc2VcbiAgfVxuXG4gIHByb3RlY3RlZCBjaGVja0RpZENvbnRyb2xGYWlsKGNhdXNlPzogdW5rbm93bik6IENhbmNlbGxhdGlvbkVycm9yIHwgVGltZW91dEVycm9yIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5jaGVja0RpZENhbmNlbChjYXVzZSkgPz8gdGhpcy4jdGltZW91dENvbnRyb2xsZXI/LmNoZWNrRGlkVGltZW91dChjYXVzZSlcbiAgfVxuXG4gIHByb3RlY3RlZCByZXNvbHZlU3luY1N1Y2Nlc3M8VD4odmFsdWU6IFQpOiBUIHwgQ2FuY2VsbGF0aW9uRXJyb3IgfCBUaW1lb3V0RXJyb3Ige1xuICAgIHJldHVybiB0aGlzLmNoZWNrRGlkQ29udHJvbEZhaWwoKSA/PyB2YWx1ZVxuICB9XG5cbiAgcHJvdGVjdGVkIHJhY2U8Vj4oXG4gICAgcHJvbWlzZTogUHJvbWlzZUxpa2U8Vj4sXG4gICAgY2F1c2U/OiB1bmtub3duXG4gICk6IFByb21pc2VMaWtlPFYgfCBDYW5jZWxsYXRpb25FcnJvciB8IFRpbWVvdXRFcnJvcj4ge1xuICAgIGNvbnN0IHRpbWVvdXRDb250cm9sbGVyID0gdGhpcy4jdGltZW91dENvbnRyb2xsZXJcblxuICAgIGlmICghdGltZW91dENvbnRyb2xsZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLnJhY2VXaXRoQ2FuY2VsbGF0aW9uKHByb21pc2UsIGNhdXNlKVxuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoXG4gICAgICB0aW1lb3V0Q29udHJvbGxlci5yYWNlKHRoaXMucmFjZVdpdGhDYW5jZWxsYXRpb24ocHJvbWlzZSwgY2F1c2UpLCBjYXVzZSlcbiAgICApLnRoZW4oKHJhY2VkKSA9PiB7XG4gICAgICBpZiAocmFjZWQgaW5zdGFuY2VvZiBUaW1lb3V0RXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hlY2tEaWRDYW5jZWwoY2F1c2UpID8/IHJhY2VkXG4gICAgICB9XG5cbiAgICAgIHJldHVybiByYWNlZFxuICAgIH0pXG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgd2FpdEZvclJldHJ5RGVsYXkoXG4gICAgZGVsYXk6IG51bWJlclxuICApOiBQcm9taXNlPENhbmNlbGxhdGlvbkVycm9yIHwgVGltZW91dEVycm9yIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKGRlbGF5IDw9IDApIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG5cbiAgICBjb25zdCBzbGVlcFJlc3VsdCA9IGF3YWl0IHRoaXMucmFjZShzbGVlcChkZWxheSkpXG5cbiAgICBpZiAoc2xlZXBSZXN1bHQgaW5zdGFuY2VvZiBDYW5jZWxsYXRpb25FcnJvciB8fCBzbGVlcFJlc3VsdCBpbnN0YW5jZW9mIFRpbWVvdXRFcnJvcikge1xuICAgICAgcmV0dXJuIHNsZWVwUmVzdWx0XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgcHJvdGVjdGVkIHNob3VsZEF0dGVtcHRSZXRyeShlcnJvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjaGVja1Nob3VsZEF0dGVtcHRSZXRyeShlcnJvciwgdGhpcy5jdHgsIHRoaXMuY29uZmlnKVxuICB9XG5cbiAgcHJvdGVjdGVkIHJldHJ5RGVsYXlGb3JDdXJyZW50QXR0ZW1wdCgpOiBudW1iZXIge1xuICAgIHJldHVybiBjYWxjdWxhdGVSZXRyeURlbGF5KHRoaXMuY3R4LnJldHJ5LmF0dGVtcHQsIHRoaXMuY29uZmlnKVxuICB9XG5cbiAgcHJvdGVjdGVkIGNoZWNrSXNSZXRyeUV4aGF1c3RlZEN1cnJlbnRBdHRlbXB0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjaGVja0lzUmV0cnlFeGhhdXN0ZWQodGhpcy5jdHgucmV0cnkuYXR0ZW1wdCwgdGhpcy5jb25maWcpXG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRSZXRyeURlY2lzaW9uKGVycm9yOiB1bmtub3duKTogUmV0cnlEZWNpc2lvbiB7XG4gICAgY29uc3Qgc2hvdWxkQXR0ZW1wdFJldHJ5ID0gdGhpcy5zaG91bGRBdHRlbXB0UmV0cnkoZXJyb3IpXG5cbiAgICByZXR1cm4ge1xuICAgICAgZGVsYXk6IHNob3VsZEF0dGVtcHRSZXRyeSA/IHRoaXMucmV0cnlEZWxheUZvckN1cnJlbnRBdHRlbXB0KCkgOiAwLFxuICAgICAgaXNSZXRyeUV4aGF1c3RlZDogdGhpcy5jaGVja0lzUmV0cnlFeGhhdXN0ZWRDdXJyZW50QXR0ZW1wdCgpLFxuICAgICAgc2hvdWxkQXR0ZW1wdFJldHJ5LFxuICAgIH1cbiAgfVxufVxuIiwKICAgICJpbXBvcnQgdHlwZSB7IEJ1aWxkZXJDb25maWcgfSBmcm9tIFwiLi4vYnVpbGRlclwiXG5pbXBvcnQgeyBQYW5pYywgVW5oYW5kbGVkRXhjZXB0aW9uIH0gZnJvbSBcIi4uL2Vycm9yc1wiXG5pbXBvcnQgeyBpbnZhcmlhbnQgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHsgQmFzZUV4ZWN1dGlvbiB9IGZyb20gXCIuL2Jhc2VcIlxuXG50eXBlIFJlc29sdmVyUGFpciA9IFsodmFsdWU6IHVua25vd24pID0+IHZvaWQsIChyZWFzb24/OiB1bmtub3duKSA9PiB2b2lkXVxuXG50eXBlIFRhc2tFeGVjdXRpb25Nb2RlID0gXCJmYWlsLWZhc3RcIiB8IFwic2V0dGxlZFwiXG5cbi8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBuby1leHBsaWNpdC1hbnkgLS0gUmVxdWlyZWQgZm9yIHRhc2stbWFwIGluZmVyZW5jZVxuZXhwb3J0IHR5cGUgVGFza1JlY29yZCA9IFJlY29yZDxzdHJpbmcsIGFueT5cblxuZXhwb3J0IHR5cGUgVGFza1ZhbGlkYXRpb248VCBleHRlbmRzIFRhc2tSZWNvcmQ+ID0ge1xuICAvLyBveGxpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZXhwbGljaXQtYW55IC0tIFJlcXVpcmVkIGZvciBmdW5jdGlvbiBjb21wYXRpYmlsaXR5IHdpdGggY29udGV4dHVhbCBgdGhpc2BcbiAgW0sgaW4ga2V5b2YgVF06IFRbS10gZXh0ZW5kcyAoLi4uYXJnczogYW55W10pID0+IGFueSA/IFRbS10gOiBuZXZlclxufVxuXG4vLyBveGxpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZXhwbGljaXQtYW55IC0tIFJlcXVpcmVkIGZvciBmdW5jdGlvbiBjb21wYXRpYmlsaXR5IHdpdGggY29udGV4dHVhbCBgdGhpc2BcbmV4cG9ydCB0eXBlIFRhc2tSZXN1bHQ8VD4gPSBUIGV4dGVuZHMgKC4uLmFyZ3M6IGFueVtdKSA9PiBpbmZlciBSID8gQXdhaXRlZDxSPiA6IG5ldmVyXG5cbmV4cG9ydCB0eXBlIFJlc3VsdFByb3h5PFQgZXh0ZW5kcyBUYXNrUmVjb3JkPiA9IHtcbiAgcmVhZG9ubHkgW0sgaW4ga2V5b2YgVF06IFByb21pc2U8VGFza1Jlc3VsdDxUW0tdPj5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBUYXNrQ29udGV4dDxUIGV4dGVuZHMgVGFza1JlY29yZD4ge1xuICAkcmVzdWx0OiBSZXN1bHRQcm94eTxUPlxuICAkc2lnbmFsOiBBYm9ydFNpZ25hbFxuICAkZGlzcG9zZXI6IEFzeW5jRGlzcG9zYWJsZVN0YWNrXG59XG5cbmV4cG9ydCB0eXBlIEluZmVycmVkVGFza0NvbnRleHQ8VCBleHRlbmRzIFRhc2tSZWNvcmQ+ID0ge1xuICAkcmVzdWx0OiB7XG4gICAgcmVhZG9ubHkgW0sgaW4ga2V5b2YgVF06IFJldHVyblR5cGU8VFtLXT4gZXh0ZW5kcyBQcm9taXNlPGluZmVyIFI+XG4gICAgICA/IFByb21pc2U8Uj5cbiAgICAgIDogUHJvbWlzZTxSZXR1cm5UeXBlPFRbS10+PlxuICB9XG4gICRzaWduYWw6IEFib3J0U2lnbmFsXG4gICRkaXNwb3NlcjogQXN5bmNEaXNwb3NhYmxlU3RhY2tcbn1cblxuZXhwb3J0IHR5cGUgQWxsVmFsdWU8VCBleHRlbmRzIFRhc2tSZWNvcmQ+ID0ge1xuICBbSyBpbiBrZXlvZiBUXTogVGFza1Jlc3VsdDxUW0tdPlxufVxuXG5pbnRlcmZhY2UgQWxsQ2F0Y2hDb250ZXh0PFQgZXh0ZW5kcyBUYXNrUmVjb3JkPiB7XG4gIGZhaWxlZFRhc2s6IChrZXlvZiBUICYgc3RyaW5nKSB8IHVuZGVmaW5lZFxuICBwYXJ0aWFsOiBQYXJ0aWFsPEFsbFZhbHVlPFQ+PlxuICBzaWduYWw6IEFib3J0U2lnbmFsXG59XG5cbnR5cGUgQWxsQ2F0Y2hGbjxUIGV4dGVuZHMgVGFza1JlY29yZCwgQz4gPSAoXG4gIGVycm9yOiB1bmtub3duLFxuICBjdHg6IEFsbENhdGNoQ29udGV4dDxUPlxuKSA9PiBDIHwgUHJvbWlzZTxDPlxuXG5leHBvcnQgaW50ZXJmYWNlIEFsbE9wdGlvbnM8VCBleHRlbmRzIFRhc2tSZWNvcmQsIEM+IHtcbiAgY2F0Y2g6IEFsbENhdGNoRm48VCwgQz5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZXR0bGVkRnVsZmlsbGVkPFQ+IHtcbiAgc3RhdHVzOiBcImZ1bGZpbGxlZFwiXG4gIHZhbHVlOiBUXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2V0dGxlZFJlamVjdGVkIHtcbiAgc3RhdHVzOiBcInJlamVjdGVkXCJcbiAgcmVhc29uOiB1bmtub3duXG59XG5cbmV4cG9ydCB0eXBlIFNldHRsZWRSZXN1bHQ8VD4gPSBTZXR0bGVkRnVsZmlsbGVkPFQ+IHwgU2V0dGxlZFJlamVjdGVkXG5cbmV4cG9ydCB0eXBlIEFsbFNldHRsZWRSZXN1bHQ8VCBleHRlbmRzIFRhc2tSZWNvcmQ+ID0ge1xuICBbSyBpbiBrZXlvZiBUXTogU2V0dGxlZFJlc3VsdDxUYXNrUmVzdWx0PFRbS10+PlxufVxuXG5pbnRlcmZhY2UgUmV0cnlJbmZvIHtcbiAgYXR0ZW1wdDogbnVtYmVyXG4gIGxpbWl0OiBudW1iZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCYXNlVHJ5Q3R4IHtcbiAgc2lnbmFsPzogQWJvcnRTaWduYWxcbn1cblxuZXhwb3J0IHR5cGUgVHJ5Q3R4Rm9yPEhhc1JldHJ5IGV4dGVuZHMgYm9vbGVhbj4gPSBCYXNlVHJ5Q3R4ICZcbiAgKEhhc1JldHJ5IGV4dGVuZHMgdHJ1ZSA/IHsgcmV0cnk6IFJldHJ5SW5mbyB9IDogUmVjb3JkPG5ldmVyLCBuZXZlcj4pXG5cbmV4cG9ydCB0eXBlIFRyeUN0eCA9IFRyeUN0eEZvcjx0cnVlPlxuXG5leHBvcnQgdHlwZSBOb25Qcm9taXNlPFQ+ID0gVCBleHRlbmRzIFByb21pc2VMaWtlPHVua25vd24+ID8gbmV2ZXIgOiBUXG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBPcmNoZXN0cmF0aW9uRXhlY3V0aW9uPFRSZXN1bHQ+IGV4dGVuZHMgQmFzZUV4ZWN1dGlvbjxQcm9taXNlPFRSZXN1bHQ+PiB7XG4gIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihjb25maWc6IEJ1aWxkZXJDb25maWcpIHtcbiAgICBjb25zdCB1bnN1cHBvcnRlZFBvbGljaWVzID0gW1xuICAgICAgY29uZmlnLnJldHJ5ID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBcInJldHJ5XCIsXG4gICAgICBjb25maWcudGltZW91dCA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogXCJ0aW1lb3V0XCIsXG4gICAgXS5maWx0ZXIoKHZhbHVlKTogdmFsdWUgaXMgXCJyZXRyeVwiIHwgXCJ0aW1lb3V0XCIgPT4gdmFsdWUgIT09IHVuZGVmaW5lZClcblxuICAgIGludmFyaWFudChcbiAgICAgIHVuc3VwcG9ydGVkUG9saWNpZXMubGVuZ3RoID09PSAwLFxuICAgICAgbmV3IFBhbmljKFwiT1JDSEVTVFJBVElPTl9VTlNVUFBPUlRFRF9QT0xJQ1lcIiwge1xuICAgICAgICBtZXNzYWdlOiBgT3JjaGVzdHJhdGlvbiBkb2VzIG5vdCBzdXBwb3J0ICR7dW5zdXBwb3J0ZWRQb2xpY2llcy5qb2luKFwiIG9yIFwiKX0gcG9saWNpZXMuYCxcbiAgICAgIH0pXG4gICAgKVxuXG4gICAgc3VwZXIoe1xuICAgICAgc2lnbmFsczogY29uZmlnLnNpZ25hbHMsXG4gICAgICB3cmFwczogY29uZmlnLndyYXBzLFxuICAgIH0pXG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgZXhlY3V0ZUNvcmUoKTogUHJvbWlzZTxUUmVzdWx0PiB7XG4gICAgLy8gT3JjaGVzdHJhdGlvbiBleGVjdXRvcnMgc3RpbGwgc2hhcmUgb3V0ZXIgd3JhcHMvY2FuY2VsbGF0aW9uIGNoZWNrcyBldmVuXG4gICAgLy8gdGhvdWdoIHRoZWlyIHRhc2sgZXhlY3V0aW9uIHN0cmF0ZWdpZXMgZGlmZmVyLlxuICAgIGNvbnN0IGNvbnRyb2xCZWZvcmVFeGVjdXRpb24gPSB0aGlzLmNoZWNrRGlkQ29udHJvbEZhaWwoKVxuXG4gICAgaWYgKGNvbnRyb2xCZWZvcmVFeGVjdXRpb24pIHtcbiAgICAgIHRocm93IGNvbnRyb2xCZWZvcmVFeGVjdXRpb25cbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlVGFza3MoKVxuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGV4ZWN1dGVUYXNrcygpOiBQcm9taXNlPFRSZXN1bHQ+XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBUYXNrR3JhcGhFeGVjdXRpb25CYXNlPFxuICBUIGV4dGVuZHMgVGFza1JlY29yZCxcbiAgVENvbnRleHQgZXh0ZW5kcyBUYXNrQ29udGV4dDxUPixcbj4ge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdGFza3M6IFRcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHRhc2tOYW1lczogQXJyYXk8a2V5b2YgVCAmIHN0cmluZz5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlc3VsdHMhOiBNYXA8a2V5b2YgVCwgdW5rbm93bj5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGVycm9ycyE6IE1hcDxrZXlvZiBULCB1bmtub3duPlxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVzb2x2ZXJzITogTWFwPGtleW9mIFQsIFJlc29sdmVyUGFpcltdPlxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgaW50ZXJuYWxDb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHRhc2tTaWduYWw6IEFib3J0U2lnbmFsXG4gIHByb3RlY3RlZCByZWFkb25seSBkaXNwb3NlcjogQXN5bmNEaXNwb3NhYmxlU3RhY2sgPSBuZXcgQXN5bmNEaXNwb3NhYmxlU3RhY2soKVxuICBwcm90ZWN0ZWQgZmlyc3RSZWplY3Rpb246IHVua25vd25cblxuICBjb25zdHJ1Y3RvcihzaWduYWw6IEFib3J0U2lnbmFsIHwgdW5kZWZpbmVkLCB0YXNrczogVCkge1xuICAgIHRoaXMudGFza3MgPSB0YXNrc1xuICAgIHRoaXMudGFza05hbWVzID0gT2JqZWN0LmtleXModGFza3MpIGFzIEFycmF5PGtleW9mIFQgJiBzdHJpbmc+XG4gICAgdGhpcy5yZXN1bHRzID0gbmV3IE1hcDxrZXlvZiBULCB1bmtub3duPigpXG4gICAgdGhpcy5lcnJvcnMgPSBuZXcgTWFwPGtleW9mIFQsIHVua25vd24+KClcbiAgICB0aGlzLnJlc29sdmVycyA9IG5ldyBNYXA8a2V5b2YgVCwgUmVzb2x2ZXJQYWlyW10+KClcbiAgICB0aGlzLnRhc2tTaWduYWwgPSBzaWduYWxcbiAgICAgID8gQWJvcnRTaWduYWwuYW55KFtzaWduYWwsIHRoaXMuaW50ZXJuYWxDb250cm9sbGVyLnNpZ25hbF0pXG4gICAgICA6IHRoaXMuaW50ZXJuYWxDb250cm9sbGVyLnNpZ25hbFxuICB9XG5cbiAgYXN5bmMgW1N5bWJvbC5hc3luY0Rpc3Bvc2VdKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZGlzcG9zZXIuZGlzcG9zZUFzeW5jKClcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRUYXNrSGFuZGxlcih0YXNrTmFtZToga2V5b2YgVCkge1xuICAgIGNvbnN0IHRhc2tGbiA9IHRoaXMudGFza3NbdGFza05hbWVdXG5cbiAgICBpbnZhcmlhbnQoXG4gICAgICB0eXBlb2YgdGFza0ZuID09PSBcImZ1bmN0aW9uXCIsXG4gICAgICBuZXcgUGFuaWMoXCJUQVNLX0lOVkFMSURfSEFORExFUlwiLCB7XG4gICAgICAgIG1lc3NhZ2U6IGBUYXNrIFwiJHtTdHJpbmcodGFza05hbWUpfVwiIGlzIG5vdCBhIGZ1bmN0aW9uYCxcbiAgICAgIH0pXG4gICAgKVxuXG4gICAgcmV0dXJuIHRhc2tGbiBhcyAodGhpczogVENvbnRleHQpID0+IHVua25vd25cbiAgfVxuXG4gIHByb3RlY3RlZCBjcmVhdGVSZXN1bHRQcm94eShyZXF1ZXN0ZXJUYXNrTmFtZToga2V5b2YgVCk6IFJlc3VsdFByb3h5PFQ+IHtcbiAgICByZXR1cm4gbmV3IFByb3h5KHt9IGFzIFJlc3VsdFByb3h5PFQ+LCB7XG4gICAgICBnZXQ6IChfLCByZWZlcmVuY2VkVGFza05hbWU6IHN0cmluZykgPT5cbiAgICAgICAgdGhpcy53YWl0Rm9yUmVzdWx0KHJlZmVyZW5jZWRUYXNrTmFtZSBhcyBrZXlvZiBULCByZXF1ZXN0ZXJUYXNrTmFtZSksXG4gICAgfSlcbiAgfVxuXG4gIHByb3RlY3RlZCB3YWl0Rm9yUmVzdWx0KHRhc2tOYW1lOiBrZXlvZiBULCByZXF1ZXN0ZXJUYXNrTmFtZT86IGtleW9mIFQpOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBpZiAocmVxdWVzdGVyVGFza05hbWUgPT09IHRhc2tOYW1lKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgIG5ldyBQYW5pYyhcIlRBU0tfU0VMRl9SRUZFUkVOQ0VcIiwge1xuICAgICAgICAgIG1lc3NhZ2U6IGBUYXNrIFwiJHtTdHJpbmcodGFza05hbWUpfVwiIGNhbm5vdCBhd2FpdCBpdHMgb3duIHJlc3VsdGAsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKCFPYmplY3QuaGFzT3duKHRoaXMudGFza3MsIHRhc2tOYW1lKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICBuZXcgUGFuaWMoXCJUQVNLX1VOS05PV05fUkVGRVJFTkNFXCIsIHtcbiAgICAgICAgICBtZXNzYWdlOiBgVW5rbm93biB0YXNrIFwiJHtTdHJpbmcodGFza05hbWUpfVwiYCxcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICB9XG5cbiAgICBpZiAodGhpcy5yZXN1bHRzLmhhcyh0YXNrTmFtZSkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5yZXN1bHRzLmdldCh0YXNrTmFtZSkpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXJyb3JzLmhhcyh0YXNrTmFtZSkpIHtcbiAgICAgIGNvbnN0IHN0b3JlZEVycm9yID0gdGhpcy5tYXBTdG9yZWRFcnJvcih0aGlzLmVycm9ycy5nZXQodGFza05hbWUpKVxuXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3Qoc3RvcmVkRXJyb3IpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHF1ZXVlID0gdGhpcy5yZXNvbHZlcnMuZ2V0KHRhc2tOYW1lKVxuXG4gICAgICBpZiAocXVldWUpIHtcbiAgICAgICAgcXVldWUucHVzaChbcmVzb2x2ZSwgcmVqZWN0XSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIHRoaXMucmVzb2x2ZXJzLnNldCh0YXNrTmFtZSwgW1tyZXNvbHZlLCByZWplY3RdXSlcbiAgICB9KVxuICB9XG5cbiAgcHJvdGVjdGVkIHN0b3JlUmVzdWx0KHRhc2tOYW1lOiBrZXlvZiBULCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgIHRoaXMucmVzdWx0cy5zZXQodGFza05hbWUsIHZhbHVlKVxuICAgIHRoaXMucmVzb2x2ZVdhaXRlcnModGFza05hbWUsIHZhbHVlKVxuICB9XG5cbiAgcHJvdGVjdGVkIHN0b3JlRXJyb3IodGFza05hbWU6IGtleW9mIFQsIGVycm9yOiB1bmtub3duKTogdm9pZCB7XG4gICAgY29uc3QgbWFwcGVkRXJyb3IgPSB0aGlzLm1hcFN0b3JlZEVycm9yKGVycm9yKVxuXG4gICAgdGhpcy5lcnJvcnMuc2V0KHRhc2tOYW1lLCBtYXBwZWRFcnJvcilcbiAgICB0aGlzLnJlamVjdFdhaXRlcnModGFza05hbWUsIG1hcHBlZEVycm9yKVxuICB9XG5cbiAgcHJvdGVjdGVkIHJlc29sdmVXYWl0ZXJzKHRhc2tOYW1lOiBrZXlvZiBULCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgIGNvbnN0IGZ1bGZpbGxlZCA9IHRoaXMucmVzb2x2ZXJzLmdldCh0YXNrTmFtZSlcblxuICAgIGlmIChmdWxmaWxsZWQpIHtcbiAgICAgIGZvciAoY29uc3QgW3Jlc29sdmVdIG9mIGZ1bGZpbGxlZCkge1xuICAgICAgICByZXNvbHZlKHZhbHVlKVxuICAgICAgfVxuXG4gICAgICB0aGlzLnJlc29sdmVycy5kZWxldGUodGFza05hbWUpXG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIHJlamVjdFdhaXRlcnModGFza05hbWU6IGtleW9mIFQsIGVycm9yOiB1bmtub3duKTogdm9pZCB7XG4gICAgY29uc3QgcmVqZWN0ZWQgPSB0aGlzLnJlc29sdmVycy5nZXQodGFza05hbWUpXG5cbiAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgIGZvciAoY29uc3QgWywgcmVqZWN0XSBvZiByZWplY3RlZCkge1xuICAgICAgICByZWplY3QoZXJyb3IpXG4gICAgICB9XG5cbiAgICAgIHRoaXMucmVzb2x2ZXJzLmRlbGV0ZSh0YXNrTmFtZSlcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYWJvcnRJbnRlcm5hbChlcnJvcjogdW5rbm93bik6IHZvaWQge1xuICAgIGlmICghdGhpcy5pbnRlcm5hbENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxDb250cm9sbGVyLmFib3J0KGVycm9yKVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBvblRhc2tSZXN1bHQoX3Rhc2tOYW1lOiBrZXlvZiBULCBfdmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMudGFza3NcbiAgICB2b2lkIF90YXNrTmFtZVxuICAgIHZvaWQgX3ZhbHVlXG4gIH1cblxuICBwcm90ZWN0ZWQgb25UYXNrRXJyb3IoX3Rhc2tOYW1lOiBrZXlvZiBULCBfZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMudGFza3NcbiAgICB2b2lkIF90YXNrTmFtZVxuICAgIHZvaWQgX2Vycm9yXG4gIH1cblxuICBwcm90ZWN0ZWQgbWFwU3RvcmVkRXJyb3IoZXJyb3I6IHVua25vd24pOiBFcnJvciB7XG4gICAgdm9pZCB0aGlzLnRhc2tzXG4gICAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBVbmhhbmRsZWRFeGNlcHRpb24odW5kZWZpbmVkLCB7IGNhdXNlOiBlcnJvciB9KVxuICB9XG5cbiAgcHJvdGVjdGVkIHNob3VsZEFib3J0T25UYXNrRXJyb3IoX2Vycm9yOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgdm9pZCB0aGlzLnRhc2tzXG4gICAgdm9pZCBfZXJyb3JcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHByb3RlY3RlZCBzaG91bGRSZXRocm93VGFza0Vycm9yKF9lcnJvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgIHZvaWQgdGhpcy50YXNrc1xuICAgIHZvaWQgX2Vycm9yXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRGaXJzdFJlamVjdGlvbihlcnJvcjogdW5rbm93bik6IHZvaWQge1xuICAgIHRoaXMuZmlyc3RSZWplY3Rpb24gPz89IGVycm9yXG4gIH1cblxuICBwcm90ZWN0ZWQgYWJzdHJhY3QgY3JlYXRlVGFza0NvbnRleHQocmVzdWx0UHJveHk6IFJlc3VsdFByb3h5PFQ+KTogVENvbnRleHRcblxuICBwcm90ZWN0ZWQgYXN5bmMgcnVuVGFzayh0YXNrTmFtZToga2V5b2YgVCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0YXNrRm4gPSB0aGlzLmdldFRhc2tIYW5kbGVyKHRhc2tOYW1lKVxuICAgICAgY29uc3QgcmVzdWx0UHJveHkgPSB0aGlzLmNyZWF0ZVJlc3VsdFByb3h5KHRhc2tOYW1lKVxuICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuY3JlYXRlVGFza0NvbnRleHQocmVzdWx0UHJveHkpXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0YXNrRm4uY2FsbChjb250ZXh0KVxuXG4gICAgICB0aGlzLnN0b3JlUmVzdWx0KHRhc2tOYW1lLCByZXN1bHQpXG4gICAgICB0aGlzLm9uVGFza1Jlc3VsdCh0YXNrTmFtZSwgcmVzdWx0KVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLnNldEZpcnN0UmVqZWN0aW9uKGVycm9yKVxuICAgICAgdGhpcy5zdG9yZUVycm9yKHRhc2tOYW1lLCBlcnJvcilcbiAgICAgIHRoaXMub25UYXNrRXJyb3IodGFza05hbWUsIGVycm9yKVxuXG4gICAgICBpZiAodGhpcy5zaG91bGRBYm9ydE9uVGFza0Vycm9yKGVycm9yKSkge1xuICAgICAgICB0aGlzLmFib3J0SW50ZXJuYWwoZXJyb3IpXG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnNob3VsZFJldGhyb3dUYXNrRXJyb3IoZXJyb3IpKSB7XG4gICAgICAgIHRocm93IGVycm9yXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUYXNrRXhlY3V0aW9uPFQgZXh0ZW5kcyBUYXNrUmVjb3JkPiBleHRlbmRzIFRhc2tHcmFwaEV4ZWN1dGlvbkJhc2U8VCwgVGFza0NvbnRleHQ8VD4+IHtcbiAgcmVhZG9ubHkgI21vZGU6IFRhc2tFeGVjdXRpb25Nb2RlXG4gIHJlYWRvbmx5ICNyZXR1cm5WYWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fVxuICAjZmFpbGVkVGFzazogKGtleW9mIFQgJiBzdHJpbmcpIHwgdW5kZWZpbmVkXG4gIHByaXZhdGUgc2V0dGxlZFByb21pc2U6IFByb21pc2U8QXJyYXk8UHJvbWlzZVNldHRsZWRSZXN1bHQ8dm9pZD4+PiB8IHVuZGVmaW5lZFxuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbDogQWJvcnRTaWduYWwgfCB1bmRlZmluZWQsIHRhc2tzOiBULCBtb2RlOiBUYXNrRXhlY3V0aW9uTW9kZSkge1xuICAgIHN1cGVyKHNpZ25hbCwgdGFza3MpXG4gICAgdGhpcy4jbW9kZSA9IG1vZGVcbiAgfVxuXG4gIGdldCBmYWlsZWRUYXNrKCk6IChrZXlvZiBUICYgc3RyaW5nKSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuI2ZhaWxlZFRhc2tcbiAgfVxuXG4gIGdldCBzaWduYWwoKTogQWJvcnRTaWduYWwge1xuICAgIHJldHVybiB0aGlzLnRhc2tTaWduYWxcbiAgfVxuXG4gIGdldCByZXR1cm5WYWx1ZSgpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gICAgcmV0dXJuIHRoaXMuI3JldHVyblZhbHVlXG4gIH1cblxuICBhc3luYyBleGVjdXRlKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgICBjb25zdCBwcm9taXNlcyA9IHRoaXMudGFza05hbWVzLm1hcChhc3luYyAobmFtZSkgPT4gdGhpcy5ydW5UYXNrKG5hbWUpKVxuICAgIHRoaXMuc2V0dGxlZFByb21pc2UgPSBQcm9taXNlLmFsbFNldHRsZWQocHJvbWlzZXMpXG5cbiAgICBpZiAodGhpcy4jbW9kZSA9PT0gXCJzZXR0bGVkXCIpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2V0dGxlZFByb21pc2VcbiAgICAgIHJldHVybiB0aGlzLiNyZXR1cm5WYWx1ZVxuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcylcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRocm93IHRoaXMubWFwU3RvcmVkRXJyb3IodGhpcy5maXJzdFJlamVjdGlvbilcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy4jcmV0dXJuVmFsdWVcbiAgfVxuXG4gIGFzeW5jIHdhaXRGb3JUYXNrc1RvU2V0dGxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc2V0dGxlZFByb21pc2VcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBjcmVhdGVUYXNrQ29udGV4dChyZXN1bHRQcm94eTogUmVzdWx0UHJveHk8VD4pOiBUYXNrQ29udGV4dDxUPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICRkaXNwb3NlcjogdGhpcy5kaXNwb3NlcixcbiAgICAgICRyZXN1bHQ6IHJlc3VsdFByb3h5LFxuICAgICAgJHNpZ25hbDogdGhpcy50YXNrU2lnbmFsLFxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBvblRhc2tSZXN1bHQodGFza05hbWU6IGtleW9mIFQsIHZhbHVlOiB1bmtub3duKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuI21vZGUgPT09IFwic2V0dGxlZFwiKSB7XG4gICAgICB0aGlzLiNyZXR1cm5WYWx1ZVt0YXNrTmFtZSBhcyBzdHJpbmddID0geyBzdGF0dXM6IFwiZnVsZmlsbGVkXCIsIHZhbHVlIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy4jcmV0dXJuVmFsdWVbdGFza05hbWUgYXMgc3RyaW5nXSA9IHZhbHVlXG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIG9uVGFza0Vycm9yKHRhc2tOYW1lOiBrZXlvZiBULCBlcnJvcjogdW5rbm93bik6IHZvaWQge1xuICAgIHRoaXMuI2ZhaWxlZFRhc2sgPz89IHRhc2tOYW1lIGFzIGtleW9mIFQgJiBzdHJpbmdcblxuICAgIGlmICh0aGlzLiNtb2RlID09PSBcInNldHRsZWRcIikge1xuICAgICAgdGhpcy4jcmV0dXJuVmFsdWVbdGFza05hbWUgYXMgc3RyaW5nXSA9IHsgcmVhc29uOiBlcnJvciwgc3RhdHVzOiBcInJlamVjdGVkXCIgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBzaG91bGRBYm9ydE9uVGFza0Vycm9yKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLiNtb2RlID09PSBcImZhaWwtZmFzdFwiXG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgc2hvdWxkUmV0aHJvd1Rhc2tFcnJvcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy4jbW9kZSA9PT0gXCJmYWlsLWZhc3RcIlxuICB9XG59XG4iLAogICAgImltcG9ydCB0eXBlIHsgQnVpbGRlckNvbmZpZyB9IGZyb20gXCIuLi9idWlsZGVyXCJcbmltcG9ydCB0eXBlIHtcbiAgQWxsT3B0aW9ucyxcbiAgQWxsVmFsdWUsXG4gIEluZmVycmVkVGFza0NvbnRleHQsXG4gIFRhc2tSZWNvcmQsXG4gIFRhc2tSZXN1bHQsXG4gIFRhc2tWYWxpZGF0aW9uLFxufSBmcm9tIFwiLi9zaGFyZWRcIlxuaW1wb3J0IHsgQ2FuY2VsbGF0aW9uRXJyb3IsIFBhbmljIH0gZnJvbSBcIi4uL2Vycm9yc1wiXG5pbXBvcnQgeyBjaGVja0lzUHJvbWlzZUxpa2UgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHsgT3JjaGVzdHJhdGlvbkV4ZWN1dGlvbiwgVGFza0V4ZWN1dGlvbiB9IGZyb20gXCIuL3NoYXJlZFwiXG5cbmNsYXNzIEFsbEV4ZWN1dGlvbjxUIGV4dGVuZHMgVGFza1JlY29yZCwgQz4gZXh0ZW5kcyBPcmNoZXN0cmF0aW9uRXhlY3V0aW9uPEFsbFZhbHVlPFQ+IHwgQz4ge1xuICByZWFkb25seSAjdGFza3M6IFRcbiAgcmVhZG9ubHkgI29wdGlvbnM6IEFsbE9wdGlvbnM8VCwgQz4gfCB1bmRlZmluZWRcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IEJ1aWxkZXJDb25maWcsIHRhc2tzOiBULCBvcHRpb25zPzogQWxsT3B0aW9uczxULCBDPikge1xuICAgIHN1cGVyKGNvbmZpZylcbiAgICB0aGlzLiN0YXNrcyA9IHRhc2tzXG4gICAgdGhpcy4jb3B0aW9ucyA9IG9wdGlvbnNcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBleGVjdXRlVGFza3MoKTogUHJvbWlzZTxBbGxWYWx1ZTxUPiB8IEM+IHtcbiAgICBhd2FpdCB1c2luZyBleGVjdXRpb24gPSBuZXcgVGFza0V4ZWN1dGlvbih0aGlzLmV4ZWN1dGlvblNpZ25hbCwgdGhpcy4jdGFza3MsIFwiZmFpbC1mYXN0XCIpXG4gICAgbGV0IHJlc3VsdCE6IEFsbFZhbHVlPFQ+IHwgQ1xuICAgIGxldCB0aHJldyA9IGZhbHNlXG4gICAgbGV0IHRocm93bkVycm9yOiB1bmtub3duXG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gKGF3YWl0IHRoaXMucmFjZVdpdGhDYW5jZWxsYXRpb24oZXhlY3V0aW9uLmV4ZWN1dGUoKSkpIGFzIEFsbFZhbHVlPFQ+XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IGNvbnRyb2xBZnRlckZhaWx1cmUgPSB0aGlzLmNoZWNrRGlkQ29udHJvbEZhaWwoZXJyb3IpXG4gICAgICBjb25zdCBjYXRjaEZuID0gdGhpcy4jb3B0aW9ucz8uY2F0Y2hcblxuICAgICAgaWYgKGNvbnRyb2xBZnRlckZhaWx1cmUpIHtcbiAgICAgICAgdGhyZXcgPSB0cnVlXG4gICAgICAgIHRocm93bkVycm9yID0gY29udHJvbEFmdGVyRmFpbHVyZVxuICAgICAgfSBlbHNlIGlmIChjYXRjaEZuKSB7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgICAgICAgZmFpbGVkVGFzazogZXhlY3V0aW9uLmZhaWxlZFRhc2ssXG4gICAgICAgICAgcGFydGlhbDogZXhlY3V0aW9uLnJldHVyblZhbHVlIGFzIFBhcnRpYWw8QWxsVmFsdWU8VD4+LFxuICAgICAgICAgIHNpZ25hbDogZXhlY3V0aW9uLnNpZ25hbCxcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgbWFwcGVkID0gY2F0Y2hGbihlcnJvciwgY29udGV4dClcbiAgICAgICAgICBpZiAoY2hlY2tJc1Byb21pc2VMaWtlKG1hcHBlZCkpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHJlc3VsdCA9IChhd2FpdCB0aGlzLnJhY2VXaXRoQ2FuY2VsbGF0aW9uKFxuICAgICAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZShtYXBwZWQpLmNhdGNoKChjYXRjaEVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoY2F0Y2hFcnJvciBpbnN0YW5jZW9mIENhbmNlbGxhdGlvbkVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGNhdGNoRXJyb3JcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhbmljKFwiQUxMX0NBVENIX0hBTkRMRVJfUkVKRUNUXCIsIHsgY2F1c2U6IGNhdGNoRXJyb3IgfSlcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICApKSBhcyBDXG4gICAgICAgICAgICB9IGNhdGNoIChtYXBwZWRFcnJvcikge1xuICAgICAgICAgICAgICB0aHJldyA9IHRydWVcbiAgICAgICAgICAgICAgdGhyb3duRXJyb3IgPSBtYXBwZWRFcnJvclxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBtYXBwZWRcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGNhdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJldyA9IHRydWVcbiAgICAgICAgICB0aHJvd25FcnJvciA9IG5ldyBQYW5pYyhcIkFMTF9DQVRDSF9IQU5ETEVSX1RIUk9XXCIsIHsgY2F1c2U6IGNhdGNoRXJyb3IgfSlcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyZXcgPSB0cnVlXG4gICAgICAgIHRocm93bkVycm9yID0gZXJyb3JcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgZXhlY3V0aW9uLndhaXRGb3JUYXNrc1RvU2V0dGxlKClcbiAgICB9XG5cbiAgICBjb25zdCBjYW5jZWxsYXRpb24gPSB0aGlzLmNoZWNrRGlkQ2FuY2VsKHRocm93bkVycm9yKVxuXG4gICAgaWYgKGNhbmNlbGxhdGlvbikge1xuICAgICAgdGhyb3cgY2FuY2VsbGF0aW9uXG4gICAgfVxuXG4gICAgaWYgKHRocmV3KSB7XG4gICAgICB0aHJvdyB0aHJvd25FcnJvclxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZUFsbDxUIGV4dGVuZHMgVGFza1JlY29yZCwgQyA9IG5ldmVyPihcbiAgY29uZmlnOiBCdWlsZGVyQ29uZmlnLFxuICB0YXNrczogVCAmIFRhc2tWYWxpZGF0aW9uPE5vSW5mZXI8VD4+ICYgVGhpc1R5cGU8SW5mZXJyZWRUYXNrQ29udGV4dDxUPj4sXG4gIG9wdGlvbnM/OiBBbGxPcHRpb25zPFQsIEM+XG4pOiBQcm9taXNlPHsgW0sgaW4ga2V5b2YgVF06IFRhc2tSZXN1bHQ8VFtLXT4gfSB8IEM+IHtcbiAgdXNpbmcgZXhlY3V0aW9uID0gbmV3IEFsbEV4ZWN1dGlvbihjb25maWcsIHRhc2tzLCBvcHRpb25zKVxuICByZXR1cm4gKGF3YWl0IGV4ZWN1dGlvbi5leGVjdXRlKCkpIGFzIHsgW0sgaW4ga2V5b2YgVF06IFRhc2tSZXN1bHQ8VFtLXT4gfSB8IENcbn1cbiIsCiAgICAiaW1wb3J0IHR5cGUgeyBCdWlsZGVyQ29uZmlnIH0gZnJvbSBcIi4uL2J1aWxkZXJcIlxuaW1wb3J0IHR5cGUgeyBBbGxTZXR0bGVkUmVzdWx0LCBJbmZlcnJlZFRhc2tDb250ZXh0LCBUYXNrUmVjb3JkLCBUYXNrVmFsaWRhdGlvbiB9IGZyb20gXCIuL3NoYXJlZFwiXG5pbXBvcnQgeyBPcmNoZXN0cmF0aW9uRXhlY3V0aW9uLCBUYXNrRXhlY3V0aW9uIH0gZnJvbSBcIi4vc2hhcmVkXCJcblxuY2xhc3MgQWxsU2V0dGxlZEV4ZWN1dGlvbjxUIGV4dGVuZHMgVGFza1JlY29yZD4gZXh0ZW5kcyBPcmNoZXN0cmF0aW9uRXhlY3V0aW9uPFxuICBBbGxTZXR0bGVkUmVzdWx0PFQ+XG4+IHtcbiAgcmVhZG9ubHkgI3Rhc2tzOiBUXG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBCdWlsZGVyQ29uZmlnLCB0YXNrczogVCkge1xuICAgIHN1cGVyKGNvbmZpZylcbiAgICB0aGlzLiN0YXNrcyA9IHRhc2tzXG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgZXhlY3V0ZVRhc2tzKCk6IFByb21pc2U8QWxsU2V0dGxlZFJlc3VsdDxUPj4ge1xuICAgIGF3YWl0IHVzaW5nIGV4ZWN1dGlvbiA9IG5ldyBUYXNrRXhlY3V0aW9uKHRoaXMuZXhlY3V0aW9uU2lnbmFsLCB0aGlzLiN0YXNrcywgXCJzZXR0bGVkXCIpXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5yYWNlV2l0aENhbmNlbGxhdGlvbihleGVjdXRpb24uZXhlY3V0ZSgpKVxuICAgIGNvbnN0IGNhbmNlbGxhdGlvbiA9IHRoaXMuY2hlY2tEaWRDYW5jZWwoKVxuXG4gICAgaWYgKGNhbmNlbGxhdGlvbikge1xuICAgICAgdGhyb3cgY2FuY2VsbGF0aW9uXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdCBhcyBBbGxTZXR0bGVkUmVzdWx0PFQ+XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVBbGxTZXR0bGVkPFQgZXh0ZW5kcyBUYXNrUmVjb3JkPihcbiAgY29uZmlnOiBCdWlsZGVyQ29uZmlnLFxuICB0YXNrczogVCAmIFRhc2tWYWxpZGF0aW9uPE5vSW5mZXI8VD4+ICYgVGhpc1R5cGU8SW5mZXJyZWRUYXNrQ29udGV4dDxUPj5cbik6IFByb21pc2U8QWxsU2V0dGxlZFJlc3VsdDxUPj4ge1xuICB1c2luZyBleGVjdXRpb24gPSBuZXcgQWxsU2V0dGxlZEV4ZWN1dGlvbihjb25maWcsIHRhc2tzKVxuICByZXR1cm4gYXdhaXQgZXhlY3V0aW9uLmV4ZWN1dGUoKVxufVxuIiwKICAgICJpbXBvcnQgdHlwZSB7IEJ1aWxkZXJDb25maWcgfSBmcm9tIFwiLi4vYnVpbGRlclwiXG5pbXBvcnQgdHlwZSB7XG4gIEluZmVycmVkVGFza0NvbnRleHQsXG4gIFJlc3VsdFByb3h5LFxuICBUYXNrQ29udGV4dCxcbiAgVGFza1JlY29yZCxcbiAgVGFza1Jlc3VsdCxcbn0gZnJvbSBcIi4vc2hhcmVkXCJcbmltcG9ydCB7IFBhbmljIH0gZnJvbSBcIi4uL2Vycm9yc1wiXG5pbXBvcnQgeyBPcmNoZXN0cmF0aW9uRXhlY3V0aW9uLCBUYXNrR3JhcGhFeGVjdXRpb25CYXNlIH0gZnJvbSBcIi4vc2hhcmVkXCJcblxuZGVjbGFyZSBjb25zdCBGTE9XX0VYSVRfQlJBTkQ6IHVuaXF1ZSBzeW1ib2xcblxuZXhwb3J0IHR5cGUgRmxvd0V4aXQ8VD4gPSB7XG4gIHJlYWRvbmx5IFtGTE9XX0VYSVRfQlJBTkRdOiBUXG59XG5cbnR5cGUgRXhpdFZhbHVlPFQ+ID0gVCBleHRlbmRzIEZsb3dFeGl0PGluZmVyIFY+ID8gViA6IG5ldmVyXG5cbnR5cGUgRmxvd0V4aXRWYWx1ZTxUIGV4dGVuZHMgVGFza1JlY29yZD4gPSB7XG4gIFtLIGluIGtleW9mIFRdOiBFeGl0VmFsdWU8VGFza1Jlc3VsdDxUW0tdPj5cbn1ba2V5b2YgVF1cblxuaW50ZXJmYWNlIEZsb3dUYXNrQ29udGV4dDxUIGV4dGVuZHMgVGFza1JlY29yZD4gZXh0ZW5kcyBUYXNrQ29udGV4dDxUPiB7XG4gICRleGl0PFY+KHZhbHVlOiBWKTogRmxvd0V4aXQ8Vj5cbn1cblxuZXhwb3J0IHR5cGUgSW5mZXJyZWRGbG93VGFza0NvbnRleHQ8VCBleHRlbmRzIFRhc2tSZWNvcmQ+ID0gSW5mZXJyZWRUYXNrQ29udGV4dDxUPiAmIHtcbiAgJGV4aXQ8Vj4odmFsdWU6IFYpOiBGbG93RXhpdDxWPlxufVxuXG5leHBvcnQgdHlwZSBGbG93UmVzdWx0PFQgZXh0ZW5kcyBUYXNrUmVjb3JkPiA9IEZsb3dFeGl0VmFsdWU8VD5cblxuY2xhc3MgRmxvd0V4aXRTaWduYWwgZXh0ZW5kcyBFcnJvciB7XG4gIHJlYWRvbmx5IHZhbHVlOiB1bmtub3duXG5cbiAgY29uc3RydWN0b3IodmFsdWU6IHVua25vd24pIHtcbiAgICBzdXBlcihcIkZsb3cgZXhpdGVkXCIpXG4gICAgdGhpcy5uYW1lID0gXCJGbG93RXhpdFNpZ25hbFwiXG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlXG4gIH1cbn1cblxuY2xhc3MgRmxvd0V4ZWN1dGlvbjxUIGV4dGVuZHMgVGFza1JlY29yZD4gZXh0ZW5kcyBUYXNrR3JhcGhFeGVjdXRpb25CYXNlPFQsIEZsb3dUYXNrQ29udGV4dDxUPj4ge1xuICAjZmlyc3RSZWplY3Rpb25XYWl0ZXJzOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdXG4gICNzZXR0bGVkUHJvbWlzZTogUHJvbWlzZTxBcnJheTxQcm9taXNlU2V0dGxlZFJlc3VsdDx2b2lkPj4+IHwgdW5kZWZpbmVkXG5cbiAgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPEZsb3dSZXN1bHQ8VD4+IHtcbiAgICBjb25zdCBwcm9taXNlcyA9IHRoaXMudGFza05hbWVzLm1hcChhc3luYyAobmFtZSkgPT4gdGhpcy5ydW5UYXNrKG5hbWUpKVxuICAgIHRoaXMuI3NldHRsZWRQcm9taXNlID0gUHJvbWlzZS5hbGxTZXR0bGVkKHByb21pc2VzKVxuXG4gICAgLy8gUmFjZSBQcm9taXNlLmFsbFNldHRsZWQoKSBhZ2FpbnN0IHRoZSBmaXJzdCByZWplY3Rpb24gcmVjb3JkZWQgYnkgcnVuVGFzaygpLlxuICAgIGF3YWl0IFByb21pc2UucmFjZShbdGhpcy4jc2V0dGxlZFByb21pc2UsIHRoaXMud2FpdEZvckZpcnN0UmVqZWN0aW9uKCldKVxuXG4gICAgaWYgKHRoaXMuZmlyc3RSZWplY3Rpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHRoaXMuZmlyc3RSZWplY3Rpb24gaW5zdGFuY2VvZiBGbG93RXhpdFNpZ25hbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5maXJzdFJlamVjdGlvbi52YWx1ZSBhcyBGbG93UmVzdWx0PFQ+XG4gICAgICB9XG5cbiAgICAgIHRocm93IHRoaXMuZmlyc3RSZWplY3Rpb25cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgUGFuaWMoXCJGTE9XX05PX0VYSVRcIilcbiAgfVxuXG4gIGFzeW5jIHdhaXRGb3JUYXNrc1RvU2V0dGxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuI3NldHRsZWRQcm9taXNlXG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgc2V0Rmlyc3RSZWplY3Rpb24oZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgICBjb25zdCBoYWRGaXJzdFJlamVjdGlvbiA9IHRoaXMuZmlyc3RSZWplY3Rpb24gIT09IHVuZGVmaW5lZFxuXG4gICAgc3VwZXIuc2V0Rmlyc3RSZWplY3Rpb24oZXJyb3IpXG5cbiAgICBpZiAoaGFkRmlyc3RSZWplY3Rpb24gfHwgdGhpcy5maXJzdFJlamVjdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHJlc29sdmUgb2YgdGhpcy4jZmlyc3RSZWplY3Rpb25XYWl0ZXJzKSB7XG4gICAgICByZXNvbHZlKClcbiAgICB9XG5cbiAgICB0aGlzLiNmaXJzdFJlamVjdGlvbldhaXRlcnMgPSBbXVxuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGNyZWF0ZVRhc2tDb250ZXh0KHJlc3VsdFByb3h5OiBSZXN1bHRQcm94eTxUPik6IEZsb3dUYXNrQ29udGV4dDxUPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICRkaXNwb3NlcjogdGhpcy5kaXNwb3NlcixcbiAgICAgICRleGl0OiAodmFsdWUpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEZsb3dFeGl0U2lnbmFsKHZhbHVlKVxuICAgICAgfSxcbiAgICAgICRyZXN1bHQ6IHJlc3VsdFByb3h5LFxuICAgICAgJHNpZ25hbDogdGhpcy50YXNrU2lnbmFsLFxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBtYXBTdG9yZWRFcnJvcihlcnJvcjogdW5rbm93bik6IEVycm9yIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBGbG93RXhpdFNpZ25hbCkge1xuICAgICAgcmV0dXJuIGVycm9yXG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLm1hcFN0b3JlZEVycm9yKGVycm9yKVxuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHNob3VsZEFib3J0T25UYXNrRXJyb3IoKTogYm9vbGVhbiB7XG4gICAgdm9pZCB0aGlzLnRhc2tOYW1lc1xuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBwcml2YXRlIHdhaXRGb3JGaXJzdFJlamVjdGlvbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5maXJzdFJlamVjdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIHRoaXMuI2ZpcnN0UmVqZWN0aW9uV2FpdGVycy5wdXNoKHJlc29sdmUpXG4gICAgfSlcbiAgfVxufVxuXG5jbGFzcyBGbG93UnVubmVyRXhlY3V0aW9uPFQgZXh0ZW5kcyBUYXNrUmVjb3JkPiBleHRlbmRzIE9yY2hlc3RyYXRpb25FeGVjdXRpb248Rmxvd1Jlc3VsdDxUPj4ge1xuICByZWFkb25seSAjdGFza3M6IFRcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IEJ1aWxkZXJDb25maWcsIHRhc2tzOiBUKSB7XG4gICAgc3VwZXIoY29uZmlnKVxuICAgIHRoaXMuI3Rhc2tzID0gdGFza3NcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBleGVjdXRlVGFza3MoKTogUHJvbWlzZTxGbG93UmVzdWx0PFQ+PiB7XG4gICAgYXdhaXQgdXNpbmcgZXhlY3V0aW9uID0gbmV3IEZsb3dFeGVjdXRpb24odGhpcy5leGVjdXRpb25TaWduYWwsIHRoaXMuI3Rhc2tzKVxuICAgIGxldCByZXN1bHQhOiBGbG93UmVzdWx0PFQ+XG4gICAgbGV0IHRocmV3ID0gZmFsc2VcbiAgICBsZXQgdGhyb3duRXJyb3I6IHVua25vd25cblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSAoYXdhaXQgdGhpcy5yYWNlV2l0aENhbmNlbGxhdGlvbihleGVjdXRpb24uZXhlY3V0ZSgpKSkgYXMgRmxvd1Jlc3VsdDxUPlxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJldyA9IHRydWVcbiAgICAgIHRocm93bkVycm9yID0gZXJyb3JcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgZXhlY3V0aW9uLndhaXRGb3JUYXNrc1RvU2V0dGxlKClcbiAgICB9XG5cbiAgICBjb25zdCBjYW5jZWxsYXRpb24gPSB0aGlzLmNoZWNrRGlkQ2FuY2VsKHRocm93bkVycm9yKVxuXG4gICAgaWYgKGNhbmNlbGxhdGlvbikge1xuICAgICAgdGhyb3cgY2FuY2VsbGF0aW9uXG4gICAgfVxuXG4gICAgaWYgKHRocmV3KSB7XG4gICAgICB0aHJvdyB0aHJvd25FcnJvclxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZUZsb3c8VCBleHRlbmRzIFRhc2tSZWNvcmQ+KFxuICBjb25maWc6IEJ1aWxkZXJDb25maWcsXG4gIHRhc2tzOiBUICYgVGhpc1R5cGU8SW5mZXJyZWRGbG93VGFza0NvbnRleHQ8VD4+XG4pOiBQcm9taXNlPEZsb3dSZXN1bHQ8VD4+IHtcbiAgdXNpbmcgZXhlY3V0aW9uID0gbmV3IEZsb3dSdW5uZXJFeGVjdXRpb24oY29uZmlnLCB0YXNrcylcbiAgcmV0dXJuIGF3YWl0IGV4ZWN1dGlvbi5leGVjdXRlKClcbn1cbiIsCiAgICAiaW1wb3J0IHR5cGUgeyBCdWlsZGVyQ29uZmlnIH0gZnJvbSBcIi4uL2J1aWxkZXJcIlxuaW1wb3J0IHR5cGUgeyBCYXNlVHJ5Q3R4LCBOb25Qcm9taXNlIH0gZnJvbSBcIi4vc2hhcmVkXCJcbmltcG9ydCB7IENvbnRyb2xFcnJvciwgUGFuaWMsIFJldHJ5RXhoYXVzdGVkRXJyb3IsIFVuaGFuZGxlZEV4Y2VwdGlvbiB9IGZyb20gXCIuLi9lcnJvcnNcIlxuaW1wb3J0IHsgY2hlY2tJc1Byb21pc2VMaWtlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IEJhc2VFeGVjdXRpb24sIFJldHJ5RGlyZWN0aXZlLCB0eXBlIFJldHJ5RGVjaXNpb24sIHR5cGUgUnVubmVyRXJyb3IgfSBmcm9tIFwiLi9iYXNlXCJcblxuZXhwb3J0IHR5cGUgUnVuVHJ5Rm48VCwgQ3R4IGV4dGVuZHMgQmFzZVRyeUN0eCA9IEJhc2VUcnlDdHg+ID0gKFxuICBjdHg6IEN0eFxuKSA9PiBOb25Qcm9taXNlPFQ+IHwgUHJvbWlzZTxUPlxuXG50eXBlIFJ1bkNhdGNoRm48RT4gPSAoZXJyb3I6IHVua25vd24pID0+IE5vblByb21pc2U8RT4gfCBQcm9taXNlPEU+XG5cbmludGVyZmFjZSBSdW5Bc3luY09wdGlvbnM8VCwgRSwgQ3R4IGV4dGVuZHMgQmFzZVRyeUN0eCA9IEJhc2VUcnlDdHg+IHtcbiAgdHJ5OiBSdW5UcnlGbjxULCBDdHg+XG4gIGNhdGNoOiBSdW5DYXRjaEZuPEU+XG59XG5cbmV4cG9ydCB0eXBlIEFzeW5jUnVuSW5wdXQ8VCwgRSwgQ3R4IGV4dGVuZHMgQmFzZVRyeUN0eCA9IEJhc2VUcnlDdHg+ID1cbiAgfCBSdW5UcnlGbjxULCBDdHg+XG4gIHwgUnVuQXN5bmNPcHRpb25zPFQsIEUsIEN0eD5cblxuLyoqIEVuY2Fwc3VsYXRlcyB0aGUgc2hhcmVkIG11dGFibGUgc3RhdGUgYW5kIGxvZ2ljIGZvciBhIHNpbmdsZSBydW4gZXhlY3V0aW9uLiAqL1xuY2xhc3MgUnVuRXhlY3V0aW9uPFQsIEUsIEN0eCBleHRlbmRzIEJhc2VUcnlDdHg+IGV4dGVuZHMgQmFzZUV4ZWN1dGlvbjxcbiAgUHJvbWlzZTxUIHwgRSB8IFJ1bm5lckVycm9yPlxuPiB7XG4gICNjYXRjaEZuOiBSdW5DYXRjaEZuPEU+IHwgdW5kZWZpbmVkXG4gICN0cnlGbjogUnVuVHJ5Rm48VCwgQ3R4PlxuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogQnVpbGRlckNvbmZpZywgaW5wdXQ6IEFzeW5jUnVuSW5wdXQ8VCwgRSwgQ3R4Pikge1xuICAgIHN1cGVyKGNvbmZpZylcblxuICAgIHRoaXMuI2NhdGNoRm4gPSB0eXBlb2YgaW5wdXQgPT09IFwiZnVuY3Rpb25cIiA/IHVuZGVmaW5lZCA6IGlucHV0LmNhdGNoXG4gICAgdGhpcy4jdHJ5Rm4gPSB0eXBlb2YgaW5wdXQgPT09IFwiZnVuY3Rpb25cIiA/IGlucHV0IDogaW5wdXQudHJ5XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgZXhlY3V0ZUNvcmUoKTogUHJvbWlzZTxUIHwgRSB8IFJ1bm5lckVycm9yPiB7XG4gICAgcmV0dXJuIHRoaXMuI3J1bkF0dGVtcHRMb29wKDEpXG4gIH1cblxuICAvKiogUmVzb2x2ZSBhbiBhdHRlbXB0IGVycm9yIGludG8gZWl0aGVyIGEgdGVybWluYWwgcmVzdWx0IG9yIGEgcmV0cnkgZGVjaXNpb24uICovXG4gIGFzeW5jICNyZXNvbHZlRmFpbHVyZShlcnJvcjogdW5rbm93bik6IFByb21pc2U8RSB8IFJ1bm5lckVycm9yIHwgUmV0cnlEaXJlY3RpdmU+IHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBQYW5pYykge1xuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG5cbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBDb250cm9sRXJyb3IpIHtcbiAgICAgIHJldHVybiBlcnJvclxuICAgIH1cblxuICAgIGNvbnN0IGNvbnRyb2xFcnJvciA9IHRoaXMuY2hlY2tEaWRDb250cm9sRmFpbChlcnJvcilcblxuICAgIGlmIChjb250cm9sRXJyb3IpIHtcbiAgICAgIHJldHVybiBjb250cm9sRXJyb3JcbiAgICB9XG5cbiAgICBjb25zdCByZXRyeURlY2lzaW9uID0gdGhpcy5idWlsZFJldHJ5RGVjaXNpb24oZXJyb3IpXG5cbiAgICBpZiAocmV0cnlEZWNpc2lvbi5zaG91bGRBdHRlbXB0UmV0cnkpIHtcbiAgICAgIHJldHVybiBuZXcgUmV0cnlEaXJlY3RpdmUocmV0cnlEZWNpc2lvbilcbiAgICB9XG5cbiAgICBpZiAocmV0cnlEZWNpc2lvbi5pc1JldHJ5RXhoYXVzdGVkKSB7XG4gICAgICByZXR1cm4gbmV3IFJldHJ5RXhoYXVzdGVkRXJyb3IodW5kZWZpbmVkLCB7IGNhdXNlOiBlcnJvciB9KVxuICAgIH1cblxuICAgIGlmICghdGhpcy4jY2F0Y2hGbikge1xuICAgICAgLy8gRXZlbiB3aXRob3V0IGEgY2F0Y2ggaGFuZGxlciwgY2FuY2VsbGF0aW9uL3RpbWVvdXQgbWF5IGhhdmUgd29uIHNpbmNlXG4gICAgICAvLyB0aGUgb3JpZ2luYWwgZmFpbHVyZSB3YXMgZmlyc3Qgb2JzZXJ2ZWQuXG4gICAgICBjb25zdCBmaW5hbGl6ZUNvbnRyb2xFcnJvciA9IHRoaXMuY2hlY2tEaWRDb250cm9sRmFpbChlcnJvcilcblxuICAgICAgaWYgKGZpbmFsaXplQ29udHJvbEVycm9yKSB7XG4gICAgICAgIHJldHVybiBmaW5hbGl6ZUNvbnRyb2xFcnJvclxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFVuaGFuZGxlZEV4Y2VwdGlvbih1bmRlZmluZWQsIHsgY2F1c2U6IGVycm9yIH0pXG4gICAgfVxuXG4gICAgbGV0IG1hcHBlZDogRSB8IFByb21pc2U8RT5cblxuICAgIHRyeSB7XG4gICAgICBtYXBwZWQgPSB0aGlzLiNjYXRjaEZuKGVycm9yKVxuICAgIH0gY2F0Y2ggKGNhdGNoRXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBQYW5pYyhcIlJVTl9DQVRDSF9IQU5ETEVSX1RIUk9XXCIsIHsgY2F1c2U6IGNhdGNoRXJyb3IgfSlcbiAgICB9XG5cbiAgICBpZiAoY2hlY2tJc1Byb21pc2VMaWtlKG1hcHBlZCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJhY2UobWFwcGVkLCBlcnJvcilcbiAgICAgIH0gY2F0Y2ggKGNhdGNoRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhbmljKFwiUlVOX0NBVENIX0hBTkRMRVJfUkVKRUNUXCIsIHsgY2F1c2U6IGNhdGNoRXJyb3IgfSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb250cm9sIHN0YXRlIGNhbiBjaGFuZ2Ugd2hpbGUgdGhlIGNhdGNoIGhhbmRsZXIgcnVucywgc28gY2hlY2sgYWdhaW5cbiAgICAvLyBiZWZvcmUgcmV0dXJuaW5nIGEgbWFwcGVkIHN5bmMgdmFsdWUuXG4gICAgY29uc3QgY2F0Y2hDb250cm9sRXJyb3IgPSB0aGlzLmNoZWNrRGlkQ29udHJvbEZhaWwoZXJyb3IpXG5cbiAgICBpZiAoY2F0Y2hDb250cm9sRXJyb3IpIHtcbiAgICAgIHJldHVybiBjYXRjaENvbnRyb2xFcnJvclxuICAgIH1cblxuICAgIHJldHVybiBtYXBwZWRcbiAgfVxuXG4gIGFzeW5jICNydW5BdHRlbXB0TG9vcChhdHRlbXB0OiBudW1iZXIpOiBQcm9taXNlPFQgfCBFIHwgUnVubmVyRXJyb3I+IHtcbiAgICBsZXQgY3VycmVudEF0dGVtcHQgPSBhdHRlbXB0XG4gICAgbGV0IGN1cnJlbnREZWNpc2lvbjogUmV0cnlEZWNpc2lvbiB8IHVuZGVmaW5lZFxuXG4gICAgLy8gb3hsaW50LWRpc2FibGUtbmV4dC1saW5lIHR5cGVzY3JpcHQvbm8tdW5uZWNlc3NhcnktY29uZGl0aW9uXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IGNvbnRyb2xCZWZvcmVBdHRlbXB0ID0gdGhpcy5jaGVja0RpZENvbnRyb2xGYWlsKClcblxuICAgICAgaWYgKGNvbnRyb2xCZWZvcmVBdHRlbXB0KSB7XG4gICAgICAgIHJldHVybiBjb250cm9sQmVmb3JlQXR0ZW1wdFxuICAgICAgfVxuXG4gICAgICBpZiAoY3VycmVudERlY2lzaW9uKSB7XG4gICAgICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wXG4gICAgICAgIGNvbnN0IGRlbGF5Q29udHJvbFJlc3VsdCA9IGF3YWl0IHRoaXMud2FpdEZvclJldHJ5RGVsYXkoY3VycmVudERlY2lzaW9uLmRlbGF5KVxuXG4gICAgICAgIGlmIChkZWxheUNvbnRyb2xSZXN1bHQpIHtcbiAgICAgICAgICByZXR1cm4gZGVsYXlDb250cm9sUmVzdWx0XG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50RGVjaXNpb24gPSB1bmRlZmluZWRcbiAgICAgIH1cblxuICAgICAgdGhpcy5jdHgucmV0cnkuYXR0ZW1wdCA9IGN1cnJlbnRBdHRlbXB0XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuI3RyeUZuKHRoaXMuY3R4IGFzIHVua25vd24gYXMgQ3R4KVxuXG4gICAgICAgIGlmIChjaGVja0lzUHJvbWlzZUxpa2UocmVzdWx0KSkge1xuICAgICAgICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wXG4gICAgICAgICAgY29uc3QgcmFjZWQgPSBhd2FpdCB0aGlzLnJhY2UoUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCkpXG4gICAgICAgICAgcmV0dXJuIHJhY2VkXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlU3luY1N1Y2Nlc3MocmVzdWx0KVxuICAgICAgfSBjYXRjaCAoYXR0ZW1wdEVycm9yKSB7XG4gICAgICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wXG4gICAgICAgIGNvbnN0IHJlc29sdmVkID0gYXdhaXQgdGhpcy4jcmVzb2x2ZUZhaWx1cmUoYXR0ZW1wdEVycm9yKVxuXG4gICAgICAgIGlmICghKHJlc29sdmVkIGluc3RhbmNlb2YgUmV0cnlEaXJlY3RpdmUpKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc29sdmVkXG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50RGVjaXNpb24gPSByZXNvbHZlZC5kZWNpc2lvblxuICAgICAgICBjdXJyZW50QXR0ZW1wdCArPSAxXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleGVjdXRlUnVuPFQsIEN0eCBleHRlbmRzIEJhc2VUcnlDdHg+KFxuICBjb25maWc6IEJ1aWxkZXJDb25maWcsXG4gIGlucHV0OiBSdW5UcnlGbjxULCBDdHg+XG4pOiBQcm9taXNlPFQgfCBVbmhhbmRsZWRFeGNlcHRpb24+XG5leHBvcnQgZnVuY3Rpb24gZXhlY3V0ZVJ1bjxULCBFLCBDdHggZXh0ZW5kcyBCYXNlVHJ5Q3R4PihcbiAgY29uZmlnOiBCdWlsZGVyQ29uZmlnLFxuICBpbnB1dDogQXN5bmNSdW5JbnB1dDxULCBFLCBDdHg+XG4pOiBQcm9taXNlPFQgfCBFIHwgUnVubmVyRXJyb3I+XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZVJ1bjxULCBFLCBDdHggZXh0ZW5kcyBCYXNlVHJ5Q3R4PihcbiAgY29uZmlnOiBCdWlsZGVyQ29uZmlnLFxuICBpbnB1dDogQXN5bmNSdW5JbnB1dDxULCBFLCBDdHg+XG4pOiBQcm9taXNlPFQgfCBFIHwgUnVubmVyRXJyb3I+IHtcbiAgdXNpbmcgZXhlY3V0aW9uID0gbmV3IFJ1bkV4ZWN1dGlvbjxULCBFLCBDdHg+KGNvbmZpZywgaW5wdXQpXG4gIHJldHVybiBhd2FpdCBleGVjdXRpb24uZXhlY3V0ZSgpXG59XG4iLAogICAgImltcG9ydCB0eXBlIHsgQnVpbGRlckNvbmZpZyB9IGZyb20gXCIuLi9idWlsZGVyXCJcbmltcG9ydCB0eXBlIHsgUnVubmVyRXJyb3IgfSBmcm9tIFwiLi9iYXNlXCJcbmltcG9ydCB0eXBlIHsgQmFzZVRyeUN0eCwgTm9uUHJvbWlzZSB9IGZyb20gXCIuL3NoYXJlZFwiXG5pbXBvcnQge1xuICBDb250cm9sRXJyb3IsXG4gIFBhbmljLFxuICBSZXRyeUV4aGF1c3RlZEVycm9yLFxuICBVbmhhbmRsZWRFeGNlcHRpb24sXG4gIHR5cGUgUGFuaWNDb2RlLFxufSBmcm9tIFwiLi4vZXJyb3JzXCJcbmltcG9ydCB7IGNoZWNrSXNQcm9taXNlTGlrZSwgaW52YXJpYW50IH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IEJhc2VFeGVjdXRpb24sIFJldHJ5RGlyZWN0aXZlIH0gZnJvbSBcIi4vYmFzZVwiXG5cbmV4cG9ydCB0eXBlIFN5bmNSdW5UcnlGbjxULCBDdHggZXh0ZW5kcyBCYXNlVHJ5Q3R4ID0gQmFzZVRyeUN0eD4gPSAoY3R4OiBDdHgpID0+IE5vblByb21pc2U8VD5cbmV4cG9ydCB0eXBlIFN5bmNSdW5DYXRjaEZuPEU+ID0gKGVycm9yOiB1bmtub3duKSA9PiBOb25Qcm9taXNlPEU+XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3luY1J1bk9wdGlvbnM8VCwgRSwgQ3R4IGV4dGVuZHMgQmFzZVRyeUN0eCA9IEJhc2VUcnlDdHg+IHtcbiAgdHJ5OiBTeW5jUnVuVHJ5Rm48VCwgQ3R4PlxuICBjYXRjaDogU3luY1J1bkNhdGNoRm48RT5cbn1cblxuZXhwb3J0IHR5cGUgU3luY1J1bklucHV0PFQsIEUsIEN0eCBleHRlbmRzIEJhc2VUcnlDdHggPSBCYXNlVHJ5Q3R4PiA9XG4gIHwgU3luY1J1blRyeUZuPFQsIEN0eD5cbiAgfCBTeW5jUnVuT3B0aW9uczxULCBFLCBDdHg+XG5cbmZ1bmN0aW9uIGFzc2VydE5vdFByb21pc2VMaWtlKHZhbHVlOiB1bmtub3duLCBjb2RlOiBQYW5pY0NvZGUsIG1lc3NhZ2U/OiBzdHJpbmcpOiB2b2lkIHtcbiAgaW52YXJpYW50KFxuICAgICFjaGVja0lzUHJvbWlzZUxpa2UodmFsdWUpLFxuICAgIG5ldyBQYW5pYyhjb2RlLCBtZXNzYWdlID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiB7IG1lc3NhZ2UgfSlcbiAgKVxufVxuXG5jbGFzcyBSdW5TeW5jRXhlY3V0aW9uPFQsIEUsIEN0eCBleHRlbmRzIEJhc2VUcnlDdHg+IGV4dGVuZHMgQmFzZUV4ZWN1dGlvbjxUIHwgRSB8IFJ1bm5lckVycm9yPiB7XG4gICNjYXRjaEZuOiBTeW5jUnVuQ2F0Y2hGbjxFPiB8IHVuZGVmaW5lZFxuICAjdHJ5Rm46IFN5bmNSdW5UcnlGbjxULCBDdHg+XG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBCdWlsZGVyQ29uZmlnLCBpbnB1dDogU3luY1J1bklucHV0PFQsIEUsIEN0eD4pIHtcbiAgICBzdXBlcihjb25maWcpXG5cbiAgICB0aGlzLiNjYXRjaEZuID0gdHlwZW9mIGlucHV0ID09PSBcImZ1bmN0aW9uXCIgPyB1bmRlZmluZWQgOiBpbnB1dC5jYXRjaFxuICAgIHRoaXMuI3RyeUZuID0gdHlwZW9mIGlucHV0ID09PSBcImZ1bmN0aW9uXCIgPyBpbnB1dCA6IGlucHV0LnRyeVxuICB9XG5cbiAgb3ZlcnJpZGUgZXhlY3V0ZSgpOiBUIHwgRSB8IFJ1bm5lckVycm9yIHtcbiAgICBjb25zdCByZXN1bHQgPSBzdXBlci5leGVjdXRlKClcbiAgICBhc3NlcnROb3RQcm9taXNlTGlrZShyZXN1bHQsIFwiUlVOX1NZTkNfV1JBUFBFRF9SRVNVTFRfUFJPTUlTRVwiKVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBleGVjdXRlQ29yZSgpOiBUIHwgRSB8IFJ1bm5lckVycm9yIHtcbiAgICByZXR1cm4gdGhpcy4jcnVuQXR0ZW1wdExvb3AoMSlcbiAgfVxuXG4gICNyZXNvbHZlRmFpbHVyZShlcnJvcjogdW5rbm93bik6IEUgfCBSdW5uZXJFcnJvciB8IFJldHJ5RGlyZWN0aXZlIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBQYW5pYykge1xuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG5cbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBDb250cm9sRXJyb3IpIHtcbiAgICAgIHJldHVybiBlcnJvclxuICAgIH1cblxuICAgIGNvbnN0IGNvbnRyb2xFcnJvciA9IHRoaXMuY2hlY2tEaWRDb250cm9sRmFpbChlcnJvcilcblxuICAgIGlmIChjb250cm9sRXJyb3IpIHtcbiAgICAgIHJldHVybiBjb250cm9sRXJyb3JcbiAgICB9XG5cbiAgICBjb25zdCByZXRyeURlY2lzaW9uID0gdGhpcy5idWlsZFJldHJ5RGVjaXNpb24oZXJyb3IpXG5cbiAgICBpZiAocmV0cnlEZWNpc2lvbi5zaG91bGRBdHRlbXB0UmV0cnkpIHtcbiAgICAgIHJldHVybiBuZXcgUmV0cnlEaXJlY3RpdmUocmV0cnlEZWNpc2lvbilcbiAgICB9XG5cbiAgICBpZiAocmV0cnlEZWNpc2lvbi5pc1JldHJ5RXhoYXVzdGVkKSB7XG4gICAgICByZXR1cm4gbmV3IFJldHJ5RXhoYXVzdGVkRXJyb3IodW5kZWZpbmVkLCB7IGNhdXNlOiBlcnJvciB9KVxuICAgIH1cblxuICAgIGlmICghdGhpcy4jY2F0Y2hGbikge1xuICAgICAgLy8gRXZlbiB3aXRob3V0IGEgY2F0Y2ggaGFuZGxlciwgY2FuY2VsbGF0aW9uL3RpbWVvdXQgbWF5IGhhdmUgd29uIHNpbmNlXG4gICAgICAvLyB0aGUgb3JpZ2luYWwgZmFpbHVyZSB3YXMgZmlyc3Qgb2JzZXJ2ZWQuXG4gICAgICBjb25zdCBmaW5hbGl6ZUNvbnRyb2xFcnJvciA9IHRoaXMuY2hlY2tEaWRDb250cm9sRmFpbChlcnJvcilcblxuICAgICAgaWYgKGZpbmFsaXplQ29udHJvbEVycm9yKSB7XG4gICAgICAgIHJldHVybiBmaW5hbGl6ZUNvbnRyb2xFcnJvclxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IFVuaGFuZGxlZEV4Y2VwdGlvbih1bmRlZmluZWQsIHsgY2F1c2U6IGVycm9yIH0pXG4gICAgfVxuXG4gICAgbGV0IG1hcHBlZDogRVxuXG4gICAgdHJ5IHtcbiAgICAgIG1hcHBlZCA9IHRoaXMuI2NhdGNoRm4oZXJyb3IpXG4gICAgfSBjYXRjaCAoY2F0Y2hFcnJvcikge1xuICAgICAgdGhyb3cgbmV3IFBhbmljKFwiUlVOX1NZTkNfQ0FUQ0hfSEFORExFUl9USFJPV1wiLCB7IGNhdXNlOiBjYXRjaEVycm9yIH0pXG4gICAgfVxuXG4gICAgYXNzZXJ0Tm90UHJvbWlzZUxpa2UobWFwcGVkLCBcIlJVTl9TWU5DX0NBVENIX1BST01JU0VcIilcblxuICAgIC8vIENvbnRyb2wgc3RhdGUgY2FuIGNoYW5nZSB3aGlsZSB0aGUgY2F0Y2ggaGFuZGxlciBydW5zLCBzbyBjaGVjayBhZ2FpblxuICAgIC8vIGJlZm9yZSByZXR1cm5pbmcgYSBtYXBwZWQgc3luYyB2YWx1ZS5cbiAgICBjb25zdCBjYXRjaENvbnRyb2xFcnJvciA9IHRoaXMuY2hlY2tEaWRDb250cm9sRmFpbChlcnJvcilcblxuICAgIGlmIChjYXRjaENvbnRyb2xFcnJvcikge1xuICAgICAgcmV0dXJuIGNhdGNoQ29udHJvbEVycm9yXG4gICAgfVxuXG4gICAgcmV0dXJuIG1hcHBlZFxuICB9XG5cbiAgI3J1bkF0dGVtcHRMb29wKGF0dGVtcHQ6IG51bWJlcik6IFQgfCBFIHwgUnVubmVyRXJyb3Ige1xuICAgIGxldCBjdXJyZW50QXR0ZW1wdCA9IGF0dGVtcHRcblxuICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSB0eXBlc2NyaXB0L25vLXVubmVjZXNzYXJ5LWNvbmRpdGlvblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCBjb250cm9sQmVmb3JlQXR0ZW1wdCA9IHRoaXMuY2hlY2tEaWRDb250cm9sRmFpbCgpXG5cbiAgICAgIGlmIChjb250cm9sQmVmb3JlQXR0ZW1wdCkge1xuICAgICAgICByZXR1cm4gY29udHJvbEJlZm9yZUF0dGVtcHRcbiAgICAgIH1cblxuICAgICAgdGhpcy5jdHgucmV0cnkuYXR0ZW1wdCA9IGN1cnJlbnRBdHRlbXB0XG5cbiAgICAgIGxldCByZXN1bHQ6IE5vblByb21pc2U8VD5cblxuICAgICAgdHJ5IHtcbiAgICAgICAgcmVzdWx0ID0gdGhpcy4jdHJ5Rm4odGhpcy5jdHggYXMgdW5rbm93biBhcyBDdHgpXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zdCByZXNvbHZlZCA9IHRoaXMuI3Jlc29sdmVGYWlsdXJlKGVycm9yKVxuXG4gICAgICAgIGlmIChyZXNvbHZlZCBpbnN0YW5jZW9mIFJldHJ5RGlyZWN0aXZlKSB7XG4gICAgICAgICAgaWYgKHJlc29sdmVkLmRlY2lzaW9uLmRlbGF5ID4gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhbmljKFwiUlVOX1NZTkNfQVNZTkNfUkVUUllfUE9MSUNZXCIpXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY3VycmVudEF0dGVtcHQgKz0gMVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzb2x2ZWRcbiAgICAgIH1cblxuICAgICAgYXNzZXJ0Tm90UHJvbWlzZUxpa2UocmVzdWx0LCBcIlJVTl9TWU5DX1RSWV9QUk9NSVNFXCIpXG5cbiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVTeW5jU3VjY2VzcyhyZXN1bHQpXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleGVjdXRlUnVuU3luYzxULCBDdHggZXh0ZW5kcyBCYXNlVHJ5Q3R4PihcbiAgY29uZmlnOiBCdWlsZGVyQ29uZmlnLFxuICBpbnB1dDogU3luY1J1blRyeUZuPFQsIEN0eD5cbik6IFQgfCBVbmhhbmRsZWRFeGNlcHRpb24gfCBSdW5uZXJFcnJvclxuZXhwb3J0IGZ1bmN0aW9uIGV4ZWN1dGVSdW5TeW5jPFQsIEUsIEN0eCBleHRlbmRzIEJhc2VUcnlDdHg+KFxuICBjb25maWc6IEJ1aWxkZXJDb25maWcsXG4gIGlucHV0OiBTeW5jUnVuSW5wdXQ8VCwgRSwgQ3R4PlxuKTogVCB8IEUgfCBSdW5uZXJFcnJvclxuZXhwb3J0IGZ1bmN0aW9uIGV4ZWN1dGVSdW5TeW5jPFQsIEUsIEN0eCBleHRlbmRzIEJhc2VUcnlDdHg+KFxuICBjb25maWc6IEJ1aWxkZXJDb25maWcsXG4gIGlucHV0OiBTeW5jUnVuSW5wdXQ8VCwgRSwgQ3R4PlxuKTogVCB8IEUgfCBSdW5uZXJFcnJvciB7XG4gIC8vIEJ1aWxkZXIgdHlwaW5nIGJsb2NrcyBhc3luYy1vbmx5IHJldHJ5IHBvbGljaWVzLCBidXQgZGlyZWN0IGV4ZWN1dG9yIHVzYWdlIGFuZFxuICAvLyB1bnNhZmUgY2FzdHMgc3RpbGwgbmVlZCBhIHJ1bnRpbWUgZ3VhcmQgaGVyZS5cbiAgY29uc3QgaXNTeW5jU2FmZVJldHJ5UG9saWN5ID1cbiAgICBjb25maWcucmV0cnkgPT09IHVuZGVmaW5lZCB8fFxuICAgIChjb25maWcucmV0cnkuYmFja29mZiA9PT0gXCJjb25zdGFudFwiICYmXG4gICAgICAhY29uZmlnLnJldHJ5LmppdHRlciAmJlxuICAgICAgKGNvbmZpZy5yZXRyeS5kZWxheU1zID8/IDApIDw9IDApXG5cbiAgaW52YXJpYW50KGlzU3luY1NhZmVSZXRyeVBvbGljeSwgbmV3IFBhbmljKFwiUlVOX1NZTkNfQVNZTkNfUkVUUllfUE9MSUNZXCIpKVxuXG4gIHVzaW5nIGV4ZWN1dGlvbiA9IG5ldyBSdW5TeW5jRXhlY3V0aW9uPFQsIEUsIEN0eD4oY29uZmlnLCBpbnB1dClcbiAgcmV0dXJuIGV4ZWN1dGlvbi5leGVjdXRlKClcbn1cbiIsCiAgICAiaW1wb3J0IHR5cGUge1xuICBDYW5jZWxsYXRpb25FcnJvcixcbiAgUmV0cnlFeGhhdXN0ZWRFcnJvcixcbiAgVGltZW91dEVycm9yLFxuICBVbmhhbmRsZWRFeGNlcHRpb24sXG59IGZyb20gXCIuL2Vycm9yc1wiXG5pbXBvcnQgdHlwZSB7XG4gIEluZmVycmVkVGFza0NvbnRleHQsXG4gIFRhc2tSZWNvcmQsXG4gIFRhc2tSZXN1bHQsXG4gIFRhc2tWYWxpZGF0aW9uLFxuICBBbGxPcHRpb25zLFxuICBBbGxTZXR0bGVkUmVzdWx0LFxuICBUcnlDdHgsXG4gIFRyeUN0eEZvcixcbn0gZnJvbSBcIi4vZXhlY3V0b3JzL3NoYXJlZFwiXG5pbXBvcnQgdHlwZSB7IFJldHJ5T3B0aW9ucywgUmV0cnlQb2xpY3kgfSBmcm9tIFwiLi9tb2RpZmllcnMvcmV0cnlcIlxuaW1wb3J0IHsgUGFuaWMgfSBmcm9tIFwiLi9lcnJvcnNcIlxuaW1wb3J0IHsgZXhlY3V0ZUFsbCB9IGZyb20gXCIuL2V4ZWN1dG9ycy9hbGxcIlxuaW1wb3J0IHsgZXhlY3V0ZUFsbFNldHRsZWQgfSBmcm9tIFwiLi9leGVjdXRvcnMvYWxsLXNldHRsZWRcIlxuaW1wb3J0IHsgZXhlY3V0ZUZsb3csIHR5cGUgRmxvd1Jlc3VsdCwgdHlwZSBJbmZlcnJlZEZsb3dUYXNrQ29udGV4dCB9IGZyb20gXCIuL2V4ZWN1dG9ycy9mbG93XCJcbmltcG9ydCB7IGV4ZWN1dGVSdW4sIHR5cGUgQXN5bmNSdW5JbnB1dCwgdHlwZSBSdW5UcnlGbiB9IGZyb20gXCIuL2V4ZWN1dG9ycy9ydW5cIlxuaW1wb3J0IHsgZXhlY3V0ZVJ1blN5bmMsIHR5cGUgU3luY1J1bklucHV0LCB0eXBlIFN5bmNSdW5UcnlGbiB9IGZyb20gXCIuL2V4ZWN1dG9ycy9ydW4tc3luY1wiXG5pbXBvcnQgeyByZXRyeU9wdGlvbnMgfSBmcm9tIFwiLi9tb2RpZmllcnMvcmV0cnlcIlxuaW1wb3J0IHsgaW52YXJpYW50IH0gZnJvbSBcIi4vdXRpbHNcIlxuXG4vKipcbiAqIFdyYXBzIGFyZSBvYnNlcnZhdGlvbmFsIGhvb2tzOiB0aGV5IGNhbiBpbnNwZWN0IGV4ZWN1dGlvbiBjb250ZXh0IGFuZFxuICogc3Vycm91bmQgZXhlY3V0aW9uLCBidXQgdGhleSBtdXN0IG5vdCBtdXRhdGUgY29udGV4dCBvciByZXBsYWNlIGl0LlxuICovXG5leHBvcnQgdHlwZSBXcmFwQ3R4ID0gUmVhZG9ubHk8T21pdDxUcnlDdHgsIFwicmV0cnlcIj4+ICYge1xuICByZWFkb25seSByZXRyeTogUmVhZG9ubHk8VHJ5Q3R4W1wicmV0cnlcIl0+XG59XG5cbnR5cGUgV3JhcEZuID0gKGN0eDogV3JhcEN0eCwgbmV4dDogKCkgPT4gdW5rbm93bikgPT4gdW5rbm93blxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkZXJDb25maWcge1xuICAvKipcbiAgICogUmV0cnkgY29uZmlndXJhdGlvbiBhcHBsaWVkIHRvIHRoZSBydW4uXG4gICAqL1xuICByZXRyeT86IFJldHJ5UG9saWN5XG4gIC8qKlxuICAgKiBUaW1lb3V0IGNvbmZpZ3VyYXRpb24gYXBwbGllZCB0byB0aGUgcnVuLlxuICAgKi9cbiAgdGltZW91dD86IG51bWJlclxuICAvKipcbiAgICogQWJvcnQgc2lnbmFscyB1c2VkIHRvIGNhbmNlbCBleGVjdXRpb24uXG4gICAqL1xuICBzaWduYWxzPzogQWJvcnRTaWduYWxbXVxuICAvKipcbiAgICogV3JhcHBlciBtaWRkbGV3YXJlIGNoYWluIGFyb3VuZCBleGVjdXRpb24uXG4gICAqL1xuICB3cmFwcz86IFdyYXBGbltdXG59XG5cbnR5cGUgQ29uZmlnUnVuRXJyb3JzID0gUmV0cnlFeGhhdXN0ZWRFcnJvciB8IFRpbWVvdXRFcnJvciB8IENhbmNlbGxhdGlvbkVycm9yXG50eXBlIE9yY2hlc3RyYXRpb25NZXRob2RzID0gXCJhbGxcIiB8IFwiYWxsU2V0dGxlZFwiIHwgXCJmbG93XCJcbnR5cGUgU2lnbmFsQnVpbGRlckhpZGRlbk1ldGhvZHM8U3VwcG9ydHNPcmNoZXN0cmF0aW9uIGV4dGVuZHMgYm9vbGVhbj4gPVxuICB8IFwicnVuU3luY1wiXG4gIHwgXCJ3cmFwXCJcbiAgfCAoU3VwcG9ydHNPcmNoZXN0cmF0aW9uIGV4dGVuZHMgdHJ1ZSA/IG5ldmVyIDogT3JjaGVzdHJhdGlvbk1ldGhvZHMpXG50eXBlIEV4ZWN1dGlvbkJ1aWxkZXJTdXJmYWNlPEUgZXh0ZW5kcyBDb25maWdSdW5FcnJvcnMsIEhhc1JldHJ5IGV4dGVuZHMgYm9vbGVhbj4gPSBPbWl0PFxuICBSdW5CdWlsZGVyPEUsIEhhc1JldHJ5LCBmYWxzZT4sXG4gIE9yY2hlc3RyYXRpb25NZXRob2RzIHwgXCJ3cmFwXCJcbj5cbnR5cGUgQXN5bmNFeGVjdXRpb25CdWlsZGVyU3VyZmFjZTxFIGV4dGVuZHMgQ29uZmlnUnVuRXJyb3JzLCBIYXNSZXRyeSBleHRlbmRzIGJvb2xlYW4+ID0gT21pdDxcbiAgUnVuQnVpbGRlcjxFLCBIYXNSZXRyeSwgZmFsc2U+LFxuICBPcmNoZXN0cmF0aW9uTWV0aG9kcyB8IFwicnVuU3luY1wiIHwgXCJ3cmFwXCJcbj5cbnR5cGUgU2lnbmFsQnVpbGRlclN1cmZhY2U8XG4gIEUgZXh0ZW5kcyBDb25maWdSdW5FcnJvcnMsXG4gIEhhc1JldHJ5IGV4dGVuZHMgYm9vbGVhbixcbiAgU3VwcG9ydHNPcmNoZXN0cmF0aW9uIGV4dGVuZHMgYm9vbGVhbixcbj4gPSBPbWl0PFxuICBSdW5CdWlsZGVyPEUsIEhhc1JldHJ5LCBTdXBwb3J0c09yY2hlc3RyYXRpb24+LFxuICBTaWduYWxCdWlsZGVySGlkZGVuTWV0aG9kczxTdXBwb3J0c09yY2hlc3RyYXRpb24+XG4+XG5cbmV4cG9ydCBjbGFzcyBSdW5CdWlsZGVyPFxuICBFIGV4dGVuZHMgQ29uZmlnUnVuRXJyb3JzID0gbmV2ZXIsXG4gIEhhc1JldHJ5IGV4dGVuZHMgYm9vbGVhbiA9IGZhbHNlLFxuICBTdXBwb3J0c09yY2hlc3RyYXRpb24gZXh0ZW5kcyBib29sZWFuID0gdHJ1ZSxcbj4ge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY29uZmlnOiBCdWlsZGVyQ29uZmlnXG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBCdWlsZGVyQ29uZmlnID0ge30pIHtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZ1xuICB9XG5cbiAgcHJvdGVjdGVkIGJ1aWxkUmV0cnlDb25maWcocG9saWN5OiBSZXRyeU9wdGlvbnMpOiBCdWlsZGVyQ29uZmlnIHtcbiAgICBjb25zdCBsaW1pdCA9IHR5cGVvZiBwb2xpY3kgPT09IFwibnVtYmVyXCIgPyBwb2xpY3kgOiBwb2xpY3kubGltaXRcblxuICAgIGludmFyaWFudChOdW1iZXIuaXNGaW5pdGUobGltaXQpLCBuZXcgUGFuaWMoXCJSRVRSWV9JTlZBTElEX0xJTUlUXCIpKVxuICAgIGludmFyaWFudChsaW1pdCA+PSAwLCBuZXcgUGFuaWMoXCJSRVRSWV9JTlZBTElEX0xJTUlUXCIpKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnRoaXMuY29uZmlnLFxuICAgICAgcmV0cnk6IHJldHJ5T3B0aW9ucyhwb2xpY3kpLFxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZFRpbWVvdXRDb25maWcobXM6IG51bWJlcik6IEJ1aWxkZXJDb25maWcge1xuICAgIGludmFyaWFudChOdW1iZXIuaXNGaW5pdGUobXMpLCBuZXcgUGFuaWMoXCJUSU1FT1VUX0lOVkFMSURfTVNcIikpXG4gICAgaW52YXJpYW50KG1zID49IDAsIG5ldyBQYW5pYyhcIlRJTUVPVVRfSU5WQUxJRF9NU1wiKSlcblxuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmNvbmZpZyxcbiAgICAgIHRpbWVvdXQ6IG1zLFxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZFNpZ25hbENvbmZpZyhzaWduYWw6IEFib3J0U2lnbmFsKTogQnVpbGRlckNvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnRoaXMuY29uZmlnLFxuICAgICAgc2lnbmFsczogWy4uLih0aGlzLmNvbmZpZy5zaWduYWxzID8/IFtdKSwgc2lnbmFsXSxcbiAgICB9XG4gIH1cblxuICByZXRyeShwb2xpY3k6IG51bWJlcik6IEV4ZWN1dGlvbkJ1aWxkZXJTdXJmYWNlPEUgfCBSZXRyeUV4aGF1c3RlZEVycm9yLCB0cnVlPlxuICByZXRyeShwb2xpY3k6IFJldHJ5T3B0aW9ucyk6IEFzeW5jRXhlY3V0aW9uQnVpbGRlclN1cmZhY2U8RSB8IFJldHJ5RXhoYXVzdGVkRXJyb3IsIHRydWU+XG4gIHJldHJ5KHBvbGljeTogUmV0cnlPcHRpb25zKTogRXhlY3V0aW9uQnVpbGRlclN1cmZhY2U8RSB8IFJldHJ5RXhoYXVzdGVkRXJyb3IsIHRydWU+IHtcbiAgICByZXR1cm4gbmV3IEV4ZWN1dGlvbkJ1aWxkZXIodGhpcy5idWlsZFJldHJ5Q29uZmlnKHBvbGljeSkpXG4gIH1cblxuICB0aW1lb3V0KG1zOiBudW1iZXIpOiBBc3luY0V4ZWN1dGlvbkJ1aWxkZXJTdXJmYWNlPEUgfCBUaW1lb3V0RXJyb3IsIEhhc1JldHJ5PiB7XG4gICAgcmV0dXJuIG5ldyBFeGVjdXRpb25CdWlsZGVyKHRoaXMuYnVpbGRUaW1lb3V0Q29uZmlnKG1zKSlcbiAgfVxuXG4gIHNpZ25hbChcbiAgICBzaWduYWw6IEFib3J0U2lnbmFsXG4gICk6IFNpZ25hbEJ1aWxkZXJTdXJmYWNlPEUgfCBDYW5jZWxsYXRpb25FcnJvciwgSGFzUmV0cnksIFN1cHBvcnRzT3JjaGVzdHJhdGlvbj4ge1xuICAgIGlmICh0aGlzIGluc3RhbmNlb2YgRXhlY3V0aW9uQnVpbGRlcikge1xuICAgICAgcmV0dXJuIG5ldyBFeGVjdXRpb25CdWlsZGVyKFxuICAgICAgICB0aGlzLmJ1aWxkU2lnbmFsQ29uZmlnKHNpZ25hbClcbiAgICAgICkgYXMgdW5rbm93biBhcyBTaWduYWxCdWlsZGVyU3VyZmFjZTxFIHwgQ2FuY2VsbGF0aW9uRXJyb3IsIEhhc1JldHJ5LCBTdXBwb3J0c09yY2hlc3RyYXRpb24+XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBSdW5CdWlsZGVyKHRoaXMuYnVpbGRTaWduYWxDb25maWcoc2lnbmFsKSkgYXMgdW5rbm93biBhcyBTaWduYWxCdWlsZGVyU3VyZmFjZTxcbiAgICAgIEUgfCBDYW5jZWxsYXRpb25FcnJvcixcbiAgICAgIEhhc1JldHJ5LFxuICAgICAgU3VwcG9ydHNPcmNoZXN0cmF0aW9uXG4gICAgPlxuICB9XG5cbiAgd3JhcChmbjogV3JhcEZuKTogUnVuQnVpbGRlcjxFLCBIYXNSZXRyeSwgU3VwcG9ydHNPcmNoZXN0cmF0aW9uPiB7XG4gICAgcmV0dXJuIG5ldyBSdW5CdWlsZGVyKHtcbiAgICAgIC4uLnRoaXMuY29uZmlnLFxuICAgICAgd3JhcHM6IFsuLi4odGhpcy5jb25maWcud3JhcHMgPz8gW10pLCBmbl0sXG4gICAgfSlcbiAgfVxuXG4gIHJ1bjxUPih0cnlGbjogUnVuVHJ5Rm48VCwgVHJ5Q3R4Rm9yPEhhc1JldHJ5Pj4pOiBQcm9taXNlPFQgfCBVbmhhbmRsZWRFeGNlcHRpb24gfCBFPlxuICBydW48VCwgQz4ob3B0aW9uczogQXN5bmNSdW5JbnB1dDxULCBDLCBUcnlDdHhGb3I8SGFzUmV0cnk+Pik6IFByb21pc2U8VCB8IEMgfCBFPlxuICBydW48VCwgQz4oaW5wdXQ6IEFzeW5jUnVuSW5wdXQ8VCwgQywgVHJ5Q3R4Rm9yPEhhc1JldHJ5Pj4pIHtcbiAgICByZXR1cm4gZXhlY3V0ZVJ1bih0aGlzLmNvbmZpZywgaW5wdXQpXG4gIH1cblxuICBydW5TeW5jPFQ+KHRyeUZuOiBTeW5jUnVuVHJ5Rm48VCwgVHJ5Q3R4Rm9yPEhhc1JldHJ5Pj4pOiBUIHwgVW5oYW5kbGVkRXhjZXB0aW9uIHwgRVxuICBydW5TeW5jPFQsIEM+KGlucHV0OiBTeW5jUnVuSW5wdXQ8VCwgQywgVHJ5Q3R4Rm9yPEhhc1JldHJ5Pj4pOiBUIHwgQyB8IEVcbiAgcnVuU3luYzxULCBDPihpbnB1dDogU3luY1J1bklucHV0PFQsIEMsIFRyeUN0eEZvcjxIYXNSZXRyeT4+KSB7XG4gICAgcmV0dXJuIGV4ZWN1dGVSdW5TeW5jKHRoaXMuY29uZmlnLCBpbnB1dClcbiAgfVxuXG4gIGFsbDxUIGV4dGVuZHMgVGFza1JlY29yZCwgQyA9IG5ldmVyPihcbiAgICB0YXNrczogVCAmIFRhc2tWYWxpZGF0aW9uPE5vSW5mZXI8VD4+ICYgVGhpc1R5cGU8SW5mZXJyZWRUYXNrQ29udGV4dDxUPj4sXG4gICAgb3B0aW9ucz86IEFsbE9wdGlvbnM8VCwgQz5cbiAgKTogUHJvbWlzZTx7IFtLIGluIGtleW9mIFRdOiBUYXNrUmVzdWx0PFRbS10+IH0gfCBDPiB7XG4gICAgcmV0dXJuIGV4ZWN1dGVBbGwodGhpcy5jb25maWcsIHRhc2tzLCBvcHRpb25zKVxuICB9XG5cbiAgYWxsU2V0dGxlZDxUIGV4dGVuZHMgVGFza1JlY29yZD4oXG4gICAgdGFza3M6IFQgJiBUYXNrVmFsaWRhdGlvbjxOb0luZmVyPFQ+PiAmIFRoaXNUeXBlPEluZmVycmVkVGFza0NvbnRleHQ8VD4+XG4gICk6IFByb21pc2U8QWxsU2V0dGxlZFJlc3VsdDxUPj4ge1xuICAgIHJldHVybiBleGVjdXRlQWxsU2V0dGxlZCh0aGlzLmNvbmZpZywgdGFza3MpXG4gIH1cblxuICBmbG93PFQgZXh0ZW5kcyBUYXNrUmVjb3JkPihcbiAgICB0YXNrczogVCAmIFRoaXNUeXBlPEluZmVycmVkRmxvd1Rhc2tDb250ZXh0PFQ+PlxuICApOiBQcm9taXNlPEZsb3dSZXN1bHQ8VD4+IHtcbiAgICByZXR1cm4gZXhlY3V0ZUZsb3codGhpcy5jb25maWcsIHRhc2tzKVxuICB9XG59XG5cbmNsYXNzIEV4ZWN1dGlvbkJ1aWxkZXI8XG4gIEUgZXh0ZW5kcyBDb25maWdSdW5FcnJvcnMgPSBuZXZlcixcbiAgSGFzUmV0cnkgZXh0ZW5kcyBib29sZWFuID0gZmFsc2UsXG4+IGV4dGVuZHMgUnVuQnVpbGRlcjxFLCBIYXNSZXRyeSwgZmFsc2U+IHtcbiAgY29uc3RydWN0b3IoY29uZmlnOiBCdWlsZGVyQ29uZmlnID0ge30pIHtcbiAgICBzdXBlcihjb25maWcpXG5cbiAgICAvLyBSZXRyeS90aW1lb3V0IGNoYWlucyBtdXN0IG5vdCBzaWxlbnRseSBrZWVwIG9yY2hlc3RyYXRpb24gZW50cnlwb2ludHMgYXRcbiAgICAvLyBydW50aW1lLCBldmVuIHRob3VnaCB0aGUgdHlwZSBzdXJmYWNlIGFscmVhZHkgcmVtb3ZlcyB0aGVtLlxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHRoaXMsIHtcbiAgICAgIGFsbDogeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQsIHdyaXRhYmxlOiBmYWxzZSB9LFxuICAgICAgYWxsU2V0dGxlZDogeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQsIHdyaXRhYmxlOiBmYWxzZSB9LFxuICAgICAgZmxvdzogeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQsIHdyaXRhYmxlOiBmYWxzZSB9LFxuICAgICAgd3JhcDogeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQsIHdyaXRhYmxlOiBmYWxzZSB9LFxuICAgIH0pXG4gIH1cbn1cbiIsCiAgICAiZXhwb3J0IGZ1bmN0aW9uIGRpc3Bvc2UoKTogQXN5bmNEaXNwb3NhYmxlU3RhY2sge1xuICByZXR1cm4gbmV3IEFzeW5jRGlzcG9zYWJsZVN0YWNrKClcbn1cbiIsCiAgICAiaW1wb3J0IHsgY2hlY2tJc1Byb21pc2VMaWtlIH0gZnJvbSBcIi4vdXRpbHNcIlxuXG50eXBlIEdlblVud3JhcDxUPiA9IEV4Y2x1ZGU8QXdhaXRlZDxUPiwgRXJyb3I+XG5leHBvcnQgdHlwZSBHZW5Vc2UgPSA8VD4odmFsdWU6IFQpID0+IEdlbmVyYXRvcjxULCBHZW5VbndyYXA8VD4sIEdlblVud3JhcDxUPj5cblxudHlwZSBHZW5FcnJvcnM8VFlpZWxkPiA9IEV4dHJhY3Q8QXdhaXRlZDxUWWllbGQ+LCBFcnJvcj5cbnR5cGUgQ2hlY2tJc0FzeW5jPFRZaWVsZCwgVFJldHVybj4gPVxuICBFeHRyYWN0PFRZaWVsZCB8IFRSZXR1cm4sIFByb21pc2VMaWtlPHVua25vd24+PiBleHRlbmRzIG5ldmVyID8gZmFsc2UgOiB0cnVlXG5cbmV4cG9ydCB0eXBlIEdlblJlc3VsdDxUWWllbGQsIFRSZXR1cm4+ID1cbiAgQ2hlY2tJc0FzeW5jPFRZaWVsZCwgVFJldHVybj4gZXh0ZW5kcyB0cnVlXG4gICAgPyBQcm9taXNlPEF3YWl0ZWQ8VFJldHVybj4gfCBHZW5FcnJvcnM8VFlpZWxkPj5cbiAgICA6IEF3YWl0ZWQ8VFJldHVybj4gfCBHZW5FcnJvcnM8VFlpZWxkPlxuXG5mdW5jdGlvbiogdXNlPFQ+KHZhbHVlOiBUKTogR2VuZXJhdG9yPFQsIEdlblVud3JhcDxUPiwgR2VuVW53cmFwPFQ+PiB7XG4gIHJldHVybiB5aWVsZCB2YWx1ZVxufVxuXG5hc3luYyBmdW5jdGlvbiBleGVjdXRlQXN5bmNHZW5lcmF0b3I8VFlpZWxkLCBUUmV0dXJuPihcbiAgaXRlcmF0b3I6IEdlbmVyYXRvcjxUWWllbGQsIFRSZXR1cm4sIHVua25vd24+LFxuICBpbml0aWFsU3RlcDogSXRlcmF0b3JSZXN1bHQ8VFlpZWxkLCBUUmV0dXJuPlxuKTogUHJvbWlzZTxBd2FpdGVkPFRSZXR1cm4+IHwgR2VuRXJyb3JzPFRZaWVsZD4+IHtcbiAgbGV0IGN1cnJlbnRTdGVwID0gaW5pdGlhbFN0ZXBcblxuICAvLyBveGxpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdHlwZXNjcmlwdC9uby11bm5lY2Vzc2FyeS1jb25kaXRpb25cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBpZiAoY3VycmVudFN0ZXAuZG9uZSkge1xuICAgICAgaWYgKGNoZWNrSXNQcm9taXNlTGlrZShjdXJyZW50U3RlcC52YWx1ZSkpIHtcbiAgICAgICAgLy8gb3hsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWF3YWl0LWluLWxvb3BcbiAgICAgICAgcmV0dXJuIGF3YWl0IGN1cnJlbnRTdGVwLnZhbHVlXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjdXJyZW50U3RlcC52YWx1ZSBhcyBBd2FpdGVkPFRSZXR1cm4+XG4gICAgfVxuXG4gICAgbGV0IGN1cnJlbnRWYWx1ZTogdW5rbm93blxuXG4gICAgaWYgKGNoZWNrSXNQcm9taXNlTGlrZShjdXJyZW50U3RlcC52YWx1ZSkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIG94bGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wXG4gICAgICAgIGN1cnJlbnRWYWx1ZSA9IGF3YWl0IGN1cnJlbnRTdGVwLnZhbHVlXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjdXJyZW50U3RlcCA9IGl0ZXJhdG9yLnRocm93KGVycm9yKVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjdXJyZW50VmFsdWUgPSBjdXJyZW50U3RlcC52YWx1ZVxuICAgIH1cblxuICAgIGlmIChjdXJyZW50VmFsdWUgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgcmV0dXJuIGN1cnJlbnRWYWx1ZSBhcyBHZW5FcnJvcnM8VFlpZWxkPlxuICAgIH1cblxuICAgIGN1cnJlbnRTdGVwID0gaXRlcmF0b3IubmV4dChjdXJyZW50VmFsdWUpXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRyaXZlR2VuPFRZaWVsZCwgVFJldHVybj4oXG4gIGZhY3Rvcnk6ICh1c2VGbjogR2VuVXNlKSA9PiBHZW5lcmF0b3I8VFlpZWxkLCBUUmV0dXJuLCB1bmtub3duPlxuKTogR2VuUmVzdWx0PFRZaWVsZCwgVFJldHVybj4ge1xuICBjb25zdCBpdGVyYXRvciA9IGZhY3RvcnkodXNlKVxuXG4gIGxldCBjdXJyZW50VmFsdWU6IHVua25vd24gPSB1bmRlZmluZWRcblxuICAvLyBveGxpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdHlwZXNjcmlwdC9uby11bm5lY2Vzc2FyeS1jb25kaXRpb25cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBjb25zdCBzdGVwID0gaXRlcmF0b3IubmV4dChjdXJyZW50VmFsdWUpXG5cbiAgICBpZiAoc3RlcC5kb25lKSB7XG4gICAgICBpZiAoY2hlY2tJc1Byb21pc2VMaWtlKHN0ZXAudmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc3RlcC52YWx1ZSkgYXMgR2VuUmVzdWx0PFRZaWVsZCwgVFJldHVybj5cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHN0ZXAudmFsdWUgYXMgR2VuUmVzdWx0PFRZaWVsZCwgVFJldHVybj5cbiAgICB9XG5cbiAgICBpZiAoY2hlY2tJc1Byb21pc2VMaWtlKHN0ZXAudmFsdWUpKSB7XG4gICAgICByZXR1cm4gZXhlY3V0ZUFzeW5jR2VuZXJhdG9yKGl0ZXJhdG9yLCBzdGVwKSBhcyBHZW5SZXN1bHQ8VFlpZWxkLCBUUmV0dXJuPlxuICAgIH1cblxuICAgIGlmIChzdGVwLnZhbHVlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBzdGVwLnZhbHVlIGFzIEdlblJlc3VsdDxUWWllbGQsIFRSZXR1cm4+XG4gICAgfVxuXG4gICAgY3VycmVudFZhbHVlID0gc3RlcC52YWx1ZVxuICB9XG59XG4iLAogICAgImltcG9ydCB7IFJ1bkJ1aWxkZXIgfSBmcm9tIFwiLi9saWIvYnVpbGRlclwiXG5cbmNvbnN0IHJvb3QgPSBuZXcgUnVuQnVpbGRlcigpXG5cbmV4cG9ydCBjb25zdCBhbGw6IFJ1bkJ1aWxkZXJbXCJhbGxcIl0gPSByb290LmFsbC5iaW5kKHJvb3QpXG5leHBvcnQgY29uc3QgYWxsU2V0dGxlZDogUnVuQnVpbGRlcltcImFsbFNldHRsZWRcIl0gPSByb290LmFsbFNldHRsZWQuYmluZChyb290KVxuZXhwb3J0IGNvbnN0IGZsb3c6IFJ1bkJ1aWxkZXJbXCJmbG93XCJdID0gcm9vdC5mbG93LmJpbmQocm9vdClcbmV4cG9ydCBjb25zdCByZXRyeTogUnVuQnVpbGRlcltcInJldHJ5XCJdID0gcm9vdC5yZXRyeS5iaW5kKHJvb3QpXG5leHBvcnQgY29uc3QgcnVuOiBSdW5CdWlsZGVyW1wicnVuXCJdID0gcm9vdC5ydW4uYmluZChyb290KVxuZXhwb3J0IGNvbnN0IHJ1blN5bmM6IFJ1bkJ1aWxkZXJbXCJydW5TeW5jXCJdID0gcm9vdC5ydW5TeW5jLmJpbmQocm9vdClcbmV4cG9ydCBjb25zdCBzaWduYWw6IFJ1bkJ1aWxkZXJbXCJzaWduYWxcIl0gPSByb290LnNpZ25hbC5iaW5kKHJvb3QpXG5leHBvcnQgY29uc3QgdGltZW91dDogUnVuQnVpbGRlcltcInRpbWVvdXRcIl0gPSByb290LnRpbWVvdXQuYmluZChyb290KVxuZXhwb3J0IGNvbnN0IHdyYXA6IFJ1bkJ1aWxkZXJbXCJ3cmFwXCJdID0gcm9vdC53cmFwLmJpbmQocm9vdClcblxuZXhwb3J0IHsgZGlzcG9zZSB9IGZyb20gXCIuL2xpYi9kaXNwb3NlXCJcbmV4cG9ydCB7IGRyaXZlR2VuIGFzIGdlbiB9IGZyb20gXCIuL2xpYi9nZW5cIlxuXG5leHBvcnQg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QUFBLEVBR2xCLE9BQU8sTUFBTTtBQUFBLElBQ1gsSUFBSSxZQUFZLE1BQU07QUFBQSxNQUNwQixJQUFJLG1CQUFtQixZQUFZLEtBQUssR0FBRztBQUFBLFFBRXpDLE9BQU8sTUFBTSxZQUFZO0FBQUEsTUFDM0I7QUFBQSxNQUVBLE9BQU8sWUFBWTtBQUFBLElBQ3JCO0FBQUEsSUFFQSxJQUFJO0FBQUEsSUFFSixJQUFJLG1CQUFtQixZQUFZLEtBQUssR0FBRztBQUFBLE1BQ3pDLElBQUk7QUFBQSxRQUVGLGVBQWUsTUFBTSxZQUFZO0FBQUEsUUFDakMsT0FBTyxPQUFPO0FBQUEsUUFDZCxjQUFjLFNBQVMsTUFBTSxLQUFLO0FBQUEsUUFDbEM7QUFBQTtBQUFBLElBRUosRUFBTztBQUFBLE1BQ0wsZUFBZSxZQUFZO0FBQUE7QUFBQSxJQUc3QixJQUFJLHdCQUF3QixPQUFPO0FBQUEsTUFDakMsT0FBTztBQUFBLElBQ1Q7QUFBQSxJQUVBLGNBQWMsU0FBUyxLQUFLLFlBQVk7QUFBQSxFQUMxQztBQUFBO0FBR0ssU0FBUyxRQUF5QixDQUN2QyxTQUM0QjtBQUFBLEVBQzVCLE1BQU0sV0FBVyxRQUFRLEdBQUc7QUFBQSxFQUU1QixJQUFJLGVBQXdCO0FBQUEsRUFHNUIsT0FBTyxNQUFNO0FBQUEsSUFDWCxNQUFNLE9BQU8sU0FBUyxLQUFLLFlBQVk7QUFBQSxJQUV2QyxJQUFJLEtBQUssTUFBTTtBQUFBLE1BQ2IsSUFBSSxtQkFBbUIsS0FBSyxLQUFLLEdBQUc7QUFBQSxRQUNsQyxPQUFPLFFBQVEsUUFBUSxLQUFLLEtBQUs7QUFBQSxNQUNuQztBQUFBLE1BRUEsT0FBTyxLQUFLO0FBQUEsSUFDZDtBQUFBLElBRUEsSUFBSSxtQkFBbUIsS0FBSyxLQUFLLEdBQUc7QUFBQSxNQUNsQyxPQUFPLHNCQUFzQixVQUFVLElBQUk7QUFBQSxJQUM3QztBQUFBLElBRUEsSUFBSSxLQUFLLGlCQUFpQixPQUFPO0FBQUEsTUFDL0IsT0FBTyxLQUFLO0FBQUEsSUFDZDtBQUFBLElBRUEsZUFBZSxLQUFLO0FBQUEsRUFDdEI7QUFBQTs7O0FDbkZGLElBQU0sT0FBTyxJQUFJO0FBRVYsSUFBTSxNQUF5QixLQUFLLElBQUksS0FBSyxJQUFJO0FBQ2pELElBQU0sYUFBdUMsS0FBSyxXQUFXLEtBQUssSUFBSTtBQUN0RSxJQUFNLE9BQTJCLEtBQUssS0FBSyxLQUFLLElBQUk7QUFDcEQsSUFBTSxRQUE2QixLQUFLLE1BQU0sS0FBSyxJQUFJO0FBQ3ZELElBQU0sTUFBeUIsS0FBSyxJQUFJLEtBQUssSUFBSTtBQUNqRCxJQUFNLFVBQWlDLEtBQUssUUFBUSxLQUFLLElBQUk7QUFDN0QsSUFBTSxTQUErQixLQUFLLE9BQU8sS0FBSyxJQUFJO0FBQzFELElBQU0sVUFBaUMsS0FBSyxRQUFRLEtBQUssSUFBSTtBQUM3RCxJQUFNLE9BQTJCLEtBQUssS0FBSyxLQUFLLElBQUk7IiwKICAiZGVidWdJZCI6ICJEQUNFQTg3RTk3NDU0MEUyNjQ3NTZFMjE2NDc1NkUyMSIsCiAgIm5hbWVzIjogW10KfQ==
|