obsidian-integration-testing 4.4.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +51 -54
  2. package/dist/lib/cjs/eval-in-obsidian.cjs +1 -1
  3. package/dist/lib/cjs/eval-in-obsidian.d.cts +36 -1
  4. package/dist/lib/cjs/global-setup-core.cjs +13 -9
  5. package/dist/lib/cjs/global-setup-core.d.cts +1 -1
  6. package/dist/lib/cjs/index.cjs +1 -4
  7. package/dist/lib/cjs/index.d.cts +3 -4
  8. package/dist/lib/cjs/kill-process-tree.cjs +57 -0
  9. package/dist/lib/cjs/kill-process-tree.d.cts +16 -0
  10. package/dist/lib/cjs/library.cjs +1 -1
  11. package/dist/lib/cjs/namespace-bootstrap.cjs +21 -2
  12. package/dist/lib/cjs/obsidian-config.cjs +11 -85
  13. package/dist/lib/cjs/obsidian-config.d.cts +12 -72
  14. package/dist/lib/cjs/obsidian-installer.cjs +180 -0
  15. package/dist/lib/cjs/obsidian-installer.d.cts +45 -0
  16. package/dist/lib/cjs/obsidian-instance.cjs +100 -0
  17. package/dist/lib/cjs/obsidian-instance.d.cts +55 -0
  18. package/dist/lib/cjs/obsidian-version-switch.cjs +105 -0
  19. package/dist/lib/cjs/obsidian-version-switch.d.cts +63 -0
  20. package/dist/lib/cjs/obsidian-version.cjs +85 -0
  21. package/dist/lib/cjs/obsidian-version.d.cts +111 -0
  22. package/dist/lib/cjs/transport-desktop-cdp.cjs +121 -7
  23. package/dist/lib/cjs/transport-desktop-cdp.d.cts +75 -14
  24. package/dist/lib/cjs/transport-factory.cjs +63 -32
  25. package/dist/lib/cjs/transport-options.cjs +1 -1
  26. package/dist/lib/cjs/transport-options.d.cts +37 -14
  27. package/dist/lib/cjs/transport.cjs +1 -1
  28. package/dist/lib/cjs/transport.d.cts +1 -1
  29. package/dist/lib/cjs/vitest/global-setup.cjs +2 -2
  30. package/dist/lib/cjs/vitest/typings.d.cts +1 -1
  31. package/dist/lib/esm/eval-in-obsidian.d.mts +36 -1
  32. package/dist/lib/esm/eval-in-obsidian.mjs +1 -1
  33. package/dist/lib/esm/global-setup-core.d.mts +1 -1
  34. package/dist/lib/esm/global-setup-core.mjs +13 -9
  35. package/dist/lib/esm/index.d.mts +3 -4
  36. package/dist/lib/esm/index.mjs +1 -3
  37. package/dist/lib/esm/kill-process-tree.d.mts +16 -0
  38. package/dist/lib/esm/kill-process-tree.mjs +23 -0
  39. package/dist/lib/esm/library.mjs +1 -1
  40. package/dist/lib/esm/namespace-bootstrap.mjs +21 -2
  41. package/dist/lib/esm/obsidian-config.d.mts +12 -72
  42. package/dist/lib/esm/obsidian-config.mjs +10 -78
  43. package/dist/lib/esm/obsidian-installer.d.mts +45 -0
  44. package/dist/lib/esm/obsidian-installer.mjs +158 -0
  45. package/dist/lib/esm/obsidian-instance.d.mts +55 -0
  46. package/dist/lib/esm/obsidian-instance.mjs +75 -0
  47. package/dist/lib/esm/obsidian-version-switch.d.mts +63 -0
  48. package/dist/lib/esm/obsidian-version-switch.mjs +89 -0
  49. package/dist/lib/esm/obsidian-version.d.mts +111 -0
  50. package/dist/lib/esm/obsidian-version.mjs +55 -0
  51. package/dist/lib/esm/transport-desktop-cdp.d.mts +75 -14
  52. package/dist/lib/esm/transport-desktop-cdp.mjs +125 -7
  53. package/dist/lib/esm/transport-factory.mjs +68 -28
  54. package/dist/lib/esm/transport-options.d.mts +37 -14
  55. package/dist/lib/esm/transport.d.mts +1 -1
  56. package/dist/lib/esm/vitest/global-setup.mjs +2 -2
  57. package/dist/lib/esm/vitest/typings.d.mts +1 -1
  58. package/dist/obsidian-integration-testing-5.1.0.tgz +0 -0
  59. package/package.json +16 -15
  60. package/dist/lib/cjs/transport-desktop-cli.cjs +0 -540
  61. package/dist/lib/cjs/transport-desktop-cli.d.cts +0 -154
  62. package/dist/lib/esm/transport-desktop-cli.d.mts +0 -154
  63. package/dist/lib/esm/transport-desktop-cli.mjs +0 -520
  64. package/dist/obsidian-integration-testing-4.4.0.tgz +0 -0
@@ -1,3 +1,10 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import {
3
+ mkdirSync,
4
+ rmSync,
5
+ writeFileSync
6
+ } from "node:fs";
7
+ import { join } from "node:path";
1
8
  import process from "node:process";
2
9
  import { DISMISS_TRUST_DIALOG_EXPR } from "./dismiss-trust-dialog.mjs";
3
10
  import { exec } from "./exec.mjs";
@@ -9,9 +16,13 @@ import {
9
16
  removeVaultFromConfig
10
17
  } from "./obsidian-config.mjs";
11
18
  import { resolveObsidianExecutable } from "./obsidian-executable.mjs";
19
+ import { launchOwnedObsidianInstance } from "./obsidian-instance.mjs";
20
+ import { copyAsarIntoUserData } from "./obsidian-version-switch.mjs";
12
21
  import { ensureNonNullable } from "./type-guards.mjs";
13
- const CDP_DEFAULT_PORT = 8315;
14
22
  const COMMAND_TIMEOUT_IN_MILLISECONDS = 3e4;
23
+ const VAULT_ID_BYTE_LENGTH = 8;
24
+ const USER_DATA_RM_TIMEOUT_IN_MILLISECONDS = 1e4;
25
+ const USER_DATA_RM_RETRY_INTERVAL_IN_MILLISECONDS = 500;
15
26
  const NO_OUTPUT = "(no output)";
16
27
  const VAULT_POLL_INTERVAL_IN_MILLISECONDS = 500;
17
28
  const VAULT_POLL_TIMEOUT_IN_MILLISECONDS = 3e4;
@@ -24,10 +35,13 @@ class DesktopCdpTransport {
24
35
  */
25
36
  isMobile = false;
26
37
  activeVaultPath = null;
38
+ cdpHost;
27
39
  cdpPort;
28
40
  cdpUrl;
29
41
  commandTimeoutInMilliseconds;
30
42
  messageId = 0;
43
+ ownedConfig;
44
+ ownedInstance;
31
45
  ws = null;
32
46
  /**
33
47
  * Creates a new CDP transport.
@@ -35,17 +49,50 @@ class DesktopCdpTransport {
35
49
  * @param config - CDP connection configuration.
36
50
  */
37
51
  constructor(config) {
38
- const host = config?.cdpHost ?? "localhost";
39
- this.cdpPort = config?.cdpPort ?? CDP_DEFAULT_PORT;
40
- this.cdpUrl = `http://${host}:${String(this.cdpPort)}`;
52
+ this.cdpHost = config?.cdpHost ?? "localhost";
41
53
  this.commandTimeoutInMilliseconds = config?.commandTimeoutInMilliseconds ?? COMMAND_TIMEOUT_IN_MILLISECONDS;
54
+ this.ownedConfig = config?.ownedInstance;
55
+ this.cdpPort = config?.cdpPort ?? 0;
56
+ this.cdpUrl = config?.cdpPort === void 0 ? "" : `http://${this.cdpHost}:${String(config.cdpPort)}`;
42
57
  }
43
58
  /**
44
- * Disposes of the active WebSocket connection.
59
+ * Disposes of the active WebSocket connection and, in owned-instance mode,
60
+ * kills the owned Obsidian process and removes its isolated user-data dir.
61
+ *
62
+ * The removal is retried because Windows briefly holds the just-killed
63
+ * process's file handles, which would otherwise fail `rmSync` with `EPERM`.
45
64
  */
46
65
  async dispose() {
47
66
  this.disconnect();
48
- await Promise.resolve();
67
+ if (!this.ownedConfig) {
68
+ return;
69
+ }
70
+ this.ownedInstance?.kill();
71
+ const { userDataDir } = this.ownedConfig;
72
+ const deadline = Date.now() + USER_DATA_RM_TIMEOUT_IN_MILLISECONDS;
73
+ while (Date.now() < deadline) {
74
+ if (tryRemoveDir(userDataDir)) {
75
+ return;
76
+ }
77
+ await delay(USER_DATA_RM_RETRY_INTERVAL_IN_MILLISECONDS);
78
+ }
79
+ if (!tryRemoveDir(userDataDir)) {
80
+ log(`[cdp-transport] Could not remove owned user-data dir within ${String(USER_DATA_RM_TIMEOUT_IN_MILLISECONDS)}ms (non-fatal): ${userDataDir}`);
81
+ }
82
+ }
83
+ /**
84
+ * Synchronous disposal — kills the owned instance and makes a best-effort
85
+ * removal of its user-data dir. Safe to call from a process `exit` handler
86
+ * (where async retries are impossible; a leftover temp dir is acceptable).
87
+ */
88
+ disposeSync() {
89
+ this.disconnect();
90
+ if (this.ownedConfig) {
91
+ this.ownedInstance?.kill();
92
+ if (!tryRemoveDir(this.ownedConfig.userDataDir)) {
93
+ log(`[cdp-transport] Owned user-data dir not removed synchronously (process may still hold handles): ${this.ownedConfig.userDataDir}`);
94
+ }
95
+ }
49
96
  }
50
97
  /**
51
98
  * Evaluates a JavaScript expression inside Obsidian via CDP `Runtime.evaluate`.
@@ -82,6 +129,9 @@ class DesktopCdpTransport {
82
129
  * @param vaultPath - The vault path (used for vault registration check).
83
130
  */
84
131
  async preflightCheck(vaultPath) {
132
+ if (this.ownedConfig) {
133
+ return;
134
+ }
85
135
  log(`[cdp-transport] Running preflight check for vault: ${vaultPath}`);
86
136
  if (!isVaultRegistered(vaultPath)) {
87
137
  throw new Error(
@@ -107,6 +157,10 @@ class DesktopCdpTransport {
107
157
  * @param vaultPath - The absolute path to the vault folder.
108
158
  */
109
159
  async registerVault(vaultPath) {
160
+ if (this.ownedConfig) {
161
+ await this.registerVaultInOwnedInstance(vaultPath);
162
+ return;
163
+ }
110
164
  log(`[cdp-transport] Registering vault: ${vaultPath}`);
111
165
  const targets = await this.getPageTargets();
112
166
  if (targets.length === 0) {
@@ -146,6 +200,9 @@ class DesktopCdpTransport {
146
200
  * @param vaultPath - The absolute path to the vault folder.
147
201
  */
148
202
  async unregisterVault(vaultPath) {
203
+ if (this.ownedConfig) {
204
+ return;
205
+ }
149
206
  try {
150
207
  await ensureNamespaceBootstrapped(this, vaultPath);
151
208
  const target = await this.findTargetForVault(vaultPath);
@@ -355,6 +412,37 @@ class DesktopCdpTransport {
355
412
  ws.close();
356
413
  }
357
414
  }
415
+ /**
416
+ * Launches and connects to a harness-owned, isolated Obsidian instance for a
417
+ * vault: provisions the asar (if any), pre-seeds the isolated `obsidian.json`
418
+ * so the vault opens directly, launches the instance on a free CDP port, then
419
+ * waits until the vault window is ready and dismisses the trust dialog.
420
+ *
421
+ * @param vaultPath - The absolute path to the vault folder.
422
+ */
423
+ async registerVaultInOwnedInstance(vaultPath) {
424
+ const config = ensureNonNullable(this.ownedConfig);
425
+ log(`[cdp-transport] Launching owned Obsidian instance for vault: ${vaultPath}`);
426
+ mkdirSync(config.userDataDir, { recursive: true });
427
+ if (config.asar) {
428
+ copyAsarIntoUserData(config.asar.path, config.asar.version, config.userDataDir);
429
+ }
430
+ const vaultId = randomBytes(VAULT_ID_BYTE_LENGTH).toString("hex");
431
+ const obsidianJson = {
432
+ updateDisabled: true,
433
+ vaults: { [vaultId]: { open: true, path: vaultPath, ts: Date.now() } }
434
+ };
435
+ writeFileSync(join(config.userDataDir, "obsidian.json"), JSON.stringify(obsidianJson));
436
+ const instance = await launchOwnedObsidianInstance({
437
+ cdpHost: this.cdpHost,
438
+ exePath: config.exePath,
439
+ userDataDir: config.userDataDir
440
+ });
441
+ this.ownedInstance = instance;
442
+ this.cdpPort = instance.port;
443
+ this.cdpUrl = instance.cdpUrl;
444
+ await this.waitForOwnedVaultReady(vaultPath);
445
+ }
358
446
  /**
359
447
  * Sends a CDP command over WebSocket and waits for the response.
360
448
  *
@@ -398,6 +486,28 @@ class DesktopCdpTransport {
398
486
  await ensureNamespaceBootstrapped(this, vaultPath);
399
487
  await this.evaluate("window.__obsidianIntegrationTesting.pollVaultBasePath()", { cwd: vaultPath });
400
488
  }
489
+ /**
490
+ * Polls the owned instance until the vault target exists, layout is ready, and
491
+ * the trust dialog (if any) has been dismissed.
492
+ *
493
+ * @param vaultPath - The absolute path to the vault folder.
494
+ */
495
+ async waitForOwnedVaultReady(vaultPath) {
496
+ log(`[cdp-transport] Waiting for owned vault to become ready (timeout=${String(VAULT_POLL_TIMEOUT_IN_MILLISECONDS)}ms)...`);
497
+ const deadline = Date.now() + VAULT_POLL_TIMEOUT_IN_MILLISECONDS;
498
+ while (Date.now() < deadline) {
499
+ try {
500
+ await this.findTargetForVault(vaultPath);
501
+ await this.waitForLayoutReady(vaultPath);
502
+ await this.dismissTrustDialog(vaultPath);
503
+ log("[cdp-transport] Owned vault is ready.");
504
+ return;
505
+ } catch {
506
+ }
507
+ await delay(VAULT_POLL_INTERVAL_IN_MILLISECONDS);
508
+ }
509
+ throw new Error(`Owned vault at ${vaultPath} did not become ready within ${String(VAULT_POLL_TIMEOUT_IN_MILLISECONDS)}ms`);
510
+ }
401
511
  }
402
512
  function delay(ms) {
403
513
  return new Promise((resolve) => {
@@ -412,7 +522,15 @@ async function getObsidianLaunchCommand(port) {
412
522
  }
413
523
  return `"${exePath}" ${flag} &`;
414
524
  }
525
+ function tryRemoveDir(dir) {
526
+ try {
527
+ rmSync(dir, { force: true, recursive: true });
528
+ return true;
529
+ } catch {
530
+ return false;
531
+ }
532
+ }
415
533
  export {
416
534
  DesktopCdpTransport
417
535
  };
418
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1kZXNrdG9wLWNkcC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIERlc2t0b3AgQ0RQIHRyYW5zcG9ydCBcdTIwMTQgZXZhbHVhdGVzIGV4cHJlc3Npb25zIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2xcbiAqIG92ZXIgV2ViU29ja2V0IGFuZCBtYW5hZ2VzIHZhdWx0cyB2aWEgRWxlY3Ryb24gSVBDLlxuICpcbiAqIE9ic2lkaWFuIGV4cG9zZXMgQ0RQIG9uIHBvcnQgODMxNSBieSBkZWZhdWx0LiBUaGlzIHRyYW5zcG9ydCBjb25uZWN0cyB0b1xuICogcGFnZSB0YXJnZXRzLCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWAgY29tbWFuZHMsIGFuZCByb3V0ZXMgdG8gdGhlIGNvcnJlY3RcbiAqIHZhdWx0IHRhcmdldCB1c2luZyBgZ2V0QmFzZVBhdGgoKWAgcHJvYmluZy5cbiAqXG4gKiBBZHZhbnRhZ2VzIG92ZXIgQ0xJIHRyYW5zcG9ydDpcbiAqIC0gTm8gQ0xJIGJpbmFyeSBpbnN0YWxsYXRpb24gbmVlZGVkXG4gKiAtIE5vIFwiQ0xJIGVuYWJsZWRcIiBzZXR0aW5nIHJlcXVpcmVkIGluIE9ic2lkaWFuXG4gKiAtIExvd2VyIG92ZXJoZWFkIChXZWJTb2NrZXQgdnMuIHByb2Nlc3Mgc3Bhd24gcGVyIGV2YWwpXG4gKlxuICogUmVxdWlyZW1lbnRzOlxuICogLSBPYnNpZGlhbiBtdXN0IGJlIHJ1bm5pbmcgd2l0aCByZW1vdGUgZGVidWdnaW5nIGVuYWJsZWQgKHBvcnQgODMxNSlcbiAqIC0gTm9kZS5qcyAyMisgKHVzZXMgYnVpbHQtaW4gYFdlYlNvY2tldGAgYW5kIGBmZXRjaGAgZ2xvYmFscylcbiAqL1xuXG4vKiB2OCBpZ25vcmUgc3RhcnQgLS0gSW50ZWdyYXRpb24tdGltZSBjb2RlIGNvdmVyZWQgYnkgaW50ZWdyYXRpb24gdGVzdHMsIG5vdCB1bml0IHRlc3RzLiAqL1xuXG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIE9ic2lkaWFuVHJhbnNwb3J0LFxuICBUcmFuc3BvcnRFdmFsT3B0aW9uc1xufSBmcm9tICcuL3RyYW5zcG9ydC5tanMnO1xuXG5pbXBvcnQgeyBESVNNSVNTX1RSVVNUX0RJQUxPR19FWFBSIH0gZnJvbSAnLi9kaXNtaXNzLXRydXN0LWRpYWxvZy5tanMnO1xuaW1wb3J0IHsgZXhlYyB9IGZyb20gJy4vZXhlYy5tanMnO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSAnLi9sb2cubWpzJztcbmltcG9ydCB7IGVuc3VyZU5hbWVzcGFjZUJvb3RzdHJhcHBlZCB9IGZyb20gJy4vbmFtZXNwYWNlLWJvb3RzdHJhcC5tanMnO1xuaW1wb3J0IHtcbiAgZ2V0VmF1bHRJZCxcbiAgaXNWYXVsdFJlZ2lzdGVyZWQsXG4gIHJlbW92ZVZhdWx0RnJvbUNvbmZpZ1xufSBmcm9tICcuL29ic2lkaWFuLWNvbmZpZy5tanMnO1xuaW1wb3J0IHsgcmVzb2x2ZU9ic2lkaWFuRXhlY3V0YWJsZSB9IGZyb20gJy4vb2JzaWRpYW4tZXhlY3V0YWJsZS5tanMnO1xuaW1wb3J0IHsgZW5zdXJlTm9uTnVsbGFibGUgfSBmcm9tICcuL3R5cGUtZ3VhcmRzLm1qcyc7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIENEUCB0cmFuc3BvcnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVza3RvcENkcFRyYW5zcG9ydENvbmZpZyB7XG4gIC8qKlxuICAgKiBDRFAgaG9zdC4gRGVmYXVsdHMgdG8gYCdsb2NhbGhvc3QnYC5cbiAgICovXG4gIGNkcEhvc3Q/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENEUCBwb3J0LiBEZWZhdWx0cyB0byBgODMxNWAuXG4gICAqL1xuICBjZHBQb3J0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3IgaW5kaXZpZHVhbCBDRFAgY29tbWFuZHMuXG4gICAqIERlZmF1bHRzIHRvIGAzMDAwMGAuXG4gICAqL1xuICBjb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzPzogbnVtYmVyO1xufVxuXG5pbnRlcmZhY2UgQ2RwRXhjZXB0aW9uRGV0YWlscyB7XG4gIGV4Y2VwdGlvbj86IENkcEV4Y2VwdGlvbk9iamVjdDtcbiAgdGV4dDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ2RwRXhjZXB0aW9uT2JqZWN0IHtcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBSZXNwb25zZSB7XG4gIGlkOiBudW1iZXI7XG4gIHJlc3VsdD86IENkcFJlc3BvbnNlUmVzdWx0O1xufVxuXG5pbnRlcmZhY2UgQ2RwUmVzcG9uc2VSZXN1bHQge1xuICByZWFkb25seSBleGNlcHRpb25EZXRhaWxzPzogQ2RwRXhjZXB0aW9uRGV0YWlscztcbiAgcmVhZG9ubHkgcmVzdWx0PzogQ2RwVmFsdWU7XG59XG5cbmludGVyZmFjZSBDZHBUYXJnZXQge1xuICBpZDogc3RyaW5nO1xuICB0aXRsZTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG4gIHVybDogc3RyaW5nO1xuICB3ZWJTb2NrZXREZWJ1Z2dlclVybDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ2RwVmFsdWUge1xuICB0eXBlOiBzdHJpbmc7XG4gIHZhbHVlPzogdW5rbm93bjtcbn1cblxuY29uc3QgQ0RQX0RFRkFVTFRfUE9SVCA9IDgzMTU7XG5jb25zdCBDT01NQU5EX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBOT19PVVRQVVQgPSAnKG5vIG91dHB1dCknO1xuY29uc3QgVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSA1MDA7XG5jb25zdCBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBWQVVMVF9DTE9TRV9ERUxBWV9JTl9NSUxMSVNFQ09ORFMgPSAxMDAwO1xuY29uc3QgQVVUT19TVEFSVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDIwMDA7XG5jb25zdCBBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5cbi8qKlxuICogVHJhbnNwb3J0IHRoYXQgY29tbXVuaWNhdGVzIHdpdGggRGVza3RvcCBPYnNpZGlhbiB2aWEgQ2hyb21lIERldlRvb2xzIFByb3RvY29sLlxuICpcbiAqIENvbm5lY3RzIHRvIE9ic2lkaWFuJ3MgQ0RQIFdlYlNvY2tldCBlbmRwb2ludCwgc2VuZHMgYFJ1bnRpbWUuZXZhbHVhdGVgXG4gKiBjb21tYW5kcywgYW5kIHJvdXRlcyBleHByZXNzaW9ucyB0byB0aGUgY29ycmVjdCB2YXVsdCB0YXJnZXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXNrdG9wQ2RwVHJhbnNwb3J0IGltcGxlbWVudHMgT2JzaWRpYW5UcmFuc3BvcnQge1xuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhpcyB0cmFuc3BvcnQgaXMgZm9yIGEgbW9iaWxlIHBsYXRmb3JtLiBBbHdheXMgYGZhbHNlYCBmb3IgdGhpcyB0cmFuc3BvcnQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXNNb2JpbGUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBhY3RpdmVWYXVsdFBhdGg6IG51bGwgfCBzdHJpbmcgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkcFBvcnQ6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBjZHBVcmw6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgbWVzc2FnZUlkID0gMDtcbiAgcHJpdmF0ZSB3czogbnVsbCB8IFdlYlNvY2tldCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgQ0RQIHRyYW5zcG9ydC5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyAtIENEUCBjb25uZWN0aW9uIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IoY29uZmlnPzogRGVza3RvcENkcFRyYW5zcG9ydENvbmZpZykge1xuICAgIGNvbnN0IGhvc3QgPSBjb25maWc/LmNkcEhvc3QgPz8gJ2xvY2FsaG9zdCc7XG4gICAgdGhpcy5jZHBQb3J0ID0gY29uZmlnPy5jZHBQb3J0ID8/IENEUF9ERUZBVUxUX1BPUlQ7XG4gICAgdGhpcy5jZHBVcmwgPSBgaHR0cDovLyR7aG9zdH06JHtTdHJpbmcodGhpcy5jZHBQb3J0KX1gO1xuICAgIHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA9IGNvbmZpZz8uY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA/PyBDT01NQU5EX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3Bvc2VzIG9mIHRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgICBhd2FpdCBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZXMgYSBKYXZhU2NyaXB0IGV4cHJlc3Npb24gaW5zaWRlIE9ic2lkaWFuIHZpYSBDRFAgYFJ1bnRpbWUuZXZhbHVhdGVgLlxuICAgKlxuICAgKiBSb3V0ZXMgdG8gdGhlIGNvcnJlY3QgdmF1bHQgdGFyZ2V0IGJhc2VkIG9uIGBvcHRpb25zLmN3ZGAuXG4gICAqXG4gICAqIEBwYXJhbSBleHByZXNzaW9uIC0gVGhlIEphdmFTY3JpcHQgZXhwcmVzc2lvbiB0byBldmFsdWF0ZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBFdmFsdWF0aW9uIG9wdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoZSBub3JtYWxpemVkIHJlc3VsdCBzdHJpbmcuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZXZhbHVhdGUoZXhwcmVzc2lvbjogc3RyaW5nLCBvcHRpb25zOiBUcmFuc3BvcnRFdmFsT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmVuc3VyZUNvbm5lY3Rpb24ob3B0aW9ucy5jd2QpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICBhd2FpdFByb21pc2U6IHRydWUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgIH0pO1xuXG4gICAgaWYgKHJlc3BvbnNlLnJlc3VsdD8uZXhjZXB0aW9uRGV0YWlscykge1xuICAgICAgY29uc3QgZGVzYyA9IHJlc3BvbnNlLnJlc3VsdC5leGNlcHRpb25EZXRhaWxzLmV4Y2VwdGlvbj8uZGVzY3JpcHRpb25cbiAgICAgICAgPz8gcmVzcG9uc2UucmVzdWx0LmV4Y2VwdGlvbkRldGFpbHMudGV4dDtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ0RQIGV2YWx1YXRpb24gZXJyb3I6ICR7ZGVzY31gKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHRPYmogPSByZXNwb25zZS5yZXN1bHQ/LnJlc3VsdDtcbiAgICBpZiAoIXJlc3VsdE9iaiB8fCByZXN1bHRPYmoudHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBOT19PVVRQVVQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIFN0cmluZyhyZXN1bHRPYmoudmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIHRoYXQgdGhlIENEUCBlbmRwb2ludCBpcyByZWFjaGFibGUgYW5kIGhhcyBPYnNpZGlhbiB0YXJnZXRzLlxuICAgKlxuICAgKiBJZiBPYnNpZGlhbiBpcyBub3QgcnVubmluZywgYXR0ZW1wdHMgdG8gYXV0by1zdGFydCBpdCB2aWEgVVJJIHByb3RvY29sXG4gICAqIGFuZCBwb2xscyB1bnRpbCBDRFAgYmVjb21lcyBhdmFpbGFibGUuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCAodXNlZCBmb3IgdmF1bHQgcmVnaXN0cmF0aW9uIGNoZWNrKS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBwcmVmbGlnaHRDaGVjayh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFJ1bm5pbmcgcHJlZmxpZ2h0IGNoZWNrIGZvciB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgaWYgKCFpc1ZhdWx0UmVnaXN0ZXJlZCh2YXVsdFBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBWYXVsdCBpcyBub3QgcmVnaXN0ZXJlZCBpbiBPYnNpZGlhbjogJHt2YXVsdFBhdGh9LiBSZWdpc3RlciB0aGUgdmF1bHQgZmlyc3Qgd2l0aCByZWdpc3RlclZhdWx0KCkgb3IgVGVtcFZhdWx0LnJlZ2lzdGVyKCkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHBhZ2UgdGFyZ2V0cycpO1xuICAgICAgfVxuICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gQ0RQIHJlYWNoYWJsZSwgJHtTdHJpbmcodGFyZ2V0cy5sZW5ndGgpfSB0YXJnZXQocykgZm91bmQuYCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZU9ic2lkaWFuUnVubmluZygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSB2YXVsdCB2aWEgRWxlY3Ryb24gSVBDIGV2YWx1YXRlZCB0aHJvdWdoIENEUC5cbiAgICpcbiAgICogVXNlcyBhbiBleGlzdGluZyBPYnNpZGlhbiB0YXJnZXQgdG8gc2VuZCB0aGUgYHZhdWx0LW9wZW5gIElQQyBjb21tYW5kLFxuICAgKiB0aGVuIHBvbGxzIHVudGlsIHRoZSBuZXcgdmF1bHQncyB0YXJnZXQgYXBwZWFycy5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFJlZ2lzdGVyaW5nIHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcbiAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgdGhpcy5nZXRQYWdlVGFyZ2V0cygpO1xuICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBPYnNpZGlhbiBDRFAgdGFyZ2V0cyBhdmFpbGFibGUuIElzIE9ic2lkaWFuIHJ1bm5pbmc/Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgaXBjV3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldChlbnN1cmVOb25OdWxsYWJsZSh0YXJnZXRzWzBdKSk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGVuc3VyZU5hbWVzcGFjZUJvb3RzdHJhcHBlZCh0aGlzLCB2YXVsdFBhdGgpO1xuICAgICAgY29uc3QgaXBjRXhwciA9IGB3aW5kb3cuX19vYnNpZGlhbkludGVncmF0aW9uVGVzdGluZy5pcGNTZW5kU3luYygke0pTT04uc3RyaW5naWZ5KHsgYXJnczogW3ZhdWx0UGF0aCwgZmFsc2VdLCBjaGFubmVsOiAndmF1bHQtb3BlbicgfSl9KWA7XG4gICAgICBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKGlwY1dzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgICBleHByZXNzaW9uOiBpcGNFeHByLFxuICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdGhpcy5lbmFibGVQbHVnaW5zSW5Mb2NhbFN0b3JhZ2UoaXBjV3MsIHZhdWx0UGF0aCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlwY1dzLmNsb3NlKCk7XG4gICAgfVxuXG4gICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gUG9sbGluZyBmb3IgdmF1bHQgdGFyZ2V0ICh0aW1lb3V0PSR7U3RyaW5nKFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zKS4uLmApO1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5maW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoKTtcbiAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gVmF1bHQgdGFyZ2V0IGZvdW5kLicpO1xuICAgICAgICBhd2FpdCB0aGlzLndhaXRGb3JMYXlvdXRSZWFkeSh2YXVsdFBhdGgpO1xuICAgICAgICBhd2FpdCB0aGlzLmRpc21pc3NUcnVzdERpYWxvZyh2YXVsdFBhdGgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gVmF1bHQgdGFyZ2V0IG5vdCByZWFkeSB5ZXQuXG4gICAgICB9XG4gICAgICBhd2FpdCBkZWxheShWQVVMVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVmF1bHQgYXQgJHt2YXVsdFBhdGh9IGRpZCBub3QgYmVjb21lIHJlYWR5IHdpdGhpbiAke1N0cmluZyhWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tc2ApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucmVnaXN0ZXJzIGEgdmF1bHQgYnkgZGVzdHJveWluZyBpdHMgd2luZG93IGFuZCByZW1vdmluZyBpdCBmcm9tIHRoZSByZWdpc3RyeS5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdW5yZWdpc3RlclZhdWx0KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGVuc3VyZU5hbWVzcGFjZUJvb3RzdHJhcHBlZCh0aGlzLCB2YXVsdFBhdGgpO1xuICAgICAgY29uc3QgdGFyZ2V0ID0gYXdhaXQgdGhpcy5maW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoKTtcbiAgICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQodGFyZ2V0KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGRlc3Ryb3lFeHByID0gJ3dpbmRvdy5fX29ic2lkaWFuSW50ZWdyYXRpb25UZXN0aW5nLmRlc3Ryb3lDdXJyZW50V2luZG93KCknO1xuICAgICAgICBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgICAgICBhd2FpdFByb21pc2U6IHRydWUsXG4gICAgICAgICAgZXhwcmVzc2lvbjogZGVzdHJveUV4cHIsXG4gICAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBXaW5kb3cgbWF5IGFscmVhZHkgYmUgY2xvc2VkLlxuICAgIH1cblxuICAgIGlmICh0aGlzLmFjdGl2ZVZhdWx0UGF0aCA9PT0gdmF1bHRQYXRoKSB7XG4gICAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgICB9XG5cbiAgICBhd2FpdCBkZWxheShWQVVMVF9DTE9TRV9ERUxBWV9JTl9NSUxMSVNFQ09ORFMpO1xuXG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KGVuc3VyZU5vbk51bGxhYmxlKHRhcmdldHNbMF0pKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGVuc3VyZU5hbWVzcGFjZUJvb3RzdHJhcHBlZCh0aGlzLCB2YXVsdFBhdGgpO1xuICAgICAgICBjb25zdCByZW1vdmVFeHByID0gYHdpbmRvdy5fX29ic2lkaWFuSW50ZWdyYXRpb25UZXN0aW5nLmlwY1NlbmRTeW5jKCR7SlNPTi5zdHJpbmdpZnkoeyBhcmdzOiBbdmF1bHRQYXRoXSwgY2hhbm5lbDogJ3ZhdWx0LXJlbW92ZScgfSl9KWA7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgICAgICBleHByZXNzaW9uOiByZW1vdmVFeHByLFxuICAgICAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBObyBDRFAgdGFyZ2V0cyBmb3IgcmVtb3ZhbCBJUEMgXHUyMDE0IHJlbW92aW5nIGRpcmVjdGx5IGZyb20gb2JzaWRpYW4uanNvbi4nKTtcbiAgICAgIHJlbW92ZVZhdWx0RnJvbUNvbmZpZyh2YXVsdFBhdGgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25uZWN0cyB0byBhIENEUCB0YXJnZXQncyBXZWJTb2NrZXQgZW5kcG9pbnQuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgQ0RQIHRhcmdldCB0byBjb25uZWN0IHRvLlxuICAgKiBAcmV0dXJucyBUaGUgb3BlbiBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY29ubmVjdFRvVGFyZ2V0KHRhcmdldDogQ2RwVGFyZ2V0KTogUHJvbWlzZTxXZWJTb2NrZXQ+IHtcbiAgICBjb25zdCB3cyA9IG5ldyBXZWJTb2NrZXQodGFyZ2V0LndlYlNvY2tldERlYnVnZ2VyVXJsKTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB3cy5vbm9wZW4gPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH07XG4gICAgICB3cy5vbmVycm9yID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gY29ubmVjdCB0byBDRFAgdGFyZ2V0OiAke3RhcmdldC53ZWJTb2NrZXREZWJ1Z2dlclVybH1gKSk7XG4gICAgICB9O1xuICAgIH0pO1xuICAgIHJldHVybiB3cztcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNjb25uZWN0cyB0aGUgYWN0aXZlIFdlYlNvY2tldCBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBkaXNjb25uZWN0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLndzPy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuICAgICAgdGhpcy53cy5jbG9zZSgpO1xuICAgIH1cbiAgICB0aGlzLndzID0gbnVsbDtcbiAgICB0aGlzLmFjdGl2ZVZhdWx0UGF0aCA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogRGlzbWlzc2VzIHRoZSBcIkRvIHlvdSB0cnVzdCB0aGUgYXV0aG9yIG9mIHRoaXMgdmF1bHQ/XCIgZGlhbG9nIGlmIHByZXNlbnQuXG4gICAqXG4gICAqIEFjdHMgYXMgYSBzYWZldHkgbmV0IHdoZW4gYGVuYWJsZS1wbHVnaW4tPGlkPmAgaXMgd3JpdHRlbiBpbiBvbmUgcmVuZGVyZXJcbiAgICogYnV0IG5vdCB5ZXQgdmlzaWJsZSB0byB0aGUgbmV3bHktb3BlbmVkIHZhdWx0J3MgcmVuZGVyZXIgKHJhY2Ugb2JzZXJ2ZWRcbiAgICogaW4gT2JzaWRpYW4gMS4xMy4wKS5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSB2YXVsdCBwYXRoIHRvIGV2YWx1YXRlIGluLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBkaXNtaXNzVHJ1c3REaWFsb2codmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV2YWx1YXRlKERJU01JU1NfVFJVU1RfRElBTE9HX0VYUFIsIHsgY3dkOiB2YXVsdFBhdGggfSk7XG4gICAgaWYgKHJlc3VsdCA9PT0gJ3RydWUnKSB7XG4gICAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBEaXNtaXNzZWQgXCJEbyB5b3UgdHJ1c3QgdGhlIGF1dGhvclwiIGRpYWxvZy4nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBgZW5hYmxlLXBsdWdpbi08dmF1bHRJZD5gIGluIE9ic2lkaWFuJ3MgbG9jYWxTdG9yYWdlIHRvIHByZXZlbnRcbiAgICogdGhlIFwiRG8geW91IHRydXN0IHRoZSBhdXRob3Igb2YgdGhpcyB2YXVsdD9cIiBkaWFsb2cgZnJvbSBhcHBlYXJpbmdcbiAgICogd2hlbiBhIHZhdWx0IHdpdGggY29tbXVuaXR5IHBsdWdpbnMgaXMgb3BlbmVkIGZvciB0aGUgZmlyc3QgdGltZS5cbiAgICpcbiAgICogTXVzdCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIGB2YXVsdC1vcGVuYCBJUEMgKHNvIHRoZSB2YXVsdCBJRCBleGlzdHMgaW5cbiAgICogYG9ic2lkaWFuLmpzb25gKSBhbmQgYmVmb3JlIHRoZSBuZXcgdmF1bHQgd2luZG93IGZpbmlzaGVzIGxvYWRpbmcuXG4gICAqXG4gICAqIEBwYXJhbSB3cyAtIEFuIG9wZW4gV2ViU29ja2V0IHRvIGFuIGV4aXN0aW5nIE9ic2lkaWFuIHRhcmdldC5cbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuYWJsZVBsdWdpbnNJbkxvY2FsU3RvcmFnZSh3czogV2ViU29ja2V0LCB2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHZhdWx0SWQgPSBnZXRWYXVsdElkKHZhdWx0UGF0aCk7XG4gICAgaWYgKCF2YXVsdElkKSB7XG4gICAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBDb3VsZCBub3QgZmluZCB2YXVsdCBJRCBcdTIwMTQgc2tpcHBpbmcgbG9jYWxTdG9yYWdlIHRydXN0IGZsYWcuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICBleHByZXNzaW9uOiBgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJHtKU09OLnN0cmluZ2lmeShgZW5hYmxlLXBsdWdpbi0ke3ZhdWx0SWR9YCl9LCAndHJ1ZScpO2AsXG4gICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgfSk7XG4gICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gU2V0IGVuYWJsZS1wbHVnaW4tJHt2YXVsdElkfSBpbiBsb2NhbFN0b3JhZ2UuYCk7XG4gIH1cblxuICAvKipcbiAgICogRW5zdXJlcyB0aGVyZSBpcyBhbiBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24gdG8gdGhlIGNvcnJlY3QgdmF1bHQgdGFyZ2V0LlxuICAgKlxuICAgKiBSZXVzZXMgdGhlIGV4aXN0aW5nIGNvbm5lY3Rpb24gaWYgaXQgdGFyZ2V0cyB0aGUgcmVxdWVzdGVkIHZhdWx0LlxuICAgKiBPdGhlcndpc2UsIGZpbmRzIHRoZSBjb3JyZWN0IHRhcmdldCBhbmQgcmVjb25uZWN0cy5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSB2YXVsdCBwYXRoIHRvIHRhcmdldC5cbiAgICogQHJldHVybnMgVGhlIGFjdGl2ZSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlQ29ubmVjdGlvbih2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8V2ViU29ja2V0PiB7XG4gICAgaWYgKHRoaXMud3M/LnJlYWR5U3RhdGUgPT09IFdlYlNvY2tldC5PUEVOICYmIHRoaXMuYWN0aXZlVmF1bHRQYXRoID09PSB2YXVsdFBhdGgpIHtcbiAgICAgIHJldHVybiB0aGlzLndzO1xuICAgIH1cblxuICAgIHRoaXMuZGlzY29ubmVjdCgpO1xuXG4gICAgY29uc3QgdGFyZ2V0ID0gYXdhaXQgdGhpcy5maW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoKTtcbiAgICB0aGlzLndzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQodGFyZ2V0KTtcbiAgICB0aGlzLmFjdGl2ZVZhdWx0UGF0aCA9IHZhdWx0UGF0aDtcbiAgICByZXR1cm4gdGhpcy53cztcbiAgfVxuXG4gIC8qKlxuICAgKiBMYXVuY2hlcyBPYnNpZGlhbiB3aXRoIGAtLXJlbW90ZS1kZWJ1Z2dpbmctcG9ydGAgYW5kIHBvbGxzIHVudGlsIENEUCBiZWNvbWVzIGF2YWlsYWJsZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlT2JzaWRpYW5SdW5uaW5nKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIE9ic2lkaWFuIENEUCBub3QgcmVhY2hhYmxlLiBTdGFydGluZyBPYnNpZGlhbiB3aXRoIHJlbW90ZSBkZWJ1Z2dpbmcuLi4nKTtcblxuICAgIGNvbnN0IGxhdW5jaENvbW1hbmQgPSBhd2FpdCBnZXRPYnNpZGlhbkxhdW5jaENvbW1hbmQodGhpcy5jZHBQb3J0KTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZXhlYyhsYXVuY2hDb21tYW5kLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBUaGUgbGF1bmNoIGNvbW1hbmQgbWF5IGZhaWwgb24gc29tZSBzeXN0ZW1zIFx1MjAxNCB3ZSdsbCBzdGlsbCB0cnkgcG9sbGluZy5cbiAgICB9XG5cbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBQb2xsaW5nIGZvciBDRFAgZW5kcG9pbnQgYXQgJHt0aGlzLmNkcFVybH0gKHRpbWVvdXQ9JHtTdHJpbmcoQVVUT19TVEFSVF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXMpLi4uYCk7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgQVVUT19TVEFSVF9USU1FT1VUX0lOX01JTExJU0VDT05EUztcbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICBhd2FpdCBkZWxheShBVVRPX1NUQVJUX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG4gICAgICAgIGlmICh0YXJnZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBPYnNpZGlhbiBDRFAgcmVhZHksICR7U3RyaW5nKHRhcmdldHMubGVuZ3RoKX0gdGFyZ2V0KHMpIGZvdW5kLmApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIENEUCBub3QgcmVhZHkgeWV0LCByZXRyeWluZy4uLicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgT2JzaWRpYW4gZGlkIG5vdCBzdGFydCB3aXRoaW4gJHtTdHJpbmcoQVVUT19TVEFSVF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXMuIEVuc3VyZSBPYnNpZGlhbiBpcyBpbnN0YWxsZWQgYW5kIGFjY2Vzc2libGUuYCk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgdGhlIENEUCB0YXJnZXQgdGhhdCBoYXMgdGhlIGdpdmVuIHZhdWx0IG9wZW4uXG4gICAqXG4gICAqIEZvciBhIHNpbmdsZSB0YXJnZXQsIHJldHVybnMgaXQgZGlyZWN0bHkuIEZvciBtdWx0aXBsZSB0YXJnZXRzLFxuICAgKiBwcm9iZXMgZWFjaCBieSBldmFsdWF0aW5nIGBnZXRCYXNlUGF0aCgpYCB0byBmaW5kIHRoZSBtYXRjaC5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSB2YXVsdCBwYXRoIHRvIG1hdGNoLlxuICAgKiBAcmV0dXJucyBUaGUgbWF0Y2hpbmcgQ0RQIHRhcmdldC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTxDZHBUYXJnZXQ+IHtcbiAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgdGhpcy5nZXRQYWdlVGFyZ2V0cygpO1xuXG4gICAgaWYgKHRhcmdldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE9ic2lkaWFuIENEUCB0YXJnZXRzIGZvdW5kJyk7XG4gICAgfVxuXG4gICAgaWYgKHRhcmdldHMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCB0YXJnZXQgb2YgdGFyZ2V0cykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYmFzZVBhdGggPSBhd2FpdCB0aGlzLnByb2JlVmF1bHRQYXRoKHRhcmdldCk7XG4gICAgICAgIGlmIChiYXNlUGF0aCA9PT0gdmF1bHRQYXRoKSB7XG4gICAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIE5vdCBhIHZhdWx0IHRhcmdldCBvciBub3QgcmVhZHkuXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBObyBDRFAgdGFyZ2V0IGZvdW5kIGZvciB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlcyB0aGUgbGlzdCBvZiBwYWdlLXR5cGUgdGFyZ2V0cyBmcm9tIHRoZSBDRFAgYC9qc29uYCBlbmRwb2ludC5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGxpc3Qgb2YgcGFnZSB0YXJnZXRzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRQYWdlVGFyZ2V0cygpOiBQcm9taXNlPENkcFRhcmdldFtdPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHt0aGlzLmNkcFVybH0vanNvbmApO1xuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCByZXNwb25zZS5qc29uKCkgYXMgQ2RwVGFyZ2V0W107XG4gICAgcmV0dXJuIHRhcmdldHMuZmlsdGVyKCh0KSA9PiB0LnR5cGUgPT09ICdwYWdlJyk7XG4gIH1cblxuICAvKipcbiAgICogUHJvYmVzIGEgdGFyZ2V0IHRvIGRpc2NvdmVyIHdoaWNoIHZhdWx0IHBhdGggaXQgaGFzIG9wZW4uXG4gICAqXG4gICAqIENyZWF0ZXMgYSB0ZW1wb3JhcnkgV2ViU29ja2V0IGNvbm5lY3Rpb24sIGV2YWx1YXRlcyBgZ2V0QmFzZVBhdGgoKWAsXG4gICAqIGFuZCByZXR1cm5zIHRoZSByZXN1bHQuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgQ0RQIHRhcmdldCB0byBwcm9iZS5cbiAgICogQHJldHVybnMgVGhlIHZhdWx0J3MgYmFzZSBwYXRoLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9iZVZhdWx0UGF0aCh0YXJnZXQ6IENkcFRhcmdldCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgICBleHByZXNzaW9uOiAnYXBwLnZhdWx0LmFkYXB0ZXIuZ2V0QmFzZVBhdGgoKScsXG4gICAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIFN0cmluZyhyZXNwb25zZS5yZXN1bHQ/LnJlc3VsdD8udmFsdWUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB3cy5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBhIENEUCBjb21tYW5kIG92ZXIgV2ViU29ja2V0IGFuZCB3YWl0cyBmb3IgdGhlIHJlc3BvbnNlLlxuICAgKlxuICAgKiBAcGFyYW0gd3MgLSBUaGUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSBtZXRob2QgLSBUaGUgQ0RQIG1ldGhvZCBuYW1lLlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIENEUCBtZXRob2QgcGFyYW1ldGVycy5cbiAgICogQHJldHVybnMgVGhlIENEUCByZXNwb25zZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2VuZENvbW1hbmQod3M6IFdlYlNvY2tldCwgbWV0aG9kOiBzdHJpbmcsIHBhcmFtczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQcm9taXNlPENkcFJlc3BvbnNlPiB7XG4gICAgY29uc3QgaWQgPSArK3RoaXMubWVzc2FnZUlkO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPENkcFJlc3BvbnNlPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHdzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBoYW5kbGVyKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQ0RQIGNvbW1hbmQgdGltZWQgb3V0IGFmdGVyICR7U3RyaW5nKHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyl9bXM6ICR7bWV0aG9kfWApKTtcbiAgICAgIH0sIHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyk7XG5cbiAgICAgIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IE1lc3NhZ2VFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCBtc2cgPSBKU09OLnBhcnNlKFN0cmluZyhldmVudC5kYXRhKSkgYXMgQ2RwUmVzcG9uc2U7XG4gICAgICAgIGlmIChtc2cuaWQgPT09IGlkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgIHdzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBoYW5kbGVyKTtcbiAgICAgICAgICByZXNvbHZlKG1zZyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGhhbmRsZXIpO1xuICAgICAgd3Muc2VuZChKU09OLnN0cmluZ2lmeSh7IGlkLCBtZXRob2QsIHBhcmFtcyB9KSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogV2FpdHMgZm9yIHRoZSB2YXVsdCdzIGBhcHAud29ya3NwYWNlYCB0byByZWFjaCBsYXlvdXQtcmVhZHkgc3RhdGUuXG4gICAqXG4gICAqIGBmaW5kVGFyZ2V0Rm9yVmF1bHRgIHJldHVybnMgYXMgc29vbiBhcyBgYXBwLnZhdWx0LmFkYXB0ZXIuZ2V0QmFzZVBhdGgoKWBcbiAgICogbWF0Y2hlcyBcdTIwMTQgd2hpY2ggaXMgdHJ1ZSBzaG9ydGx5IGFmdGVyIHRoZSBgQXBwYCBjb25zdHJ1Y3RvciBydW5zLCBiZWZvcmVcbiAgICogYHBsdWdpbnMuaW5pdGlhbGl6ZSgpYCAoYW5kIGFueSB0cnVzdCBkaWFsb2cpIGhhcyBleGVjdXRlZC4gQm9vdHN0cmFwcGluZ1xuICAgKiB0aGUgbmFtZXNwYWNlIGFuZCBjYWxsaW5nIGBwb2xsVmF1bHRCYXNlUGF0aCgpYCBhd2FpdHMgYGxheW91dFJlYWR5YCwgc29cbiAgICogYnkgdGhlIHRpbWUgdGhpcyByZXR1cm5zIHRoZSBkaWFsb2cgaGFzIGVpdGhlciByZW5kZXJlZCBvciBpcyBub3QgZ29pbmdcbiAgICogdG8gcmVuZGVyLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gZXZhbHVhdGUgaW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdhaXRGb3JMYXlvdXRSZWFkeSh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGVuc3VyZU5hbWVzcGFjZUJvb3RzdHJhcHBlZCh0aGlzLCB2YXVsdFBhdGgpO1xuICAgIGF3YWl0IHRoaXMuZXZhbHVhdGUoJ3dpbmRvdy5fX29ic2lkaWFuSW50ZWdyYXRpb25UZXN0aW5nLnBvbGxWYXVsdEJhc2VQYXRoKCknLCB7IGN3ZDogdmF1bHRQYXRoIH0pO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciB0aGUgZ2l2ZW4gZGVsYXkuXG4gKlxuICogQHBhcmFtIG1zIC0gVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBkZWxheS5cbiAqL1xuZnVuY3Rpb24gZGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKTtcbiAgfSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGxhdGZvcm0tc3BlY2lmaWMgY29tbWFuZCB0byBsYXVuY2ggT2JzaWRpYW4gd2l0aCByZW1vdGUgZGVidWdnaW5nIGVuYWJsZWQuXG4gKlxuICogUmVzb2x2ZXMgdGhlIGFjdHVhbCBpbnN0YWxsZWQgT2JzaWRpYW4gZXhlY3V0YWJsZSAoY292ZXJpbmcgaW5zdGFsbGVyLWJhc2VkXG4gKiBhbmQgYFBBVEhgLWJhc2VkIGluc3RhbGxzIHN1Y2ggYXMgYHNjb29wYCkgYW5kIHZlcmlmaWVzIGl0IGV4aXN0cyBiZWZvcmVcbiAqIHJldHVybmluZyBhIGNvbW1hbmQuIFRocm93cyBpZiBPYnNpZGlhbiBpcyBub3QgaW5zdGFsbGVkLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIENEUCBwb3J0IHRvIHVzZS5cbiAqIEByZXR1cm5zIFRoZSBzaGVsbCBjb21tYW5kIHN0cmluZy5cbiAqIEB0aHJvd3MgRXJyb3IgaWYgT2JzaWRpYW4gY2Fubm90IGJlIGxvY2F0ZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldE9ic2lkaWFuTGF1bmNoQ29tbWFuZChwb3J0OiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBleGVQYXRoID0gYXdhaXQgcmVzb2x2ZU9ic2lkaWFuRXhlY3V0YWJsZSgpO1xuICBjb25zdCBmbGFnID0gYC0tcmVtb3RlLWRlYnVnZ2luZy1wb3J0PSR7U3RyaW5nKHBvcnQpfWA7XG5cbiAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicpIHtcbiAgICByZXR1cm4gYHN0YXJ0IFwiXCIgXCIke2V4ZVBhdGh9XCIgJHtmbGFnfWA7XG4gIH1cblxuICByZXR1cm4gYFwiJHtleGVQYXRofVwiICR7ZmxhZ30gJmA7XG59XG5cbi8qIHY4IGlnbm9yZSBzdG9wICovXG4iXSwKICAibWFwcGluZ3MiOiAiQUFzQkEsT0FBTyxhQUFhO0FBT3BCLFNBQVMsaUNBQWlDO0FBQzFDLFNBQVMsWUFBWTtBQUNyQixTQUFTLFdBQVc7QUFDcEIsU0FBUyxtQ0FBbUM7QUFDNUM7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxpQ0FBaUM7QUFDMUMsU0FBUyx5QkFBeUI7QUF1RGxDLE1BQU0sbUJBQW1CO0FBQ3pCLE1BQU0sa0NBQWtDO0FBQ3hDLE1BQU0sWUFBWTtBQUNsQixNQUFNLHNDQUFzQztBQUM1QyxNQUFNLHFDQUFxQztBQUMzQyxNQUFNLG9DQUFvQztBQUMxQyxNQUFNLDJDQUEyQztBQUNqRCxNQUFNLHFDQUFxQztBQVFwQyxNQUFNLG9CQUFpRDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVB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
536
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1kZXNrdG9wLWNkcC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIERlc2t0b3AgQ0RQIHRyYW5zcG9ydCBcdTIwMTQgZXZhbHVhdGVzIGV4cHJlc3Npb25zIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2xcbiAqIG92ZXIgV2ViU29ja2V0IGFuZCBtYW5hZ2VzIHZhdWx0cyB2aWEgRWxlY3Ryb24gSVBDLlxuICpcbiAqIFR3byBtb2RlczpcbiAqIC0gKipPd25lZCAoZGVmYXVsdCkqKjogdGhlIHRyYW5zcG9ydCBsYXVuY2hlcyBhbmQgb3ducyBhbiBpc29sYXRlZCBPYnNpZGlhblxuICogICBpbnN0YW5jZSBhZ2FpbnN0IGEgdGVtcG9yYXJ5IGAtLXVzZXItZGF0YS1kaXJgIG9uIGEgZnJlZSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgLFxuICogICBuZXZlciB0b3VjaGluZyB0aGUgdXNlcidzIE9ic2lkaWFuLiBTdXBwb3J0cyB2ZXJzaW9uIHBpbm5pbmcgdmlhIHRoZSB1c2VyLWRhdGEgYXNhci5cbiAqIC0gKipBdHRhY2gqKjogd2hlbiBhbiBleHBsaWNpdCBDRFAgcG9ydCBpcyBjb25maWd1cmVkLCB0aGUgdHJhbnNwb3J0IGNvbm5lY3RzXG4gKiAgIHRvIGFuIGFscmVhZHktcnVubmluZyBPYnNpZGlhbiBvbiB0aGF0IHBvcnQuXG4gKlxuICogSXQgY29ubmVjdHMgdG8gcGFnZSB0YXJnZXRzLCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWAgY29tbWFuZHMsIGFuZCByb3V0ZXMgdG9cbiAqIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldCB1c2luZyBgZ2V0QmFzZVBhdGgoKWAgcHJvYmluZy5cbiAqXG4gKiBSZXF1aXJlbWVudHM6IE5vZGUuanMgMjIrICh1c2VzIGJ1aWx0LWluIGBXZWJTb2NrZXRgIGFuZCBgZmV0Y2hgIGdsb2JhbHMpLlxuICovXG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBJbnRlZ3JhdGlvbi10aW1lIGNvZGUgY292ZXJlZCBieSBpbnRlZ3JhdGlvbiB0ZXN0cywgbm90IHVuaXQgdGVzdHMuICovXG5cbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHtcbiAgbWtkaXJTeW5jLFxuICBybVN5bmMsXG4gIHdyaXRlRmlsZVN5bmNcbn0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5cbmltcG9ydCB0eXBlIHsgT3duZWRPYnNpZGlhbkluc3RhbmNlIH0gZnJvbSAnLi9vYnNpZGlhbi1pbnN0YW5jZS5tanMnO1xuaW1wb3J0IHR5cGUge1xuICBPYnNpZGlhblRyYW5zcG9ydCxcbiAgVHJhbnNwb3J0RXZhbE9wdGlvbnNcbn0gZnJvbSAnLi90cmFuc3BvcnQubWpzJztcblxuaW1wb3J0IHsgRElTTUlTU19UUlVTVF9ESUFMT0dfRVhQUiB9IGZyb20gJy4vZGlzbWlzcy10cnVzdC1kaWFsb2cubWpzJztcbmltcG9ydCB7IGV4ZWMgfSBmcm9tICcuL2V4ZWMubWpzJztcbmltcG9ydCB7IGxvZyB9IGZyb20gJy4vbG9nLm1qcyc7XG5pbXBvcnQgeyBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQgfSBmcm9tICcuL25hbWVzcGFjZS1ib290c3RyYXAubWpzJztcbmltcG9ydCB7XG4gIGdldFZhdWx0SWQsXG4gIGlzVmF1bHRSZWdpc3RlcmVkLFxuICByZW1vdmVWYXVsdEZyb21Db25maWdcbn0gZnJvbSAnLi9vYnNpZGlhbi1jb25maWcubWpzJztcbmltcG9ydCB7IHJlc29sdmVPYnNpZGlhbkV4ZWN1dGFibGUgfSBmcm9tICcuL29ic2lkaWFuLWV4ZWN1dGFibGUubWpzJztcbmltcG9ydCB7IGxhdW5jaE93bmVkT2JzaWRpYW5JbnN0YW5jZSB9IGZyb20gJy4vb2JzaWRpYW4taW5zdGFuY2UubWpzJztcbmltcG9ydCB7IGNvcHlBc2FySW50b1VzZXJEYXRhIH0gZnJvbSAnLi9vYnNpZGlhbi12ZXJzaW9uLXN3aXRjaC5tanMnO1xuaW1wb3J0IHsgZW5zdXJlTm9uTnVsbGFibGUgfSBmcm9tICcuL3R5cGUtZ3VhcmRzLm1qcyc7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIENEUCB0cmFuc3BvcnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVza3RvcENkcFRyYW5zcG9ydENvbmZpZyB7XG4gIC8qKlxuICAgKiBDRFAgaG9zdC4gRGVmYXVsdHMgdG8gYCdsb2NhbGhvc3QnYC5cbiAgICovXG4gIGNkcEhvc3Q/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENEUCBwb3J0IGZvciAqKmF0dGFjaCoqIG1vZGUgKHRoZSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgIHRoZSBydW5uaW5nXG4gICAqIE9ic2lkaWFuIHdhcyBsYXVuY2hlZCB3aXRoKS4gSW4gb3duZWQtaW5zdGFuY2UgbW9kZSB0aGlzIGlzIGlnbm9yZWQgXHUyMDE0IGFcbiAgICogZnJlZSBwb3J0IGlzIGNob3NlbiBhdCBsYXVuY2guXG4gICAqL1xuICBjZHBQb3J0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3IgaW5kaXZpZHVhbCBDRFAgY29tbWFuZHMuXG4gICAqIERlZmF1bHRzIHRvIGAzMDAwMGAuXG4gICAqL1xuICBjb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBXaGVuIHNldCwgdGhlIHRyYW5zcG9ydCBsYXVuY2hlcyBhbmQgb3ducyBhbiBpc29sYXRlZCBPYnNpZGlhbiBpbnN0YW5jZVxuICAgKiBpbnN0ZWFkIG9mIGF0dGFjaGluZyB0byBhIHJ1bm5pbmcgb25lLiBUaGlzIGlzIHRoZSBkZWZhdWx0IGRlc2t0b3AgbW9kZS5cbiAgICovXG4gIG93bmVkSW5zdGFuY2U/OiBPd25lZEluc3RhbmNlQ29uZmlnO1xufVxuXG4vKipcbiAqIEFuIGFzYXIgdG8gcHJvdmlzaW9uIGludG8gYSBoYXJuZXNzLW93bmVkIGluc3RhbmNlJ3MgdXNlci1kYXRhIGRpciBiZWZvcmUgbGF1bmNoLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE93bmVkSW5zdGFuY2VBc2FyIHtcbiAgLyoqIEFic29sdXRlIHBhdGggdG8gdGhlIGNhY2hlZC9zb3VyY2UgYXNhciBmaWxlLiAqL1xuICByZWFkb25seSBwYXRoOiBzdHJpbmc7XG5cbiAgLyoqIFRoZSBhc2FyJ3MgYHgueS56YCB2ZXJzaW9uLiAqL1xuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgYSBoYXJuZXNzLW93bmVkLCBpc29sYXRlZCBPYnNpZGlhbiBpbnN0YW5jZS5cbiAqXG4gKiBXaGVuIHByZXNlbnQsIHRoZSB0cmFuc3BvcnQgbGF1bmNoZXMgYW5kIG93bnMgaXRzIG93biBPYnNpZGlhbiBwcm9jZXNzXG4gKiBhZ2FpbnN0IGFuIGlzb2xhdGVkIHVzZXItZGF0YSBkaXIgaW5zdGVhZCBvZiBhdHRhY2hpbmcgdG8gYSBydW5uaW5nIGluc3RhbmNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE93bmVkSW5zdGFuY2VDb25maWcge1xuICAvKiogT3B0aW9uYWwgYXNhciB0byBwcm92aXNpb24gaW50byB7QGxpbmsgdXNlckRhdGFEaXJ9IGJlZm9yZSBsYXVuY2guICovXG4gIHJlYWRvbmx5IGFzYXI/OiBPd25lZEluc3RhbmNlQXNhciB8IHVuZGVmaW5lZDtcblxuICAvKiogQWJzb2x1dGUgcGF0aCB0byB0aGUgT2JzaWRpYW4gc2hlbGwgZXhlY3V0YWJsZSB0byBsYXVuY2guICovXG4gIHJlYWRvbmx5IGV4ZVBhdGg6IHN0cmluZztcblxuICAvKipcbiAgICogQWJzb2x1dGUgcGF0aCB0byB0aGUgaXNvbGF0ZWQgdXNlci1kYXRhIGRpci4gQ3JlYXRlZCBhbmQgb3duZWQgYnkgdGhlXG4gICAqIHRyYW5zcG9ydCwgYW5kIGRlbGV0ZWQgb24gZGlzcG9zZS5cbiAgICovXG4gIHJlYWRvbmx5IHVzZXJEYXRhRGlyOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBFeGNlcHRpb25EZXRhaWxzIHtcbiAgZXhjZXB0aW9uPzogQ2RwRXhjZXB0aW9uT2JqZWN0O1xuICB0ZXh0OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBFeGNlcHRpb25PYmplY3Qge1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIENkcFJlc3BvbnNlIHtcbiAgaWQ6IG51bWJlcjtcbiAgcmVzdWx0PzogQ2RwUmVzcG9uc2VSZXN1bHQ7XG59XG5cbmludGVyZmFjZSBDZHBSZXNwb25zZVJlc3VsdCB7XG4gIHJlYWRvbmx5IGV4Y2VwdGlvbkRldGFpbHM/OiBDZHBFeGNlcHRpb25EZXRhaWxzO1xuICByZWFkb25seSByZXN1bHQ/OiBDZHBWYWx1ZTtcbn1cblxuaW50ZXJmYWNlIENkcFRhcmdldCB7XG4gIGlkOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgdXJsOiBzdHJpbmc7XG4gIHdlYlNvY2tldERlYnVnZ2VyVXJsOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBWYWx1ZSB7XG4gIHR5cGU6IHN0cmluZztcbiAgdmFsdWU/OiB1bmtub3duO1xufVxuXG5jb25zdCBDT01NQU5EX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBWQVVMVF9JRF9CWVRFX0xFTkdUSCA9IDg7XG5jb25zdCBVU0VSX0RBVEFfUk1fVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAxMDAwMDtcbmNvbnN0IFVTRVJfREFUQV9STV9SRVRSWV9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSA1MDA7XG5jb25zdCBOT19PVVRQVVQgPSAnKG5vIG91dHB1dCknO1xuY29uc3QgVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSA1MDA7XG5jb25zdCBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBWQVVMVF9DTE9TRV9ERUxBWV9JTl9NSUxMSVNFQ09ORFMgPSAxMDAwO1xuY29uc3QgQVVUT19TVEFSVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDIwMDA7XG5jb25zdCBBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5cbi8qKlxuICogVHJhbnNwb3J0IHRoYXQgY29tbXVuaWNhdGVzIHdpdGggRGVza3RvcCBPYnNpZGlhbiB2aWEgQ2hyb21lIERldlRvb2xzIFByb3RvY29sLlxuICpcbiAqIENvbm5lY3RzIHRvIE9ic2lkaWFuJ3MgQ0RQIFdlYlNvY2tldCBlbmRwb2ludCwgc2VuZHMgYFJ1bnRpbWUuZXZhbHVhdGVgXG4gKiBjb21tYW5kcywgYW5kIHJvdXRlcyBleHByZXNzaW9ucyB0byB0aGUgY29ycmVjdCB2YXVsdCB0YXJnZXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXNrdG9wQ2RwVHJhbnNwb3J0IGltcGxlbWVudHMgT2JzaWRpYW5UcmFuc3BvcnQge1xuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhpcyB0cmFuc3BvcnQgaXMgZm9yIGEgbW9iaWxlIHBsYXRmb3JtLiBBbHdheXMgYGZhbHNlYCBmb3IgdGhpcyB0cmFuc3BvcnQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXNNb2JpbGUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBhY3RpdmVWYXVsdFBhdGg6IG51bGwgfCBzdHJpbmcgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkcEhvc3Q6IHN0cmluZztcbiAgcHJpdmF0ZSBjZHBQb3J0OiBudW1iZXI7XG4gIHByaXZhdGUgY2RwVXJsOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xuICBwcml2YXRlIG1lc3NhZ2VJZCA9IDA7XG4gIHByaXZhdGUgcmVhZG9ubHkgb3duZWRDb25maWc6IE93bmVkSW5zdGFuY2VDb25maWcgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgb3duZWRJbnN0YW5jZTogT3duZWRPYnNpZGlhbkluc3RhbmNlIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHdzOiBudWxsIHwgV2ViU29ja2V0ID0gbnVsbDtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBDRFAgdHJhbnNwb3J0LlxuICAgKlxuICAgKiBAcGFyYW0gY29uZmlnIC0gQ0RQIGNvbm5lY3Rpb24gY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihjb25maWc/OiBEZXNrdG9wQ2RwVHJhbnNwb3J0Q29uZmlnKSB7XG4gICAgdGhpcy5jZHBIb3N0ID0gY29uZmlnPy5jZHBIb3N0ID8/ICdsb2NhbGhvc3QnO1xuICAgIHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA9IGNvbmZpZz8uY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyA/PyBDT01NQU5EX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHRoaXMub3duZWRDb25maWcgPSBjb25maWc/Lm93bmVkSW5zdGFuY2U7XG4gICAgLy8gT3duZWQgbW9kZSBwaWNrcyBhIGZyZWUgcG9ydCBhdCBsYXVuY2ggKGFzc2lnbmVkIGluIHJlZ2lzdGVyVmF1bHQpLlxuICAgIC8vIEF0dGFjaCBtb2RlIGNvbm5lY3RzIHRvIHRoZSBjb25maWd1cmVkIHBvcnQ7IG5vIHBvcnQgaXMgaGFyZGNvZGVkLlxuICAgIHRoaXMuY2RwUG9ydCA9IGNvbmZpZz8uY2RwUG9ydCA/PyAwO1xuICAgIHRoaXMuY2RwVXJsID0gY29uZmlnPy5jZHBQb3J0ID09PSB1bmRlZmluZWQgPyAnJyA6IGBodHRwOi8vJHt0aGlzLmNkcEhvc3R9OiR7U3RyaW5nKGNvbmZpZy5jZHBQb3J0KX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3Bvc2VzIG9mIHRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24gYW5kLCBpbiBvd25lZC1pbnN0YW5jZSBtb2RlLFxuICAgKiBraWxscyB0aGUgb3duZWQgT2JzaWRpYW4gcHJvY2VzcyBhbmQgcmVtb3ZlcyBpdHMgaXNvbGF0ZWQgdXNlci1kYXRhIGRpci5cbiAgICpcbiAgICogVGhlIHJlbW92YWwgaXMgcmV0cmllZCBiZWNhdXNlIFdpbmRvd3MgYnJpZWZseSBob2xkcyB0aGUganVzdC1raWxsZWRcbiAgICogcHJvY2VzcydzIGZpbGUgaGFuZGxlcywgd2hpY2ggd291bGQgb3RoZXJ3aXNlIGZhaWwgYHJtU3luY2Agd2l0aCBgRVBFUk1gLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgaWYgKCF0aGlzLm93bmVkQ29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5vd25lZEluc3RhbmNlPy5raWxsKCk7XG4gICAgY29uc3QgeyB1c2VyRGF0YURpciB9ID0gdGhpcy5vd25lZENvbmZpZztcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBVU0VSX0RBVEFfUk1fVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgaWYgKHRyeVJlbW92ZURpcih1c2VyRGF0YURpcikpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVVNFUl9EQVRBX1JNX1JFVFJZX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG4gICAgfVxuICAgIGlmICghdHJ5UmVtb3ZlRGlyKHVzZXJEYXRhRGlyKSkge1xuICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gQ291bGQgbm90IHJlbW92ZSBvd25lZCB1c2VyLWRhdGEgZGlyIHdpdGhpbiAke1N0cmluZyhVU0VSX0RBVEFfUk1fVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zIChub24tZmF0YWwpOiAke3VzZXJEYXRhRGlyfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTeW5jaHJvbm91cyBkaXNwb3NhbCBcdTIwMTQga2lsbHMgdGhlIG93bmVkIGluc3RhbmNlIGFuZCBtYWtlcyBhIGJlc3QtZWZmb3J0XG4gICAqIHJlbW92YWwgb2YgaXRzIHVzZXItZGF0YSBkaXIuIFNhZmUgdG8gY2FsbCBmcm9tIGEgcHJvY2VzcyBgZXhpdGAgaGFuZGxlclxuICAgKiAod2hlcmUgYXN5bmMgcmV0cmllcyBhcmUgaW1wb3NzaWJsZTsgYSBsZWZ0b3ZlciB0ZW1wIGRpciBpcyBhY2NlcHRhYmxlKS5cbiAgICovXG4gIHB1YmxpYyBkaXNwb3NlU3luYygpOiB2b2lkIHtcbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgICBpZiAodGhpcy5vd25lZENvbmZpZykge1xuICAgICAgdGhpcy5vd25lZEluc3RhbmNlPy5raWxsKCk7XG4gICAgICBpZiAoIXRyeVJlbW92ZURpcih0aGlzLm93bmVkQ29uZmlnLnVzZXJEYXRhRGlyKSkge1xuICAgICAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBPd25lZCB1c2VyLWRhdGEgZGlyIG5vdCByZW1vdmVkIHN5bmNocm9ub3VzbHkgKHByb2Nlc3MgbWF5IHN0aWxsIGhvbGQgaGFuZGxlcyk6ICR7dGhpcy5vd25lZENvbmZpZy51c2VyRGF0YURpcn1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXZhbHVhdGVzIGEgSmF2YVNjcmlwdCBleHByZXNzaW9uIGluc2lkZSBPYnNpZGlhbiB2aWEgQ0RQIGBSdW50aW1lLmV2YWx1YXRlYC5cbiAgICpcbiAgICogUm91dGVzIHRvIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldCBiYXNlZCBvbiBgb3B0aW9ucy5jd2RgLlxuICAgKlxuICAgKiBAcGFyYW0gZXhwcmVzc2lvbiAtIFRoZSBKYXZhU2NyaXB0IGV4cHJlc3Npb24gdG8gZXZhbHVhdGUuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gRXZhbHVhdGlvbiBvcHRpb25zLlxuICAgKiBAcmV0dXJucyBUaGUgbm9ybWFsaXplZCByZXN1bHQgc3RyaW5nLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGV2YWx1YXRlKGV4cHJlc3Npb246IHN0cmluZywgb3B0aW9uczogVHJhbnNwb3J0RXZhbE9wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5lbnN1cmVDb25uZWN0aW9uKG9wdGlvbnMuY3dkKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICB9KTtcblxuICAgIGlmIChyZXNwb25zZS5yZXN1bHQ/LmV4Y2VwdGlvbkRldGFpbHMpIHtcbiAgICAgIGNvbnN0IGRlc2MgPSByZXNwb25zZS5yZXN1bHQuZXhjZXB0aW9uRGV0YWlscy5leGNlcHRpb24/LmRlc2NyaXB0aW9uXG4gICAgICAgID8/IHJlc3BvbnNlLnJlc3VsdC5leGNlcHRpb25EZXRhaWxzLnRleHQ7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENEUCBldmFsdWF0aW9uIGVycm9yOiAke2Rlc2N9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0T2JqID0gcmVzcG9uc2UucmVzdWx0Py5yZXN1bHQ7XG4gICAgaWYgKCFyZXN1bHRPYmogfHwgcmVzdWx0T2JqLnR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gTk9fT1VUUFVUO1xuICAgIH1cblxuICAgIHJldHVybiBTdHJpbmcocmVzdWx0T2JqLnZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyB0aGF0IHRoZSBDRFAgZW5kcG9pbnQgaXMgcmVhY2hhYmxlIGFuZCBoYXMgT2JzaWRpYW4gdGFyZ2V0cy5cbiAgICpcbiAgICogSWYgT2JzaWRpYW4gaXMgbm90IHJ1bm5pbmcsIGF0dGVtcHRzIHRvIGF1dG8tc3RhcnQgaXQgdmlhIFVSSSBwcm90b2NvbFxuICAgKiBhbmQgcG9sbHMgdW50aWwgQ0RQIGJlY29tZXMgYXZhaWxhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggKHVzZWQgZm9yIHZhdWx0IHJlZ2lzdHJhdGlvbiBjaGVjaykuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcHJlZmxpZ2h0Q2hlY2sodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5vd25lZENvbmZpZykge1xuICAgICAgLy8gT3duZWQgaW5zdGFuY2U6IHJlYWRpbmVzcyBpcyBndWFyYW50ZWVkIGJ5IHJlZ2lzdGVyVmF1bHQsIGFuZCB0aGUgdmF1bHRcbiAgICAgIC8vIExpdmVzIGluIHRoZSBpc29sYXRlZCBjb25maWcgXHUyMDE0IHRoZXJlIGlzIG5vdGhpbmcgdG8gdmVyaWZ5IGFnYWluc3QgdGhlXG4gICAgICAvLyBVc2VyLXNjb3BlIHJlZ2lzdHJ5LlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFJ1bm5pbmcgcHJlZmxpZ2h0IGNoZWNrIGZvciB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgaWYgKCFpc1ZhdWx0UmVnaXN0ZXJlZCh2YXVsdFBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBWYXVsdCBpcyBub3QgcmVnaXN0ZXJlZCBpbiBPYnNpZGlhbjogJHt2YXVsdFBhdGh9LiBSZWdpc3RlciB0aGUgdmF1bHQgZmlyc3Qgd2l0aCByZWdpc3RlclZhdWx0KCkgb3IgVGVtcFZhdWx0LnJlZ2lzdGVyKCkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHBhZ2UgdGFyZ2V0cycpO1xuICAgICAgfVxuICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gQ0RQIHJlYWNoYWJsZSwgJHtTdHJpbmcodGFyZ2V0cy5sZW5ndGgpfSB0YXJnZXQocykgZm91bmQuYCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZU9ic2lkaWFuUnVubmluZygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSB2YXVsdCB2aWEgRWxlY3Ryb24gSVBDIGV2YWx1YXRlZCB0aHJvdWdoIENEUC5cbiAgICpcbiAgICogVXNlcyBhbiBleGlzdGluZyBPYnNpZGlhbiB0YXJnZXQgdG8gc2VuZCB0aGUgYHZhdWx0LW9wZW5gIElQQyBjb21tYW5kLFxuICAgKiB0aGVuIHBvbGxzIHVudGlsIHRoZSBuZXcgdmF1bHQncyB0YXJnZXQgYXBwZWFycy5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm93bmVkQ29uZmlnKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyVmF1bHRJbk93bmVkSW5zdGFuY2UodmF1bHRQYXRoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBSZWdpc3RlcmluZyB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgYXZhaWxhYmxlLiBJcyBPYnNpZGlhbiBydW5uaW5nPycpO1xuICAgIH1cblxuICAgIGNvbnN0IGlwY1dzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQoZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSkpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQodGhpcywgdmF1bHRQYXRoKTtcbiAgICAgIGNvbnN0IGlwY0V4cHIgPSBgd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuaXBjU2VuZFN5bmMoJHtKU09OLnN0cmluZ2lmeSh7IGFyZ3M6IFt2YXVsdFBhdGgsIGZhbHNlXSwgY2hhbm5lbDogJ3ZhdWx0LW9wZW4nIH0pfSlgO1xuICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZChpcGNXcywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgICAgZXhwcmVzc2lvbjogaXBjRXhwcixcbiAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMuZW5hYmxlUGx1Z2luc0luTG9jYWxTdG9yYWdlKGlwY1dzLCB2YXVsdFBhdGgpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpcGNXcy5jbG9zZSgpO1xuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFBvbGxpbmcgZm9yIHZhdWx0IHRhcmdldCAodGltZW91dD0ke1N0cmluZyhWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcykuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIFZhdWx0IHRhcmdldCBmb3VuZC4nKTtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yTGF5b3V0UmVhZHkodmF1bHRQYXRoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNtaXNzVHJ1c3REaWFsb2codmF1bHRQYXRoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFZhdWx0IHRhcmdldCBub3QgcmVhZHkgeWV0LlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFZhdWx0IGF0ICR7dmF1bHRQYXRofSBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcoVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXNgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVycyBhIHZhdWx0IGJ5IGRlc3Ryb3lpbmcgaXRzIHdpbmRvdyBhbmQgcmVtb3ZpbmcgaXQgZnJvbSB0aGUgcmVnaXN0cnkuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgZm9sZGVyLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHVucmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm93bmVkQ29uZmlnKSB7XG4gICAgICAvLyBUaGUgb3duZWQgaW5zdGFuY2UgaXMga2lsbGVkIHdob2xlc2FsZSBvbiBkaXNwb3NlOyBubyBwZXItdmF1bHRcbiAgICAgIC8vIFVucmVnaXN0ZXIgaXMgbmVlZGVkIChhbmQgdGhlIHJlZ2lzdHJ5IGxpdmVzIGluIHRoZSBpc29sYXRlZCBjb25maWcpLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQodGhpcywgdmF1bHRQYXRoKTtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBkZXN0cm95RXhwciA9ICd3aW5kb3cuX19vYnNpZGlhbkludGVncmF0aW9uVGVzdGluZy5kZXN0cm95Q3VycmVudFdpbmRvdygpJztcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgICAgIGV4cHJlc3Npb246IGRlc3Ryb3lFeHByLFxuICAgICAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gV2luZG93IG1heSBhbHJlYWR5IGJlIGNsb3NlZC5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5hY3RpdmVWYXVsdFBhdGggPT09IHZhdWx0UGF0aCkge1xuICAgICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgYXdhaXQgZGVsYXkoVkFVTFRfQ0xPU0VfREVMQVlfSU5fTUlMTElTRUNPTkRTKTtcblxuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG4gICAgaWYgKHRhcmdldHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldChlbnN1cmVOb25OdWxsYWJsZSh0YXJnZXRzWzBdKSk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQodGhpcywgdmF1bHRQYXRoKTtcbiAgICAgICAgY29uc3QgcmVtb3ZlRXhwciA9IGB3aW5kb3cuX19vYnNpZGlhbkludGVncmF0aW9uVGVzdGluZy5pcGNTZW5kU3luYygke0pTT04uc3RyaW5naWZ5KHsgYXJnczogW3ZhdWx0UGF0aF0sIGNoYW5uZWw6ICd2YXVsdC1yZW1vdmUnIH0pfSlgO1xuICAgICAgICBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgICAgICBhd2FpdFByb21pc2U6IHRydWUsXG4gICAgICAgICAgZXhwcmVzc2lvbjogcmVtb3ZlRXhwcixcbiAgICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gTm8gQ0RQIHRhcmdldHMgZm9yIHJlbW92YWwgSVBDIFx1MjAxNCByZW1vdmluZyBkaXJlY3RseSBmcm9tIG9ic2lkaWFuLmpzb24uJyk7XG4gICAgICByZW1vdmVWYXVsdEZyb21Db25maWcodmF1bHRQYXRoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29ubmVjdHMgdG8gYSBDRFAgdGFyZ2V0J3MgV2ViU29ja2V0IGVuZHBvaW50LlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0IC0gVGhlIENEUCB0YXJnZXQgdG8gY29ubmVjdCB0by5cbiAgICogQHJldHVybnMgVGhlIG9wZW4gV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNvbm5lY3RUb1RhcmdldCh0YXJnZXQ6IENkcFRhcmdldCk6IFByb21pc2U8V2ViU29ja2V0PiB7XG4gICAgY29uc3Qgd3MgPSBuZXcgV2ViU29ja2V0KHRhcmdldC53ZWJTb2NrZXREZWJ1Z2dlclVybCk7XG4gICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgd3Mub25vcGVuID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9O1xuICAgICAgd3Mub25lcnJvciA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGNvbm5lY3QgdG8gQ0RQIHRhcmdldDogJHt0YXJnZXQud2ViU29ja2V0RGVidWdnZXJVcmx9YCkpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgICByZXR1cm4gd3M7XG4gIH1cblxuICAvKipcbiAgICogRGlzY29ubmVjdHMgdGhlIGFjdGl2ZSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICovXG4gIHByaXZhdGUgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy53cz8ucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4pIHtcbiAgICAgIHRoaXMud3MuY2xvc2UoKTtcbiAgICB9XG4gICAgdGhpcy53cyA9IG51bGw7XG4gICAgdGhpcy5hY3RpdmVWYXVsdFBhdGggPSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc21pc3NlcyB0aGUgXCJEbyB5b3UgdHJ1c3QgdGhlIGF1dGhvciBvZiB0aGlzIHZhdWx0P1wiIGRpYWxvZyBpZiBwcmVzZW50LlxuICAgKlxuICAgKiBBY3RzIGFzIGEgc2FmZXR5IG5ldCB3aGVuIGBlbmFibGUtcGx1Z2luLTxpZD5gIGlzIHdyaXR0ZW4gaW4gb25lIHJlbmRlcmVyXG4gICAqIGJ1dCBub3QgeWV0IHZpc2libGUgdG8gdGhlIG5ld2x5LW9wZW5lZCB2YXVsdCdzIHJlbmRlcmVyIChyYWNlIG9ic2VydmVkXG4gICAqIGluIE9ic2lkaWFuIDEuMTMuMCkuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCB0byBldmFsdWF0ZSBpbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZGlzbWlzc1RydXN0RGlhbG9nKHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ldmFsdWF0ZShESVNNSVNTX1RSVVNUX0RJQUxPR19FWFBSLCB7IGN3ZDogdmF1bHRQYXRoIH0pO1xuICAgIGlmIChyZXN1bHQgPT09ICd0cnVlJykge1xuICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gRGlzbWlzc2VkIFwiRG8geW91IHRydXN0IHRoZSBhdXRob3JcIiBkaWFsb2cuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGVuYWJsZS1wbHVnaW4tPHZhdWx0SWQ+YCBpbiBPYnNpZGlhbidzIGxvY2FsU3RvcmFnZSB0byBwcmV2ZW50XG4gICAqIHRoZSBcIkRvIHlvdSB0cnVzdCB0aGUgYXV0aG9yIG9mIHRoaXMgdmF1bHQ/XCIgZGlhbG9nIGZyb20gYXBwZWFyaW5nXG4gICAqIHdoZW4gYSB2YXVsdCB3aXRoIGNvbW11bml0eSBwbHVnaW5zIGlzIG9wZW5lZCBmb3IgdGhlIGZpcnN0IHRpbWUuXG4gICAqXG4gICAqIE11c3QgYmUgY2FsbGVkIGFmdGVyIHRoZSBgdmF1bHQtb3BlbmAgSVBDIChzbyB0aGUgdmF1bHQgSUQgZXhpc3RzIGluXG4gICAqIGBvYnNpZGlhbi5qc29uYCkgYW5kIGJlZm9yZSB0aGUgbmV3IHZhdWx0IHdpbmRvdyBmaW5pc2hlcyBsb2FkaW5nLlxuICAgKlxuICAgKiBAcGFyYW0gd3MgLSBBbiBvcGVuIFdlYlNvY2tldCB0byBhbiBleGlzdGluZyBPYnNpZGlhbiB0YXJnZXQuXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgZm9sZGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbmFibGVQbHVnaW5zSW5Mb2NhbFN0b3JhZ2Uod3M6IFdlYlNvY2tldCwgdmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB2YXVsdElkID0gZ2V0VmF1bHRJZCh2YXVsdFBhdGgpO1xuICAgIGlmICghdmF1bHRJZCkge1xuICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gQ291bGQgbm90IGZpbmQgdmF1bHQgSUQgXHUyMDE0IHNraXBwaW5nIGxvY2FsU3RvcmFnZSB0cnVzdCBmbGFnLicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgZXhwcmVzc2lvbjogYGxvY2FsU3RvcmFnZS5zZXRJdGVtKCR7SlNPTi5zdHJpbmdpZnkoYGVuYWJsZS1wbHVnaW4tJHt2YXVsdElkfWApfSwgJ3RydWUnKTtgLFxuICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgIH0pO1xuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFNldCBlbmFibGUtcGx1Z2luLSR7dmF1bHRJZH0gaW4gbG9jYWxTdG9yYWdlLmApO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlcmUgaXMgYW4gYWN0aXZlIFdlYlNvY2tldCBjb25uZWN0aW9uIHRvIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldC5cbiAgICpcbiAgICogUmV1c2VzIHRoZSBleGlzdGluZyBjb25uZWN0aW9uIGlmIGl0IHRhcmdldHMgdGhlIHJlcXVlc3RlZCB2YXVsdC5cbiAgICogT3RoZXJ3aXNlLCBmaW5kcyB0aGUgY29ycmVjdCB0YXJnZXQgYW5kIHJlY29ubmVjdHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCB0byB0YXJnZXQuXG4gICAqIEByZXR1cm5zIFRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZUNvbm5lY3Rpb24odmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPFdlYlNvY2tldD4ge1xuICAgIGlmICh0aGlzLndzPy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTiAmJiB0aGlzLmFjdGl2ZVZhdWx0UGF0aCA9PT0gdmF1bHRQYXRoKSB7XG4gICAgICByZXR1cm4gdGhpcy53cztcbiAgICB9XG5cbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcblxuICAgIGNvbnN0IHRhcmdldCA9IGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgdGhpcy53cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgdGhpcy5hY3RpdmVWYXVsdFBhdGggPSB2YXVsdFBhdGg7XG4gICAgcmV0dXJuIHRoaXMud3M7XG4gIH1cblxuICAvKipcbiAgICogTGF1bmNoZXMgT2JzaWRpYW4gd2l0aCBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgIGFuZCBwb2xscyB1bnRpbCBDRFAgYmVjb21lcyBhdmFpbGFibGUuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZU9ic2lkaWFuUnVubmluZygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBPYnNpZGlhbiBDRFAgbm90IHJlYWNoYWJsZS4gU3RhcnRpbmcgT2JzaWRpYW4gd2l0aCByZW1vdGUgZGVidWdnaW5nLi4uJyk7XG5cbiAgICBjb25zdCBsYXVuY2hDb21tYW5kID0gYXdhaXQgZ2V0T2JzaWRpYW5MYXVuY2hDb21tYW5kKHRoaXMuY2RwUG9ydCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGV4ZWMobGF1bmNoQ29tbWFuZCwgeyBpc1F1aWV0OiB0cnVlIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gVGhlIGxhdW5jaCBjb21tYW5kIG1heSBmYWlsIG9uIHNvbWUgc3lzdGVtcyBcdTIwMTQgd2UnbGwgc3RpbGwgdHJ5IHBvbGxpbmcuXG4gICAgfVxuXG4gICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gUG9sbGluZyBmb3IgQ0RQIGVuZHBvaW50IGF0ICR7dGhpcy5jZHBVcmx9ICh0aW1lb3V0PSR7U3RyaW5nKEFVVE9fU1RBUlRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zKS4uLmApO1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIEFVVE9fU1RBUlRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgYXdhaXQgZGVsYXkoQVVUT19TVEFSVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgdGhpcy5nZXRQYWdlVGFyZ2V0cygpO1xuICAgICAgICBpZiAodGFyZ2V0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gT2JzaWRpYW4gQ0RQIHJlYWR5LCAke1N0cmluZyh0YXJnZXRzLmxlbmd0aCl9IHRhcmdldChzKSBmb3VuZC5gKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBDRFAgbm90IHJlYWR5IHlldCwgcmV0cnlpbmcuLi4nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE9ic2lkaWFuIGRpZCBub3Qgc3RhcnQgd2l0aGluICR7U3RyaW5nKEFVVE9fU1RBUlRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zLiBFbnN1cmUgT2JzaWRpYW4gaXMgaW5zdGFsbGVkIGFuZCBhY2Nlc3NpYmxlLmApO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBDRFAgdGFyZ2V0IHRoYXQgaGFzIHRoZSBnaXZlbiB2YXVsdCBvcGVuLlxuICAgKlxuICAgKiBGb3IgYSBzaW5nbGUgdGFyZ2V0LCByZXR1cm5zIGl0IGRpcmVjdGx5LiBGb3IgbXVsdGlwbGUgdGFyZ2V0cyxcbiAgICogcHJvYmVzIGVhY2ggYnkgZXZhbHVhdGluZyBgZ2V0QmFzZVBhdGgoKWAgdG8gZmluZCB0aGUgbWF0Y2guXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCB0byBtYXRjaC5cbiAgICogQHJldHVybnMgVGhlIG1hdGNoaW5nIENEUCB0YXJnZXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8Q2RwVGFyZ2V0PiB7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcblxuICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBPYnNpZGlhbiBDRFAgdGFyZ2V0cyBmb3VuZCcpO1xuICAgIH1cblxuICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIGVuc3VyZU5vbk51bGxhYmxlKHRhcmdldHNbMF0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgdGFyZ2V0IG9mIHRhcmdldHMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJhc2VQYXRoID0gYXdhaXQgdGhpcy5wcm9iZVZhdWx0UGF0aCh0YXJnZXQpO1xuICAgICAgICBpZiAoYmFzZVBhdGggPT09IHZhdWx0UGF0aCkge1xuICAgICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBOb3QgYSB2YXVsdCB0YXJnZXQgb3Igbm90IHJlYWR5LlxuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgTm8gQ0RQIHRhcmdldCBmb3VuZCBmb3IgdmF1bHQ6ICR7dmF1bHRQYXRofWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoZXMgdGhlIGxpc3Qgb2YgcGFnZS10eXBlIHRhcmdldHMgZnJvbSB0aGUgQ0RQIGAvanNvbmAgZW5kcG9pbnQuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBsaXN0IG9mIHBhZ2UgdGFyZ2V0cy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0UGFnZVRhcmdldHMoKTogUHJvbWlzZTxDZHBUYXJnZXRbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7dGhpcy5jZHBVcmx9L2pzb25gKTtcbiAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIENkcFRhcmdldFtdO1xuICAgIHJldHVybiB0YXJnZXRzLmZpbHRlcigodCkgPT4gdC50eXBlID09PSAncGFnZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb2JlcyBhIHRhcmdldCB0byBkaXNjb3ZlciB3aGljaCB2YXVsdCBwYXRoIGl0IGhhcyBvcGVuLlxuICAgKlxuICAgKiBDcmVhdGVzIGEgdGVtcG9yYXJ5IFdlYlNvY2tldCBjb25uZWN0aW9uLCBldmFsdWF0ZXMgYGdldEJhc2VQYXRoKClgLFxuICAgKiBhbmQgcmV0dXJucyB0aGUgcmVzdWx0LlxuICAgKlxuICAgKiBAcGFyYW0gdGFyZ2V0IC0gVGhlIENEUCB0YXJnZXQgdG8gcHJvYmUuXG4gICAqIEByZXR1cm5zIFRoZSB2YXVsdCdzIGJhc2UgcGF0aC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcHJvYmVWYXVsdFBhdGgodGFyZ2V0OiBDZHBUYXJnZXQpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQodGFyZ2V0KTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgICAgZXhwcmVzc2lvbjogJ2FwcC52YXVsdC5hZGFwdGVyLmdldEJhc2VQYXRoKCknLFxuICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBTdHJpbmcocmVzcG9uc2UucmVzdWx0Py5yZXN1bHQ/LnZhbHVlKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgd3MuY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGF1bmNoZXMgYW5kIGNvbm5lY3RzIHRvIGEgaGFybmVzcy1vd25lZCwgaXNvbGF0ZWQgT2JzaWRpYW4gaW5zdGFuY2UgZm9yIGFcbiAgICogdmF1bHQ6IHByb3Zpc2lvbnMgdGhlIGFzYXIgKGlmIGFueSksIHByZS1zZWVkcyB0aGUgaXNvbGF0ZWQgYG9ic2lkaWFuLmpzb25gXG4gICAqIHNvIHRoZSB2YXVsdCBvcGVucyBkaXJlY3RseSwgbGF1bmNoZXMgdGhlIGluc3RhbmNlIG9uIGEgZnJlZSBDRFAgcG9ydCwgdGhlblxuICAgKiB3YWl0cyB1bnRpbCB0aGUgdmF1bHQgd2luZG93IGlzIHJlYWR5IGFuZCBkaXNtaXNzZXMgdGhlIHRydXN0IGRpYWxvZy5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyVmF1bHRJbk93bmVkSW5zdGFuY2UodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb25maWcgPSBlbnN1cmVOb25OdWxsYWJsZSh0aGlzLm93bmVkQ29uZmlnKTtcbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBMYXVuY2hpbmcgb3duZWQgT2JzaWRpYW4gaW5zdGFuY2UgZm9yIHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcblxuICAgIG1rZGlyU3luYyhjb25maWcudXNlckRhdGFEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGlmIChjb25maWcuYXNhcikge1xuICAgICAgY29weUFzYXJJbnRvVXNlckRhdGEoY29uZmlnLmFzYXIucGF0aCwgY29uZmlnLmFzYXIudmVyc2lvbiwgY29uZmlnLnVzZXJEYXRhRGlyKTtcbiAgICB9XG5cbiAgICBjb25zdCB2YXVsdElkID0gcmFuZG9tQnl0ZXMoVkFVTFRfSURfQllURV9MRU5HVEgpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBvYnNpZGlhbkpzb24gPSB7XG4gICAgICB1cGRhdGVEaXNhYmxlZDogdHJ1ZSxcbiAgICAgIHZhdWx0czogeyBbdmF1bHRJZF06IHsgb3BlbjogdHJ1ZSwgcGF0aDogdmF1bHRQYXRoLCB0czogRGF0ZS5ub3coKSB9IH1cbiAgICB9O1xuICAgIHdyaXRlRmlsZVN5bmMoam9pbihjb25maWcudXNlckRhdGFEaXIsICdvYnNpZGlhbi5qc29uJyksIEpTT04uc3RyaW5naWZ5KG9ic2lkaWFuSnNvbikpO1xuXG4gICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBsYXVuY2hPd25lZE9ic2lkaWFuSW5zdGFuY2Uoe1xuICAgICAgY2RwSG9zdDogdGhpcy5jZHBIb3N0LFxuICAgICAgZXhlUGF0aDogY29uZmlnLmV4ZVBhdGgsXG4gICAgICB1c2VyRGF0YURpcjogY29uZmlnLnVzZXJEYXRhRGlyXG4gICAgfSk7XG4gICAgdGhpcy5vd25lZEluc3RhbmNlID0gaW5zdGFuY2U7XG4gICAgdGhpcy5jZHBQb3J0ID0gaW5zdGFuY2UucG9ydDtcbiAgICB0aGlzLmNkcFVybCA9IGluc3RhbmNlLmNkcFVybDtcblxuICAgIGF3YWl0IHRoaXMud2FpdEZvck93bmVkVmF1bHRSZWFkeSh2YXVsdFBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGEgQ0RQIGNvbW1hbmQgb3ZlciBXZWJTb2NrZXQgYW5kIHdhaXRzIGZvciB0aGUgcmVzcG9uc2UuXG4gICAqXG4gICAqIEBwYXJhbSB3cyAtIFRoZSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICogQHBhcmFtIG1ldGhvZCAtIFRoZSBDRFAgbWV0aG9kIG5hbWUuXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgQ0RQIG1ldGhvZCBwYXJhbWV0ZXJzLlxuICAgKiBAcmV0dXJucyBUaGUgQ0RQIHJlc3BvbnNlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBzZW5kQ29tbWFuZCh3czogV2ViU29ja2V0LCBtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFByb21pc2U8Q2RwUmVzcG9uc2U+IHtcbiAgICBjb25zdCBpZCA9ICsrdGhpcy5tZXNzYWdlSWQ7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8Q2RwUmVzcG9uc2U+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgd3MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGhhbmRsZXIpO1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBDRFAgY29tbWFuZCB0aW1lZCBvdXQgYWZ0ZXIgJHtTdHJpbmcodGhpcy5jb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzKX1tczogJHttZXRob2R9YCkpO1xuICAgICAgfSwgdGhpcy5jb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzKTtcblxuICAgICAgZnVuY3Rpb24gaGFuZGxlcihldmVudDogTWVzc2FnZUV2ZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG1zZyA9IEpTT04ucGFyc2UoU3RyaW5nKGV2ZW50LmRhdGEpKSBhcyBDZHBSZXNwb25zZTtcbiAgICAgICAgaWYgKG1zZy5pZCA9PT0gaWQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgd3MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGhhbmRsZXIpO1xuICAgICAgICAgIHJlc29sdmUobXNnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB3cy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgaGFuZGxlcik7XG4gICAgICB3cy5zZW5kKEpTT04uc3RyaW5naWZ5KHsgaWQsIG1ldGhvZCwgcGFyYW1zIH0pKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXYWl0cyBmb3IgdGhlIHZhdWx0J3MgYGFwcC53b3Jrc3BhY2VgIHRvIHJlYWNoIGxheW91dC1yZWFkeSBzdGF0ZS5cbiAgICpcbiAgICogYGZpbmRUYXJnZXRGb3JWYXVsdGAgcmV0dXJucyBhcyBzb29uIGFzIGBhcHAudmF1bHQuYWRhcHRlci5nZXRCYXNlUGF0aCgpYFxuICAgKiBtYXRjaGVzIFx1MjAxNCB3aGljaCBpcyB0cnVlIHNob3J0bHkgYWZ0ZXIgdGhlIGBBcHBgIGNvbnN0cnVjdG9yIHJ1bnMsIGJlZm9yZVxuICAgKiBgcGx1Z2lucy5pbml0aWFsaXplKClgIChhbmQgYW55IHRydXN0IGRpYWxvZykgaGFzIGV4ZWN1dGVkLiBCb290c3RyYXBwaW5nXG4gICAqIHRoZSBuYW1lc3BhY2UgYW5kIGNhbGxpbmcgYHBvbGxWYXVsdEJhc2VQYXRoKClgIGF3YWl0cyBgbGF5b3V0UmVhZHlgLCBzb1xuICAgKiBieSB0aGUgdGltZSB0aGlzIHJldHVybnMgdGhlIGRpYWxvZyBoYXMgZWl0aGVyIHJlbmRlcmVkIG9yIGlzIG5vdCBnb2luZ1xuICAgKiB0byByZW5kZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCB0byBldmFsdWF0ZSBpbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd2FpdEZvckxheW91dFJlYWR5KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkKHRoaXMsIHZhdWx0UGF0aCk7XG4gICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgnd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcucG9sbFZhdWx0QmFzZVBhdGgoKScsIHsgY3dkOiB2YXVsdFBhdGggfSk7XG4gIH1cblxuICAvKipcbiAgICogUG9sbHMgdGhlIG93bmVkIGluc3RhbmNlIHVudGlsIHRoZSB2YXVsdCB0YXJnZXQgZXhpc3RzLCBsYXlvdXQgaXMgcmVhZHksIGFuZFxuICAgKiB0aGUgdHJ1c3QgZGlhbG9nIChpZiBhbnkpIGhhcyBiZWVuIGRpc21pc3NlZC5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdhaXRGb3JPd25lZFZhdWx0UmVhZHkodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBXYWl0aW5nIGZvciBvd25lZCB2YXVsdCB0byBiZWNvbWUgcmVhZHkgKHRpbWVvdXQ9JHtTdHJpbmcoVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXMpLi4uYCk7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUztcbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGgpO1xuICAgICAgICBhd2FpdCB0aGlzLndhaXRGb3JMYXlvdXRSZWFkeSh2YXVsdFBhdGgpO1xuICAgICAgICBhd2FpdCB0aGlzLmRpc21pc3NUcnVzdERpYWxvZyh2YXVsdFBhdGgpO1xuICAgICAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBPd25lZCB2YXVsdCBpcyByZWFkeS4nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFZhdWx0IHRhcmdldCBub3QgcmVhZHkgeWV0LlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE93bmVkIHZhdWx0IGF0ICR7dmF1bHRQYXRofSBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcoVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXNgKTtcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgdGhlIGdpdmVuIGRlbGF5LlxuICpcbiAqIEBwYXJhbSBtcyAtIFRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHMuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciB0aGUgZGVsYXkuXG4gKi9cbmZ1bmN0aW9uIGRlbGF5KG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgc2V0VGltZW91dChyZXNvbHZlLCBtcyk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHBsYXRmb3JtLXNwZWNpZmljIGNvbW1hbmQgdG8gbGF1bmNoIE9ic2lkaWFuIHdpdGggcmVtb3RlIGRlYnVnZ2luZyBlbmFibGVkLlxuICpcbiAqIFJlc29sdmVzIHRoZSBhY3R1YWwgaW5zdGFsbGVkIE9ic2lkaWFuIGV4ZWN1dGFibGUgKGNvdmVyaW5nIGluc3RhbGxlci1iYXNlZFxuICogYW5kIGBQQVRIYC1iYXNlZCBpbnN0YWxscyBzdWNoIGFzIGBzY29vcGApIGFuZCB2ZXJpZmllcyBpdCBleGlzdHMgYmVmb3JlXG4gKiByZXR1cm5pbmcgYSBjb21tYW5kLiBUaHJvd3MgaWYgT2JzaWRpYW4gaXMgbm90IGluc3RhbGxlZC5cbiAqXG4gKiBAcGFyYW0gcG9ydCAtIFRoZSBDRFAgcG9ydCB0byB1c2UuXG4gKiBAcmV0dXJucyBUaGUgc2hlbGwgY29tbWFuZCBzdHJpbmcuXG4gKiBAdGhyb3dzIEVycm9yIGlmIE9ic2lkaWFuIGNhbm5vdCBiZSBsb2NhdGVkLlxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRPYnNpZGlhbkxhdW5jaENvbW1hbmQocG9ydDogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgZXhlUGF0aCA9IGF3YWl0IHJlc29sdmVPYnNpZGlhbkV4ZWN1dGFibGUoKTtcbiAgY29uc3QgZmxhZyA9IGAtLXJlbW90ZS1kZWJ1Z2dpbmctcG9ydD0ke1N0cmluZyhwb3J0KX1gO1xuXG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgcmV0dXJuIGBzdGFydCBcIlwiIFwiJHtleGVQYXRofVwiICR7ZmxhZ31gO1xuICB9XG5cbiAgcmV0dXJuIGBcIiR7ZXhlUGF0aH1cIiAke2ZsYWd9ICZgO1xufVxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIHJlbW92ZSBhIGRpcmVjdG9yeSByZWN1cnNpdmVseSwgcmV0dXJuaW5nIHdoZXRoZXIgaXQgc3VjY2VlZGVkLlxuICpcbiAqIEBwYXJhbSBkaXIgLSBUaGUgZGlyZWN0b3J5IHRvIHJlbW92ZS5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiByZW1vdmVkLCBgZmFsc2VgIGlmIHRoZSByZW1vdmFsIHRocmV3IChlLmcuIGhhbmRsZXMgaGVsZCkuXG4gKi9cbmZ1bmN0aW9uIHRyeVJlbW92ZURpcihkaXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIHJtU3luYyhkaXIsIHsgZm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qIHY4IGlnbm9yZSBzdG9wICovXG4iXSwKICAibWFwcGluZ3MiOiAiQUFxQkEsU0FBUyxtQkFBbUI7QUFDNUI7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxZQUFZO0FBQ3JCLE9BQU8sYUFBYTtBQVFwQixTQUFTLGlDQUFpQztBQUMxQyxTQUFTLFlBQVk7QUFDckIsU0FBUyxXQUFXO0FBQ3BCLFNBQVMsbUNBQW1DO0FBQzVDO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQLFNBQVMsaUNBQWlDO0FBQzFDLFNBQVMsbUNBQW1DO0FBQzVDLFNBQVMsNEJBQTRCO0FBQ3JDLFNBQVMseUJBQXlCO0FBOEZsQyxNQUFNLGtDQUFrQztBQUN4QyxNQUFNLHVCQUF1QjtBQUM3QixNQUFNLHVDQUF1QztBQUM3QyxNQUFNLDhDQUE4QztBQUNwRCxNQUFNLFlBQVk7QUFDbEIsTUFBTSxzQ0FBc0M7QUFDNUMsTUFBTSxxQ0FBcUM7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