obsidian-integration-testing 8.0.1 → 8.1.1

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 (65) hide show
  1. package/README.md +23 -4
  2. package/dist/lib/cjs/cli.cjs +29 -8
  3. package/dist/lib/cjs/cli.d.cts +2 -1
  4. package/dist/lib/cjs/connect-to-cdp.cjs +17 -11
  5. package/dist/lib/cjs/connect-to-cdp.d.cts +35 -3
  6. package/dist/lib/cjs/context-provider.cjs +1 -1
  7. package/dist/lib/cjs/context-provider.d.cts +1 -1
  8. package/dist/lib/cjs/global-setup-core.cjs +17 -5
  9. package/dist/lib/cjs/global-setup-core.d.cts +11 -1
  10. package/dist/lib/cjs/incompatible-installer-version-error.cjs +52 -0
  11. package/dist/lib/cjs/incompatible-installer-version-error.d.cts +44 -0
  12. package/dist/lib/cjs/index.cjs +13 -1
  13. package/dist/lib/cjs/index.d.cts +7 -0
  14. package/dist/lib/cjs/installer-compatibility.cjs +64 -0
  15. package/dist/lib/cjs/installer-compatibility.d.cts +75 -0
  16. package/dist/lib/cjs/library.cjs +1 -1
  17. package/dist/lib/cjs/namespace-bootstrap.cjs +16 -7
  18. package/dist/lib/cjs/obsidian-installer.cjs +7 -4
  19. package/dist/lib/cjs/obsidian-metadata.cjs +1811 -0
  20. package/dist/lib/cjs/obsidian-metadata.d.cts +56 -0
  21. package/dist/lib/cjs/renderer-boot-detection.cjs +49 -0
  22. package/dist/lib/cjs/renderer-boot-detection.d.cts +83 -0
  23. package/dist/lib/cjs/renderer-failed-to-initialize-error.cjs +41 -0
  24. package/dist/lib/cjs/renderer-failed-to-initialize-error.d.cts +23 -0
  25. package/dist/lib/cjs/transport-desktop-cdp.cjs +85 -3
  26. package/dist/lib/cjs/transport-desktop-cdp.d.cts +55 -1
  27. package/dist/lib/cjs/transport-factory.cjs +76 -21
  28. package/dist/lib/cjs/transport-factory.d.cts +1 -1
  29. package/dist/lib/cjs/transport-options.cjs +1 -1
  30. package/dist/lib/cjs/transport-options.d.cts +37 -4
  31. package/dist/lib/cjs/visibility.cjs +10 -2
  32. package/dist/lib/cjs/visibility.d.cts +27 -8
  33. package/dist/lib/esm/cli.d.mts +2 -1
  34. package/dist/lib/esm/cli.mjs +29 -8
  35. package/dist/lib/esm/connect-to-cdp.d.mts +35 -3
  36. package/dist/lib/esm/connect-to-cdp.mjs +17 -11
  37. package/dist/lib/esm/context-provider.d.mts +1 -1
  38. package/dist/lib/esm/context-provider.mjs +1 -1
  39. package/dist/lib/esm/global-setup-core.d.mts +11 -1
  40. package/dist/lib/esm/global-setup-core.mjs +15 -4
  41. package/dist/lib/esm/incompatible-installer-version-error.d.mts +44 -0
  42. package/dist/lib/esm/incompatible-installer-version-error.mjs +28 -0
  43. package/dist/lib/esm/index.d.mts +7 -0
  44. package/dist/lib/esm/index.mjs +9 -1
  45. package/dist/lib/esm/installer-compatibility.d.mts +75 -0
  46. package/dist/lib/esm/installer-compatibility.mjs +40 -0
  47. package/dist/lib/esm/library.mjs +1 -1
  48. package/dist/lib/esm/namespace-bootstrap.mjs +16 -7
  49. package/dist/lib/esm/obsidian-installer.mjs +7 -4
  50. package/dist/lib/esm/obsidian-metadata.d.mts +56 -0
  51. package/dist/lib/esm/obsidian-metadata.mjs +1787 -0
  52. package/dist/lib/esm/renderer-boot-detection.d.mts +83 -0
  53. package/dist/lib/esm/renderer-boot-detection.mjs +23 -0
  54. package/dist/lib/esm/renderer-failed-to-initialize-error.d.mts +23 -0
  55. package/dist/lib/esm/renderer-failed-to-initialize-error.mjs +17 -0
  56. package/dist/lib/esm/transport-desktop-cdp.d.mts +55 -1
  57. package/dist/lib/esm/transport-desktop-cdp.mjs +89 -3
  58. package/dist/lib/esm/transport-factory.d.mts +1 -1
  59. package/dist/lib/esm/transport-factory.mjs +76 -21
  60. package/dist/lib/esm/transport-options.d.mts +37 -4
  61. package/dist/lib/esm/visibility.d.mts +27 -8
  62. package/dist/lib/esm/visibility.mjs +8 -2
  63. package/dist/obsidian-integration-testing-8.1.1.tgz +0 -0
  64. package/package.json +2 -3
  65. package/dist/obsidian-integration-testing-8.0.1.tgz +0 -0
@@ -43,6 +43,8 @@ var import_obsidian_config = require("./obsidian-config.cjs");
43
43
  var import_obsidian_executable = require("./obsidian-executable.cjs");
44
44
  var import_obsidian_instance = require("./obsidian-instance.cjs");
45
45
  var import_obsidian_version_switch = require("./obsidian-version-switch.cjs");
46
+ var import_renderer_boot_detection = require("./renderer-boot-detection.cjs");
47
+ var import_renderer_failed_to_initialize_error = require("./renderer-failed-to-initialize-error.cjs");
46
48
  var import_type_guards = require("./type-guards.cjs");
47
49
  var import_visibility = require("./visibility.cjs");
48
50
  const COMMAND_TIMEOUT_IN_MILLISECONDS = 3e4;
@@ -69,11 +71,13 @@ class DesktopCdpTransport {
69
71
  cdpPort;
70
72
  cdpUrl;
71
73
  commandTimeoutInMilliseconds;
74
+ deadBootGraceInMilliseconds;
72
75
  isHarnessOwnedInstance;
73
76
  isObsidianAppVisible;
74
77
  messageId = 0;
75
78
  ownedConfig;
76
79
  ownedInstance;
80
+ shouldDisableSandbox;
77
81
  ws = null;
78
82
  /**
79
83
  * Creates a new CDP transport.
@@ -83,9 +87,11 @@ class DesktopCdpTransport {
83
87
  constructor(config) {
84
88
  this.cdpHost = config?.cdpHost ?? "localhost";
85
89
  this.commandTimeoutInMilliseconds = config?.commandTimeoutInMilliseconds ?? COMMAND_TIMEOUT_IN_MILLISECONDS;
90
+ this.deadBootGraceInMilliseconds = config?.deadBootGraceInMilliseconds ?? import_renderer_boot_detection.DEFAULT_DEAD_BOOT_GRACE_IN_MILLISECONDS;
86
91
  this.isHarnessOwnedInstance = config?.isHarnessOwnedInstance ?? false;
87
- this.isObsidianAppVisible = config?.isObsidianAppVisible ?? false;
92
+ this.isObsidianAppVisible = config?.isObsidianAppVisible ?? true;
88
93
  this.ownedConfig = config?.ownedInstance;
94
+ this.shouldDisableSandbox = config?.shouldDisableSandbox ?? false;
89
95
  this.cdpPort = config?.cdpPort ?? 0;
90
96
  this.cdpUrl = config?.cdpPort === void 0 ? "" : `http://${this.cdpHost}:${String(config.cdpPort)}`;
91
97
  }
@@ -154,6 +160,17 @@ class DesktopCdpTransport {
154
160
  }
155
161
  return String(resultObj.value);
156
162
  }
163
+ /**
164
+ * Returns the resolved installer↔app compatibility verdict for this owned
165
+ * instance, so callers can assert on it. Returns `undefined` when this is not
166
+ * an owned instance, or the verdict could not be determined (e.g. an
167
+ * undetectable shell version, or the app version is absent from the table).
168
+ *
169
+ * @returns The compatibility verdict, or `undefined`.
170
+ */
171
+ getCompatibility() {
172
+ return this.ownedConfig?.compatibility;
173
+ }
157
174
  /**
158
175
  * Returns the CDP endpoint of the owned, launched instance so the global setup
159
176
  * can hand it to test workers (which then **attach** to it instead of
@@ -502,6 +519,45 @@ class DesktopCdpTransport {
502
519
  }
503
520
  throw new Error(`Vault at ${vaultPath} did not become ready within ${String(VAULT_POLL_TIMEOUT_IN_MILLISECONDS)}ms`);
504
521
  }
522
+ /**
523
+ * Samples the vault renderer's bootstrap state — whether the document is
524
+ * `complete`, whether `window.app` exists, and the `<body>` child count — from
525
+ * the first page target, for dead-boot detection. This works even when the app
526
+ * never bootstrapped (the renderer page target still exists), which is exactly
527
+ * the state it must observe.
528
+ *
529
+ * @returns The sampled observation, or `undefined` when no target is reachable
530
+ * or the probe failed (so the caller keeps polling rather than fast-failing).
531
+ */
532
+ async probeRendererBootState() {
533
+ try {
534
+ const target = (await this.getPageTargets())[0];
535
+ if (!target) {
536
+ return void 0;
537
+ }
538
+ const ws = await this.connectToTarget(target);
539
+ try {
540
+ const probeExpr = `JSON.stringify({
541
+ bodyChildElementCount: document.body ? document.body.childElementCount : 0,
542
+ hasWindowApp: typeof window.app !== 'undefined',
543
+ isDocumentComplete: document.readyState === 'complete'
544
+ })`;
545
+ const response = await this.sendCommand(ws, "Runtime.evaluate", {
546
+ expression: probeExpr,
547
+ returnByValue: true
548
+ });
549
+ const value = response.result?.result?.value;
550
+ if (typeof value !== "string") {
551
+ return void 0;
552
+ }
553
+ return JSON.parse(value);
554
+ } finally {
555
+ ws.close();
556
+ }
557
+ } catch {
558
+ return void 0;
559
+ }
560
+ }
505
561
  /**
506
562
  * Probes a target to discover which vault path it has open.
507
563
  *
@@ -556,7 +612,10 @@ class DesktopCdpTransport {
556
612
  const instance = await (0, import_obsidian_instance.launchOwnedObsidianInstance)({
557
613
  cdpHost: this.cdpHost,
558
614
  exePath: config.exePath,
559
- extraArgs: (0, import_visibility.resolveOwnedHiddenLaunchArgs)(this.isObsidianAppVisible),
615
+ extraArgs: [
616
+ ...(0, import_visibility.resolveOwnedHiddenLaunchArgs)(this.isObsidianAppVisible),
617
+ ...(0, import_visibility.resolveSandboxLaunchArgs)(this.shouldDisableSandbox)
618
+ ],
560
619
  userDataDir: config.userDataDir
561
620
  });
562
621
  this.ownedInstance = instance;
@@ -636,11 +695,21 @@ class DesktopCdpTransport {
636
695
  * Polls the owned instance until the vault target exists, layout is ready, and
637
696
  * the trust dialog (if any) has been dismissed.
638
697
  *
698
+ * Between readiness attempts it also checks for a **dead boot** — the renderer
699
+ * loaded (`document.readyState` `'complete'`) but the app never bootstrapped
700
+ * (empty `<body>`, no `window.app`), the terminal state when the asar cannot
701
+ * run on the launched Electron shell. Once that state has held for the
702
+ * configured grace window it throws a {@link RendererFailedToInitializeError}
703
+ * immediately instead of waiting out the full readiness timeout. A grace of
704
+ * `0` disables the fast-fail. The grace clock starts when the renderer first
705
+ * reports `complete`, so a slow load before then is never counted against it.
706
+ *
639
707
  * @param vaultPath - The absolute path to the vault folder.
640
708
  */
641
709
  async waitForOwnedVaultReady(vaultPath) {
642
710
  (0, import_log.log)(`[cdp-transport] Waiting for owned vault to become ready (timeout=${String(VAULT_POLL_TIMEOUT_IN_MILLISECONDS)}ms)...`);
643
711
  const deadline = Date.now() + VAULT_POLL_TIMEOUT_IN_MILLISECONDS;
712
+ let documentCompleteSince = null;
644
713
  while (Date.now() < deadline) {
645
714
  try {
646
715
  await this.findTargetForVault(vaultPath);
@@ -650,6 +719,19 @@ class DesktopCdpTransport {
650
719
  return;
651
720
  } catch {
652
721
  }
722
+ if (this.deadBootGraceInMilliseconds > 0) {
723
+ const observation = await this.probeRendererBootState();
724
+ if (observation) {
725
+ if (observation.isDocumentComplete && documentCompleteSince === null) {
726
+ documentCompleteSince = Date.now();
727
+ }
728
+ const hasGraceElapsed = documentCompleteSince !== null && Date.now() - documentCompleteSince >= this.deadBootGraceInMilliseconds;
729
+ if ((0, import_renderer_boot_detection.checkRendererBootState)({ ...observation, hasGraceElapsed }) === "dead") {
730
+ (0, import_log.log)("[cdp-transport] Owned renderer failed to initialize (dead boot); failing fast.");
731
+ throw new import_renderer_failed_to_initialize_error.RendererFailedToInitializeError(vaultPath);
732
+ }
733
+ }
734
+ }
653
735
  await delay(VAULT_POLL_INTERVAL_IN_MILLISECONDS);
654
736
  }
655
737
  throw new Error(`Owned vault at ${vaultPath} did not become ready within ${String(VAULT_POLL_TIMEOUT_IN_MILLISECONDS)}ms`);
@@ -680,4 +762,4 @@ function tryRemoveDir(dir) {
680
762
  0 && (module.exports = {
681
763
  DesktopCdpTransport
682
764
  });
683
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1kZXNrdG9wLWNkcC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIERlc2t0b3AgQ0RQIHRyYW5zcG9ydCBcdTIwMTQgZXZhbHVhdGVzIGV4cHJlc3Npb25zIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2xcbiAqIG92ZXIgV2ViU29ja2V0IGFuZCBtYW5hZ2VzIHZhdWx0cyB2aWEgRWxlY3Ryb24gSVBDLlxuICpcbiAqIFR3byBtb2RlczpcbiAqIC0gKipPd25lZCAoZGVmYXVsdCkqKjogdGhlIHRyYW5zcG9ydCBsYXVuY2hlcyBhbmQgb3ducyBhbiBpc29sYXRlZCBPYnNpZGlhblxuICogICBpbnN0YW5jZSBhZ2FpbnN0IGEgdGVtcG9yYXJ5IGAtLXVzZXItZGF0YS1kaXJgIG9uIGEgZnJlZSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgLFxuICogICBuZXZlciB0b3VjaGluZyB0aGUgdXNlcidzIE9ic2lkaWFuLiBTdXBwb3J0cyB2ZXJzaW9uIHBpbm5pbmcgdmlhIHRoZSB1c2VyLWRhdGEgYXNhci5cbiAqIC0gKipBdHRhY2gqKjogd2hlbiBhbiBleHBsaWNpdCBDRFAgcG9ydCBpcyBjb25maWd1cmVkLCB0aGUgdHJhbnNwb3J0IGNvbm5lY3RzXG4gKiAgIHRvIGFuIGFscmVhZHktcnVubmluZyBPYnNpZGlhbiBvbiB0aGF0IHBvcnQuXG4gKlxuICogSXQgY29ubmVjdHMgdG8gcGFnZSB0YXJnZXRzLCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWAgY29tbWFuZHMsIGFuZCByb3V0ZXMgdG9cbiAqIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldCB1c2luZyBgZ2V0QmFzZVBhdGgoKWAgcHJvYmluZy5cbiAqXG4gKiBSZXF1aXJlbWVudHM6IE5vZGUuanMgMjIrICh1c2VzIGJ1aWx0LWluIGBXZWJTb2NrZXRgIGFuZCBgZmV0Y2hgIGdsb2JhbHMpLlxuICovXG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBJbnRlZ3JhdGlvbi10aW1lIGNvZGUgY292ZXJlZCBieSBpbnRlZ3JhdGlvbiB0ZXN0cywgbm90IHVuaXQgdGVzdHMuICovXG5cbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHtcbiAgbWtkaXJTeW5jLFxuICBybVN5bmMsXG4gIHdyaXRlRmlsZVN5bmNcbn0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5cbmltcG9ydCB0eXBlIHsgT3duZWRPYnNpZGlhbkluc3RhbmNlIH0gZnJvbSAnLi9vYnNpZGlhbi1pbnN0YW5jZS5janMnO1xuaW1wb3J0IHR5cGUge1xuICBPYnNpZGlhblRyYW5zcG9ydCxcbiAgVHJhbnNwb3J0RXZhbE9wdGlvbnNcbn0gZnJvbSAnLi90cmFuc3BvcnQuY2pzJztcblxuaW1wb3J0IHsgRElTTUlTU19UUlVTVF9ESUFMT0dfRVhQUiB9IGZyb20gJy4vZGlzbWlzcy10cnVzdC1kaWFsb2cuY2pzJztcbmltcG9ydCB7IGV4ZWMgfSBmcm9tICcuL2V4ZWMuY2pzJztcbmltcG9ydCB7IGxvZyB9IGZyb20gJy4vbG9nLmNqcyc7XG5pbXBvcnQgeyBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQgfSBmcm9tICcuL25hbWVzcGFjZS1ib290c3RyYXAuY2pzJztcbmltcG9ydCB7XG4gIGdldFZhdWx0SWQsXG4gIGlzVmF1bHRSZWdpc3RlcmVkLFxuICByZW1vdmVWYXVsdEZyb21Db25maWdcbn0gZnJvbSAnLi9vYnNpZGlhbi1jb25maWcuY2pzJztcbmltcG9ydCB7IHJlc29sdmVPYnNpZGlhbkV4ZWN1dGFibGUgfSBmcm9tICcuL29ic2lkaWFuLWV4ZWN1dGFibGUuY2pzJztcbmltcG9ydCB7IGxhdW5jaE93bmVkT2JzaWRpYW5JbnN0YW5jZSB9IGZyb20gJy4vb2JzaWRpYW4taW5zdGFuY2UuY2pzJztcbmltcG9ydCB7IGNvcHlBc2FySW50b1VzZXJEYXRhIH0gZnJvbSAnLi9vYnNpZGlhbi12ZXJzaW9uLXN3aXRjaC5janMnO1xuaW1wb3J0IHsgZW5zdXJlTm9uTnVsbGFibGUgfSBmcm9tICcuL3R5cGUtZ3VhcmRzLmNqcyc7XG5pbXBvcnQge1xuICByZXNvbHZlT3duZWRIaWRkZW5MYXVuY2hBcmdzLFxuICBzaG91bGRIaWRlT2JzaWRpYW5BcHBcbn0gZnJvbSAnLi92aXNpYmlsaXR5LmNqcyc7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIENEUCB0cmFuc3BvcnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVza3RvcENkcFRyYW5zcG9ydENvbmZpZyB7XG4gIC8qKlxuICAgKiBDRFAgaG9zdC4gRGVmYXVsdHMgdG8gYCdsb2NhbGhvc3QnYC5cbiAgICovXG4gIGNkcEhvc3Q/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENEUCBwb3J0IGZvciAqKmF0dGFjaCoqIG1vZGUgKHRoZSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgIHRoZSBydW5uaW5nXG4gICAqIE9ic2lkaWFuIHdhcyBsYXVuY2hlZCB3aXRoKS4gSW4gb3duZWQtaW5zdGFuY2UgbW9kZSB0aGlzIGlzIGlnbm9yZWQgXHUyMDE0IGFcbiAgICogZnJlZSBwb3J0IGlzIGNob3NlbiBhdCBsYXVuY2guXG4gICAqL1xuICBjZHBQb3J0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3IgaW5kaXZpZHVhbCBDRFAgY29tbWFuZHMuXG4gICAqIERlZmF1bHRzIHRvIGAzMDAwMGAuXG4gICAqL1xuICBjb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBXaGVuIGF0dGFjaGluZyAoaS5lLiB7QGxpbmsgY2RwUG9ydH0gaXMgc2V0KSwgbWFya3MgdGhlIHRhcmdldCBhcyBhXG4gICAqICoqaGFybmVzcy1vd25lZCwgYWxyZWFkeS1wcmVwYXJlZCoqIGluc3RhbmNlLiBTdXBwcmVzc2VzIHRoZSB1c2VyLXNjb3BlXG4gICAqIHZhdWx0LXJlZ2lzdHJhdGlvbiBwcmVmbGlnaHQsIHNpbmNlIHRoZSBvd25lZCBpbnN0YW5jZSdzIHZhdWx0IGxpdmVzIGluIGFuXG4gICAqIGlzb2xhdGVkIHVzZXItZGF0YSBjb25maWcgcmF0aGVyIHRoYW4gdGhlIHVzZXItc2NvcGUgcmVnaXN0cnkuXG4gICAqL1xuICBpc0hhcm5lc3NPd25lZEluc3RhbmNlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgb3duZWQgT2JzaWRpYW4gd2luZG93IGlzIHNob3duIG9uIHNjcmVlbi4gV2hlbiBgZmFsc2VgICh0aGVcbiAgICogZGVmYXVsdCksIHRoZSBvd25lZCBpbnN0YW5jZSBpcyBsYXVuY2hlZCB3aXRoIGtlZXAtYWxpdmUgQ2hyb21pdW0gZmxhZ3MgYW5kXG4gICAqIGl0cyB3aW5kb3cgaXMgbW92ZWQgb2ZmLXNjcmVlbiBhZnRlciBsYXVuY2guIE9ubHkgbWVhbmluZ2Z1bCBpbiBvd25lZCBtb2RlO1xuICAgKiBhdHRhY2ggbW9kZSBuZXZlciB0b3VjaGVzIHRoZSAodXNlcidzKSB3aW5kb3cuXG4gICAqXG4gICAqIEBkZWZhdWx0IGBmYWxzZWBcbiAgICovXG4gIGlzT2JzaWRpYW5BcHBWaXNpYmxlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hlbiBzZXQsIHRoZSB0cmFuc3BvcnQgbGF1bmNoZXMgYW5kIG93bnMgYW4gaXNvbGF0ZWQgT2JzaWRpYW4gaW5zdGFuY2VcbiAgICogaW5zdGVhZCBvZiBhdHRhY2hpbmcgdG8gYSBydW5uaW5nIG9uZS4gVGhpcyBpcyB0aGUgZGVmYXVsdCBkZXNrdG9wIG1vZGUuXG4gICAqL1xuICBvd25lZEluc3RhbmNlPzogT3duZWRJbnN0YW5jZUNvbmZpZztcbn1cblxuLyoqXG4gKiBBbiBhc2FyIHRvIHByb3Zpc2lvbiBpbnRvIGEgaGFybmVzcy1vd25lZCBpbnN0YW5jZSdzIHVzZXItZGF0YSBkaXIgYmVmb3JlIGxhdW5jaC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPd25lZEluc3RhbmNlQXNhciB7XG4gIC8qKiBBYnNvbHV0ZSBwYXRoIHRvIHRoZSBjYWNoZWQvc291cmNlIGFzYXIgZmlsZS4gKi9cbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xuXG4gIC8qKiBUaGUgYXNhcidzIGB4LnkuemAgdmVyc2lvbi4gKi9cbiAgcmVhZG9ubHkgdmVyc2lvbjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIGEgaGFybmVzcy1vd25lZCwgaXNvbGF0ZWQgT2JzaWRpYW4gaW5zdGFuY2UuXG4gKlxuICogV2hlbiBwcmVzZW50LCB0aGUgdHJhbnNwb3J0IGxhdW5jaGVzIGFuZCBvd25zIGl0cyBvd24gT2JzaWRpYW4gcHJvY2Vzc1xuICogYWdhaW5zdCBhbiBpc29sYXRlZCB1c2VyLWRhdGEgZGlyIGluc3RlYWQgb2YgYXR0YWNoaW5nIHRvIGEgcnVubmluZyBpbnN0YW5jZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPd25lZEluc3RhbmNlQ29uZmlnIHtcbiAgLyoqIE9wdGlvbmFsIGFzYXIgdG8gcHJvdmlzaW9uIGludG8ge0BsaW5rIHVzZXJEYXRhRGlyfSBiZWZvcmUgbGF1bmNoLiAqL1xuICByZWFkb25seSBhc2FyPzogT3duZWRJbnN0YW5jZUFzYXIgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIEFic29sdXRlIHBhdGggdG8gdGhlIE9ic2lkaWFuIHNoZWxsIGV4ZWN1dGFibGUgdG8gbGF1bmNoLiAqL1xuICByZWFkb25seSBleGVQYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFic29sdXRlIHBhdGggdG8gdGhlIGlzb2xhdGVkIHVzZXItZGF0YSBkaXIuIENyZWF0ZWQgYW5kIG93bmVkIGJ5IHRoZVxuICAgKiB0cmFuc3BvcnQsIGFuZCBkZWxldGVkIG9uIGRpc3Bvc2UuXG4gICAqL1xuICByZWFkb25seSB1c2VyRGF0YURpcjogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ2RwRXhjZXB0aW9uRGV0YWlscyB7XG4gIGV4Y2VwdGlvbj86IENkcEV4Y2VwdGlvbk9iamVjdDtcbiAgdGV4dDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ2RwRXhjZXB0aW9uT2JqZWN0IHtcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBSZXNwb25zZSB7XG4gIGlkOiBudW1iZXI7XG4gIHJlc3VsdD86IENkcFJlc3BvbnNlUmVzdWx0O1xufVxuXG5pbnRlcmZhY2UgQ2RwUmVzcG9uc2VSZXN1bHQge1xuICByZWFkb25seSBleGNlcHRpb25EZXRhaWxzPzogQ2RwRXhjZXB0aW9uRGV0YWlscztcbiAgcmVhZG9ubHkgcmVzdWx0PzogQ2RwVmFsdWU7XG59XG5cbmludGVyZmFjZSBDZHBUYXJnZXQge1xuICBpZDogc3RyaW5nO1xuICB0aXRsZTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG4gIHVybDogc3RyaW5nO1xuICB3ZWJTb2NrZXREZWJ1Z2dlclVybDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ2RwVmFsdWUge1xuICB0eXBlOiBzdHJpbmc7XG4gIHZhbHVlPzogdW5rbm93bjtcbn1cblxuLyoqXG4gKiBUaGUgQ0RQIGVuZHBvaW50IG9mIGEgbGF1bmNoZWQsIGhhcm5lc3Mtb3duZWQgaW5zdGFuY2UuXG4gKi9cbmludGVyZmFjZSBPd25lZEluc3RhbmNlRW5kcG9pbnQge1xuICAvKiogQ0RQIGhvc3QgKGUuZy4gYCdsb2NhbGhvc3QnYCkuICovXG4gIHJlYWRvbmx5IGhvc3Q6IHN0cmluZztcblxuICAvKiogVGhlIGZyZWUgQ0RQIHBvcnQgdGhlIG93bmVkIGluc3RhbmNlIHdhcyBsYXVuY2hlZCBvbi4gKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG5jb25zdCBDT01NQU5EX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBWQVVMVF9JRF9CWVRFX0xFTkdUSCA9IDg7XG5jb25zdCBVU0VSX0RBVEFfUk1fVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAxMDAwMDtcbmNvbnN0IFVTRVJfREFUQV9STV9SRVRSWV9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSA1MDA7XG5jb25zdCBOT19PVVRQVVQgPSAnKG5vIG91dHB1dCknO1xuY29uc3QgVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSA1MDA7XG5jb25zdCBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBWQVVMVF9DTE9TRV9ERUxBWV9JTl9NSUxMSVNFQ09ORFMgPSAxMDAwO1xuY29uc3QgQVVUT19TVEFSVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDIwMDA7XG5jb25zdCBBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzAwMDA7XG5jb25zdCBJTlNUQU5DRV9FWElUX1NFVFRMRV9ERUxBWV9JTl9NSUxMSVNFQ09ORFMgPSA1MDA7XG5jb25zdCBPV05FRF9XSU5ET1dfT0ZGU0NSRUVOX01BUkdJTl9JTl9QSVhFTFMgPSAyMDA7XG5jb25zdCBPV05FRF9XSU5ET1dfSElERV9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDIwMDAwO1xuY29uc3QgT1dORURfV0lORE9XX0hJREVfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMgPSAyNTA7XG5cbi8qKlxuICogVHJhbnNwb3J0IHRoYXQgY29tbXVuaWNhdGVzIHdpdGggRGVza3RvcCBPYnNpZGlhbiB2aWEgQ2hyb21lIERldlRvb2xzIFByb3RvY29sLlxuICpcbiAqIENvbm5lY3RzIHRvIE9ic2lkaWFuJ3MgQ0RQIFdlYlNvY2tldCBlbmRwb2ludCwgc2VuZHMgYFJ1bnRpbWUuZXZhbHVhdGVgXG4gKiBjb21tYW5kcywgYW5kIHJvdXRlcyBleHByZXNzaW9ucyB0byB0aGUgY29ycmVjdCB2YXVsdCB0YXJnZXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXNrdG9wQ2RwVHJhbnNwb3J0IGltcGxlbWVudHMgT2JzaWRpYW5UcmFuc3BvcnQge1xuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhpcyB0cmFuc3BvcnQgaXMgZm9yIGEgbW9iaWxlIHBsYXRmb3JtLiBBbHdheXMgYGZhbHNlYCBmb3IgdGhpcyB0cmFuc3BvcnQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXNNb2JpbGUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBhY3RpdmVWYXVsdFBhdGg6IG51bGwgfCBzdHJpbmcgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkcEhvc3Q6IHN0cmluZztcbiAgcHJpdmF0ZSBjZHBQb3J0OiBudW1iZXI7XG4gIHByaXZhdGUgY2RwVXJsOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGlzSGFybmVzc093bmVkSW5zdGFuY2U6IGJvb2xlYW47XG4gIHByaXZhdGUgcmVhZG9ubHkgaXNPYnNpZGlhbkFwcFZpc2libGU6IGJvb2xlYW47XG4gIHByaXZhdGUgbWVzc2FnZUlkID0gMDtcbiAgcHJpdmF0ZSByZWFkb25seSBvd25lZENvbmZpZzogT3duZWRJbnN0YW5jZUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBvd25lZEluc3RhbmNlOiBPd25lZE9ic2lkaWFuSW5zdGFuY2UgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgd3M6IG51bGwgfCBXZWJTb2NrZXQgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IENEUCB0cmFuc3BvcnQuXG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBDRFAgY29ubmVjdGlvbiBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKGNvbmZpZz86IERlc2t0b3BDZHBUcmFuc3BvcnRDb25maWcpIHtcbiAgICB0aGlzLmNkcEhvc3QgPSBjb25maWc/LmNkcEhvc3QgPz8gJ2xvY2FsaG9zdCc7XG4gICAgdGhpcy5jb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzID0gY29uZmlnPy5jb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzID8/IENPTU1BTkRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgdGhpcy5pc0hhcm5lc3NPd25lZEluc3RhbmNlID0gY29uZmlnPy5pc0hhcm5lc3NPd25lZEluc3RhbmNlID8/IGZhbHNlO1xuICAgIHRoaXMuaXNPYnNpZGlhbkFwcFZpc2libGUgPSBjb25maWc/LmlzT2JzaWRpYW5BcHBWaXNpYmxlID8/IGZhbHNlO1xuICAgIHRoaXMub3duZWRDb25maWcgPSBjb25maWc/Lm93bmVkSW5zdGFuY2U7XG4gICAgLy8gT3duZWQgbW9kZSBwaWNrcyBhIGZyZWUgcG9ydCBhdCBsYXVuY2ggKGFzc2lnbmVkIGluIHJlZ2lzdGVyVmF1bHQpLlxuICAgIC8vIEF0dGFjaCBtb2RlIGNvbm5lY3RzIHRvIHRoZSBjb25maWd1cmVkIHBvcnQ7IG5vIHBvcnQgaXMgaGFyZGNvZGVkLlxuICAgIHRoaXMuY2RwUG9ydCA9IGNvbmZpZz8uY2RwUG9ydCA/PyAwO1xuICAgIHRoaXMuY2RwVXJsID0gY29uZmlnPy5jZHBQb3J0ID09PSB1bmRlZmluZWQgPyAnJyA6IGBodHRwOi8vJHt0aGlzLmNkcEhvc3R9OiR7U3RyaW5nKGNvbmZpZy5jZHBQb3J0KX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3Bvc2VzIG9mIHRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24gYW5kLCBpbiBvd25lZC1pbnN0YW5jZSBtb2RlLFxuICAgKiBraWxscyB0aGUgb3duZWQgT2JzaWRpYW4gcHJvY2VzcyBhbmQgcmVtb3ZlcyBpdHMgaXNvbGF0ZWQgdXNlci1kYXRhIGRpci5cbiAgICpcbiAgICogVGhlIHJlbW92YWwgaXMgcmV0cmllZCBiZWNhdXNlIFdpbmRvd3MgYnJpZWZseSBob2xkcyB0aGUganVzdC1raWxsZWRcbiAgICogcHJvY2VzcydzIGZpbGUgaGFuZGxlcywgd2hpY2ggd291bGQgb3RoZXJ3aXNlIGZhaWwgYHJtU3luY2Agd2l0aCBgRVBFUk1gLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgaWYgKCF0aGlzLm93bmVkQ29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5vd25lZEluc3RhbmNlPy5raWxsKCk7XG4gICAgY29uc3QgeyB1c2VyRGF0YURpciB9ID0gdGhpcy5vd25lZENvbmZpZztcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBVU0VSX0RBVEFfUk1fVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgaWYgKHRyeVJlbW92ZURpcih1c2VyRGF0YURpcikpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVVNFUl9EQVRBX1JNX1JFVFJZX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG4gICAgfVxuICAgIGlmICghdHJ5UmVtb3ZlRGlyKHVzZXJEYXRhRGlyKSkge1xuICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gQ291bGQgbm90IHJlbW92ZSBvd25lZCB1c2VyLWRhdGEgZGlyIHdpdGhpbiAke1N0cmluZyhVU0VSX0RBVEFfUk1fVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zIChub24tZmF0YWwpOiAke3VzZXJEYXRhRGlyfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTeW5jaHJvbm91cyBkaXNwb3NhbCBcdTIwMTQga2lsbHMgdGhlIG93bmVkIGluc3RhbmNlIGFuZCBtYWtlcyBhIGJlc3QtZWZmb3J0XG4gICAqIHJlbW92YWwgb2YgaXRzIHVzZXItZGF0YSBkaXIuIFNhZmUgdG8gY2FsbCBmcm9tIGEgcHJvY2VzcyBgZXhpdGAgaGFuZGxlclxuICAgKiAod2hlcmUgYXN5bmMgcmV0cmllcyBhcmUgaW1wb3NzaWJsZTsgYSBsZWZ0b3ZlciB0ZW1wIGRpciBpcyBhY2NlcHRhYmxlKS5cbiAgICovXG4gIHB1YmxpYyBkaXNwb3NlU3luYygpOiB2b2lkIHtcbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgICBpZiAodGhpcy5vd25lZENvbmZpZykge1xuICAgICAgdGhpcy5vd25lZEluc3RhbmNlPy5raWxsKCk7XG4gICAgICBpZiAoIXRyeVJlbW92ZURpcih0aGlzLm93bmVkQ29uZmlnLnVzZXJEYXRhRGlyKSkge1xuICAgICAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBPd25lZCB1c2VyLWRhdGEgZGlyIG5vdCByZW1vdmVkIHN5bmNocm9ub3VzbHkgKHByb2Nlc3MgbWF5IHN0aWxsIGhvbGQgaGFuZGxlcyk6ICR7dGhpcy5vd25lZENvbmZpZy51c2VyRGF0YURpcn1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXZhbHVhdGVzIGEgSmF2YVNjcmlwdCBleHByZXNzaW9uIGluc2lkZSBPYnNpZGlhbiB2aWEgQ0RQIGBSdW50aW1lLmV2YWx1YXRlYC5cbiAgICpcbiAgICogUm91dGVzIHRvIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldCBiYXNlZCBvbiBgb3B0aW9ucy5jd2RgLlxuICAgKlxuICAgKiBAcGFyYW0gZXhwcmVzc2lvbiAtIFRoZSBKYXZhU2NyaXB0IGV4cHJlc3Npb24gdG8gZXZhbHVhdGUuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gRXZhbHVhdGlvbiBvcHRpb25zLlxuICAgKiBAcmV0dXJucyBUaGUgbm9ybWFsaXplZCByZXN1bHQgc3RyaW5nLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGV2YWx1YXRlKGV4cHJlc3Npb246IHN0cmluZywgb3B0aW9uczogVHJhbnNwb3J0RXZhbE9wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5lbnN1cmVDb25uZWN0aW9uKG9wdGlvbnMuY3dkKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICB9KTtcblxuICAgIGlmIChyZXNwb25zZS5yZXN1bHQ/LmV4Y2VwdGlvbkRldGFpbHMpIHtcbiAgICAgIGNvbnN0IGRlc2MgPSByZXNwb25zZS5yZXN1bHQuZXhjZXB0aW9uRGV0YWlscy5leGNlcHRpb24/LmRlc2NyaXB0aW9uXG4gICAgICAgID8/IHJlc3BvbnNlLnJlc3VsdC5leGNlcHRpb25EZXRhaWxzLnRleHQ7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENEUCBldmFsdWF0aW9uIGVycm9yOiAke2Rlc2N9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0T2JqID0gcmVzcG9uc2UucmVzdWx0Py5yZXN1bHQ7XG4gICAgaWYgKCFyZXN1bHRPYmogfHwgcmVzdWx0T2JqLnR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gTk9fT1VUUFVUO1xuICAgIH1cblxuICAgIHJldHVybiBTdHJpbmcocmVzdWx0T2JqLnZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBDRFAgZW5kcG9pbnQgb2YgdGhlIG93bmVkLCBsYXVuY2hlZCBpbnN0YW5jZSBzbyB0aGUgZ2xvYmFsIHNldHVwXG4gICAqIGNhbiBoYW5kIGl0IHRvIHRlc3Qgd29ya2VycyAod2hpY2ggdGhlbiAqKmF0dGFjaCoqIHRvIGl0IGluc3RlYWQgb2ZcbiAgICogbGF1bmNoaW5nIHRoZWlyIG93bikuIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiB0aGlzIHRyYW5zcG9ydCBpcyBub3QgYW5cbiAgICogb3duZWQgaW5zdGFuY2UsIG9yIGl0cyBpbnN0YW5jZSBoYXMgbm90IGJlZW4gbGF1bmNoZWQgeWV0LlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgb3duZWQgaW5zdGFuY2UncyBDRFAgaG9zdCBhbmQgcG9ydCwgb3IgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBwdWJsaWMgZ2V0T3duZWRJbnN0YW5jZUVuZHBvaW50KCk6IE93bmVkSW5zdGFuY2VFbmRwb2ludCB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0aGlzLm93bmVkQ29uZmlnIHx8ICF0aGlzLm93bmVkSW5zdGFuY2UpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB7IGhvc3Q6IHRoaXMuY2RwSG9zdCwgcG9ydDogdGhpcy5jZHBQb3J0IH07XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpZXMgdGhhdCB0aGUgQ0RQIGVuZHBvaW50IGlzIHJlYWNoYWJsZSBhbmQgaGFzIE9ic2lkaWFuIHRhcmdldHMuXG4gICAqXG4gICAqIElmIE9ic2lkaWFuIGlzIG5vdCBydW5uaW5nLCBhdHRlbXB0cyB0byBhdXRvLXN0YXJ0IGl0IHZpYSBVUkkgcHJvdG9jb2xcbiAgICogYW5kIHBvbGxzIHVudGlsIENEUCBiZWNvbWVzIGF2YWlsYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSB2YXVsdCBwYXRoICh1c2VkIGZvciB2YXVsdCByZWdpc3RyYXRpb24gY2hlY2spLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHByZWZsaWdodENoZWNrKHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMub3duZWRDb25maWcgfHwgdGhpcy5pc0hhcm5lc3NPd25lZEluc3RhbmNlKSB7XG4gICAgICAvLyBPd25lZCBpbnN0YW5jZSAobGF1bmNoZWQgaGVyZSkgb3IgYSB3b3JrZXIgYXR0YWNoZWQgdG8gb25lOiByZWFkaW5lc3MgaXNcbiAgICAgIC8vIEd1YXJhbnRlZWQgYnkgdGhlIGdsb2JhbCBzZXR1cCdzIHJlZ2lzdGVyVmF1bHQsIGFuZCB0aGUgdmF1bHQgbGl2ZXMgaW5cbiAgICAgIC8vIFRoZSBpc29sYXRlZCBjb25maWcgXHUyMDE0IHRoZXJlIGlzIG5vdGhpbmcgdG8gdmVyaWZ5IGFnYWluc3QgdGhlIHVzZXItc2NvcGVcbiAgICAgIC8vIFJlZ2lzdHJ5LlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFJ1bm5pbmcgcHJlZmxpZ2h0IGNoZWNrIGZvciB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgaWYgKCFpc1ZhdWx0UmVnaXN0ZXJlZCh2YXVsdFBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBWYXVsdCBpcyBub3QgcmVnaXN0ZXJlZCBpbiBPYnNpZGlhbjogJHt2YXVsdFBhdGh9LiBSZWdpc3RlciB0aGUgdmF1bHQgZmlyc3Qgd2l0aCByZWdpc3RlclZhdWx0KCkgb3IgVGVtcFZhdWx0LnJlZ2lzdGVyKCkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHBhZ2UgdGFyZ2V0cycpO1xuICAgICAgfVxuICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gQ0RQIHJlYWNoYWJsZSwgJHtTdHJpbmcodGFyZ2V0cy5sZW5ndGgpfSB0YXJnZXQocykgZm91bmQuYCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZU9ic2lkaWFuUnVubmluZygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSB2YXVsdCB2aWEgRWxlY3Ryb24gSVBDIGV2YWx1YXRlZCB0aHJvdWdoIENEUC5cbiAgICpcbiAgICogVXNlcyBhbiBleGlzdGluZyBPYnNpZGlhbiB0YXJnZXQgdG8gc2VuZCB0aGUgYHZhdWx0LW9wZW5gIElQQyBjb21tYW5kLFxuICAgKiB0aGVuIHBvbGxzIHVudGlsIHRoZSBuZXcgdmF1bHQncyB0YXJnZXQgYXBwZWFycy5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm93bmVkQ29uZmlnKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyVmF1bHRJbk93bmVkSW5zdGFuY2UodmF1bHRQYXRoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLm9wZW5WYXVsdEluUnVubmluZ0luc3RhbmNlKHZhdWx0UGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogVW5yZWdpc3RlcnMgYSB2YXVsdCBieSBkZXN0cm95aW5nIGl0cyB3aW5kb3cgYW5kIHJlbW92aW5nIGl0IGZyb20gdGhlIHJlZ2lzdHJ5LlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB1bnJlZ2lzdGVyVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5vd25lZENvbmZpZykge1xuICAgICAgLy8gVGhlIG93bmVkIGluc3RhbmNlIGlzIGtpbGxlZCB3aG9sZXNhbGUgb24gZGlzcG9zZTsgbm8gcGVyLXZhdWx0XG4gICAgICAvLyBVbnJlZ2lzdGVyIGlzIG5lZWRlZCAoYW5kIHRoZSByZWdpc3RyeSBsaXZlcyBpbiB0aGUgaXNvbGF0ZWQgY29uZmlnKS5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkKHRoaXMsIHZhdWx0UGF0aCk7XG4gICAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGgpO1xuICAgICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZGVzdHJveUV4cHIgPSAnd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuZGVzdHJveUN1cnJlbnRXaW5kb3coKSc7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgICAgICBleHByZXNzaW9uOiBkZXN0cm95RXhwcixcbiAgICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFdpbmRvdyBtYXkgYWxyZWFkeSBiZSBjbG9zZWQuXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYWN0aXZlVmF1bHRQYXRoID09PSB2YXVsdFBhdGgpIHtcbiAgICAgIHRoaXMuZGlzY29ubmVjdCgpO1xuICAgIH1cblxuICAgIGF3YWl0IGRlbGF5KFZBVUxUX0NMT1NFX0RFTEFZX0lOX01JTExJU0VDT05EUyk7XG5cbiAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgdGhpcy5nZXRQYWdlVGFyZ2V0cygpO1xuICAgIGlmICh0YXJnZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQoZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSkpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkKHRoaXMsIHZhdWx0UGF0aCk7XG4gICAgICAgIGNvbnN0IHJlbW92ZUV4cHIgPSBgd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuaXBjU2VuZFN5bmMoJHtKU09OLnN0cmluZ2lmeSh7IGFyZ3M6IFt2YXVsdFBhdGhdLCBjaGFubmVsOiAndmF1bHQtcmVtb3ZlJyB9KX0pYDtcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgICAgIGV4cHJlc3Npb246IHJlbW92ZUV4cHIsXG4gICAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIE5vIENEUCB0YXJnZXRzIGZvciByZW1vdmFsIElQQyBcdTIwMTQgcmVtb3ZpbmcgZGlyZWN0bHkgZnJvbSBvYnNpZGlhbi5qc29uLicpO1xuICAgICAgcmVtb3ZlVmF1bHRGcm9tQ29uZmlnKHZhdWx0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3RzIHRvIGEgQ0RQIHRhcmdldCdzIFdlYlNvY2tldCBlbmRwb2ludC5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCAtIFRoZSBDRFAgdGFyZ2V0IHRvIGNvbm5lY3QgdG8uXG4gICAqIEByZXR1cm5zIFRoZSBvcGVuIFdlYlNvY2tldCBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb25uZWN0VG9UYXJnZXQodGFyZ2V0OiBDZHBUYXJnZXQpOiBQcm9taXNlPFdlYlNvY2tldD4ge1xuICAgIGNvbnN0IHdzID0gbmV3IFdlYlNvY2tldCh0YXJnZXQud2ViU29ja2V0RGVidWdnZXJVcmwpO1xuICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHdzLm9ub3BlbiA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfTtcbiAgICAgIHdzLm9uZXJyb3IgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBjb25uZWN0IHRvIENEUCB0YXJnZXQ6ICR7dGFyZ2V0LndlYlNvY2tldERlYnVnZ2VyVXJsfWApKTtcbiAgICAgIH07XG4gICAgfSk7XG4gICAgcmV0dXJuIHdzO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc2Nvbm5lY3RzIHRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMud3M/LnJlYWR5U3RhdGUgPT09IFdlYlNvY2tldC5PUEVOKSB7XG4gICAgICB0aGlzLndzLmNsb3NlKCk7XG4gICAgfVxuICAgIHRoaXMud3MgPSBudWxsO1xuICAgIHRoaXMuYWN0aXZlVmF1bHRQYXRoID0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNtaXNzZXMgdGhlIFwiRG8geW91IHRydXN0IHRoZSBhdXRob3Igb2YgdGhpcyB2YXVsdD9cIiBkaWFsb2cgaWYgcHJlc2VudC5cbiAgICpcbiAgICogQWN0cyBhcyBhIHNhZmV0eSBuZXQgd2hlbiBgZW5hYmxlLXBsdWdpbi08aWQ+YCBpcyB3cml0dGVuIGluIG9uZSByZW5kZXJlclxuICAgKiBidXQgbm90IHlldCB2aXNpYmxlIHRvIHRoZSBuZXdseS1vcGVuZWQgdmF1bHQncyByZW5kZXJlciAocmFjZSBvYnNlcnZlZFxuICAgKiBpbiBPYnNpZGlhbiAxLjEzLjApLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gZXZhbHVhdGUgaW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGRpc21pc3NUcnVzdERpYWxvZyh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXZhbHVhdGUoRElTTUlTU19UUlVTVF9ESUFMT0dfRVhQUiwgeyBjd2Q6IHZhdWx0UGF0aCB9KTtcbiAgICBpZiAocmVzdWx0ID09PSAndHJ1ZScpIHtcbiAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIERpc21pc3NlZCBcIkRvIHlvdSB0cnVzdCB0aGUgYXV0aG9yXCIgZGlhbG9nLicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBlbmFibGUtcGx1Z2luLTx2YXVsdElkPmAgaW4gT2JzaWRpYW4ncyBsb2NhbFN0b3JhZ2UgdG8gcHJldmVudFxuICAgKiB0aGUgXCJEbyB5b3UgdHJ1c3QgdGhlIGF1dGhvciBvZiB0aGlzIHZhdWx0P1wiIGRpYWxvZyBmcm9tIGFwcGVhcmluZ1xuICAgKiB3aGVuIGEgdmF1bHQgd2l0aCBjb21tdW5pdHkgcGx1Z2lucyBpcyBvcGVuZWQgZm9yIHRoZSBmaXJzdCB0aW1lLlxuICAgKlxuICAgKiBNdXN0IGJlIGNhbGxlZCBhZnRlciB0aGUgYHZhdWx0LW9wZW5gIElQQyAoc28gdGhlIHZhdWx0IElEIGV4aXN0cyBpblxuICAgKiBgb2JzaWRpYW4uanNvbmApIGFuZCBiZWZvcmUgdGhlIG5ldyB2YXVsdCB3aW5kb3cgZmluaXNoZXMgbG9hZGluZy5cbiAgICpcbiAgICogQHBhcmFtIHdzIC0gQW4gb3BlbiBXZWJTb2NrZXQgdG8gYW4gZXhpc3RpbmcgT2JzaWRpYW4gdGFyZ2V0LlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5hYmxlUGx1Z2luc0luTG9jYWxTdG9yYWdlKHdzOiBXZWJTb2NrZXQsIHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdmF1bHRJZCA9IGdldFZhdWx0SWQodmF1bHRQYXRoKTtcbiAgICBpZiAoIXZhdWx0SWQpIHtcbiAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIENvdWxkIG5vdCBmaW5kIHZhdWx0IElEIFx1MjAxNCBza2lwcGluZyBsb2NhbFN0b3JhZ2UgdHJ1c3QgZmxhZy4nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgIGV4cHJlc3Npb246IGBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgke0pTT04uc3RyaW5naWZ5KGBlbmFibGUtcGx1Z2luLSR7dmF1bHRJZH1gKX0sICd0cnVlJyk7YCxcbiAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICB9KTtcbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBTZXQgZW5hYmxlLXBsdWdpbi0ke3ZhdWx0SWR9IGluIGxvY2FsU3RvcmFnZS5gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmVzIHRoZXJlIGlzIGFuIGFjdGl2ZSBXZWJTb2NrZXQgY29ubmVjdGlvbiB0byB0aGUgY29ycmVjdCB2YXVsdCB0YXJnZXQuXG4gICAqXG4gICAqIFJldXNlcyB0aGUgZXhpc3RpbmcgY29ubmVjdGlvbiBpZiBpdCB0YXJnZXRzIHRoZSByZXF1ZXN0ZWQgdmF1bHQuXG4gICAqIE90aGVyd2lzZSwgZmluZHMgdGhlIGNvcnJlY3QgdGFyZ2V0IGFuZCByZWNvbm5lY3RzLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gdGFyZ2V0LlxuICAgKiBAcmV0dXJucyBUaGUgYWN0aXZlIFdlYlNvY2tldCBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVDb25uZWN0aW9uKHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTxXZWJTb2NrZXQ+IHtcbiAgICBpZiAodGhpcy53cz8ucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4gJiYgdGhpcy5hY3RpdmVWYXVsdFBhdGggPT09IHZhdWx0UGF0aCkge1xuICAgICAgcmV0dXJuIHRoaXMud3M7XG4gICAgfVxuXG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG5cbiAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGgpO1xuICAgIHRoaXMud3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgIHRoaXMuYWN0aXZlVmF1bHRQYXRoID0gdmF1bHRQYXRoO1xuICAgIHJldHVybiB0aGlzLndzO1xuICB9XG5cbiAgLyoqXG4gICAqIExhdW5jaGVzIE9ic2lkaWFuIHdpdGggYC0tcmVtb3RlLWRlYnVnZ2luZy1wb3J0YCBhbmQgcG9sbHMgdW50aWwgQ0RQIGJlY29tZXMgYXZhaWxhYmxlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVPYnNpZGlhblJ1bm5pbmcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gT2JzaWRpYW4gQ0RQIG5vdCByZWFjaGFibGUuIFN0YXJ0aW5nIE9ic2lkaWFuIHdpdGggcmVtb3RlIGRlYnVnZ2luZy4uLicpO1xuXG4gICAgY29uc3QgbGF1bmNoQ29tbWFuZCA9IGF3YWl0IGdldE9ic2lkaWFuTGF1bmNoQ29tbWFuZCh0aGlzLmNkcFBvcnQpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBleGVjKGxhdW5jaENvbW1hbmQsIHsgaXNRdWlldDogdHJ1ZSB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFRoZSBsYXVuY2ggY29tbWFuZCBtYXkgZmFpbCBvbiBzb21lIHN5c3RlbXMgXHUyMDE0IHdlJ2xsIHN0aWxsIHRyeSBwb2xsaW5nLlxuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFBvbGxpbmcgZm9yIENEUCBlbmRwb2ludCBhdCAke3RoaXMuY2RwVXJsfSAodGltZW91dD0ke1N0cmluZyhBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcykuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGF3YWl0IGRlbGF5KEFVVE9fU1RBUlRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgICAgaWYgKHRhcmdldHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIE9ic2lkaWFuIENEUCByZWFkeSwgJHtTdHJpbmcodGFyZ2V0cy5sZW5ndGgpfSB0YXJnZXQocykgZm91bmQuYCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gQ0RQIG5vdCByZWFkeSB5ZXQsIHJldHJ5aW5nLi4uJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBPYnNpZGlhbiBkaWQgbm90IHN0YXJ0IHdpdGhpbiAke1N0cmluZyhBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcy4gRW5zdXJlIE9ic2lkaWFuIGlzIGluc3RhbGxlZCBhbmQgYWNjZXNzaWJsZS5gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgQ0RQIHRhcmdldCB0aGF0IGhhcyB0aGUgZ2l2ZW4gdmF1bHQgb3Blbi5cbiAgICpcbiAgICogRm9yIGEgc2luZ2xlIHRhcmdldCwgcmV0dXJucyBpdCBkaXJlY3RseS4gRm9yIG11bHRpcGxlIHRhcmdldHMsXG4gICAqIHByb2JlcyBlYWNoIGJ5IGV2YWx1YXRpbmcgYGdldEJhc2VQYXRoKClgIHRvIGZpbmQgdGhlIG1hdGNoLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gbWF0Y2guXG4gICAqIEByZXR1cm5zIFRoZSBtYXRjaGluZyBDRFAgdGFyZ2V0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmaW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPENkcFRhcmdldD4ge1xuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG5cbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgZm91bmQnKTtcbiAgICB9XG5cbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBlbnN1cmVOb25OdWxsYWJsZSh0YXJnZXRzWzBdKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHRhcmdldCBvZiB0YXJnZXRzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBiYXNlUGF0aCA9IGF3YWl0IHRoaXMucHJvYmVWYXVsdFBhdGgodGFyZ2V0KTtcbiAgICAgICAgaWYgKGJhc2VQYXRoID09PSB2YXVsdFBhdGgpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gTm90IGEgdmF1bHQgdGFyZ2V0IG9yIG5vdCByZWFkeS5cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIENEUCB0YXJnZXQgZm91bmQgZm9yIHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaGVzIHRoZSBsaXN0IG9mIHBhZ2UtdHlwZSB0YXJnZXRzIGZyb20gdGhlIENEUCBgL2pzb25gIGVuZHBvaW50LlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgbGlzdCBvZiBwYWdlIHRhcmdldHMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFBhZ2VUYXJnZXRzKCk6IFByb21pc2U8Q2RwVGFyZ2V0W10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGAke3RoaXMuY2RwVXJsfS9qc29uYCk7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKSBhcyBDZHBUYXJnZXRbXTtcbiAgICByZXR1cm4gdGFyZ2V0cy5maWx0ZXIoKHQpID0+IHQudHlwZSA9PT0gJ3BhZ2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlcyB0aGUgb3duZWQgaW5zdGFuY2UncyB3aW5kb3cgb2ZmLXNjcmVlbiBzbyBhIGhpZGRlbiBydW4gbmV2ZXIgc3RlYWxzXG4gICAqIGZvY3VzLiBVc2VzIEVsZWN0cm9uJ3MgcmVtb3RlIGJyaWRnZSAoYHdpbmRvdy5lbGVjdHJvbi5yZW1vdGVgKSBcdTIwMTQgdGhlIG9ubHlcbiAgICogY3Jvc3MtcGxhdGZvcm0gd2F5IHRvIHJlcG9zaXRpb24gdGhlIHdpbmRvdyBcdTIwMTQgcGxhY2luZyBpdCBqdXN0IGJleW9uZCB0aGVcbiAgICogcmlnaHQgZWRnZSBvZiBhbGwgZGlzcGxheXMuIFRoZSB3aW5kb3cgc3RheXMgXCJ2aXNpYmxlXCIgdG8gQ2hyb21pdW0gKHNvXG4gICAqIHRpbWVycywgYHJlcXVlc3RBbmltYXRpb25GcmFtZWAsIGA6aG92ZXJgLCBhbmQgdHJ1c3RlZCBpbnB1dCBrZWVwIHdvcmtpbmcpLFxuICAgKiB1bmxpa2UgbWluaW1pemluZywgd2hpY2ggd291bGQgZnJlZXplIGByZXF1ZXN0QW5pbWF0aW9uRnJhbWVgLlxuICAgKlxuICAgKiBUaGUgcmVtb3RlIGJyaWRnZSBpcyBub3QgYXZhaWxhYmxlIHRoZSBpbnN0YW50IENEUCBzdGFydHMgc2VydmluZywgc28gdGhpc1xuICAgKiBwb2xscyB1bnRpbCB0aGUgbW92ZSBzdWNjZWVkcy4gQmVzdC1lZmZvcnQ6IGlmIHRoZSB3aW5kb3cgY2Fubm90IGJlIG1vdmVkXG4gICAqIHdpdGhpbiB0aGUgdGltZW91dCwgdGhlIGtlZXAtYWxpdmUgbGF1bmNoIGZsYWdzIHN0aWxsIGFwcGx5IGFuZCB0aGUgcnVuXG4gICAqIHByb2NlZWRzICh3b3JzdCBjYXNlIHRoZSB3aW5kb3cgaXMgYnJpZWZseSB2aXNpYmxlKS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgbW92ZU93bmVkV2luZG93T2Zmc2NyZWVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1vdmVFeHByID0gYCgoKSA9PiB7XG4gICAgICBjb25zdCByZW1vdGUgPSB3aW5kb3cuZWxlY3Ryb24gJiYgd2luZG93LmVsZWN0cm9uLnJlbW90ZTtcbiAgICAgIGlmICghcmVtb3RlIHx8IHR5cGVvZiByZW1vdGUuZ2V0Q3VycmVudFdpbmRvdyAhPT0gJ2Z1bmN0aW9uJykgeyByZXR1cm4gJ25vLWJyaWRnZSc7IH1cbiAgICAgIGNvbnN0IHdpbiA9IHJlbW90ZS5nZXRDdXJyZW50V2luZG93KCk7XG4gICAgICBjb25zdCBkaXNwbGF5cyA9IHJlbW90ZS5zY3JlZW4uZ2V0QWxsRGlzcGxheXMoKTtcbiAgICAgIGNvbnN0IG1heFJpZ2h0ID0gTWF0aC5tYXgoLi4uZGlzcGxheXMubWFwKChkaXNwbGF5KSA9PiBkaXNwbGF5LmJvdW5kcy54ICsgZGlzcGxheS5ib3VuZHMud2lkdGgpKTtcbiAgICAgIHdpbi5zZXRQb3NpdGlvbihtYXhSaWdodCArICR7U3RyaW5nKE9XTkVEX1dJTkRPV19PRkZTQ1JFRU5fTUFSR0lOX0lOX1BJWEVMUyl9LCAwKTtcbiAgICAgIHJldHVybiAnbW92ZWQnO1xuICAgIH0pKClgO1xuXG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgT1dORURfV0lORE9XX0hJREVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gKGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKSlbMF07XG4gICAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgICAgICAgIGV4cHJlc3Npb246IG1vdmVFeHByLFxuICAgICAgICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5yZXN1bHQ/LnJlc3VsdD8udmFsdWUgPT09ICdtb3ZlZCcpIHtcbiAgICAgICAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gTW92ZWQgb3duZWQgT2JzaWRpYW4gd2luZG93IG9mZi1zY3JlZW4gKGhpZGRlbiBtb2RlKS4nKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIENEUCBlbmRwb2ludCAvIHRhcmdldCAvIHJlbW90ZSBicmlkZ2Ugbm90IHJlYWR5IHlldCBcdTIwMTQga2VlcCBwb2xsaW5nLlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoT1dORURfV0lORE9XX0hJREVfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBDb3VsZCBub3QgbW92ZSBvd25lZCB3aW5kb3cgb2ZmLXNjcmVlbiB3aXRoaW4gJHtTdHJpbmcoT1dORURfV0lORE9XX0hJREVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zIChub24tZmF0YWw7IGtlZXAtYWxpdmUgZmxhZ3Mgc3RpbGwgYXBwbGllZCkuYCk7XG4gIH1cblxuICAvKipcbiAgICogT3BlbnMgYSB2YXVsdCBpbiBhbiBhbHJlYWR5LXJ1bm5pbmcgT2JzaWRpYW4gaW5zdGFuY2UgdmlhIHRoZSBgdmF1bHQtb3BlbmBcbiAgICogRWxlY3Ryb24gSVBDIChldmFsdWF0ZWQgdGhyb3VnaCBDRFAgb24gYW4gZXhpc3RpbmcgdGFyZ2V0KSwgdGhlbiBwb2xscyB1bnRpbFxuICAgKiB0aGUgbmV3IHZhdWx0J3Mgd2luZG93IHRhcmdldCBhcHBlYXJzLCBpcyBsYXlvdXQtcmVhZHksIGFuZCBpdHMgdHJ1c3QgZGlhbG9nXG4gICAqIChpZiBhbnkpIGhhcyBiZWVuIGRpc21pc3NlZC5cbiAgICpcbiAgICogU2hhcmVkIGJ5IHRoZSBhdHRhY2gtbW9kZSB7QGxpbmsgcmVnaXN0ZXJWYXVsdH0gYW5kIHRoZSBvd25lZC1tb2RlXG4gICAqIFwiaW5zdGFuY2UgYWxyZWFkeSBsYXVuY2hlZFwiIHBhdGgsIHNvIG9wZW5pbmcgYW4gYWRkaXRpb25hbCB2YXVsdCBuZXZlclxuICAgKiByZWxhdW5jaGVzIHRoZSBwcm9jZXNzICh3aGljaCB3b3VsZCBzdXJmYWNlIHRoZSB2YXVsdCBwaWNrZXIpLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgb3BlblZhdWx0SW5SdW5uaW5nSW5zdGFuY2UodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBSZWdpc3RlcmluZyB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgYXZhaWxhYmxlLiBJcyBPYnNpZGlhbiBydW5uaW5nPycpO1xuICAgIH1cblxuICAgIGNvbnN0IGlwY1dzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQoZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSkpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQodGhpcywgdmF1bHRQYXRoKTtcbiAgICAgIGNvbnN0IGlwY0V4cHIgPSBgd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuaXBjU2VuZFN5bmMoJHtKU09OLnN0cmluZ2lmeSh7IGFyZ3M6IFt2YXVsdFBhdGgsIGZhbHNlXSwgY2hhbm5lbDogJ3ZhdWx0LW9wZW4nIH0pfSlgO1xuICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZChpcGNXcywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgICAgZXhwcmVzc2lvbjogaXBjRXhwcixcbiAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMuZW5hYmxlUGx1Z2luc0luTG9jYWxTdG9yYWdlKGlwY1dzLCB2YXVsdFBhdGgpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpcGNXcy5jbG9zZSgpO1xuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFBvbGxpbmcgZm9yIHZhdWx0IHRhcmdldCAodGltZW91dD0ke1N0cmluZyhWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcykuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIFZhdWx0IHRhcmdldCBmb3VuZC4nKTtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yTGF5b3V0UmVhZHkodmF1bHRQYXRoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNtaXNzVHJ1c3REaWFsb2codmF1bHRQYXRoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFZhdWx0IHRhcmdldCBub3QgcmVhZHkgeWV0LlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFZhdWx0IGF0ICR7dmF1bHRQYXRofSBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcoVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXNgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9iZXMgYSB0YXJnZXQgdG8gZGlzY292ZXIgd2hpY2ggdmF1bHQgcGF0aCBpdCBoYXMgb3Blbi5cbiAgICpcbiAgICogQ3JlYXRlcyBhIHRlbXBvcmFyeSBXZWJTb2NrZXQgY29ubmVjdGlvbiwgZXZhbHVhdGVzIGBnZXRCYXNlUGF0aCgpYCxcbiAgICogYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCAtIFRoZSBDRFAgdGFyZ2V0IHRvIHByb2JlLlxuICAgKiBAcmV0dXJucyBUaGUgdmF1bHQncyBiYXNlIHBhdGguXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByb2JlVmF1bHRQYXRoKHRhcmdldDogQ2RwVGFyZ2V0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgIGV4cHJlc3Npb246ICdhcHAudmF1bHQuYWRhcHRlci5nZXRCYXNlUGF0aCgpJyxcbiAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gU3RyaW5nKHJlc3BvbnNlLnJlc3VsdD8ucmVzdWx0Py52YWx1ZSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdzLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExhdW5jaGVzIGFuZCBjb25uZWN0cyB0byBhIGhhcm5lc3Mtb3duZWQsIGlzb2xhdGVkIE9ic2lkaWFuIGluc3RhbmNlIGZvciBhXG4gICAqIHZhdWx0OiBwcm92aXNpb25zIHRoZSBhc2FyIChpZiBhbnkpLCBwcmUtc2VlZHMgdGhlIGlzb2xhdGVkIGBvYnNpZGlhbi5qc29uYFxuICAgKiBzbyB0aGUgdmF1bHQgb3BlbnMgZGlyZWN0bHksIGxhdW5jaGVzIHRoZSBpbnN0YW5jZSBvbiBhIGZyZWUgQ0RQIHBvcnQsIHRoZW5cbiAgICogd2FpdHMgdW50aWwgdGhlIHZhdWx0IHdpbmRvdyBpcyByZWFkeSBhbmQgZGlzbWlzc2VzIHRoZSB0cnVzdCBkaWFsb2cuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgZm9sZGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlclZhdWx0SW5Pd25lZEluc3RhbmNlKHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29uZmlnID0gZW5zdXJlTm9uTnVsbGFibGUodGhpcy5vd25lZENvbmZpZyk7XG5cbiAgICBpZiAodGhpcy5vd25lZEluc3RhbmNlKSB7XG4gICAgICAvLyBBIHByaW9yIHZhdWx0J3MgaW5zdGFuY2UgaXMgc3RpbGwgcnVubmluZyBpbiB0aGlzIChwZXItd29ya2VyIGNhY2hlZClcbiAgICAgIC8vIFRyYW5zcG9ydC4gUmVsYXVuY2ggZnJlc2ggZm9yIHRoZSBuZXcgdmF1bHQ6IHJlbGF1bmNoaW5nIG92ZXIgdGhlIGxpdmVcbiAgICAgIC8vIEluc3RhbmNlIGlzIGZvcndhcmRlZCBieSBFbGVjdHJvbidzIHNpbmdsZS1pbnN0YW5jZSBsb2NrIG9uIHRoZSBzaGFyZWRcbiAgICAgIC8vIFVzZXItZGF0YSBkaXIgYW5kIHN1cmZhY2VzIHRoZSB2YXVsdCBwaWNrZXIsIGFuZCBvcGVuaW5nIGEgc2Vjb25kIHdpbmRvd1xuICAgICAgLy8gVmlhIElQQyBsZWF2ZXMgc3RhbGUgd2luZG93cyB0aGF0IGJyZWFrIHZhdWx0LXRhcmdldCByb3V0aW5nLiBTbyBraWxsIHRoZVxuICAgICAgLy8gUnVubmluZyBpbnN0YW5jZSwgd2FpdCBmb3IgaXQgdG8gZXhpdCAocmVsZWFzaW5nIHRoZSBsb2NrKSwgdGhlbiBsYXVuY2hcbiAgICAgIC8vIEFnYWluIGJlbG93IHdpdGggdGhlIG5ldyB2YXVsdCBwcmUtc2VlZGVkIFx1MjAxNCBlYWNoIHZhdWx0IGdldHMgYSBwcmlzdGluZVxuICAgICAgLy8gU2luZ2xlLXdpbmRvdyBpbnN0YW5jZSBvcGVuZWQgZGlyZWN0bHksIG5ldmVyIHRoZSBzZWxlY3Rvci5cbiAgICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFJlbGF1bmNoaW5nIG93bmVkIGluc3RhbmNlIGZvciBuZXcgdmF1bHQ6ICR7dmF1bHRQYXRofWApO1xuICAgICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgICBjb25zdCBwcmV2aW91c0NkcFVybCA9IHRoaXMuY2RwVXJsO1xuICAgICAgdGhpcy5vd25lZEluc3RhbmNlLmtpbGwoKTtcbiAgICAgIHRoaXMub3duZWRJbnN0YW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgIGF3YWl0IHRoaXMud2FpdEZvckluc3RhbmNlRXhpdChwcmV2aW91c0NkcFVybCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIExhdW5jaGluZyBvd25lZCBPYnNpZGlhbiBpbnN0YW5jZSBmb3IgdmF1bHQ6ICR7dmF1bHRQYXRofWApO1xuICAgIH1cblxuICAgIG1rZGlyU3luYyhjb25maWcudXNlckRhdGFEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGlmIChjb25maWcuYXNhcikge1xuICAgICAgY29weUFzYXJJbnRvVXNlckRhdGEoY29uZmlnLmFzYXIucGF0aCwgY29uZmlnLmFzYXIudmVyc2lvbiwgY29uZmlnLnVzZXJEYXRhRGlyKTtcbiAgICB9XG5cbiAgICBjb25zdCB2YXVsdElkID0gcmFuZG9tQnl0ZXMoVkFVTFRfSURfQllURV9MRU5HVEgpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBvYnNpZGlhbkpzb24gPSB7XG4gICAgICB1cGRhdGVEaXNhYmxlZDogdHJ1ZSxcbiAgICAgIHZhdWx0czogeyBbdmF1bHRJZF06IHsgb3BlbjogdHJ1ZSwgcGF0aDogdmF1bHRQYXRoLCB0czogRGF0ZS5ub3coKSB9IH1cbiAgICB9O1xuICAgIHdyaXRlRmlsZVN5bmMoam9pbihjb25maWcudXNlckRhdGFEaXIsICdvYnNpZGlhbi5qc29uJyksIEpTT04uc3RyaW5naWZ5KG9ic2lkaWFuSnNvbikpO1xuXG4gICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBsYXVuY2hPd25lZE9ic2lkaWFuSW5zdGFuY2Uoe1xuICAgICAgY2RwSG9zdDogdGhpcy5jZHBIb3N0LFxuICAgICAgZXhlUGF0aDogY29uZmlnLmV4ZVBhdGgsXG4gICAgICBleHRyYUFyZ3M6IHJlc29sdmVPd25lZEhpZGRlbkxhdW5jaEFyZ3ModGhpcy5pc09ic2lkaWFuQXBwVmlzaWJsZSksXG4gICAgICB1c2VyRGF0YURpcjogY29uZmlnLnVzZXJEYXRhRGlyXG4gICAgfSk7XG4gICAgdGhpcy5vd25lZEluc3RhbmNlID0gaW5zdGFuY2U7XG4gICAgdGhpcy5jZHBQb3J0ID0gaW5zdGFuY2UucG9ydDtcbiAgICB0aGlzLmNkcFVybCA9IGluc3RhbmNlLmNkcFVybDtcblxuICAgIGlmIChzaG91bGRIaWRlT2JzaWRpYW5BcHAodGhpcy5pc09ic2lkaWFuQXBwVmlzaWJsZSkpIHtcbiAgICAgIGF3YWl0IHRoaXMubW92ZU93bmVkV2luZG93T2Zmc2NyZWVuKCk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy53YWl0Rm9yT3duZWRWYXVsdFJlYWR5KHZhdWx0UGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgYSBDRFAgY29tbWFuZCBvdmVyIFdlYlNvY2tldCBhbmQgd2FpdHMgZm9yIHRoZSByZXNwb25zZS5cbiAgICpcbiAgICogQHBhcmFtIHdzIC0gVGhlIFdlYlNvY2tldCBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0gbWV0aG9kIC0gVGhlIENEUCBtZXRob2QgbmFtZS5cbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBDRFAgbWV0aG9kIHBhcmFtZXRlcnMuXG4gICAqIEByZXR1cm5zIFRoZSBDRFAgcmVzcG9uc2UuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNlbmRDb21tYW5kKHdzOiBXZWJTb2NrZXQsIG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogUHJvbWlzZTxDZHBSZXNwb25zZT4ge1xuICAgIGNvbnN0IGlkID0gKyt0aGlzLm1lc3NhZ2VJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTxDZHBSZXNwb25zZT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB3cy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgaGFuZGxlcik7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYENEUCBjb21tYW5kIHRpbWVkIG91dCBhZnRlciAke1N0cmluZyh0aGlzLmNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHMpfW1zOiAke21ldGhvZH1gKSk7XG4gICAgICB9LCB0aGlzLmNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHMpO1xuXG4gICAgICBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBNZXNzYWdlRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbXNnID0gSlNPTi5wYXJzZShTdHJpbmcoZXZlbnQuZGF0YSkpIGFzIENkcFJlc3BvbnNlO1xuICAgICAgICBpZiAobXNnLmlkID09PSBpZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICB3cy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgaGFuZGxlcik7XG4gICAgICAgICAgcmVzb2x2ZShtc2cpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHdzLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBoYW5kbGVyKTtcbiAgICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkoeyBpZCwgbWV0aG9kLCBwYXJhbXMgfSkpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvbGxzIGEga2lsbGVkIG93bmVkIGluc3RhbmNlJ3MgQ0RQIGVuZHBvaW50IHVudGlsIGl0IHN0b3BzIHJlc3BvbmRpbmcsXG4gICAqIGNvbmZpcm1pbmcgdGhlIHByb2Nlc3MgaGFzIGV4aXRlZCBhbmQgcmVsZWFzZWQgRWxlY3Ryb24ncyBzaW5nbGUtaW5zdGFuY2VcbiAgICogbG9jayBvbiB0aGUgc2hhcmVkIHVzZXItZGF0YSBkaXIgYmVmb3JlIGEgZnJlc2ggaW5zdGFuY2UgaXMgbGF1bmNoZWQgaW50byBpdC5cbiAgICpcbiAgICogQHBhcmFtIGNkcFVybCAtIFRoZSBDRFAgVVJMIG9mIHRoZSBpbnN0YW5jZSB0aGF0IHdhcyBqdXN0IGtpbGxlZC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd2FpdEZvckluc3RhbmNlRXhpdChjZHBVcmw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFdhaXRpbmcgZm9yIHByZXZpb3VzIG93bmVkIGluc3RhbmNlIGF0ICR7Y2RwVXJsfSB0byBleGl0Li4uYCk7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUztcbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGAke2NkcFVybH0vanNvbmApO1xuICAgICAgICBhd2FpdCByZXNwb25zZS5ib2R5Py5jYW5jZWwoKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBUaGUgZW5kcG9pbnQgaXMgZ29uZTogdGhlIHByb2Nlc3MgaGFzIGV4aXRlZCBhbmQgcmVsZWFzZWQgdGhlIGxvY2suXG4gICAgICAgIGF3YWl0IGRlbGF5KElOU1RBTkNFX0VYSVRfU0VUVExFX0RFTEFZX0lOX01JTExJU0VDT05EUyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGF3YWl0IGRlbGF5KFZBVUxUX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG4gICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gUHJldmlvdXMgaW5zdGFuY2Ugc3RpbGwgcmVzcG9uZGVkIGJlZm9yZSB0aW1lb3V0OyByZWxhdW5jaGluZyBhbnl3YXkuJyk7XG4gIH1cblxuICAvKipcbiAgICogV2FpdHMgZm9yIHRoZSB2YXVsdCdzIGBhcHAud29ya3NwYWNlYCB0byByZWFjaCBsYXlvdXQtcmVhZHkgc3RhdGUuXG4gICAqXG4gICAqIGBmaW5kVGFyZ2V0Rm9yVmF1bHRgIHJldHVybnMgYXMgc29vbiBhcyBgYXBwLnZhdWx0LmFkYXB0ZXIuZ2V0QmFzZVBhdGgoKWBcbiAgICogbWF0Y2hlcyBcdTIwMTQgd2hpY2ggaXMgdHJ1ZSBzaG9ydGx5IGFmdGVyIHRoZSBgQXBwYCBjb25zdHJ1Y3RvciBydW5zLCBiZWZvcmVcbiAgICogYHBsdWdpbnMuaW5pdGlhbGl6ZSgpYCAoYW5kIGFueSB0cnVzdCBkaWFsb2cpIGhhcyBleGVjdXRlZC4gQm9vdHN0cmFwcGluZ1xuICAgKiB0aGUgbmFtZXNwYWNlIGFuZCBjYWxsaW5nIGBwb2xsVmF1bHRCYXNlUGF0aCgpYCBhd2FpdHMgYGxheW91dFJlYWR5YCwgc29cbiAgICogYnkgdGhlIHRpbWUgdGhpcyByZXR1cm5zIHRoZSBkaWFsb2cgaGFzIGVpdGhlciByZW5kZXJlZCBvciBpcyBub3QgZ29pbmdcbiAgICogdG8gcmVuZGVyLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gZXZhbHVhdGUgaW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdhaXRGb3JMYXlvdXRSZWFkeSh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGVuc3VyZU5hbWVzcGFjZUJvb3RzdHJhcHBlZCh0aGlzLCB2YXVsdFBhdGgpO1xuICAgIGF3YWl0IHRoaXMuZXZhbHVhdGUoJ3dpbmRvdy5fX29ic2lkaWFuSW50ZWdyYXRpb25UZXN0aW5nLnBvbGxWYXVsdEJhc2VQYXRoKCknLCB7IGN3ZDogdmF1bHRQYXRoIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvbGxzIHRoZSBvd25lZCBpbnN0YW5jZSB1bnRpbCB0aGUgdmF1bHQgdGFyZ2V0IGV4aXN0cywgbGF5b3V0IGlzIHJlYWR5LCBhbmRcbiAgICogdGhlIHRydXN0IGRpYWxvZyAoaWYgYW55KSBoYXMgYmVlbiBkaXNtaXNzZWQuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgZm9sZGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB3YWl0Rm9yT3duZWRWYXVsdFJlYWR5KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gV2FpdGluZyBmb3Igb3duZWQgdmF1bHQgdG8gYmVjb21lIHJlYWR5ICh0aW1lb3V0PSR7U3RyaW5nKFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zKS4uLmApO1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5maW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoKTtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yTGF5b3V0UmVhZHkodmF1bHRQYXRoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNtaXNzVHJ1c3REaWFsb2codmF1bHRQYXRoKTtcbiAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gT3duZWQgdmF1bHQgaXMgcmVhZHkuJyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBWYXVsdCB0YXJnZXQgbm90IHJlYWR5IHlldC5cbiAgICAgIH1cbiAgICAgIGF3YWl0IGRlbGF5KFZBVUxUX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBPd25lZCB2YXVsdCBhdCAke3ZhdWx0UGF0aH0gZGlkIG5vdCBiZWNvbWUgcmVhZHkgd2l0aGluICR7U3RyaW5nKFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zYCk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBnaXZlbiBkZWxheS5cbiAqXG4gKiBAcGFyYW0gbXMgLSBUaGUgZGVsYXkgaW4gbWlsbGlzZWNvbmRzLlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgdGhlIGRlbGF5LlxuICovXG5mdW5jdGlvbiBkZWxheShtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBwbGF0Zm9ybS1zcGVjaWZpYyBjb21tYW5kIHRvIGxhdW5jaCBPYnNpZGlhbiB3aXRoIHJlbW90ZSBkZWJ1Z2dpbmcgZW5hYmxlZC5cbiAqXG4gKiBSZXNvbHZlcyB0aGUgYWN0dWFsIGluc3RhbGxlZCBPYnNpZGlhbiBleGVjdXRhYmxlIChjb3ZlcmluZyBpbnN0YWxsZXItYmFzZWRcbiAqIGFuZCBgUEFUSGAtYmFzZWQgaW5zdGFsbHMgc3VjaCBhcyBgc2Nvb3BgKSBhbmQgdmVyaWZpZXMgaXQgZXhpc3RzIGJlZm9yZVxuICogcmV0dXJuaW5nIGEgY29tbWFuZC4gVGhyb3dzIGlmIE9ic2lkaWFuIGlzIG5vdCBpbnN0YWxsZWQuXG4gKlxuICogQHBhcmFtIHBvcnQgLSBUaGUgQ0RQIHBvcnQgdG8gdXNlLlxuICogQHJldHVybnMgVGhlIHNoZWxsIGNvbW1hbmQgc3RyaW5nLlxuICogQHRocm93cyBFcnJvciBpZiBPYnNpZGlhbiBjYW5ub3QgYmUgbG9jYXRlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0T2JzaWRpYW5MYXVuY2hDb21tYW5kKHBvcnQ6IG51bWJlcik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGV4ZVBhdGggPSBhd2FpdCByZXNvbHZlT2JzaWRpYW5FeGVjdXRhYmxlKCk7XG4gIGNvbnN0IGZsYWcgPSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnQ9JHtTdHJpbmcocG9ydCl9YDtcblxuICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgIHJldHVybiBgc3RhcnQgXCJcIiBcIiR7ZXhlUGF0aH1cIiAke2ZsYWd9YDtcbiAgfVxuXG4gIHJldHVybiBgXCIke2V4ZVBhdGh9XCIgJHtmbGFnfSAmYDtcbn1cblxuLyoqXG4gKiBBdHRlbXB0cyB0byByZW1vdmUgYSBkaXJlY3RvcnkgcmVjdXJzaXZlbHksIHJldHVybmluZyB3aGV0aGVyIGl0IHN1Y2NlZWRlZC5cbiAqXG4gKiBAcGFyYW0gZGlyIC0gVGhlIGRpcmVjdG9yeSB0byByZW1vdmUuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgcmVtb3ZlZCwgYGZhbHNlYCBpZiB0aGUgcmVtb3ZhbCB0aHJldyAoZS5nLiBoYW5kbGVzIGhlbGQpLlxuICovXG5mdW5jdGlvbiB0cnlSZW1vdmVEaXIoZGlyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBybVN5bmMoZGlyLCB7IGZvcmNlOiB0cnVlLCByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKiB2OCBpZ25vcmUgc3RvcCAqL1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFxQkEseUJBQTRCO0FBQzVCLHFCQUlPO0FBQ1AsdUJBQXFCO0FBQ3JCLDBCQUFvQjtBQVFwQixrQ0FBMEM7QUFDMUMsa0JBQXFCO0FBQ3JCLGlCQUFvQjtBQUNwQixpQ0FBNEM7QUFDNUMsNkJBSU87QUFDUCxpQ0FBMEM7QUFDMUMsK0JBQTRDO0FBQzVDLHFDQUFxQztBQUNyQyx5QkFBa0M7QUFDbEMsd0JBR087QUEySFAsTUFBTSxrQ0FBa0M7QUFDeEMsTUFBTSx1QkFBdUI7QUFDN0IsTUFBTSx1Q0FBdUM7QUFDN0MsTUFBTSw4Q0FBOEM7QUFDcEQsTUFBTSxZQUFZO0FBQ2xCLE1BQU0sc0NBQXNDO0FBQzVDLE1BQU0scUNBQXFDO0FBQzNDLE1BQU0sb0NBQW9DO0FBQzFDLE1BQU0sMkNBQTJDO0FBQ2pELE1BQU0scUNBQXFDO0FBQzNDLE1BQU0sNkNBQTZDO0FBQ25ELE1BQU0sMENBQTBDO0FBQ2hELE1BQU0sNENBQTRDO0FBQ2xELE1BQU0sa0RBQWtEO0FBUWpELE1BQU0sb0JBQWlEO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFJNUMsV0FBVztBQUFBLEVBQ25CLGtCQUFpQztBQUFBLEVBQ3hCO0FBQUEsRUFDVDtBQUFBLEVBQ0E7QUFBQSxFQUNTO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNULFlBQVk7QUFBQSxFQUNIO0FBQUEsRUFDVDtBQUFBLEVBQ0EsS0FBdUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPeEIsWUFBWSxRQUFvQztBQUNyRCxTQUFLLFVBQVUsUUFBUSxXQUFXO0FBQ2xDLFNBQUssK0JBQStCLFFBQVEsZ0NB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VyxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU87QUFDN0MsY0FBTSxTQUFTLE1BQU0sT0FBTztBQUFBLE1BQzlCLFFBQVE7QUFFTixjQUFNLE1BQU0sMENBQTBDO0FBQ3REO0FBQUEsTUFDRjtBQUNBLFlBQU0sTUFBTSxtQ0FBbUM7QUFBQSxJQUNqRDtBQUNBLHdCQUFJLHVGQUF1RjtBQUFBLEVBQzdGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFjQSxNQUFjLG1CQUFtQixXQUFrQztBQUNqRSxjQUFNLHdEQUE0QixNQUFNLFNBQVM7QUFDakQsVUFBTSxLQUFLLFNBQVMsMkRBQTJELEVBQUUsS0FBSyxVQUFVLENBQUM7QUFBQSxFQUNuRztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBUUEsTUFBYyx1QkFBdUIsV0FBa0M7QUFDckUsd0JBQUksb0VBQW9FLE9BQU8sa0NBQWtDLENBQUMsUUFBUTtBQUMxSCxVQUFNLFdBQVcsS0FBSyxJQUFJLElBQUk7QUFDOUIsV0FBTyxLQUFLLElBQUksSUFBSSxVQUFVO0FBQzVCLFVBQUk7QUFDRixjQUFNLEtBQUssbUJBQW1CLFNBQVM7QUFDdkMsY0FBTSxLQUFLLG1CQUFtQixTQUFTO0FBQ3ZDLGNBQU0sS0FBSyxtQkFBbUIsU0FBUztBQUN2Qyw0QkFBSSx1Q0FBdUM7QUFDM0M7QUFBQSxNQUNGLFFBQVE7QUFBQSxNQUVSO0FBQ0EsWUFBTSxNQUFNLG1DQUFtQztBQUFBLElBQ2pEO0FBQ0EsVUFBTSxJQUFJLE1BQU0sa0JBQWtCLFNBQVMsZ0NBQWdDLE9BQU8sa0NBQWtDLENBQUMsSUFBSTtBQUFBLEVBQzNIO0FBQ0Y7QUFRQSxTQUFTLE1BQU0sSUFBMkI7QUFDeEMsU0FBTyxJQUFJLFFBQVEsQ0FBQyxZQUFZO0FBQzlCLGVBQVcsU0FBUyxFQUFFO0FBQUEsRUFDeEIsQ0FBQztBQUNIO0FBYUEsZUFBZSx5QkFBeUIsTUFBK0I7QUFDckUsUUFBTSxVQUFVLFVBQU0sc0RBQTBCO0FBQ2hELFFBQU0sT0FBTywyQkFBMkIsT0FBTyxJQUFJLENBQUM7QUFFcEQsTUFBSSxvQkFBQUEsUUFBUSxhQUFhLFNBQVM7QUFDaEMsV0FBTyxhQUFhLE9BQU8sS0FBSyxJQUFJO0FBQUEsRUFDdEM7QUFFQSxTQUFPLElBQUksT0FBTyxLQUFLLElBQUk7QUFDN0I7QUFRQSxTQUFTLGFBQWEsS0FBc0I7QUFDMUMsTUFBSTtBQUNGLCtCQUFPLEtBQUssRUFBRSxPQUFPLE1BQU0sV0FBVyxLQUFLLENBQUM7QUFDNUMsV0FBTztBQUFBLEVBQ1QsUUFBUTtBQUNOLFdBQU87QUFBQSxFQUNUO0FBQ0Y7IiwKICAibmFtZXMiOiBbInByb2Nlc3MiXQp9Cg==
765
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1kZXNrdG9wLWNkcC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIERlc2t0b3AgQ0RQIHRyYW5zcG9ydCBcdTIwMTQgZXZhbHVhdGVzIGV4cHJlc3Npb25zIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2xcbiAqIG92ZXIgV2ViU29ja2V0IGFuZCBtYW5hZ2VzIHZhdWx0cyB2aWEgRWxlY3Ryb24gSVBDLlxuICpcbiAqIFR3byBtb2RlczpcbiAqIC0gKipPd25lZCAoZGVmYXVsdCkqKjogdGhlIHRyYW5zcG9ydCBsYXVuY2hlcyBhbmQgb3ducyBhbiBpc29sYXRlZCBPYnNpZGlhblxuICogICBpbnN0YW5jZSBhZ2FpbnN0IGEgdGVtcG9yYXJ5IGAtLXVzZXItZGF0YS1kaXJgIG9uIGEgZnJlZSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnRgLFxuICogICBuZXZlciB0b3VjaGluZyB0aGUgdXNlcidzIE9ic2lkaWFuLiBTdXBwb3J0cyB2ZXJzaW9uIHBpbm5pbmcgdmlhIHRoZSB1c2VyLWRhdGEgYXNhci5cbiAqIC0gKipBdHRhY2gqKjogd2hlbiBhbiBleHBsaWNpdCBDRFAgcG9ydCBpcyBjb25maWd1cmVkLCB0aGUgdHJhbnNwb3J0IGNvbm5lY3RzXG4gKiAgIHRvIGFuIGFscmVhZHktcnVubmluZyBPYnNpZGlhbiBvbiB0aGF0IHBvcnQuXG4gKlxuICogSXQgY29ubmVjdHMgdG8gcGFnZSB0YXJnZXRzLCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWAgY29tbWFuZHMsIGFuZCByb3V0ZXMgdG9cbiAqIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldCB1c2luZyBgZ2V0QmFzZVBhdGgoKWAgcHJvYmluZy5cbiAqXG4gKiBSZXF1aXJlbWVudHM6IE5vZGUuanMgMjIrICh1c2VzIGJ1aWx0LWluIGBXZWJTb2NrZXRgIGFuZCBgZmV0Y2hgIGdsb2JhbHMpLlxuICovXG5cbi8qIHY4IGlnbm9yZSBzdGFydCAtLSBJbnRlZ3JhdGlvbi10aW1lIGNvZGUgY292ZXJlZCBieSBpbnRlZ3JhdGlvbiB0ZXN0cywgbm90IHVuaXQgdGVzdHMuICovXG5cbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHtcbiAgbWtkaXJTeW5jLFxuICBybVN5bmMsXG4gIHdyaXRlRmlsZVN5bmNcbn0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5cbmltcG9ydCB0eXBlIHsgSW5zdGFsbGVyQ29tcGF0aWJpbGl0eSB9IGZyb20gJy4vaW5zdGFsbGVyLWNvbXBhdGliaWxpdHkuY2pzJztcbmltcG9ydCB0eXBlIHsgT3duZWRPYnNpZGlhbkluc3RhbmNlIH0gZnJvbSAnLi9vYnNpZGlhbi1pbnN0YW5jZS5janMnO1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJlckJvb3RPYnNlcnZhdGlvbiB9IGZyb20gJy4vcmVuZGVyZXItYm9vdC1kZXRlY3Rpb24uY2pzJztcbmltcG9ydCB0eXBlIHtcbiAgT2JzaWRpYW5UcmFuc3BvcnQsXG4gIFRyYW5zcG9ydEV2YWxPcHRpb25zXG59IGZyb20gJy4vdHJhbnNwb3J0LmNqcyc7XG5cbmltcG9ydCB7IERJU01JU1NfVFJVU1RfRElBTE9HX0VYUFIgfSBmcm9tICcuL2Rpc21pc3MtdHJ1c3QtZGlhbG9nLmNqcyc7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSAnLi9leGVjLmNqcyc7XG5pbXBvcnQgeyBsb2cgfSBmcm9tICcuL2xvZy5janMnO1xuaW1wb3J0IHsgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkIH0gZnJvbSAnLi9uYW1lc3BhY2UtYm9vdHN0cmFwLmNqcyc7XG5pbXBvcnQge1xuICBnZXRWYXVsdElkLFxuICBpc1ZhdWx0UmVnaXN0ZXJlZCxcbiAgcmVtb3ZlVmF1bHRGcm9tQ29uZmlnXG59IGZyb20gJy4vb2JzaWRpYW4tY29uZmlnLmNqcyc7XG5pbXBvcnQgeyByZXNvbHZlT2JzaWRpYW5FeGVjdXRhYmxlIH0gZnJvbSAnLi9vYnNpZGlhbi1leGVjdXRhYmxlLmNqcyc7XG5pbXBvcnQgeyBsYXVuY2hPd25lZE9ic2lkaWFuSW5zdGFuY2UgfSBmcm9tICcuL29ic2lkaWFuLWluc3RhbmNlLmNqcyc7XG5pbXBvcnQgeyBjb3B5QXNhckludG9Vc2VyRGF0YSB9IGZyb20gJy4vb2JzaWRpYW4tdmVyc2lvbi1zd2l0Y2guY2pzJztcbmltcG9ydCB7XG4gIGNoZWNrUmVuZGVyZXJCb290U3RhdGUsXG4gIERFRkFVTFRfREVBRF9CT09UX0dSQUNFX0lOX01JTExJU0VDT05EU1xufSBmcm9tICcuL3JlbmRlcmVyLWJvb3QtZGV0ZWN0aW9uLmNqcyc7XG5pbXBvcnQgeyBSZW5kZXJlckZhaWxlZFRvSW5pdGlhbGl6ZUVycm9yIH0gZnJvbSAnLi9yZW5kZXJlci1mYWlsZWQtdG8taW5pdGlhbGl6ZS1lcnJvci5janMnO1xuaW1wb3J0IHsgZW5zdXJlTm9uTnVsbGFibGUgfSBmcm9tICcuL3R5cGUtZ3VhcmRzLmNqcyc7XG5pbXBvcnQge1xuICByZXNvbHZlT3duZWRIaWRkZW5MYXVuY2hBcmdzLFxuICByZXNvbHZlU2FuZGJveExhdW5jaEFyZ3MsXG4gIHNob3VsZEhpZGVPYnNpZGlhbkFwcFxufSBmcm9tICcuL3Zpc2liaWxpdHkuY2pzJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgQ0RQIHRyYW5zcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXNrdG9wQ2RwVHJhbnNwb3J0Q29uZmlnIHtcbiAgLyoqXG4gICAqIENEUCBob3N0LiBEZWZhdWx0cyB0byBgJ2xvY2FsaG9zdCdgLlxuICAgKi9cbiAgY2RwSG9zdD86IHN0cmluZztcblxuICAvKipcbiAgICogQ0RQIHBvcnQgZm9yICoqYXR0YWNoKiogbW9kZSAodGhlIGAtLXJlbW90ZS1kZWJ1Z2dpbmctcG9ydGAgdGhlIHJ1bm5pbmdcbiAgICogT2JzaWRpYW4gd2FzIGxhdW5jaGVkIHdpdGgpLiBJbiBvd25lZC1pbnN0YW5jZSBtb2RlIHRoaXMgaXMgaWdub3JlZCBcdTIwMTQgYVxuICAgKiBmcmVlIHBvcnQgaXMgY2hvc2VuIGF0IGxhdW5jaC5cbiAgICovXG4gIGNkcFBvcnQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciBpbmRpdmlkdWFsIENEUCBjb21tYW5kcy5cbiAgICogRGVmYXVsdHMgdG8gYDMwMDAwYC5cbiAgICovXG4gIGNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEdyYWNlIHdpbmRvdyBpbiBtaWxsaXNlY29uZHMgZm9yIGZhc3QtZmFpbGluZyBhIGRlYWQgYm9vdCBvZiB0aGUgb3duZWRcbiAgICogaW5zdGFuY2UgKGVtcHR5IGA8Ym9keT5gIHdpdGggbm8gYHdpbmRvdy5hcHBgIGFmdGVyIHRoZSByZW5kZXJlciByZWFjaGVkXG4gICAqIGBkb2N1bWVudC5yZWFkeVN0YXRlYCBgJ2NvbXBsZXRlJ2ApLiBEZWZhdWx0cyB0b1xuICAgKiB7QGxpbmsgREVGQVVMVF9ERUFEX0JPT1RfR1JBQ0VfSU5fTUlMTElTRUNPTkRTfS4gYDBgIGRpc2FibGVzIGZhc3QtZmFpbC5cbiAgICovXG4gIGRlYWRCb290R3JhY2VJbk1pbGxpc2Vjb25kcz86IG51bWJlcjtcblxuICAvKipcbiAgICogV2hlbiBhdHRhY2hpbmcgKGkuZS4ge0BsaW5rIGNkcFBvcnR9IGlzIHNldCksIG1hcmtzIHRoZSB0YXJnZXQgYXMgYVxuICAgKiAqKmhhcm5lc3Mtb3duZWQsIGFscmVhZHktcHJlcGFyZWQqKiBpbnN0YW5jZS4gU3VwcHJlc3NlcyB0aGUgdXNlci1zY29wZVxuICAgKiB2YXVsdC1yZWdpc3RyYXRpb24gcHJlZmxpZ2h0LCBzaW5jZSB0aGUgb3duZWQgaW5zdGFuY2UncyB2YXVsdCBsaXZlcyBpbiBhblxuICAgKiBpc29sYXRlZCB1c2VyLWRhdGEgY29uZmlnIHJhdGhlciB0aGFuIHRoZSB1c2VyLXNjb3BlIHJlZ2lzdHJ5LlxuICAgKi9cbiAgaXNIYXJuZXNzT3duZWRJbnN0YW5jZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIG93bmVkIE9ic2lkaWFuIHdpbmRvdyBpcyBzaG93biBvbiBzY3JlZW4uIFdoZW4gYGZhbHNlYCAodGhlXG4gICAqIGRlZmF1bHQpLCB0aGUgb3duZWQgaW5zdGFuY2UgaXMgbGF1bmNoZWQgd2l0aCBrZWVwLWFsaXZlIENocm9taXVtIGZsYWdzIGFuZFxuICAgKiBpdHMgd2luZG93IGlzIG1vdmVkIG9mZi1zY3JlZW4gYWZ0ZXIgbGF1bmNoLiBPbmx5IG1lYW5pbmdmdWwgaW4gb3duZWQgbW9kZTtcbiAgICogYXR0YWNoIG1vZGUgbmV2ZXIgdG91Y2hlcyB0aGUgKHVzZXIncykgd2luZG93LlxuICAgKlxuICAgKiBAZGVmYXVsdCBgdHJ1ZWBcbiAgICovXG4gIGlzT2JzaWRpYW5BcHBWaXNpYmxlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hlbiBzZXQsIHRoZSB0cmFuc3BvcnQgbGF1bmNoZXMgYW5kIG93bnMgYW4gaXNvbGF0ZWQgT2JzaWRpYW4gaW5zdGFuY2VcbiAgICogaW5zdGVhZCBvZiBhdHRhY2hpbmcgdG8gYSBydW5uaW5nIG9uZS4gVGhpcyBpcyB0aGUgZGVmYXVsdCBkZXNrdG9wIG1vZGUuXG4gICAqL1xuICBvd25lZEluc3RhbmNlPzogT3duZWRJbnN0YW5jZUNvbmZpZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBsYXVuY2ggdGhlIG93bmVkIGluc3RhbmNlIHdpdGggQ2hyb21pdW0ncyBzYW5kYm94IGRpc2FibGVkXG4gICAqIChgLS1uby1zYW5kYm94YCkuIE5lZWRlZCB0byBib290IG9uIExpbnV4IHdpdGhvdXQgYSBjb3JyZWN0bHktY29uZmlndXJlZFxuICAgKiBzZXR1aWQgYGNocm9tZS1zYW5kYm94YCBoZWxwZXIgKGUuZy4gYW4gZXh0cmFjdGVkIHBvcnRhYmxlIHNoZWxsLCBvciBDSSBhcyBhXG4gICAqIG5vbi1yb290IHVzZXIpOyBoYXJtbGVzcyBvbiBXaW5kb3dzL21hY09TLiBPbmx5IG1lYW5pbmdmdWwgaW4gb3duZWQgbW9kZS5cbiAgICpcbiAgICogQGRlZmF1bHQgYGZhbHNlYFxuICAgKi9cbiAgc2hvdWxkRGlzYWJsZVNhbmRib3g/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEFuIGFzYXIgdG8gcHJvdmlzaW9uIGludG8gYSBoYXJuZXNzLW93bmVkIGluc3RhbmNlJ3MgdXNlci1kYXRhIGRpciBiZWZvcmUgbGF1bmNoLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE93bmVkSW5zdGFuY2VBc2FyIHtcbiAgLyoqIEFic29sdXRlIHBhdGggdG8gdGhlIGNhY2hlZC9zb3VyY2UgYXNhciBmaWxlLiAqL1xuICByZWFkb25seSBwYXRoOiBzdHJpbmc7XG5cbiAgLyoqIFRoZSBhc2FyJ3MgYHgueS56YCB2ZXJzaW9uLiAqL1xuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgYSBoYXJuZXNzLW93bmVkLCBpc29sYXRlZCBPYnNpZGlhbiBpbnN0YW5jZS5cbiAqXG4gKiBXaGVuIHByZXNlbnQsIHRoZSB0cmFuc3BvcnQgbGF1bmNoZXMgYW5kIG93bnMgaXRzIG93biBPYnNpZGlhbiBwcm9jZXNzXG4gKiBhZ2FpbnN0IGFuIGlzb2xhdGVkIHVzZXItZGF0YSBkaXIgaW5zdGVhZCBvZiBhdHRhY2hpbmcgdG8gYSBydW5uaW5nIGluc3RhbmNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE93bmVkSW5zdGFuY2VDb25maWcge1xuICAvKiogT3B0aW9uYWwgYXNhciB0byBwcm92aXNpb24gaW50byB7QGxpbmsgdXNlckRhdGFEaXJ9IGJlZm9yZSBsYXVuY2guICovXG4gIHJlYWRvbmx5IGFzYXI/OiBPd25lZEluc3RhbmNlQXNhciB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogVGhlIHJlc29sdmVkIGluc3RhbGxlclx1MjE5NGFwcCBjb21wYXRpYmlsaXR5IHZlcmRpY3QsIHdoZW4gaXQgY291bGQgYmUgZGV0ZXJtaW5lZFxuICAgKiAoYW4gYXNhci1zd2FwIG9udG8gYSBrbm93biBzaGVsbCB2ZXJzaW9uKS4gU3VyZmFjZWQgYnlcbiAgICoge0BsaW5rIERlc2t0b3BDZHBUcmFuc3BvcnQuZ2V0Q29tcGF0aWJpbGl0eX0uXG4gICAqL1xuICByZWFkb25seSBjb21wYXRpYmlsaXR5PzogSW5zdGFsbGVyQ29tcGF0aWJpbGl0eSB8IHVuZGVmaW5lZDtcblxuICAvKiogQWJzb2x1dGUgcGF0aCB0byB0aGUgT2JzaWRpYW4gc2hlbGwgZXhlY3V0YWJsZSB0byBsYXVuY2guICovXG4gIHJlYWRvbmx5IGV4ZVBhdGg6IHN0cmluZztcblxuICAvKipcbiAgICogQWJzb2x1dGUgcGF0aCB0byB0aGUgaXNvbGF0ZWQgdXNlci1kYXRhIGRpci4gQ3JlYXRlZCBhbmQgb3duZWQgYnkgdGhlXG4gICAqIHRyYW5zcG9ydCwgYW5kIGRlbGV0ZWQgb24gZGlzcG9zZS5cbiAgICovXG4gIHJlYWRvbmx5IHVzZXJEYXRhRGlyOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBFeGNlcHRpb25EZXRhaWxzIHtcbiAgZXhjZXB0aW9uPzogQ2RwRXhjZXB0aW9uT2JqZWN0O1xuICB0ZXh0OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBFeGNlcHRpb25PYmplY3Qge1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIENkcFJlc3BvbnNlIHtcbiAgaWQ6IG51bWJlcjtcbiAgcmVzdWx0PzogQ2RwUmVzcG9uc2VSZXN1bHQ7XG59XG5cbmludGVyZmFjZSBDZHBSZXNwb25zZVJlc3VsdCB7XG4gIHJlYWRvbmx5IGV4Y2VwdGlvbkRldGFpbHM/OiBDZHBFeGNlcHRpb25EZXRhaWxzO1xuICByZWFkb25seSByZXN1bHQ/OiBDZHBWYWx1ZTtcbn1cblxuaW50ZXJmYWNlIENkcFRhcmdldCB7XG4gIGlkOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgdXJsOiBzdHJpbmc7XG4gIHdlYlNvY2tldERlYnVnZ2VyVXJsOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDZHBWYWx1ZSB7XG4gIHR5cGU6IHN0cmluZztcbiAgdmFsdWU/OiB1bmtub3duO1xufVxuXG4vKipcbiAqIFRoZSBDRFAgZW5kcG9pbnQgb2YgYSBsYXVuY2hlZCwgaGFybmVzcy1vd25lZCBpbnN0YW5jZS5cbiAqL1xuaW50ZXJmYWNlIE93bmVkSW5zdGFuY2VFbmRwb2ludCB7XG4gIC8qKiBDRFAgaG9zdCAoZS5nLiBgJ2xvY2FsaG9zdCdgKS4gKi9cbiAgcmVhZG9ubHkgaG9zdDogc3RyaW5nO1xuXG4gIC8qKiBUaGUgZnJlZSBDRFAgcG9ydCB0aGUgb3duZWQgaW5zdGFuY2Ugd2FzIGxhdW5jaGVkIG9uLiAqL1xuICByZWFkb25seSBwb3J0OiBudW1iZXI7XG59XG5cbmNvbnN0IENPTU1BTkRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMDAwMDtcbmNvbnN0IFZBVUxUX0lEX0JZVEVfTEVOR1RIID0gODtcbmNvbnN0IFVTRVJfREFUQV9STV9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDEwMDAwO1xuY29uc3QgVVNFUl9EQVRBX1JNX1JFVFJZX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IE5PX09VVFBVVCA9ICcobm8gb3V0cHV0KSc7XG5jb25zdCBWQVVMVF9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMDAwMDtcbmNvbnN0IFZBVUxUX0NMT1NFX0RFTEFZX0lOX01JTExJU0VDT05EUyA9IDEwMDA7XG5jb25zdCBBVVRPX1NUQVJUX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTID0gMjAwMDtcbmNvbnN0IEFVVE9fU1RBUlRfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMDAwMDtcbmNvbnN0IElOU1RBTkNFX0VYSVRfU0VUVExFX0RFTEFZX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IE9XTkVEX1dJTkRPV19PRkZTQ1JFRU5fTUFSR0lOX0lOX1BJWEVMUyA9IDIwMDtcbmNvbnN0IE9XTkVEX1dJTkRPV19ISURFX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMjAwMDA7XG5jb25zdCBPV05FRF9XSU5ET1dfSElERV9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDI1MDtcblxuLyoqXG4gKiBUcmFuc3BvcnQgdGhhdCBjb21tdW5pY2F0ZXMgd2l0aCBEZXNrdG9wIE9ic2lkaWFuIHZpYSBDaHJvbWUgRGV2VG9vbHMgUHJvdG9jb2wuXG4gKlxuICogQ29ubmVjdHMgdG8gT2JzaWRpYW4ncyBDRFAgV2ViU29ja2V0IGVuZHBvaW50LCBzZW5kcyBgUnVudGltZS5ldmFsdWF0ZWBcbiAqIGNvbW1hbmRzLCBhbmQgcm91dGVzIGV4cHJlc3Npb25zIHRvIHRoZSBjb3JyZWN0IHZhdWx0IHRhcmdldC5cbiAqL1xuZXhwb3J0IGNsYXNzIERlc2t0b3BDZHBUcmFuc3BvcnQgaW1wbGVtZW50cyBPYnNpZGlhblRyYW5zcG9ydCB7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0aGlzIHRyYW5zcG9ydCBpcyBmb3IgYSBtb2JpbGUgcGxhdGZvcm0uIEFsd2F5cyBgZmFsc2VgIGZvciB0aGlzIHRyYW5zcG9ydC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBpc01vYmlsZSA9IGZhbHNlO1xuICBwcml2YXRlIGFjdGl2ZVZhdWx0UGF0aDogbnVsbCB8IHN0cmluZyA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2RwSG9zdDogc3RyaW5nO1xuICBwcml2YXRlIGNkcFBvcnQ6IG51bWJlcjtcbiAgcHJpdmF0ZSBjZHBVcmw6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kVGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVhZEJvb3RHcmFjZUluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgaXNIYXJuZXNzT3duZWRJbnN0YW5jZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBpc09ic2lkaWFuQXBwVmlzaWJsZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSBtZXNzYWdlSWQgPSAwO1xuICBwcml2YXRlIHJlYWRvbmx5IG93bmVkQ29uZmlnOiBPd25lZEluc3RhbmNlQ29uZmlnIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIG93bmVkSW5zdGFuY2U6IE93bmVkT2JzaWRpYW5JbnN0YW5jZSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBzaG91bGREaXNhYmxlU2FuZGJveDogYm9vbGVhbjtcbiAgcHJpdmF0ZSB3czogbnVsbCB8IFdlYlNvY2tldCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgQ0RQIHRyYW5zcG9ydC5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyAtIENEUCBjb25uZWN0aW9uIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IoY29uZmlnPzogRGVza3RvcENkcFRyYW5zcG9ydENvbmZpZykge1xuICAgIHRoaXMuY2RwSG9zdCA9IGNvbmZpZz8uY2RwSG9zdCA/PyAnbG9jYWxob3N0JztcbiAgICB0aGlzLmNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHMgPSBjb25maWc/LmNvbW1hbmRUaW1lb3V0SW5NaWxsaXNlY29uZHMgPz8gQ09NTUFORF9USU1FT1VUX0lOX01JTExJU0VDT05EUztcbiAgICB0aGlzLmRlYWRCb290R3JhY2VJbk1pbGxpc2Vjb25kcyA9IGNvbmZpZz8uZGVhZEJvb3RHcmFjZUluTWlsbGlzZWNvbmRzID8/IERFRkFVTFRfREVBRF9CT09UX0dSQUNFX0lOX01JTExJU0VDT05EUztcbiAgICB0aGlzLmlzSGFybmVzc093bmVkSW5zdGFuY2UgPSBjb25maWc/LmlzSGFybmVzc093bmVkSW5zdGFuY2UgPz8gZmFsc2U7XG4gICAgdGhpcy5pc09ic2lkaWFuQXBwVmlzaWJsZSA9IGNvbmZpZz8uaXNPYnNpZGlhbkFwcFZpc2libGUgPz8gdHJ1ZTtcbiAgICB0aGlzLm93bmVkQ29uZmlnID0gY29uZmlnPy5vd25lZEluc3RhbmNlO1xuICAgIHRoaXMuc2hvdWxkRGlzYWJsZVNhbmRib3ggPSBjb25maWc/LnNob3VsZERpc2FibGVTYW5kYm94ID8/IGZhbHNlO1xuICAgIC8vIE93bmVkIG1vZGUgcGlja3MgYSBmcmVlIHBvcnQgYXQgbGF1bmNoIChhc3NpZ25lZCBpbiByZWdpc3RlclZhdWx0KS5cbiAgICAvLyBBdHRhY2ggbW9kZSBjb25uZWN0cyB0byB0aGUgY29uZmlndXJlZCBwb3J0OyBubyBwb3J0IGlzIGhhcmRjb2RlZC5cbiAgICB0aGlzLmNkcFBvcnQgPSBjb25maWc/LmNkcFBvcnQgPz8gMDtcbiAgICB0aGlzLmNkcFVybCA9IGNvbmZpZz8uY2RwUG9ydCA9PT0gdW5kZWZpbmVkID8gJycgOiBgaHR0cDovLyR7dGhpcy5jZHBIb3N0fToke1N0cmluZyhjb25maWcuY2RwUG9ydCl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwb3NlcyBvZiB0aGUgYWN0aXZlIFdlYlNvY2tldCBjb25uZWN0aW9uIGFuZCwgaW4gb3duZWQtaW5zdGFuY2UgbW9kZSxcbiAgICoga2lsbHMgdGhlIG93bmVkIE9ic2lkaWFuIHByb2Nlc3MgYW5kIHJlbW92ZXMgaXRzIGlzb2xhdGVkIHVzZXItZGF0YSBkaXIuXG4gICAqXG4gICAqIFRoZSByZW1vdmFsIGlzIHJldHJpZWQgYmVjYXVzZSBXaW5kb3dzIGJyaWVmbHkgaG9sZHMgdGhlIGp1c3Qta2lsbGVkXG4gICAqIHByb2Nlc3MncyBmaWxlIGhhbmRsZXMsIHdoaWNoIHdvdWxkIG90aGVyd2lzZSBmYWlsIGBybVN5bmNgIHdpdGggYEVQRVJNYC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBkaXNwb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZGlzY29ubmVjdCgpO1xuICAgIGlmICghdGhpcy5vd25lZENvbmZpZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMub3duZWRJbnN0YW5jZT8ua2lsbCgpO1xuICAgIGNvbnN0IHsgdXNlckRhdGFEaXIgfSA9IHRoaXMub3duZWRDb25maWc7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgVVNFUl9EQVRBX1JNX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGlmICh0cnlSZW1vdmVEaXIodXNlckRhdGFEaXIpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGF3YWl0IGRlbGF5KFVTRVJfREFUQV9STV9SRVRSWV9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICBpZiAoIXRyeVJlbW92ZURpcih1c2VyRGF0YURpcikpIHtcbiAgICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIENvdWxkIG5vdCByZW1vdmUgb3duZWQgdXNlci1kYXRhIGRpciB3aXRoaW4gJHtTdHJpbmcoVVNFUl9EQVRBX1JNX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcyAobm9uLWZhdGFsKTogJHt1c2VyRGF0YURpcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3luY2hyb25vdXMgZGlzcG9zYWwgXHUyMDE0IGtpbGxzIHRoZSBvd25lZCBpbnN0YW5jZSBhbmQgbWFrZXMgYSBiZXN0LWVmZm9ydFxuICAgKiByZW1vdmFsIG9mIGl0cyB1c2VyLWRhdGEgZGlyLiBTYWZlIHRvIGNhbGwgZnJvbSBhIHByb2Nlc3MgYGV4aXRgIGhhbmRsZXJcbiAgICogKHdoZXJlIGFzeW5jIHJldHJpZXMgYXJlIGltcG9zc2libGU7IGEgbGVmdG92ZXIgdGVtcCBkaXIgaXMgYWNjZXB0YWJsZSkuXG4gICAqL1xuICBwdWJsaWMgZGlzcG9zZVN5bmMoKTogdm9pZCB7XG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgaWYgKHRoaXMub3duZWRDb25maWcpIHtcbiAgICAgIHRoaXMub3duZWRJbnN0YW5jZT8ua2lsbCgpO1xuICAgICAgaWYgKCF0cnlSZW1vdmVEaXIodGhpcy5vd25lZENvbmZpZy51c2VyRGF0YURpcikpIHtcbiAgICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gT3duZWQgdXNlci1kYXRhIGRpciBub3QgcmVtb3ZlZCBzeW5jaHJvbm91c2x5IChwcm9jZXNzIG1heSBzdGlsbCBob2xkIGhhbmRsZXMpOiAke3RoaXMub3duZWRDb25maWcudXNlckRhdGFEaXJ9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlcyBhIEphdmFTY3JpcHQgZXhwcmVzc2lvbiBpbnNpZGUgT2JzaWRpYW4gdmlhIENEUCBgUnVudGltZS5ldmFsdWF0ZWAuXG4gICAqXG4gICAqIFJvdXRlcyB0byB0aGUgY29ycmVjdCB2YXVsdCB0YXJnZXQgYmFzZWQgb24gYG9wdGlvbnMuY3dkYC5cbiAgICpcbiAgICogQHBhcmFtIGV4cHJlc3Npb24gLSBUaGUgSmF2YVNjcmlwdCBleHByZXNzaW9uIHRvIGV2YWx1YXRlLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEV2YWx1YXRpb24gb3B0aW9ucy5cbiAgICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgcmVzdWx0IHN0cmluZy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBldmFsdWF0ZShleHByZXNzaW9uOiBzdHJpbmcsIG9wdGlvbnM6IFRyYW5zcG9ydEV2YWxPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuZW5zdXJlQ29ubmVjdGlvbihvcHRpb25zLmN3ZCk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgfSk7XG5cbiAgICBpZiAocmVzcG9uc2UucmVzdWx0Py5leGNlcHRpb25EZXRhaWxzKSB7XG4gICAgICBjb25zdCBkZXNjID0gcmVzcG9uc2UucmVzdWx0LmV4Y2VwdGlvbkRldGFpbHMuZXhjZXB0aW9uPy5kZXNjcmlwdGlvblxuICAgICAgICA/PyByZXNwb25zZS5yZXN1bHQuZXhjZXB0aW9uRGV0YWlscy50ZXh0O1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDRFAgZXZhbHVhdGlvbiBlcnJvcjogJHtkZXNjfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdE9iaiA9IHJlc3BvbnNlLnJlc3VsdD8ucmVzdWx0O1xuICAgIGlmICghcmVzdWx0T2JqIHx8IHJlc3VsdE9iai50eXBlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIE5PX09VVFBVVDtcbiAgICB9XG5cbiAgICByZXR1cm4gU3RyaW5nKHJlc3VsdE9iai52YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgcmVzb2x2ZWQgaW5zdGFsbGVyXHUyMTk0YXBwIGNvbXBhdGliaWxpdHkgdmVyZGljdCBmb3IgdGhpcyBvd25lZFxuICAgKiBpbnN0YW5jZSwgc28gY2FsbGVycyBjYW4gYXNzZXJ0IG9uIGl0LiBSZXR1cm5zIGB1bmRlZmluZWRgIHdoZW4gdGhpcyBpcyBub3RcbiAgICogYW4gb3duZWQgaW5zdGFuY2UsIG9yIHRoZSB2ZXJkaWN0IGNvdWxkIG5vdCBiZSBkZXRlcm1pbmVkIChlLmcuIGFuXG4gICAqIHVuZGV0ZWN0YWJsZSBzaGVsbCB2ZXJzaW9uLCBvciB0aGUgYXBwIHZlcnNpb24gaXMgYWJzZW50IGZyb20gdGhlIHRhYmxlKS5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGNvbXBhdGliaWxpdHkgdmVyZGljdCwgb3IgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBwdWJsaWMgZ2V0Q29tcGF0aWJpbGl0eSgpOiBJbnN0YWxsZXJDb21wYXRpYmlsaXR5IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vd25lZENvbmZpZz8uY29tcGF0aWJpbGl0eTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBDRFAgZW5kcG9pbnQgb2YgdGhlIG93bmVkLCBsYXVuY2hlZCBpbnN0YW5jZSBzbyB0aGUgZ2xvYmFsIHNldHVwXG4gICAqIGNhbiBoYW5kIGl0IHRvIHRlc3Qgd29ya2VycyAod2hpY2ggdGhlbiAqKmF0dGFjaCoqIHRvIGl0IGluc3RlYWQgb2ZcbiAgICogbGF1bmNoaW5nIHRoZWlyIG93bikuIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiB0aGlzIHRyYW5zcG9ydCBpcyBub3QgYW5cbiAgICogb3duZWQgaW5zdGFuY2UsIG9yIGl0cyBpbnN0YW5jZSBoYXMgbm90IGJlZW4gbGF1bmNoZWQgeWV0LlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgb3duZWQgaW5zdGFuY2UncyBDRFAgaG9zdCBhbmQgcG9ydCwgb3IgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBwdWJsaWMgZ2V0T3duZWRJbnN0YW5jZUVuZHBvaW50KCk6IE93bmVkSW5zdGFuY2VFbmRwb2ludCB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0aGlzLm93bmVkQ29uZmlnIHx8ICF0aGlzLm93bmVkSW5zdGFuY2UpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiB7IGhvc3Q6IHRoaXMuY2RwSG9zdCwgcG9ydDogdGhpcy5jZHBQb3J0IH07XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpZXMgdGhhdCB0aGUgQ0RQIGVuZHBvaW50IGlzIHJlYWNoYWJsZSBhbmQgaGFzIE9ic2lkaWFuIHRhcmdldHMuXG4gICAqXG4gICAqIElmIE9ic2lkaWFuIGlzIG5vdCBydW5uaW5nLCBhdHRlbXB0cyB0byBhdXRvLXN0YXJ0IGl0IHZpYSBVUkkgcHJvdG9jb2xcbiAgICogYW5kIHBvbGxzIHVudGlsIENEUCBiZWNvbWVzIGF2YWlsYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSB2YXVsdCBwYXRoICh1c2VkIGZvciB2YXVsdCByZWdpc3RyYXRpb24gY2hlY2spLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHByZWZsaWdodENoZWNrKHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMub3duZWRDb25maWcgfHwgdGhpcy5pc0hhcm5lc3NPd25lZEluc3RhbmNlKSB7XG4gICAgICAvLyBPd25lZCBpbnN0YW5jZSAobGF1bmNoZWQgaGVyZSkgb3IgYSB3b3JrZXIgYXR0YWNoZWQgdG8gb25lOiByZWFkaW5lc3MgaXNcbiAgICAgIC8vIEd1YXJhbnRlZWQgYnkgdGhlIGdsb2JhbCBzZXR1cCdzIHJlZ2lzdGVyVmF1bHQsIGFuZCB0aGUgdmF1bHQgbGl2ZXMgaW5cbiAgICAgIC8vIFRoZSBpc29sYXRlZCBjb25maWcgXHUyMDE0IHRoZXJlIGlzIG5vdGhpbmcgdG8gdmVyaWZ5IGFnYWluc3QgdGhlIHVzZXItc2NvcGVcbiAgICAgIC8vIFJlZ2lzdHJ5LlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFJ1bm5pbmcgcHJlZmxpZ2h0IGNoZWNrIGZvciB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgaWYgKCFpc1ZhdWx0UmVnaXN0ZXJlZCh2YXVsdFBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBWYXVsdCBpcyBub3QgcmVnaXN0ZXJlZCBpbiBPYnNpZGlhbjogJHt2YXVsdFBhdGh9LiBSZWdpc3RlciB0aGUgdmF1bHQgZmlyc3Qgd2l0aCByZWdpc3RlclZhdWx0KCkgb3IgVGVtcFZhdWx0LnJlZ2lzdGVyKCkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHBhZ2UgdGFyZ2V0cycpO1xuICAgICAgfVxuICAgICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gQ0RQIHJlYWNoYWJsZSwgJHtTdHJpbmcodGFyZ2V0cy5sZW5ndGgpfSB0YXJnZXQocykgZm91bmQuYCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZU9ic2lkaWFuUnVubmluZygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSB2YXVsdCB2aWEgRWxlY3Ryb24gSVBDIGV2YWx1YXRlZCB0aHJvdWdoIENEUC5cbiAgICpcbiAgICogVXNlcyBhbiBleGlzdGluZyBPYnNpZGlhbiB0YXJnZXQgdG8gc2VuZCB0aGUgYHZhdWx0LW9wZW5gIElQQyBjb21tYW5kLFxuICAgKiB0aGVuIHBvbGxzIHVudGlsIHRoZSBuZXcgdmF1bHQncyB0YXJnZXQgYXBwZWFycy5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBmb2xkZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm93bmVkQ29uZmlnKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyVmF1bHRJbk93bmVkSW5zdGFuY2UodmF1bHRQYXRoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLm9wZW5WYXVsdEluUnVubmluZ0luc3RhbmNlKHZhdWx0UGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogVW5yZWdpc3RlcnMgYSB2YXVsdCBieSBkZXN0cm95aW5nIGl0cyB3aW5kb3cgYW5kIHJlbW92aW5nIGl0IGZyb20gdGhlIHJlZ2lzdHJ5LlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB1bnJlZ2lzdGVyVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5vd25lZENvbmZpZykge1xuICAgICAgLy8gVGhlIG93bmVkIGluc3RhbmNlIGlzIGtpbGxlZCB3aG9sZXNhbGUgb24gZGlzcG9zZTsgbm8gcGVyLXZhdWx0XG4gICAgICAvLyBVbnJlZ2lzdGVyIGlzIG5lZWRlZCAoYW5kIHRoZSByZWdpc3RyeSBsaXZlcyBpbiB0aGUgaXNvbGF0ZWQgY29uZmlnKS5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkKHRoaXMsIHZhdWx0UGF0aCk7XG4gICAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGgpO1xuICAgICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZGVzdHJveUV4cHIgPSAnd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuZGVzdHJveUN1cnJlbnRXaW5kb3coKSc7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgICAgICBleHByZXNzaW9uOiBkZXN0cm95RXhwcixcbiAgICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFdpbmRvdyBtYXkgYWxyZWFkeSBiZSBjbG9zZWQuXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYWN0aXZlVmF1bHRQYXRoID09PSB2YXVsdFBhdGgpIHtcbiAgICAgIHRoaXMuZGlzY29ubmVjdCgpO1xuICAgIH1cblxuICAgIGF3YWl0IGRlbGF5KFZBVUxUX0NMT1NFX0RFTEFZX0lOX01JTExJU0VDT05EUyk7XG5cbiAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgdGhpcy5nZXRQYWdlVGFyZ2V0cygpO1xuICAgIGlmICh0YXJnZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQoZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSkpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkKHRoaXMsIHZhdWx0UGF0aCk7XG4gICAgICAgIGNvbnN0IHJlbW92ZUV4cHIgPSBgd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuaXBjU2VuZFN5bmMoJHtKU09OLnN0cmluZ2lmeSh7IGFyZ3M6IFt2YXVsdFBhdGhdLCBjaGFubmVsOiAndmF1bHQtcmVtb3ZlJyB9KX0pYDtcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgICAgYXdhaXRQcm9taXNlOiB0cnVlLFxuICAgICAgICAgIGV4cHJlc3Npb246IHJlbW92ZUV4cHIsXG4gICAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIE5vIENEUCB0YXJnZXRzIGZvciByZW1vdmFsIElQQyBcdTIwMTQgcmVtb3ZpbmcgZGlyZWN0bHkgZnJvbSBvYnNpZGlhbi5qc29uLicpO1xuICAgICAgcmVtb3ZlVmF1bHRGcm9tQ29uZmlnKHZhdWx0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3RzIHRvIGEgQ0RQIHRhcmdldCdzIFdlYlNvY2tldCBlbmRwb2ludC5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCAtIFRoZSBDRFAgdGFyZ2V0IHRvIGNvbm5lY3QgdG8uXG4gICAqIEByZXR1cm5zIFRoZSBvcGVuIFdlYlNvY2tldCBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb25uZWN0VG9UYXJnZXQodGFyZ2V0OiBDZHBUYXJnZXQpOiBQcm9taXNlPFdlYlNvY2tldD4ge1xuICAgIGNvbnN0IHdzID0gbmV3IFdlYlNvY2tldCh0YXJnZXQud2ViU29ja2V0RGVidWdnZXJVcmwpO1xuICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHdzLm9ub3BlbiA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfTtcbiAgICAgIHdzLm9uZXJyb3IgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBjb25uZWN0IHRvIENEUCB0YXJnZXQ6ICR7dGFyZ2V0LndlYlNvY2tldERlYnVnZ2VyVXJsfWApKTtcbiAgICAgIH07XG4gICAgfSk7XG4gICAgcmV0dXJuIHdzO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc2Nvbm5lY3RzIHRoZSBhY3RpdmUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMud3M/LnJlYWR5U3RhdGUgPT09IFdlYlNvY2tldC5PUEVOKSB7XG4gICAgICB0aGlzLndzLmNsb3NlKCk7XG4gICAgfVxuICAgIHRoaXMud3MgPSBudWxsO1xuICAgIHRoaXMuYWN0aXZlVmF1bHRQYXRoID0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNtaXNzZXMgdGhlIFwiRG8geW91IHRydXN0IHRoZSBhdXRob3Igb2YgdGhpcyB2YXVsdD9cIiBkaWFsb2cgaWYgcHJlc2VudC5cbiAgICpcbiAgICogQWN0cyBhcyBhIHNhZmV0eSBuZXQgd2hlbiBgZW5hYmxlLXBsdWdpbi08aWQ+YCBpcyB3cml0dGVuIGluIG9uZSByZW5kZXJlclxuICAgKiBidXQgbm90IHlldCB2aXNpYmxlIHRvIHRoZSBuZXdseS1vcGVuZWQgdmF1bHQncyByZW5kZXJlciAocmFjZSBvYnNlcnZlZFxuICAgKiBpbiBPYnNpZGlhbiAxLjEzLjApLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gZXZhbHVhdGUgaW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGRpc21pc3NUcnVzdERpYWxvZyh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXZhbHVhdGUoRElTTUlTU19UUlVTVF9ESUFMT0dfRVhQUiwgeyBjd2Q6IHZhdWx0UGF0aCB9KTtcbiAgICBpZiAocmVzdWx0ID09PSAndHJ1ZScpIHtcbiAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIERpc21pc3NlZCBcIkRvIHlvdSB0cnVzdCB0aGUgYXV0aG9yXCIgZGlhbG9nLicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBlbmFibGUtcGx1Z2luLTx2YXVsdElkPmAgaW4gT2JzaWRpYW4ncyBsb2NhbFN0b3JhZ2UgdG8gcHJldmVudFxuICAgKiB0aGUgXCJEbyB5b3UgdHJ1c3QgdGhlIGF1dGhvciBvZiB0aGlzIHZhdWx0P1wiIGRpYWxvZyBmcm9tIGFwcGVhcmluZ1xuICAgKiB3aGVuIGEgdmF1bHQgd2l0aCBjb21tdW5pdHkgcGx1Z2lucyBpcyBvcGVuZWQgZm9yIHRoZSBmaXJzdCB0aW1lLlxuICAgKlxuICAgKiBNdXN0IGJlIGNhbGxlZCBhZnRlciB0aGUgYHZhdWx0LW9wZW5gIElQQyAoc28gdGhlIHZhdWx0IElEIGV4aXN0cyBpblxuICAgKiBgb2JzaWRpYW4uanNvbmApIGFuZCBiZWZvcmUgdGhlIG5ldyB2YXVsdCB3aW5kb3cgZmluaXNoZXMgbG9hZGluZy5cbiAgICpcbiAgICogQHBhcmFtIHdzIC0gQW4gb3BlbiBXZWJTb2NrZXQgdG8gYW4gZXhpc3RpbmcgT2JzaWRpYW4gdGFyZ2V0LlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5hYmxlUGx1Z2luc0luTG9jYWxTdG9yYWdlKHdzOiBXZWJTb2NrZXQsIHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdmF1bHRJZCA9IGdldFZhdWx0SWQodmF1bHRQYXRoKTtcbiAgICBpZiAoIXZhdWx0SWQpIHtcbiAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIENvdWxkIG5vdCBmaW5kIHZhdWx0IElEIFx1MjAxNCBza2lwcGluZyBsb2NhbFN0b3JhZ2UgdHJ1c3QgZmxhZy4nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgIGV4cHJlc3Npb246IGBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgke0pTT04uc3RyaW5naWZ5KGBlbmFibGUtcGx1Z2luLSR7dmF1bHRJZH1gKX0sICd0cnVlJyk7YCxcbiAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICB9KTtcbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBTZXQgZW5hYmxlLXBsdWdpbi0ke3ZhdWx0SWR9IGluIGxvY2FsU3RvcmFnZS5gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmVzIHRoZXJlIGlzIGFuIGFjdGl2ZSBXZWJTb2NrZXQgY29ubmVjdGlvbiB0byB0aGUgY29ycmVjdCB2YXVsdCB0YXJnZXQuXG4gICAqXG4gICAqIFJldXNlcyB0aGUgZXhpc3RpbmcgY29ubmVjdGlvbiBpZiBpdCB0YXJnZXRzIHRoZSByZXF1ZXN0ZWQgdmF1bHQuXG4gICAqIE90aGVyd2lzZSwgZmluZHMgdGhlIGNvcnJlY3QgdGFyZ2V0IGFuZCByZWNvbm5lY3RzLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gdGFyZ2V0LlxuICAgKiBAcmV0dXJucyBUaGUgYWN0aXZlIFdlYlNvY2tldCBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVDb25uZWN0aW9uKHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTxXZWJTb2NrZXQ+IHtcbiAgICBpZiAodGhpcy53cz8ucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4gJiYgdGhpcy5hY3RpdmVWYXVsdFBhdGggPT09IHZhdWx0UGF0aCkge1xuICAgICAgcmV0dXJuIHRoaXMud3M7XG4gICAgfVxuXG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG5cbiAgICBjb25zdCB0YXJnZXQgPSBhd2FpdCB0aGlzLmZpbmRUYXJnZXRGb3JWYXVsdCh2YXVsdFBhdGgpO1xuICAgIHRoaXMud3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgIHRoaXMuYWN0aXZlVmF1bHRQYXRoID0gdmF1bHRQYXRoO1xuICAgIHJldHVybiB0aGlzLndzO1xuICB9XG5cbiAgLyoqXG4gICAqIExhdW5jaGVzIE9ic2lkaWFuIHdpdGggYC0tcmVtb3RlLWRlYnVnZ2luZy1wb3J0YCBhbmQgcG9sbHMgdW50aWwgQ0RQIGJlY29tZXMgYXZhaWxhYmxlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVPYnNpZGlhblJ1bm5pbmcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gT2JzaWRpYW4gQ0RQIG5vdCByZWFjaGFibGUuIFN0YXJ0aW5nIE9ic2lkaWFuIHdpdGggcmVtb3RlIGRlYnVnZ2luZy4uLicpO1xuXG4gICAgY29uc3QgbGF1bmNoQ29tbWFuZCA9IGF3YWl0IGdldE9ic2lkaWFuTGF1bmNoQ29tbWFuZCh0aGlzLmNkcFBvcnQpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBleGVjKGxhdW5jaENvbW1hbmQsIHsgaXNRdWlldDogdHJ1ZSB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFRoZSBsYXVuY2ggY29tbWFuZCBtYXkgZmFpbCBvbiBzb21lIHN5c3RlbXMgXHUyMDE0IHdlJ2xsIHN0aWxsIHRyeSBwb2xsaW5nLlxuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFBvbGxpbmcgZm9yIENEUCBlbmRwb2ludCBhdCAke3RoaXMuY2RwVXJsfSAodGltZW91dD0ke1N0cmluZyhBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcykuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGF3YWl0IGRlbGF5KEFVVE9fU1RBUlRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICAgICAgaWYgKHRhcmdldHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIE9ic2lkaWFuIENEUCByZWFkeSwgJHtTdHJpbmcodGFyZ2V0cy5sZW5ndGgpfSB0YXJnZXQocykgZm91bmQuYCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gQ0RQIG5vdCByZWFkeSB5ZXQsIHJldHJ5aW5nLi4uJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBPYnNpZGlhbiBkaWQgbm90IHN0YXJ0IHdpdGhpbiAke1N0cmluZyhBVVRPX1NUQVJUX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcy4gRW5zdXJlIE9ic2lkaWFuIGlzIGluc3RhbGxlZCBhbmQgYWNjZXNzaWJsZS5gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgQ0RQIHRhcmdldCB0aGF0IGhhcyB0aGUgZ2l2ZW4gdmF1bHQgb3Blbi5cbiAgICpcbiAgICogRm9yIGEgc2luZ2xlIHRhcmdldCwgcmV0dXJucyBpdCBkaXJlY3RseS4gRm9yIG11bHRpcGxlIHRhcmdldHMsXG4gICAqIHByb2JlcyBlYWNoIGJ5IGV2YWx1YXRpbmcgYGdldEJhc2VQYXRoKClgIHRvIGZpbmQgdGhlIG1hdGNoLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggdG8gbWF0Y2guXG4gICAqIEByZXR1cm5zIFRoZSBtYXRjaGluZyBDRFAgdGFyZ2V0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmaW5kVGFyZ2V0Rm9yVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPENkcFRhcmdldD4ge1xuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmdldFBhZ2VUYXJnZXRzKCk7XG5cbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgZm91bmQnKTtcbiAgICB9XG5cbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBlbnN1cmVOb25OdWxsYWJsZSh0YXJnZXRzWzBdKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHRhcmdldCBvZiB0YXJnZXRzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBiYXNlUGF0aCA9IGF3YWl0IHRoaXMucHJvYmVWYXVsdFBhdGgodGFyZ2V0KTtcbiAgICAgICAgaWYgKGJhc2VQYXRoID09PSB2YXVsdFBhdGgpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gTm90IGEgdmF1bHQgdGFyZ2V0IG9yIG5vdCByZWFkeS5cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIENEUCB0YXJnZXQgZm91bmQgZm9yIHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaGVzIHRoZSBsaXN0IG9mIHBhZ2UtdHlwZSB0YXJnZXRzIGZyb20gdGhlIENEUCBgL2pzb25gIGVuZHBvaW50LlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgbGlzdCBvZiBwYWdlIHRhcmdldHMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFBhZ2VUYXJnZXRzKCk6IFByb21pc2U8Q2RwVGFyZ2V0W10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGAke3RoaXMuY2RwVXJsfS9qc29uYCk7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKSBhcyBDZHBUYXJnZXRbXTtcbiAgICByZXR1cm4gdGFyZ2V0cy5maWx0ZXIoKHQpID0+IHQudHlwZSA9PT0gJ3BhZ2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlcyB0aGUgb3duZWQgaW5zdGFuY2UncyB3aW5kb3cgb2ZmLXNjcmVlbiBzbyBhIGhpZGRlbiBydW4gbmV2ZXIgc3RlYWxzXG4gICAqIGZvY3VzLiBVc2VzIEVsZWN0cm9uJ3MgcmVtb3RlIGJyaWRnZSAoYHdpbmRvdy5lbGVjdHJvbi5yZW1vdGVgKSBcdTIwMTQgdGhlIG9ubHlcbiAgICogY3Jvc3MtcGxhdGZvcm0gd2F5IHRvIHJlcG9zaXRpb24gdGhlIHdpbmRvdyBcdTIwMTQgcGxhY2luZyBpdCBqdXN0IGJleW9uZCB0aGVcbiAgICogcmlnaHQgZWRnZSBvZiBhbGwgZGlzcGxheXMuIFRoZSB3aW5kb3cgc3RheXMgXCJ2aXNpYmxlXCIgdG8gQ2hyb21pdW0gKHNvXG4gICAqIHRpbWVycywgYHJlcXVlc3RBbmltYXRpb25GcmFtZWAsIGA6aG92ZXJgLCBhbmQgdHJ1c3RlZCBpbnB1dCBrZWVwIHdvcmtpbmcpLFxuICAgKiB1bmxpa2UgbWluaW1pemluZywgd2hpY2ggd291bGQgZnJlZXplIGByZXF1ZXN0QW5pbWF0aW9uRnJhbWVgLlxuICAgKlxuICAgKiBUaGUgcmVtb3RlIGJyaWRnZSBpcyBub3QgYXZhaWxhYmxlIHRoZSBpbnN0YW50IENEUCBzdGFydHMgc2VydmluZywgc28gdGhpc1xuICAgKiBwb2xscyB1bnRpbCB0aGUgbW92ZSBzdWNjZWVkcy4gQmVzdC1lZmZvcnQ6IGlmIHRoZSB3aW5kb3cgY2Fubm90IGJlIG1vdmVkXG4gICAqIHdpdGhpbiB0aGUgdGltZW91dCwgdGhlIGtlZXAtYWxpdmUgbGF1bmNoIGZsYWdzIHN0aWxsIGFwcGx5IGFuZCB0aGUgcnVuXG4gICAqIHByb2NlZWRzICh3b3JzdCBjYXNlIHRoZSB3aW5kb3cgaXMgYnJpZWZseSB2aXNpYmxlKS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgbW92ZU93bmVkV2luZG93T2Zmc2NyZWVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1vdmVFeHByID0gYCgoKSA9PiB7XG4gICAgICBjb25zdCByZW1vdGUgPSB3aW5kb3cuZWxlY3Ryb24gJiYgd2luZG93LmVsZWN0cm9uLnJlbW90ZTtcbiAgICAgIGlmICghcmVtb3RlIHx8IHR5cGVvZiByZW1vdGUuZ2V0Q3VycmVudFdpbmRvdyAhPT0gJ2Z1bmN0aW9uJykgeyByZXR1cm4gJ25vLWJyaWRnZSc7IH1cbiAgICAgIGNvbnN0IHdpbiA9IHJlbW90ZS5nZXRDdXJyZW50V2luZG93KCk7XG4gICAgICBjb25zdCBkaXNwbGF5cyA9IHJlbW90ZS5zY3JlZW4uZ2V0QWxsRGlzcGxheXMoKTtcbiAgICAgIGNvbnN0IG1heFJpZ2h0ID0gTWF0aC5tYXgoLi4uZGlzcGxheXMubWFwKChkaXNwbGF5KSA9PiBkaXNwbGF5LmJvdW5kcy54ICsgZGlzcGxheS5ib3VuZHMud2lkdGgpKTtcbiAgICAgIHdpbi5zZXRQb3NpdGlvbihtYXhSaWdodCArICR7U3RyaW5nKE9XTkVEX1dJTkRPV19PRkZTQ1JFRU5fTUFSR0lOX0lOX1BJWEVMUyl9LCAwKTtcbiAgICAgIHJldHVybiAnbW92ZWQnO1xuICAgIH0pKClgO1xuXG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgT1dORURfV0lORE9XX0hJREVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gKGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKSlbMF07XG4gICAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgICBjb25zdCB3cyA9IGF3YWl0IHRoaXMuY29ubmVjdFRvVGFyZ2V0KHRhcmdldCk7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5zZW5kQ29tbWFuZCh3cywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgICAgICAgIGV4cHJlc3Npb246IG1vdmVFeHByLFxuICAgICAgICAgICAgICByZXR1cm5CeVZhbHVlOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5yZXN1bHQ/LnJlc3VsdD8udmFsdWUgPT09ICdtb3ZlZCcpIHtcbiAgICAgICAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gTW92ZWQgb3duZWQgT2JzaWRpYW4gd2luZG93IG9mZi1zY3JlZW4gKGhpZGRlbiBtb2RlKS4nKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIENEUCBlbmRwb2ludCAvIHRhcmdldCAvIHJlbW90ZSBicmlkZ2Ugbm90IHJlYWR5IHlldCBcdTIwMTQga2VlcCBwb2xsaW5nLlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoT1dORURfV0lORE9XX0hJREVfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBDb3VsZCBub3QgbW92ZSBvd25lZCB3aW5kb3cgb2ZmLXNjcmVlbiB3aXRoaW4gJHtTdHJpbmcoT1dORURfV0lORE9XX0hJREVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zIChub24tZmF0YWw7IGtlZXAtYWxpdmUgZmxhZ3Mgc3RpbGwgYXBwbGllZCkuYCk7XG4gIH1cblxuICAvKipcbiAgICogT3BlbnMgYSB2YXVsdCBpbiBhbiBhbHJlYWR5LXJ1bm5pbmcgT2JzaWRpYW4gaW5zdGFuY2UgdmlhIHRoZSBgdmF1bHQtb3BlbmBcbiAgICogRWxlY3Ryb24gSVBDIChldmFsdWF0ZWQgdGhyb3VnaCBDRFAgb24gYW4gZXhpc3RpbmcgdGFyZ2V0KSwgdGhlbiBwb2xscyB1bnRpbFxuICAgKiB0aGUgbmV3IHZhdWx0J3Mgd2luZG93IHRhcmdldCBhcHBlYXJzLCBpcyBsYXlvdXQtcmVhZHksIGFuZCBpdHMgdHJ1c3QgZGlhbG9nXG4gICAqIChpZiBhbnkpIGhhcyBiZWVuIGRpc21pc3NlZC5cbiAgICpcbiAgICogU2hhcmVkIGJ5IHRoZSBhdHRhY2gtbW9kZSB7QGxpbmsgcmVnaXN0ZXJWYXVsdH0gYW5kIHRoZSBvd25lZC1tb2RlXG4gICAqIFwiaW5zdGFuY2UgYWxyZWFkeSBsYXVuY2hlZFwiIHBhdGgsIHNvIG9wZW5pbmcgYW4gYWRkaXRpb25hbCB2YXVsdCBuZXZlclxuICAgKiByZWxhdW5jaGVzIHRoZSBwcm9jZXNzICh3aGljaCB3b3VsZCBzdXJmYWNlIHRoZSB2YXVsdCBwaWNrZXIpLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgb3BlblZhdWx0SW5SdW5uaW5nSW5zdGFuY2UodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBSZWdpc3RlcmluZyB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgY29uc3QgdGFyZ2V0cyA9IGF3YWl0IHRoaXMuZ2V0UGFnZVRhcmdldHMoKTtcbiAgICBpZiAodGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gT2JzaWRpYW4gQ0RQIHRhcmdldHMgYXZhaWxhYmxlLiBJcyBPYnNpZGlhbiBydW5uaW5nPycpO1xuICAgIH1cblxuICAgIGNvbnN0IGlwY1dzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQoZW5zdXJlTm9uTnVsbGFibGUodGFyZ2V0c1swXSkpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBlbnN1cmVOYW1lc3BhY2VCb290c3RyYXBwZWQodGhpcywgdmF1bHRQYXRoKTtcbiAgICAgIGNvbnN0IGlwY0V4cHIgPSBgd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcuaXBjU2VuZFN5bmMoJHtKU09OLnN0cmluZ2lmeSh7IGFyZ3M6IFt2YXVsdFBhdGgsIGZhbHNlXSwgY2hhbm5lbDogJ3ZhdWx0LW9wZW4nIH0pfSlgO1xuICAgICAgYXdhaXQgdGhpcy5zZW5kQ29tbWFuZChpcGNXcywgJ1J1bnRpbWUuZXZhbHVhdGUnLCB7XG4gICAgICAgIGF3YWl0UHJvbWlzZTogdHJ1ZSxcbiAgICAgICAgZXhwcmVzc2lvbjogaXBjRXhwcixcbiAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMuZW5hYmxlUGx1Z2luc0luTG9jYWxTdG9yYWdlKGlwY1dzLCB2YXVsdFBhdGgpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpcGNXcy5jbG9zZSgpO1xuICAgIH1cblxuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFBvbGxpbmcgZm9yIHZhdWx0IHRhcmdldCAodGltZW91dD0ke1N0cmluZyhWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcykuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIFZhdWx0IHRhcmdldCBmb3VuZC4nKTtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yTGF5b3V0UmVhZHkodmF1bHRQYXRoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNtaXNzVHJ1c3REaWFsb2codmF1bHRQYXRoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFZhdWx0IHRhcmdldCBub3QgcmVhZHkgeWV0LlxuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFZhdWx0IGF0ICR7dmF1bHRQYXRofSBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcoVkFVTFRfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyl9bXNgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYW1wbGVzIHRoZSB2YXVsdCByZW5kZXJlcidzIGJvb3RzdHJhcCBzdGF0ZSBcdTIwMTQgd2hldGhlciB0aGUgZG9jdW1lbnQgaXNcbiAgICogYGNvbXBsZXRlYCwgd2hldGhlciBgd2luZG93LmFwcGAgZXhpc3RzLCBhbmQgdGhlIGA8Ym9keT5gIGNoaWxkIGNvdW50IFx1MjAxNCBmcm9tXG4gICAqIHRoZSBmaXJzdCBwYWdlIHRhcmdldCwgZm9yIGRlYWQtYm9vdCBkZXRlY3Rpb24uIFRoaXMgd29ya3MgZXZlbiB3aGVuIHRoZSBhcHBcbiAgICogbmV2ZXIgYm9vdHN0cmFwcGVkICh0aGUgcmVuZGVyZXIgcGFnZSB0YXJnZXQgc3RpbGwgZXhpc3RzKSwgd2hpY2ggaXMgZXhhY3RseVxuICAgKiB0aGUgc3RhdGUgaXQgbXVzdCBvYnNlcnZlLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgc2FtcGxlZCBvYnNlcnZhdGlvbiwgb3IgYHVuZGVmaW5lZGAgd2hlbiBubyB0YXJnZXQgaXMgcmVhY2hhYmxlXG4gICAqICAgb3IgdGhlIHByb2JlIGZhaWxlZCAoc28gdGhlIGNhbGxlciBrZWVwcyBwb2xsaW5nIHJhdGhlciB0aGFuIGZhc3QtZmFpbGluZykuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByb2JlUmVuZGVyZXJCb290U3RhdGUoKTogUHJvbWlzZTxSZW5kZXJlckJvb3RPYnNlcnZhdGlvbiB8IHVuZGVmaW5lZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0YXJnZXQgPSAoYXdhaXQgdGhpcy5nZXRQYWdlVGFyZ2V0cygpKVswXTtcbiAgICAgIGlmICghdGFyZ2V0KSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5jb25uZWN0VG9UYXJnZXQodGFyZ2V0KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHByb2JlRXhwciA9IGBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgYm9keUNoaWxkRWxlbWVudENvdW50OiBkb2N1bWVudC5ib2R5ID8gZG9jdW1lbnQuYm9keS5jaGlsZEVsZW1lbnRDb3VudCA6IDAsXG4gICAgICAgICAgaGFzV2luZG93QXBwOiB0eXBlb2Ygd2luZG93LmFwcCAhPT0gJ3VuZGVmaW5lZCcsXG4gICAgICAgICAgaXNEb2N1bWVudENvbXBsZXRlOiBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnXG4gICAgICAgIH0pYDtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmRDb21tYW5kKHdzLCAnUnVudGltZS5ldmFsdWF0ZScsIHtcbiAgICAgICAgICBleHByZXNzaW9uOiBwcm9iZUV4cHIsXG4gICAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSByZXNwb25zZS5yZXN1bHQ/LnJlc3VsdD8udmFsdWU7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZSh2YWx1ZSkgYXMgUmVuZGVyZXJCb290T2JzZXJ2YXRpb247XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJvYmVzIGEgdGFyZ2V0IHRvIGRpc2NvdmVyIHdoaWNoIHZhdWx0IHBhdGggaXQgaGFzIG9wZW4uXG4gICAqXG4gICAqIENyZWF0ZXMgYSB0ZW1wb3JhcnkgV2ViU29ja2V0IGNvbm5lY3Rpb24sIGV2YWx1YXRlcyBgZ2V0QmFzZVBhdGgoKWAsXG4gICAqIGFuZCByZXR1cm5zIHRoZSByZXN1bHQuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgQ0RQIHRhcmdldCB0byBwcm9iZS5cbiAgICogQHJldHVybnMgVGhlIHZhdWx0J3MgYmFzZSBwYXRoLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9iZVZhdWx0UGF0aCh0YXJnZXQ6IENkcFRhcmdldCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgd3MgPSBhd2FpdCB0aGlzLmNvbm5lY3RUb1RhcmdldCh0YXJnZXQpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuc2VuZENvbW1hbmQod3MsICdSdW50aW1lLmV2YWx1YXRlJywge1xuICAgICAgICBleHByZXNzaW9uOiAnYXBwLnZhdWx0LmFkYXB0ZXIuZ2V0QmFzZVBhdGgoKScsXG4gICAgICAgIHJldHVybkJ5VmFsdWU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIFN0cmluZyhyZXNwb25zZS5yZXN1bHQ/LnJlc3VsdD8udmFsdWUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB3cy5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMYXVuY2hlcyBhbmQgY29ubmVjdHMgdG8gYSBoYXJuZXNzLW93bmVkLCBpc29sYXRlZCBPYnNpZGlhbiBpbnN0YW5jZSBmb3IgYVxuICAgKiB2YXVsdDogcHJvdmlzaW9ucyB0aGUgYXNhciAoaWYgYW55KSwgcHJlLXNlZWRzIHRoZSBpc29sYXRlZCBgb2JzaWRpYW4uanNvbmBcbiAgICogc28gdGhlIHZhdWx0IG9wZW5zIGRpcmVjdGx5LCBsYXVuY2hlcyB0aGUgaW5zdGFuY2Ugb24gYSBmcmVlIENEUCBwb3J0LCB0aGVuXG4gICAqIHdhaXRzIHVudGlsIHRoZSB2YXVsdCB3aW5kb3cgaXMgcmVhZHkgYW5kIGRpc21pc3NlcyB0aGUgdHJ1c3QgZGlhbG9nLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVnaXN0ZXJWYXVsdEluT3duZWRJbnN0YW5jZSh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IGVuc3VyZU5vbk51bGxhYmxlKHRoaXMub3duZWRDb25maWcpO1xuXG4gICAgaWYgKHRoaXMub3duZWRJbnN0YW5jZSkge1xuICAgICAgLy8gQSBwcmlvciB2YXVsdCdzIGluc3RhbmNlIGlzIHN0aWxsIHJ1bm5pbmcgaW4gdGhpcyAocGVyLXdvcmtlciBjYWNoZWQpXG4gICAgICAvLyBUcmFuc3BvcnQuIFJlbGF1bmNoIGZyZXNoIGZvciB0aGUgbmV3IHZhdWx0OiByZWxhdW5jaGluZyBvdmVyIHRoZSBsaXZlXG4gICAgICAvLyBJbnN0YW5jZSBpcyBmb3J3YXJkZWQgYnkgRWxlY3Ryb24ncyBzaW5nbGUtaW5zdGFuY2UgbG9jayBvbiB0aGUgc2hhcmVkXG4gICAgICAvLyBVc2VyLWRhdGEgZGlyIGFuZCBzdXJmYWNlcyB0aGUgdmF1bHQgcGlja2VyLCBhbmQgb3BlbmluZyBhIHNlY29uZCB3aW5kb3dcbiAgICAgIC8vIFZpYSBJUEMgbGVhdmVzIHN0YWxlIHdpbmRvd3MgdGhhdCBicmVhayB2YXVsdC10YXJnZXQgcm91dGluZy4gU28ga2lsbCB0aGVcbiAgICAgIC8vIFJ1bm5pbmcgaW5zdGFuY2UsIHdhaXQgZm9yIGl0IHRvIGV4aXQgKHJlbGVhc2luZyB0aGUgbG9jayksIHRoZW4gbGF1bmNoXG4gICAgICAvLyBBZ2FpbiBiZWxvdyB3aXRoIHRoZSBuZXcgdmF1bHQgcHJlLXNlZWRlZCBcdTIwMTQgZWFjaCB2YXVsdCBnZXRzIGEgcHJpc3RpbmVcbiAgICAgIC8vIFNpbmdsZS13aW5kb3cgaW5zdGFuY2Ugb3BlbmVkIGRpcmVjdGx5LCBuZXZlciB0aGUgc2VsZWN0b3IuXG4gICAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBSZWxhdW5jaGluZyBvd25lZCBpbnN0YW5jZSBmb3IgbmV3IHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcbiAgICAgIHRoaXMuZGlzY29ubmVjdCgpO1xuICAgICAgY29uc3QgcHJldmlvdXNDZHBVcmwgPSB0aGlzLmNkcFVybDtcbiAgICAgIHRoaXMub3duZWRJbnN0YW5jZS5raWxsKCk7XG4gICAgICB0aGlzLm93bmVkSW5zdGFuY2UgPSB1bmRlZmluZWQ7XG4gICAgICBhd2FpdCB0aGlzLndhaXRGb3JJbnN0YW5jZUV4aXQocHJldmlvdXNDZHBVcmwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2coYFtjZHAtdHJhbnNwb3J0XSBMYXVuY2hpbmcgb3duZWQgT2JzaWRpYW4gaW5zdGFuY2UgZm9yIHZhdWx0OiAke3ZhdWx0UGF0aH1gKTtcbiAgICB9XG5cbiAgICBta2RpclN5bmMoY29uZmlnLnVzZXJEYXRhRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBpZiAoY29uZmlnLmFzYXIpIHtcbiAgICAgIGNvcHlBc2FySW50b1VzZXJEYXRhKGNvbmZpZy5hc2FyLnBhdGgsIGNvbmZpZy5hc2FyLnZlcnNpb24sIGNvbmZpZy51c2VyRGF0YURpcik7XG4gICAgfVxuXG4gICAgY29uc3QgdmF1bHRJZCA9IHJhbmRvbUJ5dGVzKFZBVUxUX0lEX0JZVEVfTEVOR1RIKS50b1N0cmluZygnaGV4Jyk7XG4gICAgY29uc3Qgb2JzaWRpYW5Kc29uID0ge1xuICAgICAgdXBkYXRlRGlzYWJsZWQ6IHRydWUsXG4gICAgICB2YXVsdHM6IHsgW3ZhdWx0SWRdOiB7IG9wZW46IHRydWUsIHBhdGg6IHZhdWx0UGF0aCwgdHM6IERhdGUubm93KCkgfSB9XG4gICAgfTtcbiAgICB3cml0ZUZpbGVTeW5jKGpvaW4oY29uZmlnLnVzZXJEYXRhRGlyLCAnb2JzaWRpYW4uanNvbicpLCBKU09OLnN0cmluZ2lmeShvYnNpZGlhbkpzb24pKTtcblxuICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgbGF1bmNoT3duZWRPYnNpZGlhbkluc3RhbmNlKHtcbiAgICAgIGNkcEhvc3Q6IHRoaXMuY2RwSG9zdCxcbiAgICAgIGV4ZVBhdGg6IGNvbmZpZy5leGVQYXRoLFxuICAgICAgZXh0cmFBcmdzOiBbXG4gICAgICAgIC4uLnJlc29sdmVPd25lZEhpZGRlbkxhdW5jaEFyZ3ModGhpcy5pc09ic2lkaWFuQXBwVmlzaWJsZSksXG4gICAgICAgIC4uLnJlc29sdmVTYW5kYm94TGF1bmNoQXJncyh0aGlzLnNob3VsZERpc2FibGVTYW5kYm94KVxuICAgICAgXSxcbiAgICAgIHVzZXJEYXRhRGlyOiBjb25maWcudXNlckRhdGFEaXJcbiAgICB9KTtcbiAgICB0aGlzLm93bmVkSW5zdGFuY2UgPSBpbnN0YW5jZTtcbiAgICB0aGlzLmNkcFBvcnQgPSBpbnN0YW5jZS5wb3J0O1xuICAgIHRoaXMuY2RwVXJsID0gaW5zdGFuY2UuY2RwVXJsO1xuXG4gICAgaWYgKHNob3VsZEhpZGVPYnNpZGlhbkFwcCh0aGlzLmlzT2JzaWRpYW5BcHBWaXNpYmxlKSkge1xuICAgICAgYXdhaXQgdGhpcy5tb3ZlT3duZWRXaW5kb3dPZmZzY3JlZW4oKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLndhaXRGb3JPd25lZFZhdWx0UmVhZHkodmF1bHRQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBhIENEUCBjb21tYW5kIG92ZXIgV2ViU29ja2V0IGFuZCB3YWl0cyBmb3IgdGhlIHJlc3BvbnNlLlxuICAgKlxuICAgKiBAcGFyYW0gd3MgLSBUaGUgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSBtZXRob2QgLSBUaGUgQ0RQIG1ldGhvZCBuYW1lLlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIENEUCBtZXRob2QgcGFyYW1ldGVycy5cbiAgICogQHJldHVybnMgVGhlIENEUCByZXNwb25zZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2VuZENvbW1hbmQod3M6IFdlYlNvY2tldCwgbWV0aG9kOiBzdHJpbmcsIHBhcmFtczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQcm9taXNlPENkcFJlc3BvbnNlPiB7XG4gICAgY29uc3QgaWQgPSArK3RoaXMubWVzc2FnZUlkO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPENkcFJlc3BvbnNlPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHdzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBoYW5kbGVyKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQ0RQIGNvbW1hbmQgdGltZWQgb3V0IGFmdGVyICR7U3RyaW5nKHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyl9bXM6ICR7bWV0aG9kfWApKTtcbiAgICAgIH0sIHRoaXMuY29tbWFuZFRpbWVvdXRJbk1pbGxpc2Vjb25kcyk7XG5cbiAgICAgIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IE1lc3NhZ2VFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCBtc2cgPSBKU09OLnBhcnNlKFN0cmluZyhldmVudC5kYXRhKSkgYXMgQ2RwUmVzcG9uc2U7XG4gICAgICAgIGlmIChtc2cuaWQgPT09IGlkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgIHdzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBoYW5kbGVyKTtcbiAgICAgICAgICByZXNvbHZlKG1zZyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGhhbmRsZXIpO1xuICAgICAgd3Muc2VuZChKU09OLnN0cmluZ2lmeSh7IGlkLCBtZXRob2QsIHBhcmFtcyB9KSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUG9sbHMgYSBraWxsZWQgb3duZWQgaW5zdGFuY2UncyBDRFAgZW5kcG9pbnQgdW50aWwgaXQgc3RvcHMgcmVzcG9uZGluZyxcbiAgICogY29uZmlybWluZyB0aGUgcHJvY2VzcyBoYXMgZXhpdGVkIGFuZCByZWxlYXNlZCBFbGVjdHJvbidzIHNpbmdsZS1pbnN0YW5jZVxuICAgKiBsb2NrIG9uIHRoZSBzaGFyZWQgdXNlci1kYXRhIGRpciBiZWZvcmUgYSBmcmVzaCBpbnN0YW5jZSBpcyBsYXVuY2hlZCBpbnRvIGl0LlxuICAgKlxuICAgKiBAcGFyYW0gY2RwVXJsIC0gVGhlIENEUCBVUkwgb2YgdGhlIGluc3RhbmNlIHRoYXQgd2FzIGp1c3Qga2lsbGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB3YWl0Rm9ySW5zdGFuY2VFeGl0KGNkcFVybDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nKGBbY2RwLXRyYW5zcG9ydF0gV2FpdGluZyBmb3IgcHJldmlvdXMgb3duZWQgaW5zdGFuY2UgYXQgJHtjZHBVcmx9IHRvIGV4aXQuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7Y2RwVXJsfS9qc29uYCk7XG4gICAgICAgIGF3YWl0IHJlc3BvbnNlLmJvZHk/LmNhbmNlbCgpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFRoZSBlbmRwb2ludCBpcyBnb25lOiB0aGUgcHJvY2VzcyBoYXMgZXhpdGVkIGFuZCByZWxlYXNlZCB0aGUgbG9jay5cbiAgICAgICAgYXdhaXQgZGVsYXkoSU5TVEFOQ0VfRVhJVF9TRVRUTEVfREVMQVlfSU5fTUlMTElTRUNPTkRTKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgYXdhaXQgZGVsYXkoVkFVTFRfUE9MTF9JTlRFUlZBTF9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIH1cbiAgICBsb2coJ1tjZHAtdHJhbnNwb3J0XSBQcmV2aW91cyBpbnN0YW5jZSBzdGlsbCByZXNwb25kZWQgYmVmb3JlIHRpbWVvdXQ7IHJlbGF1bmNoaW5nIGFueXdheS4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXYWl0cyBmb3IgdGhlIHZhdWx0J3MgYGFwcC53b3Jrc3BhY2VgIHRvIHJlYWNoIGxheW91dC1yZWFkeSBzdGF0ZS5cbiAgICpcbiAgICogYGZpbmRUYXJnZXRGb3JWYXVsdGAgcmV0dXJucyBhcyBzb29uIGFzIGBhcHAudmF1bHQuYWRhcHRlci5nZXRCYXNlUGF0aCgpYFxuICAgKiBtYXRjaGVzIFx1MjAxNCB3aGljaCBpcyB0cnVlIHNob3J0bHkgYWZ0ZXIgdGhlIGBBcHBgIGNvbnN0cnVjdG9yIHJ1bnMsIGJlZm9yZVxuICAgKiBgcGx1Z2lucy5pbml0aWFsaXplKClgIChhbmQgYW55IHRydXN0IGRpYWxvZykgaGFzIGV4ZWN1dGVkLiBCb290c3RyYXBwaW5nXG4gICAqIHRoZSBuYW1lc3BhY2UgYW5kIGNhbGxpbmcgYHBvbGxWYXVsdEJhc2VQYXRoKClgIGF3YWl0cyBgbGF5b3V0UmVhZHlgLCBzb1xuICAgKiBieSB0aGUgdGltZSB0aGlzIHJldHVybnMgdGhlIGRpYWxvZyBoYXMgZWl0aGVyIHJlbmRlcmVkIG9yIGlzIG5vdCBnb2luZ1xuICAgKiB0byByZW5kZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCB0byBldmFsdWF0ZSBpbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd2FpdEZvckxheW91dFJlYWR5KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZW5zdXJlTmFtZXNwYWNlQm9vdHN0cmFwcGVkKHRoaXMsIHZhdWx0UGF0aCk7XG4gICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgnd2luZG93Ll9fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmcucG9sbFZhdWx0QmFzZVBhdGgoKScsIHsgY3dkOiB2YXVsdFBhdGggfSk7XG4gIH1cblxuICAvKipcbiAgICogUG9sbHMgdGhlIG93bmVkIGluc3RhbmNlIHVudGlsIHRoZSB2YXVsdCB0YXJnZXQgZXhpc3RzLCBsYXlvdXQgaXMgcmVhZHksIGFuZFxuICAgKiB0aGUgdHJ1c3QgZGlhbG9nIChpZiBhbnkpIGhhcyBiZWVuIGRpc21pc3NlZC5cbiAgICpcbiAgICogQmV0d2VlbiByZWFkaW5lc3MgYXR0ZW1wdHMgaXQgYWxzbyBjaGVja3MgZm9yIGEgKipkZWFkIGJvb3QqKiBcdTIwMTQgdGhlIHJlbmRlcmVyXG4gICAqIGxvYWRlZCAoYGRvY3VtZW50LnJlYWR5U3RhdGVgIGAnY29tcGxldGUnYCkgYnV0IHRoZSBhcHAgbmV2ZXIgYm9vdHN0cmFwcGVkXG4gICAqIChlbXB0eSBgPGJvZHk+YCwgbm8gYHdpbmRvdy5hcHBgKSwgdGhlIHRlcm1pbmFsIHN0YXRlIHdoZW4gdGhlIGFzYXIgY2Fubm90XG4gICAqIHJ1biBvbiB0aGUgbGF1bmNoZWQgRWxlY3Ryb24gc2hlbGwuIE9uY2UgdGhhdCBzdGF0ZSBoYXMgaGVsZCBmb3IgdGhlXG4gICAqIGNvbmZpZ3VyZWQgZ3JhY2Ugd2luZG93IGl0IHRocm93cyBhIHtAbGluayBSZW5kZXJlckZhaWxlZFRvSW5pdGlhbGl6ZUVycm9yfVxuICAgKiBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIHdhaXRpbmcgb3V0IHRoZSBmdWxsIHJlYWRpbmVzcyB0aW1lb3V0LiBBIGdyYWNlIG9mXG4gICAqIGAwYCBkaXNhYmxlcyB0aGUgZmFzdC1mYWlsLiBUaGUgZ3JhY2UgY2xvY2sgc3RhcnRzIHdoZW4gdGhlIHJlbmRlcmVyIGZpcnN0XG4gICAqIHJlcG9ydHMgYGNvbXBsZXRlYCwgc28gYSBzbG93IGxvYWQgYmVmb3JlIHRoZW4gaXMgbmV2ZXIgY291bnRlZCBhZ2FpbnN0IGl0LlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IGZvbGRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd2FpdEZvck93bmVkVmF1bHRSZWFkeSh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZyhgW2NkcC10cmFuc3BvcnRdIFdhaXRpbmcgZm9yIG93bmVkIHZhdWx0IHRvIGJlY29tZSByZWFkeSAodGltZW91dD0ke1N0cmluZyhWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTKX1tcykuLi5gKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBWQVVMVF9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIGxldCBkb2N1bWVudENvbXBsZXRlU2luY2U6IG51bGwgfCBudW1iZXIgPSBudWxsO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZmluZFRhcmdldEZvclZhdWx0KHZhdWx0UGF0aCk7XG4gICAgICAgIGF3YWl0IHRoaXMud2FpdEZvckxheW91dFJlYWR5KHZhdWx0UGF0aCk7XG4gICAgICAgIGF3YWl0IHRoaXMuZGlzbWlzc1RydXN0RGlhbG9nKHZhdWx0UGF0aCk7XG4gICAgICAgIGxvZygnW2NkcC10cmFuc3BvcnRdIE93bmVkIHZhdWx0IGlzIHJlYWR5LicpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gVmF1bHQgdGFyZ2V0IG5vdCByZWFkeSB5ZXQuXG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmRlYWRCb290R3JhY2VJbk1pbGxpc2Vjb25kcyA+IDApIHtcbiAgICAgICAgY29uc3Qgb2JzZXJ2YXRpb24gPSBhd2FpdCB0aGlzLnByb2JlUmVuZGVyZXJCb290U3RhdGUoKTtcbiAgICAgICAgaWYgKG9ic2VydmF0aW9uKSB7XG4gICAgICAgICAgaWYgKG9ic2VydmF0aW9uLmlzRG9jdW1lbnRDb21wbGV0ZSAmJiBkb2N1bWVudENvbXBsZXRlU2luY2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGRvY3VtZW50Q29tcGxldGVTaW5jZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGhhc0dyYWNlRWxhcHNlZCA9IGRvY3VtZW50Q29tcGxldGVTaW5jZSAhPT0gbnVsbFxuICAgICAgICAgICAgJiYgRGF0ZS5ub3coKSAtIGRvY3VtZW50Q29tcGxldGVTaW5jZSA+PSB0aGlzLmRlYWRCb290R3JhY2VJbk1pbGxpc2Vjb25kcztcbiAgICAgICAgICBpZiAoY2hlY2tSZW5kZXJlckJvb3RTdGF0ZSh7IC4uLm9ic2VydmF0aW9uLCBoYXNHcmFjZUVsYXBzZWQgfSkgPT09ICdkZWFkJykge1xuICAgICAgICAgICAgbG9nKCdbY2RwLXRyYW5zcG9ydF0gT3duZWQgcmVuZGVyZXIgZmFpbGVkIHRvIGluaXRpYWxpemUgKGRlYWQgYm9vdCk7IGZhaWxpbmcgZmFzdC4nKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBSZW5kZXJlckZhaWxlZFRvSW5pdGlhbGl6ZUVycm9yKHZhdWx0UGF0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGRlbGF5KFZBVUxUX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBPd25lZCB2YXVsdCBhdCAke3ZhdWx0UGF0aH0gZGlkIG5vdCBiZWNvbWUgcmVhZHkgd2l0aGluICR7U3RyaW5nKFZBVUxUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMpfW1zYCk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBnaXZlbiBkZWxheS5cbiAqXG4gKiBAcGFyYW0gbXMgLSBUaGUgZGVsYXkgaW4gbWlsbGlzZWNvbmRzLlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgdGhlIGRlbGF5LlxuICovXG5mdW5jdGlvbiBkZWxheShtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBwbGF0Zm9ybS1zcGVjaWZpYyBjb21tYW5kIHRvIGxhdW5jaCBPYnNpZGlhbiB3aXRoIHJlbW90ZSBkZWJ1Z2dpbmcgZW5hYmxlZC5cbiAqXG4gKiBSZXNvbHZlcyB0aGUgYWN0dWFsIGluc3RhbGxlZCBPYnNpZGlhbiBleGVjdXRhYmxlIChjb3ZlcmluZyBpbnN0YWxsZXItYmFzZWRcbiAqIGFuZCBgUEFUSGAtYmFzZWQgaW5zdGFsbHMgc3VjaCBhcyBgc2Nvb3BgKSBhbmQgdmVyaWZpZXMgaXQgZXhpc3RzIGJlZm9yZVxuICogcmV0dXJuaW5nIGEgY29tbWFuZC4gVGhyb3dzIGlmIE9ic2lkaWFuIGlzIG5vdCBpbnN0YWxsZWQuXG4gKlxuICogQHBhcmFtIHBvcnQgLSBUaGUgQ0RQIHBvcnQgdG8gdXNlLlxuICogQHJldHVybnMgVGhlIHNoZWxsIGNvbW1hbmQgc3RyaW5nLlxuICogQHRocm93cyBFcnJvciBpZiBPYnNpZGlhbiBjYW5ub3QgYmUgbG9jYXRlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0T2JzaWRpYW5MYXVuY2hDb21tYW5kKHBvcnQ6IG51bWJlcik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGV4ZVBhdGggPSBhd2FpdCByZXNvbHZlT2JzaWRpYW5FeGVjdXRhYmxlKCk7XG4gIGNvbnN0IGZsYWcgPSBgLS1yZW1vdGUtZGVidWdnaW5nLXBvcnQ9JHtTdHJpbmcocG9ydCl9YDtcblxuICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgIHJldHVybiBgc3RhcnQgXCJcIiBcIiR7ZXhlUGF0aH1cIiAke2ZsYWd9YDtcbiAgfVxuXG4gIHJldHVybiBgXCIke2V4ZVBhdGh9XCIgJHtmbGFnfSAmYDtcbn1cblxuLyoqXG4gKiBBdHRlbXB0cyB0byByZW1vdmUgYSBkaXJlY3RvcnkgcmVjdXJzaXZlbHksIHJldHVybmluZyB3aGV0aGVyIGl0IHN1Y2NlZWRlZC5cbiAqXG4gKiBAcGFyYW0gZGlyIC0gVGhlIGRpcmVjdG9yeSB0byByZW1vdmUuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgcmVtb3ZlZCwgYGZhbHNlYCBpZiB0aGUgcmVtb3ZhbCB0aHJldyAoZS5nLiBoYW5kbGVzIGhlbGQpLlxuICovXG5mdW5jdGlvbiB0cnlSZW1vdmVEaXIoZGlyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBybVN5bmMoZGlyLCB7IGZvcmNlOiB0cnVlLCByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKiB2OCBpZ25vcmUgc3RvcCAqL1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFxQkEseUJBQTRCO0FBQzVCLHFCQUlPO0FBQ1AsdUJBQXFCO0FBQ3JCLDBCQUFvQjtBQVVwQixrQ0FBMEM7QUFDMUMsa0JBQXFCO0FBQ3JCLGlCQUFvQjtBQUNwQixpQ0FBNEM7QUFDNUMsNkJBSU87QUFDUCxpQ0FBMEM7QUFDMUMsK0JBQTRDO0FBQzVDLHFDQUFxQztBQUNyQyxxQ0FHTztBQUNQLGlEQUFnRDtBQUNoRCx5QkFBa0M7QUFDbEMsd0JBSU87QUFvSlAsTUFBTSxrQ0FBa0M7QUFDeEMsTUFBTSx1QkFBdUI7QUFDN0IsTUFBTSx1Q0FBdUM7QUFDN0MsTUFBTSw4Q0FBOEM7QUFDcEQsTUFBTSxZQUFZO0FBQ2xCLE1BQU0sc0NBQXNDO0FBQzVDLE1BQU0scUNBQXFDO0FBQzNDLE1BQU0sb0NBQW9DO0FBQzFDLE1BQU0sMkNBQTJDO0FBQ2pELE1BQU0scUNBQXFDO0FBQzNDLE1BQU0sNkNBQTZDO0FBQ25ELE1BQU0sMENBQTBDO0FBQ2hELE1BQU0sNENBQTRDO0FBQ2xELE1BQU0sa0RBQWtEO0FBUWpELE1BQU0sb0JBQWlEO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFJNUMsV0FBVztBQUFBLEVBQ25CLGtCQUFpQztBQUFBLEVBQ3hCO0FBQUEsRUFDVDtBQUFBLEVBQ0E7QUFBQSxFQUNTO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDVCxZQUFZO0FBQUEsRUFDSDtBQUFBLEVBQ1Q7QUFBQSxFQUNTO0FBQUEsRUFDVCxLQUF1QjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU94QixZQUFZLFFBQW9DO0FBQ3JELFNBQUssVUFBVSxRQUFRLFdBQVc7QUFDbEMsU0FBSywrQkFBK0IsUUFBUSxnQ0FBZ0M7QUFDNUUsU0FB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
@@ -16,6 +16,7 @@
16
16
  *
17
17
  * Requirements: Node.js 22+ (uses built-in `WebSocket` and `fetch` globals).
18
18
  */
19
+ import type { InstallerCompatibility } from './installer-compatibility.cjs';
19
20
  import type { ObsidianTransport, TransportEvalOptions } from './transport.cjs';
20
21
  /**
21
22
  * Configuration for the CDP transport.
@@ -36,6 +37,13 @@ export interface DesktopCdpTransportConfig {
36
37
  * Defaults to `30000`.
37
38
  */
38
39
  commandTimeoutInMilliseconds?: number;
40
+ /**
41
+ * Grace window in milliseconds for fast-failing a dead boot of the owned
42
+ * instance (empty `<body>` with no `window.app` after the renderer reached
43
+ * `document.readyState` `'complete'`). Defaults to
44
+ * {@link DEFAULT_DEAD_BOOT_GRACE_IN_MILLISECONDS}. `0` disables fast-fail.
45
+ */
46
+ deadBootGraceInMilliseconds?: number;
39
47
  /**
40
48
  * When attaching (i.e. {@link cdpPort} is set), marks the target as a
41
49
  * **harness-owned, already-prepared** instance. Suppresses the user-scope
@@ -49,7 +57,7 @@ export interface DesktopCdpTransportConfig {
49
57
  * its window is moved off-screen after launch. Only meaningful in owned mode;
50
58
  * attach mode never touches the (user's) window.
51
59
  *
52
- * @default `false`
60
+ * @default `true`
53
61
  */
54
62
  isObsidianAppVisible?: boolean;
55
63
  /**
@@ -57,6 +65,15 @@ export interface DesktopCdpTransportConfig {
57
65
  * instead of attaching to a running one. This is the default desktop mode.
58
66
  */
59
67
  ownedInstance?: OwnedInstanceConfig;
68
+ /**
69
+ * Whether to launch the owned instance with Chromium's sandbox disabled
70
+ * (`--no-sandbox`). Needed to boot on Linux without a correctly-configured
71
+ * setuid `chrome-sandbox` helper (e.g. an extracted portable shell, or CI as a
72
+ * non-root user); harmless on Windows/macOS. Only meaningful in owned mode.
73
+ *
74
+ * @default `false`
75
+ */
76
+ shouldDisableSandbox?: boolean;
60
77
  }
61
78
  /**
62
79
  * An asar to provision into a harness-owned instance's user-data dir before launch.
@@ -76,6 +93,12 @@ export interface OwnedInstanceAsar {
76
93
  export interface OwnedInstanceConfig {
77
94
  /** Optional asar to provision into {@link userDataDir} before launch. */
78
95
  readonly asar?: OwnedInstanceAsar | undefined;
96
+ /**
97
+ * The resolved installer↔app compatibility verdict, when it could be determined
98
+ * (an asar-swap onto a known shell version). Surfaced by
99
+ * {@link DesktopCdpTransport.getCompatibility}.
100
+ */
101
+ readonly compatibility?: InstallerCompatibility | undefined;
79
102
  /** Absolute path to the Obsidian shell executable to launch. */
80
103
  readonly exePath: string;
81
104
  /**
@@ -109,11 +132,13 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
109
132
  private cdpPort;
110
133
  private cdpUrl;
111
134
  private readonly commandTimeoutInMilliseconds;
135
+ private readonly deadBootGraceInMilliseconds;
112
136
  private readonly isHarnessOwnedInstance;
113
137
  private readonly isObsidianAppVisible;
114
138
  private messageId;
115
139
  private readonly ownedConfig;
116
140
  private ownedInstance;
141
+ private readonly shouldDisableSandbox;
117
142
  private ws;
118
143
  /**
119
144
  * Creates a new CDP transport.
@@ -145,6 +170,15 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
145
170
  * @returns The normalized result string.
146
171
  */
147
172
  evaluate(expression: string, options: TransportEvalOptions): Promise<string>;
173
+ /**
174
+ * Returns the resolved installer↔app compatibility verdict for this owned
175
+ * instance, so callers can assert on it. Returns `undefined` when this is not
176
+ * an owned instance, or the verdict could not be determined (e.g. an
177
+ * undetectable shell version, or the app version is absent from the table).
178
+ *
179
+ * @returns The compatibility verdict, or `undefined`.
180
+ */
181
+ getCompatibility(): InstallerCompatibility | undefined;
148
182
  /**
149
183
  * Returns the CDP endpoint of the owned, launched instance so the global setup
150
184
  * can hand it to test workers (which then **attach** to it instead of
@@ -268,6 +302,17 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
268
302
  * @param vaultPath - The absolute path to the vault folder.
269
303
  */
270
304
  private openVaultInRunningInstance;
305
+ /**
306
+ * Samples the vault renderer's bootstrap state — whether the document is
307
+ * `complete`, whether `window.app` exists, and the `<body>` child count — from
308
+ * the first page target, for dead-boot detection. This works even when the app
309
+ * never bootstrapped (the renderer page target still exists), which is exactly
310
+ * the state it must observe.
311
+ *
312
+ * @returns The sampled observation, or `undefined` when no target is reachable
313
+ * or the probe failed (so the caller keeps polling rather than fast-failing).
314
+ */
315
+ private probeRendererBootState;
271
316
  /**
272
317
  * Probes a target to discover which vault path it has open.
273
318
  *
@@ -321,6 +366,15 @@ export declare class DesktopCdpTransport implements ObsidianTransport {
321
366
  * Polls the owned instance until the vault target exists, layout is ready, and
322
367
  * the trust dialog (if any) has been dismissed.
323
368
  *
369
+ * Between readiness attempts it also checks for a **dead boot** — the renderer
370
+ * loaded (`document.readyState` `'complete'`) but the app never bootstrapped
371
+ * (empty `<body>`, no `window.app`), the terminal state when the asar cannot
372
+ * run on the launched Electron shell. Once that state has held for the
373
+ * configured grace window it throws a {@link RendererFailedToInitializeError}
374
+ * immediately instead of waiting out the full readiness timeout. A grace of
375
+ * `0` disables the fast-fail. The grace clock starts when the renderer first
376
+ * reports `complete`, so a slow load before then is never counted against it.
377
+ *
324
378
  * @param vaultPath - The absolute path to the vault folder.
325
379
  */
326
380
  private waitForOwnedVaultReady;