socket-function 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/SocketFunction.d.ts +1 -1
  2. package/SocketFunctionTypes.d.ts +1 -1
  3. package/hot/HotReloadController.d.ts +3 -3
  4. package/index.d.ts +25 -10
  5. package/package.json +1 -1
  6. package/require/CSSShim.d.ts +1 -1
  7. package/require/RequireController.d.ts +2 -2
  8. package/require/compileFlags.d.ts +1 -1
  9. package/require/require.d.ts +1 -1
  10. package/src/callManager.d.ts +1 -1
  11. package/test.ts +5 -11
  12. package/time/trueTimeShim.d.ts +16 -1
  13. package/time/trueTimeShim.ts +43 -7
  14. package/dist/SetProcessVariables.ts.cache +0 -9
  15. package/dist/SocketFunction.ts.cache +0 -467
  16. package/hot/dist/HotReloadController.ts.cache +0 -252
  17. package/require/dist/RequireController.ts.cache +0 -386
  18. package/require/dist/compileFlags.ts.cache +0 -41
  19. package/require/dist/extMapper.ts.cache +0 -368
  20. package/require/dist/require.ts.cache +0 -676
  21. package/src/JSONLACKS/dist/JSONLACKS.ts.cache +0 -469
  22. package/src/dist/CallFactory.ts.cache +0 -930
  23. package/src/dist/Zip.ts.cache +0 -156
  24. package/src/dist/batching.ts.cache +0 -377
  25. package/src/dist/bits.ts.cache +0 -121
  26. package/src/dist/buffers.ts.cache +0 -76
  27. package/src/dist/caching.ts.cache +0 -302
  28. package/src/dist/callHTTPHandler.ts.cache +0 -264
  29. package/src/dist/callManager.ts.cache +0 -159
  30. package/src/dist/certStore.ts.cache +0 -59
  31. package/src/dist/createSingleton.ts.cache +0 -62
  32. package/src/dist/fixLargeNetworkCalls.ts.cache +0 -17
  33. package/src/dist/forwardPort.ts.cache +0 -222
  34. package/src/dist/https.ts.cache +0 -141
  35. package/src/dist/misc.ts.cache +0 -499
  36. package/src/dist/nodeCache.ts.cache +0 -136
  37. package/src/dist/nodeProxy.ts.cache +0 -57
  38. package/src/dist/protocolNegotiation.ts.cache +0 -101
  39. package/src/dist/tlsParsing.ts.cache +0 -85
  40. package/src/dist/types.ts.cache +0 -9
  41. package/src/dist/webSocketServer.ts.cache +0 -365
  42. package/src/dist/websocketFactory.ts.cache +0 -53
  43. package/src/formatting/dist/colors.ts.cache +0 -98
  44. package/src/formatting/dist/format.ts.cache +0 -396
  45. package/src/formatting/dist/logColors.ts.cache +0 -28
  46. package/src/lz4/dist/LZ4.ts.cache +0 -53
  47. package/src/profiling/dist/getOwnTime.ts.cache +0 -100
  48. package/src/profiling/dist/measure.ts.cache +0 -338
  49. package/src/profiling/dist/stats.ts.cache +0 -202
  50. package/src/profiling/dist/statsFormat.ts.cache +0 -45
  51. package/time/dist/trueTimeShim.ts.cache +0 -707
@@ -1,930 +0,0 @@
1
- "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
26
- exports.getStats = exports.createCallFactory = exports.harvestCallTimes = exports.getPendingCallCount = exports.harvestFailedCallCount = void 0;
27
- const callManager_1 = require("./callManager");
28
- const misc_1 = require("./misc");
29
- const websocketFactory_1 = require("./websocketFactory");
30
- const SocketFunction_1 = require("../SocketFunction");
31
- const nodeCache_1 = require("./nodeCache");
32
- const caching_1 = require("./caching");
33
- const logColors_1 = require("./formatting/logColors");
34
- const fixLargeNetworkCalls_1 = require("./fixLargeNetworkCalls");
35
- const batching_1 = require("./batching");
36
- const format_1 = require("./formatting/format");
37
- const compileFlags_1 = require("../require/compileFlags");
38
- const measure_1 = require("./profiling/measure");
39
- const Zip_1 = require("./Zip");
40
- const protocolNegotiation_1 = require("./protocolNegotiation");
41
- setImmediate(() => Promise.resolve().then(() => __importStar(require("./lz4/LZ4"))));
42
- (0, compileFlags_1.setFlag)(require, "pako", "allowclient", true);
43
- // NOTE: If it is too low, and too many servers disconnect, we can easily spend 100% of our time
44
- // trying to reconnect.
45
- // (Or... maybe the delay is just waiting, and we aren't actually overloading the server?)
46
- const MIN_RETRY_DELAY = 5000;
47
- const INITIALIZE_STATE_SEQ_NUM = -1;
48
- let pendingCallCount = 0;
49
- let harvestableFailedCalls = 0;
50
- const CALL_TIMES_LIMIT = 1000 * 1000 * 10;
51
- let harvestableCallTimes = [];
52
- function harvestFailedCallCount() {
53
- let count = harvestableFailedCalls;
54
- harvestableFailedCalls = 0;
55
- return count;
56
- }
57
- exports.harvestFailedCallCount = harvestFailedCallCount;
58
- function getPendingCallCount() {
59
- return pendingCallCount;
60
- }
61
- exports.getPendingCallCount = getPendingCallCount;
62
- function harvestCallTimes() {
63
- let times = harvestableCallTimes;
64
- harvestableCallTimes = [];
65
- return times;
66
- }
67
- exports.harvestCallTimes = harvestCallTimes;
68
- (0, batching_1.runInfinitePoll)(misc_1.timeInMinute * 15, () => {
69
- if (harvestableCallTimes.length > CALL_TIMES_LIMIT) {
70
- harvestableCallTimes = harvestableCallTimes.slice(-CALL_TIMES_LIMIT);
71
- }
72
- });
73
- async function createCallFactory(webSocketBase,
74
- // The node id we are connecting to (or that connected to us)
75
- nodeId,
76
- // The node id that we were contacted on
77
- localNodeId = "") {
78
- let niceConnectionName = nodeId;
79
- const createWebsocket = (0, websocketFactory_1.createWebsocketFactory)();
80
- const registerOnce = (0, caching_1.lazy)(() => (0, nodeCache_1.registerNodeClient)(callFactory));
81
- let canReconnect = !!(0, nodeCache_1.getNodeIdLocation)(nodeId);
82
- let pendingCalls = new Map();
83
- // NOTE: It is important to make this as random as possible, to prevent
84
- // reconnections dues to a process being reset causing seqNum collisions
85
- // in return calls.
86
- let nextSeqNum = Date.now() + Math.random();
87
- // NOTE: I'm not sure if this is needed, I thought it was, but... now I think
88
- // it probably isn't...
89
- // if (webSocketBase?.readyState === 1 /* OPEN */ && webSocketBase.ping) {
90
- // // Heartbeat loop, otherwise onDisconnect is never called.
91
- // ((async () => {
92
- // while (webSocketBase?.readyState === 1 /* OPEN */ && webSocketBase.ping) {
93
- // await delay(1000 * 60);
94
- // webSocketBase.ping?.();
95
- // }
96
- // }))().catch(() => { });
97
- // }
98
- let lastConnectionAttempt = 0;
99
- let callerContext = {
100
- nodeId,
101
- localNodeId
102
- };
103
- let disconnectCallbacks = new Set();
104
- function onNextDisconnect(callback) {
105
- disconnectCallbacks.add(callback);
106
- }
107
- let callFactory = {
108
- nodeId,
109
- lastClosed: 0,
110
- connectionId: { nodeId },
111
- receivedInitializeState: undefined,
112
- onNextDisconnect,
113
- disconnect() {
114
- canReconnect = false;
115
- callFactory.closedForever = true;
116
- if (webSocketPromise) {
117
- webSocketPromise.then(ws => ws.close()).catch(() => { });
118
- }
119
- },
120
- async performCall(call) {
121
- var _a;
122
- let seqNum = nextSeqNum++;
123
- let fullCall = {
124
- nodeId,
125
- isReturn: false,
126
- args: call.args,
127
- classGuid: call.classGuid,
128
- functionName: call.functionName,
129
- seqNum,
130
- };
131
- let data;
132
- let originalArgs = call.args;
133
- let time = Date.now();
134
- let sendStats = {
135
- uncompressedSize: 0,
136
- compressedSize: 0,
137
- };
138
- try {
139
- if ((_a = callFactory.receivedInitializeState) === null || _a === void 0 ? void 0 : _a.supportsLZ4) {
140
- let compressMode = (0, callManager_1.shouldCompressCall)(fullCall);
141
- // If it's undefined, then we compress it. We basically always want to compress from now on, because LZ4 is so fast.
142
- if (compressMode !== false) {
143
- fullCall.args = await compressObjLZ4(fullCall.args, sendStats);
144
- fullCall.isArgsCompressed = "LZ4";
145
- }
146
- }
147
- else {
148
- if ((0, callManager_1.shouldCompressCall)(fullCall)) {
149
- fullCall.args = await compressObj(fullCall.args, sendStats);
150
- fullCall.isArgsCompressed = "zip";
151
- }
152
- }
153
- let dataMaybePromise = SocketFunction_1.SocketFunction.WIRE_SERIALIZER.serialize(fullCall);
154
- if (dataMaybePromise instanceof Promise) {
155
- data = await dataMaybePromise;
156
- }
157
- else {
158
- data = dataMaybePromise;
159
- }
160
- if (!sendStats.compressedSize) {
161
- let totalSize = 0;
162
- for (let d of data) {
163
- totalSize += d.length;
164
- }
165
- sendStats.uncompressedSize = totalSize;
166
- sendStats.compressedSize = totalSize;
167
- }
168
- addSendStats(sendStats);
169
- }
170
- catch (e) {
171
- throw new Error(`Error serializing data for call ${call.classGuid}.${call.functionName}\n${e.stack}`);
172
- }
173
- time = Date.now() - time;
174
- let size = data.map(x => x.length).reduce((a, b) => a + b, 0);
175
- if (time > SocketFunction_1.SocketFunction.WIRE_WARN_TIME) {
176
- console.log((0, logColors_1.red)(`Slow serialize, took ${(0, format_1.formatTime)(time)} to serialize ${(0, format_1.formatNumber)(size)} bytes. For ${call.classGuid}.${call.functionName}`));
177
- }
178
- if (size > SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE * 1.5) {
179
- let splitArgIndex = originalArgs.findIndex(fixLargeNetworkCalls_1.isSplitableArray);
180
- if (splitArgIndex >= 0) {
181
- console.log((0, logColors_1.yellow)(`Splitting large call due to large args: ${call.classGuid}.${call.functionName}`));
182
- let SPLIT_GROUPS = 10;
183
- let splitArg = originalArgs[splitArgIndex];
184
- let subCalls = (0, misc_1.list)(SPLIT_GROUPS).map(index => {
185
- let start = Math.floor(index / SPLIT_GROUPS * splitArg.length);
186
- let end = Math.floor((index + 1) / SPLIT_GROUPS * splitArg.length);
187
- return splitArg.slice(start, end);
188
- }).filter(x => x.length > 0);
189
- let calls = subCalls.map(async (splitList) => {
190
- let subCall = { ...call };
191
- subCall.args = subCall.args.slice();
192
- subCall.args[splitArgIndex] = (0, fixLargeNetworkCalls_1.markArrayAsSplitable)(splitList);
193
- await callFactory.performCall(subCall);
194
- });
195
- await Promise.allSettled(calls);
196
- await Promise.all(calls);
197
- // Eh... we COULD return the array of results, but... then the result would sometimes be an array,
198
- // some times not, so, it is better to return a string which will make it more clear why it sometimes varies.
199
- return "CALLS_SPLIT_DUE_TO_LARGE_ARGS";
200
- }
201
- throw new Error(`Call too large to send (${call.classGuid}.${call.functionName}, size: ${(0, format_1.formatNumber)(size)} > ${(0, format_1.formatNumber)(SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE)}). If you need to handle very large static data use some external service, such as Backblaze B2 or AWS S3. Or consider fragmenting data at an application level, because sending large data will cause large lag spikes for other clients using this server. Or, if absolutely required, set SocketFunction.MAX_MESSAGE_SIZE to a higher value.`);
202
- }
203
- let resultPromise = new Promise((resolve, reject) => {
204
- let startTime = Date.now();
205
- pendingCallCount++;
206
- let callback = (result) => {
207
- pendingCallCount--;
208
- pendingCalls.delete(seqNum);
209
- harvestableCallTimes.push({ start: startTime, end: Date.now(), });
210
- if (result.error) {
211
- reject((0, misc_1.convertErrorStackToError)(result.error));
212
- }
213
- else {
214
- resolve(result.result);
215
- }
216
- };
217
- pendingCalls.set(seqNum, { callback, data, call: fullCall });
218
- });
219
- {
220
- let resultSize = data.map(x => x.length).reduce((a, b) => a + b, 0);
221
- for (let callback of SocketFunction_1.SocketFunction.trackMessageSizes.upload) {
222
- callback(resultSize);
223
- }
224
- if (SocketFunction_1.SocketFunction.logMessages) {
225
- let fncHack = "";
226
- if (call.functionName === "addCall") {
227
- let arg = originalArgs[0];
228
- fncHack = `.${arg.DomainName}.${arg.ModuleId}.${arg.FunctionId}`;
229
- }
230
- console.log(`SIZE\t${((0, misc_1.formatNumberSuffixed)(resultSize) + `B`).padEnd(4, " ")}\t${(0, format_1.formatNumber)(data.length)} buffers\tREMOTE CALL\t${call.classGuid}.${call.functionName}${fncHack} at ${Date.now()}`);
231
- }
232
- }
233
- // If sending OR resultPromise throws, we want to error out. This solves some issues with resultPromise
234
- // erroring out first, which is before we await it, which makes NodeJS angry (unhandled promise rejection).
235
- // Also, technically, we could receive the result before we finish sending, in which case, we might
236
- // as well return it immediately.
237
- await Promise.race([send(data), resultPromise]);
238
- return await resultPromise;
239
- }
240
- };
241
- let webSocketPromise;
242
- let hasEverConnected = false;
243
- if (webSocketBase) {
244
- webSocketPromise = Promise.resolve(webSocketBase);
245
- await initializeWebsocket(webSocketBase);
246
- }
247
- async function initializeWebsocket(newWebSocket, skipCloseHandling = false) {
248
- registerOnce();
249
- callFactory.receivedInitializeState = undefined;
250
- function onClose(error) {
251
- // We try various connections, and if they fail, we will just try other node IDs until we finally do connect, and then we stick with that nodeId, and when it disconnects we need to handle disconnections normally.
252
- if (skipCloseHandling && !hasEverConnected) {
253
- return;
254
- }
255
- callFactory.connectionId = { nodeId };
256
- callFactory.lastClosed = Date.now();
257
- callFactory.isConnected = false;
258
- webSocketPromise = undefined;
259
- if (!canReconnect) {
260
- callFactory.closedForever = true;
261
- }
262
- for (let [key, call] of pendingCalls) {
263
- harvestableFailedCalls++;
264
- pendingCalls.delete(key);
265
- call.callback({
266
- isReturn: true,
267
- result: undefined,
268
- error: error,
269
- seqNum: call.call.seqNum,
270
- });
271
- }
272
- let callbacks = disconnectCallbacks;
273
- disconnectCallbacks = new Set();
274
- for (let callback of callbacks) {
275
- try {
276
- callback();
277
- }
278
- catch (_a) { }
279
- }
280
- }
281
- newWebSocket.addEventListener("error", e => {
282
- // NOTE: No more logging, as we throw, so the caller should be logging the
283
- // error (or swallowing it, if that is what it wants to do).
284
- //console.log(`Websocket error for ${niceConnectionName}`, e.message);
285
- onClose(new Error(`Connection error for ${niceConnectionName}: ${e.message}`).stack);
286
- });
287
- newWebSocket.addEventListener("close", async () => {
288
- //console.log(`Websocket closed ${niceConnectionName}`);
289
- onClose(new Error(`Connection closed to ${niceConnectionName}`).stack);
290
- });
291
- newWebSocket.addEventListener("message", onMessage);
292
- if (newWebSocket.readyState === 0 /* CONNECTING */) {
293
- await new Promise(resolve => {
294
- newWebSocket.addEventListener("open", () => {
295
- if (!SocketFunction_1.SocketFunction.silent) {
296
- console.log(`Connection established to ${niceConnectionName}`);
297
- }
298
- callFactory.isConnected = true;
299
- hasEverConnected = true;
300
- resolve();
301
- });
302
- newWebSocket.addEventListener("close", () => resolve());
303
- newWebSocket.addEventListener("error", () => resolve());
304
- });
305
- }
306
- else if (newWebSocket.readyState === 1 /* OPEN */) {
307
- callFactory.isConnected = true;
308
- hasEverConnected = true;
309
- }
310
- else {
311
- onClose(new Error(`Websocket received in closed state`).stack);
312
- }
313
- if (callFactory.lastClosed && callFactory.isConnected) {
314
- console.log(`Successfully reconnected to ${nodeId}, which has been closed for ${(0, format_1.formatTime)(Date.now() - callFactory.lastClosed)}`, { nodeId });
315
- }
316
- if (callFactory.isConnected && newWebSocket.protocol) {
317
- let decoded = (0, protocolNegotiation_1.decodeProtocol)(newWebSocket.protocol);
318
- if (decoded) {
319
- callFactory.receivedInitializeState = {
320
- supportsLZ4: decoded.flags.serverLZ4,
321
- };
322
- callFactory.protocolNegotiated = true;
323
- if (SocketFunction_1.SocketFunction.logMessages) {
324
- console.log((0, logColors_1.green)(`Negotiated protocol with ${niceConnectionName}: target=${decoded.target}, clientLZ4=${decoded.flags.clientLZ4}, serverLZ4=${decoded.flags.serverLZ4}`));
325
- }
326
- }
327
- }
328
- }
329
- const BASE_LENGTH_OFFSET = 324432461592612;
330
- let sendInSerial = (0, batching_1.runInSerial)(async (val) => val());
331
- async function sendRaw(data) {
332
- if (!webSocketPromise) {
333
- if (canReconnect) {
334
- webSocketPromise = tryToReconnect();
335
- }
336
- else {
337
- throw new Error(`Cannot send data to ${niceConnectionName} as the connection has closed`);
338
- }
339
- }
340
- let webSocket = await webSocketPromise;
341
- await sendInSerial(async () => {
342
- for (let d of data) {
343
- if (d.length > 1000 * 1000 * 10) {
344
- console.log(`Sending large packet ${(0, format_1.formatNumber)(d.length)}B to ${nodeId} at ${Date.now()}`);
345
- }
346
- // NOTE: If our latency is 500ms, with 10MB/s, then we need a high water
347
- // mark of at least 5MB, otherwise our connection is slowed down.
348
- // - Using the actual high water mark is too difficult, as we receive incoming connections.
349
- // This is also easier to configure, and we can dynamically change it if we have to.
350
- // NOTE: In practice we only hit this when sending large Buffers (~30MB), so low values
351
- // are equivalent to waiting for drain. We want to avoid waiting for drain, so we use a high value.
352
- const maxWriteBuffer = 128 * 1024 * 1024;
353
- webSocket.send(d);
354
- let socket = webSocket._socket;
355
- if (socket) {
356
- while (socket.writableLength > maxWriteBuffer) {
357
- // NOTE: Waiting 1ms probably waits more like 16ms.
358
- await new Promise(r => setTimeout(r, 1));
359
- }
360
- }
361
- }
362
- });
363
- }
364
- async function send(data) {
365
- await sendRaw([
366
- (data.length + BASE_LENGTH_OFFSET).toString(),
367
- ...data,
368
- ]);
369
- }
370
- async function sendWithHeader(data, header) {
371
- if (data.some(x => x.length > SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE * 1.5)) {
372
- if (header.type === "Buffer" || header.type === "Buffer[]") {
373
- header.bufferLengths = data.map(x => x.length);
374
- let fitBuffers = [];
375
- for (let buf of data) {
376
- if (buf.length > SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE) {
377
- let offset = 0;
378
- while (offset < buf.length) {
379
- fitBuffers.push(buf.slice(offset, offset + SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE));
380
- offset += SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE;
381
- }
382
- }
383
- else {
384
- fitBuffers.push(buf);
385
- }
386
- }
387
- data = fitBuffers;
388
- header.bufferCount = fitBuffers.length;
389
- }
390
- else {
391
- throw new Error(`Cannot send large amounts of data unless we are returning Buffer or Buffer[]`);
392
- }
393
- }
394
- // if (totalResultSize > SocketFunction.MAX_MESSAGE_SIZE * 1.5) {
395
- // Split up Buffer[] if they are too large
396
- await sendRaw([
397
- JSON.stringify(header),
398
- ...data,
399
- ]);
400
- }
401
- // IMPORTANT! NEVER allow for reconnection of client ids. A lot of code depends on the fact that clients will reconnect with a new client node id when they disconnect!
402
- async function tryToReconnect() {
403
- // Don't try to reconnect too often!
404
- let timeSinceLastAttempt = Date.now() - lastConnectionAttempt;
405
- if (timeSinceLastAttempt < MIN_RETRY_DELAY) {
406
- await new Promise(r => setTimeout(r, MIN_RETRY_DELAY - timeSinceLastAttempt));
407
- }
408
- lastConnectionAttempt = Date.now();
409
- // Try alternates, and if any work, use them.
410
- try {
411
- let alternates = await SocketFunction_1.SocketFunction.GET_ALTERNATE_NODE_IDS(nodeId);
412
- if (alternates) {
413
- for (let alternateNodeId of alternates) {
414
- let newWebSocket = createWebsocket(alternateNodeId, (0, protocolNegotiation_1.proposeProtocols)((0, misc_1.isNode)() ? nodeId : undefined, { lz4: true }));
415
- await initializeWebsocket(newWebSocket, true);
416
- if (callFactory.isConnected) {
417
- return newWebSocket;
418
- }
419
- }
420
- }
421
- }
422
- catch (e) {
423
- console.error("Error getting alternate node IDs", e);
424
- }
425
- let newWebSocket = createWebsocket(nodeId, (0, protocolNegotiation_1.proposeProtocols)(!SocketFunction_1.SocketFunction.isClient() ? nodeId : undefined, { lz4: true }));
426
- await initializeWebsocket(newWebSocket);
427
- return newWebSocket;
428
- }
429
- let pendingCall;
430
- async function processPendingCall() {
431
- var _a, _b;
432
- if (!pendingCall)
433
- throw new Error(`No pending call`);
434
- let currentCall = pendingCall;
435
- pendingCall = undefined;
436
- let currentBuffers = currentCall.buffers;
437
- let call;
438
- let resultSize;
439
- let time = Date.now();
440
- if (currentCall.type === "Buffer" || currentCall.type === "Buffer[]") {
441
- let result = currentBuffers;
442
- if (currentCall.bufferLengths) {
443
- let pendingBuffers = currentBuffers;
444
- function takeBuffer(len) {
445
- let lenLeft = len;
446
- let buffers = [];
447
- while (lenLeft > 0) {
448
- let buf = currentBuffers.shift();
449
- if (!buf) {
450
- throw new Error(`Not enough buffers received.`);
451
- }
452
- if (buf.length > lenLeft) {
453
- buffers.push(buf.slice(0, lenLeft));
454
- currentBuffers.unshift(buf.slice(lenLeft));
455
- break;
456
- }
457
- else {
458
- buffers.push(buf);
459
- lenLeft -= buf.length;
460
- }
461
- }
462
- if (buffers.length === 1) {
463
- return buffers[0];
464
- }
465
- return Buffer.concat(buffers);
466
- }
467
- result = currentCall.bufferLengths.map(takeBuffer);
468
- if (pendingBuffers.length > 0) {
469
- throw new Error(`Received too many buffers.`);
470
- }
471
- }
472
- resultSize = result.map(x => x.length).reduce((a, b) => a + b, 0);
473
- if (currentCall.type === "Buffer") {
474
- if (result.length === 1) {
475
- result = result[0];
476
- }
477
- else {
478
- result = Buffer.concat(result);
479
- }
480
- }
481
- call = {
482
- ...currentCall.metadata,
483
- result,
484
- };
485
- }
486
- else {
487
- resultSize = currentBuffers.map(x => x.length).reduce((a, b) => a + b, 0);
488
- call = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.deserialize(currentBuffers);
489
- }
490
- let parseTime = Date.now() - time;
491
- for (let callback of SocketFunction_1.SocketFunction.trackMessageSizes.download) {
492
- callback(resultSize);
493
- }
494
- let receiveStats = {
495
- uncompressedSize: resultSize,
496
- compressedSize: resultSize,
497
- };
498
- let sendStats = {
499
- uncompressedSize: 0,
500
- compressedSize: 0,
501
- };
502
- if (call.isReturn) {
503
- // Tolerate the legacy initialize packet from old peers — silently
504
- // ignore so it doesn't get logged as an unknown call. Our actual
505
- // initialize state comes from Sec-WebSocket-Protocol negotiation.
506
- if (call.seqNum === INITIALIZE_STATE_SEQ_NUM) {
507
- return;
508
- }
509
- let callbackObj = pendingCalls.get(call.seqNum);
510
- if (parseTime > SocketFunction_1.SocketFunction.WIRE_WARN_TIME) {
511
- console.log((0, logColors_1.red)(`Slow parse, took ${parseTime}ms to parse ${resultSize} bytes, for receiving result of call to ${callbackObj === null || callbackObj === void 0 ? void 0 : callbackObj.call.classGuid}.${callbackObj === null || callbackObj === void 0 ? void 0 : callbackObj.call.functionName}`));
512
- }
513
- if (!callbackObj) {
514
- console.log((0, logColors_1.blue)(`Got return for unknown call ${call.seqNum} (created at time ${new Date(call.seqNum)}), ${nodeId} / ${localNodeId}`));
515
- return;
516
- }
517
- if (SocketFunction_1.SocketFunction.logMessages) {
518
- let call = callbackObj.call;
519
- console.log(`SIZE\t${((0, misc_1.formatNumberSuffixed)(resultSize) + "B").padEnd(4, " ")}\t${(0, format_1.formatNumber)(currentBuffers.length)} buffers\tRETURN\t${call.classGuid}.${call.functionName} at ${Date.now()}, (${nodeId} / ${localNodeId})`);
520
- }
521
- if (call.isResultCompressed === "LZ4") {
522
- call.result = await decompressObjLZ4(call.result, receiveStats);
523
- call.isResultCompressed = undefined;
524
- }
525
- else if (call.isResultCompressed === "zip" || call.isResultCompressed === true) {
526
- call.result = await decompressObj(call.result, receiveStats);
527
- call.isResultCompressed = undefined;
528
- }
529
- callbackObj.callback(call);
530
- }
531
- else {
532
- if (call.isArgsCompressed === "LZ4") {
533
- call.args = await decompressObjLZ4(call.args, sendStats);
534
- call.isArgsCompressed = undefined;
535
- }
536
- else if (call.isArgsCompressed === "zip" || call.isArgsCompressed === true) {
537
- call.args = await decompressObj(call.args, sendStats);
538
- call.isArgsCompressed = undefined;
539
- }
540
- if (SocketFunction_1.SocketFunction.logMessages) {
541
- console.log(`SIZE\t${((0, misc_1.formatNumberSuffixed)(resultSize) + "B").padEnd(4, " ")}\tEVALUATE\t${call.classGuid}.${call.functionName} at ${Date.now()}, (${nodeId} / ${localNodeId})`);
542
- }
543
- if (parseTime > SocketFunction_1.SocketFunction.WIRE_WARN_TIME) {
544
- console.log((0, logColors_1.red)(`Slow parse, took ${parseTime}ms to parse ${resultSize} bytes, for call to ${call.classGuid}.${call.functionName}`));
545
- }
546
- let response;
547
- try {
548
- SocketFunction_1.SocketFunction.TOTAL_CALLS++;
549
- let result = await (0, callManager_1.performLocalCall)({ call, caller: callerContext });
550
- response = {
551
- isReturn: true,
552
- result,
553
- seqNum: call.seqNum,
554
- };
555
- if (SocketFunction_1.SocketFunction.logMessages) {
556
- let timeTaken = Date.now() - time;
557
- console.log(`DUR\t${((0, format_1.formatTime)(timeTaken)).padEnd(6, " ")}\tFINISH\t${call.classGuid}.${call.functionName} at ${Date.now()}, (${nodeId} / ${localNodeId})`);
558
- }
559
- if ((_a = callFactory.receivedInitializeState) === null || _a === void 0 ? void 0 : _a.supportsLZ4) {
560
- let compressMode = (0, callManager_1.shouldCompressCall)(call);
561
- if (compressMode !== false) {
562
- response.result = await compressObjLZ4(response.result, sendStats);
563
- response.isResultCompressed = "LZ4";
564
- }
565
- }
566
- else {
567
- if ((0, callManager_1.shouldCompressCall)(call)) {
568
- response.result = await compressObj(response.result, sendStats);
569
- response.isResultCompressed = "zip";
570
- }
571
- }
572
- }
573
- catch (e) {
574
- response = {
575
- isReturn: true,
576
- result: undefined,
577
- seqNum: call.seqNum,
578
- error: e.stack,
579
- };
580
- }
581
- {
582
- let start = time;
583
- let end = Date.now();
584
- for (let fnc of SocketFunction_1.SocketFunction.trackMessageSizes.callTimes) {
585
- fnc({ start, end });
586
- }
587
- }
588
- let size = 0;
589
- if (response.result instanceof Buffer) {
590
- let { result, ...remaining } = response;
591
- size = result.length;
592
- await sendWithHeader([result], { type: "Buffer", bufferCount: 1, metadata: remaining });
593
- }
594
- else if (Array.isArray(response.result) && response.result.every(x => x instanceof Buffer)) {
595
- let { result, ...remaining } = response;
596
- for (let r of result) {
597
- size += r.length;
598
- }
599
- await sendWithHeader(result, { type: "Buffer[]", bufferCount: result.length, metadata: remaining });
600
- }
601
- else {
602
- const LIMIT = ((_b = (0, callManager_1.getCallFlags)(call)) === null || _b === void 0 ? void 0 : _b.responseLimit) || SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE * 1.5;
603
- let result = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.serialize(response);
604
- let totalResultSize = result.map(x => x.length).reduce((a, b) => a + b, 0);
605
- if (totalResultSize > LIMIT) {
606
- response = {
607
- isReturn: true,
608
- result: undefined,
609
- seqNum: call.seqNum,
610
- error: new Error(`Response too large to send. Return Buffer[] to exceed the limits, or set responseLimit when registering the collection. ${call.classGuid}.${call.functionName}, size: ${(0, format_1.formatNumber)(totalResultSize)} > ${(0, format_1.formatNumber)(SocketFunction_1.SocketFunction.MAX_MESSAGE_SIZE)}. If you need to handle very large static data use some external service, such as Backblaze B2 or AWS S3. Or, if absolutely required, set SocketFunction.MAX_MESSAGE_SIZE to a higher value.`).stack,
611
- };
612
- result = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.serialize(response);
613
- }
614
- for (let r of result) {
615
- size += r.length;
616
- }
617
- await send(result);
618
- }
619
- // If we have no size, then it's probably uncompressed
620
- if (!sendStats.compressedSize) {
621
- sendStats.compressedSize = size;
622
- sendStats.uncompressedSize = size;
623
- }
624
- }
625
- addSendStats(sendStats);
626
- addReceiveStats(receiveStats);
627
- }
628
- let clientsideSerial = (0, batching_1.runInSerial)(async (val) => val);
629
- async function onMessage(message) {
630
- try {
631
- if (typeof message === "object" && "data" in message) {
632
- message = message.data;
633
- }
634
- // Extra clienside parsing is required
635
- if (!(0, misc_1.isNode)()) {
636
- // Immediately start the arrayBuffer conversion. This should be fast, but...
637
- // maybe we will add more here, and so doing it in parallel might be useful.
638
- let fixMessageBlob = (async () => {
639
- if (message instanceof Blob) {
640
- message = Buffer.from(await message.arrayBuffer());
641
- }
642
- })();
643
- // We need to force the results to be in serial, otherwise strings leapfrog
644
- // ahead of buffers, which breaks things.
645
- await clientsideSerial(fixMessageBlob);
646
- }
647
- if (typeof message === "string") {
648
- if (message.startsWith("{")) {
649
- let obj = JSON.parse(message);
650
- pendingCall = {
651
- ...obj,
652
- buffers: [],
653
- };
654
- }
655
- else {
656
- let count = parseInt(message);
657
- if (isNaN(count)) {
658
- throw new Error(`Invalid message count ${message}`);
659
- }
660
- if (count < BASE_LENGTH_OFFSET) {
661
- throw new Error(`Invalid message count ${message}`);
662
- }
663
- count -= BASE_LENGTH_OFFSET;
664
- if (count > 1000 * 1000) {
665
- throw new Error(`Invalid message count ${count}`);
666
- }
667
- pendingCall = {
668
- buffers: [],
669
- bufferCount: count,
670
- type: "serialized",
671
- };
672
- }
673
- if ((pendingCall === null || pendingCall === void 0 ? void 0 : pendingCall.bufferCount) === 0) {
674
- await processPendingCall();
675
- }
676
- return;
677
- }
678
- if (message instanceof Buffer) {
679
- if (!pendingCall) {
680
- throw new Error(`Received data without size ${message.byteLength}B, first 100 bytes: ${message.slice(0, 100).toString("hex")}`);
681
- }
682
- let totalSize = message.byteLength + pendingCall.buffers.reduce((a, b) => a + b.length, 0);
683
- if (totalSize > 1000 * 1000 * 10 || pendingCall.bufferCount > 1000 && (pendingCall.buffers.length % 100 === 0)) {
684
- if (pendingCall.buffers.length === 0) {
685
- console.log(`Received large/many packets ${(0, format_1.formatNumber)(totalSize)}B (${pendingCall.buffers.length} / ${pendingCall.bufferCount}) at ${Date.now()}`);
686
- }
687
- else {
688
- let elapsed = Date.now() - (pendingCall.firstReceivedTime || 0);
689
- console.log(`Received large/many packets ${(0, format_1.formatNumber)(totalSize)}B (${pendingCall.buffers.length} / ${pendingCall.bufferCount}) after ${(0, format_1.formatTime)(elapsed)}`);
690
- }
691
- }
692
- if (pendingCall.buffers.length === 0) {
693
- pendingCall.firstReceivedTime = Date.now();
694
- }
695
- pendingCall.buffers.push(message);
696
- if (pendingCall.buffers.length !== pendingCall.bufferCount) {
697
- return;
698
- }
699
- await processPendingCall();
700
- return;
701
- }
702
- throw new Error(`Unhandled data type ${typeof message}`);
703
- }
704
- catch (e) {
705
- let err = e.stack || e.message || e;
706
- // NOTE: I'm looking for all types of errors here (specifically, .send errors), in case
707
- // there are errors I should be handling.
708
- if (err.startsWith("Error: Cannot send data to") && err.includes("as the connection has closed")) {
709
- // This is fine, just ignore it
710
- }
711
- else if (err.includes("The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.")) {
712
- console.error(`WebSocket data was dropped by the browser due to exceeding the Blob limit. Either you are about to run out of memory, or you hit the much lower Incognito Blob limit. This will likely break the application. To reset the memory you must close all tabs of this site. This is a bug/feature in chrome.`);
713
- }
714
- else {
715
- console.error(e.stack);
716
- }
717
- }
718
- }
719
- return callFactory;
720
- }
721
- exports.createCallFactory = createCallFactory;
722
- let uncompressedSent = 0;
723
- let compressedSent = 0;
724
- let uncompressedReceived = 0;
725
- let compressedReceived = 0;
726
- let sendCount = 0;
727
- let receiveCount = 0;
728
- function addSendStats(stats) {
729
- uncompressedSent += stats.uncompressedSize;
730
- compressedSent += stats.compressedSize;
731
- sendCount++;
732
- }
733
- function addReceiveStats(stats) {
734
- uncompressedReceived += stats.uncompressedSize;
735
- compressedReceived += stats.compressedSize;
736
- receiveCount++;
737
- }
738
- function getStats() {
739
- return {
740
- uncompressedSent,
741
- compressedSent,
742
- uncompressedReceived,
743
- compressedReceived,
744
- sendCount,
745
- receiveCount,
746
- };
747
- }
748
- exports.getStats = getStats;
749
- // Register this late as I don't want it to appear before the memory register info, which is use more useful than the network one.
750
- setImmediate(() => {
751
- (0, measure_1.registerMeasureInfo)(() => `NET => ${(0, format_1.formatNumber)(compressedSent)}B (${(0, format_1.formatNumber)(uncompressedSent)}B/${(0, format_1.formatNumber)(sendCount)}) / <= ${(0, format_1.formatNumber)(compressedReceived)}B (${(0, format_1.formatNumber)(uncompressedReceived)}B/${(0, format_1.formatNumber)(receiveCount)})`);
752
- });
753
- const compressObj = (0, measure_1.measureWrap)(async function wireCallCompress(obj, stats) {
754
- let buffers = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.serialize(obj);
755
- if (buffers.length > 1) {
756
- throw new Error("Legacy CompressObj only supports single buffer");
757
- }
758
- let lengthBuffer = Buffer.from((new Float64Array(buffers.map(x => x.length))).buffer);
759
- let buffer = Buffer.concat([lengthBuffer, ...buffers]);
760
- stats.uncompressedSize += buffer.length;
761
- let result = await Zip_1.Zip.gzip(buffer);
762
- stats.compressedSize += result.length;
763
- return result;
764
- });
765
- // Assumes the caller already added the obj.length to both the uncompressedSize and compressedSize, and is just looking to update the uncompressedSize to be larger according to the size after we uncompress
766
- const decompressObj = (0, measure_1.measureWrap)(async function wireCallDecompress(obj, stats) {
767
- let buffer = await Zip_1.Zip.gunzip(obj);
768
- stats.uncompressedSize += buffer.length - obj.length;
769
- let lengthBuffer = buffer.slice(0, 8);
770
- let lengths = new Float64Array(lengthBuffer.buffer, lengthBuffer.byteOffset, lengthBuffer.byteLength / 8);
771
- let buffers = [];
772
- let offset = 8;
773
- for (let length of lengths) {
774
- buffers.push(buffer.slice(offset, offset + length));
775
- offset += length;
776
- }
777
- let result = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.deserialize(buffers);
778
- return result;
779
- });
780
- const compressObjLZ4 = (0, measure_1.measureWrap)(async function wireCallCompressLZ4(obj, stats) {
781
- const { LZ4 } = await Promise.resolve().then(() => __importStar(require("./lz4/LZ4")));
782
- let headerParts;
783
- let dataBuffers;
784
- if (obj instanceof Buffer) {
785
- headerParts = [1];
786
- dataBuffers = [obj];
787
- }
788
- else if (Array.isArray(obj) && obj.every((x) => x instanceof Buffer)) {
789
- let bufferArray = obj;
790
- const TARGET_SIZE = 50 * 1024 * 1024;
791
- const MIN_INDIVIDUAL_SIZE = 10 * 1024 * 1024;
792
- const MAX_UNSPLIT_SIZE = 100 * 1024 * 1024;
793
- let outputBuffers = [];
794
- let outputDescriptors = [];
795
- let currentGroup = [];
796
- let currentGroupSize = 0;
797
- function flushCurrentGroup() {
798
- if (currentGroup.length > 0) {
799
- outputBuffers.push(Buffer.concat(currentGroup));
800
- outputDescriptors.push(currentGroup.map(b => b.length));
801
- currentGroup = [];
802
- currentGroupSize = 0;
803
- }
804
- }
805
- for (let buf of bufferArray) {
806
- if (buf.length >= MIN_INDIVIDUAL_SIZE) {
807
- flushCurrentGroup();
808
- if (buf.length > MAX_UNSPLIT_SIZE) {
809
- let offset = 0;
810
- while (offset < buf.length) {
811
- let chunkSize = Math.min(TARGET_SIZE, buf.length - offset);
812
- outputBuffers.push(buf.slice(offset, offset + chunkSize));
813
- outputDescriptors.push([chunkSize]);
814
- offset += chunkSize;
815
- }
816
- }
817
- else {
818
- outputBuffers.push(buf);
819
- outputDescriptors.push([buf.length]);
820
- }
821
- }
822
- else {
823
- currentGroup.push(buf);
824
- currentGroupSize += buf.length;
825
- if (currentGroupSize >= TARGET_SIZE) {
826
- flushCurrentGroup();
827
- }
828
- }
829
- }
830
- flushCurrentGroup();
831
- headerParts = [2, outputBuffers.length];
832
- for (let descriptor of outputDescriptors) {
833
- headerParts.push(descriptor.length, ...descriptor);
834
- }
835
- dataBuffers = outputBuffers;
836
- }
837
- else {
838
- let buffers = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.serialize(obj);
839
- headerParts = [3, buffers.length];
840
- dataBuffers = buffers;
841
- }
842
- let headerBuffer = Buffer.from((new Float64Array(headerParts)).buffer);
843
- let allBuffers = [headerBuffer, ...dataBuffers];
844
- stats.uncompressedSize += allBuffers.reduce((sum, buf) => sum + buf.length, 0);
845
- let compressed = [];
846
- let startTime = Date.now();
847
- let lastWarnTime = startTime;
848
- let currentUncompressedSize = 0;
849
- let currentCompressedSize = 0;
850
- function logIfSlow(i) {
851
- let now = Date.now();
852
- if (now - lastWarnTime > 500) {
853
- let elapsed = now - startTime;
854
- console.log(`Slow LZ4 compress (${(0, format_1.formatTime)(elapsed)}: ${i + 1}/${allBuffers.length} buffers, ${(0, format_1.formatNumber)(currentUncompressedSize)}B => ${(0, format_1.formatNumber)(currentCompressedSize)}B`);
855
- lastWarnTime = now;
856
- }
857
- }
858
- for (let i = 0; i < allBuffers.length; i++) {
859
- let buf = allBuffers[i];
860
- currentUncompressedSize += buf.length;
861
- let compressedBuf = LZ4.compress(buf);
862
- compressed.push(compressedBuf);
863
- currentCompressedSize += compressedBuf.length;
864
- logIfSlow(i);
865
- }
866
- logIfSlow(allBuffers.length);
867
- stats.compressedSize += currentCompressedSize;
868
- return compressed;
869
- });
870
- const decompressObjLZ4 = (0, measure_1.measureWrap)(async function wireCallDecompressLZ4(obj, stats) {
871
- const { LZ4 } = await Promise.resolve().then(() => __importStar(require("./lz4/LZ4")));
872
- stats.compressedSize += obj.reduce((sum, buf) => sum + buf.length, 0);
873
- let decompressed = [];
874
- let startTime = Date.now();
875
- let lastWarnTime = startTime;
876
- let currentCompressedSize = 0;
877
- let currentUncompressedSize = 0;
878
- function logIfSlow(i) {
879
- let now = Date.now();
880
- if (now - lastWarnTime > 500) {
881
- let elapsed = now - startTime;
882
- console.log(`Slow LZ4 decompress (${(0, format_1.formatTime)(elapsed)}): ${i + 1}/${obj.length} buffers, ${(0, format_1.formatNumber)(currentCompressedSize)}B => ${(0, format_1.formatNumber)(currentUncompressedSize)}B`);
883
- lastWarnTime = now;
884
- }
885
- }
886
- for (let i = 0; i < obj.length; i++) {
887
- let buf = obj[i];
888
- currentCompressedSize += buf.length;
889
- let decompressedBuf = LZ4.decompress(buf);
890
- decompressed.push(decompressedBuf);
891
- currentUncompressedSize += decompressedBuf.length;
892
- logIfSlow(i);
893
- }
894
- logIfSlow(obj.length);
895
- stats.uncompressedSize += currentUncompressedSize;
896
- let headerBuffer = decompressed[0];
897
- let dataBuffers = decompressed.slice(1);
898
- let typeBuffer = headerBuffer.slice(0, 8);
899
- let type = new Float64Array(typeBuffer.buffer, typeBuffer.byteOffset, 1)[0];
900
- if (type === 1) {
901
- return dataBuffers[0];
902
- }
903
- if (type === 2) {
904
- let headerData = new Float64Array(headerBuffer.buffer, headerBuffer.byteOffset, headerBuffer.byteLength / 8);
905
- let outputBufferCount = headerData[1];
906
- let buffers = [];
907
- let headerIndex = 2;
908
- for (let i = 0; i < outputBufferCount; i++) {
909
- let inputBufferCount = headerData[headerIndex++];
910
- let sizes = [];
911
- for (let j = 0; j < inputBufferCount; j++) {
912
- sizes.push(headerData[headerIndex++]);
913
- }
914
- let outputBuffer = dataBuffers[i];
915
- let offset = 0;
916
- for (let size of sizes) {
917
- buffers.push(outputBuffer.slice(offset, offset + size));
918
- offset += size;
919
- }
920
- }
921
- return buffers;
922
- }
923
- if (type === 3) {
924
- let result = await SocketFunction_1.SocketFunction.WIRE_SERIALIZER.deserialize(dataBuffers);
925
- return result;
926
- }
927
- throw new Error(`Unknown compression type ${type}`);
928
- });
929
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FsbEZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJDYWxsRmFjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLCtDQUFtRjtBQUNuRixpQ0FBOEg7QUFDOUgseURBQTBFO0FBQzFFLHNEQUFtRDtBQUVuRCwyQ0FBcUY7QUFFckYsdUNBQWlDO0FBQ2pDLHNEQUFrRTtBQUNsRSxpRUFBZ0Y7QUFDaEYseUNBQWlFO0FBQ2pFLGdEQUErRDtBQUcvRCwwREFBa0Q7QUFDbEQsaURBQW1GO0FBRW5GLCtCQUE0QjtBQUM1QiwrREFBeUU7QUFDekUsWUFBWSxDQUFDLEdBQUcsRUFBRSxtREFBUSxXQUFXLEdBQUMsQ0FBQyxDQUFDO0FBRXhDLElBQUEsc0JBQU8sRUFBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUU5QyxnR0FBZ0c7QUFDaEcsd0JBQXdCO0FBQ3hCLDJGQUEyRjtBQUMzRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUM7QUE2RDdCLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFFcEMsSUFBSSxnQkFBZ0IsR0FBRyxDQUFDLENBQUM7QUFDekIsSUFBSSxzQkFBc0IsR0FBRyxDQUFDLENBQUM7QUFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUMxQyxJQUFJLG9CQUFvQixHQUFzQyxFQUFFLENBQUM7QUFDakUsU0FBZ0Isc0JBQXNCO0lBQ2xDLElBQUksS0FBSyxHQUFHLHNCQUFzQixDQUFDO0lBQ25DLHNCQUFzQixHQUFHLENBQUMsQ0FBQztJQUMzQixPQUFPLEtBQUssQ0FBQztBQUNqQixDQUFDO0FBSkQsd0RBSUM7QUFDRCxTQUFnQixtQkFBbUI7SUFDL0IsT0FBTyxnQkFBZ0IsQ0FBQztBQUM1QixDQUFDO0FBRkQsa0RBRUM7QUFDRCxTQUFnQixnQkFBZ0I7SUFD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QUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxJQUFJLElBQUksQ0FBQztZQUNuQixDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDO0lBQ25CLENBQUM7SUFFRCxJQUFJLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNiLElBQUksTUFBTSxHQUFHLE1BQU0sK0JBQWMsQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzNFLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3hELENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2FsbGVyQ29udGV4dCwgQ2FsbGVyQ29udGV4dEJhc2UsIENhbGxUeXBlLCBGdWxsQ2FsbFR5cGUgfSBmcm9tIFwiLi4vU29ja2V0RnVuY3Rpb25UeXBlc1wiO1xuaW1wb3J0ICogYXMgd3MgZnJvbSBcIndzXCI7XG5pbXBvcnQgeyBnZXRDYWxsRmxhZ3MsIHBlcmZvcm1Mb2NhbENhbGwsIHNob3VsZENvbXByZXNzQ2FsbCB9IGZyb20gXCIuL2NhbGxNYW5hZ2VyXCI7XG5pbXBvcnQgeyBjb252ZXJ0RXJyb3JTdGFja1RvRXJyb3IsIGZvcm1hdE51bWJlclN1ZmZpeGVkLCBpc0J1ZmZlclR5cGUsIGlzTm9kZSwgbGlzdCwgdGltZUluSG91ciwgdGltZUluTWludXRlIH0gZnJvbSBcIi4vbWlzY1wiO1xuaW1wb3J0IHsgY3JlYXRlV2Vic29ja2V0RmFjdG9yeSwgZ2V0VExTU29ja2V0IH0gZnJvbSBcIi4vd2Vic29ja2V0RmFjdG9yeVwiO1xuaW1wb3J0IHsgU29ja2V0RnVuY3Rpb24gfSBmcm9tIFwiLi4vU29ja2V0RnVuY3Rpb25cIjtcbmltcG9ydCAqIGFzIHRscyBmcm9tIFwidGxzXCI7XG5pbXBvcnQgeyBnZXRDbGllbnROb2RlSWQsIGdldE5vZGVJZExvY2F0aW9uLCByZWdpc3Rlck5vZGVDbGllbnQgfSBmcm9tIFwiLi9ub2RlQ2FjaGVcIjtcbmltcG9ydCBkZWJ1Z2JyZWFrIGZyb20gXCJkZWJ1Z2JyZWFrXCI7XG5pbXBvcnQgeyBsYXp5IH0gZnJvbSBcIi4vY2FjaGluZ1wiO1xuaW1wb3J0IHsgYmx1ZSwgZ3JlZW4sIHJlZCwgeWVsbG93IH0gZnJvbSBcIi4vZm9ybWF0dGluZy9sb2dDb2xvcnNcIjtcbmltcG9ydCB7IGlzU3BsaXRhYmxlQXJyYXksIG1hcmtBcnJheUFzU3BsaXRhYmxlIH0gZnJvbSBcIi4vZml4TGFyZ2VOZXR3b3JrQ2FsbHNcIjtcbmltcG9ydCB7IGRlbGF5LCBydW5JbmZpbml0ZVBvbGwsIHJ1bkluU2VyaWFsIH0gZnJvbSBcIi4vYmF0Y2hpbmdcIjtcbmltcG9ydCB7IGZvcm1hdE51bWJlciwgZm9ybWF0VGltZSB9IGZyb20gXCIuL2Zvcm1hdHRpbmcvZm9ybWF0XCI7XG5pbXBvcnQgemxpYiBmcm9tIFwiemxpYlwiO1xuaW1wb3J0IHBha28gZnJvbSBcInBha29cIjtcbmltcG9ydCB7IHNldEZsYWcgfSBmcm9tIFwiLi4vcmVxdWlyZS9jb21waWxlRmxhZ3NcIjtcbmltcG9ydCB7IG1lYXN1cmVGbmMsIG1lYXN1cmVXcmFwLCByZWdpc3Rlck1lYXN1cmVJbmZvIH0gZnJvbSBcIi4vcHJvZmlsaW5nL21lYXN1cmVcIjtcbmltcG9ydCB7IE1heWJlUHJvbWlzZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBaaXAgfSBmcm9tIFwiLi9aaXBcIjtcbmltcG9ydCB7IGRlY29kZVByb3RvY29sLCBwcm9wb3NlUHJvdG9jb2xzIH0gZnJvbSBcIi4vcHJvdG9jb2xOZWdvdGlhdGlvblwiO1xuc2V0SW1tZWRpYXRlKCgpID0+IGltcG9ydChcIi4vbHo0L0xaNFwiKSk7XG5cbnNldEZsYWcocmVxdWlyZSwgXCJwYWtvXCIsIFwiYWxsb3djbGllbnRcIiwgdHJ1ZSk7XG5cbi8vIE5PVEU6IElmIGl0IGlzIHRvbyBsb3csIGFuZCB0b28gbWFueSBzZXJ2ZXJzIGRpc2Nvbm5lY3QsIHdlIGNhbiBlYXNpbHkgc3BlbmQgMTAwJSBvZiBvdXIgdGltZVxuLy8gIHRyeWluZyB0byByZWNvbm5lY3QuXG4vLyAgKE9yLi4uIG1heWJlIHRoZSBkZWxheSBpcyBqdXN0IHdhaXRpbmcsIGFuZCB3ZSBhcmVuJ3QgYWN0dWFsbHkgb3ZlcmxvYWRpbmcgdGhlIHNlcnZlcj8pXG5jb25zdCBNSU5fUkVUUllfREVMQVkgPSA1MDAwO1xuXG50eXBlIEludGVybmFsQ2FsbFR5cGUgPSBGdWxsQ2FsbFR5cGUgJiB7XG4gICAgc2VxTnVtOiBudW1iZXI7XG4gICAgaXNSZXR1cm46IGZhbHNlO1xuICAgIGlzQXJnc0NvbXByZXNzZWQ/OiBib29sZWFuIHwgXCJMWjRcIiB8IFwiemlwXCI7XG59XG5cbnR5cGUgSW50ZXJuYWxSZXR1cm5UeXBlID0ge1xuICAgIGlzUmV0dXJuOiB0cnVlO1xuICAgIHJlc3VsdDogdW5rbm93bjtcbiAgICBlcnJvcj86IHN0cmluZztcbiAgICBzZXFOdW06IG51bWJlcjtcbiAgICBpc1Jlc3VsdENvbXByZXNzZWQ/OiBib29sZWFuIHwgXCJMWjRcIiB8IFwiemlwXCI7XG59O1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FsbEZhY3Rvcnkge1xuICAgIG5vZGVJZDogc3RyaW5nO1xuICAgIHJlYWxOb2RlSWQ/OiBzdHJpbmc7XG4gICAgbGFzdENsb3NlZDogbnVtYmVyO1xuICAgIGNsb3NlZEZvcmV2ZXI/OiBib29sZWFuO1xuICAgIGlzQ29ubmVjdGVkPzogYm9vbGVhbjtcbiAgICByZWNlaXZlZEluaXRpYWxpemVTdGF0ZT86IEluaXRpYWxpemVTdGF0ZTtcbiAgICAvLyBUcnVlIGlmIHRoZSBjb25uZWN0aW9uIHdhcyBlc3RhYmxpc2hlZCB3aXRoIGEgbmVnb3RpYXRlZFxuICAgIC8vIFNlYy1XZWJTb2NrZXQtUHJvdG9jb2wgKHNvIHRoZSBsZWdhY3kgaW5pdGlhbGl6ZSBwYWNrZXQgc2hvdWxkIGJlIHNraXBwZWQpLlxuICAgIHByb3RvY29sTmVnb3RpYXRlZD86IGJvb2xlYW47XG4gICAgLy8gTk9URTogTWF5IG9yIG1heSBub3QgaGF2ZSByZWNvbm5lY3Rpb24gb3IgcmV0cnkgbG9naWMgaW5zaWRlIG9mIHBlcmZvcm1DYWxsLlxuICAgIC8vICBUcmlnZ2VyIHBlcmZvcm1Mb2NhbENhbGwgb24gdGhlIG90aGVyIHNpZGUgb2YgdGhlIGNvbm5lY3Rpb25cbiAgICBwZXJmb3JtQ2FsbChjYWxsOiBDYWxsVHlwZSk6IFByb21pc2U8dW5rbm93bj47XG4gICAgb25OZXh0RGlzY29ubmVjdChjYWxsYmFjazogKCkgPT4gdm9pZCk6IHZvaWQ7XG4gICAgZGlzY29ubmVjdCgpOiB2b2lkO1xuICAgIC8vIElmIHdlIGNoYW5nZSB0aGUgbm9kZSBJRCB3ZSBuZWVkIHRvIHJlY3JlYXRlIHRoaXMgb2JqZWN0LCBlc3NlbnRpYWxseSB0aGlzIG9iamVjdCBzaG91bGQgYmUgaW1tdXRhYmxlLiBJIGZvcmdldCB3aHkgd2Ugd2FudGVkIHRoaXMuIEkgdGhpbmsgaXQncyBiZWNhdXNlIHdlIGRpZG4ndCBrbm93IGZvciBzdXJlIGlmIG5vZGUgSUQgd291bGQgYmUgdW5pcXVlLCBidXQgaXQgd2lsbCBiZS4gXG4gICAgY29ubmVjdGlvbklkOiB7IG5vZGVJZDogc3RyaW5nIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZGVySW50ZXJmYWNlIHtcbiAgICBub2RlSWQ/OiBzdHJpbmc7XG4gICAgLy8gT25seSBzZXQgQUZURVIgXCJvcGVuXCIgKGlmIHNldCBhdCBhbGwsIGFzIGluIHRoZSBicm93c2VyIHdlIGRvbid0IGhhdmUgYWNjZXNzIHRvIHRoZSBzb2NrZXQpLlxuICAgIF9zb2NrZXQ/OiB0bHMuVExTU29ja2V0O1xuICAgIC8vIFRoZSBjaG9zZW4gU2VjLVdlYlNvY2tldC1Qcm90b2NvbCB2YWx1ZSAoc2V0IGFmdGVyIFwib3BlblwiIGJ5IGJvdGggTm9kZSBgd3NgXG4gICAgLy8gYW5kIHRoZSBicm93c2VyIFdlYlNvY2tldCkuIEVtcHR5IHN0cmluZyBtZWFucyBub25lIHdhcyBuZWdvdGlhdGVkLlxuICAgIHByb3RvY29sPzogc3RyaW5nO1xuXG4gICAgc2VuZChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpOiB2b2lkO1xuICAgIGNsb3NlKCk6IHZvaWQ7XG5cbiAgICBhZGRFdmVudExpc3RlbmVyKGV2ZW50OiBcIm9wZW5cIiwgbGlzdGVuZXI6ICgpID0+IHZvaWQpOiB2b2lkO1xuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnQ6IFwiY2xvc2VcIiwgbGlzdGVuZXI6ICgpID0+IHZvaWQpOiB2b2lkO1xuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnQ6IFwiZXJyb3JcIiwgbGlzdGVuZXI6IChlcnI6IHsgbWVzc2FnZTogc3RyaW5nIH0pID0+IHZvaWQpOiB2b2lkO1xuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnQ6IFwibWVzc2FnZVwiLCBsaXN0ZW5lcjogKGRhdGE6IHdzLlJhd0RhdGEgfCB3cy5NZXNzYWdlRXZlbnQgfCBzdHJpbmcpID0+IHZvaWQpOiB2b2lkO1xuXG4gICAgcmVhZHlTdGF0ZTogbnVtYmVyO1xuXG4gICAgcGluZz8oKTogdm9pZDtcbn1cblxudHlwZSBJbml0aWFsaXplU3RhdGUgPSB7XG4gICAgc3VwcG9ydHNMWjQ/OiBib29sZWFuO1xufTtcblxuY29uc3QgSU5JVElBTElaRV9TVEFURV9TRVFfTlVNID0gLTE7XG5cbmxldCBwZW5kaW5nQ2FsbENvdW50ID0gMDtcbmxldCBoYXJ2ZXN0YWJsZUZhaWxlZENhbGxzID0gMDtcbmNvbnN0IENBTExfVElNRVNfTElNSVQgPSAxMDAwICogMTAwMCAqIDEwO1xubGV0IGhhcnZlc3RhYmxlQ2FsbFRpbWVzOiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyOyB9W10gPSBbXTtcbmV4cG9ydCBmdW5jdGlvbiBoYXJ2ZXN0RmFpbGVkQ2FsbENvdW50KCkge1xuICAgIGxldCBjb3VudCA9IGhhcnZlc3RhYmxlRmFpbGVkQ2FsbHM7XG4gICAgaGFydmVzdGFibGVGYWlsZWRDYWxscyA9IDA7XG4gICAgcmV0dXJuIGNvdW50O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdldFBlbmRpbmdDYWxsQ291bnQoKSB7XG4gICAgcmV0dXJuIHBlbmRpbmdDYWxsQ291bnQ7XG59XG5leHBvcnQgZnVuY3Rpb24gaGFydmVzdENhbGxUaW1lcygpIHtcbiAgICBsZXQgdGltZXMgPSBoYXJ2ZXN0YWJsZUNhbGxUaW1lcztcbiAgICBoYXJ2ZXN0YWJsZUNhbGxUaW1lcyA9IFtdO1xuICAgIHJldHVybiB0aW1lcztcbn1cbnJ1bkluZmluaXRlUG9sbCh0aW1lSW5NaW51dGUgKiAxNSwgKCkgPT4ge1xuICAgIGlmIChoYXJ2ZXN0YWJsZUNhbGxUaW1lcy5sZW5ndGggPiBDQUxMX1RJTUVTX0xJTUlUKSB7XG4gICAgICAgIGhhcnZlc3RhYmxlQ2FsbFRpbWVzID0gaGFydmVzdGFibGVDYWxsVGltZXMuc2xpY2UoLUNBTExfVElNRVNfTElNSVQpO1xuICAgIH1cbn0pO1xuXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVDYWxsRmFjdG9yeShcbiAgICB3ZWJTb2NrZXRCYXNlOiBTZW5kZXJJbnRlcmZhY2UgfCB1bmRlZmluZWQsXG4gICAgLy8gVGhlIG5vZGUgaWQgd2UgYXJlIGNvbm5lY3RpbmcgdG8gKG9yIHRoYXQgY29ubmVjdGVkIHRvIHVzKVxuICAgIG5vZGVJZDogc3RyaW5nLFxuICAgIC8vIFRoZSBub2RlIGlkIHRoYXQgd2Ugd2VyZSBjb250YWN0ZWQgb25cbiAgICBsb2NhbE5vZGVJZCA9IFwiXCIsXG4pOiBQcm9taXNlPENhbGxGYWN0b3J5PiB7XG4gICAgbGV0IG5pY2VDb25uZWN0aW9uTmFtZSA9IG5vZGVJZDtcblxuICAgIGNvbnN0IGNyZWF0ZVdlYnNvY2tldCA9IGNyZWF0ZVdlYnNvY2tldEZhY3RvcnkoKTtcbiAgICBjb25zdCByZWdpc3Rlck9uY2UgPSBsYXp5KCgpID0+IHJlZ2lzdGVyTm9kZUNsaWVudChjYWxsRmFjdG9yeSkpO1xuXG4gICAgbGV0IGNhblJlY29ubmVjdCA9ICEhZ2V0Tm9kZUlkTG9jYXRpb24obm9kZUlkKTtcblxuICAgIGxldCBwZW5kaW5nQ2FsbHM6IE1hcDxudW1iZXIsIHtcbiAgICAgICAgZGF0YTogQnVmZmVyW107XG4gICAgICAgIGNhbGw6IEludGVybmFsQ2FsbFR5cGU7XG4gICAgICAgIGNhbGxiYWNrOiAocmVzdWx0SlNPTjogSW50ZXJuYWxSZXR1cm5UeXBlKSA9PiB2b2lkO1xuICAgIH0+ID0gbmV3IE1hcCgpO1xuICAgIC8vIE5PVEU6IEl0IGlzIGltcG9ydGFudCB0byBtYWtlIHRoaXMgYXMgcmFuZG9tIGFzIHBvc3NpYmxlLCB0byBwcmV2ZW50XG4gICAgLy8gIHJlY29ubmVjdGlvbnMgZHVlcyB0byBhIHByb2Nlc3MgYmVpbmcgcmVzZXQgY2F1c2luZyBzZXFOdW0gY29sbGlzaW9uc1xuICAgIC8vICBpbiByZXR1cm4gY2FsbHMuXG4gICAgbGV0IG5leHRTZXFOdW0gPSBEYXRlLm5vdygpICsgTWF0aC5yYW5kb20oKTtcblxuICAgIC8vIE5PVEU6IEknbSBub3Qgc3VyZSBpZiB0aGlzIGlzIG5lZWRlZCwgSSB0aG91Z2h0IGl0IHdhcywgYnV0Li4uIG5vdyBJIHRoaW5rXG4gICAgLy8gIGl0IHByb2JhYmx5IGlzbid0Li4uXG4gICAgLy8gaWYgKHdlYlNvY2tldEJhc2U/LnJlYWR5U3RhdGUgPT09IDEgLyogT1BFTiAqLyAmJiB3ZWJTb2NrZXRCYXNlLnBpbmcpIHtcbiAgICAvLyAgICAgLy8gSGVhcnRiZWF0IGxvb3AsIG90aGVyd2lzZSBvbkRpc2Nvbm5lY3QgaXMgbmV2ZXIgY2FsbGVkLlxuICAgIC8vICAgICAoKGFzeW5jICgpID0+IHtcbiAgICAvLyAgICAgICAgIHdoaWxlICh3ZWJTb2NrZXRCYXNlPy5yZWFkeVN0YXRlID09PSAxIC8qIE9QRU4gKi8gJiYgd2ViU29ja2V0QmFzZS5waW5nKSB7XG4gICAgLy8gICAgICAgICAgICAgYXdhaXQgZGVsYXkoMTAwMCAqIDYwKTtcbiAgICAvLyAgICAgICAgICAgICB3ZWJTb2NrZXRCYXNlLnBpbmc/LigpO1xuICAgIC8vICAgICAgICAgfVxuICAgIC8vICAgICB9KSkoKS5jYXRjaCgoKSA9PiB7IH0pO1xuICAgIC8vIH1cblxuICAgIGxldCBsYXN0Q29ubmVjdGlvbkF0dGVtcHQgPSAwO1xuXG4gICAgbGV0IGNhbGxlckNvbnRleHQ6IENhbGxlckNvbnRleHRCYXNlID0ge1xuICAgICAgICBub2RlSWQsXG4gICAgICAgIGxvY2FsTm9kZUlkXG4gICAgfTtcblxuICAgIGxldCBkaXNjb25uZWN0Q2FsbGJhY2tzID0gbmV3IFNldDwoKSA9PiB2b2lkPigpO1xuICAgIGZ1bmN0aW9uIG9uTmV4dERpc2Nvbm5lY3QoY2FsbGJhY2s6ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICAgICAgZGlzY29ubmVjdENhbGxiYWNrcy5hZGQoY2FsbGJhY2spO1xuICAgIH1cblxuICAgIGxldCBjYWxsRmFjdG9yeTogQ2FsbEZhY3RvcnkgPSB7XG4gICAgICAgIG5vZGVJZCxcbiAgICAgICAgbGFzdENsb3NlZDogMCxcbiAgICAgICAgY29ubmVjdGlvbklkOiB7IG5vZGVJZCB9LFxuICAgICAgICByZWNlaXZlZEluaXRpYWxpemVTdGF0ZTogdW5kZWZpbmVkLFxuICAgICAgICBvbk5leHREaXNjb25uZWN0LFxuICAgICAgICBkaXNjb25uZWN0KCkge1xuICAgICAgICAgICAgY2FuUmVjb25uZWN0ID0gZmFsc2U7XG4gICAgICAgICAgICBjYWxsRmFjdG9yeS5jbG9zZWRGb3JldmVyID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh3ZWJTb2NrZXRQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgd2ViU29ja2V0UHJvbWlzZS50aGVuKHdzID0+IHdzLmNsb3NlKCkpLmNhdGNoKCgpID0+IHsgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGFzeW5jIHBlcmZvcm1DYWxsKGNhbGw6IENhbGxUeXBlKSB7XG4gICAgICAgICAgICBsZXQgc2VxTnVtID0gbmV4dFNlcU51bSsrO1xuICAgICAgICAgICAgbGV0IGZ1bGxDYWxsOiBJbnRlcm5hbENhbGxUeXBlID0ge1xuICAgICAgICAgICAgICAgIG5vZGVJZCxcbiAgICAgICAgICAgICAgICBpc1JldHVybjogZmFsc2UsXG4gICAgICAgICAgICAgICAgYXJnczogY2FsbC5hcmdzLFxuICAgICAgICAgICAgICAgIGNsYXNzR3VpZDogY2FsbC5jbGFzc0d1aWQsXG4gICAgICAgICAgICAgICAgZnVuY3Rpb25OYW1lOiBjYWxsLmZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICAgICAgICBzZXFOdW0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbGV0IGRhdGE6IEJ1ZmZlcltdO1xuICAgICAgICAgICAgbGV0IG9yaWdpbmFsQXJncyA9IGNhbGwuYXJncztcbiAgICAgICAgICAgIGxldCB0aW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIGxldCBzZW5kU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgdW5jb21wcmVzc2VkU2l6ZTogMCxcbiAgICAgICAgICAgICAgICBjb21wcmVzc2VkU2l6ZTogMCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChjYWxsRmFjdG9yeS5yZWNlaXZlZEluaXRpYWxpemVTdGF0ZT8uc3VwcG9ydHNMWjQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbXByZXNzTW9kZSA9IHNob3VsZENvbXByZXNzQ2FsbChmdWxsQ2FsbCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGl0J3MgdW5kZWZpbmVkLCB0aGVuIHdlIGNvbXByZXNzIGl0LiBXZSBiYXNpY2FsbHkgYWx3YXlzIHdhbnQgdG8gY29tcHJlc3MgZnJvbSBub3cgb24sIGJlY2F1c2UgTFo0IGlzIHNvIGZhc3QuIFxuICAgICAgICAgICAgICAgICAgICBpZiAoY29tcHJlc3NNb2RlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVsbENhbGwuYXJncyA9IGF3YWl0IGNvbXByZXNzT2JqTFo0KGZ1bGxDYWxsLmFyZ3MsIHNlbmRTdGF0cykgYXMgYW55O1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVsbENhbGwuaXNBcmdzQ29tcHJlc3NlZCA9IFwiTFo0XCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQ29tcHJlc3NDYWxsKGZ1bGxDYWxsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVsbENhbGwuYXJncyA9IGF3YWl0IGNvbXByZXNzT2JqKGZ1bGxDYWxsLmFyZ3MsIHNlbmRTdGF0cykgYXMgYW55O1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVsbENhbGwuaXNBcmdzQ29tcHJlc3NlZCA9IFwiemlwXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGRhdGFNYXliZVByb21pc2UgPSBTb2NrZXRGdW5jdGlvbi5XSVJFX1NFUklBTElaRVIuc2VyaWFsaXplKGZ1bGxDYWxsKTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YU1heWJlUHJvbWlzZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGF3YWl0IGRhdGFNYXliZVByb21pc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFNYXliZVByb21pc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghc2VuZFN0YXRzLmNvbXByZXNzZWRTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0b3RhbFNpemUgPSAwO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBkIG9mIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsU2l6ZSArPSBkLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZW5kU3RhdHMudW5jb21wcmVzc2VkU2l6ZSA9IHRvdGFsU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgc2VuZFN0YXRzLmNvbXByZXNzZWRTaXplID0gdG90YWxTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhZGRTZW5kU3RhdHMoc2VuZFN0YXRzKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igc2VyaWFsaXppbmcgZGF0YSBmb3IgY2FsbCAke2NhbGwuY2xhc3NHdWlkfS4ke2NhbGwuZnVuY3Rpb25OYW1lfVxcbiR7ZS5zdGFja31gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRpbWUgPSBEYXRlLm5vdygpIC0gdGltZTtcbiAgICAgICAgICAgIGxldCBzaXplID0gZGF0YS5tYXAoeCA9PiB4Lmxlbmd0aCkucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCk7XG4gICAgICAgICAgICBpZiAodGltZSA+IFNvY2tldEZ1bmN0aW9uLldJUkVfV0FSTl9USU1FKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVkKGBTbG93IHNlcmlhbGl6ZSwgdG9vayAke2Zvcm1hdFRpbWUodGltZSl9IHRvIHNlcmlhbGl6ZSAke2Zvcm1hdE51bWJlcihzaXplKX0gYnl0ZXMuIEZvciAke2NhbGwuY2xhc3NHdWlkfS4ke2NhbGwuZnVuY3Rpb25OYW1lfWApKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNpemUgPiBTb2NrZXRGdW5jdGlvbi5NQVhfTUVTU0FHRV9TSVpFICogMS41KSB7XG4gICAgICAgICAgICAgICAgbGV0IHNwbGl0QXJnSW5kZXggPSBvcmlnaW5hbEFyZ3MuZmluZEluZGV4KGlzU3BsaXRhYmxlQXJyYXkpO1xuICAgICAgICAgICAgICAgIGlmIChzcGxpdEFyZ0luZGV4ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coeWVsbG93KGBTcGxpdHRpbmcgbGFyZ2UgY2FsbCBkdWUgdG8gbGFyZ2UgYXJnczogJHtjYWxsLmNsYXNzR3VpZH0uJHtjYWxsLmZ1bmN0aW9uTmFtZX1gKSk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBTUExJVF9HUk9VUFMgPSAxMDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHNwbGl0QXJnID0gb3JpZ2luYWxBcmdzW3NwbGl0QXJnSW5kZXhdIGFzIHVua25vd25bXTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1YkNhbGxzID0gbGlzdChTUExJVF9HUk9VUFMpLm1hcChpbmRleCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSBNYXRoLmZsb29yKGluZGV4IC8gU1BMSVRfR1JPVVBTICogc3BsaXRBcmcubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbmQgPSBNYXRoLmZsb29yKChpbmRleCArIDEpIC8gU1BMSVRfR1JPVVBTICogc3BsaXRBcmcubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzcGxpdEFyZy5zbGljZShzdGFydCwgZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuZmlsdGVyKHggPT4geC5sZW5ndGggPiAwKTtcblxuICAgICAgICAgICAgICAgICAgICBsZXQgY2FsbHMgPSBzdWJDYWxscy5tYXAoYXN5bmMgc3BsaXRMaXN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdWJDYWxsID0geyAuLi5jYWxsIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJDYWxsLmFyZ3MgPSBzdWJDYWxsLmFyZ3Muc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YkNhbGwuYXJnc1tzcGxpdEFyZ0luZGV4XSA9IG1hcmtBcnJheUFzU3BsaXRhYmxlKHNwbGl0TGlzdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBjYWxsRmFjdG9yeS5wZXJmb3JtQ2FsbChzdWJDYWxsKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChjYWxscyk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGNhbGxzKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gRWguLi4gd2UgQ09VTEQgcmV0dXJuIHRoZSBhcnJheSBvZiByZXN1bHRzLCBidXQuLi4gdGhlbiB0aGUgcmVzdWx0IHdvdWxkIHNvbWV0aW1lcyBiZSBhbiBhcnJheSxcbiAgICAgICAgICAgICAgICAgICAgLy8gIHNvbWUgdGltZXMgbm90LCBzbywgaXQgaXMgYmV0dGVyIHRvIHJldHVybiBhIHN0cmluZyB3aGljaCB3aWxsIG1ha2UgaXQgbW9yZSBjbGVhciB3aHkgaXQgc29tZXRpbWVzIHZhcmllcy5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiQ0FMTFNfU1BMSVRfRFVFX1RPX0xBUkdFX0FSR1NcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbGwgdG9vIGxhcmdlIHRvIHNlbmQgKCR7Y2FsbC5jbGFzc0d1aWR9LiR7Y2FsbC5mdW5jdGlvbk5hbWV9LCBzaXplOiAke2Zvcm1hdE51bWJlcihzaXplKX0gPiAke2Zvcm1hdE51bWJlcihTb2NrZXRGdW5jdGlvbi5NQVhfTUVTU0FHRV9TSVpFKX0pLiBJZiB5b3UgbmVlZCB0byBoYW5kbGUgdmVyeSBsYXJnZSBzdGF0aWMgZGF0YSB1c2Ugc29tZSBleHRlcm5hbCBzZXJ2aWNlLCBzdWNoIGFzIEJhY2tibGF6ZSBCMiBvciBBV1MgUzMuIE9yIGNvbnNpZGVyIGZyYWdtZW50aW5nIGRhdGEgYXQgYW4gYXBwbGljYXRpb24gbGV2ZWwsIGJlY2F1c2Ugc2VuZGluZyBsYXJnZSBkYXRhIHdpbGwgY2F1c2UgbGFyZ2UgbGFnIHNwaWtlcyBmb3Igb3RoZXIgY2xpZW50cyB1c2luZyB0aGlzIHNlcnZlci4gT3IsIGlmIGFic29sdXRlbHkgcmVxdWlyZWQsIHNldCBTb2NrZXRGdW5jdGlvbi5NQVhfTUVTU0FHRV9TSVpFIHRvIGEgaGlnaGVyIHZhbHVlLmApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgcmVzdWx0UHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICBwZW5kaW5nQ2FsbENvdW50Kys7XG4gICAgICAgICAgICAgICAgbGV0IGNhbGxiYWNrID0gKHJlc3VsdDogSW50ZXJuYWxSZXR1cm5UeXBlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdDYWxsQ291bnQtLTtcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ0NhbGxzLmRlbGV0ZShzZXFOdW0pO1xuICAgICAgICAgICAgICAgICAgICBoYXJ2ZXN0YWJsZUNhbGxUaW1lcy5wdXNoKHsgc3RhcnQ6IHN0YXJ0VGltZSwgZW5kOiBEYXRlLm5vdygpLCB9KTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoY29udmVydEVycm9yU3RhY2tUb0Vycm9yKHJlc3VsdC5lcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQucmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcGVuZGluZ0NhbGxzLnNldChzZXFOdW0sIHsgY2FsbGJhY2ssIGRhdGEsIGNhbGw6IGZ1bGxDYWxsIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBsZXQgcmVzdWx0U2l6ZSA9IGRhdGEubWFwKHggPT4geC5sZW5ndGgpLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGNhbGxiYWNrIG9mIFNvY2tldEZ1bmN0aW9uLnRyYWNrTWVzc2FnZVNpemVzLnVwbG9hZCkge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhyZXN1bHRTaXplKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKFNvY2tldEZ1bmN0aW9uLmxvZ01lc3NhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBmbmNIYWNrID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGwuZnVuY3Rpb25OYW1lID09PSBcImFkZENhbGxcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFyZyA9IG9yaWdpbmFsQXJnc1swXSBhcyBhbnk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmbmNIYWNrID0gYC4ke2FyZy5Eb21haW5OYW1lfS4ke2FyZy5Nb2R1bGVJZH0uJHthcmcuRnVuY3Rpb25JZH1gO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBTSVpFXFx0JHsoZm9ybWF0TnVtYmVyU3VmZml4ZWQocmVzdWx0U2l6ZSkgKyBgQmApLnBhZEVuZCg0LCBcIiBcIil9XFx0JHtmb3JtYXROdW1iZXIoZGF0YS5sZW5ndGgpfSBidWZmZXJzXFx0UkVNT1RFIENBTExcXHQke2NhbGwuY2xhc3NHdWlkfS4ke2NhbGwuZnVuY3Rpb25OYW1lfSR7Zm5jSGFja30gYXQgJHtEYXRlLm5vdygpfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHNlbmRpbmcgT1IgcmVzdWx0UHJvbWlzZSB0aHJvd3MsIHdlIHdhbnQgdG8gZXJyb3Igb3V0LiBUaGlzIHNvbHZlcyBzb21lIGlzc3VlcyB3aXRoIHJlc3VsdFByb21pc2VcbiAgICAgICAgICAgIC8vICAgICAgZXJyb3Jpbmcgb3V0IGZpcnN0LCB3aGljaCBpcyBiZWZvcmUgd2UgYXdhaXQgaXQsIHdoaWNoIG1ha2VzIE5vZGVKUyBhbmdyeSAodW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uKS5cbiAgICAgICAgICAgIC8vICAgICAgQWxzbywgdGVjaG5pY2FsbHksIHdlIGNvdWxkIHJlY2VpdmUgdGhlIHJlc3VsdCBiZWZvcmUgd2UgZmluaXNoIHNlbmRpbmcsIGluIHdoaWNoIGNhc2UsIHdlIG1pZ2h0XG4gICAgICAgICAgICAvLyAgICAgIGFzIHdlbGwgcmV0dXJuIGl0IGltbWVkaWF0ZWx5LlxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5yYWNlKFtzZW5kKGRhdGEpLCByZXN1bHRQcm9taXNlXSk7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcmVzdWx0UHJvbWlzZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBsZXQgd2ViU29ja2V0UHJvbWlzZTogUHJvbWlzZTxTZW5kZXJJbnRlcmZhY2U+IHwgdW5kZWZpbmVkO1xuICAgIGxldCBoYXNFdmVyQ29ubmVjdGVkID0gZmFsc2U7XG4gICAgaWYgKHdlYlNvY2tldEJhc2UpIHtcbiAgICAgICAgd2ViU29ja2V0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSh3ZWJTb2NrZXRCYXNlKTtcbiAgICAgICAgYXdhaXQgaW5pdGlhbGl6ZVdlYnNvY2tldCh3ZWJTb2NrZXRCYXNlKTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBpbml0aWFsaXplV2Vic29ja2V0KG5ld1dlYlNvY2tldDogU2VuZGVySW50ZXJmYWNlLCBza2lwQ2xvc2VIYW5kbGluZyA9IGZhbHNlKSB7XG4gICAgICAgIHJlZ2lzdGVyT25jZSgpO1xuICAgICAgICBjYWxsRmFjdG9yeS5yZWNlaXZlZEluaXRpYWxpemVTdGF0ZSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBmdW5jdGlvbiBvbkNsb3NlKGVycm9yOiBzdHJpbmcpIHtcbiAgICAgICAgICAgIC8vIFdlIHRyeSB2YXJpb3VzIGNvbm5lY3Rpb25zLCBhbmQgaWYgdGhleSBmYWlsLCB3ZSB3aWxsIGp1c3QgdHJ5IG90aGVyIG5vZGUgSURzIHVudGlsIHdlIGZpbmFsbHkgZG8gY29ubmVjdCwgYW5kIHRoZW4gd2Ugc3RpY2sgd2l0aCB0aGF0IG5vZGVJZCwgYW5kIHdoZW4gaXQgZGlzY29ubmVjdHMgd2UgbmVlZCB0byBoYW5kbGUgZGlzY29ubmVjdGlvbnMgbm9ybWFsbHkuXG4gICAgICAgICAgICBpZiAoc2tpcENsb3NlSGFuZGxpbmcgJiYgIWhhc0V2ZXJDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNhbGxGYWN0b3J5LmNvbm5lY3Rpb25JZCA9IHsgbm9kZUlkIH07XG4gICAgICAgICAgICBjYWxsRmFjdG9yeS5sYXN0Q2xvc2VkID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIGNhbGxGYWN0b3J5LmlzQ29ubmVjdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB3ZWJTb2NrZXRQcm9taXNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKCFjYW5SZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICBjYWxsRmFjdG9yeS5jbG9zZWRGb3JldmVyID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IFtrZXksIGNhbGxdIG9mIHBlbmRpbmdDYWxscykge1xuICAgICAgICAgICAgICAgIGhhcnZlc3RhYmxlRmFpbGVkQ2FsbHMrKztcbiAgICAgICAgICAgICAgICBwZW5kaW5nQ2FsbHMuZGVsZXRlKGtleSk7XG4gICAgICAgICAgICAgICAgY2FsbC5jYWxsYmFjayh7XG4gICAgICAgICAgICAgICAgICAgIGlzUmV0dXJuOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgICAgICAgICBzZXFOdW06IGNhbGwuY2FsbC5zZXFOdW0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjYWxsYmFja3MgPSBkaXNjb25uZWN0Q2FsbGJhY2tzO1xuICAgICAgICAgICAgZGlzY29ubmVjdENhbGxiYWNrcyA9IG5ldyBTZXQoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGNhbGxiYWNrIG9mIGNhbGxiYWNrcykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCB7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dlYlNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIiwgZSA9PiB7XG4gICAgICAgICAgICAvLyBOT1RFOiBObyBtb3JlIGxvZ2dpbmcsIGFzIHdlIHRocm93LCBzbyB0aGUgY2FsbGVyIHNob3VsZCBiZSBsb2dnaW5nIHRoZVxuICAgICAgICAgICAgLy8gIGVycm9yIChvciBzd2FsbG93aW5nIGl0LCBpZiB0aGF0IGlzIHdoYXQgaXQgd2FudHMgdG8gZG8pLlxuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhgV2Vic29ja2V0IGVycm9yIGZvciAke25pY2VDb25uZWN0aW9uTmFtZX1gLCBlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgb25DbG9zZShuZXcgRXJyb3IoYENvbm5lY3Rpb24gZXJyb3IgZm9yICR7bmljZUNvbm5lY3Rpb25OYW1lfTogJHtlLm1lc3NhZ2V9YCkuc3RhY2shKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbmV3V2ViU29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKGBXZWJzb2NrZXQgY2xvc2VkICR7bmljZUNvbm5lY3Rpb25OYW1lfWApO1xuICAgICAgICAgICAgb25DbG9zZShuZXcgRXJyb3IoYENvbm5lY3Rpb24gY2xvc2VkIHRvICR7bmljZUNvbm5lY3Rpb25OYW1lfWApLnN0YWNrISk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIG5ld1dlYlNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBvbk1lc3NhZ2UpO1xuXG5cbiAgICAgICAgaWYgKG5ld1dlYlNvY2tldC5yZWFkeVN0YXRlID09PSAwIC8qIENPTk5FQ1RJTkcgKi8pIHtcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KHJlc29sdmUgPT4ge1xuICAgICAgICAgICAgICAgIG5ld1dlYlNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwib3BlblwiLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghU29ja2V0RnVuY3Rpb24uc2lsZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgQ29ubmVjdGlvbiBlc3RhYmxpc2hlZCB0byAke25pY2VDb25uZWN0aW9uTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYWxsRmFjdG9yeS5pc0Nvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGhhc0V2ZXJDb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbmV3V2ViU29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICAgICAgICAgIG5ld1dlYlNvY2tldC5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIiwgKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKG5ld1dlYlNvY2tldC5yZWFkeVN0YXRlID09PSAxIC8qIE9QRU4gKi8pIHtcbiAgICAgICAgICAgIGNhbGxGYWN0b3J5LmlzQ29ubmVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGhhc0V2ZXJDb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb25DbG9zZShuZXcgRXJyb3IoYFdlYnNvY2tldCByZWNlaXZlZCBpbiBjbG9zZWQgc3RhdGVgKS5zdGFjayEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNhbGxGYWN0b3J5Lmxhc3RDbG9zZWQgJiYgY2FsbEZhY3RvcnkuaXNDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBTdWNjZXNzZnVsbHkgcmVjb25uZWN0ZWQgdG8gJHtub2RlSWR9LCB3aGljaCBoYXMgYmVlbiBjbG9zZWQgZm9yICR7Zm9ybWF0VGltZShEYXRlLm5vdygpIC0gY2FsbEZhY3RvcnkubGFzdENsb3NlZCl9YCwgeyBub2RlSWQgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FsbEZhY3RvcnkuaXNDb25uZWN0ZWQgJiYgbmV3V2ViU29ja2V0LnByb3RvY29sKSB7XG4gICAgICAgICAgICBsZXQgZGVjb2RlZCA9IGRlY29kZVByb3RvY29sKG5ld1dlYlNvY2tldC5wcm90b2NvbCk7XG4gICAgICAgICAgICBpZiAoZGVjb2RlZCkge1xuICAgICAgICAgICAgICAgIGNhbGxGYWN0b3J5LnJlY2VpdmVkSW5pdGlhbGl6ZVN0YXRlID0ge1xuICAgICAgICAgICAgICAgICAgICBzdXBwb3J0c0xaNDogZGVjb2RlZC5mbGFncy5zZXJ2ZXJMWjQsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBjYWxsRmFjdG9yeS5wcm90b2NvbE5lZ290aWF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGlmIChTb2NrZXRGdW5jdGlvbi5sb2dNZXNzYWdlcykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhncmVlbihgTmVnb3RpYXRlZCBwcm90b2NvbCB3aXRoICR7bmljZUNvbm5lY3Rpb25OYW1lfTogdGFyZ2V0PSR7ZGVjb2RlZC50YXJnZXR9LCBjbGllbnRMWjQ9JHtkZWNvZGVkLmZsYWdzLmNsaWVudExaNH0sIHNlcnZlckxaND0ke2RlY29kZWQuZmxhZ3Muc2VydmVyTFo0fWApKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBCQVNFX0xFTkdUSF9PRkZTRVQgPSAzMjRfNDMyXzQ2MV81OTJfNjEyO1xuICAgIHR5cGUgTWVzc2FnZUhlYWRlciA9IHtcbiAgICAgICAgdHlwZTogXCJzZXJpYWxpemVkXCI7XG4gICAgICAgIGJ1ZmZlckNvdW50OiBudW1iZXI7XG4gICAgfSB8IHtcbiAgICAgICAgdHlwZTogXCJCdWZmZXJbXVwiIHwgXCJCdWZmZXJcIjtcbiAgICAgICAgYnVmZmVyQ291bnQ6IG51bWJlcjtcbiAgICAgICAgYnVmZmVyTGVuZ3Rocz86IG51bWJlcltdO1xuICAgICAgICBtZXRhZGF0YTogT21pdDxJbnRlcm5hbFJldHVyblR5cGUsIFwicmVzdWx0XCI+O1xuICAgIH07XG4gICAgbGV0IHNlbmRJblNlcmlhbCA9IHJ1bkluU2VyaWFsKGFzeW5jICh2YWw6ICgpID0+IFByb21pc2U8dm9pZD4pID0+IHZhbCgpKTtcbiAgICBhc3luYyBmdW5jdGlvbiBzZW5kUmF3KGRhdGE6IChzdHJpbmcgfCBCdWZmZXIpW10pIHtcbiAgICAgICAgaWYgKCF3ZWJTb2NrZXRQcm9taXNlKSB7XG4gICAgICAgICAgICBpZiAoY2FuUmVjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgd2ViU29ja2V0UHJvbWlzZSA9IHRyeVRvUmVjb25uZWN0KCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHNlbmQgZGF0YSB0byAke25pY2VDb25uZWN0aW9uTmFtZX0gYXMgdGhlIGNvbm5lY3Rpb24gaGFzIGNsb3NlZGApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGxldCB3ZWJTb2NrZXQgPSBhd2FpdCB3ZWJTb2NrZXRQcm9taXNlO1xuICAgICAgICBhd2FpdCBzZW5kSW5TZXJpYWwoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgZm9yIChsZXQgZCBvZiBkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKGQubGVuZ3RoID4gMTAwMCAqIDEwMDAgKiAxMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgU2VuZGluZyBsYXJnZSBwYWNrZXQgJHtmb3JtYXROdW1iZXIoZC5sZW5ndGgpfUIgdG8gJHtub2RlSWR9IGF0ICR7RGF0ZS5ub3coKX1gKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBOT1RFOiBJZiBvdXIgbGF0ZW5jeSBpcyA1MDBtcywgd2l0aCAxME1CL3MsIHRoZW4gd2UgbmVlZCBhIGhpZ2ggd2F0ZXJcbiAgICAgICAgICAgICAgICAvLyAgbWFyayBvZiBhdCBsZWFzdCA1TUIsIG90aGVyd2lzZSBvdXIgY29ubmVjdGlvbiBpcyBzbG93ZWQgZG93bi5cbiAgICAgICAgICAgICAgICAvLyAgLSBVc2luZyB0aGUgYWN0dWFsIGhpZ2ggd2F0ZXIgbWFyayBpcyB0b28gZGlmZmljdWx0LCBhcyB3ZSByZWNlaXZlIGluY29taW5nIGNvbm5lY3Rpb25zLlxuICAgICAgICAgICAgICAgIC8vICAgICAgVGhpcyBpcyBhbHNvIGVhc2llciB0byBjb25maWd1cmUsIGFuZCB3ZSBjYW4gZHluYW1pY2FsbHkgY2hhbmdlIGl0IGlmIHdlIGhhdmUgdG8uXG4gICAgICAgICAgICAgICAgLy8gTk9URTogSW4gcHJhY3RpY2Ugd2Ugb25seSBoaXQgdGhpcyB3aGVuIHNlbmRpbmcgbGFyZ2UgQnVmZmVycyAofjMwTUIpLCBzbyBsb3cgdmFsdWVzXG4gICAgICAgICAgICAgICAgLy8gIGFyZSBlcXVpdmFsZW50IHRvIHdhaXRpbmcgZm9yIGRyYWluLiBXZSB3YW50IHRvIGF2b2lkIHdhaXRpbmcgZm9yIGRyYWluLCBzbyB3ZSB1c2UgYSBoaWdoIHZhbHVlLlxuICAgICAgICAgICAgICAgIGNvbnN0IG1heFdyaXRlQnVmZmVyID0gMTI4ICogMTAyNCAqIDEwMjQ7XG4gICAgICAgICAgICAgICAgd2ViU29ja2V0LnNlbmQoZCk7XG5cbiAgICAgICAgICAgICAgICBsZXQgc29ja2V0ID0gd2ViU29ja2V0Ll9zb2NrZXQ7XG4gICAgICAgICAgICAgICAgaWYgKHNvY2tldCkge1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc29ja2V0LndyaXRhYmxlTGVuZ3RoID4gbWF4V3JpdGVCdWZmZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5PVEU6IFdhaXRpbmcgMW1zIHByb2JhYmx5IHdhaXRzIG1vcmUgbGlrZSAxNm1zLlxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UociA9PiBzZXRUaW1lb3V0KHIsIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGFzeW5jIGZ1bmN0aW9uIHNlbmQoZGF0YTogQnVmZmVyW10pIHtcbiAgICAgICAgYXdhaXQgc2VuZFJhdyhbXG4gICAgICAgICAgICAoZGF0YS5sZW5ndGggKyBCQVNFX0xFTkdUSF9PRkZTRVQpLnRvU3RyaW5nKCksXG4gICAgICAgICAgICAuLi5kYXRhLFxuICAgICAgICBdKTtcbiAgICB9XG4gICAgYXN5bmMgZnVuY3Rpb24gc2VuZFdpdGhIZWFkZXIoZGF0YTogQnVmZmVyW10sIGhlYWRlcjogTWVzc2FnZUhlYWRlcikge1xuICAgICAgICBpZiAoZGF0YS5zb21lKHggPT4geC5sZW5ndGggPiBTb2NrZXRGdW5jdGlvbi5NQVhfTUVTU0FHRV9TSVpFICogMS41KSkge1xuICAgICAgICAgICAgaWYgKGhlYWRlci50eXBlID09PSBcIkJ1ZmZlclwiIHx8IGhlYWRlci50eXBlID09PSBcIkJ1ZmZlcltdXCIpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXIuYnVmZmVyTGVuZ3RocyA9IGRhdGEubWFwKHggPT4geC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGxldCBmaXRCdWZmZXJzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGJ1ZiBvZiBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChidWYubGVuZ3RoID4gU29ja2V0RnVuY3Rpb24uTUFYX01FU1NBR0VfU0laRSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAob2Zmc2V0IDwgYnVmLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpdEJ1ZmZlcnMucHVzaChidWYuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBTb2NrZXRGdW5jdGlvbi5NQVhfTUVTU0FHRV9TSVpFKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ICs9IFNvY2tldEZ1bmN0aW9uLk1BWF9NRVNTQUdFX1NJWkU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaXRCdWZmZXJzLnB1c2goYnVmKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkYXRhID0gZml0QnVmZmVycztcbiAgICAgICAgICAgICAgICBoZWFkZXIuYnVmZmVyQ291bnQgPSBmaXRCdWZmZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3Qgc2VuZCBsYXJnZSBhbW91bnRzIG9mIGRhdGEgdW5sZXNzIHdlIGFyZSByZXR1cm5pbmcgQnVmZmVyIG9yIEJ1ZmZlcltdYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgKHRvdGFsUmVzdWx0U2l6ZSA+IFNvY2tldEZ1bmN0aW9uLk1BWF9NRVNTQUdFX1NJWkUgKiAxLjUpIHtcbiAgICAgICAgLy8gU3BsaXQgdXAgQnVmZmVyW10gaWYgdGhleSBhcmUgdG9vIGxhcmdlXG4gICAgICAgIGF3YWl0IHNlbmRSYXcoW1xuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoaGVhZGVyKSxcbiAgICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICAvLyBJTVBPUlRBTlQhIE5FVkVSIGFsbG93IGZvciByZWNvbm5lY3Rpb24gb2YgY2xpZW50IGlkcy4gQSBsb3Qgb2YgY29kZSBkZXBlbmRzIG9uIHRoZSBmYWN0IHRoYXQgY2xpZW50cyB3aWxsIHJlY29ubmVjdCB3aXRoIGEgbmV3IGNsaWVudCBub2RlIGlkIHdoZW4gdGhleSBkaXNjb25uZWN0IVxuICAgIGFzeW5jIGZ1bmN0aW9uIHRyeVRvUmVjb25uZWN0KCk6IFByb21pc2U8U2VuZGVySW50ZXJmYWNlPiB7XG4gICAgICAgIC8vIERvbid0IHRyeSB0byByZWNvbm5lY3QgdG9vIG9mdGVuIVxuICAgICAgICBsZXQgdGltZVNpbmNlTGFzdEF0dGVtcHQgPSBEYXRlLm5vdygpIC0gbGFzdENvbm5lY3Rpb25BdHRlbXB0O1xuICAgICAgICBpZiAodGltZVNpbmNlTGFzdEF0dGVtcHQgPCBNSU5fUkVUUllfREVMQVkpIHtcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gc2V0VGltZW91dChyLCBNSU5fUkVUUllfREVMQVkgLSB0aW1lU2luY2VMYXN0QXR0ZW1wdCkpO1xuICAgICAgICB9XG4gICAgICAgIGxhc3RDb25uZWN0aW9uQXR0ZW1wdCA9IERhdGUubm93KCk7XG5cbiAgICAgICAgLy8gVHJ5IGFsdGVybmF0ZXMsIGFuZCBpZiBhbnkgd29yaywgdXNlIHRoZW0uXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQgYWx0ZXJuYXRlcyA9IGF3YWl0IFNvY2tldEZ1bmN0aW9uLkdFVF9BTFRFUk5BVEVfTk9ERV9JRFMobm9kZUlkKTtcbiAgICAgICAgICAgIGlmIChhbHRlcm5hdGVzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgYWx0ZXJuYXRlTm9kZUlkIG9mIGFsdGVybmF0ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG5ld1dlYlNvY2tldCA9IGNyZWF0ZVdlYnNvY2tldChhbHRlcm5hdGVOb2RlSWQsIHByb3Bvc2VQcm90b2NvbHMoaXNOb2RlKCkgPyBub2RlSWQgOiB1bmRlZmluZWQsIHsgbHo0OiB0cnVlIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgaW5pdGlhbGl6ZVdlYnNvY2tldChuZXdXZWJTb2NrZXQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjYWxsRmFjdG9yeS5pc0Nvbm5lY3RlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ld1dlYlNvY2tldDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIGdldHRpbmcgYWx0ZXJuYXRlIG5vZGUgSURzXCIsIGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5ld1dlYlNvY2tldCA9IGNyZWF0ZVdlYnNvY2tldChub2RlSWQsIHByb3Bvc2VQcm90b2NvbHMoIVNvY2tldEZ1bmN0aW9uLmlzQ2xpZW50KCkgPyBub2RlSWQgOiB1bmRlZmluZWQsIHsgbHo0OiB0cnVlIH0pKTtcbiAgICAgICAgYXdhaXQgaW5pdGlhbGl6ZVdlYnNvY2tldChuZXdXZWJTb2NrZXQpO1xuXG4gICAgICAgIHJldHVybiBuZXdXZWJTb2NrZXQ7XG4gICAgfVxuXG4gICAgbGV0IHBlbmRpbmdDYWxsOiBNZXNzYWdlSGVhZGVyICYge1xuICAgICAgICBidWZmZXJzOiBCdWZmZXJbXTtcbiAgICAgICAgZmlyc3RSZWNlaXZlZFRpbWU/OiBudW1iZXI7XG4gICAgfSB8IHVuZGVmaW5lZDtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NQZW5kaW5nQ2FsbCgpIHtcbiAgICAgICAgaWYgKCFwZW5kaW5nQ2FsbCkgdGhyb3cgbmV3IEVycm9yKGBObyBwZW5kaW5nIGNhbGxgKTtcbiAgICAgICAgbGV0IGN1cnJlbnRDYWxsID0gcGVuZGluZ0NhbGw7XG4gICAgICAgIHBlbmRpbmdDYWxsID0gdW5kZWZpbmVkO1xuICAgICAgICBsZXQgY3VycmVudEJ1ZmZlcnMgPSBjdXJyZW50Q2FsbC5idWZmZXJzO1xuICAgICAgICBsZXQgY2FsbDogSW50ZXJuYWxDYWxsVHlwZSB8IEludGVybmFsUmV0dXJuVHlwZTtcbiAgICAgICAgbGV0IHJlc3VsdFNpemU6IG51bWJlcjtcbiAgICAgICAgbGV0IHRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICBpZiAoY3VycmVudENhbGwudHlwZSA9PT0gXCJCdWZmZXJcIiB8fCBjdXJyZW50Q2FsbC50eXBlID09PSBcIkJ1ZmZlcltdXCIpIHtcbiAgICAgICAgICAgIGxldCByZXN1bHQ6IEJ1ZmZlciB8IEJ1ZmZlcltdID0gY3VycmVudEJ1ZmZlcnM7XG4gICAgICAgICAgICBpZiAoY3VycmVudENhbGwuYnVmZmVyTGVuZ3Rocykge1xuICAgICAgICAgICAgICAgIGxldCBwZW5kaW5nQnVmZmVycyA9IGN1cnJlbnRCdWZmZXJzO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHRha2VCdWZmZXIobGVuOiBudW1iZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxlbkxlZnQgPSBsZW47XG4gICAgICAgICAgICAgICAgICAgIGxldCBidWZmZXJzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobGVuTGVmdCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBidWYgPSBjdXJyZW50QnVmZmVycy5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFidWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBlbm91Z2ggYnVmZmVycyByZWNlaXZlZC5gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChidWYubGVuZ3RoID4gbGVuTGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcnMucHVzaChidWYuc2xpY2UoMCwgbGVuTGVmdCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRCdWZmZXJzLnVuc2hpZnQoYnVmLnNsaWNlKGxlbkxlZnQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVycy5wdXNoKGJ1Zik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuTGVmdCAtPSBidWYubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChidWZmZXJzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcnNbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoYnVmZmVycyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGN1cnJlbnRDYWxsLmJ1ZmZlckxlbmd0aHMubWFwKHRha2VCdWZmZXIpO1xuICAgICAgICAgICAgICAgIGlmIChwZW5kaW5nQnVmZmVycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVjZWl2ZWQgdG9vIG1hbnkgYnVmZmVycy5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHRTaXplID0gcmVzdWx0Lm1hcCh4ID0+IHgubGVuZ3RoKS5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50Q2FsbC50eXBlID09PSBcIkJ1ZmZlclwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0WzBdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEJ1ZmZlci5jb25jYXQocmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsID0ge1xuICAgICAgICAgICAgICAgIC4uLmN1cnJlbnRDYWxsLm1ldGFkYXRhLFxuICAgICAgICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRTaXplID0gY3VycmVudEJ1ZmZlcnMubWFwKHggPT4geC5sZW5ndGgpLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuICAgICAgICAgICAgY2FsbCA9IGF3YWl0IFNvY2tldEZ1bmN0aW9uLldJUkVfU0VSSUFMSVpFUi5kZXNlcmlhbGl6ZShjdXJyZW50QnVmZmVycykgYXMgSW50ZXJuYWxDYWxsVHlwZSB8IEludGVybmFsUmV0dXJuVHlwZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcGFyc2VUaW1lID0gRGF0ZS5ub3coKSAtIHRpbWU7XG4gICAgICAgIGZvciAobGV0IGNhbGxiYWNrIG9mIFNvY2tldEZ1bmN0aW9uLnRyYWNrTWVzc2FnZVNpemVzLmRvd25sb2FkKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhyZXN1bHRTaXplKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZWNlaXZlU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7XG4gICAgICAgICAgICB1bmNvbXByZXNzZWRTaXplOiByZXN1bHRTaXplLFxuICAgICAgICAgICAgY29tcHJlc3NlZFNpemU6IHJlc3VsdFNpemUsXG4gICAgICAgIH07XG4gICAgICAgIGxldCBzZW5kU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7XG4gICAgICAgICAgICB1bmNvbXByZXNzZWRTaXplOiAwLFxuICAgICAgICAgICAgY29tcHJlc3NlZFNpemU6IDAsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGNhbGwuaXNSZXR1cm4pIHtcbiAgICAgICAgICAgIC8vIFRvbGVyYXRlIHRoZSBsZWdhY3kgaW5pdGlhbGl6ZSBwYWNrZXQgZnJvbSBvbGQgcGVlcnMg4oCUIHNpbGVudGx5XG4gICAgICAgICAgICAvLyBpZ25vcmUgc28gaXQgZG9lc24ndCBnZXQgbG9nZ2VkIGFzIGFuIHVua25vd24gY2FsbC4gT3VyIGFjdHVhbFxuICAgICAgICAgICAgLy8gaW5pdGlhbGl6ZSBzdGF0ZSBjb21lcyBmcm9tIFNlYy1XZWJTb2NrZXQtUHJvdG9jb2wgbmVnb3RpYXRpb24uXG4gICAgICAgICAgICBpZiAoY2FsbC5zZXFOdW0gPT09IElOSVRJQUxJWkVfU1RBVEVfU0VRX05VTSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBjYWxsYmFja09iaiA9IHBlbmRpbmdDYWxscy5nZXQoY2FsbC5zZXFOdW0pO1xuICAgICAgICAgICAgaWYgKHBhcnNlVGltZSA+IFNvY2tldEZ1bmN0aW9uLldJUkVfV0FSTl9USU1FKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVkKGBTbG93IHBhcnNlLCB0b29rICR7cGFyc2VUaW1lfW1zIHRvIHBhcnNlICR7cmVzdWx0U2l6ZX0gYnl0ZXMsIGZvciByZWNlaXZpbmcgcmVzdWx0IG9mIGNhbGwgdG8gJHtjYWxsYmFja09iaj8uY2FsbC5jbGFzc0d1aWR9LiR7Y2FsbGJhY2tPYmo/LmNhbGwuZnVuY3Rpb25OYW1lfWApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY2FsbGJhY2tPYmopIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhibHVlKGBHb3QgcmV0dXJuIGZvciB1bmtub3duIGNhbGwgJHtjYWxsLnNlcU51bX0gKGNyZWF0ZWQgYXQgdGltZSAke25ldyBEYXRlKGNhbGwuc2VxTnVtKX0pLCAke25vZGVJZH0gLyAke2xvY2FsTm9kZUlkfWApKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoU29ja2V0RnVuY3Rpb24ubG9nTWVzc2FnZXMpIHtcbiAgICAgICAgICAgICAgICBsZXQgY2FsbCA9IGNhbGxiYWNrT2JqLmNhbGw7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coYFNJWkVcXHQkeyhmb3JtYXROdW1iZXJTdWZmaXhlZChyZXN1bHRTaXplKSArIFwiQlwiKS5wYWRFbmQoNCwgXCIgXCIpfVxcdCR7Zm9ybWF0TnVtYmVyKGN1cnJlbnRCdWZmZXJzLmxlbmd0aCl9IGJ1ZmZlcnNcXHRSRVRVUk5cXHQke2NhbGwuY2xhc3NHdWlkfS4ke2NhbGwuZnVuY3Rpb25OYW1lfSBhdCAke0RhdGUubm93KCl9LCAoJHtub2RlSWR9IC8gJHtsb2NhbE5vZGVJZH0pYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbC5pc1Jlc3VsdENvbXByZXNzZWQgPT09IFwiTFo0XCIpIHtcbiAgICAgICAgICAgICAgICBjYWxsLnJlc3VsdCA9IGF3YWl0IGRlY29tcHJlc3NPYmpMWjQoY2FsbC5yZXN1bHQgYXMgQnVmZmVyW10sIHJlY2VpdmVTdGF0cyk7XG4gICAgICAgICAgICAgICAgY2FsbC5pc1Jlc3VsdENvbXByZXNzZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNhbGwuaXNSZXN1bHRDb21wcmVzc2VkID09PSBcInppcFwiIHx8IGNhbGwuaXNSZXN1bHRDb21wcmVzc2VkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgY2FsbC5yZXN1bHQgPSBhd2FpdCBkZWNvbXByZXNzT2JqKGNhbGwucmVzdWx0IGFzIEJ1ZmZlciwgcmVjZWl2ZVN0YXRzKTtcbiAgICAgICAgICAgICAgICBjYWxsLmlzUmVzdWx0Q29tcHJlc3NlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrT2JqLmNhbGxiYWNrKGNhbGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNhbGwuaXNBcmdzQ29tcHJlc3NlZCA9PT0gXCJMWjRcIikge1xuICAgICAgICAgICAgICAgIGNhbGwuYXJncyA9IGF3YWl0IGRlY29tcHJlc3NPYmpMWjQoY2FsbC5hcmdzIGFzIGFueSBhcyBCdWZmZXJbXSwgc2VuZFN0YXRzKSBhcyBhbnk7XG4gICAgICAgICAgICAgICAgY2FsbC5pc0FyZ3NDb21wcmVzc2VkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjYWxsLmlzQXJnc0NvbXByZXNzZWQgPT09IFwiemlwXCIgfHwgY2FsbC5pc0FyZ3NDb21wcmVzc2VkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgY2FsbC5hcmdzID0gYXdhaXQgZGVjb21wcmVzc09iaihjYWxsLmFyZ3MgYXMgYW55IGFzIEJ1ZmZlciwgc2VuZFN0YXRzKSBhcyBhbnk7XG4gICAgICAgICAgICAgICAgY2FsbC5pc0FyZ3NDb21wcmVzc2VkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFNvY2tldEZ1bmN0aW9uLmxvZ01lc3NhZ2VzKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coYFNJWkVcXHQkeyhmb3JtYXROdW1iZXJTdWZmaXhlZChyZXN1bHRTaXplKSArIFwiQlwiKS5wYWRFbmQoNCwgXCIgXCIpfVxcdEVWQUxVQVRFXFx0JHtjYWxsLmNsYXNzR3VpZH0uJHtjYWxsLmZ1bmN0aW9uTmFtZX0gYXQgJHtEYXRlLm5vdygpfSwgKCR7bm9kZUlkfSAvICR7bG9jYWxOb2RlSWR9KWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcnNlVGltZSA+IFNvY2tldEZ1bmN0aW9uLldJUkVfV0FSTl9USU1FKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVkKGBTbG93IHBhcnNlLCB0b29rICR7cGFyc2VUaW1lfW1zIHRvIHBhcnNlICR7cmVzdWx0U2l6ZX0gYnl0ZXMsIGZvciBjYWxsIHRvICR7Y2FsbC5jbGFzc0d1aWR9LiR7Y2FsbC5mdW5jdGlvbk5hbWV9YCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgcmVzcG9uc2U6IEludGVybmFsUmV0dXJuVHlwZTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgU29ja2V0RnVuY3Rpb24uVE9UQUxfQ0FMTFMrKztcbiAgICAgICAgICAgICAgICBsZXQgcmVzdWx0ID0gYXdhaXQgcGVyZm9ybUxvY2FsQ2FsbCh7IGNhbGwsIGNhbGxlcjogY2FsbGVyQ29udGV4dCB9KTtcbiAgICAgICAgICAgICAgICByZXNwb25zZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgaXNSZXR1cm46IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICAgICAgICAgICAgc2VxTnVtOiBjYWxsLnNlcU51bSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmIChTb2NrZXRGdW5jdGlvbi5sb2dNZXNzYWdlcykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgdGltZVRha2VuID0gRGF0ZS5ub3coKSAtIHRpbWU7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBEVVJcXHQkeyhmb3JtYXRUaW1lKHRpbWVUYWtlbikpLnBhZEVuZCg2LCBcIiBcIil9XFx0RklOSVNIXFx0JHtjYWxsLmNsYXNzR3VpZH0uJHtjYWxsLmZ1bmN0aW9uTmFtZX0gYXQgJHtEYXRlLm5vdygpfSwgKCR7bm9kZUlkfSAvICR7bG9jYWxOb2RlSWR9KWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2FsbEZhY3RvcnkucmVjZWl2ZWRJbml0aWFsaXplU3RhdGU/LnN1cHBvcnRzTFo0KSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb21wcmVzc01vZGUgPSBzaG91bGRDb21wcmVzc0NhbGwoY2FsbCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb21wcmVzc01vZGUgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5yZXN1bHQgPSBhd2FpdCBjb21wcmVzc09iakxaNChyZXNwb25zZS5yZXN1bHQsIHNlbmRTdGF0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5pc1Jlc3VsdENvbXByZXNzZWQgPSBcIkxaNFwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNob3VsZENvbXByZXNzQ2FsbChjYWxsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UucmVzdWx0ID0gYXdhaXQgY29tcHJlc3NPYmoocmVzcG9uc2UucmVzdWx0LCBzZW5kU3RhdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuaXNSZXN1bHRDb21wcmVzc2VkID0gXCJ6aXBcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlID0ge1xuICAgICAgICAgICAgICAgICAgICBpc1JldHVybjogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIHNlcU51bTogY2FsbC5zZXFOdW0sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBlLnN0YWNrLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbGV0IHN0YXJ0ID0gdGltZTtcbiAgICAgICAgICAgICAgICBsZXQgZW5kID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBmbmMgb2YgU29ja2V0RnVuY3Rpb24udHJhY2tNZXNzYWdlU2l6ZXMuY2FsbFRpbWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZuYyh7IHN0YXJ0LCBlbmQgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgc2l6ZSA9IDA7XG5cbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5yZXN1bHQgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgICAgICAgICAgICBsZXQgeyByZXN1bHQsIC4uLnJlbWFpbmluZyB9ID0gcmVzcG9uc2U7XG4gICAgICAgICAgICAgICAgc2l6ZSA9IHJlc3VsdC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgYXdhaXQgc2VuZFdpdGhIZWFkZXIoW3Jlc3VsdF0sIHsgdHlwZTogXCJCdWZmZXJcIiwgYnVmZmVyQ291bnQ6IDEsIG1ldGFkYXRhOiByZW1haW5pbmcgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocmVzcG9uc2UucmVzdWx0KSAmJiByZXNwb25zZS5yZXN1bHQuZXZlcnkoeCA9PiB4IGluc3RhbmNlb2YgQnVmZmVyKSkge1xuICAgICAgICAgICAgICAgIGxldCB7IHJlc3VsdCwgLi4ucmVtYWluaW5nIH0gPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCByIG9mIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBzaXplICs9IHIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhd2FpdCBzZW5kV2l0aEhlYWRlcihyZXN1bHQsIHsgdHlwZTogXCJCdWZmZXJbXVwiLCBidWZmZXJDb3VudDogcmVzdWx0Lmxlbmd0aCwgbWV0YWRhdGE6IHJlbWFpbmluZyB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgTElNSVQgPSBnZXRDYWxsRmxhZ3MoY2FsbCk/LnJlc3BvbnNlTGltaXQgfHwgU29ja2V0RnVuY3Rpb24uTUFYX01FU1NBR0VfU0laRSAqIDEuNTtcbiAgICAgICAgICAgICAgICBsZXQgcmVzdWx0OiBCdWZmZXJbXSA9IGF3YWl0IFNvY2tldEZ1bmN0aW9uLldJUkVfU0VSSUFMSVpFUi5zZXJpYWxpemUocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGxldCB0b3RhbFJlc3VsdFNpemUgPSByZXN1bHQubWFwKHggPT4geC5sZW5ndGgpLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuICAgICAgICAgICAgICAgIGlmICh0b3RhbFJlc3VsdFNpemUgPiBMSU1JVCkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUmV0dXJuOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXFOdW06IGNhbGwuc2VxTnVtLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IG5ldyBFcnJvcihgUmVzcG9uc2UgdG9vIGxhcmdlIHRvIHNlbmQuIFJldHVybiBCdWZmZXJbXSB0byBleGNlZWQgdGhlIGxpbWl0cywgb3Igc2V0IHJlc3BvbnNlTGltaXQgd2hlbiByZWdpc3RlcmluZyB0aGUgY29sbGVjdGlvbi4gJHtjYWxsLmNsYXNzR3VpZH0uJHtjYWxsLmZ1bmN0aW9uTmFtZX0sIHNpemU6ICR7Zm9ybWF0TnVtYmVyKHRvdGFsUmVzdWx0U2l6ZSl9ID4gJHtmb3JtYXROdW1iZXIoU29ja2V0RnVuY3Rpb24uTUFYX01FU1NBR0VfU0laRSl9LiBJZiB5b3UgbmVlZCB0byBoYW5kbGUgdmVyeSBsYXJnZSBzdGF0aWMgZGF0YSB1c2Ugc29tZSBleHRlcm5hbCBzZXJ2aWNlLCBzdWNoIGFzIEJhY2tibGF6ZSBCMiBvciBBV1MgUzMuIE9yLCBpZiBhYnNvbHV0ZWx5IHJlcXVpcmVkLCBzZXQgU29ja2V0RnVuY3Rpb24uTUFYX01FU1NBR0VfU0laRSB0byBhIGhpZ2hlciB2YWx1ZS5gKS5zdGFjayxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgU29ja2V0RnVuY3Rpb24uV0lSRV9TRVJJQUxJWkVSLnNlcmlhbGl6ZShyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAobGV0IHIgb2YgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIHNpemUgKz0gci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF3YWl0IHNlbmQocmVzdWx0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgd2UgaGF2ZSBubyBzaXplLCB0aGVuIGl0J3MgcHJvYmFibHkgdW5jb21wcmVzc2VkXG4gICAgICAgICAgICBpZiAoIXNlbmRTdGF0cy5jb21wcmVzc2VkU2l6ZSkge1xuICAgICAgICAgICAgICAgIHNlbmRTdGF0cy5jb21wcmVzc2VkU2l6ZSA9IHNpemU7XG4gICAgICAgICAgICAgICAgc2VuZFN0YXRzLnVuY29tcHJlc3NlZFNpemUgPSBzaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgYWRkU2VuZFN0YXRzKHNlbmRTdGF0cyk7XG4gICAgICAgIGFkZFJlY2VpdmVTdGF0cyhyZWNlaXZlU3RhdHMpO1xuICAgIH1cblxuICAgIGxldCBjbGllbnRzaWRlU2VyaWFsID0gcnVuSW5TZXJpYWwoYXN5bmMgPFQ+KHZhbDogUHJvbWlzZTxUPikgPT4gdmFsKTtcbiAgICBhc3luYyBmdW5jdGlvbiBvbk1lc3NhZ2UobWVzc2FnZTogd3MuUmF3RGF0YSB8IHdzLk1lc3NhZ2VFdmVudCB8IHN0cmluZykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlID09PSBcIm9iamVjdFwiICYmIFwiZGF0YVwiIGluIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gbWVzc2FnZS5kYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRXh0cmEgY2xpZW5zaWRlIHBhcnNpbmcgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgIGlmICghaXNOb2RlKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBJbW1lZGlhdGVseSBzdGFydCB0aGUgYXJyYXlCdWZmZXIgY29udmVyc2lvbi4gVGhpcyBzaG91bGQgYmUgZmFzdCwgYnV0Li4uXG4gICAgICAgICAgICAgICAgLy8gIG1heWJlIHdlIHdpbGwgYWRkIG1vcmUgaGVyZSwgYW5kIHNvIGRvaW5nIGl0IGluIHBhcmFsbGVsIG1pZ2h0IGJlIHVzZWZ1bC5cbiAgICAgICAgICAgICAgICBsZXQgZml4TWVzc2FnZUJsb2IgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZSBpbnN0YW5jZW9mIEJsb2IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShhd2FpdCBtZXNzYWdlLmFycmF5QnVmZmVyKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIGZvcmNlIHRoZSByZXN1bHRzIHRvIGJlIGluIHNlcmlhbCwgb3RoZXJ3aXNlIHN0cmluZ3MgbGVhcGZyb2dcbiAgICAgICAgICAgICAgICAvLyAgYWhlYWQgb2YgYnVmZmVycywgd2hpY2ggYnJlYWtzIHRoaW5ncy5cbiAgICAgICAgICAgICAgICBhd2FpdCBjbGllbnRzaWRlU2VyaWFsKGZpeE1lc3NhZ2VCbG9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLnN0YXJ0c1dpdGgoXCJ7XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvYmogPSBKU09OLnBhcnNlKG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nQ2FsbCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLm9iaixcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcnM6IFtdLFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjb3VudCA9IHBhcnNlSW50KG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNOYU4oY291bnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbWVzc2FnZSBjb3VudCAke21lc3NhZ2V9YCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50IDwgQkFTRV9MRU5HVEhfT0ZGU0VUKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbWVzc2FnZSBjb3VudCAke21lc3NhZ2V9YCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY291bnQgLT0gQkFTRV9MRU5HVEhfT0ZGU0VUO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY291bnQgPiAxMDAwICogMTAwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIG1lc3NhZ2UgY291bnQgJHtjb3VudH1gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nQ2FsbCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlcnM6IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyQ291bnQ6IGNvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzZXJpYWxpemVkXCIsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwZW5kaW5nQ2FsbD8uYnVmZmVyQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcHJvY2Vzc1BlbmRpbmdDYWxsKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlIGluc3RhbmNlb2YgQnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFwZW5kaW5nQ2FsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlY2VpdmVkIGRhdGEgd2l0aG91dCBzaXplICR7bWVzc2FnZS5ieXRlTGVuZ3RofUIsIGZpcnN0IDEwMCBieXRlczogJHttZXNzYWdlLnNsaWNlKDAsIDEwMCkudG9TdHJpbmcoXCJoZXhcIil9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCB0b3RhbFNpemUgPSBtZXNzYWdlLmJ5dGVMZW5ndGggKyBwZW5kaW5nQ2FsbC5idWZmZXJzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIubGVuZ3RoLCAwKTtcbiAgICAgICAgICAgICAgICBpZiAodG90YWxTaXplID4gMTAwMCAqIDEwMDAgKiAxMCB8fCBwZW5kaW5nQ2FsbC5idWZmZXJDb3VudCA+IDEwMDAgJiYgKHBlbmRpbmdDYWxsLmJ1ZmZlcnMubGVuZ3RoICUgMTAwID09PSAwKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocGVuZGluZ0NhbGwuYnVmZmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBSZWNlaXZlZCBsYXJnZS9tYW55IHBhY2tldHMgJHtmb3JtYXROdW1iZXIodG90YWxTaXplKX1CICgke3BlbmRpbmdDYWxsLmJ1ZmZlcnMubGVuZ3RofSAvICR7cGVuZGluZ0NhbGwuYnVmZmVyQ291bnR9KSBhdCAke0RhdGUubm93KCl9YCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZWxhcHNlZCA9IERhdGUubm93KCkgLSAocGVuZGluZ0NhbGwuZmlyc3RSZWNlaXZlZFRpbWUgfHwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgUmVjZWl2ZWQgbGFyZ2UvbWFueSBwYWNrZXRzICR7Zm9ybWF0TnVtYmVyKHRvdGFsU2l6ZSl9QiAoJHtwZW5kaW5nQ2FsbC5idWZmZXJzLmxlbmd0aH0gLyAke3BlbmRpbmdDYWxsLmJ1ZmZlckNvdW50fSkgYWZ0ZXIgJHtmb3JtYXRUaW1lKGVsYXBzZWQpfWApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwZW5kaW5nQ2FsbC5idWZmZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nQ2FsbC5maXJzdFJlY2VpdmVkVGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBlbmRpbmdDYWxsLmJ1ZmZlcnMucHVzaChtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBpZiAocGVuZGluZ0NhbGwuYnVmZmVycy5sZW5ndGggIT09IHBlbmRpbmdDYWxsLmJ1ZmZlckNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBwcm9jZXNzUGVuZGluZ0NhbGwoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuaGFuZGxlZCBkYXRhIHR5cGUgJHt0eXBlb2YgbWVzc2FnZX1gKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBsZXQgZXJyID0gZS5zdGFjayB8fCBlLm1lc3NhZ2UgfHwgZTtcbiAgICAgICAgICAgIC8vIE5PVEU6IEknbSBsb29raW5nIGZvciBhbGwgdHlwZXMgb2YgZXJyb3JzIGhlcmUgKHNwZWNpZmljYWxseSwgLnNlbmQgZXJyb3JzKSwgaW4gY2FzZVxuICAgICAgICAgICAgLy8gIHRoZXJlIGFyZSBlcnJvcnMgSSBzaG91bGQgYmUgaGFuZGxpbmcuXG4gICAgICAgICAgICBpZiAoZXJyLnN0YXJ0c1dpdGgoXCJFcnJvcjogQ2Fubm90IHNlbmQgZGF0YSB0b1wiKSAmJiBlcnIuaW5jbHVkZXMoXCJhcyB0aGUgY29ubmVjdGlvbiBoYXMgY2xvc2VkXCIpKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBmaW5lLCBqdXN0IGlnbm9yZSBpdFxuICAgICAgICAgICAgfSBlbHNlIGlmIChlcnIuaW5jbHVkZXMoXCJUaGUgcmVxdWVzdGVkIGZpbGUgY291bGQgbm90IGJlIHJlYWQsIHR5cGljYWxseSBkdWUgdG8gcGVybWlzc2lvbiBwcm9ibGVtcyB0aGF0IGhhdmUgb2NjdXJyZWQgYWZ0ZXIgYSByZWZlcmVuY2UgdG8gYSBmaWxlIHdhcyBhY3F1aXJlZC5cIikpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBXZWJTb2NrZXQgZGF0YSB3YXMgZHJvcHBlZCBieSB0aGUgYnJvd3NlciBkdWUgdG8gZXhjZWVkaW5nIHRoZSBCbG9iIGxpbWl0LiBFaXRoZXIgeW91IGFyZSBhYm91dCB0byBydW4gb3V0IG9mIG1lbW9yeSwgb3IgeW91IGhpdCB0aGUgbXVjaCBsb3dlciBJbmNvZ25pdG8gQmxvYiBsaW1pdC4gVGhpcyB3aWxsIGxpa2VseSBicmVhayB0aGUgYXBwbGljYXRpb24uIFRvIHJlc2V0IHRoZSBtZW1vcnkgeW91IG11c3QgY2xvc2UgYWxsIHRhYnMgb2YgdGhpcyBzaXRlLiBUaGlzIGlzIGEgYnVnL2ZlYXR1cmUgaW4gY2hyb21lLmApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUuc3RhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICByZXR1cm4gY2FsbEZhY3Rvcnk7XG59XG5cblxubGV0IHVuY29tcHJlc3NlZFNlbnQgPSAwO1xubGV0IGNvbXByZXNzZWRTZW50ID0gMDtcbmxldCB1bmNvbXByZXNzZWRSZWNlaXZlZCA9IDA7XG5sZXQgY29tcHJlc3NlZFJlY2VpdmVkID0gMDtcblxubGV0IHNlbmRDb3VudCA9IDA7XG5sZXQgcmVjZWl2ZUNvdW50ID0gMDtcblxuZnVuY3Rpb24gYWRkU2VuZFN0YXRzKHN0YXRzOiBDb21wcmVzc2lvblN0YXRzKSB7XG4gICAgdW5jb21wcmVzc2VkU2VudCArPSBzdGF0cy51bmNvbXByZXNzZWRTaXplO1xuICAgIGNvbXByZXNzZWRTZW50ICs9IHN0YXRzLmNvbXByZXNzZWRTaXplO1xuICAgIHNlbmRDb3VudCsrO1xufVxuZnVuY3Rpb24gYWRkUmVjZWl2ZVN0YXRzKHN0YXRzOiBDb21wcmVzc2lvblN0YXRzKSB7XG4gICAgdW5jb21wcmVzc2VkUmVjZWl2ZWQgKz0gc3RhdHMudW5jb21wcmVzc2VkU2l6ZTtcbiAgICBjb21wcmVzc2VkUmVjZWl2ZWQgKz0gc3RhdHMuY29tcHJlc3NlZFNpemU7XG4gICAgcmVjZWl2ZUNvdW50Kys7XG59XG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhdHMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdW5jb21wcmVzc2VkU2VudCxcbiAgICAgICAgY29tcHJlc3NlZFNlbnQsXG4gICAgICAgIHVuY29tcHJlc3NlZFJlY2VpdmVkLFxuICAgICAgICBjb21wcmVzc2VkUmVjZWl2ZWQsXG4gICAgICAgIHNlbmRDb3VudCxcbiAgICAgICAgcmVjZWl2ZUNvdW50LFxuICAgIH07XG59XG4vLyBSZWdpc3RlciB0aGlzIGxhdGUgYXMgSSBkb24ndCB3YW50IGl0IHRvIGFwcGVhciBiZWZvcmUgdGhlIG1lbW9yeSByZWdpc3RlciBpbmZvLCB3aGljaCBpcyB1c2UgbW9yZSB1c2VmdWwgdGhhbiB0aGUgbmV0d29yayBvbmUuIFxuc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICByZWdpc3Rlck1lYXN1cmVJbmZvKCgpID0+IGBORVQgPT4gJHtmb3JtYXROdW1iZXIoY29tcHJlc3NlZFNlbnQpfUIgKCR7Zm9ybWF0TnVtYmVyKHVuY29tcHJlc3NlZFNlbnQpfUIvJHtmb3JtYXROdW1iZXIoc2VuZENvdW50KX0pIC8gPD0gJHtmb3JtYXROdW1iZXIoY29tcHJlc3NlZFJlY2VpdmVkKX1CICgke2Zvcm1hdE51bWJlcih1bmNvbXByZXNzZWRSZWNlaXZlZCl9Qi8ke2Zvcm1hdE51bWJlcihyZWNlaXZlQ291bnQpfSlgKTtcbn0pO1xuXG50eXBlIENvbXByZXNzaW9uU3RhdHMgPSB7XG4gICAgdW5jb21wcmVzc2VkU2l6ZTogbnVtYmVyO1xuICAgIGNvbXByZXNzZWRTaXplOiBudW1iZXI7XG59O1xuXG5jb25zdCBjb21wcmVzc09iaiA9IG1lYXN1cmVXcmFwKGFzeW5jIGZ1bmN0aW9uIHdpcmVDYWxsQ29tcHJlc3Mob2JqOiB1bmtub3duLCBzdGF0czogQ29tcHJlc3Npb25TdGF0cyk6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgbGV0IGJ1ZmZlcnMgPSBhd2FpdCBTb2NrZXRGdW5jdGlvbi5XSVJFX1NFUklBTElaRVIuc2VyaWFsaXplKG9iaik7XG4gICAgaWYgKGJ1ZmZlcnMubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMZWdhY3kgQ29tcHJlc3NPYmogb25seSBzdXBwb3J0cyBzaW5nbGUgYnVmZmVyXCIpO1xuICAgIH1cbiAgICBsZXQgbGVuZ3RoQnVmZmVyID0gQnVmZmVyLmZyb20oKG5ldyBGbG9hdDY0QXJyYXkoYnVmZmVycy5tYXAoeCA9PiB4Lmxlbmd0aCkpKS5idWZmZXIpO1xuICAgIGxldCBidWZmZXIgPSBCdWZmZXIuY29uY2F0KFtsZW5ndGhCdWZmZXIsIC4uLmJ1ZmZlcnNdKTtcbiAgICBzdGF0cy51bmNvbXByZXNzZWRTaXplICs9IGJ1ZmZlci5sZW5ndGg7XG4gICAgbGV0IHJlc3VsdCA9IGF3YWl0IFppcC5nemlwKGJ1ZmZlcik7XG4gICAgc3RhdHMuY29tcHJlc3NlZFNpemUgKz0gcmVzdWx0Lmxlbmd0aDtcbiAgICByZXR1cm4gcmVzdWx0O1xufSk7XG4vLyBBc3N1bWVzIHRoZSBjYWxsZXIgYWxyZWFkeSBhZGRlZCB0aGUgb2JqLmxlbmd0aCB0byBib3RoIHRoZSB1bmNvbXByZXNzZWRTaXplIGFuZCBjb21wcmVzc2VkU2l6ZSwgYW5kIGlzIGp1c3QgbG9va2luZyB0byB1cGRhdGUgdGhlIHVuY29tcHJlc3NlZFNpemUgdG8gYmUgbGFyZ2VyIGFjY29yZGluZyB0byB0aGUgc2l6ZSBhZnRlciB3ZSB1bmNvbXByZXNzXG5jb25zdCBkZWNvbXByZXNzT2JqID0gbWVhc3VyZVdyYXAoYXN5bmMgZnVuY3Rpb24gd2lyZUNhbGxEZWNvbXByZXNzKG9iajogQnVmZmVyLCBzdGF0czogQ29tcHJlc3Npb25TdGF0cyk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIGxldCBidWZmZXIgPSBhd2FpdCBaaXAuZ3VuemlwKG9iaik7XG4gICAgc3RhdHMudW5jb21wcmVzc2VkU2l6ZSArPSBidWZmZXIubGVuZ3RoIC0gb2JqLmxlbmd0aDtcbiAgICBsZXQgbGVuZ3RoQnVmZmVyID0gYnVmZmVyLnNsaWNlKDAsIDgpO1xuICAgIGxldCBsZW5ndGhzID0gbmV3IEZsb2F0NjRBcnJheShsZW5ndGhCdWZmZXIuYnVmZmVyLCBsZW5ndGhCdWZmZXIuYnl0ZU9mZnNldCwgbGVuZ3RoQnVmZmVyLmJ5dGVMZW5ndGggLyA4KTtcbiAgICBsZXQgYnVmZmVyczogQnVmZmVyW10gPSBbXTtcbiAgICBsZXQgb2Zmc2V0ID0gODtcbiAgICBmb3IgKGxldCBsZW5ndGggb2YgbGVuZ3Rocykge1xuICAgICAgICBidWZmZXJzLnB1c2goYnVmZmVyLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgbGVuZ3RoKSk7XG4gICAgICAgIG9mZnNldCArPSBsZW5ndGg7XG4gICAgfVxuICAgIGxldCByZXN1bHQgPSBhd2FpdCBTb2NrZXRGdW5jdGlvbi5XSVJFX1NFUklBTElaRVIuZGVzZXJpYWxpemUoYnVmZmVycyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuXG5jb25zdCBjb21wcmVzc09iakxaNCA9IG1lYXN1cmVXcmFwKGFzeW5jIGZ1bmN0aW9uIHdpcmVDYWxsQ29tcHJlc3NMWjQob2JqOiB1bmtub3duLCBzdGF0czogQ29tcHJlc3Npb25TdGF0cyk6IFByb21pc2U8QnVmZmVyW10+IHtcbiAgICBjb25zdCB7IExaNCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9sejQvTFo0XCIpO1xuICAgIGxldCBoZWFkZXJQYXJ0czogbnVtYmVyW107XG4gICAgbGV0IGRhdGFCdWZmZXJzOiBCdWZmZXJbXTtcblxuICAgIGlmIChvYmogaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgICAgaGVhZGVyUGFydHMgPSBbMV07XG4gICAgICAgIGRhdGFCdWZmZXJzID0gW29ial07XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iaikgJiYgb2JqLmV2ZXJ5KCh4OiBhbnkpID0+IHggaW5zdGFuY2VvZiBCdWZmZXIpKSB7XG4gICAgICAgIGxldCBidWZmZXJBcnJheSA9IG9iaiBhcyBCdWZmZXJbXTtcbiAgICAgICAgY29uc3QgVEFSR0VUX1NJWkUgPSA1MCAqIDEwMjQgKiAxMDI0O1xuICAgICAgICBjb25zdCBNSU5fSU5ESVZJRFVBTF9TSVpFID0gMTAgKiAxMDI0ICogMTAyNDtcbiAgICAgICAgY29uc3QgTUFYX1VOU1BMSVRfU0laRSA9IDEwMCAqIDEwMjQgKiAxMDI0O1xuXG4gICAgICAgIGxldCBvdXRwdXRCdWZmZXJzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICBsZXQgb3V0cHV0RGVzY3JpcHRvcnM6IG51bWJlcltdW10gPSBbXTtcbiAgICAgICAgbGV0IGN1cnJlbnRHcm91cDogQnVmZmVyW10gPSBbXTtcbiAgICAgICAgbGV0IGN1cnJlbnRHcm91cFNpemUgPSAwO1xuXG4gICAgICAgIGZ1bmN0aW9uIGZsdXNoQ3VycmVudEdyb3VwKCkge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRHcm91cC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0QnVmZmVycy5wdXNoKEJ1ZmZlci5jb25jYXQoY3VycmVudEdyb3VwKSk7XG4gICAgICAgICAgICAgICAgb3V0cHV0RGVzY3JpcHRvcnMucHVzaChjdXJyZW50R3JvdXAubWFwKGIgPT4gYi5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50R3JvdXAgPSBbXTtcbiAgICAgICAgICAgICAgICBjdXJyZW50R3JvdXBTaXplID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGJ1ZiBvZiBidWZmZXJBcnJheSkge1xuICAgICAgICAgICAgaWYgKGJ1Zi5sZW5ndGggPj0gTUlOX0lORElWSURVQUxfU0laRSkge1xuICAgICAgICAgICAgICAgIGZsdXNoQ3VycmVudEdyb3VwKCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoYnVmLmxlbmd0aCA+IE1BWF9VTlNQTElUX1NJWkUpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChvZmZzZXQgPCBidWYubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2h1bmtTaXplID0gTWF0aC5taW4oVEFSR0VUX1NJWkUsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0QnVmZmVycy5wdXNoKGJ1Zi5zbGljZShvZmZzZXQsIG9mZnNldCArIGNodW5rU2l6ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0RGVzY3JpcHRvcnMucHVzaChbY2h1bmtTaXplXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gY2h1bmtTaXplO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0QnVmZmVycy5wdXNoKGJ1Zik7XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dERlc2NyaXB0b3JzLnB1c2goW2J1Zi5sZW5ndGhdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRHcm91cC5wdXNoKGJ1Zik7XG4gICAgICAgICAgICAgICAgY3VycmVudEdyb3VwU2l6ZSArPSBidWYubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRHcm91cFNpemUgPj0gVEFSR0VUX1NJWkUpIHtcbiAgICAgICAgICAgICAgICAgICAgZmx1c2hDdXJyZW50R3JvdXAoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmbHVzaEN1cnJlbnRHcm91cCgpO1xuXG4gICAgICAgIGhlYWRlclBhcnRzID0gWzIsIG91dHB1dEJ1ZmZlcnMubGVuZ3RoXTtcbiAgICAgICAgZm9yIChsZXQgZGVzY3JpcHRvciBvZiBvdXRwdXREZXNjcmlwdG9ycykge1xuICAgICAgICAgICAgaGVhZGVyUGFydHMucHVzaChkZXNjcmlwdG9yLmxlbmd0aCwgLi4uZGVzY3JpcHRvcik7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YUJ1ZmZlcnMgPSBvdXRwdXRCdWZmZXJzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBidWZmZXJzID0gYXdhaXQgU29ja2V0RnVuY3Rpb24uV0lSRV9TRVJJQUxJWkVSLnNlcmlhbGl6ZShvYmopO1xuICAgICAgICBoZWFkZXJQYXJ0cyA9IFszLCBidWZmZXJzLmxlbmd0aF07XG4gICAgICAgIGRhdGFCdWZmZXJzID0gYnVmZmVycztcbiAgICB9XG5cbiAgICBsZXQgaGVhZGVyQnVmZmVyID0gQnVmZmVyLmZyb20oKG5ldyBGbG9hdDY0QXJyYXkoaGVhZGVyUGFydHMpKS5idWZmZXIpO1xuICAgIGxldCBhbGxCdWZmZXJzID0gW2hlYWRlckJ1ZmZlciwgLi4uZGF0YUJ1ZmZlcnNdO1xuXG4gICAgc3RhdHMudW5jb21wcmVzc2VkU2l6ZSArPSBhbGxCdWZmZXJzLnJlZHVjZSgoc3VtLCBidWYpID0+IHN1bSArIGJ1Zi5sZW5ndGgsIDApO1xuXG4gICAgbGV0IGNvbXByZXNzZWQ6IEJ1ZmZlcltdID0gW107XG4gICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgbGV0IGxhc3RXYXJuVGltZSA9IHN0YXJ0VGltZTtcbiAgICBsZXQgY3VycmVudFVuY29tcHJlc3NlZFNpemUgPSAwO1xuICAgIGxldCBjdXJyZW50Q29tcHJlc3NlZFNpemUgPSAwO1xuXG4gICAgZnVuY3Rpb24gbG9nSWZTbG93KGk6IG51bWJlcikge1xuICAgICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYgKG5vdyAtIGxhc3RXYXJuVGltZSA+IDUwMCkge1xuICAgICAgICAgICAgbGV0IGVsYXBzZWQgPSBub3cgLSBzdGFydFRpbWU7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgU2xvdyBMWjQgY29tcHJlc3MgKCR7Zm9ybWF0VGltZShlbGFwc2VkKX06ICR7aSArIDF9LyR7YWxsQnVmZmVycy5sZW5ndGh9IGJ1ZmZlcnMsICR7Zm9ybWF0TnVtYmVyKGN1cnJlbnRVbmNvbXByZXNzZWRTaXplKX1CID0+ICR7Zm9ybWF0TnVtYmVyKGN1cnJlbnRDb21wcmVzc2VkU2l6ZSl9QmApO1xuICAgICAgICAgICAgbGFzdFdhcm5UaW1lID0gbm93O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhbGxCdWZmZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBidWYgPSBhbGxCdWZmZXJzW2ldO1xuICAgICAgICBjdXJyZW50VW5jb21wcmVzc2VkU2l6ZSArPSBidWYubGVuZ3RoO1xuICAgICAgICBsZXQgY29tcHJlc3NlZEJ1ZiA9IExaNC5jb21wcmVzcyhidWYpO1xuICAgICAgICBjb21wcmVzc2VkLnB1c2goY29tcHJlc3NlZEJ1Zik7XG4gICAgICAgIGN1cnJlbnRDb21wcmVzc2VkU2l6ZSArPSBjb21wcmVzc2VkQnVmLmxlbmd0aDtcblxuICAgICAgICBsb2dJZlNsb3coaSk7XG4gICAgfVxuICAgIGxvZ0lmU2xvdyhhbGxCdWZmZXJzLmxlbmd0aCk7XG5cbiAgICBzdGF0cy5jb21wcmVzc2VkU2l6ZSArPSBjdXJyZW50Q29tcHJlc3NlZFNpemU7XG5cbiAgICByZXR1cm4gY29tcHJlc3NlZDtcbn0pO1xuXG5jb25zdCBkZWNvbXByZXNzT2JqTFo0ID0gbWVhc3VyZVdyYXAoYXN5bmMgZnVuY3Rpb24gd2lyZUNhbGxEZWNvbXByZXNzTFo0KG9iajogQnVmZmVyW10sIHN0YXRzOiBDb21wcmVzc2lvblN0YXRzKTogUHJvbWlzZTx1bmtub3duPiB7XG5cbiAgICBjb25zdCB7IExaNCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9sejQvTFo0XCIpO1xuICAgIHN0YXRzLmNvbXByZXNzZWRTaXplICs9IG9iai5yZWR1Y2UoKHN1bSwgYnVmKSA9PiBzdW0gKyBidWYubGVuZ3RoLCAwKTtcblxuICAgIGxldCBkZWNvbXByZXNzZWQ6IEJ1ZmZlcltdID0gW107XG4gICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgbGV0IGxhc3RXYXJuVGltZSA9IHN0YXJ0VGltZTtcbiAgICBsZXQgY3VycmVudENvbXByZXNzZWRTaXplID0gMDtcbiAgICBsZXQgY3VycmVudFVuY29tcHJlc3NlZFNpemUgPSAwO1xuICAgIGZ1bmN0aW9uIGxvZ0lmU2xvdyhpOiBudW1iZXIpIHtcbiAgICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGlmIChub3cgLSBsYXN0V2FyblRpbWUgPiA1MDApIHtcbiAgICAgICAgICAgIGxldCBlbGFwc2VkID0gbm93IC0gc3RhcnRUaW1lO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFNsb3cgTFo0IGRlY29tcHJlc3MgKCR7Zm9ybWF0VGltZShlbGFwc2VkKX0pOiAke2kgKyAxfS8ke29iai5sZW5ndGh9IGJ1ZmZlcnMsICR7Zm9ybWF0TnVtYmVyKGN1cnJlbnRDb21wcmVzc2VkU2l6ZSl9QiA9PiAke2Zvcm1hdE51bWJlcihjdXJyZW50VW5jb21wcmVzc2VkU2l6ZSl9QmApO1xuICAgICAgICAgICAgbGFzdFdhcm5UaW1lID0gbm93O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGJ1ZiA9IG9ialtpXTtcbiAgICAgICAgY3VycmVudENvbXByZXNzZWRTaXplICs9IGJ1Zi5sZW5ndGg7XG4gICAgICAgIGxldCBkZWNvbXByZXNzZWRCdWYgPSBMWjQuZGVjb21wcmVzcyhidWYpO1xuICAgICAgICBkZWNvbXByZXNzZWQucHVzaChkZWNvbXByZXNzZWRCdWYpO1xuICAgICAgICBjdXJyZW50VW5jb21wcmVzc2VkU2l6ZSArPSBkZWNvbXByZXNzZWRCdWYubGVuZ3RoO1xuXG4gICAgICAgIGxvZ0lmU2xvdyhpKTtcbiAgICB9XG4gICAgbG9nSWZTbG93KG9iai5sZW5ndGgpO1xuXG4gICAgc3RhdHMudW5jb21wcmVzc2VkU2l6ZSArPSBjdXJyZW50VW5jb21wcmVzc2VkU2l6ZTtcblxuICAgIGxldCBoZWFkZXJCdWZmZXIgPSBkZWNvbXByZXNzZWRbMF07XG4gICAgbGV0IGRhdGFCdWZmZXJzID0gZGVjb21wcmVzc2VkLnNsaWNlKDEpO1xuXG4gICAgbGV0IHR5cGVCdWZmZXIgPSBoZWFkZXJCdWZmZXIuc2xpY2UoMCwgOCk7XG4gICAgbGV0IHR5cGUgPSBuZXcgRmxvYXQ2NEFycmF5KHR5cGVCdWZmZXIuYnVmZmVyLCB0eXBlQnVmZmVyLmJ5dGVPZmZzZXQsIDEpWzBdO1xuXG4gICAgaWYgKHR5cGUgPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGFCdWZmZXJzWzBdO1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAyKSB7XG4gICAgICAgIGxldCBoZWFkZXJEYXRhID0gbmV3IEZsb2F0NjRBcnJheShoZWFkZXJCdWZmZXIuYnVmZmVyLCBoZWFkZXJCdWZmZXIuYnl0ZU9mZnNldCwgaGVhZGVyQnVmZmVyLmJ5dGVMZW5ndGggLyA4KTtcbiAgICAgICAgbGV0IG91dHB1dEJ1ZmZlckNvdW50ID0gaGVhZGVyRGF0YVsxXTtcblxuICAgICAgICBsZXQgYnVmZmVyczogQnVmZmVyW10gPSBbXTtcbiAgICAgICAgbGV0IGhlYWRlckluZGV4ID0gMjtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dEJ1ZmZlckNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIGxldCBpbnB1dEJ1ZmZlckNvdW50ID0gaGVhZGVyRGF0YVtoZWFkZXJJbmRleCsrXTtcbiAgICAgICAgICAgIGxldCBzaXplczogbnVtYmVyW10gPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaW5wdXRCdWZmZXJDb3VudDsgaisrKSB7XG4gICAgICAgICAgICAgICAgc2l6ZXMucHVzaChoZWFkZXJEYXRhW2hlYWRlckluZGV4KytdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IG91dHB1dEJ1ZmZlciA9IGRhdGFCdWZmZXJzW2ldO1xuICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBzaXplIG9mIHNpemVzKSB7XG4gICAgICAgICAgICAgICAgYnVmZmVycy5wdXNoKG91dHB1dEJ1ZmZlci5zbGljZShvZmZzZXQsIG9mZnNldCArIHNpemUpKTtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gc2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBidWZmZXJzO1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAzKSB7XG4gICAgICAgIGxldCByZXN1bHQgPSBhd2FpdCBTb2NrZXRGdW5jdGlvbi5XSVJFX1NFUklBTElaRVIuZGVzZXJpYWxpemUoZGF0YUJ1ZmZlcnMpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBjb21wcmVzc2lvbiB0eXBlICR7dHlwZX1gKTtcbn0pOyJdfQ==
930
- /* _JS_SOURCE_HASH = "dda71e5b802e2381d3abdcba068e868fa08242c064c83808ce610e33b0ca8f25"; */