sliftutils 1.7.9 → 1.7.11

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 (92) hide show
  1. package/bin/storageserver.js +4 -0
  2. package/{teststorage → examplestorage}/browser.tsx +18 -22
  3. package/{teststorage/server.ts → examplestorage/exampleserver.ts} +4 -6
  4. package/index.d.ts +770 -84
  5. package/misc/dist/environment.ts.cache +3 -3
  6. package/misc/dist/getSecret.ts.cache +139 -0
  7. package/misc/dist/strings.ts.cache +13 -0
  8. package/misc/dist/zip.ts.cache +9 -0
  9. package/misc/getSecret.ts +38 -16
  10. package/misc/https/cloudflareHelpers.d.ts +19 -0
  11. package/misc/https/cloudflareHelpers.ts +69 -0
  12. package/misc/https/dist/certs.ts.cache +115 -179
  13. package/misc/https/dist/cloudflareHelpers.ts.cache +68 -0
  14. package/misc/https/dist/dns.ts.cache +112 -100
  15. package/misc/https/dist/hostServer.ts.cache +130 -0
  16. package/misc/https/dist/httpsCerts.ts.cache +24 -5
  17. package/misc/https/dist/persistentLocalStorage.ts.cache +3 -2
  18. package/misc/https/dns.d.ts +41 -8
  19. package/misc/https/dns.ts +104 -106
  20. package/misc/https/hostServer.d.ts +0 -3
  21. package/misc/https/hostServer.ts +12 -8
  22. package/package.json +3 -2
  23. package/render-utils/dist/observer.tsx.cache +3 -2
  24. package/spec.txt +0 -55
  25. package/storage/ArchivesDisk.d.ts +67 -0
  26. package/storage/ArchivesDisk.ts +369 -0
  27. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +1242 -0
  28. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +513 -0
  29. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +352 -0
  30. package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +306 -0
  31. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +435 -0
  32. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +58 -0
  33. package/storage/BulkDatabase2/dist/blockCache.ts.cache +179 -0
  34. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +149 -0
  35. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +101 -0
  36. package/storage/BulkDatabase2/dist/streamLog.ts.cache +227 -0
  37. package/storage/BulkDatabase2/dist/syncClient.ts.cache +104 -0
  38. package/storage/IArchives.d.ts +127 -1
  39. package/storage/IArchives.ts +201 -1
  40. package/storage/backblaze.d.ts +29 -2
  41. package/storage/backblaze.ts +214 -78
  42. package/storage/dist/ArchivesDisk.ts.cache +373 -0
  43. package/storage/dist/FileFolderAPI.tsx.cache +508 -65
  44. package/storage/dist/IArchives.ts.cache +44 -0
  45. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +8 -2
  46. package/storage/dist/JSONStorage.ts.cache +6 -2
  47. package/storage/dist/PendingManager.tsx.cache +1 -1
  48. package/storage/dist/TransactionStorage.ts.cache +231 -92
  49. package/storage/dist/backblaze.ts.cache +797 -0
  50. package/storage/dist/fileSystemPointer.ts.cache +36 -3
  51. package/storage/dist/remoteFileStorage.ts.cache +495 -0
  52. package/storage/remoteStorage/ArchivesRemote.d.ts +34 -18
  53. package/storage/remoteStorage/ArchivesRemote.ts +85 -65
  54. package/storage/remoteStorage/ArchivesUrl.d.ts +48 -0
  55. package/storage/remoteStorage/ArchivesUrl.ts +86 -0
  56. package/storage/remoteStorage/accessPage.tsx +111 -28
  57. package/storage/remoteStorage/blobStore.d.ts +128 -25
  58. package/storage/remoteStorage/blobStore.ts +757 -290
  59. package/storage/remoteStorage/cliArgs.d.ts +1 -0
  60. package/storage/remoteStorage/cliArgs.ts +9 -0
  61. package/storage/remoteStorage/createArchives.d.ts +85 -0
  62. package/storage/remoteStorage/createArchives.ts +612 -0
  63. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +197 -0
  64. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +85 -0
  65. package/storage/remoteStorage/dist/accessPage.tsx.cache +222 -0
  66. package/storage/remoteStorage/dist/blobStore.ts.cache +837 -0
  67. package/storage/remoteStorage/dist/cliArgs.ts.cache +16 -0
  68. package/storage/remoteStorage/dist/createArchives.ts.cache +610 -0
  69. package/storage/remoteStorage/dist/remoteConfig.ts.cache +206 -0
  70. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +223 -0
  71. package/storage/remoteStorage/dist/storageController.ts.cache +500 -0
  72. package/storage/remoteStorage/dist/storageServer.ts.cache +106 -0
  73. package/storage/remoteStorage/dist/storageServerCli.ts.cache +39 -0
  74. package/storage/remoteStorage/dist/storageServerState.ts.cache +518 -0
  75. package/storage/remoteStorage/grantAccess.js +4 -0
  76. package/storage/remoteStorage/grantAccessCli.d.ts +1 -0
  77. package/storage/remoteStorage/grantAccessCli.ts +27 -0
  78. package/storage/remoteStorage/remoteConfig.d.ts +29 -0
  79. package/storage/remoteStorage/remoteConfig.ts +194 -0
  80. package/storage/remoteStorage/sourceWrapper.d.ts +41 -0
  81. package/storage/remoteStorage/sourceWrapper.ts +223 -0
  82. package/storage/remoteStorage/spec.md +31 -0
  83. package/storage/remoteStorage/storageController.d.ts +30 -27
  84. package/storage/remoteStorage/storageController.ts +297 -159
  85. package/storage/remoteStorage/storageServer.d.ts +6 -0
  86. package/storage/remoteStorage/storageServer.ts +88 -94
  87. package/storage/remoteStorage/storageServerCli.d.ts +1 -0
  88. package/storage/remoteStorage/storageServerCli.ts +38 -0
  89. package/storage/remoteStorage/storageServerState.d.ts +43 -0
  90. package/storage/remoteStorage/storageServerState.ts +540 -0
  91. package/testsite/server.ts +0 -2
  92. package/yarn.lock +11 -6
@@ -0,0 +1,373 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
+ //exports.applyFindInfoShape = exports.ArchivesDisk = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const caching_1 = require("socket-function/src/caching");
10
+ const batching_1 = require("socket-function/src/batching");
11
+ const misc_1 = require("socket-function/src/misc");
12
+ const IArchives_1 = require("./IArchives");
13
+ // The base file-system IArchives: storage is one-to-one with the file system, every key is exactly
14
+ // one real file under <folder>/files, so the file system itself is the index. File handles are
15
+ // cached and reused, and closed once idle (see FileHandleCache). All operations on a file run in
16
+ // serial, so they can't collide with each other or with handle closing. Used as the disk
17
+ // synchronization source of BlobStore (see remoteStorage/blobStore.ts).
18
+ const HANDLE_IDLE_TIMEOUT = 1000 * 60;
19
+ const HANDLE_SWEEP_INTERVAL = 1000 * 15;
20
+ // Caches open file handles, closing them once idle for HANDLE_IDLE_TIMEOUT. Instead of one
21
+ // setTimeout per handle, a list sorted by last use is swept periodically (entries are moved via
22
+ // binary search on access, and lastUse values only increase, so touched entries append at the
23
+ // end). Also serializes operations per file: each operation only starts once the previous one on
24
+ // the same file finished, and a handle is never closed while an operation is pending on it.
25
+ class FileHandleCache {
26
+ constructor() {
27
+ this.entries = new Map();
28
+ // Sorted by lastUse ascending (least recently used first)
29
+ this.lru = [];
30
+ this.pending = new Map();
31
+ (0, batching_1.runInfinitePoll)(HANDLE_SWEEP_INTERVAL, () => this.sweep());
32
+ }
33
+ // Runs fnc after every previously scheduled operation on filePath has finished
34
+ run(filePath, fnc) {
35
+ let prev = this.pending.get(filePath) || Promise.resolve();
36
+ let result = prev.then(fnc);
37
+ // The pending chain must never reject, or one failed operation would poison all later ones
38
+ let last = result.then(() => { }, () => { });
39
+ this.pending.set(filePath, last);
40
+ void last.then(() => {
41
+ // If we're still the last pending operation on this file, clear ourselves
42
+ if (this.pending.get(filePath) === last) {
43
+ this.pending.delete(filePath);
44
+ }
45
+ });
46
+ return result;
47
+ }
48
+ // Only call inside run() for the same filePath (so opens can't collide with closes)
49
+ async getHandle(filePath, flags) {
50
+ let entry = this.entries.get(filePath);
51
+ if (entry) {
52
+ this.removeFromLRU(entry);
53
+ entry.lastUse = Date.now();
54
+ this.lru.push(entry);
55
+ return entry.handle;
56
+ }
57
+ let handle = await fs_1.default.promises.open(filePath, flags);
58
+ entry = { filePath, handle, lastUse: Date.now() };
59
+ this.entries.set(filePath, entry);
60
+ this.lru.push(entry);
61
+ return handle;
62
+ }
63
+ // Only call inside run() for the same filePath
64
+ async closeNow(filePath) {
65
+ let entry = this.entries.get(filePath);
66
+ if (!entry)
67
+ return;
68
+ this.entries.delete(filePath);
69
+ this.removeFromLRU(entry);
70
+ await entry.handle.close();
71
+ }
72
+ removeFromLRU(entry) {
73
+ let index = (0, misc_1.binarySearchBasic)(this.lru, x => x.lastUse, entry.lastUse);
74
+ if (index < 0)
75
+ return;
76
+ // Multiple entries can share a lastUse, so scan for the exact one
77
+ while (index < this.lru.length && this.lru[index].lastUse === entry.lastUse) {
78
+ if (this.lru[index] === entry) {
79
+ this.lru.splice(index, 1);
80
+ return;
81
+ }
82
+ index++;
83
+ }
84
+ }
85
+ async sweep() {
86
+ let cutoff = Date.now() - HANDLE_IDLE_TIMEOUT;
87
+ let index = 0;
88
+ while (index < this.lru.length && this.lru[index].lastUse <= cutoff) {
89
+ let entry = this.lru[index];
90
+ // Can't close a handle with a pending operation; it'll be swept after it finishes
91
+ if (this.pending.has(entry.filePath)) {
92
+ index++;
93
+ continue;
94
+ }
95
+ this.lru.splice(index, 1);
96
+ this.entries.delete(entry.filePath);
97
+ await entry.handle.close();
98
+ }
99
+ }
100
+ }
101
+ class ArchivesDisk {
102
+ constructor(folder) {
103
+ this.folder = folder;
104
+ this.filesDir = path_1.default.join(this.folder, "files");
105
+ this.uploadsDir = path_1.default.join(this.folder, "uploads");
106
+ this.handles = new FileHandleCache();
107
+ this.largeUploads = new Map();
108
+ this.nextLargeUploadId = 1;
109
+ this.init = (0, caching_1.lazy)(async () => {
110
+ await fs_1.default.promises.mkdir(this.filesDir, { recursive: true });
111
+ await fs_1.default.promises.mkdir(this.uploadsDir, { recursive: true });
112
+ // Uploads don't survive restarts (the uploader streams into them), so old ones are garbage
113
+ for (let file of await fs_1.default.promises.readdir(this.uploadsDir)) {
114
+ await fs_1.default.promises.unlink(path_1.default.join(this.uploadsDir, file));
115
+ }
116
+ });
117
+ }
118
+ getDebugName() {
119
+ return `disk/${this.folder}`;
120
+ }
121
+ async getConfig() {
122
+ return {};
123
+ }
124
+ async hasWriteAccess() {
125
+ return true;
126
+ }
127
+ filePath(key) {
128
+ let result = path_1.default.join(this.filesDir, key);
129
+ if (!result.startsWith(this.filesDir + path_1.default.sep)) {
130
+ throw new Error(`Invalid key ${JSON.stringify(key.slice(0, 200))}, it escapes the store folder`);
131
+ }
132
+ return result;
133
+ }
134
+ async set(key, data, config) {
135
+ await this.init();
136
+ let lastModified = config === null || config === void 0 ? void 0 : config.lastModified;
137
+ if (lastModified) {
138
+ (0, IArchives_1.assertValidLastModified)(lastModified);
139
+ }
140
+ let filePath = this.filePath(key);
141
+ await this.handles.run(filePath, async () => {
142
+ if (lastModified) {
143
+ let existing = await statOrUndefined(filePath);
144
+ // An older write never overwrites a newer one (see IArchives.set)
145
+ if (existing && lastModified < existing.mtimeMs)
146
+ return;
147
+ }
148
+ await fs_1.default.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
149
+ let handle = await this.handles.getHandle(filePath, fs_1.default.constants.O_RDWR | fs_1.default.constants.O_CREAT);
150
+ await handle.truncate(0);
151
+ await handle.write(data, 0, data.length, 0);
152
+ if (lastModified) {
153
+ await handle.utimes(new Date(lastModified), new Date(lastModified));
154
+ }
155
+ });
156
+ }
157
+ async del(key) {
158
+ await this.init();
159
+ let filePath = this.filePath(key);
160
+ await this.handles.run(filePath, async () => {
161
+ await this.handles.closeNow(filePath);
162
+ try {
163
+ await fs_1.default.promises.unlink(filePath);
164
+ }
165
+ catch (e) {
166
+ if (e.code !== "ENOENT")
167
+ throw e;
168
+ }
169
+ });
170
+ }
171
+ async get(key, config) {
172
+ let result = await this.get2(key, config);
173
+ return result && result.data || undefined;
174
+ }
175
+ async get2(key, config) {
176
+ await this.init();
177
+ let range = config === null || config === void 0 ? void 0 : config.range;
178
+ let filePath = this.filePath(key);
179
+ return await this.handles.run(filePath, async () => {
180
+ let handle;
181
+ try {
182
+ handle = await this.handles.getHandle(filePath, fs_1.default.constants.O_RDWR);
183
+ }
184
+ catch (e) {
185
+ if (e.code === "ENOENT")
186
+ return undefined;
187
+ throw e;
188
+ }
189
+ let stats = await handle.stat();
190
+ let size = stats.size;
191
+ let start = range && Math.min(range.start, size) || 0;
192
+ let end = range && Math.min(range.end, size) || size;
193
+ if (end <= start)
194
+ return { data: Buffer.alloc(0), writeTime: stats.mtimeMs, size };
195
+ let buffer = Buffer.alloc(end - start);
196
+ let { bytesRead } = await handle.read(buffer, 0, buffer.length, start);
197
+ if (bytesRead !== buffer.length) {
198
+ throw new Error(`Expected ${buffer.length} bytes at ${filePath}:${start}, read ${bytesRead}`);
199
+ }
200
+ return { data: buffer, writeTime: stats.mtimeMs, size };
201
+ });
202
+ }
203
+ async getInfo(key) {
204
+ await this.init();
205
+ let filePath = this.filePath(key);
206
+ return await this.handles.run(filePath, async () => {
207
+ let stats = await statOrUndefined(filePath);
208
+ if (!stats || !stats.isFile())
209
+ return undefined;
210
+ return { writeTime: stats.mtimeMs, size: stats.size };
211
+ });
212
+ }
213
+ async find(prefix, config) {
214
+ return (await this.findInfo(prefix, config)).map(x => x.path);
215
+ }
216
+ async findInfo(prefix, config) {
217
+ await this.init();
218
+ let infos = new Map();
219
+ await this.collectFiles("", prefix, infos);
220
+ let files = Array.from(infos.values());
221
+ files = applyFindInfoShape(files, prefix, config);
222
+ (0, misc_1.sort)(files, x => x.path);
223
+ return files;
224
+ }
225
+ // relDir is "" or ends with "/". Only descends into directories that can still match the prefix.
226
+ async collectFiles(relDir, prefix, infos) {
227
+ let entries;
228
+ try {
229
+ entries = await fs_1.default.promises.readdir(path_1.default.join(this.filesDir, relDir), { withFileTypes: true });
230
+ }
231
+ catch (e) {
232
+ if (e.code === "ENOENT")
233
+ return;
234
+ throw e;
235
+ }
236
+ for (let entry of entries) {
237
+ let relPath = relDir + entry.name;
238
+ if (entry.isDirectory()) {
239
+ let dirPath = relPath + "/";
240
+ if (dirPath.startsWith(prefix) || prefix.startsWith(dirPath)) {
241
+ await this.collectFiles(dirPath, prefix, infos);
242
+ }
243
+ continue;
244
+ }
245
+ if (!entry.isFile())
246
+ continue;
247
+ if (!relPath.startsWith(prefix))
248
+ continue;
249
+ let stats = await statOrUndefined(path_1.default.join(this.filesDir, relPath));
250
+ // Deleted while we were walking
251
+ if (!stats)
252
+ continue;
253
+ infos.set(relPath, { path: relPath, createTime: stats.mtimeMs, size: stats.size });
254
+ }
255
+ }
256
+ async setLargeFile(config) {
257
+ let id = await this.startLargeUpload();
258
+ try {
259
+ while (true) {
260
+ let data = await config.getNextData();
261
+ if (!data)
262
+ break;
263
+ await this.appendLargeUpload(id, data);
264
+ }
265
+ await this.finishLargeUpload(id, config.path);
266
+ }
267
+ catch (e) {
268
+ await this.cancelLargeUpload(id);
269
+ throw e;
270
+ }
271
+ }
272
+ // Large files stream into their own file under uploads/, then move into place on finish. No
273
+ // handle is opened until the first append actually happens.
274
+ async startLargeUpload() {
275
+ await this.init();
276
+ let id = `${Date.now()}_${this.nextLargeUploadId++}`;
277
+ this.largeUploads.set(id, { tmpPath: path_1.default.join(this.uploadsDir, `upload_${id}.tmp`) });
278
+ return id;
279
+ }
280
+ async appendLargeUpload(id, data) {
281
+ let upload = this.largeUploads.get(id);
282
+ if (!upload)
283
+ throw new Error(`Unknown large upload ${id}`);
284
+ const tmpPath = upload.tmpPath;
285
+ await this.handles.run(tmpPath, async () => {
286
+ let handle = await this.handles.getHandle(tmpPath, fs_1.default.constants.O_WRONLY | fs_1.default.constants.O_CREAT | fs_1.default.constants.O_APPEND);
287
+ await handle.write(data, 0, data.length);
288
+ });
289
+ }
290
+ async finishLargeUpload(id, key) {
291
+ let upload = this.largeUploads.get(id);
292
+ if (!upload)
293
+ throw new Error(`Unknown large upload ${id}`);
294
+ const tmpPath = upload.tmpPath;
295
+ this.largeUploads.delete(id);
296
+ let filePath = this.filePath(key);
297
+ await this.handles.run(tmpPath, () => this.handles.closeNow(tmpPath));
298
+ await this.handles.run(filePath, async () => {
299
+ // Close any cached handle to the file we're replacing, so later reads reopen the new file
300
+ await this.handles.closeNow(filePath);
301
+ await fs_1.default.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
302
+ try {
303
+ await fs_1.default.promises.rename(tmpPath, filePath);
304
+ }
305
+ catch (e) {
306
+ if (e.code !== "ENOENT")
307
+ throw e;
308
+ // Nothing was ever appended, so the upload file was never created
309
+ await fs_1.default.promises.writeFile(filePath, Buffer.alloc(0));
310
+ }
311
+ });
312
+ }
313
+ async cancelLargeUpload(id) {
314
+ let upload = this.largeUploads.get(id);
315
+ if (!upload)
316
+ return;
317
+ const tmpPath = upload.tmpPath;
318
+ this.largeUploads.delete(id);
319
+ await this.handles.run(tmpPath, async () => {
320
+ await this.handles.closeNow(tmpPath);
321
+ try {
322
+ await fs_1.default.promises.unlink(tmpPath);
323
+ }
324
+ catch (e) {
325
+ if (e.code !== "ENOENT")
326
+ throw e;
327
+ }
328
+ });
329
+ }
330
+ async getURL(path) {
331
+ throw new Error(`getURL is not supported for disk archives (${this.getDebugName()}, path ${path})`);
332
+ }
333
+ }
334
+ exports.ArchivesDisk = ArchivesDisk;
335
+ async function statOrUndefined(filePath) {
336
+ try {
337
+ return await fs_1.default.promises.stat(filePath);
338
+ }
339
+ catch (e) {
340
+ if (e.code === "ENOENT")
341
+ return undefined;
342
+ throw e;
343
+ }
344
+ }
345
+ // The folders/shallow post-processing shared by findInfo implementations that list flat files
346
+ // (used by ArchivesDisk on the raw disk walk, and by BlobStore on its index).
347
+ function applyFindInfoShape(files, prefix, config) {
348
+ if ((config === null || config === void 0 ? void 0 : config.type) === "folders") {
349
+ let folders = new Map();
350
+ for (let file of files) {
351
+ let rest = file.path.slice(prefix.length);
352
+ let restParts = rest.split("/");
353
+ if (restParts.length < 2)
354
+ continue;
355
+ let folder;
356
+ if (config.shallow) {
357
+ folder = prefix + restParts[0];
358
+ }
359
+ else {
360
+ folder = file.path.split("/").slice(0, -1).join("/");
361
+ }
362
+ folders.set(folder, { path: folder, createTime: file.createTime, size: file.size });
363
+ }
364
+ return Array.from(folders.values());
365
+ }
366
+ if (config === null || config === void 0 ? void 0 : config.shallow) {
367
+ return files.filter(file => !file.path.slice(prefix.length).includes("/"));
368
+ }
369
+ return files;
370
+ }
371
+ exports.applyFindInfoShape = applyFindInfoShape;
372
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXJjaGl2ZXNEaXNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiQXJjaGl2ZXNEaXNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDRDQUFvQjtBQUNwQixnREFBd0I7QUFDeEIseURBQW1EO0FBQ25ELDJEQUErRDtBQUMvRCxtREFBbUU7QUFDbkUsMkNBQWtHO0FBRWxHLG1HQUFtRztBQUNuRywrRkFBK0Y7QUFDL0YsaUdBQWlHO0FBQ2pHLHlGQUF5RjtBQUN6Rix3RUFBd0U7QUFFeEUsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0FBQ3RDLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztBQVF4QywyRkFBMkY7QUFDM0YsZ0dBQWdHO0FBQ2hHLDhGQUE4RjtBQUM5RixpR0FBaUc7QUFDakcsNEZBQTRGO0FBQzVGLE1BQU0sZUFBZTtJQU1qQjtRQUxRLFlBQU8sR0FBRyxJQUFJLEdBQUcsRUFBdUIsQ0FBQztRQUNqRCwwREFBMEQ7UUFDbEQsUUFBRyxHQUFrQixFQUFFLENBQUM7UUFDeEIsWUFBTyxHQUFHLElBQUksR0FBRyxFQUF5QixDQUFDO1FBRy9DLElBQUEsMEJBQWUsRUFBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBRUQsK0VBQStFO0lBQ3hFLEdBQUcsQ0FBSSxRQUFnQixFQUFFLEdBQXFCO1FBQ2pELElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMzRCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzVCLDJGQUEyRjtRQUMzRixJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFB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QU0sR0FBRyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLENBQUM7aUJBQU0sQ0FBQztnQkFDSixNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6RCxDQUFDO1lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN4RixDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFDRCxJQUFJLE1BQU0sYUFBTixNQUFNLHVCQUFOLE1BQU0sQ0FBRSxPQUFPLEVBQUUsQ0FBQztRQUNsQixPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQztBQXJCRCxnREFxQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgbGF6eSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2NhY2hpbmdcIjtcbmltcG9ydCB7IHJ1bkluZmluaXRlUG9sbCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2JhdGNoaW5nXCI7XG5pbXBvcnQgeyBzb3J0LCBiaW5hcnlTZWFyY2hCYXNpYyB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL21pc2NcIjtcbmltcG9ydCB7IElBcmNoaXZlcywgQXJjaGl2ZUZpbGVJbmZvLCBBcmNoaXZlc0NvbmZpZywgYXNzZXJ0VmFsaWRMYXN0TW9kaWZpZWQgfSBmcm9tIFwiLi9JQXJjaGl2ZXNcIjtcblxuLy8gVGhlIGJhc2UgZmlsZS1zeXN0ZW0gSUFyY2hpdmVzOiBzdG9yYWdlIGlzIG9uZS10by1vbmUgd2l0aCB0aGUgZmlsZSBzeXN0ZW0sIGV2ZXJ5IGtleSBpcyBleGFjdGx5XG4vLyBvbmUgcmVhbCBmaWxlIHVuZGVyIDxmb2xkZXI+L2ZpbGVzLCBzbyB0aGUgZmlsZSBzeXN0ZW0gaXRzZWxmIGlzIHRoZSBpbmRleC4gRmlsZSBoYW5kbGVzIGFyZVxuLy8gY2FjaGVkIGFuZCByZXVzZWQsIGFuZCBjbG9zZWQgb25jZSBpZGxlIChzZWUgRmlsZUhhbmRsZUNhY2hlKS4gQWxsIG9wZXJhdGlvbnMgb24gYSBmaWxlIHJ1biBpblxuLy8gc2VyaWFsLCBzbyB0aGV5IGNhbid0IGNvbGxpZGUgd2l0aCBlYWNoIG90aGVyIG9yIHdpdGggaGFuZGxlIGNsb3NpbmcuIFVzZWQgYXMgdGhlIGRpc2tcbi8vIHN5bmNocm9uaXphdGlvbiBzb3VyY2Ugb2YgQmxvYlN0b3JlIChzZWUgcmVtb3RlU3RvcmFnZS9ibG9iU3RvcmUudHMpLlxuXG5jb25zdCBIQU5ETEVfSURMRV9USU1FT1VUID0gMTAwMCAqIDYwO1xuY29uc3QgSEFORExFX1NXRUVQX0lOVEVSVkFMID0gMTAwMCAqIDE1O1xuXG50eXBlIEhhbmRsZUVudHJ5ID0ge1xuICAgIGZpbGVQYXRoOiBzdHJpbmc7XG4gICAgaGFuZGxlOiBmcy5wcm9taXNlcy5GaWxlSGFuZGxlO1xuICAgIGxhc3RVc2U6IG51bWJlcjtcbn07XG5cbi8vIENhY2hlcyBvcGVuIGZpbGUgaGFuZGxlcywgY2xvc2luZyB0aGVtIG9uY2UgaWRsZSBmb3IgSEFORExFX0lETEVfVElNRU9VVC4gSW5zdGVhZCBvZiBvbmVcbi8vIHNldFRpbWVvdXQgcGVyIGhhbmRsZSwgYSBsaXN0IHNvcnRlZCBieSBsYXN0IHVzZSBpcyBzd2VwdCBwZXJpb2RpY2FsbHkgKGVudHJpZXMgYXJlIG1vdmVkIHZpYVxuLy8gYmluYXJ5IHNlYXJjaCBvbiBhY2Nlc3MsIGFuZCBsYXN0VXNlIHZhbHVlcyBvbmx5IGluY3JlYXNlLCBzbyB0b3VjaGVkIGVudHJpZXMgYXBwZW5kIGF0IHRoZVxuLy8gZW5kKS4gQWxzbyBzZXJpYWxpemVzIG9wZXJhdGlvbnMgcGVyIGZpbGU6IGVhY2ggb3BlcmF0aW9uIG9ubHkgc3RhcnRzIG9uY2UgdGhlIHByZXZpb3VzIG9uZSBvblxuLy8gdGhlIHNhbWUgZmlsZSBmaW5pc2hlZCwgYW5kIGEgaGFuZGxlIGlzIG5ldmVyIGNsb3NlZCB3aGlsZSBhbiBvcGVyYXRpb24gaXMgcGVuZGluZyBvbiBpdC5cbmNsYXNzIEZpbGVIYW5kbGVDYWNoZSB7XG4gICAgcHJpdmF0ZSBlbnRyaWVzID0gbmV3IE1hcDxzdHJpbmcsIEhhbmRsZUVudHJ5PigpO1xuICAgIC8vIFNvcnRlZCBieSBsYXN0VXNlIGFzY2VuZGluZyAobGVhc3QgcmVjZW50bHkgdXNlZCBmaXJzdClcbiAgICBwcml2YXRlIGxydTogSGFuZGxlRW50cnlbXSA9IFtdO1xuICAgIHByaXZhdGUgcGVuZGluZyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PigpO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHJ1bkluZmluaXRlUG9sbChIQU5ETEVfU1dFRVBfSU5URVJWQUwsICgpID0+IHRoaXMuc3dlZXAoKSk7XG4gICAgfVxuXG4gICAgLy8gUnVucyBmbmMgYWZ0ZXIgZXZlcnkgcHJldmlvdXNseSBzY2hlZHVsZWQgb3BlcmF0aW9uIG9uIGZpbGVQYXRoIGhhcyBmaW5pc2hlZFxuICAgIHB1YmxpYyBydW48VD4oZmlsZVBhdGg6IHN0cmluZywgZm5jOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgICAgIGxldCBwcmV2ID0gdGhpcy5wZW5kaW5nLmdldChmaWxlUGF0aCkgfHwgUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIGxldCByZXN1bHQgPSBwcmV2LnRoZW4oZm5jKTtcbiAgICAgICAgLy8gVGhlIHBlbmRpbmcgY2hhaW4gbXVzdCBuZXZlciByZWplY3QsIG9yIG9uZSBmYWlsZWQgb3BlcmF0aW9uIHdvdWxkIHBvaXNvbiBhbGwgbGF0ZXIgb25lc1xuICAgICAgICBsZXQgbGFzdCA9IHJlc3VsdC50aGVuKCgpID0+IHsgfSwgKCkgPT4geyB9KTtcbiAgICAgICAgdGhpcy5wZW5kaW5nLnNldChmaWxlUGF0aCwgbGFzdCk7XG4gICAgICAgIHZvaWQgbGFzdC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIC8vIElmIHdlJ3JlIHN0aWxsIHRoZSBsYXN0IHBlbmRpbmcgb3BlcmF0aW9uIG9uIHRoaXMgZmlsZSwgY2xlYXIgb3Vyc2VsdmVzXG4gICAgICAgICAgICBpZiAodGhpcy5wZW5kaW5nLmdldChmaWxlUGF0aCkgPT09IGxhc3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmcuZGVsZXRlKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLy8gT25seSBjYWxsIGluc2lkZSBydW4oKSBmb3IgdGhlIHNhbWUgZmlsZVBhdGggKHNvIG9wZW5zIGNhbid0IGNvbGxpZGUgd2l0aCBjbG9zZXMpXG4gICAgcHVibGljIGFzeW5jIGdldEhhbmRsZShmaWxlUGF0aDogc3RyaW5nLCBmbGFnczogbnVtYmVyKTogUHJvbWlzZTxmcy5wcm9taXNlcy5GaWxlSGFuZGxlPiB7XG4gICAgICAgIGxldCBlbnRyeSA9IHRoaXMuZW50cmllcy5nZXQoZmlsZVBhdGgpO1xuICAgICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbUxSVShlbnRyeSk7XG4gICAgICAgICAgICBlbnRyeS5sYXN0VXNlID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIHRoaXMubHJ1LnB1c2goZW50cnkpO1xuICAgICAgICAgICAgcmV0dXJuIGVudHJ5LmhhbmRsZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaGFuZGxlID0gYXdhaXQgZnMucHJvbWlzZXMub3BlbihmaWxlUGF0aCwgZmxhZ3MpO1xuICAgICAgICBlbnRyeSA9IHsgZmlsZVBhdGgsIGhhbmRsZSwgbGFzdFVzZTogRGF0ZS5ub3coKSB9O1xuICAgICAgICB0aGlzLmVudHJpZXMuc2V0KGZpbGVQYXRoLCBlbnRyeSk7XG4gICAgICAgIHRoaXMubHJ1LnB1c2goZW50cnkpO1xuICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgIH1cblxuICAgIC8vIE9ubHkgY2FsbCBpbnNpZGUgcnVuKCkgZm9yIHRoZSBzYW1lIGZpbGVQYXRoXG4gICAgcHVibGljIGFzeW5jIGNsb3NlTm93KGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IGVudHJ5ID0gdGhpcy5lbnRyaWVzLmdldChmaWxlUGF0aCk7XG4gICAgICAgIGlmICghZW50cnkpIHJldHVybjtcbiAgICAgICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShmaWxlUGF0aCk7XG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbUxSVShlbnRyeSk7XG4gICAgICAgIGF3YWl0IGVudHJ5LmhhbmRsZS5jbG9zZSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3ZlRnJvbUxSVShlbnRyeTogSGFuZGxlRW50cnkpIHtcbiAgICAgICAgbGV0IGluZGV4ID0gYmluYXJ5U2VhcmNoQmFzaWModGhpcy5scnUsIHggPT4geC5sYXN0VXNlLCBlbnRyeS5sYXN0VXNlKTtcbiAgICAgICAgaWYgKGluZGV4IDwgMCkgcmV0dXJuO1xuICAgICAgICAvLyBNdWx0aXBsZSBlbnRyaWVzIGNhbiBzaGFyZSBhIGxhc3RVc2UsIHNvIHNjYW4gZm9yIHRoZSBleGFjdCBvbmVcbiAgICAgICAgd2hpbGUgKGluZGV4IDwgdGhpcy5scnUubGVuZ3RoICYmIHRoaXMubHJ1W2luZGV4XS5sYXN0VXNlID09PSBlbnRyeS5sYXN0VXNlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5scnVbaW5kZXhdID09PSBlbnRyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMubHJ1LnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgc3dlZXAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGxldCBjdXRvZmYgPSBEYXRlLm5vdygpIC0gSEFORExFX0lETEVfVElNRU9VVDtcbiAgICAgICAgbGV0IGluZGV4ID0gMDtcbiAgICAgICAgd2hpbGUgKGluZGV4IDwgdGhpcy5scnUubGVuZ3RoICYmIHRoaXMubHJ1W2luZGV4XS5sYXN0VXNlIDw9IGN1dG9mZikge1xuICAgICAgICAgICAgbGV0IGVudHJ5ID0gdGhpcy5scnVbaW5kZXhdO1xuICAgICAgICAgICAgLy8gQ2FuJ3QgY2xvc2UgYSBoYW5kbGUgd2l0aCBhIHBlbmRpbmcgb3BlcmF0aW9uOyBpdCdsbCBiZSBzd2VwdCBhZnRlciBpdCBmaW5pc2hlc1xuICAgICAgICAgICAgaWYgKHRoaXMucGVuZGluZy5oYXMoZW50cnkuZmlsZVBhdGgpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubHJ1LnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICB0aGlzLmVudHJpZXMuZGVsZXRlKGVudHJ5LmZpbGVQYXRoKTtcbiAgICAgICAgICAgIGF3YWl0IGVudHJ5LmhhbmRsZS5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgQXJjaGl2ZXNEaXNrIGltcGxlbWVudHMgSUFyY2hpdmVzIHtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZvbGRlcjogc3RyaW5nKSB7IH1cblxuICAgIHByaXZhdGUgZmlsZXNEaXIgPSBwYXRoLmpvaW4odGhpcy5mb2xkZXIsIFwiZmlsZXNcIik7XG4gICAgcHJpdmF0ZSB1cGxvYWRzRGlyID0gcGF0aC5qb2luKHRoaXMuZm9sZGVyLCBcInVwbG9hZHNcIik7XG4gICAgcHJpdmF0ZSBoYW5kbGVzID0gbmV3IEZpbGVIYW5kbGVDYWNoZSgpO1xuICAgIHByaXZhdGUgbGFyZ2VVcGxvYWRzID0gbmV3IE1hcDxzdHJpbmcsIHsgdG1wUGF0aDogc3RyaW5nIH0+KCk7XG4gICAgcHJpdmF0ZSBuZXh0TGFyZ2VVcGxvYWRJZCA9IDE7XG5cbiAgICBwdWJsaWMgaW5pdCA9IGxhenkoYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBmcy5wcm9taXNlcy5ta2Rpcih0aGlzLmZpbGVzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgYXdhaXQgZnMucHJvbWlzZXMubWtkaXIodGhpcy51cGxvYWRzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgLy8gVXBsb2FkcyBkb24ndCBzdXJ2aXZlIHJlc3RhcnRzICh0aGUgdXBsb2FkZXIgc3RyZWFtcyBpbnRvIHRoZW0pLCBzbyBvbGQgb25lcyBhcmUgZ2FyYmFnZVxuICAgICAgICBmb3IgKGxldCBmaWxlIG9mIGF3YWl0IGZzLnByb21pc2VzLnJlYWRkaXIodGhpcy51cGxvYWRzRGlyKSkge1xuICAgICAgICAgICAgYXdhaXQgZnMucHJvbWlzZXMudW5saW5rKHBhdGguam9pbih0aGlzLnVwbG9hZHNEaXIsIGZpbGUpKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgcHVibGljIGdldERlYnVnTmFtZSgpIHtcbiAgICAgICAgcmV0dXJuIGBkaXNrLyR7dGhpcy5mb2xkZXJ9YDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0Q29uZmlnKCk6IFByb21pc2U8QXJjaGl2ZXNDb25maWc+IHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBoYXNXcml0ZUFjY2VzcygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaWxlUGF0aChrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGxldCByZXN1bHQgPSBwYXRoLmpvaW4odGhpcy5maWxlc0Rpciwga2V5KTtcbiAgICAgICAgaWYgKCFyZXN1bHQuc3RhcnRzV2l0aCh0aGlzLmZpbGVzRGlyICsgcGF0aC5zZXApKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQga2V5ICR7SlNPTi5zdHJpbmdpZnkoa2V5LnNsaWNlKDAsIDIwMCkpfSwgaXQgZXNjYXBlcyB0aGUgc3RvcmUgZm9sZGVyYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2V0KGtleTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IHsgbGFzdE1vZGlmaWVkPzogbnVtYmVyIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5pbml0KCk7XG4gICAgICAgIGxldCBsYXN0TW9kaWZpZWQgPSBjb25maWc/Lmxhc3RNb2RpZmllZDtcbiAgICAgICAgaWYgKGxhc3RNb2RpZmllZCkge1xuICAgICAgICAgICAgYXNzZXJ0VmFsaWRMYXN0TW9kaWZpZWQobGFzdE1vZGlmaWVkKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZmlsZVBhdGggPSB0aGlzLmZpbGVQYXRoKGtleSk7XG4gICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlcy5ydW4oZmlsZVBhdGgsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGlmIChsYXN0TW9kaWZpZWQpIHtcbiAgICAgICAgICAgICAgICBsZXQgZXhpc3RpbmcgPSBhd2FpdCBzdGF0T3JVbmRlZmluZWQoZmlsZVBhdGgpO1xuICAgICAgICAgICAgICAgIC8vIEFuIG9sZGVyIHdyaXRlIG5ldmVyIG92ZXJ3cml0ZXMgYSBuZXdlciBvbmUgKHNlZSBJQXJjaGl2ZXMuc2V0KVxuICAgICAgICAgICAgICAgIGlmIChleGlzdGluZyAmJiBsYXN0TW9kaWZpZWQgPCBleGlzdGluZy5tdGltZU1zKSByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBmcy5wcm9taXNlcy5ta2RpcihwYXRoLmRpcm5hbWUoZmlsZVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgIGxldCBoYW5kbGUgPSBhd2FpdCB0aGlzLmhhbmRsZXMuZ2V0SGFuZGxlKGZpbGVQYXRoLCBmcy5jb25zdGFudHMuT19SRFdSIHwgZnMuY29uc3RhbnRzLk9fQ1JFQVQpO1xuICAgICAgICAgICAgYXdhaXQgaGFuZGxlLnRydW5jYXRlKDApO1xuICAgICAgICAgICAgYXdhaXQgaGFuZGxlLndyaXRlKGRhdGEsIDAsIGRhdGEubGVuZ3RoLCAwKTtcbiAgICAgICAgICAgIGlmIChsYXN0TW9kaWZpZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBoYW5kbGUudXRpbWVzKG5ldyBEYXRlKGxhc3RNb2RpZmllZCksIG5ldyBEYXRlKGxhc3RNb2RpZmllZCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZGVsKGtleTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW5pdCgpO1xuICAgICAgICBsZXQgZmlsZVBhdGggPSB0aGlzLmZpbGVQYXRoKGtleSk7XG4gICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlcy5ydW4oZmlsZVBhdGgsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlcy5jbG9zZU5vdyhmaWxlUGF0aCk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZzLnByb21pc2VzLnVubGluayhmaWxlUGF0aCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoZS5jb2RlICE9PSBcIkVOT0VOVFwiKSB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0KGtleTogc3RyaW5nLCBjb25maWc/OiB7IHJhbmdlPzogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlciB9IH0pOiBQcm9taXNlPEJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBsZXQgcmVzdWx0ID0gYXdhaXQgdGhpcy5nZXQyKGtleSwgY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiByZXN1bHQuZGF0YSB8fCB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldDIoa2V5OiBzdHJpbmcsIGNvbmZpZz86IHsgcmFuZ2U/OiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH0gfSk6IFByb21pc2U8eyBkYXRhOiBCdWZmZXI7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLmluaXQoKTtcbiAgICAgICAgbGV0IHJhbmdlID0gY29uZmlnPy5yYW5nZTtcbiAgICAgICAgbGV0IGZpbGVQYXRoID0gdGhpcy5maWxlUGF0aChrZXkpO1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5oYW5kbGVzLnJ1bihmaWxlUGF0aCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgbGV0IGhhbmRsZTogZnMucHJvbWlzZXMuRmlsZUhhbmRsZTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlID0gYXdhaXQgdGhpcy5oYW5kbGVzLmdldEhhbmRsZShmaWxlUGF0aCwgZnMuY29uc3RhbnRzLk9fUkRXUik7XG4gICAgICAgICAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgICAgICAgICAgICBpZiAoZS5jb2RlID09PSBcIkVOT0VOVFwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3RhdHMgPSBhd2FpdCBoYW5kbGUuc3RhdCgpO1xuICAgICAgICAgICAgbGV0IHNpemUgPSBzdGF0cy5zaXplO1xuICAgICAgICAgICAgbGV0IHN0YXJ0ID0gcmFuZ2UgJiYgTWF0aC5taW4ocmFuZ2Uuc3RhcnQsIHNpemUpIHx8IDA7XG4gICAgICAgICAgICBsZXQgZW5kID0gcmFuZ2UgJiYgTWF0aC5taW4ocmFuZ2UuZW5kLCBzaXplKSB8fCBzaXplO1xuICAgICAgICAgICAgaWYgKGVuZCA8PSBzdGFydCkgcmV0dXJuIHsgZGF0YTogQnVmZmVyLmFsbG9jKDApLCB3cml0ZVRpbWU6IHN0YXRzLm10aW1lTXMsIHNpemUgfTtcbiAgICAgICAgICAgIGxldCBidWZmZXIgPSBCdWZmZXIuYWxsb2MoZW5kIC0gc3RhcnQpO1xuICAgICAgICAgICAgbGV0IHsgYnl0ZXNSZWFkIH0gPSBhd2FpdCBoYW5kbGUucmVhZChidWZmZXIsIDAsIGJ1ZmZlci5sZW5ndGgsIHN0YXJ0KTtcbiAgICAgICAgICAgIGlmIChieXRlc1JlYWQgIT09IGJ1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkICR7YnVmZmVyLmxlbmd0aH0gYnl0ZXMgYXQgJHtmaWxlUGF0aH06JHtzdGFydH0sIHJlYWQgJHtieXRlc1JlYWR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geyBkYXRhOiBidWZmZXIsIHdyaXRlVGltZTogc3RhdHMubXRpbWVNcywgc2l6ZSB9O1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0SW5mbyhrZXk6IHN0cmluZyk6IFByb21pc2U8eyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH0gfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5pbml0KCk7XG4gICAgICAgIGxldCBmaWxlUGF0aCA9IHRoaXMuZmlsZVBhdGgoa2V5KTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaGFuZGxlcy5ydW4oZmlsZVBhdGgsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGxldCBzdGF0cyA9IGF3YWl0IHN0YXRPclVuZGVmaW5lZChmaWxlUGF0aCk7XG4gICAgICAgICAgICBpZiAoIXN0YXRzIHx8ICFzdGF0cy5pc0ZpbGUoKSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJldHVybiB7IHdyaXRlVGltZTogc3RhdHMubXRpbWVNcywgc2l6ZTogc3RhdHMuc2l6ZSB9O1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZmluZChwcmVmaXg6IHN0cmluZywgY29uZmlnPzogeyBzaGFsbG93PzogYm9vbGVhbjsgdHlwZTogXCJmaWxlc1wiIHwgXCJmb2xkZXJzXCIgfSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmZpbmRJbmZvKHByZWZpeCwgY29uZmlnKSkubWFwKHggPT4geC5wYXRoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZmluZEluZm8ocHJlZml4OiBzdHJpbmcsIGNvbmZpZz86IHsgc2hhbGxvdz86IGJvb2xlYW47IHR5cGU/OiBcImZpbGVzXCIgfCBcImZvbGRlcnNcIiB9KTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT4ge1xuICAgICAgICBhd2FpdCB0aGlzLmluaXQoKTtcbiAgICAgICAgbGV0IGluZm9zID0gbmV3IE1hcDxzdHJpbmcsIEFyY2hpdmVGaWxlSW5mbz4oKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jb2xsZWN0RmlsZXMoXCJcIiwgcHJlZml4LCBpbmZvcyk7XG4gICAgICAgIGxldCBmaWxlcyA9IEFycmF5LmZyb20oaW5mb3MudmFsdWVzKCkpO1xuICAgICAgICBmaWxlcyA9IGFwcGx5RmluZEluZm9TaGFwZShmaWxlcywgcHJlZml4LCBjb25maWcpO1xuICAgICAgICBzb3J0KGZpbGVzLCB4ID0+IHgucGF0aCk7XG4gICAgICAgIHJldHVybiBmaWxlcztcbiAgICB9XG5cbiAgICAvLyByZWxEaXIgaXMgXCJcIiBvciBlbmRzIHdpdGggXCIvXCIuIE9ubHkgZGVzY2VuZHMgaW50byBkaXJlY3RvcmllcyB0aGF0IGNhbiBzdGlsbCBtYXRjaCB0aGUgcHJlZml4LlxuICAgIHByaXZhdGUgYXN5bmMgY29sbGVjdEZpbGVzKHJlbERpcjogc3RyaW5nLCBwcmVmaXg6IHN0cmluZywgaW5mb3M6IE1hcDxzdHJpbmcsIEFyY2hpdmVGaWxlSW5mbz4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IGVudHJpZXM6IGZzLkRpcmVudFtdO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZW50cmllcyA9IGF3YWl0IGZzLnByb21pc2VzLnJlYWRkaXIocGF0aC5qb2luKHRoaXMuZmlsZXNEaXIsIHJlbERpciksIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBpZiAoZS5jb2RlID09PSBcIkVOT0VOVFwiKSByZXR1cm47XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGxldCByZWxQYXRoID0gcmVsRGlyICsgZW50cnkubmFtZTtcbiAgICAgICAgICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgICAgICAgbGV0IGRpclBhdGggPSByZWxQYXRoICsgXCIvXCI7XG4gICAgICAgICAgICAgICAgaWYgKGRpclBhdGguc3RhcnRzV2l0aChwcmVmaXgpIHx8IHByZWZpeC5zdGFydHNXaXRoKGRpclBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY29sbGVjdEZpbGVzKGRpclBhdGgsIHByZWZpeCwgaW5mb3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghZW50cnkuaXNGaWxlKCkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKCFyZWxQYXRoLnN0YXJ0c1dpdGgocHJlZml4KSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgc3RhdHMgPSBhd2FpdCBzdGF0T3JVbmRlZmluZWQocGF0aC5qb2luKHRoaXMuZmlsZXNEaXIsIHJlbFBhdGgpKTtcbiAgICAgICAgICAgIC8vIERlbGV0ZWQgd2hpbGUgd2Ugd2VyZSB3YWxraW5nXG4gICAgICAgICAgICBpZiAoIXN0YXRzKSBjb250aW51ZTtcbiAgICAgICAgICAgIGluZm9zLnNldChyZWxQYXRoLCB7IHBhdGg6IHJlbFBhdGgsIGNyZWF0ZVRpbWU6IHN0YXRzLm10aW1lTXMsIHNpemU6IHN0YXRzLnNpemUgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2V0TGFyZ2VGaWxlKGNvbmZpZzogeyBwYXRoOiBzdHJpbmc7IGdldE5leHREYXRhKCk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPiB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGxldCBpZCA9IGF3YWl0IHRoaXMuc3RhcnRMYXJnZVVwbG9hZCgpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICBsZXQgZGF0YSA9IGF3YWl0IGNvbmZpZy5nZXROZXh0RGF0YSgpO1xuICAgICAgICAgICAgICAgIGlmICghZGF0YSkgYnJlYWs7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5hcHBlbmRMYXJnZVVwbG9hZChpZCwgZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmZpbmlzaExhcmdlVXBsb2FkKGlkLCBjb25maWcucGF0aCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2FuY2VsTGFyZ2VVcGxvYWQoaWQpO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIExhcmdlIGZpbGVzIHN0cmVhbSBpbnRvIHRoZWlyIG93biBmaWxlIHVuZGVyIHVwbG9hZHMvLCB0aGVuIG1vdmUgaW50byBwbGFjZSBvbiBmaW5pc2guIE5vXG4gICAgLy8gaGFuZGxlIGlzIG9wZW5lZCB1bnRpbCB0aGUgZmlyc3QgYXBwZW5kIGFjdHVhbGx5IGhhcHBlbnMuXG4gICAgcHVibGljIGFzeW5jIHN0YXJ0TGFyZ2VVcGxvYWQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5pbml0KCk7XG4gICAgICAgIGxldCBpZCA9IGAke0RhdGUubm93KCl9XyR7dGhpcy5uZXh0TGFyZ2VVcGxvYWRJZCsrfWA7XG4gICAgICAgIHRoaXMubGFyZ2VVcGxvYWRzLnNldChpZCwgeyB0bXBQYXRoOiBwYXRoLmpvaW4odGhpcy51cGxvYWRzRGlyLCBgdXBsb2FkXyR7aWR9LnRtcGApIH0pO1xuICAgICAgICByZXR1cm4gaWQ7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBhcHBlbmRMYXJnZVVwbG9hZChpZDogc3RyaW5nLCBkYXRhOiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IHVwbG9hZCA9IHRoaXMubGFyZ2VVcGxvYWRzLmdldChpZCk7XG4gICAgICAgIGlmICghdXBsb2FkKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gbGFyZ2UgdXBsb2FkICR7aWR9YCk7XG4gICAgICAgIGNvbnN0IHRtcFBhdGggPSB1cGxvYWQudG1wUGF0aDtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVzLnJ1bih0bXBQYXRoLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgaGFuZGxlID0gYXdhaXQgdGhpcy5oYW5kbGVzLmdldEhhbmRsZSh0bXBQYXRoLCBmcy5jb25zdGFudHMuT19XUk9OTFkgfCBmcy5jb25zdGFudHMuT19DUkVBVCB8IGZzLmNvbnN0YW50cy5PX0FQUEVORCk7XG4gICAgICAgICAgICBhd2FpdCBoYW5kbGUud3JpdGUoZGF0YSwgMCwgZGF0YS5sZW5ndGgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGZpbmlzaExhcmdlVXBsb2FkKGlkOiBzdHJpbmcsIGtleTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGxldCB1cGxvYWQgPSB0aGlzLmxhcmdlVXBsb2Fkcy5nZXQoaWQpO1xuICAgICAgICBpZiAoIXVwbG9hZCkgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGxhcmdlIHVwbG9hZCAke2lkfWApO1xuICAgICAgICBjb25zdCB0bXBQYXRoID0gdXBsb2FkLnRtcFBhdGg7XG4gICAgICAgIHRoaXMubGFyZ2VVcGxvYWRzLmRlbGV0ZShpZCk7XG4gICAgICAgIGxldCBmaWxlUGF0aCA9IHRoaXMuZmlsZVBhdGgoa2V5KTtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVzLnJ1bih0bXBQYXRoLCAoKSA9PiB0aGlzLmhhbmRsZXMuY2xvc2VOb3codG1wUGF0aCkpO1xuICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZXMucnVuKGZpbGVQYXRoLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAvLyBDbG9zZSBhbnkgY2FjaGVkIGhhbmRsZSB0byB0aGUgZmlsZSB3ZSdyZSByZXBsYWNpbmcsIHNvIGxhdGVyIHJlYWRzIHJlb3BlbiB0aGUgbmV3IGZpbGVcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlcy5jbG9zZU5vdyhmaWxlUGF0aCk7XG4gICAgICAgICAgICBhd2FpdCBmcy5wcm9taXNlcy5ta2RpcihwYXRoLmRpcm5hbWUoZmlsZVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZnMucHJvbWlzZXMucmVuYW1lKHRtcFBhdGgsIGZpbGVQYXRoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgIGlmIChlLmNvZGUgIT09IFwiRU5PRU5UXCIpIHRocm93IGU7XG4gICAgICAgICAgICAgICAgLy8gTm90aGluZyB3YXMgZXZlciBhcHBlbmRlZCwgc28gdGhlIHVwbG9hZCBmaWxlIHdhcyBuZXZlciBjcmVhdGVkXG4gICAgICAgICAgICAgICAgYXdhaXQgZnMucHJvbWlzZXMud3JpdGVGaWxlKGZpbGVQYXRoLCBCdWZmZXIuYWxsb2MoMCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGNhbmNlbExhcmdlVXBsb2FkKGlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbGV0IHVwbG9hZCA9IHRoaXMubGFyZ2VVcGxvYWRzLmdldChpZCk7XG4gICAgICAgIGlmICghdXBsb2FkKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHRtcFBhdGggPSB1cGxvYWQudG1wUGF0aDtcbiAgICAgICAgdGhpcy5sYXJnZVVwbG9hZHMuZGVsZXRlKGlkKTtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVzLnJ1bih0bXBQYXRoLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZXMuY2xvc2VOb3codG1wUGF0aCk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZzLnByb21pc2VzLnVubGluayh0bXBQYXRoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgIGlmIChlLmNvZGUgIT09IFwiRU5PRU5UXCIpIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRVUkwocGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBnZXRVUkwgaXMgbm90IHN1cHBvcnRlZCBmb3IgZGlzayBhcmNoaXZlcyAoJHt0aGlzLmdldERlYnVnTmFtZSgpfSwgcGF0aCAke3BhdGh9KWApO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gc3RhdE9yVW5kZWZpbmVkKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPGZzLlN0YXRzIHwgdW5kZWZpbmVkPiB7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZzLnByb21pc2VzLnN0YXQoZmlsZVBhdGgpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICBpZiAoZS5jb2RlID09PSBcIkVOT0VOVFwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB0aHJvdyBlO1xuICAgIH1cbn1cblxuLy8gVGhlIGZvbGRlcnMvc2hhbGxvdyBwb3N0LXByb2Nlc3Npbmcgc2hhcmVkIGJ5IGZpbmRJbmZvIGltcGxlbWVudGF0aW9ucyB0aGF0IGxpc3QgZmxhdCBmaWxlc1xuLy8gKHVzZWQgYnkgQXJjaGl2ZXNEaXNrIG9uIHRoZSByYXcgZGlzayB3YWxrLCBhbmQgYnkgQmxvYlN0b3JlIG9uIGl0cyBpbmRleCkuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlGaW5kSW5mb1NoYXBlKGZpbGVzOiBBcmNoaXZlRmlsZUluZm9bXSwgcHJlZml4OiBzdHJpbmcsIGNvbmZpZz86IHsgc2hhbGxvdz86IGJvb2xlYW47IHR5cGU/OiBcImZpbGVzXCIgfCBcImZvbGRlcnNcIiB9KTogQXJjaGl2ZUZpbGVJbmZvW10ge1xuICAgIGlmIChjb25maWc/LnR5cGUgPT09IFwiZm9sZGVyc1wiKSB7XG4gICAgICAgIGxldCBmb2xkZXJzID0gbmV3IE1hcDxzdHJpbmcsIEFyY2hpdmVGaWxlSW5mbz4oKTtcbiAgICAgICAgZm9yIChsZXQgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICAgICAgbGV0IHJlc3QgPSBmaWxlLnBhdGguc2xpY2UocHJlZml4Lmxlbmd0aCk7XG4gICAgICAgICAgICBsZXQgcmVzdFBhcnRzID0gcmVzdC5zcGxpdChcIi9cIik7XG4gICAgICAgICAgICBpZiAocmVzdFBhcnRzLmxlbmd0aCA8IDIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IGZvbGRlcjogc3RyaW5nO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5zaGFsbG93KSB7XG4gICAgICAgICAgICAgICAgZm9sZGVyID0gcHJlZml4ICsgcmVzdFBhcnRzWzBdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb2xkZXIgPSBmaWxlLnBhdGguc3BsaXQoXCIvXCIpLnNsaWNlKDAsIC0xKS5qb2luKFwiL1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvbGRlcnMuc2V0KGZvbGRlciwgeyBwYXRoOiBmb2xkZXIsIGNyZWF0ZVRpbWU6IGZpbGUuY3JlYXRlVGltZSwgc2l6ZTogZmlsZS5zaXplIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKGZvbGRlcnMudmFsdWVzKCkpO1xuICAgIH1cbiAgICBpZiAoY29uZmlnPy5zaGFsbG93KSB7XG4gICAgICAgIHJldHVybiBmaWxlcy5maWx0ZXIoZmlsZSA9PiAhZmlsZS5wYXRoLnNsaWNlKHByZWZpeC5sZW5ndGgpLmluY2x1ZGVzKFwiL1wiKSk7XG4gICAgfVxuICAgIHJldHVybiBmaWxlcztcbn1cbiJdfQ==
373
+ /* _JS_SOURCE_HASH = "9e9a4bb7586f9d75283eaf57d9a71e2ffd25ef1ea107a52ec483353eb71dc468"; */