obsidian-integration-testing 11.0.0 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/cjs/adb-device-list.cjs +54 -0
- package/dist/lib/cjs/adb-device-list.d.cts +72 -0
- package/dist/lib/cjs/android-sdk.cjs +52 -0
- package/dist/lib/cjs/android-sdk.d.cts +29 -0
- package/dist/lib/cjs/app-startup-progress.cjs +87 -0
- package/dist/lib/cjs/app-startup-progress.d.cts +128 -0
- package/dist/lib/cjs/appium-server-marker.cjs +112 -0
- package/dist/lib/cjs/appium-server-marker.d.cts +103 -0
- package/dist/lib/cjs/avd-probe-verdict.cjs +90 -0
- package/dist/lib/cjs/avd-probe-verdict.d.cts +175 -0
- package/dist/lib/cjs/cli.cjs +104 -19
- package/dist/lib/cjs/cli.d.cts +16 -8
- package/dist/lib/cjs/community-plugin-registry.cjs +52 -0
- package/dist/lib/cjs/community-plugin-registry.d.cts +116 -0
- package/dist/lib/cjs/config-directory-fallback-error.cjs +57 -0
- package/dist/lib/cjs/config-directory-fallback-error.d.cts +64 -0
- package/dist/lib/cjs/config-directory.cjs +46 -0
- package/dist/lib/cjs/config-directory.d.cts +45 -0
- package/dist/lib/cjs/connect-to-cdp.cjs +13 -7
- package/dist/lib/cjs/connect-to-cdp.d.cts +19 -0
- package/dist/lib/cjs/context-provider.cjs +12 -1
- package/dist/lib/cjs/context-provider.d.cts +26 -3
- package/dist/lib/cjs/demo-vault-bootstrap.cjs +148 -0
- package/dist/lib/cjs/demo-vault-bootstrap.d.cts +114 -0
- package/dist/lib/cjs/demo-vault-populate.cjs +38 -10
- package/dist/lib/cjs/demo-vault-populate.d.cts +70 -0
- package/dist/lib/cjs/device-readiness.cjs +38 -3
- package/dist/lib/cjs/device-readiness.d.cts +83 -9
- package/dist/lib/cjs/emulator-arguments.cjs +6 -2
- package/dist/lib/cjs/emulator-arguments.d.cts +26 -0
- package/dist/lib/cjs/emulator-backend.cjs +71 -0
- package/dist/lib/cjs/emulator-backend.d.cts +76 -0
- package/dist/lib/cjs/emulator-liveness.cjs +72 -0
- package/dist/lib/cjs/emulator-liveness.d.cts +158 -0
- package/dist/lib/cjs/emulator-snapshot.cjs +57 -0
- package/dist/lib/cjs/emulator-snapshot.d.cts +68 -0
- package/dist/lib/cjs/eval-in-obsidian.cjs +1 -1
- package/dist/lib/cjs/eval-in-obsidian.d.cts +42 -13
- package/dist/lib/cjs/global-setup-core.cjs +30 -30
- package/dist/lib/cjs/global-setup-core.d.cts +27 -2
- package/dist/lib/cjs/headless-vault-config.cjs +51 -0
- package/dist/lib/cjs/headless-vault-config.d.cts +67 -0
- package/dist/lib/cjs/index.cjs +24 -1
- package/dist/lib/cjs/index.d.cts +14 -5
- package/dist/lib/cjs/installer-asset.cjs +1 -1
- package/dist/lib/cjs/installer-asset.d.cts +1 -1
- package/dist/lib/cjs/integration-setup-failed-error.cjs +62 -0
- package/dist/lib/cjs/integration-setup-failed-error.d.cts +66 -0
- package/dist/lib/cjs/jest/global-setup.cjs +2 -2
- package/dist/lib/cjs/jest/global-setup.d.cts +5 -1
- package/dist/lib/cjs/kill-process-tree.cjs +18 -7
- package/dist/lib/cjs/kill-process-tree.d.cts +10 -2
- package/dist/lib/cjs/library.cjs +1 -1
- package/dist/lib/cjs/mobile-input.cjs +173 -0
- package/dist/lib/cjs/mobile-input.d.cts +156 -0
- package/dist/lib/cjs/namespace-bootstrap.cjs +92 -9
- package/dist/lib/cjs/obsidian-installer.cjs +1 -1
- package/dist/lib/cjs/obsidian-instance.cjs +52 -3
- package/dist/lib/cjs/obsidian-instance.d.cts +12 -0
- package/dist/lib/cjs/obsidian-metadata.cjs +123 -17
- package/dist/lib/cjs/obsidian-metadata.d.cts +17 -6
- package/dist/lib/cjs/obsidian-version-switch.cjs +3 -3
- package/dist/lib/cjs/open-obsidian-settings-tab.cjs +1 -1
- package/dist/lib/cjs/open-obsidian-settings-tab.d.cts +3 -2
- package/dist/lib/cjs/owned-instance-exit-marker.cjs +99 -0
- package/dist/lib/cjs/owned-instance-exit-marker.d.cts +106 -0
- package/dist/lib/cjs/owned-instance-exited-error.cjs +106 -0
- package/dist/lib/cjs/owned-instance-exited-error.d.cts +98 -0
- package/dist/lib/cjs/owned-vault-seed.cjs +9 -5
- package/dist/lib/cjs/owned-vault-seed.d.cts +24 -3
- package/dist/lib/cjs/parent-liveness.cjs +42 -5
- package/dist/lib/cjs/parent-liveness.d.cts +37 -5
- package/dist/lib/cjs/port-owner.cjs +61 -0
- package/dist/lib/cjs/port-owner.d.cts +47 -0
- package/dist/lib/cjs/process-capture.cjs +62 -0
- package/dist/lib/cjs/process-capture.d.cts +83 -0
- package/dist/lib/cjs/process-exit-message.cjs +14 -8
- package/dist/lib/cjs/process-exit-message.d.cts +37 -3
- package/dist/lib/cjs/process-liveness.cjs +51 -0
- package/dist/lib/cjs/process-liveness.d.cts +18 -0
- package/dist/lib/cjs/release-catalog.cjs +73 -0
- package/dist/lib/cjs/release-catalog.d.cts +125 -0
- package/dist/lib/cjs/run-version-matrix.cjs +1 -1
- package/dist/lib/cjs/run-version-matrix.d.cts +1 -1
- package/dist/lib/cjs/teardown-verdict.cjs +53 -0
- package/dist/lib/cjs/teardown-verdict.d.cts +69 -0
- package/dist/lib/cjs/temporary-vault.cjs +43 -8
- package/dist/lib/cjs/temporary-vault.d.cts +47 -5
- package/dist/lib/cjs/transport-appium.cjs +223 -17
- package/dist/lib/cjs/transport-appium.d.cts +104 -3
- package/dist/lib/cjs/transport-desktop-cdp.cjs +201 -6
- package/dist/lib/cjs/transport-desktop-cdp.d.cts +100 -0
- package/dist/lib/cjs/transport-factory.cjs +1165 -142
- package/dist/lib/cjs/transport-factory.d.cts +10 -1
- package/dist/lib/cjs/transport-options.cjs +11 -3
- package/dist/lib/cjs/transport-options.d.cts +131 -12
- package/dist/lib/cjs/transport.cjs +1 -1
- package/dist/lib/cjs/transport.d.cts +7 -1
- package/dist/lib/cjs/vault-plugin-install.cjs +40 -0
- package/dist/lib/cjs/vault-plugin-install.d.cts +64 -0
- package/dist/lib/cjs/vault-teardown-verdict.cjs +42 -0
- package/dist/lib/cjs/vault-teardown-verdict.d.cts +57 -0
- package/dist/lib/cjs/version-matrix.cjs +1 -1
- package/dist/lib/cjs/version-matrix.d.cts +2 -2
- package/dist/lib/cjs/vitest/global-setup.cjs +13 -7
- package/dist/lib/cjs/vitest/global-setup.d.cts +5 -1
- package/dist/lib/cjs/vitest/setup.cjs +2 -1
- package/dist/lib/cjs/vitest/setup.d.cts +5 -0
- package/dist/lib/cjs/vitest/typings.d.cts +6 -4
- package/dist/lib/cjs/webview-cdp.cjs +263 -0
- package/dist/lib/cjs/webview-cdp.d.cts +156 -0
- package/dist/lib/cjs/wedged-appium-server.cjs +113 -0
- package/dist/lib/cjs/wedged-appium-server.d.cts +187 -0
- package/dist/lib/esm/adb-device-list.d.mts +72 -0
- package/dist/lib/esm/adb-device-list.mjs +28 -0
- package/dist/lib/esm/android-sdk.d.mts +29 -0
- package/dist/lib/esm/android-sdk.mjs +18 -0
- package/dist/lib/esm/app-startup-progress.d.mts +128 -0
- package/dist/lib/esm/app-startup-progress.mjs +59 -0
- package/dist/lib/esm/appium-server-marker.d.mts +103 -0
- package/dist/lib/esm/appium-server-marker.mjs +89 -0
- package/dist/lib/esm/avd-probe-verdict.d.mts +175 -0
- package/dist/lib/esm/avd-probe-verdict.mjs +62 -0
- package/dist/lib/esm/cli.d.mts +16 -8
- package/dist/lib/esm/cli.mjs +110 -19
- package/dist/lib/esm/community-plugin-registry.d.mts +116 -0
- package/dist/lib/esm/community-plugin-registry.mjs +23 -0
- package/dist/lib/esm/config-directory-fallback-error.d.mts +64 -0
- package/dist/lib/esm/config-directory-fallback-error.mjs +33 -0
- package/dist/lib/esm/config-directory.d.mts +45 -0
- package/dist/lib/esm/config-directory.mjs +21 -0
- package/dist/lib/esm/connect-to-cdp.d.mts +19 -0
- package/dist/lib/esm/connect-to-cdp.mjs +13 -7
- package/dist/lib/esm/context-provider.d.mts +26 -3
- package/dist/lib/esm/context-provider.mjs +10 -1
- package/dist/lib/esm/demo-vault-bootstrap.d.mts +114 -0
- package/dist/lib/esm/demo-vault-bootstrap.mjs +127 -0
- package/dist/lib/esm/demo-vault-populate.d.mts +70 -0
- package/dist/lib/esm/demo-vault-populate.mjs +35 -9
- package/dist/lib/esm/device-readiness.d.mts +83 -9
- package/dist/lib/esm/device-readiness.mjs +34 -2
- package/dist/lib/esm/emulator-arguments.d.mts +26 -0
- package/dist/lib/esm/emulator-arguments.mjs +6 -2
- package/dist/lib/esm/emulator-backend.d.mts +76 -0
- package/dist/lib/esm/emulator-backend.mjs +45 -0
- package/dist/lib/esm/emulator-liveness.d.mts +158 -0
- package/dist/lib/esm/emulator-liveness.mjs +47 -0
- package/dist/lib/esm/emulator-snapshot.d.mts +68 -0
- package/dist/lib/esm/emulator-snapshot.mjs +32 -0
- package/dist/lib/esm/eval-in-obsidian.d.mts +42 -13
- package/dist/lib/esm/eval-in-obsidian.mjs +1 -1
- package/dist/lib/esm/global-setup-core.d.mts +27 -2
- package/dist/lib/esm/global-setup-core.mjs +34 -35
- package/dist/lib/esm/headless-vault-config.d.mts +67 -0
- package/dist/lib/esm/headless-vault-config.mjs +31 -0
- package/dist/lib/esm/index.d.mts +14 -5
- package/dist/lib/esm/index.mjs +26 -2
- package/dist/lib/esm/installer-asset.d.mts +1 -1
- package/dist/lib/esm/installer-asset.mjs +1 -1
- package/dist/lib/esm/integration-setup-failed-error.d.mts +66 -0
- package/dist/lib/esm/integration-setup-failed-error.mjs +38 -0
- package/dist/lib/esm/jest/global-setup.d.mts +5 -1
- package/dist/lib/esm/jest/global-setup.mjs +2 -2
- package/dist/lib/esm/kill-process-tree.d.mts +10 -2
- package/dist/lib/esm/kill-process-tree.mjs +16 -6
- package/dist/lib/esm/library.mjs +1 -1
- package/dist/lib/esm/mobile-input.d.mts +156 -0
- package/dist/lib/esm/mobile-input.mjs +144 -0
- package/dist/lib/esm/namespace-bootstrap.mjs +95 -9
- package/dist/lib/esm/obsidian-installer.mjs +1 -1
- package/dist/lib/esm/obsidian-instance.d.mts +12 -0
- package/dist/lib/esm/obsidian-instance.mjs +55 -3
- package/dist/lib/esm/obsidian-metadata.d.mts +17 -6
- package/dist/lib/esm/obsidian-metadata.mjs +123 -17
- package/dist/lib/esm/obsidian-version-switch.mjs +3 -3
- package/dist/lib/esm/open-obsidian-settings-tab.d.mts +3 -2
- package/dist/lib/esm/open-obsidian-settings-tab.mjs +1 -1
- package/dist/lib/esm/owned-instance-exit-marker.d.mts +106 -0
- package/dist/lib/esm/owned-instance-exit-marker.mjs +78 -0
- package/dist/lib/esm/owned-instance-exited-error.d.mts +98 -0
- package/dist/lib/esm/owned-instance-exited-error.mjs +81 -0
- package/dist/lib/esm/owned-vault-seed.d.mts +24 -3
- package/dist/lib/esm/owned-vault-seed.mjs +9 -5
- package/dist/lib/esm/parent-liveness.d.mts +37 -5
- package/dist/lib/esm/parent-liveness.mjs +42 -5
- package/dist/lib/esm/port-owner.d.mts +47 -0
- package/dist/lib/esm/port-owner.mjs +36 -0
- package/dist/lib/esm/process-capture.d.mts +83 -0
- package/dist/lib/esm/process-capture.mjs +38 -0
- package/dist/lib/esm/process-exit-message.d.mts +37 -3
- package/dist/lib/esm/process-exit-message.mjs +13 -8
- package/dist/lib/esm/process-liveness.d.mts +18 -0
- package/dist/lib/esm/process-liveness.mjs +17 -0
- package/dist/lib/esm/release-catalog.d.mts +125 -0
- package/dist/lib/esm/release-catalog.mjs +46 -0
- package/dist/lib/esm/run-version-matrix.d.mts +1 -1
- package/dist/lib/esm/run-version-matrix.mjs +1 -1
- package/dist/lib/esm/teardown-verdict.d.mts +69 -0
- package/dist/lib/esm/teardown-verdict.mjs +28 -0
- package/dist/lib/esm/temporary-vault.d.mts +47 -5
- package/dist/lib/esm/temporary-vault.mjs +43 -8
- package/dist/lib/esm/transport-appium.d.mts +104 -3
- package/dist/lib/esm/transport-appium.mjs +233 -17
- package/dist/lib/esm/transport-desktop-cdp.d.mts +100 -0
- package/dist/lib/esm/transport-desktop-cdp.mjs +208 -7
- package/dist/lib/esm/transport-factory.d.mts +10 -1
- package/dist/lib/esm/transport-factory.mjs +1220 -149
- package/dist/lib/esm/transport-options.d.mts +131 -12
- package/dist/lib/esm/transport-options.mjs +9 -2
- package/dist/lib/esm/transport.d.mts +7 -1
- package/dist/lib/esm/vault-plugin-install.d.mts +64 -0
- package/dist/lib/esm/vault-plugin-install.mjs +20 -0
- package/dist/lib/esm/vault-teardown-verdict.d.mts +57 -0
- package/dist/lib/esm/vault-teardown-verdict.mjs +18 -0
- package/dist/lib/esm/version-matrix.d.mts +2 -2
- package/dist/lib/esm/version-matrix.mjs +1 -1
- package/dist/lib/esm/vitest/global-setup.d.mts +5 -1
- package/dist/lib/esm/vitest/global-setup.mjs +14 -7
- package/dist/lib/esm/vitest/setup.d.mts +5 -0
- package/dist/lib/esm/vitest/setup.mjs +3 -1
- package/dist/lib/esm/vitest/typings.d.mts +6 -4
- package/dist/lib/esm/webview-cdp.d.mts +156 -0
- package/dist/lib/esm/webview-cdp.mjs +235 -0
- package/dist/lib/esm/wedged-appium-server.d.mts +187 -0
- package/dist/lib/esm/wedged-appium-server.mjs +86 -0
- package/package.json +25 -23
- package/dist/lib/cjs/native-dialog-monitor.cjs +0 -192
- package/dist/lib/cjs/native-dialog-monitor.d.cts +0 -66
- package/dist/lib/cjs/obsidian-namespace.cjs +0 -17
- package/dist/lib/cjs/obsidian-namespace.d.cts +0 -128
- package/dist/lib/esm/native-dialog-monitor.d.mts +0 -66
- package/dist/lib/esm/native-dialog-monitor.mjs +0 -158
- package/dist/lib/esm/obsidian-namespace.d.mts +0 -128
- package/dist/lib/esm/obsidian-namespace.mjs +0 -1
|
@@ -5,13 +5,27 @@ import {
|
|
|
5
5
|
} from "node:fs/promises";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
+
import {
|
|
9
|
+
buildStartupTimeoutMessage,
|
|
10
|
+
checkAppStarted,
|
|
11
|
+
checkLayoutReady,
|
|
12
|
+
classifyAppStartupProbe,
|
|
13
|
+
compareAppStartupMilestones
|
|
14
|
+
} from "./app-startup-progress.mjs";
|
|
8
15
|
import {
|
|
9
16
|
decodeBase64Png,
|
|
10
17
|
isPng
|
|
11
18
|
} from "./capture-screenshot.mjs";
|
|
19
|
+
import { errorToString } from "./error-to-string.mjs";
|
|
12
20
|
import { exec } from "./exec.mjs";
|
|
13
21
|
import { TEMP_VAULT_DIR_PREFIX } from "./leftover-cleanup.mjs";
|
|
14
22
|
import { log } from "./log.mjs";
|
|
23
|
+
import {
|
|
24
|
+
buildResolveInputExpression,
|
|
25
|
+
MOBILE_INPUT_BINDING_NAME,
|
|
26
|
+
toCdpInputCommands
|
|
27
|
+
} from "./mobile-input.mjs";
|
|
28
|
+
import { connectToWebViewCdp } from "./webview-cdp.mjs";
|
|
15
29
|
const NO_OUTPUT = "(no output)";
|
|
16
30
|
const APP_STATE_FOREGROUND = 4;
|
|
17
31
|
const WEBVIEW_CONTEXT_PREFIX = "WEBVIEW_md.obsidian";
|
|
@@ -19,6 +33,7 @@ const WEBVIEW_POLL_INTERVAL_IN_MILLISECONDS = 500;
|
|
|
19
33
|
const DEFAULT_WEBVIEW_POLL_TIMEOUT_IN_MILLISECONDS = 6e4;
|
|
20
34
|
const LAYOUT_READY_POLL_INTERVAL_IN_MILLISECONDS = 500;
|
|
21
35
|
const DEFAULT_LAYOUT_READY_POLL_TIMEOUT_IN_MILLISECONDS = 9e4;
|
|
36
|
+
const DEFAULT_APP_START_POLL_TIMEOUT_IN_MILLISECONDS = 18e4;
|
|
22
37
|
const APP_RESTART_DELAY_IN_MILLISECONDS = 2e3;
|
|
23
38
|
const DEFAULT_APP_ID = "md.obsidian";
|
|
24
39
|
const ADB_VAULT_REMOVE_TIMEOUT_IN_MILLISECONDS = 3e4;
|
|
@@ -38,8 +53,23 @@ class AppiumTransport {
|
|
|
38
53
|
*/
|
|
39
54
|
isMobile = true;
|
|
40
55
|
appId;
|
|
56
|
+
appStartTimeoutInMilliseconds;
|
|
41
57
|
browser;
|
|
42
58
|
deviceId;
|
|
59
|
+
/**
|
|
60
|
+
* The `process.on('exit')` handler that tears the channel down when nothing else will.
|
|
61
|
+
*/
|
|
62
|
+
disposeInputChannelOnExit = null;
|
|
63
|
+
/**
|
|
64
|
+
* The host half of the trusted-input channel: a CDP connection to the WebView, independent of the
|
|
65
|
+
* Appium session, opened lazily on first evaluate and reused (see **L39**).
|
|
66
|
+
*/
|
|
67
|
+
inputChannel = null;
|
|
68
|
+
/**
|
|
69
|
+
* Set once the trusted-input channel is known not to be openable here (iOS, a remote hub, no local
|
|
70
|
+
* `adb`), so the attempt is not repeated on every evaluate.
|
|
71
|
+
*/
|
|
72
|
+
isInputChannelUnavailable = false;
|
|
43
73
|
/**
|
|
44
74
|
* Tracks whether the driver is currently switched to the WebView context.
|
|
45
75
|
*
|
|
@@ -70,6 +100,7 @@ class AppiumTransport {
|
|
|
70
100
|
this.layoutReadyTimeoutInMilliseconds = config.layoutReadyTimeoutInMilliseconds ?? DEFAULT_LAYOUT_READY_POLL_TIMEOUT_IN_MILLISECONDS;
|
|
71
101
|
this.platform = config.platform;
|
|
72
102
|
this.appId = config.appId ?? DEFAULT_APP_ID;
|
|
103
|
+
this.appStartTimeoutInMilliseconds = config.appStartTimeoutInMilliseconds ?? DEFAULT_APP_START_POLL_TIMEOUT_IN_MILLISECONDS;
|
|
73
104
|
this.shouldSweepLeftovers = config.shouldSweepLeftovers ?? true;
|
|
74
105
|
this.vaultBasePath = config.vaultBasePath ?? DEFAULT_VAULT_BASE_PATH[this.platform] ?? DEFAULT_ANDROID_VAULT_BASE_PATH;
|
|
75
106
|
this.webviewTimeoutInMilliseconds = config.webviewTimeoutInMilliseconds ?? DEFAULT_WEBVIEW_POLL_TIMEOUT_IN_MILLISECONDS;
|
|
@@ -121,10 +152,24 @@ class AppiumTransport {
|
|
|
121
152
|
* deletion so the session remains available for the owning process.
|
|
122
153
|
*/
|
|
123
154
|
async dispose() {
|
|
155
|
+
await this.disposeInputChannel();
|
|
124
156
|
if (this.isSessionOwner) {
|
|
125
157
|
await this.browser.deleteSession();
|
|
126
158
|
}
|
|
127
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Synchronous teardown for `process.on('exit')` handlers.
|
|
162
|
+
*
|
|
163
|
+
* Only the trusted-input channel needs it: the Appium session is the owning process's to end, and an
|
|
164
|
+
* abrupt exit is exactly when the async {@link AppiumTransport.dispose} never runs — which would strand
|
|
165
|
+
* the adb port forward on the device.
|
|
166
|
+
*/
|
|
167
|
+
disposeSync() {
|
|
168
|
+
const channel = this.inputChannel;
|
|
169
|
+
this.inputChannel = null;
|
|
170
|
+
this.unregisterInputChannelExitHandler();
|
|
171
|
+
channel?.disposeSync();
|
|
172
|
+
}
|
|
128
173
|
/**
|
|
129
174
|
* Evaluates a JavaScript expression inside Obsidian Mobile's WebView.
|
|
130
175
|
*
|
|
@@ -137,6 +182,7 @@ class AppiumTransport {
|
|
|
137
182
|
*/
|
|
138
183
|
async evaluate(expression, _options) {
|
|
139
184
|
await this.ensureWebViewContext();
|
|
185
|
+
await this.ensureInputChannel();
|
|
140
186
|
try {
|
|
141
187
|
const result = await this.browser.execute(
|
|
142
188
|
`return (${expression})`
|
|
@@ -248,7 +294,8 @@ class AppiumTransport {
|
|
|
248
294
|
* 3. Add the vault to localStorage (`mobile-external-vaults`, `mobile-selected-vault`,
|
|
249
295
|
* `enable-plugin-<path>`)
|
|
250
296
|
* 4. Trigger `location.reload()` so Obsidian re-reads localStorage and opens the vault
|
|
251
|
-
* 5. Wait for `app
|
|
297
|
+
* 5. Wait for `globalThis.app` to exist (the app's cold start), then — on a
|
|
298
|
+
* separate, tighter budget — for `app.workspace.layoutReady`
|
|
252
299
|
*
|
|
253
300
|
* Existing vault registrations in localStorage are preserved (append, not
|
|
254
301
|
* overwrite) — except the **harness's own** `temp-vault-*` registrations from
|
|
@@ -288,6 +335,7 @@ class AppiumTransport {
|
|
|
288
335
|
deviceVaultPath,
|
|
289
336
|
stalePrefix
|
|
290
337
|
);
|
|
338
|
+
await this.waitForAppStarted();
|
|
291
339
|
await this.waitForLayoutReady();
|
|
292
340
|
}
|
|
293
341
|
/**
|
|
@@ -329,6 +377,55 @@ class AppiumTransport {
|
|
|
329
377
|
}
|
|
330
378
|
await this.removeDeviceVaultDirectory(deviceVaultPath);
|
|
331
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* Closes the trusted-input channel, if one is open.
|
|
382
|
+
*/
|
|
383
|
+
async disposeInputChannel() {
|
|
384
|
+
const channel = this.inputChannel;
|
|
385
|
+
this.inputChannel = null;
|
|
386
|
+
this.unregisterInputChannelExitHandler();
|
|
387
|
+
await channel?.dispose();
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Opens the trusted-input channel if it is not already open, and re-opens it if the WebView went away.
|
|
391
|
+
*
|
|
392
|
+
* Installs a `Runtime.addBinding` function on the page and services every call to it for the life of the
|
|
393
|
+
* connection. The binding is exposed on *every* execution context of the page, so it survives the
|
|
394
|
+
* `location.reload()` that {@link AppiumTransport.registerVault} performs; only a full app restart, which
|
|
395
|
+
* destroys the WebView target, needs the reconnect below.
|
|
396
|
+
*/
|
|
397
|
+
async ensureInputChannel() {
|
|
398
|
+
if (this.inputChannel?.isOpen || this.isInputChannelUnavailable) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (this.platform !== "android") {
|
|
402
|
+
this.isInputChannelUnavailable = true;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
await this.disposeInputChannel();
|
|
406
|
+
try {
|
|
407
|
+
const connection = await connectToWebViewCdp({ appId: this.appId, deviceId: this.deviceId });
|
|
408
|
+
await connection.send("Runtime.enable");
|
|
409
|
+
await connection.send("Runtime.addBinding", { name: MOBILE_INPUT_BINDING_NAME });
|
|
410
|
+
connection.on("Runtime.bindingCalled", (params) => {
|
|
411
|
+
if (params["name"] !== MOBILE_INPUT_BINDING_NAME) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const payload = params["payload"];
|
|
415
|
+
this.handleInputRequest(connection, typeof payload === "string" ? payload : "").catch(() => {
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
this.inputChannel = connection;
|
|
419
|
+
this.disposeInputChannelOnExit = () => {
|
|
420
|
+
connection.disposeSync();
|
|
421
|
+
};
|
|
422
|
+
process.once("exit", this.disposeInputChannelOnExit);
|
|
423
|
+
log("[appium-transport] Trusted-input channel open.");
|
|
424
|
+
} catch (error) {
|
|
425
|
+
this.isInputChannelUnavailable = true;
|
|
426
|
+
log(`[appium-transport] Trusted input is unavailable on this device: ${errorToString(error)}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
332
429
|
/**
|
|
333
430
|
* Switches the driver to the `WEBVIEW_md.obsidian` context.
|
|
334
431
|
*
|
|
@@ -378,6 +475,58 @@ class AppiumTransport {
|
|
|
378
475
|
getDeviceVaultPath(vaultPath) {
|
|
379
476
|
return `${this.vaultBasePath}${extractVaultName(vaultPath)}`;
|
|
380
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* Services one input request from the renderer: inject, then resolve the renderer's promise.
|
|
480
|
+
*
|
|
481
|
+
* Every failure path still resolves that promise — with an error message the renderer re-throws — because
|
|
482
|
+
* a request that is silently dropped would hang the closure until the whole run times out, and report
|
|
483
|
+
* nothing about why.
|
|
484
|
+
*
|
|
485
|
+
* @param connection - The channel the request arrived on.
|
|
486
|
+
* @param payload - The raw JSON payload the binding was called with.
|
|
487
|
+
*/
|
|
488
|
+
async handleInputRequest(connection, payload) {
|
|
489
|
+
let requestId = "";
|
|
490
|
+
try {
|
|
491
|
+
const { id, request } = JSON.parse(payload);
|
|
492
|
+
requestId = id;
|
|
493
|
+
await connection.sendAll(toCdpInputCommands(request));
|
|
494
|
+
await connection.send("Runtime.evaluate", { expression: buildResolveInputExpression(id) });
|
|
495
|
+
} catch (error) {
|
|
496
|
+
const message = errorToString(error);
|
|
497
|
+
log(`[appium-transport] Trusted input failed: ${message}`);
|
|
498
|
+
if (!requestId) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
try {
|
|
502
|
+
await connection.send("Runtime.evaluate", { expression: buildResolveInputExpression(requestId, message) });
|
|
503
|
+
} catch {
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Probes the WebView once for how far Obsidian's startup has got.
|
|
509
|
+
*
|
|
510
|
+
* A probe that throws is reported as `undefined` rather than propagated: the
|
|
511
|
+
* page is mid-`location.reload()` for most of the app-start phase, and a
|
|
512
|
+
* WebView that cannot answer yet is the *expected* reading there, not an error.
|
|
513
|
+
*
|
|
514
|
+
* @returns What the probe saw, or `undefined` when it could not run.
|
|
515
|
+
*/
|
|
516
|
+
async probeStartup() {
|
|
517
|
+
try {
|
|
518
|
+
return await this.browser.execute(() => {
|
|
519
|
+
const app = globalThis.app;
|
|
520
|
+
return {
|
|
521
|
+
hasApp: !!app,
|
|
522
|
+
hasWorkspace: !!app?.workspace,
|
|
523
|
+
isLayoutReady: !!app?.workspace?.layoutReady
|
|
524
|
+
};
|
|
525
|
+
});
|
|
526
|
+
} catch {
|
|
527
|
+
return void 0;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
381
530
|
/**
|
|
382
531
|
* Pushes the minimal `.obsidian/app.json` vault marker via `adb push`.
|
|
383
532
|
*
|
|
@@ -435,30 +584,97 @@ class AppiumTransport {
|
|
|
435
584
|
log(`[appium-transport] Vault directory removal failed (non-fatal): ${String(error)}`);
|
|
436
585
|
}
|
|
437
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* Drops the `process.on('exit')` handler that would otherwise close an already-closed channel, and would
|
|
589
|
+
* stack a listener per reconnect.
|
|
590
|
+
*/
|
|
591
|
+
unregisterInputChannelExitHandler() {
|
|
592
|
+
if (!this.disposeInputChannelOnExit) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
process.off("exit", this.disposeInputChannelOnExit);
|
|
596
|
+
this.disposeInputChannelOnExit = null;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Polls until `globalThis.app` exists in the WebView — the app has finished
|
|
600
|
+
* its cold start and Obsidian's own boot has begun.
|
|
601
|
+
*
|
|
602
|
+
* This is the **first** of the two budgets spent after `location.reload()`,
|
|
603
|
+
* and the generous one. Everything it pays for is outside Obsidian's control:
|
|
604
|
+
* the WebView reloading, and a guest that may still be optimizing packages.
|
|
605
|
+
* Keeping it separate is the point of the split — the old single wall clock
|
|
606
|
+
* started here and left the tight layout budget paying for a cold start.
|
|
607
|
+
*/
|
|
608
|
+
async waitForAppStarted() {
|
|
609
|
+
log(`[appium-transport] Waiting for the app to start (timeout=${String(this.appStartTimeoutInMilliseconds)}ms)...`);
|
|
610
|
+
await this.waitForStartupMilestone({
|
|
611
|
+
isSatisfied: checkAppStarted,
|
|
612
|
+
phase: "app-start",
|
|
613
|
+
timeoutInMilliseconds: this.appStartTimeoutInMilliseconds
|
|
614
|
+
});
|
|
615
|
+
}
|
|
438
616
|
/**
|
|
439
617
|
* Polls until `app.workspace.layoutReady` is `true` in the WebView.
|
|
618
|
+
*
|
|
619
|
+
* The **second** budget, and the tight one: by the time it starts, the app is
|
|
620
|
+
* already up, so all it covers is Obsidian opening the vault and loading
|
|
621
|
+
* plugins — ~1s in practice, ≤8.4s under heavy host stress (**L19**).
|
|
440
622
|
*/
|
|
441
623
|
async waitForLayoutReady() {
|
|
442
|
-
const start = Date.now();
|
|
443
|
-
const deadline = start + this.layoutReadyTimeoutInMilliseconds;
|
|
444
624
|
log(`[appium-transport] Waiting for layout ready (timeout=${String(this.layoutReadyTimeoutInMilliseconds)}ms)...`);
|
|
625
|
+
await this.waitForStartupMilestone({
|
|
626
|
+
isSatisfied: checkLayoutReady,
|
|
627
|
+
phase: "layout-ready",
|
|
628
|
+
timeoutInMilliseconds: this.layoutReadyTimeoutInMilliseconds
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Polls the WebView until a startup phase's milestone is satisfied, tracking
|
|
633
|
+
* the evidence that tells a slow Obsidian from a contended guest.
|
|
634
|
+
*
|
|
635
|
+
* Each poll costs exactly one `browser.execute` round-trip — deliberately not
|
|
636
|
+
* an {@link ensureWebViewContext} call, whose `getContexts()` runs
|
|
637
|
+
* `adb shell cat /proc/net/unix` and was measured at ~17s per **L19**. The
|
|
638
|
+
* round-trip is timed, and the slowest one is reported on timeout: a phase
|
|
639
|
+
* that ran out after a handful of probes each taking tens of seconds was
|
|
640
|
+
* starved by the guest, not by Obsidian.
|
|
641
|
+
*
|
|
642
|
+
* @param params - The phase, its budget, and the predicate that ends it.
|
|
643
|
+
*/
|
|
644
|
+
async waitForStartupMilestone(params) {
|
|
645
|
+
const { isSatisfied, phase, timeoutInMilliseconds } = params;
|
|
646
|
+
const start = Date.now();
|
|
647
|
+
const deadline = start + timeoutInMilliseconds;
|
|
648
|
+
let furthestMilestone = "no-webview";
|
|
649
|
+
let pollCount = 0;
|
|
650
|
+
let slowestRoundTripInMilliseconds = 0;
|
|
445
651
|
while (Date.now() < deadline) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
652
|
+
const roundTripStart = Date.now();
|
|
653
|
+
const milestone = classifyAppStartupProbe(await this.probeStartup());
|
|
654
|
+
const roundTripInMilliseconds = Date.now() - roundTripStart;
|
|
655
|
+
pollCount++;
|
|
656
|
+
slowestRoundTripInMilliseconds = Math.max(slowestRoundTripInMilliseconds, roundTripInMilliseconds);
|
|
657
|
+
if (compareAppStartupMilestones(milestone, furthestMilestone) > 0) {
|
|
658
|
+
furthestMilestone = milestone;
|
|
659
|
+
}
|
|
660
|
+
if (isSatisfied(milestone)) {
|
|
661
|
+
log(`[appium-transport] Phase "${phase}" satisfied after ${String(Date.now() - start)}ms (${String(pollCount)} probe(s)).`);
|
|
662
|
+
this.isInWebViewContext = true;
|
|
663
|
+
return;
|
|
457
664
|
}
|
|
458
|
-
log(
|
|
665
|
+
log(
|
|
666
|
+
`[appium-transport] Phase "${phase}" not satisfied yet: ${milestone} (elapsed=${String(Date.now() - start)}ms, round-trip=${String(roundTripInMilliseconds)}ms). Retrying...`
|
|
667
|
+
);
|
|
459
668
|
await delay(LAYOUT_READY_POLL_INTERVAL_IN_MILLISECONDS);
|
|
460
669
|
}
|
|
461
|
-
throw new Error(
|
|
670
|
+
throw new Error(buildStartupTimeoutMessage({
|
|
671
|
+
elapsedInMilliseconds: Date.now() - start,
|
|
672
|
+
milestone: furthestMilestone,
|
|
673
|
+
phase,
|
|
674
|
+
pollCount,
|
|
675
|
+
slowestRoundTripInMilliseconds,
|
|
676
|
+
timeoutInMilliseconds
|
|
677
|
+
}));
|
|
462
678
|
}
|
|
463
679
|
}
|
|
464
680
|
function delay(ms) {
|
|
@@ -475,4 +691,4 @@ export {
|
|
|
475
691
|
AppiumTransport,
|
|
476
692
|
DEFAULT_ANDROID_VAULT_BASE_PATH
|
|
477
693
|
};
|
|
478
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1hcHBpdW0udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBBcHBpdW0gdHJhbnNwb3J0IFx1MjAxNCBldmFsdWF0ZXMgZXhwcmVzc2lvbnMgaW5zaWRlIE9ic2lkaWFuIE1vYmlsZSB2aWEgV2ViVmlld1xuICogSmF2YVNjcmlwdCBpbmplY3Rpb24uIE1hbmFnZXMgdmF1bHQgbGlmZWN5Y2xlIHZpYSBsb2NhbFN0b3JhZ2UgYW5kIGZpbGUgcHVzaC5cbiAqXG4gKiBDb25maWd1cmVkIHZpYSBgZW52aXJvbm1lbnRPcHRpb25zLm9ic2lkaWFuVHJhbnNwb3J0YCBpbiB2aXRlc3QgY29uZmlnOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIHZpdGVzdC5jb25maWcudHNcbiAqIGVudmlyb25tZW50T3B0aW9uczoge1xuICogICBvYnNpZGlhblRyYW5zcG9ydDoge1xuICogICAgIHR5cGU6ICdvYnNpZGlhbi1hbmRyb2lkLWFwcGl1bScsXG4gKiAgICAgYXBwaXVtVXJsOiAnaHR0cDovL2xvY2FsaG9zdDo0NzIzJyxcbiAqICAgICBhdmROYW1lOiAnb2JzaWRpYW5fdGVzdCcsXG4gKiAgIH0sXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBGb3IgQnJvd3NlclN0YWNrLCBzZXQgYGFwcGl1bVVybGAgdG8gdGhlIEJyb3dzZXJTdGFjayBodWIgVVJMXG4gKiBcdTIwMTQgdGhlIHRyYW5zcG9ydCBpdHNlbGYgaXMgaHViLWFnbm9zdGljLlxuICpcbiAqICMjIEhvdyB2YXVsdCByZWdpc3RyYXRpb24gd29ya3Mgb24gbW9iaWxlXG4gKlxuICogT2JzaWRpYW4gTW9iaWxlIHN0b3JlcyBpdHMgdmF1bHQgcmVnaXN0cnkgaW4gdGhlIFdlYlZpZXcncyBgbG9jYWxTdG9yYWdlYDpcbiAqXG4gKiAtIGBtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzYCBcdTIwMTQgSlNPTiBhcnJheSBvZiByZWdpc3RlcmVkIHZhdWx0IHBhdGhzXG4gKiAtIGBtb2JpbGUtc2VsZWN0ZWQtdmF1bHRgIFx1MjAxNCB0aGUgY3VycmVudGx5IGFjdGl2ZSB2YXVsdCBwYXRoXG4gKiAtIGBlbmFibGUtcGx1Z2luLTx2YXVsdFBhdGg+YCBcdTIwMTQgYFwidHJ1ZVwiYCB0byBlbmFibGUgdGhlIHBsdWdpbiBzeXN0ZW0gZm9yIHRoZSB2YXVsdFxuICpcbiAqIFRvIHJlZ2lzdGVyIGEgdmF1bHQgcHJvZ3JhbW1hdGljYWxseSAod2l0aG91dCBVSSBpbnRlcmFjdGlvbik6XG4gKlxuICogMS4gUHVzaCB2YXVsdCBmaWxlcyB0byB0aGUgZGV2aWNlIChlLmcuIGAvc2RjYXJkL0RvY3VtZW50cy88TmFtZT4vLm9ic2lkaWFuL2FwcC5qc29uYClcbiAqIDIuIFN3aXRjaCB0byBgV0VCVklFV19tZC5vYnNpZGlhbmAgY29udGV4dFxuICogMy4gU2V0IHRoZSBsb2NhbFN0b3JhZ2UgZW50cmllc1xuICogNC4gQ2FsbCBgbG9jYXRpb24ucmVsb2FkKClgIFx1MjAxNCBPYnNpZGlhbiByZS1yZWFkcyBsb2NhbFN0b3JhZ2UgYW5kIG9wZW5zIHRoZSB2YXVsdFxuICpcbiAqIFRoaXMgYXZvaWRzIHRoZSBvbmJvYXJkaW5nIGZsb3cgZW50aXJlbHkuXG4gKi9cblxuLyogdjggaWdub3JlIHN0YXJ0IC0tIEludGVncmF0aW9uLXRpbWUgY29kZSBjb3ZlcmVkIGJ5IGludGVncmF0aW9uIHRlc3RzLCBub3QgdW5pdCB0ZXN0cy4gKi9cblxuaW1wb3J0IHR5cGUgeyBCcm93c2VyIH0gZnJvbSAnd2ViZHJpdmVyaW8nO1xuXG5pbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHtcbiAgcm0sXG4gIHdyaXRlRmlsZVxufSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCc7XG5cbmltcG9ydCB0eXBlIHsgQ2FwdHVyZVNjcmVlbnNob3RQYXJhbXMgfSBmcm9tICcuL2NhcHR1cmUtc2NyZWVuc2hvdC5tanMnO1xuaW1wb3J0IHR5cGUge1xuICBDb25zb2xlQ2FwdHVyZUhhbmRsZSxcbiAgT2JzaWRpYW5UcmFuc3BvcnQsXG4gIFRyYW5zcG9ydEV2YWxPcHRpb25zXG59IGZyb20gJy4vdHJhbnNwb3J0Lm1qcyc7XG5cbmltcG9ydCB7XG4gIGRlY29kZUJhc2U2NFBuZyxcbiAgaXNQbmdcbn0gZnJvbSAnLi9jYXB0dXJlLXNjcmVlbnNob3QubWpzJztcbmltcG9ydCB7IGV4ZWMgfSBmcm9tICcuL2V4ZWMubWpzJztcbmltcG9ydCB7IFRFTVBfVkFVTFRfRElSX1BSRUZJWCB9IGZyb20gJy4vbGVmdG92ZXItY2xlYW51cC5tanMnO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSAnLi9sb2cubWpzJztcblxuLyoqXG4gKiBTZXNzaW9uIGNvbm5lY3Rpb24gaW5mbyByZXR1cm5lZCBieSB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LmdldFNlc3Npb25JbmZvfSxcbiAqIHVzZWQgdG8gcmVhdHRhY2ggZnJvbSBhbm90aGVyIHByb2Nlc3MuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwaXVtU2Vzc2lvbkluZm8ge1xuICAvKipcbiAgVGhlIGRldmljZSBVRElEIChlLmcuIGAnZW11bGF0b3ItNTU1NCdgKS5cbiAgICovXG4gIGRldmljZUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gIFRoZSBBcHBpdW0vV2ViRHJpdmVyIHNlc3Npb24gSUQuXG4gICAqL1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgQXBwaXVtIHRyYW5zcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBpdW1UcmFuc3BvcnRDb25maWcge1xuICAvKipcbiAgICogQXBwIHBhY2thZ2UgKEFuZHJvaWQpIG9yIGJ1bmRsZSBJRCAoaU9TKS5cbiAgICogRGVmYXVsdHMgdG8gYCdtZC5vYnNpZGlhbidgLlxuICAgKi9cbiAgYXBwSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBcHBpdW0gYnJvd3Nlci9kcml2ZXIgaW5zdGFuY2UuXG4gICAqIENyZWF0ZWQgYnkgdGhlIGNvbnN1bWVyIHZpYSBlLmcuIFdlYkRyaXZlcklPJ3MgYHJlbW90ZSgpYC5cbiAgICovXG4gIGJyb3dzZXI6IEJyb3dzZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBkZXZpY2UgVURJRCAoZS5nLiBgJ2VtdWxhdG9yLTU1NTQnYCkuXG4gICAqIFVzZWQgZm9yIGBhZGJgIGNvbW1hbmRzIHdoZW4gcHVzaGluZyBmaWxlcyB0byB0aGUgZGV2aWNlLlxuICAgKi9cbiAgZGV2aWNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHRyYW5zcG9ydCBvd25zIHRoZSBBcHBpdW0gc2Vzc2lvbiBhbmQgc2hvdWxkIGRlbGV0ZSBpdCBvblxuICAgKiB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LmRpc3Bvc2V9LlxuICAgKlxuICAgKiBgdHJ1ZWAgZm9yIHNlc3Npb25zIGNyZWF0ZWQgdmlhIGByZW1vdGUoKWAgKGdsb2JhbCBzZXR1cCkuXG4gICAqIGBmYWxzZWAgZm9yIHNlc3Npb25zIHJlYXR0YWNoZWQgdmlhIGBhdHRhY2goKWAgKHRlc3Qgd29ya2VycykuXG4gICAqXG4gICAqIEBkZWZhdWx0IGB0cnVlYFxuICAgKi9cbiAgaXNTZXNzaW9uT3duZXI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3Igd2FpdGluZyBmb3IgYGFwcC53b3Jrc3BhY2UubGF5b3V0UmVhZHlgIGFmdGVyXG4gICAqIHRoZSB2YXVsdCBpcyAocmUpb3BlbmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgOTAwMDBgXG4gICAqL1xuICBsYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kcz86IG51bWJlcjtcblxuICAvKipcbiAgICogVGFyZ2V0IHBsYXRmb3JtLiBEZXRlcm1pbmVzIFdlYlZpZXcgY29udGV4dCBuYW1pbmcgYW5kIGRldmljZSBmaWxlIHBhdGhzLlxuICAgKi9cbiAgcGxhdGZvcm06ICdhbmRyb2lkJyB8ICdpb3MnO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHJlZ2lzdGVyaW5nIGEgdmF1bHQgYWxzbyBwcnVuZXMgdGhlICoqb3RoZXIqKiBgdGVtcC12YXVsdC0qYFxuICAgKiByZWdpc3RyYXRpb25zIGVhcmxpZXIgcnVucyBsZWZ0IGluIE9ic2lkaWFuIE1vYmlsZSdzIGBsb2NhbFN0b3JhZ2VgLlxuICAgKlxuICAgKiBUaGUgZGV2aWNlLXNpZGUgZGlyZWN0b3JpZXMgYXJlIHN3ZXB0IGJlZm9yZSB0aGUgYXBwIGxhdW5jaGVzIChzZWUgdGhlXG4gICAqIGZhY3RvcnkpOyB0aGlzIHJlbW92ZXMgdGhlaXIgbm93LWRhbmdsaW5nIHJlZ2lzdHJ5IGVudHJpZXMsIHdoaWNoIGFyZSB3aGF0XG4gICAqIE9ic2lkaWFuIGFjdHVhbGx5IGVudW1lcmF0ZXMgYXQgc3RhcnR1cC4gVW5yZWdpc3RlcmluZyB0aGlzIHJ1bidzIG93biB2YXVsdFxuICAgKiBpcyB1bmFmZmVjdGVkIFx1MjAxNCB0aGF0IGFsd2F5cyBoYXBwZW5zLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgdHJ1ZWBcbiAgICovXG4gIHNob3VsZFN3ZWVwTGVmdG92ZXJzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQmFzZSBwYXRoIG9uIHRoZSBkZXZpY2Ugd2hlcmUgT2JzaWRpYW4gc3RvcmVzIHZhdWx0cy5cbiAgICpcbiAgICogRGVmYXVsdHM6XG4gICAqIC0gQW5kcm9pZDogYC9zZGNhcmQvRG9jdW1lbnRzL2BcbiAgICogLSBpT1M6IGBAbWQub2JzaWRpYW46ZG9jdW1lbnRzL2BcbiAgICovXG4gIHZhdWx0QmFzZVBhdGg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciB3YWl0aW5nIGZvciB0aGUgV2ViVmlldyBjb250ZXh0IHRvIGJlY29tZSBhdmFpbGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGA2MDAwMGBcbiAgICovXG4gIHdlYnZpZXdUaW1lb3V0SW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG59XG5cbmNvbnN0IE5PX09VVFBVVCA9ICcobm8gb3V0cHV0KSc7XG5jb25zdCBBUFBfU1RBVEVfRk9SRUdST1VORCA9IDQ7XG5jb25zdCBXRUJWSUVXX0NPTlRFWFRfUFJFRklYID0gJ1dFQlZJRVdfbWQub2JzaWRpYW4nO1xuY29uc3QgV0VCVklFV19QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IERFRkFVTFRfV0VCVklFV19QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gNjBfMDAwO1xuY29uc3QgTEFZT1VUX1JFQURZX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTID0gNTAwO1xuY29uc3QgREVGQVVMVF9MQVlPVVRfUkVBRFlfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDkwXzAwMDtcbmNvbnN0IEFQUF9SRVNUQVJUX0RFTEFZX0lOX01JTExJU0VDT05EUyA9IDIwMDA7XG5jb25zdCBERUZBVUxUX0FQUF9JRCA9ICdtZC5vYnNpZGlhbic7XG5jb25zdCBBREJfVkFVTFRfUkVNT1ZFX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMzBfMDAwO1xuXG4vLyAtLS0gQ29uc29sZSBjYXB0dXJlIChMYXllciAyIG9mIHRoZSBwbHVnaW4tbG9hZCBlcnJvciBzdXJmYWNpbmcsIHNlZSBUODgpIC0tLVxuY29uc3QgQ09OU09MRV9DQVBUVVJFX01BUktFUl9UQUcgPSAnT0lUX0NBUFRVUkUnO1xuY29uc3QgQ09OU09MRV9DQVBUVVJFX1RBSUxfTUFYX0xFTkdUSCA9IDgwMDA7XG5jb25zdCBBREJfTE9HX01BUktFUl9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDUwMDA7XG5jb25zdCBMT0dDQVRfRFVNUF9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDEwXzAwMDtcbi8qKlxuICogYGFkYiBsb2djYXQgLXYgdGltZWAgbGluZXMgbG9vayBsaWtlIGBNTS1ERCBISDpNTTpTUy5tbW0gTEVWRUwvVEFHKCBQSUQpOiBtZXNzYWdlYC5cbiAqIEtlZXAgb25seSB0aGUgdGFncyBDaHJvbWl1bS9XZWJWaWV3IHJvdXRlcyBKUyBgY29uc29sZS4qYCBvdXRwdXQgYW5kIHVuY2F1Z2h0XG4gKiBlcnJvcnMgdG8gKGBjaHJvbWl1bWAsIHRoZSBDYXBhY2l0b3IgY29uc29sZSBicmlkZ2UsIGFuZCBuYXRpdmUgYEFuZHJvaWRSdW50aW1lYCkuXG4gKi9cbmNvbnN0IENPTlNPTEVfQ0FQVFVSRV9UQUdfUkUgPSAvXFwvKD86Y2hyb21pdW18QW5kcm9pZFJ1bnRpbWV8Q2FwYWNpdG9yXFwvQ29uc29sZSlcXCgvO1xuXG4vKipcbiAqIEJhc2UgcGF0aCBvbiBhbiBBbmRyb2lkIGRldmljZSB3aGVyZSBPYnNpZGlhbiBNb2JpbGUgc3RvcmVzIGl0cyB2YXVsdHMuXG4gKlxuICogRXhwb3J0ZWQgYmVjYXVzZSB0aGUgdHJhbnNwb3J0IGZhY3Rvcnkgc3dlZXBzIGxlZnRvdmVyIHZhdWx0cyBmcm9tIGl0IGJlZm9yZVxuICogYSB0cmFuc3BvcnQgZXhpc3RzIChzZWUgdGhlIHJlcG8ncyBMMzEpLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9BTkRST0lEX1ZBVUxUX0JBU0VfUEFUSCA9ICcvc2RjYXJkL0RvY3VtZW50cy8nO1xuXG5jb25zdCBERUZBVUxUX1ZBVUxUX0JBU0VfUEFUSDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgYW5kcm9pZDogREVGQVVMVF9BTkRST0lEX1ZBVUxUX0JBU0VfUEFUSCxcbiAgaW9zOiAnQG1kLm9ic2lkaWFuOmRvY3VtZW50cy8nXG59O1xuXG5pbnRlcmZhY2UgTG9hZGluZ0FwcCB7XG4gIHdvcmtzcGFjZT86IExvYWRpbmdXb3Jrc3BhY2U7XG59XG5cbmludGVyZmFjZSBMb2FkaW5nV29ya3NwYWNlIHtcbiAgbGF5b3V0UmVhZHk/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFRyYW5zcG9ydCB0aGF0IGNvbW11bmljYXRlcyB3aXRoIE9ic2lkaWFuIE1vYmlsZSB2aWEgQXBwaXVtIFdlYlZpZXcgSlMgaW5qZWN0aW9uLlxuICpcbiAqIEV2YWx1YXRlcyBleHByZXNzaW9ucyBieSBzd2l0Y2hpbmcgdG8gdGhlIGBXRUJWSUVXX21kLm9ic2lkaWFuYCBjb250ZXh0IGFuZFxuICogY2FsbGluZyBgZXhlY3V0ZSgpYC4gTWFuYWdlcyB2YXVsdHMgYnkgd3JpdGluZyB0byB0aGUgV2ViVmlldydzIGBsb2NhbFN0b3JhZ2VgXG4gKiAod2hpY2ggT2JzaWRpYW4gdXNlcyBhcyBpdHMgdmF1bHQgcmVnaXN0cnkgb24gbW9iaWxlKSBhbmQgcHVzaGluZyBmaWxlcyB0byB0aGUgZGV2aWNlLlxuICovXG5leHBvcnQgY2xhc3MgQXBwaXVtVHJhbnNwb3J0IGltcGxlbWVudHMgT2JzaWRpYW5UcmFuc3BvcnQge1xuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhpcyB0cmFuc3BvcnQgaXMgZm9yIGEgbW9iaWxlIHBsYXRmb3JtLiBBbHdheXMgYHRydWVgIGZvciB0aGlzIHRyYW5zcG9ydC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBpc01vYmlsZSA9IHRydWU7XG4gIHByaXZhdGUgcmVhZG9ubHkgYXBwSWQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBicm93c2VyOiBCcm93c2VyO1xuICBwcml2YXRlIHJlYWRvbmx5IGRldmljZUlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUcmFja3Mgd2hldGhlciB0aGUgZHJpdmVyIGlzIGN1cnJlbnRseSBzd2l0Y2hlZCB0byB0aGUgV2ViVmlldyBjb250ZXh0LlxuICAgKlxuICAgKiBTZXQgdG8gYHRydWVgIGFmdGVyIGEgc3VjY2Vzc2Z1bCBgc3dpdGNoQ29udGV4dChXRUJWSUVXX21kLm9ic2lkaWFuKWAuXG4gICAqIFJlc2V0IHRvIGBmYWxzZWAgd2hlbiB0aGUgY29udGV4dCBpcyBrbm93biB0byBiZSBpbnZhbGlkYXRlZFxuICAgKiAoZS5nLiBhZnRlciBgbG9jYXRpb24ucmVsb2FkKClgIGluIHtAbGluayByZWdpc3RlclZhdWx0fSkuXG4gICAqXG4gICAqIFdoZW4gYHRydWVgLCB7QGxpbmsgZW5zdXJlV2ViVmlld0NvbnRleHR9IHNraXBzIHRoZSBleHBlbnNpdmVcbiAgICogYGdldENvbnRleHRzKClgIGNhbGwgKHdoaWNoIHJ1bnMgYGFkYiBzaGVsbCBjYXQgL3Byb2MvbmV0L3VuaXhgIGFuZFxuICAgKiBjYW4gdGltZSBvdXQgb24gc2xvdyBlbXVsYXRvcnMpLlxuICAgKi9cbiAgcHJpdmF0ZSBpc0luV2ViVmlld0NvbnRleHQgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWFkb25seSBpc1Nlc3Npb25Pd25lcjogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBsYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHBsYXRmb3JtOiAnYW5kcm9pZCcgfCAnaW9zJztcbiAgcHJpdmF0ZSByZWFkb25seSBzaG91bGRTd2VlcExlZnRvdmVyczogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSB2YXVsdEJhc2VQYXRoOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB3ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgQXBwaXVtIHRyYW5zcG9ydC5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyAtIEFwcGl1bSB0cmFuc3BvcnQgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihjb25maWc6IEFwcGl1bVRyYW5zcG9ydENvbmZpZykge1xuICAgIHRoaXMuYnJvd3NlciA9IGNvbmZpZy5icm93c2VyO1xuICAgIHRoaXMuZGV2aWNlSWQgPSBjb25maWcuZGV2aWNlSWQ7XG4gICAgdGhpcy5pc1Nlc3Npb25Pd25lciA9IGNvbmZpZy5pc1Nlc3Npb25Pd25lciA/PyB0cnVlO1xuICAgIHRoaXMubGF5b3V0UmVhZHlUaW1lb3V0SW5NaWxsaXNlY29uZHMgPSBjb25maWcubGF5b3V0UmVhZHlUaW1lb3V0SW5NaWxsaXNlY29uZHMgPz8gREVGQVVMVF9MQVlPVVRfUkVBRFlfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUztcbiAgICB0aGlzLnBsYXRmb3JtID0gY29uZmlnLnBsYXRmb3JtO1xuICAgIHRoaXMuYXBwSWQgPSBjb25maWcuYXBwSWQgPz8gREVGQVVMVF9BUFBfSUQ7XG4gICAgdGhpcy5zaG91bGRTd2VlcExlZnRvdmVycyA9IGNvbmZpZy5zaG91bGRTd2VlcExlZnRvdmVycyA/PyB0cnVlO1xuICAgIHRoaXMudmF1bHRCYXNlUGF0aCA9IGNvbmZpZy52YXVsdEJhc2VQYXRoID8/IERFRkFVTFRfVkFVTFRfQkFTRV9QQVRIW3RoaXMucGxhdGZvcm1dID8/IERFRkFVTFRfQU5EUk9JRF9WQVVMVF9CQVNFX1BBVEg7XG4gICAgdGhpcy53ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzID0gY29uZmlnLndlYnZpZXdUaW1lb3V0SW5NaWxsaXNlY29uZHMgPz8gREVGQVVMVF9XRUJWSUVXX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gIH1cblxuICAvKipcbiAgICogQmVnaW5zIGEgY29uc29sZSBjYXB0dXJlIGJ5IHN0YW1waW5nIHRoZSBkZXZpY2UgbG9nIHdpdGggYSB1bmlxdWUgbWFya2VyLlxuICAgKlxuICAgKiBVc2VzIGBhZGIgc2hlbGwgbG9nYCB0byB3cml0ZSBhIG1hcmtlciBpbnRvIGBsb2djYXRgIGF0IGNhcHR1cmUgc3RhcnQgc28gYVxuICAgKiBsYXRlciB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LnJlYWRDb25zb2xlQ2FwdHVyZVNpbmNlfSBjYW4gc2xpY2Ugb3V0XG4gICAqIGV2ZXJ5dGhpbmcgdGhlIFdlYlZpZXcgbG9nZ2VkIGFmdGVyd2FyZHMgXHUyMDE0IHdpdGhvdXQgdGhlIGludmFzaXZlIGBsb2djYXQgLWNgXG4gICAqIGJ1ZmZlciBjbGVhci5cbiAgICpcbiAgICogQHJldHVybnMgQSBoYW5kbGUgY2FycnlpbmcgdGhlIHVuaXF1ZSBtYXJrZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYmVnaW5Db25zb2xlQ2FwdHVyZSgpOiBQcm9taXNlPENvbnNvbGVDYXB0dXJlSGFuZGxlPiB7XG4gICAgY29uc3QgbWFya2VyID0gYCR7Q09OU09MRV9DQVBUVVJFX01BUktFUl9UQUd9XyR7cmFuZG9tVVVJRCgpfWA7XG4gICAgYXdhaXQgZXhlYyhcbiAgICAgIFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ2xvZycsICctdCcsIENPTlNPTEVfQ0FQVFVSRV9NQVJLRVJfVEFHLCBtYXJrZXJdLFxuICAgICAgeyBpc1F1aWV0OiB0cnVlLCBzaG91bGRJZ25vcmVFeGl0Q29kZTogdHJ1ZSwgdGltZW91dEluTWlsbGlzZWNvbmRzOiBBREJfTE9HX01BUktFUl9USU1FT1VUX0lOX01JTExJU0VDT05EUyB9XG4gICAgKTtcbiAgICByZXR1cm4geyBtYXJrZXIgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYXB0dXJlcyBhIFBORyBzY3JlZW5zaG90IG9mIHRoZSBkZXZpY2UncyBzY3JlZW4uXG4gICAqXG4gICAqIFRoZSBpbWFnZSBpcyBhbHdheXMgdGhlIGRldmljZSdzIG5hdGl2ZSBmcmFtZWJ1ZmZlciBcdTIwMTQgdGhlcmUgaXMgbm8gbW9iaWxlXG4gICAqIGVxdWl2YWxlbnQgb2YgdGhlIGRlc2t0b3Agdmlld3BvcnQgb3ZlcnJpZGUsIHNvXG4gICAqIHtAbGluayBDYXB0dXJlU2NyZWVuc2hvdFBhcmFtcy53aWR0aEluUGl4ZWxzfSAvXG4gICAqIHtAbGluayBDYXB0dXJlU2NyZWVuc2hvdFBhcmFtcy5oZWlnaHRJblBpeGVsc30gYXJlIGlnbm9yZWQuIFNpemUgYSBtb2JpbGVcbiAgICogY2FwdHVyZSBieSBjaG9vc2luZyBhbiBBVkQgd2hvc2Ugc2NyZWVuIGdlb21ldHJ5IGFscmVhZHkgbWF0Y2hlcyB3aGF0IHRoZVxuICAgKiBpbWFnZSBoYXMgdG8gYmUuXG4gICAqXG4gICAqIEBwYXJhbSBfcGFyYW1zIC0gQ2FwdHVyZSBwYXJhbWV0ZXJzLiBJZ25vcmVkIG9uIG1vYmlsZTogYGN3ZGAgZG9lcyBub3Qgc2VsZWN0IGEgd2luZG93ICh2YXVsdCB0YXJnZXRpbmcgaXMgdmlhIGxvY2FsU3RvcmFnZSksIGFuZCB0aGUgc2l6ZSBjYW5ub3QgYmUgb3ZlcnJpZGRlbi5cbiAgICogQHJldHVybnMgVGhlIHJhdyBQTkcgYnl0ZXMuXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGRyaXZlciByZXR1cm5zIGRhdGEgdGhhdCBpcyBub3QgYSBQTkcuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgY2FwdHVyZVNjcmVlbnNob3QoX3BhcmFtczogQ2FwdHVyZVNjcmVlbnNob3RQYXJhbXMpOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCBieXRlcyA9IGRlY29kZUJhc2U2NFBuZyhhd2FpdCB0aGlzLmJyb3dzZXIudGFrZVNjcmVlbnNob3QoKSk7XG4gICAgaWYgKCFpc1BuZyhieXRlcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXBwaXVtIHNjcmVlbnNob3QgZXJyb3I6IHRha2VTY3JlZW5zaG90IHJldHVybmVkIGRhdGEgdGhhdCBpcyBub3QgYSBQTkcuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuZHMgdGhlIEFwcGl1bSBzZXNzaW9uLlxuICAgKlxuICAgKiBPbmx5IGRlbGV0ZXMgdGhlIHNlc3Npb24gaWYgdGhpcyB0cmFuc3BvcnQgb3ducyBpdC4gVHJhbnNwb3J0cyBjcmVhdGVkXG4gICAqIHZpYSBgYXR0YWNoKClgICh0ZXN0IHdvcmtlcnMgcmV1c2luZyB0aGUgZ2xvYmFsIHNldHVwJ3Mgc2Vzc2lvbikgc2tpcFxuICAgKiBkZWxldGlvbiBzbyB0aGUgc2Vzc2lvbiByZW1haW5zIGF2YWlsYWJsZSBmb3IgdGhlIG93bmluZyBwcm9jZXNzLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuaXNTZXNzaW9uT3duZXIpIHtcbiAgICAgIGF3YWl0IHRoaXMuYnJvd3Nlci5kZWxldGVTZXNzaW9uKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlcyBhIEphdmFTY3JpcHQgZXhwcmVzc2lvbiBpbnNpZGUgT2JzaWRpYW4gTW9iaWxlJ3MgV2ViVmlldy5cbiAgICpcbiAgICogU3dpdGNoZXMgdG8gdGhlIGBXRUJWSUVXX21kLm9ic2lkaWFuYCBjb250ZXh0LCBleGVjdXRlcyB0aGUgZXhwcmVzc2lvbixcbiAgICogYW5kIHJldHVybnMgdGhlIHJlc3VsdCBzdHJpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBleHByZXNzaW9uIC0gVGhlIEphdmFTY3JpcHQgZXhwcmVzc2lvbiB0byBldmFsdWF0ZS5cbiAgICogQHBhcmFtIF9vcHRpb25zIC0gRXZhbHVhdGlvbiBvcHRpb25zIChjd2QgaXMgbm90IHVzZWQgb24gbW9iaWxlIFx1MjAxNCB2YXVsdCB0YXJnZXRpbmcgaXMgdmlhIGxvY2FsU3RvcmFnZSkuXG4gICAqIEByZXR1cm5zIFRoZSBub3JtYWxpemVkIHJlc3VsdCBzdHJpbmcuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZXZhbHVhdGUoZXhwcmVzc2lvbjogc3RyaW5nLCBfb3B0aW9uczogVHJhbnNwb3J0RXZhbE9wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlV2ViVmlld0NvbnRleHQoKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmJyb3dzZXIuZXhlY3V0ZTxudWxsIHwgc3RyaW5nIHwgdW5kZWZpbmVkLCBbXT4oXG4gICAgICAgIGByZXR1cm4gKCR7ZXhwcmVzc2lvbn0pYFxuICAgICAgKTtcblxuICAgICAgaWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkIHx8IHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gTk9fT1VUUFVUO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAvLyBDb250ZXh0IG1heSBoYXZlIGJlZW4gbG9zdCBtaWQtZXhlY3V0aW9uIChlLmcuIHBhZ2UgcmVsb2FkKS5cbiAgICAgIHRoaXMuaXNJbldlYlZpZXdDb250ZXh0ID0gZmFsc2U7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2Vzc2lvbiBjb25uZWN0aW9uIGluZm8gbmVlZGVkIHRvIHJlYXR0YWNoIHRvIHRoaXMgc2Vzc2lvblxuICAgKiBmcm9tIGFub3RoZXIgcHJvY2VzcyAoZS5nLiBhIHRlc3Qgd29ya2VyKS5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIHNlc3Npb24gSUQgYW5kIGRldmljZSBJRC5cbiAgICovXG4gIHB1YmxpYyBnZXRTZXNzaW9uSW5mbygpOiBBcHBpdW1TZXNzaW9uSW5mbyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRldmljZUlkOiB0aGlzLmRldmljZUlkLFxuICAgICAgc2Vzc2lvbklkOiB0aGlzLmJyb3dzZXIuc2Vzc2lvbklkXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyB0aGF0IHRoZSBPYnNpZGlhbiBhcHAgaXMgcnVubmluZyBhbmQgdGhlIFdlYlZpZXcgaXMgYXZhaWxhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gX3ZhdWx0UGF0aCAtIE5vdCB1c2VkIG9uIG1vYmlsZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBwcmVmbGlnaHRDaGVjayhfdmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coJ1thcHBpdW0tdHJhbnNwb3J0XSBSdW5uaW5nIHByZWZsaWdodCBjaGVjay4uLicpO1xuICAgIGNvbnN0IHN0YXRlID0gYXdhaXQgdGhpcy5icm93c2VyLnF1ZXJ5QXBwU3RhdGUodGhpcy5hcHBJZCk7XG4gICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gQXBwIHN0YXRlOiAke1N0cmluZyhzdGF0ZSl9IChuZWVkICR7U3RyaW5nKEFQUF9TVEFURV9GT1JFR1JPVU5EKX09Zm9yZWdyb3VuZClgKTtcbiAgICBpZiAoc3RhdGUgIT09IEFQUF9TVEFURV9GT1JFR1JPVU5EKSB7XG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBBY3RpdmF0aW5nIGFwcCAke3RoaXMuYXBwSWR9Li4uYCk7XG4gICAgICB0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCA9IGZhbHNlO1xuICAgICAgYXdhaXQgdGhpcy5icm93c2VyLmFjdGl2YXRlQXBwKHRoaXMuYXBwSWQpO1xuICAgICAgYXdhaXQgZGVsYXkoQVBQX1JFU1RBUlRfREVMQVlfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVdlYlZpZXdDb250ZXh0KCk7XG4gICAgbG9nKCdbYXBwaXVtLXRyYW5zcG9ydF0gUHJlZmxpZ2h0IGNoZWNrIHBhc3NlZC4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdXNoZXMgdmF1bHQgZmlsZXMgdG8gdGhlIGRldmljZSB2aWEgY29tcHJlc3NlZCBgYWRiIHB1c2hgLlxuICAgKlxuICAgKiBDcmVhdGVzIGEgdGFyLmd6IGFyY2hpdmUgb2YgdGhlIGxvY2FsIHZhdWx0IGRpcmVjdG9yeSwgcHVzaGVzIGl0IHRvIHRoZVxuICAgKiBkZXZpY2UgYXMgYSBzaW5nbGUgZmlsZSwgYW5kIGV4dHJhY3RzIGl0IGluLXBsYWNlLiBUaGlzIGF2b2lkcyB0aGVcbiAgICogd2ViZHJpdmVyIGBSYW5nZUVycm9yYCBvbiBsYXJnZSBiYXNlNjQgcGF5bG9hZHMgYW5kIGlzIHNpZ25pZmljYW50bHlcbiAgICogZmFzdGVyIHRoYW4gcGVyLWZpbGUgYGJyb3dzZXIucHVzaEZpbGUoKWAgY2FsbHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgdmF1bHQgcGF0aCAodXNlZCBhcyB0aGUgdmF1bHQgZGlyZWN0b3J5IG5hbWUgb24gZGV2aWNlKS5cbiAgICogQHBhcmFtIF9maWxlcyAtIE1hcCBvZiByZWxhdGl2ZSBmaWxlIHBhdGhzIHRvIGNvbnRlbnQgYnVmZmVycyAodW51c2VkIFx1MjAxNCBhZGIgcHVzaGVzIHRoZSBkaXJlY3RvcnkgZGlyZWN0bHkpLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHB1c2hGaWxlcyh2YXVsdFBhdGg6IHN0cmluZywgX2ZpbGVzOiBSZWNvcmQ8c3RyaW5nLCBVaW50OEFycmF5Pik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRldmljZVZhdWx0UGF0aCA9IHRoaXMuZ2V0RGV2aWNlVmF1bHRQYXRoKHZhdWx0UGF0aCk7XG4gICAgY29uc3QgYXJjaGl2ZU5hbWUgPSBgdmF1bHQtJHtyYW5kb21VVUlEKCl9LnRhci5nemA7XG4gICAgY29uc3QgbG9jYWxBcmNoaXZlID0gam9pbih0bXBkaXIoKSwgYXJjaGl2ZU5hbWUpO1xuICAgIGNvbnN0IHJlbW90ZUFyY2hpdmUgPSBgL2RhdGEvbG9jYWwvdG1wLyR7YXJjaGl2ZU5hbWV9YDtcblxuICAgIHRyeSB7XG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBDcmVhdGluZyBhcmNoaXZlOiAke2xvY2FsQXJjaGl2ZX1gKTtcbiAgICAgIGF3YWl0IGV4ZWMoWyd0YXInLCAnY3pmJywgYXJjaGl2ZU5hbWUsICctQycsIHZhdWx0UGF0aCwgJy4nXSwgeyBjd2Q6IHRtcGRpcigpLCBpc1F1aWV0OiB0cnVlIH0pO1xuXG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBQdXNoaW5nIGFyY2hpdmUgdG8gZGV2aWNlICR7dGhpcy5kZXZpY2VJZH0uLi5gKTtcbiAgICAgIGF3YWl0IGV4ZWMoWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAncHVzaCcsIGxvY2FsQXJjaGl2ZSwgcmVtb3RlQXJjaGl2ZV0sIHsgaXNRdWlldDogdHJ1ZSB9KTtcblxuICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gRXh0cmFjdGluZyBhcmNoaXZlIG9uIGRldmljZSBhdCAke2RldmljZVZhdWx0UGF0aH0uLi5gKTtcbiAgICAgIGF3YWl0IGV4ZWMoWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAnc2hlbGwnLCAnbWtkaXInLCAnLXAnLCBkZXZpY2VWYXVsdFBhdGhdLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG4gICAgICBhd2FpdCBleGVjKFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ3RhcicsICd4emYnLCByZW1vdGVBcmNoaXZlLCAnLUMnLCBkZXZpY2VWYXVsdFBhdGhdLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG5cbiAgICAgIGxvZygnW2FwcGl1bS10cmFuc3BvcnRdIEZsdXNoaW5nIGZpbGVzeXN0ZW0gYnVmZmVycy4uLicpO1xuICAgICAgYXdhaXQgZXhlYyhbJ2FkYicsICctcycsIHRoaXMuZGV2aWNlSWQsICdzaGVsbCcsICdzeW5jJ10sIHsgaXNRdWlldDogdHJ1ZSB9KTtcblxuICAgICAgbG9nKCdbYXBwaXVtLXRyYW5zcG9ydF0gQ2xlYW5pbmcgdXAgcmVtb3RlIGFyY2hpdmUuLi4nKTtcbiAgICAgIGF3YWl0IGV4ZWMoWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAnc2hlbGwnLCAncm0nLCByZW1vdGVBcmNoaXZlXSwgeyBpc1F1aWV0OiB0cnVlIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBybShsb2NhbEFyY2hpdmUsIHsgZm9yY2U6IHRydWUgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIER1bXBzIGBhZGIgbG9nY2F0YCBhbmQgcmV0dXJucyB0aGUgV2ViVmlldyBjb25zb2xlL2Vycm9yIG91dHB1dCBsb2dnZWRcbiAgICogc2luY2UgdGhlIG1hcmtlciBmcm9tIHtAbGluayBBcHBpdW1UcmFuc3BvcnQuYmVnaW5Db25zb2xlQ2FwdHVyZX0uXG4gICAqXG4gICAqIEZpbHRlcnMgdG8gdGhlIENocm9taXVtL1dlYlZpZXcgdGFncyB0aGF0IGNhcnJ5IEpTIGBjb25zb2xlLipgIG91dHB1dCBhbmRcbiAgICogdW5jYXVnaHQgZXJyb3JzLCBhbmQgY2FwcyB0aGUgcmVzdWx0IGxlbmd0aC4gQm91bmRlZCwgcG9zdC1ob2MsXG4gICAqIGZhaWx1cmUtcGF0aC1vbmx5IFx1MjAxNCBuZXZlciBhIGxpdmUgbW9uaXRvci5cbiAgICpcbiAgICogQHBhcmFtIGhhbmRsZSAtIFRoZSBjYXB0dXJlIGhhbmRsZSAob3IgYHVuZGVmaW5lZGAgd2hlbiBjYXB0dXJlIG5ldmVyIHN0YXJ0ZWQpLlxuICAgKiBAcmV0dXJucyBUaGUgY2FwdHVyZWQgY29uc29sZS9lcnJvciB0ZXh0LCBvciBgdW5kZWZpbmVkYCBpZiBub3RoaW5nIHJlbGV2YW50IHdhcyBsb2dnZWQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVhZENvbnNvbGVDYXB0dXJlU2luY2UoaGFuZGxlOiBDb25zb2xlQ2FwdHVyZUhhbmRsZSB8IHVuZGVmaW5lZCk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCFoYW5kbGUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgZHVtcCA9IGF3YWl0IGV4ZWMoXG4gICAgICBbJ2FkYicsICctcycsIHRoaXMuZGV2aWNlSWQsICdsb2djYXQnLCAnLWQnLCAnLXYnLCAndGltZSddLFxuICAgICAgeyBpc1F1aWV0OiB0cnVlLCBzaG91bGRJZ25vcmVFeGl0Q29kZTogdHJ1ZSwgdGltZW91dEluTWlsbGlzZWNvbmRzOiBMT0dDQVRfRFVNUF9USU1FT1VUX0lOX01JTExJU0VDT05EUyB9XG4gICAgKTtcblxuICAgIGNvbnN0IG1hcmtlckluZGV4ID0gZHVtcC5sYXN0SW5kZXhPZihoYW5kbGUubWFya2VyKTtcbiAgICBjb25zdCByZWdpb24gPSBtYXJrZXJJbmRleCA9PT0gLTEgPyBkdW1wIDogZHVtcC5zbGljZShtYXJrZXJJbmRleCArIGhhbmRsZS5tYXJrZXIubGVuZ3RoKTtcbiAgICBjb25zdCByZWxldmFudCA9IHJlZ2lvblxuICAgICAgLnNwbGl0KCdcXG4nKVxuICAgICAgLmZpbHRlcigobGluZSkgPT4gQ09OU09MRV9DQVBUVVJFX1RBR19SRS50ZXN0KGxpbmUpKVxuICAgICAgLmpvaW4oJ1xcbicpXG4gICAgICAudHJpbSgpO1xuXG4gICAgaWYgKCFyZWxldmFudCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVsZXZhbnQuc2xpY2UoLUNPTlNPTEVfQ0FQVFVSRV9UQUlMX01BWF9MRU5HVEgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHZhdWx0IG9uIG1vYmlsZSBieSBwdXNoaW5nIGZpbGVzIGFuZCBjb25maWd1cmluZyBsb2NhbFN0b3JhZ2UuXG4gICAqXG4gICAqIFRoZSByZWdpc3RyYXRpb24gZmxvdzpcbiAgICogMS4gUHVzaCBhIG1pbmltYWwgYC5vYnNpZGlhbi9hcHAuanNvbmAgdG8gdGhlIGRldmljZSBzbyBPYnNpZGlhbiByZWNvZ25pemVzIHRoZSB2YXVsdFxuICAgKiAyLiBTd2l0Y2ggdG8gdGhlIFdlYlZpZXcgY29udGV4dFxuICAgKiAzLiBBZGQgdGhlIHZhdWx0IHRvIGxvY2FsU3RvcmFnZSAoYG1vYmlsZS1leHRlcm5hbC12YXVsdHNgLCBgbW9iaWxlLXNlbGVjdGVkLXZhdWx0YCxcbiAgICogICAgYGVuYWJsZS1wbHVnaW4tPHBhdGg+YClcbiAgICogNC4gVHJpZ2dlciBgbG9jYXRpb24ucmVsb2FkKClgIHNvIE9ic2lkaWFuIHJlLXJlYWRzIGxvY2FsU3RvcmFnZSBhbmQgb3BlbnMgdGhlIHZhdWx0XG4gICAqIDUuIFdhaXQgZm9yIGBhcHAud29ya3NwYWNlLmxheW91dFJlYWR5YFxuICAgKlxuICAgKiBFeGlzdGluZyB2YXVsdCByZWdpc3RyYXRpb25zIGluIGxvY2FsU3RvcmFnZSBhcmUgcHJlc2VydmVkIChhcHBlbmQsIG5vdFxuICAgKiBvdmVyd3JpdGUpIFx1MjAxNCBleGNlcHQgdGhlICoqaGFybmVzcydzIG93bioqIGB0ZW1wLXZhdWx0LSpgIHJlZ2lzdHJhdGlvbnMgZnJvbVxuICAgKiBlYXJsaWVyIHJ1bnMsIHdoaWNoIGFyZSBwcnVuZWQgd2hlbiB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0Q29uZmlnLnNob3VsZFN3ZWVwTGVmdG92ZXJzfVxuICAgKiBpcyBvbi4gVGhlaXIgZGlyZWN0b3JpZXMgYXJlIGFscmVhZHkgZ29uZSAodGhlIGZhY3Rvcnkgc3dlZXBzIHRoZW0gYmVmb3JlXG4gICAqIHRoZSBhcHAgbGF1bmNoZXMpLCBhbmQgaXQgaXMgdGhpcyByZWdpc3RyeSBcdTIwMTQgbm90IHRoZSBmaWxlc3lzdGVtIFx1MjAxNCB0aGF0XG4gICAqIE9ic2lkaWFuIGVudW1lcmF0ZXMgYXQgc3RhcnR1cCwgc28gbGVhdmluZyB0aGVtIGlzIHdoYXQgbWFrZXMgZWFjaCBmYWlsZWRcbiAgICogcnVuIHNsb3cgdGhlIG5leHQgb25lIGRvd24uXG4gICAqXG4gICAqIEBwYXJhbSB2YXVsdFBhdGggLSBUaGUgYWJzb2x1dGUgcGF0aCB0byB0aGUgdmF1bHQgb24gdGhlIGhvc3QgbWFjaGluZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyByZWdpc3RlclZhdWx0KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gUmVnaXN0ZXJpbmcgdmF1bHQ6ICR7dmF1bHRQYXRofWApO1xuICAgIGNvbnN0IGRldmljZVZhdWx0UGF0aCA9IHRoaXMuZ2V0RGV2aWNlVmF1bHRQYXRoKHZhdWx0UGF0aCk7XG5cbiAgICAvLyBQdXNoIGEgbWluaW1hbCAub2JzaWRpYW4gZGlyZWN0b3J5IHNvIE9ic2lkaWFuIHJlY29nbml6ZXMgaXQgYXMgYSB2YXVsdC5cbiAgICBhd2FpdCB0aGlzLnB1c2hPYnNpZGlhbk1hcmtlcihkZXZpY2VWYXVsdFBhdGgpO1xuXG4gICAgLy8gU3dpdGNoIHRvIFdlYlZpZXcgYW5kIGNvbmZpZ3VyZSBsb2NhbFN0b3JhZ2UuXG4gICAgYXdhaXQgdGhpcy5lbnN1cmVXZWJWaWV3Q29udGV4dCgpO1xuXG4gICAgLy8gSW52YWxpZGF0ZSBiZWZvcmUgcmVsb2FkIFx1MjAxNCB0aGUgcGFnZSB3aWxsIG5hdmlnYXRlIGFuZCB0aGUgV2ViVmlld1xuICAgIC8vIENvbnRleHQgbWF5IGJlIHRlbXBvcmFyaWx5IHVuYXZhaWxhYmxlIGR1cmluZyByZWxvYWQuXG4gICAgdGhpcy5pc0luV2ViVmlld0NvbnRleHQgPSBmYWxzZTtcblxuICAgIGNvbnN0IHN0YWxlUHJlZml4ID0gdGhpcy5zaG91bGRTd2VlcExlZnRvdmVycyA/IGAke3RoaXMudmF1bHRCYXNlUGF0aH0ke1RFTVBfVkFVTFRfRElSX1BSRUZJWH1gIDogJyc7XG5cbiAgICBhd2FpdCB0aGlzLmJyb3dzZXIuZXhlY3V0ZShcbiAgICAgIChwYXRoOiBzdHJpbmcsIHBydW5lUHJlZml4OiBzdHJpbmcpID0+IHtcbiAgICAgICAgbGV0IGV4aXN0aW5nID0gSlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnbW9iaWxlLWV4dGVybmFsLXZhdWx0cycpID8/ICdbXScpIGFzIHN0cmluZ1tdO1xuXG4gICAgICAgIGlmIChwcnVuZVByZWZpeCkge1xuICAgICAgICAgIGNvbnN0IHN0YWxlID0gZXhpc3RpbmcuZmlsdGVyKChyZWdpc3RlcmVkKSA9PiByZWdpc3RlcmVkICE9PSBwYXRoICYmIHJlZ2lzdGVyZWQuc3RhcnRzV2l0aChwcnVuZVByZWZpeCkpO1xuICAgICAgICAgIGZvciAoY29uc3QgcmVnaXN0ZXJlZCBvZiBzdGFsZSkge1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oYGVuYWJsZS1wbHVnaW4tJHtyZWdpc3RlcmVkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBleGlzdGluZyA9IGV4aXN0aW5nLmZpbHRlcigocmVnaXN0ZXJlZCkgPT4gIXN0YWxlLmluY2x1ZGVzKHJlZ2lzdGVyZWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZXhpc3RpbmcuaW5jbHVkZXMocGF0aCkpIHtcbiAgICAgICAgICBleGlzdGluZy5wdXNoKHBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzJywgSlNPTi5zdHJpbmdpZnkoZXhpc3RpbmcpKTtcbiAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ21vYmlsZS1zZWxlY3RlZC12YXVsdCcsIHBhdGgpO1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShgZW5hYmxlLXBsdWdpbi0ke3BhdGh9YCwgJ3RydWUnKTtcbiAgICAgICAgbG9jYXRpb24ucmVsb2FkKCk7XG4gICAgICB9LFxuICAgICAgZGV2aWNlVmF1bHRQYXRoLFxuICAgICAgc3RhbGVQcmVmaXhcbiAgICApO1xuXG4gICAgLy8gV2FpdCBmb3IgcmVsb2FkICsgdmF1bHQgaW5pdGlhbGl6YXRpb24uXG4gICAgYXdhaXQgdGhpcy53YWl0Rm9yTGF5b3V0UmVhZHkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVycyBhIHZhdWx0IG9uIG1vYmlsZSBieSByZW1vdmluZyBpdCBmcm9tIGxvY2FsU3RvcmFnZS5cbiAgICpcbiAgICogUHJlc2VydmVzIG90aGVyIHZhdWx0IHJlZ2lzdHJhdGlvbnMuIElmIHRoZSB1bnJlZ2lzdGVyZWQgdmF1bHQgd2FzIHNlbGVjdGVkLFxuICAgKiBzd2l0Y2hlcyB0byB0aGUgZmlyc3QgcmVtYWluaW5nIHZhdWx0IChvciBjbGVhcnMgdGhlIHNlbGVjdGlvbikuXG4gICAqXG4gICAqIFRoZSB2YXVsdCdzICoqZmlsZXMgYXJlIHRoZW4gcmVtb3ZlZCBmcm9tIHRoZSBkZXZpY2Ugb3ZlciBgYWRiYCwgd2hldGhlciBvclxuICAgKiBub3QgdGhlIGBsb2NhbFN0b3JhZ2VgIHN0ZXAgc3VjY2VlZGVkKiogXHUyMDE0IGRlbGliZXJhdGVseSwgYmVjYXVzZSB0aGVcbiAgICogYGxvY2FsU3RvcmFnZWAgc3RlcCBnb2VzIHRocm91Z2ggdGhlIFdlYlZpZXcgYW5kIGEgZGVhZCBXZWJWaWV3IGlzIGV4YWN0bHlcbiAgICogd2hhdCBtb3N0IEFuZHJvaWQgZmFpbHVyZXMgYXJlLiBSb3V0aW5nIHRoZSByZW1vdmFsIHRocm91Z2ggdGhlIGFwcCB3YXMgd2hhdFxuICAgKiBtYWRlIGV2ZXJ5IGZhaWxlZCBydW4gbGVhayBpdHMgdmF1bHQgKGBWYXVsdCBjbGVhbnVwIGVycm9yIChub24tZmF0YWwpOiBub1xuICAgKiBzdWNoIHdpbmRvd2ApLCBzbyB0aGUgZmlsZXN5c3RlbS1sZXZlbCByZW1vdmFsIG11c3Qgbm90IGRlcGVuZCBvbiBpdC5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBvbiB0aGUgaG9zdCBtYWNoaW5lLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHVucmVnaXN0ZXJWYXVsdCh2YXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRldmljZVZhdWx0UGF0aCA9IHRoaXMuZ2V0RGV2aWNlVmF1bHRQYXRoKHZhdWx0UGF0aCk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5lbnN1cmVXZWJWaWV3Q29udGV4dCgpO1xuXG4gICAgICBhd2FpdCB0aGlzLmJyb3dzZXIuZXhlY3V0ZSgocGF0aDogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nID0gSlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnbW9iaWxlLWV4dGVybmFsLXZhdWx0cycpID8/ICdbXScpIGFzIHN0cmluZ1tdO1xuICAgICAgICBjb25zdCBmaWx0ZXJlZCA9IGV4aXN0aW5nLmZpbHRlcigodikgPT4gdiAhPT0gcGF0aCk7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzJywgSlNPTi5zdHJpbmdpZnkoZmlsdGVyZWQpKTtcbiAgICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oYGVuYWJsZS1wbHVnaW4tJHtwYXRofWApO1xuICAgICAgICBpZiAobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ21vYmlsZS1zZWxlY3RlZC12YXVsdCcpID09PSBwYXRoKSB7XG4gICAgICAgICAgaWYgKGZpbHRlcmVkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdtb2JpbGUtc2VsZWN0ZWQtdmF1bHQnLCBmaWx0ZXJlZFswXSA/PyAnJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKCdtb2JpbGUtc2VsZWN0ZWQtdmF1bHQnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIGRldmljZVZhdWx0UGF0aCk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGxvZyhcbiAgICAgICAgYFthcHBpdW0tdHJhbnNwb3J0XSBDb3VsZCBub3QgZGVyZWdpc3RlciAke2RldmljZVZhdWx0UGF0aH0gZnJvbSBsb2NhbFN0b3JhZ2UgYFxuICAgICAgICAgICsgYCgke1N0cmluZyhlcnJvcil9KTsgcmVtb3ZpbmcgaXRzIGZpbGVzIGFueXdheS5gXG4gICAgICApO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMucmVtb3ZlRGV2aWNlVmF1bHREaXJlY3RvcnkoZGV2aWNlVmF1bHRQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTd2l0Y2hlcyB0aGUgZHJpdmVyIHRvIHRoZSBgV0VCVklFV19tZC5vYnNpZGlhbmAgY29udGV4dC5cbiAgICpcbiAgICogSWYgdGhlIGNvbnRleHQgd2FzIGFscmVhZHkgdmVyaWZpZWQgKGNhY2hlZCB2aWEge0BsaW5rIGlzSW5XZWJWaWV3Q29udGV4dH0pLFxuICAgKiByZXR1cm5zIGltbWVkaWF0ZWx5IHdpdGhvdXQgY2FsbGluZyBgZ2V0Q29udGV4dHMoKWAgXHUyMDE0IHdoaWNoIHJ1bnNcbiAgICogYGFkYiBzaGVsbCBjYXQgL3Byb2MvbmV0L3VuaXhgIGFuZCBjYW4gdGltZSBvdXQgb24gc2xvdyBlbXVsYXRvcnMuXG4gICAqXG4gICAqIFBvbGxzIHVudGlsIHRoZSBjb250ZXh0IGJlY29tZXMgYXZhaWxhYmxlICh0aGUgYXBwIG1heSBzdGlsbCBiZSBsb2FkaW5nKS5cbiAgICogVXNlcyB0aGUgYFdFQlZJRVdfbWQub2JzaWRpYW5gIGNvbnRleHQgc3BlY2lmaWNhbGx5IHRvIGF2b2lkIGNvbm5lY3RpbmdcbiAgICogdG8gQ2hyb21lIG9yIG90aGVyIFdlYlZpZXdzIG9uIHRoZSBkZXZpY2UuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZVdlYlZpZXdDb250ZXh0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIHRoaXMud2Vidmlld1RpbWVvdXRJbk1pbGxpc2Vjb25kcztcbiAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBXYWl0aW5nIGZvciAke1dFQlZJRVdfQ09OVEVYVF9QUkVGSVh9IGNvbnRleHQgKHRpbWVvdXQ9JHtTdHJpbmcodGhpcy53ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzKX1tcykuLi5gKTtcblxuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGNvbnN0IGNvbnRleHRzID0gYXdhaXQgdGhpcy5icm93c2VyLmdldENvbnRleHRzKCk7XG4gICAgICBjb25zdCBvYnNpZGlhbkNvbnRleHQgPSBjb250ZXh0cy5maW5kKChjb250ZXh0KTogY29udGV4dCBpcyBzdHJpbmcgPT4gdHlwZW9mIGNvbnRleHQgPT09ICdzdHJpbmcnICYmIGNvbnRleHQuc3RhcnRzV2l0aChXRUJWSUVXX0NPTlRFWFRfUFJFRklYKSk7XG5cbiAgICAgIGlmIChvYnNpZGlhbkNvbnRleHQpIHtcbiAgICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gRm91bmQgV2ViVmlldyBjb250ZXh0OiAke29ic2lkaWFuQ29udGV4dH1gKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmJyb3dzZXIuc3dpdGNoQ29udGV4dChvYnNpZGlhbkNvbnRleHQpO1xuICAgICAgICAgIHRoaXMuaXNJbldlYlZpZXdDb250ZXh0ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gc3dpdGNoQ29udGV4dCBmYWlsZWQ6ICR7U3RyaW5nKGVycm9yKX0uIFJlc2V0dGluZyB0byBOQVRJVkVfQVBQIGJlZm9yZSByZXRyeWluZy4uLmApO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmJyb3dzZXIuc3dpdGNoQ29udGV4dCgnTkFUSVZFX0FQUCcpO1xuICAgICAgICAgIH0gY2F0Y2ggKHJlc2V0RXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIE5BVElWRV9BUFAgcmVzZXQgYWxzbyBmYWlsZWQ6ICR7U3RyaW5nKHJlc2V0RXJyb3IpfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBXZWJWaWV3IG5vdCByZWFkeSwgYXZhaWxhYmxlIGNvbnRleHRzOiAke0pTT04uc3RyaW5naWZ5KGNvbnRleHRzKX0uIFJldHJ5aW5nLi4uYCk7XG4gICAgICBhd2FpdCBkZWxheShXRUJWSUVXX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vICR7V0VCVklFV19DT05URVhUX1BSRUZJWH0gY29udGV4dCBmb3VuZCB3aXRoaW4gJHtTdHJpbmcodGhpcy53ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzKX1tcy4gSXMgdGhlIE9ic2lkaWFuIGFwcCBmdWxseSBsb2FkZWQ/YCk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBob3N0LXNpZGUgdmF1bHQgcGF0aCB0byB0aGUgZGV2aWNlLXNpZGUgcGF0aC5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIEFic29sdXRlIHBhdGggb24gdGhlIGhvc3QgbWFjaGluZS5cbiAgICogQHJldHVybnMgVGhlIGRldmljZS1zaWRlIHZhdWx0IHBhdGguXG4gICAqL1xuICBwcml2YXRlIGdldERldmljZVZhdWx0UGF0aCh2YXVsdFBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMudmF1bHRCYXNlUGF0aH0ke2V4dHJhY3RWYXVsdE5hbWUodmF1bHRQYXRoKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFB1c2hlcyB0aGUgbWluaW1hbCBgLm9ic2lkaWFuL2FwcC5qc29uYCB2YXVsdCBtYXJrZXIgdmlhIGBhZGIgcHVzaGAuXG4gICAqXG4gICAqIGBicm93c2VyLnB1c2hGaWxlYCAoV2ViRHJpdmVyIGJhc2U2NCkgaXMgYW4gb3JkZXIgb2YgbWFnbml0dWRlIHNsb3dlciBvbiBhXG4gICAqIGNvbGQgb3IgbG9hZGVkIGVtdWxhdG9yIFx1MjAxNCBtZWFzdXJlZCBhdCA5XHUyMDEzMjFzIHBlciBjYWxsIGZvciB0aGlzIDItYnl0ZSBtYXJrZXIsXG4gICAqIHZlcnN1cyBzdWItc2Vjb25kIG92ZXIgYGFkYmAuIFRoaXMgbWlycm9ycyB7QGxpbmsgcHVzaEZpbGVzfSwgd2hpY2ggc3dpdGNoZWRcbiAgICogdG8gYGFkYmAgZm9yIHRoZSBzYW1lIHJlYXNvbi4gYG1rZGlyIC1wYCBndWFyYW50ZWVzIHRoZSBwYXJlbnQgZGlyZWN0b3J5LlxuICAgKlxuICAgKiBAcGFyYW0gZGV2aWNlVmF1bHRQYXRoIC0gVGhlIGRldmljZS1zaWRlIHZhdWx0IGRpcmVjdG9yeSBwYXRoLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwdXNoT2JzaWRpYW5NYXJrZXIoZGV2aWNlVmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsb2NhbE1hcmtlciA9IGpvaW4odG1wZGlyKCksIGBvYnNpZGlhbi1tYXJrZXItJHtyYW5kb21VVUlEKCl9Lmpzb25gKTtcbiAgICBjb25zdCByZW1vdGVNYXJrZXIgPSBgJHtkZXZpY2VWYXVsdFBhdGh9Ly5vYnNpZGlhbi9hcHAuanNvbmA7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd3JpdGVGaWxlKGxvY2FsTWFya2VyLCAne30nLCAndXRmLTgnKTtcbiAgICAgIGF3YWl0IGV4ZWMoWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAnc2hlbGwnLCAnbWtkaXInLCAnLXAnLCBgJHtkZXZpY2VWYXVsdFBhdGh9Ly5vYnNpZGlhbmBdLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG4gICAgICBhd2FpdCBleGVjKFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3B1c2gnLCBsb2NhbE1hcmtlciwgcmVtb3RlTWFya2VyXSwgeyBpc1F1aWV0OiB0cnVlIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBybShsb2NhbE1hcmtlciwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIHZhdWx0IGRpcmVjdG9yeSBmcm9tIHRoZSBkZXZpY2Ugb3ZlciBgYWRiYCwgYW5kIENIRUNLUyB0aGF0IGl0IGlzXG4gICAqIGFjdHVhbGx5IGdvbmUuXG4gICAqXG4gICAqIEJlc3QtZWZmb3J0OiBhIGZhaWx1cmUgaXMgbG9nZ2VkLCBub3QgdGhyb3duLCBzbyBhIHRlYXJkb3duIHByb2JsZW0gbmV2ZXJcbiAgICogbWFza3MgdGhlIHRlc3QgcmVzdWx0LiBUaGUgbmV4dCBydW4ncyBzdGFydC1vZi1ydW4gc3dlZXAgcGlja3MgdXAgd2hhdGV2ZXJcbiAgICogdGhpcyBjb3VsZCBub3QgcmVtb3ZlLlxuICAgKlxuICAgKiBUaGUgY2hlY2sgaXMgdGhlIHBvaW50LiBgcm0gLXJmYCBydW5zIHdpdGggYHNob3VsZElnbm9yZUV4aXRDb2RlYCwgc28gYW5cbiAgICogdW5yZW1vdmVkIGRpcmVjdG9yeSB1c2VkIHRvIGxlYXZlIG5vIHRyYWNlIGF0IGFsbCBcdTIwMTQgd2hpY2ggaXMgaG93IHJ1bnMgdGhhdFxuICAgKiBwYXNzZWQgZW5kIHRvIGVuZCB3ZXJlIHN0aWxsIGZvdW5kIHRvIGJlIGxlYWtpbmcgYSB2YXVsdCBhcGllY2UsIGludmlzaWJseSxcbiAgICogdW50aWwgc29tZW9uZSBjb3VudGVkIHRoZSBkaXJlY3RvcmllcyBvbiB0aGUgZGV2aWNlIGJ5IGhhbmQuIEEgbGVhayBpcyBub3dcbiAgICogbmFtZWQgaW4gdGhlIGxvZyBhdCB0aGUgbW9tZW50IGl0IGhhcHBlbnMuXG4gICAqXG4gICAqIEBwYXJhbSBkZXZpY2VWYXVsdFBhdGggLSBUaGUgZGV2aWNlLXNpZGUgdmF1bHQgZGlyZWN0b3J5IHBhdGguXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlbW92ZURldmljZVZhdWx0RGlyZWN0b3J5KGRldmljZVZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIFJlbW92aW5nIHZhdWx0IGRpcmVjdG9yeSBmcm9tIGRldmljZTogJHtkZXZpY2VWYXVsdFBhdGh9YCk7XG4gICAgICBhd2FpdCBleGVjKFxuICAgICAgICBbJ2FkYicsICctcycsIHRoaXMuZGV2aWNlSWQsICdzaGVsbCcsICdybScsICctcmYnLCBkZXZpY2VWYXVsdFBhdGhdLFxuICAgICAgICB7IGlzUXVpZXQ6IHRydWUsIHNob3VsZElnbm9yZUV4aXRDb2RlOiB0cnVlLCB0aW1lb3V0SW5NaWxsaXNlY29uZHM6IEFEQl9WQVVMVF9SRU1PVkVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgfVxuICAgICAgKTtcblxuICAgICAgY29uc3QgbGlzdGluZyA9IGF3YWl0IGV4ZWMoXG4gICAgICAgIFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ2xzJywgJy1kJywgZGV2aWNlVmF1bHRQYXRoXSxcbiAgICAgICAgeyBpc1F1aWV0OiB0cnVlLCBzaG91bGRJZ25vcmVFeGl0Q29kZTogdHJ1ZSwgdGltZW91dEluTWlsbGlzZWNvbmRzOiBBREJfVkFVTFRfUkVNT1ZFX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTIH1cbiAgICAgICk7XG5cbiAgICAgIGlmIChsaXN0aW5nLmluY2x1ZGVzKGRldmljZVZhdWx0UGF0aCkpIHtcbiAgICAgICAgbG9nKFxuICAgICAgICAgIGBbYXBwaXVtLXRyYW5zcG9ydF0gV2FybmluZzogJHtkZXZpY2VWYXVsdFBhdGh9IHN1cnZpdmVkIHJlbW92YWwgYW5kIGlzIG5vdyBsZWFrZWQgcmVzaWR1ZS4gYFxuICAgICAgICAgICAgKyAnVGhlIG5leHQgcnVuXFwncyBzdGFydC1vZi1ydW4gc3dlZXAgd2lsbCByZXRyeSBpdC4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIFZhdWx0IGRpcmVjdG9yeSByZW1vdmFsIGZhaWxlZCAobm9uLWZhdGFsKTogJHtTdHJpbmcoZXJyb3IpfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQb2xscyB1bnRpbCBgYXBwLndvcmtzcGFjZS5sYXlvdXRSZWFkeWAgaXMgYHRydWVgIGluIHRoZSBXZWJWaWV3LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB3YWl0Rm9yTGF5b3V0UmVhZHkoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGRlYWRsaW5lID0gc3RhcnQgKyB0aGlzLmxheW91dFJlYWR5VGltZW91dEluTWlsbGlzZWNvbmRzO1xuICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIFdhaXRpbmcgZm9yIGxheW91dCByZWFkeSAodGltZW91dD0ke1N0cmluZyh0aGlzLmxheW91dFJlYWR5VGltZW91dEluTWlsbGlzZWNvbmRzKX1tcykuLi5gKTtcblxuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGlzUmVhZHkgPSBhd2FpdCB0aGlzLmJyb3dzZXIuZXhlY3V0ZSgoKTogYm9vbGVhbiA9PiB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1kZXByZWNhdGVkIC0tIFdlIG5lZWQgZ2xvYmFsIGBhcHBgIHZhcmlhYmxlLlxuICAgICAgICAgIGNvbnN0IGFwcCA9IGdsb2JhbFRoaXMuYXBwIGFzIExvYWRpbmdBcHAgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgcmV0dXJuICEhYXBwPy53b3Jrc3BhY2U/LmxheW91dFJlYWR5O1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGlzUmVhZHkpIHtcbiAgICAgICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBMYXlvdXQgaXMgcmVhZHkgYWZ0ZXIgJHtTdHJpbmcoRGF0ZS5ub3coKSAtIHN0YXJ0KX1tcy5gKTtcbiAgICAgICAgICB0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gQXBwIG5vdCByZWFkeSB5ZXQgKHBhZ2UgbWF5IGJlIHJlbG9hZGluZykuXG4gICAgICB9XG5cbiAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIExheW91dCBub3QgcmVhZHkgeWV0IChlbGFwc2VkPSR7U3RyaW5nKERhdGUubm93KCkgLSBzdGFydCl9bXMpLiBSZXRyeWluZy4uLmApO1xuICAgICAgYXdhaXQgZGVsYXkoTEFZT1VUX1JFQURZX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE9ic2lkaWFuIGxheW91dCBkaWQgbm90IGJlY29tZSByZWFkeSB3aXRoaW4gJHtTdHJpbmcodGhpcy5sYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kcyl9bXNgKTtcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgdGhlIGdpdmVuIGRlbGF5LlxuICpcbiAqIEBwYXJhbSBtcyAtIFRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHMuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciB0aGUgZGVsYXkuXG4gKi9cbmZ1bmN0aW9uIGRlbGF5KG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgc2V0VGltZW91dChyZXNvbHZlLCBtcyk7XG4gIH0pO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIHRoZSB2YXVsdCBkaXJlY3RvcnkgbmFtZSBmcm9tIGEgaG9zdC1zaWRlIHZhdWx0IHBhdGguXG4gKlxuICogQHBhcmFtIHZhdWx0UGF0aCAtIEFic29sdXRlIHBhdGggb24gdGhlIGhvc3QgbWFjaGluZS5cbiAqIEByZXR1cm5zIFRoZSBsYXN0IHBhdGggc2VnbWVudCAodmF1bHQgZGlyZWN0b3J5IG5hbWUpLlxuICovXG5mdW5jdGlvbiBleHRyYWN0VmF1bHROYW1lKHZhdWx0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHZhdWx0UGF0aC5yZXBsYWNlKC9bXFxcXC9dKyQvLCAnJyk7XG4gIGNvbnN0IGxhc3RTZXBhcmF0b3IgPSBNYXRoLm1heChub3JtYWxpemVkLmxhc3RJbmRleE9mKCcvJyksIG5vcm1hbGl6ZWQubGFzdEluZGV4T2YoJ1xcXFwnKSk7XG4gIHJldHVybiBub3JtYWxpemVkLnNsaWNlKGxhc3RTZXBhcmF0b3IgKyAxKTtcbn1cblxu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
|
|
694
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC1hcHBpdW0udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBBcHBpdW0gdHJhbnNwb3J0IFx1MjAxNCBldmFsdWF0ZXMgZXhwcmVzc2lvbnMgaW5zaWRlIE9ic2lkaWFuIE1vYmlsZSB2aWEgV2ViVmlld1xuICogSmF2YVNjcmlwdCBpbmplY3Rpb24uIE1hbmFnZXMgdmF1bHQgbGlmZWN5Y2xlIHZpYSBsb2NhbFN0b3JhZ2UgYW5kIGZpbGUgcHVzaC5cbiAqXG4gKiBDb25maWd1cmVkIHZpYSBgZW52aXJvbm1lbnRPcHRpb25zLm9ic2lkaWFuVHJhbnNwb3J0YCBpbiB2aXRlc3QgY29uZmlnOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIHZpdGVzdC5jb25maWcudHNcbiAqIGVudmlyb25tZW50T3B0aW9uczoge1xuICogICBvYnNpZGlhblRyYW5zcG9ydDoge1xuICogICAgIHR5cGU6ICdvYnNpZGlhbi1hbmRyb2lkLWFwcGl1bScsXG4gKiAgICAgYXBwaXVtVXJsOiAnaHR0cDovL2xvY2FsaG9zdDo0NzIzJyxcbiAqICAgICBhdmROYW1lOiAnb2JzaWRpYW5fdGVzdCcsXG4gKiAgIH0sXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBGb3IgQnJvd3NlclN0YWNrLCBzZXQgYGFwcGl1bVVybGAgdG8gdGhlIEJyb3dzZXJTdGFjayBodWIgVVJMXG4gKiBcdTIwMTQgdGhlIHRyYW5zcG9ydCBpdHNlbGYgaXMgaHViLWFnbm9zdGljLlxuICpcbiAqICMjIEhvdyB2YXVsdCByZWdpc3RyYXRpb24gd29ya3Mgb24gbW9iaWxlXG4gKlxuICogT2JzaWRpYW4gTW9iaWxlIHN0b3JlcyBpdHMgdmF1bHQgcmVnaXN0cnkgaW4gdGhlIFdlYlZpZXcncyBgbG9jYWxTdG9yYWdlYDpcbiAqXG4gKiAtIGBtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzYCBcdTIwMTQgSlNPTiBhcnJheSBvZiByZWdpc3RlcmVkIHZhdWx0IHBhdGhzXG4gKiAtIGBtb2JpbGUtc2VsZWN0ZWQtdmF1bHRgIFx1MjAxNCB0aGUgY3VycmVudGx5IGFjdGl2ZSB2YXVsdCBwYXRoXG4gKiAtIGBlbmFibGUtcGx1Z2luLTx2YXVsdFBhdGg+YCBcdTIwMTQgYFwidHJ1ZVwiYCB0byBlbmFibGUgdGhlIHBsdWdpbiBzeXN0ZW0gZm9yIHRoZSB2YXVsdFxuICpcbiAqIFRvIHJlZ2lzdGVyIGEgdmF1bHQgcHJvZ3JhbW1hdGljYWxseSAod2l0aG91dCBVSSBpbnRlcmFjdGlvbik6XG4gKlxuICogMS4gUHVzaCB2YXVsdCBmaWxlcyB0byB0aGUgZGV2aWNlIChlLmcuIGAvc2RjYXJkL0RvY3VtZW50cy88TmFtZT4vLm9ic2lkaWFuL2FwcC5qc29uYClcbiAqIDIuIFN3aXRjaCB0byBgV0VCVklFV19tZC5vYnNpZGlhbmAgY29udGV4dFxuICogMy4gU2V0IHRoZSBsb2NhbFN0b3JhZ2UgZW50cmllc1xuICogNC4gQ2FsbCBgbG9jYXRpb24ucmVsb2FkKClgIFx1MjAxNCBPYnNpZGlhbiByZS1yZWFkcyBsb2NhbFN0b3JhZ2UgYW5kIG9wZW5zIHRoZSB2YXVsdFxuICpcbiAqIFRoaXMgYXZvaWRzIHRoZSBvbmJvYXJkaW5nIGZsb3cgZW50aXJlbHkuXG4gKi9cblxuLyogdjggaWdub3JlIHN0YXJ0IC0tIEludGVncmF0aW9uLXRpbWUgY29kZSBjb3ZlcmVkIGJ5IGludGVncmF0aW9uIHRlc3RzLCBub3QgdW5pdCB0ZXN0cy4gKi9cblxuaW1wb3J0IHR5cGUgeyBCcm93c2VyIH0gZnJvbSAnd2ViZHJpdmVyaW8nO1xuXG5pbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHtcbiAgcm0sXG4gIHdyaXRlRmlsZVxufSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCc7XG5cbmltcG9ydCB0eXBlIHtcbiAgQXBwU3RhcnR1cE1pbGVzdG9uZSxcbiAgQXBwU3RhcnR1cFBoYXNlLFxuICBTdGFydHVwUHJvYmVSZXN1bHRcbn0gZnJvbSAnLi9hcHAtc3RhcnR1cC1wcm9ncmVzcy5tanMnO1xuaW1wb3J0IHR5cGUgeyBDYXB0dXJlU2NyZWVuc2hvdFBhcmFtcyB9IGZyb20gJy4vY2FwdHVyZS1zY3JlZW5zaG90Lm1qcyc7XG5pbXBvcnQgdHlwZSB7IE1vYmlsZUlucHV0RW52ZWxvcGUgfSBmcm9tICcuL21vYmlsZS1pbnB1dC5tanMnO1xuaW1wb3J0IHR5cGUge1xuICBDb25zb2xlQ2FwdHVyZUhhbmRsZSxcbiAgT2JzaWRpYW5UcmFuc3BvcnQsXG4gIFRyYW5zcG9ydEV2YWxPcHRpb25zXG59IGZyb20gJy4vdHJhbnNwb3J0Lm1qcyc7XG5pbXBvcnQgdHlwZSB7IFdlYlZpZXdDZHBDb25uZWN0aW9uIH0gZnJvbSAnLi93ZWJ2aWV3LWNkcC5tanMnO1xuXG5pbXBvcnQge1xuICBidWlsZFN0YXJ0dXBUaW1lb3V0TWVzc2FnZSxcbiAgY2hlY2tBcHBTdGFydGVkLFxuICBjaGVja0xheW91dFJlYWR5LFxuICBjbGFzc2lmeUFwcFN0YXJ0dXBQcm9iZSxcbiAgY29tcGFyZUFwcFN0YXJ0dXBNaWxlc3RvbmVzXG59IGZyb20gJy4vYXBwLXN0YXJ0dXAtcHJvZ3Jlc3MubWpzJztcbmltcG9ydCB7XG4gIGRlY29kZUJhc2U2NFBuZyxcbiAgaXNQbmdcbn0gZnJvbSAnLi9jYXB0dXJlLXNjcmVlbnNob3QubWpzJztcbmltcG9ydCB7IGVycm9yVG9TdHJpbmcgfSBmcm9tICcuL2Vycm9yLXRvLXN0cmluZy5tanMnO1xuaW1wb3J0IHsgZXhlYyB9IGZyb20gJy4vZXhlYy5tanMnO1xuaW1wb3J0IHsgVEVNUF9WQVVMVF9ESVJfUFJFRklYIH0gZnJvbSAnLi9sZWZ0b3Zlci1jbGVhbnVwLm1qcyc7XG5pbXBvcnQgeyBsb2cgfSBmcm9tICcuL2xvZy5tanMnO1xuaW1wb3J0IHtcbiAgYnVpbGRSZXNvbHZlSW5wdXRFeHByZXNzaW9uLFxuICBNT0JJTEVfSU5QVVRfQklORElOR19OQU1FLFxuICB0b0NkcElucHV0Q29tbWFuZHNcbn0gZnJvbSAnLi9tb2JpbGUtaW5wdXQubWpzJztcbmltcG9ydCB7IGNvbm5lY3RUb1dlYlZpZXdDZHAgfSBmcm9tICcuL3dlYnZpZXctY2RwLm1qcyc7XG5cbi8qKlxuICogU2Vzc2lvbiBjb25uZWN0aW9uIGluZm8gcmV0dXJuZWQgYnkge0BsaW5rIEFwcGl1bVRyYW5zcG9ydC5nZXRTZXNzaW9uSW5mb30sXG4gKiB1c2VkIHRvIHJlYXR0YWNoIGZyb20gYW5vdGhlciBwcm9jZXNzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwcGl1bVNlc3Npb25JbmZvIHtcbiAgLyoqXG4gIFRoZSBkZXZpY2UgVURJRCAoZS5nLiBgJ2VtdWxhdG9yLTU1NTQnYCkuXG4gICAqL1xuICBkZXZpY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICBUaGUgQXBwaXVtL1dlYkRyaXZlciBzZXNzaW9uIElELlxuICAgKi9cbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIEFwcGl1bSB0cmFuc3BvcnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwaXVtVHJhbnNwb3J0Q29uZmlnIHtcbiAgLyoqXG4gICAqIEFwcCBwYWNrYWdlIChBbmRyb2lkKSBvciBidW5kbGUgSUQgKGlPUykuXG4gICAqIERlZmF1bHRzIHRvIGAnbWQub2JzaWRpYW4nYC5cbiAgICovXG4gIGFwcElkPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3IgT2JzaWRpYW4gTW9iaWxlIHRvIGdldCBhcyBmYXIgYXMgYGdsb2JhbFRoaXMuYXBwYFxuICAgKiBleGlzdGluZyBhZnRlciB0aGUgdmF1bHQgaXMgKHJlKW9wZW5lZCwgYmVmb3JlIHRoZSB0aWdodGVyXG4gICAqIHtAbGluayBsYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kc30gY2xvY2sgc3RhcnRzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgMTgwMDAwYFxuICAgKi9cbiAgYXBwU3RhcnRUaW1lb3V0SW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBBcHBpdW0gYnJvd3Nlci9kcml2ZXIgaW5zdGFuY2UuXG4gICAqIENyZWF0ZWQgYnkgdGhlIGNvbnN1bWVyIHZpYSBlLmcuIFdlYkRyaXZlcklPJ3MgYHJlbW90ZSgpYC5cbiAgICovXG4gIGJyb3dzZXI6IEJyb3dzZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBkZXZpY2UgVURJRCAoZS5nLiBgJ2VtdWxhdG9yLTU1NTQnYCkuXG4gICAqIFVzZWQgZm9yIGBhZGJgIGNvbW1hbmRzIHdoZW4gcHVzaGluZyBmaWxlcyB0byB0aGUgZGV2aWNlLlxuICAgKi9cbiAgZGV2aWNlSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHRyYW5zcG9ydCBvd25zIHRoZSBBcHBpdW0gc2Vzc2lvbiBhbmQgc2hvdWxkIGRlbGV0ZSBpdCBvblxuICAgKiB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LmRpc3Bvc2V9LlxuICAgKlxuICAgKiBgdHJ1ZWAgZm9yIHNlc3Npb25zIGNyZWF0ZWQgdmlhIGByZW1vdGUoKWAgKGdsb2JhbCBzZXR1cCkuXG4gICAqIGBmYWxzZWAgZm9yIHNlc3Npb25zIHJlYXR0YWNoZWQgdmlhIGBhdHRhY2goKWAgKHRlc3Qgd29ya2VycykuXG4gICAqXG4gICAqIEBkZWZhdWx0IGB0cnVlYFxuICAgKi9cbiAgaXNTZXNzaW9uT3duZXI/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3Igd2FpdGluZyBmb3IgYGFwcC53b3Jrc3BhY2UubGF5b3V0UmVhZHlgLCBjb3VudGVkXG4gICAqIGZyb20gdGhlIG1vbWVudCB7QGxpbmsgYXBwU3RhcnRUaW1lb3V0SW5NaWxsaXNlY29uZHN9IGlzIHNhdGlzZmllZCBcdTIwMTQgbm90IGZyb21cbiAgICogdGhlIHJlbG9hZCwgc28gYSBjb2xkIGFwcCBzdGFydCBpcyBub3QgY2hhcmdlZCBhZ2FpbnN0IGl0LlxuICAgKlxuICAgKiBAZGVmYXVsdCBgOTAwMDBgXG4gICAqL1xuICBsYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kcz86IG51bWJlcjtcblxuICAvKipcbiAgICogVGFyZ2V0IHBsYXRmb3JtLiBEZXRlcm1pbmVzIFdlYlZpZXcgY29udGV4dCBuYW1pbmcgYW5kIGRldmljZSBmaWxlIHBhdGhzLlxuICAgKi9cbiAgcGxhdGZvcm06ICdhbmRyb2lkJyB8ICdpb3MnO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHJlZ2lzdGVyaW5nIGEgdmF1bHQgYWxzbyBwcnVuZXMgdGhlICoqb3RoZXIqKiBgdGVtcC12YXVsdC0qYFxuICAgKiByZWdpc3RyYXRpb25zIGVhcmxpZXIgcnVucyBsZWZ0IGluIE9ic2lkaWFuIE1vYmlsZSdzIGBsb2NhbFN0b3JhZ2VgLlxuICAgKlxuICAgKiBUaGUgZGV2aWNlLXNpZGUgZGlyZWN0b3JpZXMgYXJlIHN3ZXB0IGJlZm9yZSB0aGUgYXBwIGxhdW5jaGVzIChzZWUgdGhlXG4gICAqIGZhY3RvcnkpOyB0aGlzIHJlbW92ZXMgdGhlaXIgbm93LWRhbmdsaW5nIHJlZ2lzdHJ5IGVudHJpZXMsIHdoaWNoIGFyZSB3aGF0XG4gICAqIE9ic2lkaWFuIGFjdHVhbGx5IGVudW1lcmF0ZXMgYXQgc3RhcnR1cC4gVW5yZWdpc3RlcmluZyB0aGlzIHJ1bidzIG93biB2YXVsdFxuICAgKiBpcyB1bmFmZmVjdGVkIFx1MjAxNCB0aGF0IGFsd2F5cyBoYXBwZW5zLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgdHJ1ZWBcbiAgICovXG4gIHNob3VsZFN3ZWVwTGVmdG92ZXJzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQmFzZSBwYXRoIG9uIHRoZSBkZXZpY2Ugd2hlcmUgT2JzaWRpYW4gc3RvcmVzIHZhdWx0cy5cbiAgICpcbiAgICogRGVmYXVsdHM6XG4gICAqIC0gQW5kcm9pZDogYC9zZGNhcmQvRG9jdW1lbnRzL2BcbiAgICogLSBpT1M6IGBAbWQub2JzaWRpYW46ZG9jdW1lbnRzL2BcbiAgICovXG4gIHZhdWx0QmFzZVBhdGg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciB3YWl0aW5nIGZvciB0aGUgV2ViVmlldyBjb250ZXh0IHRvIGJlY29tZSBhdmFpbGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGA2MDAwMGBcbiAgICovXG4gIHdlYnZpZXdUaW1lb3V0SW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG59XG5cbmNvbnN0IE5PX09VVFBVVCA9ICcobm8gb3V0cHV0KSc7XG5jb25zdCBBUFBfU1RBVEVfRk9SRUdST1VORCA9IDQ7XG5jb25zdCBXRUJWSUVXX0NPTlRFWFRfUFJFRklYID0gJ1dFQlZJRVdfbWQub2JzaWRpYW4nO1xuY29uc3QgV0VCVklFV19QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyA9IDUwMDtcbmNvbnN0IERFRkFVTFRfV0VCVklFV19QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gNjBfMDAwO1xuY29uc3QgTEFZT1VUX1JFQURZX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTID0gNTAwO1xuY29uc3QgREVGQVVMVF9MQVlPVVRfUkVBRFlfUE9MTF9USU1FT1VUX0lOX01JTExJU0VDT05EUyA9IDkwXzAwMDtcbmNvbnN0IERFRkFVTFRfQVBQX1NUQVJUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAxODBfMDAwO1xuY29uc3QgQVBQX1JFU1RBUlRfREVMQVlfSU5fTUlMTElTRUNPTkRTID0gMjAwMDtcbmNvbnN0IERFRkFVTFRfQVBQX0lEID0gJ21kLm9ic2lkaWFuJztcbmNvbnN0IEFEQl9WQVVMVF9SRU1PVkVfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgPSAzMF8wMDA7XG5cbi8vIC0tLSBDb25zb2xlIGNhcHR1cmUgKExheWVyIDIgb2YgdGhlIHBsdWdpbi1sb2FkIGVycm9yIHN1cmZhY2luZykgLS0tXG5jb25zdCBDT05TT0xFX0NBUFRVUkVfTUFSS0VSX1RBRyA9ICdPSVRfQ0FQVFVSRSc7XG5jb25zdCBDT05TT0xFX0NBUFRVUkVfVEFJTF9NQVhfTEVOR1RIID0gODAwMDtcbmNvbnN0IEFEQl9MT0dfTUFSS0VSX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gNTAwMDtcbmNvbnN0IExPR0NBVF9EVU1QX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTID0gMTBfMDAwO1xuLyoqXG4gKiBgYWRiIGxvZ2NhdCAtdiB0aW1lYCBsaW5lcyBsb29rIGxpa2UgYE1NLUREIEhIOk1NOlNTLm1tbSBMRVZFTC9UQUcoIFBJRCk6IG1lc3NhZ2VgLlxuICogS2VlcCBvbmx5IHRoZSB0YWdzIENocm9taXVtL1dlYlZpZXcgcm91dGVzIEpTIGBjb25zb2xlLipgIG91dHB1dCBhbmQgdW5jYXVnaHRcbiAqIGVycm9ycyB0byAoYGNocm9taXVtYCwgdGhlIENhcGFjaXRvciBjb25zb2xlIGJyaWRnZSwgYW5kIG5hdGl2ZSBgQW5kcm9pZFJ1bnRpbWVgKS5cbiAqL1xuY29uc3QgQ09OU09MRV9DQVBUVVJFX1RBR19SRSA9IC9cXC8oPzpjaHJvbWl1bXxBbmRyb2lkUnVudGltZXxDYXBhY2l0b3JcXC9Db25zb2xlKVxcKC87XG5cbi8qKlxuICogQmFzZSBwYXRoIG9uIGFuIEFuZHJvaWQgZGV2aWNlIHdoZXJlIE9ic2lkaWFuIE1vYmlsZSBzdG9yZXMgaXRzIHZhdWx0cy5cbiAqXG4gKiBFeHBvcnRlZCBiZWNhdXNlIHRoZSB0cmFuc3BvcnQgZmFjdG9yeSBzd2VlcHMgbGVmdG92ZXIgdmF1bHRzIGZyb20gaXQgYmVmb3JlXG4gKiBhIHRyYW5zcG9ydCBleGlzdHMgKHNlZSB0aGUgcmVwbydzIEwzMSkuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0FORFJPSURfVkFVTFRfQkFTRV9QQVRIID0gJy9zZGNhcmQvRG9jdW1lbnRzLyc7XG5cbmNvbnN0IERFRkFVTFRfVkFVTFRfQkFTRV9QQVRIOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBhbmRyb2lkOiBERUZBVUxUX0FORFJPSURfVkFVTFRfQkFTRV9QQVRILFxuICBpb3M6ICdAbWQub2JzaWRpYW46ZG9jdW1lbnRzLydcbn07XG5cbmludGVyZmFjZSBMb2FkaW5nQXBwIHtcbiAgd29ya3NwYWNlPzogTG9hZGluZ1dvcmtzcGFjZTtcbn1cblxuaW50ZXJmYWNlIExvYWRpbmdXb3Jrc3BhY2Uge1xuICBsYXlvdXRSZWFkeT86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIEFwcGl1bVRyYW5zcG9ydC53YWl0Rm9yU3RhcnR1cE1pbGVzdG9uZX0uXG4gKi9cbmludGVyZmFjZSBXYWl0Rm9yU3RhcnR1cE1pbGVzdG9uZVBhcmFtcyB7XG4gIC8qKlxuICBXaGV0aGVyIHRoZSBtaWxlc3RvbmUganVzdCBvYnNlcnZlZCBlbmRzIHRoaXMgcGhhc2UuXG4gICAqL1xuICByZWFkb25seSBpc1NhdGlzZmllZDogKG1pbGVzdG9uZTogQXBwU3RhcnR1cE1pbGVzdG9uZSkgPT4gYm9vbGVhbjtcblxuICAvKipcbiAgVGhlIHBoYXNlIGJlaW5nIHdhaXRlZCBvdXQsIG5hbWVkIGluIHRoZSBsb2cgYW5kIGluIHRoZSB0aW1lb3V0IG1lc3NhZ2UuXG4gICAqL1xuICByZWFkb25seSBwaGFzZTogQXBwU3RhcnR1cFBoYXNlO1xuXG4gIC8qKlxuICBUaGlzIHBoYXNlJ3MgYnVkZ2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgdGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG59XG5cbi8qKlxuICogVHJhbnNwb3J0IHRoYXQgY29tbXVuaWNhdGVzIHdpdGggT2JzaWRpYW4gTW9iaWxlIHZpYSBBcHBpdW0gV2ViVmlldyBKUyBpbmplY3Rpb24uXG4gKlxuICogRXZhbHVhdGVzIGV4cHJlc3Npb25zIGJ5IHN3aXRjaGluZyB0byB0aGUgYFdFQlZJRVdfbWQub2JzaWRpYW5gIGNvbnRleHQgYW5kXG4gKiBjYWxsaW5nIGBleGVjdXRlKClgLiBNYW5hZ2VzIHZhdWx0cyBieSB3cml0aW5nIHRvIHRoZSBXZWJWaWV3J3MgYGxvY2FsU3RvcmFnZWBcbiAqICh3aGljaCBPYnNpZGlhbiB1c2VzIGFzIGl0cyB2YXVsdCByZWdpc3RyeSBvbiBtb2JpbGUpIGFuZCBwdXNoaW5nIGZpbGVzIHRvIHRoZSBkZXZpY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBBcHBpdW1UcmFuc3BvcnQgaW1wbGVtZW50cyBPYnNpZGlhblRyYW5zcG9ydCB7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0aGlzIHRyYW5zcG9ydCBpcyBmb3IgYSBtb2JpbGUgcGxhdGZvcm0uIEFsd2F5cyBgdHJ1ZWAgZm9yIHRoaXMgdHJhbnNwb3J0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGlzTW9iaWxlID0gdHJ1ZTtcbiAgcHJpdmF0ZSByZWFkb25seSBhcHBJZDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGFwcFN0YXJ0VGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnJvd3NlcjogQnJvd3NlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBkZXZpY2VJZDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGBwcm9jZXNzLm9uKCdleGl0JylgIGhhbmRsZXIgdGhhdCB0ZWFycyB0aGUgY2hhbm5lbCBkb3duIHdoZW4gbm90aGluZyBlbHNlIHdpbGwuXG4gICAqL1xuICBwcml2YXRlIGRpc3Bvc2VJbnB1dENoYW5uZWxPbkV4aXQ6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogVGhlIGhvc3QgaGFsZiBvZiB0aGUgdHJ1c3RlZC1pbnB1dCBjaGFubmVsOiBhIENEUCBjb25uZWN0aW9uIHRvIHRoZSBXZWJWaWV3LCBpbmRlcGVuZGVudCBvZiB0aGVcbiAgICogQXBwaXVtIHNlc3Npb24sIG9wZW5lZCBsYXppbHkgb24gZmlyc3QgZXZhbHVhdGUgYW5kIHJldXNlZCAoc2VlICoqTDM5KiopLlxuICAgKi9cbiAgcHJpdmF0ZSBpbnB1dENoYW5uZWw6IG51bGwgfCBXZWJWaWV3Q2RwQ29ubmVjdGlvbiA9IG51bGw7XG4gIC8qKlxuICAgKiBTZXQgb25jZSB0aGUgdHJ1c3RlZC1pbnB1dCBjaGFubmVsIGlzIGtub3duIG5vdCB0byBiZSBvcGVuYWJsZSBoZXJlIChpT1MsIGEgcmVtb3RlIGh1Yiwgbm8gbG9jYWxcbiAgICogYGFkYmApLCBzbyB0aGUgYXR0ZW1wdCBpcyBub3QgcmVwZWF0ZWQgb24gZXZlcnkgZXZhbHVhdGUuXG4gICAqL1xuICBwcml2YXRlIGlzSW5wdXRDaGFubmVsVW5hdmFpbGFibGUgPSBmYWxzZTtcbiAgLyoqXG4gICAqIFRyYWNrcyB3aGV0aGVyIHRoZSBkcml2ZXIgaXMgY3VycmVudGx5IHN3aXRjaGVkIHRvIHRoZSBXZWJWaWV3IGNvbnRleHQuXG4gICAqXG4gICAqIFNldCB0byBgdHJ1ZWAgYWZ0ZXIgYSBzdWNjZXNzZnVsIGBzd2l0Y2hDb250ZXh0KFdFQlZJRVdfbWQub2JzaWRpYW4pYC5cbiAgICogUmVzZXQgdG8gYGZhbHNlYCB3aGVuIHRoZSBjb250ZXh0IGlzIGtub3duIHRvIGJlIGludmFsaWRhdGVkXG4gICAqIChlLmcuIGFmdGVyIGBsb2NhdGlvbi5yZWxvYWQoKWAgaW4ge0BsaW5rIHJlZ2lzdGVyVmF1bHR9KS5cbiAgICpcbiAgICogV2hlbiBgdHJ1ZWAsIHtAbGluayBlbnN1cmVXZWJWaWV3Q29udGV4dH0gc2tpcHMgdGhlIGV4cGVuc2l2ZVxuICAgKiBgZ2V0Q29udGV4dHMoKWAgY2FsbCAod2hpY2ggcnVucyBgYWRiIHNoZWxsIGNhdCAvcHJvYy9uZXQvdW5peGAgYW5kXG4gICAqIGNhbiB0aW1lIG91dCBvbiBzbG93IGVtdWxhdG9ycykuXG4gICAqL1xuICBwcml2YXRlIGlzSW5XZWJWaWV3Q29udGV4dCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWRvbmx5IGlzU2Vzc2lvbk93bmVyOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IGxheW91dFJlYWR5VGltZW91dEluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGxhdGZvcm06ICdhbmRyb2lkJyB8ICdpb3MnO1xuICBwcml2YXRlIHJlYWRvbmx5IHNob3VsZFN3ZWVwTGVmdG92ZXJzOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IHZhdWx0QmFzZVBhdGg6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IHdlYnZpZXdUaW1lb3V0SW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBBcHBpdW0gdHJhbnNwb3J0LlxuICAgKlxuICAgKiBAcGFyYW0gY29uZmlnIC0gQXBwaXVtIHRyYW5zcG9ydCBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKGNvbmZpZzogQXBwaXVtVHJhbnNwb3J0Q29uZmlnKSB7XG4gICAgdGhpcy5icm93c2VyID0gY29uZmlnLmJyb3dzZXI7XG4gICAgdGhpcy5kZXZpY2VJZCA9IGNvbmZpZy5kZXZpY2VJZDtcbiAgICB0aGlzLmlzU2Vzc2lvbk93bmVyID0gY29uZmlnLmlzU2Vzc2lvbk93bmVyID8/IHRydWU7XG4gICAgdGhpcy5sYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kcyA9IGNvbmZpZy5sYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kcyA/PyBERUZBVUxUX0xBWU9VVF9SRUFEWV9QT0xMX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTO1xuICAgIHRoaXMucGxhdGZvcm0gPSBjb25maWcucGxhdGZvcm07XG4gICAgdGhpcy5hcHBJZCA9IGNvbmZpZy5hcHBJZCA/PyBERUZBVUxUX0FQUF9JRDtcbiAgICB0aGlzLmFwcFN0YXJ0VGltZW91dEluTWlsbGlzZWNvbmRzID0gY29uZmlnLmFwcFN0YXJ0VGltZW91dEluTWlsbGlzZWNvbmRzID8/IERFRkFVTFRfQVBQX1NUQVJUX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gICAgdGhpcy5zaG91bGRTd2VlcExlZnRvdmVycyA9IGNvbmZpZy5zaG91bGRTd2VlcExlZnRvdmVycyA/PyB0cnVlO1xuICAgIHRoaXMudmF1bHRCYXNlUGF0aCA9IGNvbmZpZy52YXVsdEJhc2VQYXRoID8/IERFRkFVTFRfVkFVTFRfQkFTRV9QQVRIW3RoaXMucGxhdGZvcm1dID8/IERFRkFVTFRfQU5EUk9JRF9WQVVMVF9CQVNFX1BBVEg7XG4gICAgdGhpcy53ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzID0gY29uZmlnLndlYnZpZXdUaW1lb3V0SW5NaWxsaXNlY29uZHMgPz8gREVGQVVMVF9XRUJWSUVXX1BPTExfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFM7XG4gIH1cblxuICAvKipcbiAgICogQmVnaW5zIGEgY29uc29sZSBjYXB0dXJlIGJ5IHN0YW1waW5nIHRoZSBkZXZpY2UgbG9nIHdpdGggYSB1bmlxdWUgbWFya2VyLlxuICAgKlxuICAgKiBVc2VzIGBhZGIgc2hlbGwgbG9nYCB0byB3cml0ZSBhIG1hcmtlciBpbnRvIGBsb2djYXRgIGF0IGNhcHR1cmUgc3RhcnQgc28gYVxuICAgKiBsYXRlciB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LnJlYWRDb25zb2xlQ2FwdHVyZVNpbmNlfSBjYW4gc2xpY2Ugb3V0XG4gICAqIGV2ZXJ5dGhpbmcgdGhlIFdlYlZpZXcgbG9nZ2VkIGFmdGVyd2FyZHMgXHUyMDE0IHdpdGhvdXQgdGhlIGludmFzaXZlIGBsb2djYXQgLWNgXG4gICAqIGJ1ZmZlciBjbGVhci5cbiAgICpcbiAgICogQHJldHVybnMgQSBoYW5kbGUgY2FycnlpbmcgdGhlIHVuaXF1ZSBtYXJrZXIuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYmVnaW5Db25zb2xlQ2FwdHVyZSgpOiBQcm9taXNlPENvbnNvbGVDYXB0dXJlSGFuZGxlPiB7XG4gICAgY29uc3QgbWFya2VyID0gYCR7Q09OU09MRV9DQVBUVVJFX01BUktFUl9UQUd9XyR7cmFuZG9tVVVJRCgpfWA7XG4gICAgYXdhaXQgZXhlYyhcbiAgICAgIFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ2xvZycsICctdCcsIENPTlNPTEVfQ0FQVFVSRV9NQVJLRVJfVEFHLCBtYXJrZXJdLFxuICAgICAgeyBpc1F1aWV0OiB0cnVlLCBzaG91bGRJZ25vcmVFeGl0Q29kZTogdHJ1ZSwgdGltZW91dEluTWlsbGlzZWNvbmRzOiBBREJfTE9HX01BUktFUl9USU1FT1VUX0lOX01JTExJU0VDT05EUyB9XG4gICAgKTtcbiAgICByZXR1cm4geyBtYXJrZXIgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYXB0dXJlcyBhIFBORyBzY3JlZW5zaG90IG9mIHRoZSBkZXZpY2UncyBzY3JlZW4uXG4gICAqXG4gICAqIFRoZSBpbWFnZSBpcyBhbHdheXMgdGhlIGRldmljZSdzIG5hdGl2ZSBmcmFtZWJ1ZmZlciBcdTIwMTQgdGhlcmUgaXMgbm8gbW9iaWxlXG4gICAqIGVxdWl2YWxlbnQgb2YgdGhlIGRlc2t0b3Agdmlld3BvcnQgb3ZlcnJpZGUsIHNvXG4gICAqIHtAbGluayBDYXB0dXJlU2NyZWVuc2hvdFBhcmFtcy53aWR0aEluUGl4ZWxzfSAvXG4gICAqIHtAbGluayBDYXB0dXJlU2NyZWVuc2hvdFBhcmFtcy5oZWlnaHRJblBpeGVsc30gYXJlIGlnbm9yZWQuIFNpemUgYSBtb2JpbGVcbiAgICogY2FwdHVyZSBieSBjaG9vc2luZyBhbiBBVkQgd2hvc2Ugc2NyZWVuIGdlb21ldHJ5IGFscmVhZHkgbWF0Y2hlcyB3aGF0IHRoZVxuICAgKiBpbWFnZSBoYXMgdG8gYmUuXG4gICAqXG4gICAqIEBwYXJhbSBfcGFyYW1zIC0gQ2FwdHVyZSBwYXJhbWV0ZXJzLiBJZ25vcmVkIG9uIG1vYmlsZTogYGN3ZGAgZG9lcyBub3Qgc2VsZWN0IGEgd2luZG93ICh2YXVsdCB0YXJnZXRpbmcgaXMgdmlhIGxvY2FsU3RvcmFnZSksIGFuZCB0aGUgc2l6ZSBjYW5ub3QgYmUgb3ZlcnJpZGRlbi5cbiAgICogQHJldHVybnMgVGhlIHJhdyBQTkcgYnl0ZXMuXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGRyaXZlciByZXR1cm5zIGRhdGEgdGhhdCBpcyBub3QgYSBQTkcuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgY2FwdHVyZVNjcmVlbnNob3QoX3BhcmFtczogQ2FwdHVyZVNjcmVlbnNob3RQYXJhbXMpOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCBieXRlcyA9IGRlY29kZUJhc2U2NFBuZyhhd2FpdCB0aGlzLmJyb3dzZXIudGFrZVNjcmVlbnNob3QoKSk7XG4gICAgaWYgKCFpc1BuZyhieXRlcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXBwaXVtIHNjcmVlbnNob3QgZXJyb3I6IHRha2VTY3JlZW5zaG90IHJldHVybmVkIGRhdGEgdGhhdCBpcyBub3QgYSBQTkcuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuZHMgdGhlIEFwcGl1bSBzZXNzaW9uLlxuICAgKlxuICAgKiBPbmx5IGRlbGV0ZXMgdGhlIHNlc3Npb24gaWYgdGhpcyB0cmFuc3BvcnQgb3ducyBpdC4gVHJhbnNwb3J0cyBjcmVhdGVkXG4gICAqIHZpYSBgYXR0YWNoKClgICh0ZXN0IHdvcmtlcnMgcmV1c2luZyB0aGUgZ2xvYmFsIHNldHVwJ3Mgc2Vzc2lvbikgc2tpcFxuICAgKiBkZWxldGlvbiBzbyB0aGUgc2Vzc2lvbiByZW1haW5zIGF2YWlsYWJsZSBmb3IgdGhlIG93bmluZyBwcm9jZXNzLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5kaXNwb3NlSW5wdXRDaGFubmVsKCk7XG5cbiAgICBpZiAodGhpcy5pc1Nlc3Npb25Pd25lcikge1xuICAgICAgYXdhaXQgdGhpcy5icm93c2VyLmRlbGV0ZVNlc3Npb24oKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3luY2hyb25vdXMgdGVhcmRvd24gZm9yIGBwcm9jZXNzLm9uKCdleGl0JylgIGhhbmRsZXJzLlxuICAgKlxuICAgKiBPbmx5IHRoZSB0cnVzdGVkLWlucHV0IGNoYW5uZWwgbmVlZHMgaXQ6IHRoZSBBcHBpdW0gc2Vzc2lvbiBpcyB0aGUgb3duaW5nIHByb2Nlc3MncyB0byBlbmQsIGFuZCBhblxuICAgKiBhYnJ1cHQgZXhpdCBpcyBleGFjdGx5IHdoZW4gdGhlIGFzeW5jIHtAbGluayBBcHBpdW1UcmFuc3BvcnQuZGlzcG9zZX0gbmV2ZXIgcnVucyBcdTIwMTQgd2hpY2ggd291bGQgc3RyYW5kXG4gICAqIHRoZSBhZGIgcG9ydCBmb3J3YXJkIG9uIHRoZSBkZXZpY2UuXG4gICAqL1xuICBwdWJsaWMgZGlzcG9zZVN5bmMoKTogdm9pZCB7XG4gICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuaW5wdXRDaGFubmVsO1xuICAgIHRoaXMuaW5wdXRDaGFubmVsID0gbnVsbDtcbiAgICB0aGlzLnVucmVnaXN0ZXJJbnB1dENoYW5uZWxFeGl0SGFuZGxlcigpO1xuICAgIGNoYW5uZWw/LmRpc3Bvc2VTeW5jKCk7XG4gIH1cblxuICAvKipcbiAgICogRXZhbHVhdGVzIGEgSmF2YVNjcmlwdCBleHByZXNzaW9uIGluc2lkZSBPYnNpZGlhbiBNb2JpbGUncyBXZWJWaWV3LlxuICAgKlxuICAgKiBTd2l0Y2hlcyB0byB0aGUgYFdFQlZJRVdfbWQub2JzaWRpYW5gIGNvbnRleHQsIGV4ZWN1dGVzIHRoZSBleHByZXNzaW9uLFxuICAgKiBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IHN0cmluZy5cbiAgICpcbiAgICogQHBhcmFtIGV4cHJlc3Npb24gLSBUaGUgSmF2YVNjcmlwdCBleHByZXNzaW9uIHRvIGV2YWx1YXRlLlxuICAgKiBAcGFyYW0gX29wdGlvbnMgLSBFdmFsdWF0aW9uIG9wdGlvbnMgKGN3ZCBpcyBub3QgdXNlZCBvbiBtb2JpbGUgXHUyMDE0IHZhdWx0IHRhcmdldGluZyBpcyB2aWEgbG9jYWxTdG9yYWdlKS5cbiAgICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgcmVzdWx0IHN0cmluZy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBldmFsdWF0ZShleHByZXNzaW9uOiBzdHJpbmcsIF9vcHRpb25zOiBUcmFuc3BvcnRFdmFsT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVXZWJWaWV3Q29udGV4dCgpO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlSW5wdXRDaGFubmVsKCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5icm93c2VyLmV4ZWN1dGU8bnVsbCB8IHN0cmluZyB8IHVuZGVmaW5lZCwgW10+KFxuICAgICAgICBgcmV0dXJuICgke2V4cHJlc3Npb259KWBcbiAgICAgICk7XG5cbiAgICAgIGlmIChyZXN1bHQgPT09IHVuZGVmaW5lZCB8fCByZXN1bHQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIE5PX09VVFBVVDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgLy8gQ29udGV4dCBtYXkgaGF2ZSBiZWVuIGxvc3QgbWlkLWV4ZWN1dGlvbiAoZS5nLiBwYWdlIHJlbG9hZCkuXG4gICAgICB0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCA9IGZhbHNlO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNlc3Npb24gY29ubmVjdGlvbiBpbmZvIG5lZWRlZCB0byByZWF0dGFjaCB0byB0aGlzIHNlc3Npb25cbiAgICogZnJvbSBhbm90aGVyIHByb2Nlc3MgKGUuZy4gYSB0ZXN0IHdvcmtlcikuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBzZXNzaW9uIElEIGFuZCBkZXZpY2UgSUQuXG4gICAqL1xuICBwdWJsaWMgZ2V0U2Vzc2lvbkluZm8oKTogQXBwaXVtU2Vzc2lvbkluZm8ge1xuICAgIHJldHVybiB7XG4gICAgICBkZXZpY2VJZDogdGhpcy5kZXZpY2VJZCxcbiAgICAgIHNlc3Npb25JZDogdGhpcy5icm93c2VyLnNlc3Npb25JZFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpZXMgdGhhdCB0aGUgT2JzaWRpYW4gYXBwIGlzIHJ1bm5pbmcgYW5kIHRoZSBXZWJWaWV3IGlzIGF2YWlsYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIF92YXVsdFBhdGggLSBOb3QgdXNlZCBvbiBtb2JpbGUuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcHJlZmxpZ2h0Q2hlY2soX3ZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nKCdbYXBwaXVtLXRyYW5zcG9ydF0gUnVubmluZyBwcmVmbGlnaHQgY2hlY2suLi4nKTtcbiAgICBjb25zdCBzdGF0ZSA9IGF3YWl0IHRoaXMuYnJvd3Nlci5xdWVyeUFwcFN0YXRlKHRoaXMuYXBwSWQpO1xuICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIEFwcCBzdGF0ZTogJHtTdHJpbmcoc3RhdGUpfSAobmVlZCAke1N0cmluZyhBUFBfU1RBVEVfRk9SRUdST1VORCl9PWZvcmVncm91bmQpYCk7XG4gICAgaWYgKHN0YXRlICE9PSBBUFBfU1RBVEVfRk9SRUdST1VORCkge1xuICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gQWN0aXZhdGluZyBhcHAgJHt0aGlzLmFwcElkfS4uLmApO1xuICAgICAgdGhpcy5pc0luV2ViVmlld0NvbnRleHQgPSBmYWxzZTtcbiAgICAgIGF3YWl0IHRoaXMuYnJvd3Nlci5hY3RpdmF0ZUFwcCh0aGlzLmFwcElkKTtcbiAgICAgIGF3YWl0IGRlbGF5KEFQUF9SRVNUQVJUX0RFTEFZX0lOX01JTExJU0VDT05EUyk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5lbnN1cmVXZWJWaWV3Q29udGV4dCgpO1xuICAgIGxvZygnW2FwcGl1bS10cmFuc3BvcnRdIFByZWZsaWdodCBjaGVjayBwYXNzZWQuJyk7XG4gIH1cblxuICAvKipcbiAgICogUHVzaGVzIHZhdWx0IGZpbGVzIHRvIHRoZSBkZXZpY2UgdmlhIGNvbXByZXNzZWQgYGFkYiBwdXNoYC5cbiAgICpcbiAgICogQ3JlYXRlcyBhIHRhci5neiBhcmNoaXZlIG9mIHRoZSBsb2NhbCB2YXVsdCBkaXJlY3RvcnksIHB1c2hlcyBpdCB0byB0aGVcbiAgICogZGV2aWNlIGFzIGEgc2luZ2xlIGZpbGUsIGFuZCBleHRyYWN0cyBpdCBpbi1wbGFjZS4gVGhpcyBhdm9pZHMgdGhlXG4gICAqIHdlYmRyaXZlciBgUmFuZ2VFcnJvcmAgb24gbGFyZ2UgYmFzZTY0IHBheWxvYWRzIGFuZCBpcyBzaWduaWZpY2FudGx5XG4gICAqIGZhc3RlciB0aGFuIHBlci1maWxlIGBicm93c2VyLnB1c2hGaWxlKClgIGNhbGxzLlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIHZhdWx0IHBhdGggKHVzZWQgYXMgdGhlIHZhdWx0IGRpcmVjdG9yeSBuYW1lIG9uIGRldmljZSkuXG4gICAqIEBwYXJhbSBfZmlsZXMgLSBNYXAgb2YgcmVsYXRpdmUgZmlsZSBwYXRocyB0byBjb250ZW50IGJ1ZmZlcnMgKHVudXNlZCBcdTIwMTQgYWRiIHB1c2hlcyB0aGUgZGlyZWN0b3J5IGRpcmVjdGx5KS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBwdXNoRmlsZXModmF1bHRQYXRoOiBzdHJpbmcsIF9maWxlczogUmVjb3JkPHN0cmluZywgVWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBkZXZpY2VWYXVsdFBhdGggPSB0aGlzLmdldERldmljZVZhdWx0UGF0aCh2YXVsdFBhdGgpO1xuICAgIGNvbnN0IGFyY2hpdmVOYW1lID0gYHZhdWx0LSR7cmFuZG9tVVVJRCgpfS50YXIuZ3pgO1xuICAgIGNvbnN0IGxvY2FsQXJjaGl2ZSA9IGpvaW4odG1wZGlyKCksIGFyY2hpdmVOYW1lKTtcbiAgICBjb25zdCByZW1vdGVBcmNoaXZlID0gYC9kYXRhL2xvY2FsL3RtcC8ke2FyY2hpdmVOYW1lfWA7XG5cbiAgICB0cnkge1xuICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gQ3JlYXRpbmcgYXJjaGl2ZTogJHtsb2NhbEFyY2hpdmV9YCk7XG4gICAgICBhd2FpdCBleGVjKFsndGFyJywgJ2N6ZicsIGFyY2hpdmVOYW1lLCAnLUMnLCB2YXVsdFBhdGgsICcuJ10sIHsgY3dkOiB0bXBkaXIoKSwgaXNRdWlldDogdHJ1ZSB9KTtcblxuICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gUHVzaGluZyBhcmNoaXZlIHRvIGRldmljZSAke3RoaXMuZGV2aWNlSWR9Li4uYCk7XG4gICAgICBhd2FpdCBleGVjKFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3B1c2gnLCBsb2NhbEFyY2hpdmUsIHJlbW90ZUFyY2hpdmVdLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG5cbiAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIEV4dHJhY3RpbmcgYXJjaGl2ZSBvbiBkZXZpY2UgYXQgJHtkZXZpY2VWYXVsdFBhdGh9Li4uYCk7XG4gICAgICBhd2FpdCBleGVjKFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ21rZGlyJywgJy1wJywgZGV2aWNlVmF1bHRQYXRoXSwgeyBpc1F1aWV0OiB0cnVlIH0pO1xuICAgICAgYXdhaXQgZXhlYyhbJ2FkYicsICctcycsIHRoaXMuZGV2aWNlSWQsICdzaGVsbCcsICd0YXInLCAneHpmJywgcmVtb3RlQXJjaGl2ZSwgJy1DJywgZGV2aWNlVmF1bHRQYXRoXSwgeyBpc1F1aWV0OiB0cnVlIH0pO1xuXG4gICAgICBsb2coJ1thcHBpdW0tdHJhbnNwb3J0XSBGbHVzaGluZyBmaWxlc3lzdGVtIGJ1ZmZlcnMuLi4nKTtcbiAgICAgIGF3YWl0IGV4ZWMoWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAnc2hlbGwnLCAnc3luYyddLCB7IGlzUXVpZXQ6IHRydWUgfSk7XG5cbiAgICAgIGxvZygnW2FwcGl1bS10cmFuc3BvcnRdIENsZWFuaW5nIHVwIHJlbW90ZSBhcmNoaXZlLi4uJyk7XG4gICAgICBhd2FpdCBleGVjKFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ3JtJywgcmVtb3RlQXJjaGl2ZV0sIHsgaXNRdWlldDogdHJ1ZSB9KTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgcm0obG9jYWxBcmNoaXZlLCB7IGZvcmNlOiB0cnVlIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEdW1wcyBgYWRiIGxvZ2NhdGAgYW5kIHJldHVybnMgdGhlIFdlYlZpZXcgY29uc29sZS9lcnJvciBvdXRwdXQgbG9nZ2VkXG4gICAqIHNpbmNlIHRoZSBtYXJrZXIgZnJvbSB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LmJlZ2luQ29uc29sZUNhcHR1cmV9LlxuICAgKlxuICAgKiBGaWx0ZXJzIHRvIHRoZSBDaHJvbWl1bS9XZWJWaWV3IHRhZ3MgdGhhdCBjYXJyeSBKUyBgY29uc29sZS4qYCBvdXRwdXQgYW5kXG4gICAqIHVuY2F1Z2h0IGVycm9ycywgYW5kIGNhcHMgdGhlIHJlc3VsdCBsZW5ndGguIEJvdW5kZWQsIHBvc3QtaG9jLFxuICAgKiBmYWlsdXJlLXBhdGgtb25seSBcdTIwMTQgbmV2ZXIgYSBsaXZlIG1vbml0b3IuXG4gICAqXG4gICAqIEBwYXJhbSBoYW5kbGUgLSBUaGUgY2FwdHVyZSBoYW5kbGUgKG9yIGB1bmRlZmluZWRgIHdoZW4gY2FwdHVyZSBuZXZlciBzdGFydGVkKS5cbiAgICogQHJldHVybnMgVGhlIGNhcHR1cmVkIGNvbnNvbGUvZXJyb3IgdGV4dCwgb3IgYHVuZGVmaW5lZGAgaWYgbm90aGluZyByZWxldmFudCB3YXMgbG9nZ2VkLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlYWRDb25zb2xlQ2FwdHVyZVNpbmNlKGhhbmRsZTogQ29uc29sZUNhcHR1cmVIYW5kbGUgfCB1bmRlZmluZWQpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICghaGFuZGxlKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IGR1bXAgPSBhd2FpdCBleGVjKFxuICAgICAgWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAnbG9nY2F0JywgJy1kJywgJy12JywgJ3RpbWUnXSxcbiAgICAgIHsgaXNRdWlldDogdHJ1ZSwgc2hvdWxkSWdub3JlRXhpdENvZGU6IHRydWUsIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogTE9HQ0FUX0RVTVBfVElNRU9VVF9JTl9NSUxMSVNFQ09ORFMgfVxuICAgICk7XG5cbiAgICBjb25zdCBtYXJrZXJJbmRleCA9IGR1bXAubGFzdEluZGV4T2YoaGFuZGxlLm1hcmtlcik7XG4gICAgY29uc3QgcmVnaW9uID0gbWFya2VySW5kZXggPT09IC0xID8gZHVtcCA6IGR1bXAuc2xpY2UobWFya2VySW5kZXggKyBoYW5kbGUubWFya2VyLmxlbmd0aCk7XG4gICAgY29uc3QgcmVsZXZhbnQgPSByZWdpb25cbiAgICAgIC5zcGxpdCgnXFxuJylcbiAgICAgIC5maWx0ZXIoKGxpbmUpID0+IENPTlNPTEVfQ0FQVFVSRV9UQUdfUkUudGVzdChsaW5lKSlcbiAgICAgIC5qb2luKCdcXG4nKVxuICAgICAgLnRyaW0oKTtcblxuICAgIGlmICghcmVsZXZhbnQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlbGV2YW50LnNsaWNlKC1DT05TT0xFX0NBUFRVUkVfVEFJTF9NQVhfTEVOR1RIKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSB2YXVsdCBvbiBtb2JpbGUgYnkgcHVzaGluZyBmaWxlcyBhbmQgY29uZmlndXJpbmcgbG9jYWxTdG9yYWdlLlxuICAgKlxuICAgKiBUaGUgcmVnaXN0cmF0aW9uIGZsb3c6XG4gICAqIDEuIFB1c2ggYSBtaW5pbWFsIGAub2JzaWRpYW4vYXBwLmpzb25gIHRvIHRoZSBkZXZpY2Ugc28gT2JzaWRpYW4gcmVjb2duaXplcyB0aGUgdmF1bHRcbiAgICogMi4gU3dpdGNoIHRvIHRoZSBXZWJWaWV3IGNvbnRleHRcbiAgICogMy4gQWRkIHRoZSB2YXVsdCB0byBsb2NhbFN0b3JhZ2UgKGBtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzYCwgYG1vYmlsZS1zZWxlY3RlZC12YXVsdGAsXG4gICAqICAgIGBlbmFibGUtcGx1Z2luLTxwYXRoPmApXG4gICAqIDQuIFRyaWdnZXIgYGxvY2F0aW9uLnJlbG9hZCgpYCBzbyBPYnNpZGlhbiByZS1yZWFkcyBsb2NhbFN0b3JhZ2UgYW5kIG9wZW5zIHRoZSB2YXVsdFxuICAgKiA1LiBXYWl0IGZvciBgZ2xvYmFsVGhpcy5hcHBgIHRvIGV4aXN0ICh0aGUgYXBwJ3MgY29sZCBzdGFydCksIHRoZW4gXHUyMDE0IG9uIGFcbiAgICogICAgc2VwYXJhdGUsIHRpZ2h0ZXIgYnVkZ2V0IFx1MjAxNCBmb3IgYGFwcC53b3Jrc3BhY2UubGF5b3V0UmVhZHlgXG4gICAqXG4gICAqIEV4aXN0aW5nIHZhdWx0IHJlZ2lzdHJhdGlvbnMgaW4gbG9jYWxTdG9yYWdlIGFyZSBwcmVzZXJ2ZWQgKGFwcGVuZCwgbm90XG4gICAqIG92ZXJ3cml0ZSkgXHUyMDE0IGV4Y2VwdCB0aGUgKipoYXJuZXNzJ3Mgb3duKiogYHRlbXAtdmF1bHQtKmAgcmVnaXN0cmF0aW9ucyBmcm9tXG4gICAqIGVhcmxpZXIgcnVucywgd2hpY2ggYXJlIHBydW5lZCB3aGVuIHtAbGluayBBcHBpdW1UcmFuc3BvcnRDb25maWcuc2hvdWxkU3dlZXBMZWZ0b3ZlcnN9XG4gICAqIGlzIG9uLiBUaGVpciBkaXJlY3RvcmllcyBhcmUgYWxyZWFkeSBnb25lICh0aGUgZmFjdG9yeSBzd2VlcHMgdGhlbSBiZWZvcmVcbiAgICogdGhlIGFwcCBsYXVuY2hlcyksIGFuZCBpdCBpcyB0aGlzIHJlZ2lzdHJ5IFx1MjAxNCBub3QgdGhlIGZpbGVzeXN0ZW0gXHUyMDE0IHRoYXRcbiAgICogT2JzaWRpYW4gZW51bWVyYXRlcyBhdCBzdGFydHVwLCBzbyBsZWF2aW5nIHRoZW0gaXMgd2hhdCBtYWtlcyBlYWNoIGZhaWxlZFxuICAgKiBydW4gc2xvdyB0aGUgbmV4dCBvbmUgZG93bi5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIFRoZSBhYnNvbHV0ZSBwYXRoIHRvIHRoZSB2YXVsdCBvbiB0aGUgaG9zdCBtYWNoaW5lLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyVmF1bHQodmF1bHRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBSZWdpc3RlcmluZyB2YXVsdDogJHt2YXVsdFBhdGh9YCk7XG4gICAgY29uc3QgZGV2aWNlVmF1bHRQYXRoID0gdGhpcy5nZXREZXZpY2VWYXVsdFBhdGgodmF1bHRQYXRoKTtcblxuICAgIC8vIFB1c2ggYSBtaW5pbWFsIC5vYnNpZGlhbiBkaXJlY3Rvcnkgc28gT2JzaWRpYW4gcmVjb2duaXplcyBpdCBhcyBhIHZhdWx0LlxuICAgIGF3YWl0IHRoaXMucHVzaE9ic2lkaWFuTWFya2VyKGRldmljZVZhdWx0UGF0aCk7XG5cbiAgICAvLyBTd2l0Y2ggdG8gV2ViVmlldyBhbmQgY29uZmlndXJlIGxvY2FsU3RvcmFnZS5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVdlYlZpZXdDb250ZXh0KCk7XG5cbiAgICAvLyBJbnZhbGlkYXRlIGJlZm9yZSByZWxvYWQgXHUyMDE0IHRoZSBwYWdlIHdpbGwgbmF2aWdhdGUgYW5kIHRoZSBXZWJWaWV3XG4gICAgLy8gQ29udGV4dCBtYXkgYmUgdGVtcG9yYXJpbHkgdW5hdmFpbGFibGUgZHVyaW5nIHJlbG9hZC5cbiAgICB0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCA9IGZhbHNlO1xuXG4gICAgY29uc3Qgc3RhbGVQcmVmaXggPSB0aGlzLnNob3VsZFN3ZWVwTGVmdG92ZXJzID8gYCR7dGhpcy52YXVsdEJhc2VQYXRofSR7VEVNUF9WQVVMVF9ESVJfUFJFRklYfWAgOiAnJztcblxuICAgIGF3YWl0IHRoaXMuYnJvd3Nlci5leGVjdXRlKFxuICAgICAgKHBhdGg6IHN0cmluZywgcHJ1bmVQcmVmaXg6IHN0cmluZykgPT4ge1xuICAgICAgICBsZXQgZXhpc3RpbmcgPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzJykgPz8gJ1tdJykgYXMgc3RyaW5nW107XG5cbiAgICAgICAgaWYgKHBydW5lUHJlZml4KSB7XG4gICAgICAgICAgY29uc3Qgc3RhbGUgPSBleGlzdGluZy5maWx0ZXIoKHJlZ2lzdGVyZWQpID0+IHJlZ2lzdGVyZWQgIT09IHBhdGggJiYgcmVnaXN0ZXJlZC5zdGFydHNXaXRoKHBydW5lUHJlZml4KSk7XG4gICAgICAgICAgZm9yIChjb25zdCByZWdpc3RlcmVkIG9mIHN0YWxlKSB7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShgZW5hYmxlLXBsdWdpbi0ke3JlZ2lzdGVyZWR9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGV4aXN0aW5nID0gZXhpc3RpbmcuZmlsdGVyKChyZWdpc3RlcmVkKSA9PiAhc3RhbGUuaW5jbHVkZXMocmVnaXN0ZXJlZCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFleGlzdGluZy5pbmNsdWRlcyhwYXRoKSkge1xuICAgICAgICAgIGV4aXN0aW5nLnB1c2gocGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ21vYmlsZS1leHRlcm5hbC12YXVsdHMnLCBKU09OLnN0cmluZ2lmeShleGlzdGluZykpO1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnbW9iaWxlLXNlbGVjdGVkLXZhdWx0JywgcGF0aCk7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGBlbmFibGUtcGx1Z2luLSR7cGF0aH1gLCAndHJ1ZScpO1xuICAgICAgICBsb2NhdGlvbi5yZWxvYWQoKTtcbiAgICAgIH0sXG4gICAgICBkZXZpY2VWYXVsdFBhdGgsXG4gICAgICBzdGFsZVByZWZpeFxuICAgICk7XG5cbiAgICAvLyBXYWl0IGZvciByZWxvYWQgKyB2YXVsdCBpbml0aWFsaXphdGlvbiwgYXMgdHdvIHNlcGFyYXRlbHkgYnVkZ2V0ZWQgcGhhc2VzOlxuICAgIC8vIFRoZSBhcHAncyBjb2xkIHN0YXJ0IGZpcnN0LCB0aGVuIE9ic2lkaWFuJ3Mgb3duIHdvcmsuIFNlZSBgd2FpdEZvckFwcFN0YXJ0ZWRgLlxuICAgIGF3YWl0IHRoaXMud2FpdEZvckFwcFN0YXJ0ZWQoKTtcbiAgICBhd2FpdCB0aGlzLndhaXRGb3JMYXlvdXRSZWFkeSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucmVnaXN0ZXJzIGEgdmF1bHQgb24gbW9iaWxlIGJ5IHJlbW92aW5nIGl0IGZyb20gbG9jYWxTdG9yYWdlLlxuICAgKlxuICAgKiBQcmVzZXJ2ZXMgb3RoZXIgdmF1bHQgcmVnaXN0cmF0aW9ucy4gSWYgdGhlIHVucmVnaXN0ZXJlZCB2YXVsdCB3YXMgc2VsZWN0ZWQsXG4gICAqIHN3aXRjaGVzIHRvIHRoZSBmaXJzdCByZW1haW5pbmcgdmF1bHQgKG9yIGNsZWFycyB0aGUgc2VsZWN0aW9uKS5cbiAgICpcbiAgICogVGhlIHZhdWx0J3MgKipmaWxlcyBhcmUgdGhlbiByZW1vdmVkIGZyb20gdGhlIGRldmljZSBvdmVyIGBhZGJgLCB3aGV0aGVyIG9yXG4gICAqIG5vdCB0aGUgYGxvY2FsU3RvcmFnZWAgc3RlcCBzdWNjZWVkZWQqKiBcdTIwMTQgZGVsaWJlcmF0ZWx5LCBiZWNhdXNlIHRoZVxuICAgKiBgbG9jYWxTdG9yYWdlYCBzdGVwIGdvZXMgdGhyb3VnaCB0aGUgV2ViVmlldyBhbmQgYSBkZWFkIFdlYlZpZXcgaXMgZXhhY3RseVxuICAgKiB3aGF0IG1vc3QgQW5kcm9pZCBmYWlsdXJlcyBhcmUuIFJvdXRpbmcgdGhlIHJlbW92YWwgdGhyb3VnaCB0aGUgYXBwIHdhcyB3aGF0XG4gICAqIG1hZGUgZXZlcnkgZmFpbGVkIHJ1biBsZWFrIGl0cyB2YXVsdCAoYFZhdWx0IGNsZWFudXAgZXJyb3IgKG5vbi1mYXRhbCk6IG5vXG4gICAqIHN1Y2ggd2luZG93YCksIHNvIHRoZSBmaWxlc3lzdGVtLWxldmVsIHJlbW92YWwgbXVzdCBub3QgZGVwZW5kIG9uIGl0LlxuICAgKlxuICAgKiBAcGFyYW0gdmF1bHRQYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIHZhdWx0IG9uIHRoZSBob3N0IG1hY2hpbmUuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdW5yZWdpc3RlclZhdWx0KHZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZGV2aWNlVmF1bHRQYXRoID0gdGhpcy5nZXREZXZpY2VWYXVsdFBhdGgodmF1bHRQYXRoKTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZVdlYlZpZXdDb250ZXh0KCk7XG5cbiAgICAgIGF3YWl0IHRoaXMuYnJvd3Nlci5leGVjdXRlKChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdtb2JpbGUtZXh0ZXJuYWwtdmF1bHRzJykgPz8gJ1tdJykgYXMgc3RyaW5nW107XG4gICAgICAgIGNvbnN0IGZpbHRlcmVkID0gZXhpc3RpbmcuZmlsdGVyKCh2KSA9PiB2ICE9PSBwYXRoKTtcbiAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ21vYmlsZS1leHRlcm5hbC12YXVsdHMnLCBKU09OLnN0cmluZ2lmeShmaWx0ZXJlZCkpO1xuICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShgZW5hYmxlLXBsdWdpbi0ke3BhdGh9YCk7XG4gICAgICAgIGlmIChsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnbW9iaWxlLXNlbGVjdGVkLXZhdWx0JykgPT09IHBhdGgpIHtcbiAgICAgICAgICBpZiAoZmlsdGVyZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ21vYmlsZS1zZWxlY3RlZC12YXVsdCcsIGZpbHRlcmVkWzBdID8/ICcnKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oJ21vYmlsZS1zZWxlY3RlZC12YXVsdCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgZGV2aWNlVmF1bHRQYXRoKTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgbG9nKFxuICAgICAgICBgW2FwcGl1bS10cmFuc3BvcnRdIENvdWxkIG5vdCBkZXJlZ2lzdGVyICR7ZGV2aWNlVmF1bHRQYXRofSBmcm9tIGxvY2FsU3RvcmFnZSBgXG4gICAgICAgICAgKyBgKCR7U3RyaW5nKGVycm9yKX0pOyByZW1vdmluZyBpdHMgZmlsZXMgYW55d2F5LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5yZW1vdmVEZXZpY2VWYXVsdERpcmVjdG9yeShkZXZpY2VWYXVsdFBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyB0aGUgdHJ1c3RlZC1pbnB1dCBjaGFubmVsLCBpZiBvbmUgaXMgb3Blbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZGlzcG9zZUlucHV0Q2hhbm5lbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjaGFubmVsID0gdGhpcy5pbnB1dENoYW5uZWw7XG4gICAgdGhpcy5pbnB1dENoYW5uZWwgPSBudWxsO1xuICAgIHRoaXMudW5yZWdpc3RlcklucHV0Q2hhbm5lbEV4aXRIYW5kbGVyKCk7XG4gICAgYXdhaXQgY2hhbm5lbD8uZGlzcG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wZW5zIHRoZSB0cnVzdGVkLWlucHV0IGNoYW5uZWwgaWYgaXQgaXMgbm90IGFscmVhZHkgb3BlbiwgYW5kIHJlLW9wZW5zIGl0IGlmIHRoZSBXZWJWaWV3IHdlbnQgYXdheS5cbiAgICpcbiAgICogSW5zdGFsbHMgYSBgUnVudGltZS5hZGRCaW5kaW5nYCBmdW5jdGlvbiBvbiB0aGUgcGFnZSBhbmQgc2VydmljZXMgZXZlcnkgY2FsbCB0byBpdCBmb3IgdGhlIGxpZmUgb2YgdGhlXG4gICAqIGNvbm5lY3Rpb24uIFRoZSBiaW5kaW5nIGlzIGV4cG9zZWQgb24gKmV2ZXJ5KiBleGVjdXRpb24gY29udGV4dCBvZiB0aGUgcGFnZSwgc28gaXQgc3Vydml2ZXMgdGhlXG4gICAqIGBsb2NhdGlvbi5yZWxvYWQoKWAgdGhhdCB7QGxpbmsgQXBwaXVtVHJhbnNwb3J0LnJlZ2lzdGVyVmF1bHR9IHBlcmZvcm1zOyBvbmx5IGEgZnVsbCBhcHAgcmVzdGFydCwgd2hpY2hcbiAgICogZGVzdHJveXMgdGhlIFdlYlZpZXcgdGFyZ2V0LCBuZWVkcyB0aGUgcmVjb25uZWN0IGJlbG93LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVJbnB1dENoYW5uZWwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuaW5wdXRDaGFubmVsPy5pc09wZW4gfHwgdGhpcy5pc0lucHV0Q2hhbm5lbFVuYXZhaWxhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGhlIGNoYW5uZWwgaXMgcmVhY2hhYmxlIG9ubHkgb3ZlciBsb2NhbCBgYWRiYCwgc28gaXQgZG9lcyBub3QgZXhpc3Qgb24gaU9TIG9yIGFnYWluc3QgYSByZW1vdGUgaHViXG4gICAgLy8gKEJyb3dzZXJTdGFjaykuIFRob3NlIGFyZSBzdXBwb3J0ZWQgdHJhbnNwb3J0cywgc28gdGhpcyBzdGF5cyAqKmJlc3QtZWZmb3J0Kio6IGEgcnVuIHRoYXQgbmV2ZXJcbiAgICAvLyBEcml2ZXMgaW5wdXQgbXVzdCBub3QgZmFpbCBiZWNhdXNlIHRoZSBjaGFubmVsIGNvdWxkIG5vdCBiZSBvcGVuZWQuIEEgcnVuIHRoYXQgKmRvZXMqIGRyaXZlIGlucHV0XG4gICAgLy8gR2V0cyBhIGxlZ2libGUgZXJyb3IgZnJvbSB0aGUgcmVuZGVyZXIncyBvd24gZ3VhcmQsIHdoaWNoIG5hbWVzIHRoZSBtaXNzaW5nIGNoYW5uZWwuXG4gICAgaWYgKHRoaXMucGxhdGZvcm0gIT09ICdhbmRyb2lkJykge1xuICAgICAgdGhpcy5pc0lucHV0Q2hhbm5lbFVuYXZhaWxhYmxlID0gdHJ1ZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmRpc3Bvc2VJbnB1dENoYW5uZWwoKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb25uZWN0aW9uID0gYXdhaXQgY29ubmVjdFRvV2ViVmlld0NkcCh7IGFwcElkOiB0aGlzLmFwcElkLCBkZXZpY2VJZDogdGhpcy5kZXZpY2VJZCB9KTtcbiAgICAgIGF3YWl0IGNvbm5lY3Rpb24uc2VuZCgnUnVudGltZS5lbmFibGUnKTtcbiAgICAgIGF3YWl0IGNvbm5lY3Rpb24uc2VuZCgnUnVudGltZS5hZGRCaW5kaW5nJywgeyBuYW1lOiBNT0JJTEVfSU5QVVRfQklORElOR19OQU1FIH0pO1xuICAgICAgY29ubmVjdGlvbi5vbignUnVudGltZS5iaW5kaW5nQ2FsbGVkJywgKHBhcmFtczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgICAgaWYgKHBhcmFtc1snbmFtZSddICE9PSBNT0JJTEVfSU5QVVRfQklORElOR19OQU1FKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHBhcmFtc1sncGF5bG9hZCddO1xuICAgICAgICAvLyBEZWxpYmVyYXRlbHkgbm90IGF3YWl0ZWQ6IHRoaXMgcnVucyB3aGlsZSB0aGUgcmVuZGVyZXIncyBgRXhlY3V0ZSBTY3JpcHRgIGlzIHN0aWxsIHBlbmRpbmcsIGFuZFxuICAgICAgICAvLyBUaGF0IGlzIHRoZSB3aG9sZSBwb2ludCBcdTIwMTQgdGhlIHJlcXVlc3QgaXMgc2VydmljZWQgY29uY3VycmVudGx5IGFuZCBhbnN3ZXJlZCBieSByZXNvbHZpbmcgdGhlXG4gICAgICAgIC8vIFJlbmRlcmVyJ3MgcHJvbWlzZSBvdmVyIHRoaXMgc2FtZSBzb2NrZXQuIEl0IGhhbmRsZXMgaXRzIG93biBmYWlsdXJlcywgc28gbm90aGluZyByZWFjaGVzIGhlcmUuXG4gICAgICAgIHRoaXMuaGFuZGxlSW5wdXRSZXF1ZXN0KGNvbm5lY3Rpb24sIHR5cGVvZiBwYXlsb2FkID09PSAnc3RyaW5nJyA/IHBheWxvYWQgOiAnJykuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIFVucmVhY2hhYmxlOiBgaGFuZGxlSW5wdXRSZXF1ZXN0YCBuZXZlciByZWplY3RzLlxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmlucHV0Q2hhbm5lbCA9IGNvbm5lY3Rpb247XG5cbiAgICAgIC8vIFNlbGYtY2xlYW5pbmcsIGRlbGliZXJhdGVseTogdGhpcyB0cmFuc3BvcnQgY2FuIGJlIGNyZWF0ZWQgc3RyYWlnaHQgZnJvbSBhIHRlc3Qgd29ya2VyLCB3aXRoIG5vXG4gICAgICAvLyBgY29yZVNldHVwYCBvd25pbmcgaXRzIGxpZmVjeWNsZSBhbmQgdGhlcmVmb3JlIG5vdGhpbmcgdGhhdCBldmVyIGNhbGxzIGBkaXNwb3NlYC9gZGlzcG9zZVN5bmNgIFx1MjAxNFxuICAgICAgLy8gV2hpY2ggaXMgaG93IGEgcnVuIGxlYXZlcyBpdHMgYWRiIHBvcnQgZm9yd2FyZCBzdHJhbmRlZCBvbiB0aGUgZGV2aWNlIChvYnNlcnZlZCAyMDI2LTA4LTMwKS4gVGhlXG4gICAgICAvLyBIYW5kbGVyIGlzIHJlbW92ZWQgYWdhaW4gb24gZGlzcG9zYWwgc28gcmVjb25uZWN0cyBkbyBub3Qgc3RhY2sgbGlzdGVuZXJzLlxuICAgICAgdGhpcy5kaXNwb3NlSW5wdXRDaGFubmVsT25FeGl0ID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25uZWN0aW9uLmRpc3Bvc2VTeW5jKCk7XG4gICAgICB9O1xuICAgICAgcHJvY2Vzcy5vbmNlKCdleGl0JywgdGhpcy5kaXNwb3NlSW5wdXRDaGFubmVsT25FeGl0KTtcblxuICAgICAgbG9nKCdbYXBwaXVtLXRyYW5zcG9ydF0gVHJ1c3RlZC1pbnB1dCBjaGFubmVsIG9wZW4uJyk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIC8vIEdpdmUgdXAgZm9yIHRoZSBsaWZlIG9mIHRoZSB0cmFuc3BvcnQgcmF0aGVyIHRoYW4gcGF5aW5nIGFuIGBhZGJgIHJvdW5kLXRyaXAgb24gZXZlcnkgZXZhbC5cbiAgICAgIC8vIEEgc29ja2V0IHRoYXQgbWVyZWx5ICpjbG9zZWQqIGFmdGVyIGEgc3VjY2Vzc2Z1bCBjb25uZWN0IGlzIGEgZGlmZmVyZW50IGNhc2UgXHUyMDE0IGBpc09wZW5gIGlzIGZhbHNlXG4gICAgICAvLyBUaGVyZSB3aGlsZSB0aGlzIGZsYWcgc3RheXMgdW5zZXQsIHNvIHRoZSByZWNvbm5lY3QgYWJvdmUgc3RpbGwgcnVucy5cbiAgICAgIHRoaXMuaXNJbnB1dENoYW5uZWxVbmF2YWlsYWJsZSA9IHRydWU7XG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBUcnVzdGVkIGlucHV0IGlzIHVuYXZhaWxhYmxlIG9uIHRoaXMgZGV2aWNlOiAke2Vycm9yVG9TdHJpbmcoZXJyb3IpfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTd2l0Y2hlcyB0aGUgZHJpdmVyIHRvIHRoZSBgV0VCVklFV19tZC5vYnNpZGlhbmAgY29udGV4dC5cbiAgICpcbiAgICogSWYgdGhlIGNvbnRleHQgd2FzIGFscmVhZHkgdmVyaWZpZWQgKGNhY2hlZCB2aWEge0BsaW5rIGlzSW5XZWJWaWV3Q29udGV4dH0pLFxuICAgKiByZXR1cm5zIGltbWVkaWF0ZWx5IHdpdGhvdXQgY2FsbGluZyBgZ2V0Q29udGV4dHMoKWAgXHUyMDE0IHdoaWNoIHJ1bnNcbiAgICogYGFkYiBzaGVsbCBjYXQgL3Byb2MvbmV0L3VuaXhgIGFuZCBjYW4gdGltZSBvdXQgb24gc2xvdyBlbXVsYXRvcnMuXG4gICAqXG4gICAqIFBvbGxzIHVudGlsIHRoZSBjb250ZXh0IGJlY29tZXMgYXZhaWxhYmxlICh0aGUgYXBwIG1heSBzdGlsbCBiZSBsb2FkaW5nKS5cbiAgICogVXNlcyB0aGUgYFdFQlZJRVdfbWQub2JzaWRpYW5gIGNvbnRleHQgc3BlY2lmaWNhbGx5IHRvIGF2b2lkIGNvbm5lY3RpbmdcbiAgICogdG8gQ2hyb21lIG9yIG90aGVyIFdlYlZpZXdzIG9uIHRoZSBkZXZpY2UuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZVdlYlZpZXdDb250ZXh0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIHRoaXMud2Vidmlld1RpbWVvdXRJbk1pbGxpc2Vjb25kcztcbiAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBXYWl0aW5nIGZvciAke1dFQlZJRVdfQ09OVEVYVF9QUkVGSVh9IGNvbnRleHQgKHRpbWVvdXQ9JHtTdHJpbmcodGhpcy53ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzKX1tcykuLi5gKTtcblxuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGNvbnN0IGNvbnRleHRzID0gYXdhaXQgdGhpcy5icm93c2VyLmdldENvbnRleHRzKCk7XG4gICAgICBjb25zdCBvYnNpZGlhbkNvbnRleHQgPSBjb250ZXh0cy5maW5kKChjb250ZXh0KTogY29udGV4dCBpcyBzdHJpbmcgPT4gdHlwZW9mIGNvbnRleHQgPT09ICdzdHJpbmcnICYmIGNvbnRleHQuc3RhcnRzV2l0aChXRUJWSUVXX0NPTlRFWFRfUFJFRklYKSk7XG5cbiAgICAgIGlmIChvYnNpZGlhbkNvbnRleHQpIHtcbiAgICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gRm91bmQgV2ViVmlldyBjb250ZXh0OiAke29ic2lkaWFuQ29udGV4dH1gKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmJyb3dzZXIuc3dpdGNoQ29udGV4dChvYnNpZGlhbkNvbnRleHQpO1xuICAgICAgICAgIHRoaXMuaXNJbldlYlZpZXdDb250ZXh0ID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgbG9nKGBbYXBwaXVtLXRyYW5zcG9ydF0gc3dpdGNoQ29udGV4dCBmYWlsZWQ6ICR7U3RyaW5nKGVycm9yKX0uIFJlc2V0dGluZyB0byBOQVRJVkVfQVBQIGJlZm9yZSByZXRyeWluZy4uLmApO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmJyb3dzZXIuc3dpdGNoQ29udGV4dCgnTkFUSVZFX0FQUCcpO1xuICAgICAgICAgIH0gY2F0Y2ggKHJlc2V0RXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIE5BVElWRV9BUFAgcmVzZXQgYWxzbyBmYWlsZWQ6ICR7U3RyaW5nKHJlc2V0RXJyb3IpfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBXZWJWaWV3IG5vdCByZWFkeSwgYXZhaWxhYmxlIGNvbnRleHRzOiAke0pTT04uc3RyaW5naWZ5KGNvbnRleHRzKX0uIFJldHJ5aW5nLi4uYCk7XG4gICAgICBhd2FpdCBkZWxheShXRUJWSUVXX1BPTExfSU5URVJWQUxfSU5fTUlMTElTRUNPTkRTKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vICR7V0VCVklFV19DT05URVhUX1BSRUZJWH0gY29udGV4dCBmb3VuZCB3aXRoaW4gJHtTdHJpbmcodGhpcy53ZWJ2aWV3VGltZW91dEluTWlsbGlzZWNvbmRzKX1tcy4gSXMgdGhlIE9ic2lkaWFuIGFwcCBmdWxseSBsb2FkZWQ/YCk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBob3N0LXNpZGUgdmF1bHQgcGF0aCB0byB0aGUgZGV2aWNlLXNpZGUgcGF0aC5cbiAgICpcbiAgICogQHBhcmFtIHZhdWx0UGF0aCAtIEFic29sdXRlIHBhdGggb24gdGhlIGhvc3QgbWFjaGluZS5cbiAgICogQHJldHVybnMgVGhlIGRldmljZS1zaWRlIHZhdWx0IHBhdGguXG4gICAqL1xuICBwcml2YXRlIGdldERldmljZVZhdWx0UGF0aCh2YXVsdFBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMudmF1bHRCYXNlUGF0aH0ke2V4dHJhY3RWYXVsdE5hbWUodmF1bHRQYXRoKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlcnZpY2VzIG9uZSBpbnB1dCByZXF1ZXN0IGZyb20gdGhlIHJlbmRlcmVyOiBpbmplY3QsIHRoZW4gcmVzb2x2ZSB0aGUgcmVuZGVyZXIncyBwcm9taXNlLlxuICAgKlxuICAgKiBFdmVyeSBmYWlsdXJlIHBhdGggc3RpbGwgcmVzb2x2ZXMgdGhhdCBwcm9taXNlIFx1MjAxNCB3aXRoIGFuIGVycm9yIG1lc3NhZ2UgdGhlIHJlbmRlcmVyIHJlLXRocm93cyBcdTIwMTQgYmVjYXVzZVxuICAgKiBhIHJlcXVlc3QgdGhhdCBpcyBzaWxlbnRseSBkcm9wcGVkIHdvdWxkIGhhbmcgdGhlIGNsb3N1cmUgdW50aWwgdGhlIHdob2xlIHJ1biB0aW1lcyBvdXQsIGFuZCByZXBvcnRcbiAgICogbm90aGluZyBhYm91dCB3aHkuXG4gICAqXG4gICAqIEBwYXJhbSBjb25uZWN0aW9uIC0gVGhlIGNoYW5uZWwgdGhlIHJlcXVlc3QgYXJyaXZlZCBvbi5cbiAgICogQHBhcmFtIHBheWxvYWQgLSBUaGUgcmF3IEpTT04gcGF5bG9hZCB0aGUgYmluZGluZyB3YXMgY2FsbGVkIHdpdGguXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGhhbmRsZUlucHV0UmVxdWVzdChjb25uZWN0aW9uOiBXZWJWaWV3Q2RwQ29ubmVjdGlvbiwgcGF5bG9hZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IHJlcXVlc3RJZCA9ICcnO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGlkLCByZXF1ZXN0IH0gPSBKU09OLnBhcnNlKHBheWxvYWQpIGFzIE1vYmlsZUlucHV0RW52ZWxvcGU7XG4gICAgICByZXF1ZXN0SWQgPSBpZDtcbiAgICAgIGF3YWl0IGNvbm5lY3Rpb24uc2VuZEFsbCh0b0NkcElucHV0Q29tbWFuZHMocmVxdWVzdCkpO1xuICAgICAgYXdhaXQgY29ubmVjdGlvbi5zZW5kKCdSdW50aW1lLmV2YWx1YXRlJywgeyBleHByZXNzaW9uOiBidWlsZFJlc29sdmVJbnB1dEV4cHJlc3Npb24oaWQpIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3JUb1N0cmluZyhlcnJvcik7XG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBUcnVzdGVkIGlucHV0IGZhaWxlZDogJHttZXNzYWdlfWApO1xuICAgICAgaWYgKCFyZXF1ZXN0SWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBjb25uZWN0aW9uLnNlbmQoJ1J1bnRpbWUuZXZhbHVhdGUnLCB7IGV4cHJlc3Npb246IGJ1aWxkUmVzb2x2ZUlucHV0RXhwcmVzc2lvbihyZXF1ZXN0SWQsIG1lc3NhZ2UpIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFRoZSBzb2NrZXQgaXMgZ29uZTsgdGhlIHJlbmRlcmVyJ3Mgb3duIHRpbWVvdXQgaXMgdGhlIHJlbWFpbmluZyBiYWNrc3RvcC5cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJvYmVzIHRoZSBXZWJWaWV3IG9uY2UgZm9yIGhvdyBmYXIgT2JzaWRpYW4ncyBzdGFydHVwIGhhcyBnb3QuXG4gICAqXG4gICAqIEEgcHJvYmUgdGhhdCB0aHJvd3MgaXMgcmVwb3J0ZWQgYXMgYHVuZGVmaW5lZGAgcmF0aGVyIHRoYW4gcHJvcGFnYXRlZDogdGhlXG4gICAqIHBhZ2UgaXMgbWlkLWBsb2NhdGlvbi5yZWxvYWQoKWAgZm9yIG1vc3Qgb2YgdGhlIGFwcC1zdGFydCBwaGFzZSwgYW5kIGFcbiAgICogV2ViVmlldyB0aGF0IGNhbm5vdCBhbnN3ZXIgeWV0IGlzIHRoZSAqZXhwZWN0ZWQqIHJlYWRpbmcgdGhlcmUsIG5vdCBhbiBlcnJvci5cbiAgICpcbiAgICogQHJldHVybnMgV2hhdCB0aGUgcHJvYmUgc2F3LCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGNvdWxkIG5vdCBydW4uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByb2JlU3RhcnR1cCgpOiBQcm9taXNlPFN0YXJ0dXBQcm9iZVJlc3VsdCB8IHVuZGVmaW5lZD4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5icm93c2VyLmV4ZWN1dGUoKCk6IFN0YXJ0dXBQcm9iZVJlc3VsdCA9PiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZGVwcmVjYXRlZCAtLSBXZSBuZWVkIGdsb2JhbCBgYXBwYCB2YXJpYWJsZS5cbiAgICAgICAgY29uc3QgYXBwID0gZ2xvYmFsVGhpcy5hcHAgYXMgTG9hZGluZ0FwcCB8IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBoYXNBcHA6ICEhYXBwLFxuICAgICAgICAgIGhhc1dvcmtzcGFjZTogISFhcHA/LndvcmtzcGFjZSxcbiAgICAgICAgICBpc0xheW91dFJlYWR5OiAhIWFwcD8ud29ya3NwYWNlPy5sYXlvdXRSZWFkeVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQdXNoZXMgdGhlIG1pbmltYWwgYC5vYnNpZGlhbi9hcHAuanNvbmAgdmF1bHQgbWFya2VyIHZpYSBgYWRiIHB1c2hgLlxuICAgKlxuICAgKiBgYnJvd3Nlci5wdXNoRmlsZWAgKFdlYkRyaXZlciBiYXNlNjQpIGlzIGFuIG9yZGVyIG9mIG1hZ25pdHVkZSBzbG93ZXIgb24gYVxuICAgKiBjb2xkIG9yIGxvYWRlZCBlbXVsYXRvciBcdTIwMTQgbWVhc3VyZWQgYXQgOVx1MjAxMzIxcyBwZXIgY2FsbCBmb3IgdGhpcyAyLWJ5dGUgbWFya2VyLFxuICAgKiB2ZXJzdXMgc3ViLXNlY29uZCBvdmVyIGBhZGJgLiBUaGlzIG1pcnJvcnMge0BsaW5rIHB1c2hGaWxlc30sIHdoaWNoIHN3aXRjaGVkXG4gICAqIHRvIGBhZGJgIGZvciB0aGUgc2FtZSByZWFzb24uIGBta2RpciAtcGAgZ3VhcmFudGVlcyB0aGUgcGFyZW50IGRpcmVjdG9yeS5cbiAgICpcbiAgICogQHBhcmFtIGRldmljZVZhdWx0UGF0aCAtIFRoZSBkZXZpY2Utc2lkZSB2YXVsdCBkaXJlY3RvcnkgcGF0aC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcHVzaE9ic2lkaWFuTWFya2VyKGRldmljZVZhdWx0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbG9jYWxNYXJrZXIgPSBqb2luKHRtcGRpcigpLCBgb2JzaWRpYW4tbWFya2VyLSR7cmFuZG9tVVVJRCgpfS5qc29uYCk7XG4gICAgY29uc3QgcmVtb3RlTWFya2VyID0gYCR7ZGV2aWNlVmF1bHRQYXRofS8ub2JzaWRpYW4vYXBwLmpzb25gO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHdyaXRlRmlsZShsb2NhbE1hcmtlciwgJ3t9JywgJ3V0Zi04Jyk7XG4gICAgICBhd2FpdCBleGVjKFsnYWRiJywgJy1zJywgdGhpcy5kZXZpY2VJZCwgJ3NoZWxsJywgJ21rZGlyJywgJy1wJywgYCR7ZGV2aWNlVmF1bHRQYXRofS8ub2JzaWRpYW5gXSwgeyBpc1F1aWV0OiB0cnVlIH0pO1xuICAgICAgYXdhaXQgZXhlYyhbJ2FkYicsICctcycsIHRoaXMuZGV2aWNlSWQsICdwdXNoJywgbG9jYWxNYXJrZXIsIHJlbW90ZU1hcmtlcl0sIHsgaXNRdWlldDogdHJ1ZSB9KTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgcm0obG9jYWxNYXJrZXIsIHsgZm9yY2U6IHRydWUgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSB2YXVsdCBkaXJlY3RvcnkgZnJvbSB0aGUgZGV2aWNlIG92ZXIgYGFkYmAsIGFuZCBDSEVDS1MgdGhhdCBpdCBpc1xuICAgKiBhY3R1YWxseSBnb25lLlxuICAgKlxuICAgKiBCZXN0LWVmZm9ydDogYSBmYWlsdXJlIGlzIGxvZ2dlZCwgbm90IHRocm93biwgc28gYSB0ZWFyZG93biBwcm9ibGVtIG5ldmVyXG4gICAqIG1hc2tzIHRoZSB0ZXN0IHJlc3VsdC4gVGhlIG5leHQgcnVuJ3Mgc3RhcnQtb2YtcnVuIHN3ZWVwIHBpY2tzIHVwIHdoYXRldmVyXG4gICAqIHRoaXMgY291bGQgbm90IHJlbW92ZS5cbiAgICpcbiAgICogVGhlIGNoZWNrIGlzIHRoZSBwb2ludC4gYHJtIC1yZmAgcnVucyB3aXRoIGBzaG91bGRJZ25vcmVFeGl0Q29kZWAsIHNvIGFuXG4gICAqIHVucmVtb3ZlZCBkaXJlY3RvcnkgdXNlZCB0byBsZWF2ZSBubyB0cmFjZSBhdCBhbGwgXHUyMDE0IHdoaWNoIGlzIGhvdyBydW5zIHRoYXRcbiAgICogcGFzc2VkIGVuZCB0byBlbmQgd2VyZSBzdGlsbCBmb3VuZCB0byBiZSBsZWFraW5nIGEgdmF1bHQgYXBpZWNlLCBpbnZpc2libHksXG4gICAqIHVudGlsIHNvbWVvbmUgY291bnRlZCB0aGUgZGlyZWN0b3JpZXMgb24gdGhlIGRldmljZSBieSBoYW5kLiBBIGxlYWsgaXMgbm93XG4gICAqIG5hbWVkIGluIHRoZSBsb2cgYXQgdGhlIG1vbWVudCBpdCBoYXBwZW5zLlxuICAgKlxuICAgKiBAcGFyYW0gZGV2aWNlVmF1bHRQYXRoIC0gVGhlIGRldmljZS1zaWRlIHZhdWx0IGRpcmVjdG9yeSBwYXRoLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZW1vdmVEZXZpY2VWYXVsdERpcmVjdG9yeShkZXZpY2VWYXVsdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBSZW1vdmluZyB2YXVsdCBkaXJlY3RvcnkgZnJvbSBkZXZpY2U6ICR7ZGV2aWNlVmF1bHRQYXRofWApO1xuICAgICAgYXdhaXQgZXhlYyhcbiAgICAgICAgWydhZGInLCAnLXMnLCB0aGlzLmRldmljZUlkLCAnc2hlbGwnLCAncm0nLCAnLXJmJywgZGV2aWNlVmF1bHRQYXRoXSxcbiAgICAgICAgeyBpc1F1aWV0OiB0cnVlLCBzaG91bGRJZ25vcmVFeGl0Q29kZTogdHJ1ZSwgdGltZW91dEluTWlsbGlzZWNvbmRzOiBBREJfVkFVTFRfUkVNT1ZFX1RJTUVPVVRfSU5fTUlMTElTRUNPTkRTIH1cbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGxpc3RpbmcgPSBhd2FpdCBleGVjKFxuICAgICAgICBbJ2FkYicsICctcycsIHRoaXMuZGV2aWNlSWQsICdzaGVsbCcsICdscycsICctZCcsIGRldmljZVZhdWx0UGF0aF0sXG4gICAgICAgIHsgaXNRdWlldDogdHJ1ZSwgc2hvdWxkSWdub3JlRXhpdENvZGU6IHRydWUsIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogQURCX1ZBVUxUX1JFTU9WRV9USU1FT1VUX0lOX01JTExJU0VDT05EUyB9XG4gICAgICApO1xuXG4gICAgICBpZiAobGlzdGluZy5pbmNsdWRlcyhkZXZpY2VWYXVsdFBhdGgpKSB7XG4gICAgICAgIGxvZyhcbiAgICAgICAgICBgW2FwcGl1bS10cmFuc3BvcnRdIFdhcm5pbmc6ICR7ZGV2aWNlVmF1bHRQYXRofSBzdXJ2aXZlZCByZW1vdmFsIGFuZCBpcyBub3cgbGVha2VkIHJlc2lkdWUuIGBcbiAgICAgICAgICAgICsgJ1RoZSBuZXh0IHJ1blxcJ3Mgc3RhcnQtb2YtcnVuIHN3ZWVwIHdpbGwgcmV0cnkgaXQuJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBWYXVsdCBkaXJlY3RvcnkgcmVtb3ZhbCBmYWlsZWQgKG5vbi1mYXRhbCk6ICR7U3RyaW5nKGVycm9yKX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRHJvcHMgdGhlIGBwcm9jZXNzLm9uKCdleGl0JylgIGhhbmRsZXIgdGhhdCB3b3VsZCBvdGhlcndpc2UgY2xvc2UgYW4gYWxyZWFkeS1jbG9zZWQgY2hhbm5lbCwgYW5kIHdvdWxkXG4gICAqIHN0YWNrIGEgbGlzdGVuZXIgcGVyIHJlY29ubmVjdC5cbiAgICovXG4gIHByaXZhdGUgdW5yZWdpc3RlcklucHV0Q2hhbm5lbEV4aXRIYW5kbGVyKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5kaXNwb3NlSW5wdXRDaGFubmVsT25FeGl0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcHJvY2Vzcy5vZmYoJ2V4aXQnLCB0aGlzLmRpc3Bvc2VJbnB1dENoYW5uZWxPbkV4aXQpO1xuICAgIHRoaXMuZGlzcG9zZUlucHV0Q2hhbm5lbE9uRXhpdCA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUG9sbHMgdW50aWwgYGdsb2JhbFRoaXMuYXBwYCBleGlzdHMgaW4gdGhlIFdlYlZpZXcgXHUyMDE0IHRoZSBhcHAgaGFzIGZpbmlzaGVkXG4gICAqIGl0cyBjb2xkIHN0YXJ0IGFuZCBPYnNpZGlhbidzIG93biBib290IGhhcyBiZWd1bi5cbiAgICpcbiAgICogVGhpcyBpcyB0aGUgKipmaXJzdCoqIG9mIHRoZSB0d28gYnVkZ2V0cyBzcGVudCBhZnRlciBgbG9jYXRpb24ucmVsb2FkKClgLFxuICAgKiBhbmQgdGhlIGdlbmVyb3VzIG9uZS4gRXZlcnl0aGluZyBpdCBwYXlzIGZvciBpcyBvdXRzaWRlIE9ic2lkaWFuJ3MgY29udHJvbDpcbiAgICogdGhlIFdlYlZpZXcgcmVsb2FkaW5nLCBhbmQgYSBndWVzdCB0aGF0IG1heSBzdGlsbCBiZSBvcHRpbWl6aW5nIHBhY2thZ2VzLlxuICAgKiBLZWVwaW5nIGl0IHNlcGFyYXRlIGlzIHRoZSBwb2ludCBvZiB0aGUgc3BsaXQgXHUyMDE0IHRoZSBvbGQgc2luZ2xlIHdhbGwgY2xvY2tcbiAgICogc3RhcnRlZCBoZXJlIGFuZCBsZWZ0IHRoZSB0aWdodCBsYXlvdXQgYnVkZ2V0IHBheWluZyBmb3IgYSBjb2xkIHN0YXJ0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB3YWl0Rm9yQXBwU3RhcnRlZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBXYWl0aW5nIGZvciB0aGUgYXBwIHRvIHN0YXJ0ICh0aW1lb3V0PSR7U3RyaW5nKHRoaXMuYXBwU3RhcnRUaW1lb3V0SW5NaWxsaXNlY29uZHMpfW1zKS4uLmApO1xuICAgIGF3YWl0IHRoaXMud2FpdEZvclN0YXJ0dXBNaWxlc3RvbmUoe1xuICAgICAgaXNTYXRpc2ZpZWQ6IGNoZWNrQXBwU3RhcnRlZCxcbiAgICAgIHBoYXNlOiAnYXBwLXN0YXJ0JyxcbiAgICAgIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogdGhpcy5hcHBTdGFydFRpbWVvdXRJbk1pbGxpc2Vjb25kc1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvbGxzIHVudGlsIGBhcHAud29ya3NwYWNlLmxheW91dFJlYWR5YCBpcyBgdHJ1ZWAgaW4gdGhlIFdlYlZpZXcuXG4gICAqXG4gICAqIFRoZSAqKnNlY29uZCoqIGJ1ZGdldCwgYW5kIHRoZSB0aWdodCBvbmU6IGJ5IHRoZSB0aW1lIGl0IHN0YXJ0cywgdGhlIGFwcCBpc1xuICAgKiBhbHJlYWR5IHVwLCBzbyBhbGwgaXQgY292ZXJzIGlzIE9ic2lkaWFuIG9wZW5pbmcgdGhlIHZhdWx0IGFuZCBsb2FkaW5nXG4gICAqIHBsdWdpbnMgXHUyMDE0IH4xcyBpbiBwcmFjdGljZSwgXHUyMjY0OC40cyB1bmRlciBoZWF2eSBob3N0IHN0cmVzcyAoKipMMTkqKikuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdhaXRGb3JMYXlvdXRSZWFkeSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2coYFthcHBpdW0tdHJhbnNwb3J0XSBXYWl0aW5nIGZvciBsYXlvdXQgcmVhZHkgKHRpbWVvdXQ9JHtTdHJpbmcodGhpcy5sYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kcyl9bXMpLi4uYCk7XG4gICAgYXdhaXQgdGhpcy53YWl0Rm9yU3RhcnR1cE1pbGVzdG9uZSh7XG4gICAgICBpc1NhdGlzZmllZDogY2hlY2tMYXlvdXRSZWFkeSxcbiAgICAgIHBoYXNlOiAnbGF5b3V0LXJlYWR5JyxcbiAgICAgIHRpbWVvdXRJbk1pbGxpc2Vjb25kczogdGhpcy5sYXlvdXRSZWFkeVRpbWVvdXRJbk1pbGxpc2Vjb25kc1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvbGxzIHRoZSBXZWJWaWV3IHVudGlsIGEgc3RhcnR1cCBwaGFzZSdzIG1pbGVzdG9uZSBpcyBzYXRpc2ZpZWQsIHRyYWNraW5nXG4gICAqIHRoZSBldmlkZW5jZSB0aGF0IHRlbGxzIGEgc2xvdyBPYnNpZGlhbiBmcm9tIGEgY29udGVuZGVkIGd1ZXN0LlxuICAgKlxuICAgKiBFYWNoIHBvbGwgY29zdHMgZXhhY3RseSBvbmUgYGJyb3dzZXIuZXhlY3V0ZWAgcm91bmQtdHJpcCBcdTIwMTQgZGVsaWJlcmF0ZWx5IG5vdFxuICAgKiBhbiB7QGxpbmsgZW5zdXJlV2ViVmlld0NvbnRleHR9IGNhbGwsIHdob3NlIGBnZXRDb250ZXh0cygpYCBydW5zXG4gICAqIGBhZGIgc2hlbGwgY2F0IC9wcm9jL25ldC91bml4YCBhbmQgd2FzIG1lYXN1cmVkIGF0IH4xN3MgcGVyICoqTDE5KiouIFRoZVxuICAgKiByb3VuZC10cmlwIGlzIHRpbWVkLCBhbmQgdGhlIHNsb3dlc3Qgb25lIGlzIHJlcG9ydGVkIG9uIHRpbWVvdXQ6IGEgcGhhc2VcbiAgICogdGhhdCByYW4gb3V0IGFmdGVyIGEgaGFuZGZ1bCBvZiBwcm9iZXMgZWFjaCB0YWtpbmcgdGVucyBvZiBzZWNvbmRzIHdhc1xuICAgKiBzdGFydmVkIGJ5IHRoZSBndWVzdCwgbm90IGJ5IE9ic2lkaWFuLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBoYXNlLCBpdHMgYnVkZ2V0LCBhbmQgdGhlIHByZWRpY2F0ZSB0aGF0IGVuZHMgaXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdhaXRGb3JTdGFydHVwTWlsZXN0b25lKHBhcmFtczogV2FpdEZvclN0YXJ0dXBNaWxlc3RvbmVQYXJhbXMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGlzU2F0aXNmaWVkLCBwaGFzZSwgdGltZW91dEluTWlsbGlzZWNvbmRzIH0gPSBwYXJhbXM7XG4gICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGRlYWRsaW5lID0gc3RhcnQgKyB0aW1lb3V0SW5NaWxsaXNlY29uZHM7XG5cbiAgICBsZXQgZnVydGhlc3RNaWxlc3RvbmU6IEFwcFN0YXJ0dXBNaWxlc3RvbmUgPSAnbm8td2Vidmlldyc7XG4gICAgbGV0IHBvbGxDb3VudCA9IDA7XG4gICAgbGV0IHNsb3dlc3RSb3VuZFRyaXBJbk1pbGxpc2Vjb25kcyA9IDA7XG5cbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICBjb25zdCByb3VuZFRyaXBTdGFydCA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBtaWxlc3RvbmUgPSBjbGFzc2lmeUFwcFN0YXJ0dXBQcm9iZShhd2FpdCB0aGlzLnByb2JlU3RhcnR1cCgpKTtcbiAgICAgIGNvbnN0IHJvdW5kVHJpcEluTWlsbGlzZWNvbmRzID0gRGF0ZS5ub3coKSAtIHJvdW5kVHJpcFN0YXJ0O1xuXG4gICAgICBwb2xsQ291bnQrKztcbiAgICAgIHNsb3dlc3RSb3VuZFRyaXBJbk1pbGxpc2Vjb25kcyA9IE1hdGgubWF4KHNsb3dlc3RSb3VuZFRyaXBJbk1pbGxpc2Vjb25kcywgcm91bmRUcmlwSW5NaWxsaXNlY29uZHMpO1xuICAgICAgaWYgKGNvbXBhcmVBcHBTdGFydHVwTWlsZXN0b25lcyhtaWxlc3RvbmUsIGZ1cnRoZXN0TWlsZXN0b25lKSA+IDApIHtcbiAgICAgICAgZnVydGhlc3RNaWxlc3RvbmUgPSBtaWxlc3RvbmU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc1NhdGlzZmllZChtaWxlc3RvbmUpKSB7XG4gICAgICAgIGxvZyhgW2FwcGl1bS10cmFuc3BvcnRdIFBoYXNlIFwiJHtwaGFzZX1cIiBzYXRpc2ZpZWQgYWZ0ZXIgJHtTdHJpbmcoRGF0ZS5ub3coKSAtIHN0YXJ0KX1tcyAoJHtTdHJpbmcocG9sbENvdW50KX0gcHJvYmUocykpLmApO1xuICAgICAgICB0aGlzLmlzSW5XZWJWaWV3Q29udGV4dCA9IHRydWU7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbG9nKFxuICAgICAgICBgW2FwcGl1bS10cmFuc3BvcnRdIFBoYXNlIFwiJHtwaGFzZX1cIiBub3Qgc2F0aXNmaWVkIHlldDogJHttaWxlc3RvbmV9IGBcbiAgICAgICAgICArIGAoZWxhcHNlZD0ke1N0cmluZyhEYXRlLm5vdygpIC0gc3RhcnQpfW1zLCByb3VuZC10cmlwPSR7U3RyaW5nKHJvdW5kVHJpcEluTWlsbGlzZWNvbmRzKX1tcykuIFJldHJ5aW5nLi4uYFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGRlbGF5KExBWU9VVF9SRUFEWV9QT0xMX0lOVEVSVkFMX0lOX01JTExJU0VDT05EUyk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGJ1aWxkU3RhcnR1cFRpbWVvdXRNZXNzYWdlKHtcbiAgICAgIGVsYXBzZWRJbk1pbGxpc2Vjb25kczogRGF0ZS5ub3coKSAtIHN0YXJ0LFxuICAgICAgbWlsZXN0b25lOiBmdXJ0aGVzdE1pbGVzdG9uZSxcbiAgICAgIHBoYXNlLFxuICAgICAgcG9sbENvdW50LFxuICAgICAgc2xvd2VzdFJvdW5kVHJpcEluTWlsbGlzZWNvbmRzLFxuICAgICAgdGltZW91dEluTWlsbGlzZWNvbmRzXG4gICAgfSkpO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlciB0aGUgZ2l2ZW4gZGVsYXkuXG4gKlxuICogQHBhcmFtIG1zIC0gVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcy5cbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBkZWxheS5cbiAqL1xuZnVuY3Rpb24gZGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKTtcbiAgfSk7XG59XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIHZhdWx0IGRpcmVjdG9yeSBuYW1lIGZyb20gYSBob3N0LXNpZGUgdmF1bHQgcGF0aC5cbiAqXG4gKiBAcGFyYW0gdmF1bHRQYXRoIC0gQWJzb2x1dGUgcGF0aCBvbiB0aGUgaG9zdCBtYWNoaW5lLlxuICogQHJldHVybnMgVGhlIGxhc3QgcGF0aCBzZWdtZW50ICh2YXVsdCBkaXJlY3RvcnkgbmFtZSkuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RWYXVsdE5hbWUodmF1bHRQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBub3JtYWxpemVkID0gdmF1bHRQYXRoLnJlcGxhY2UoL1tcXFxcL10rJC8sICcnKTtcbiAgY29uc3QgbGFzdFNlcGFyYXRvciA9IE1hdGgubWF4KG5vcm1hbGl6ZWQubGFzdEluZGV4T2YoJy8nKSwgbm9ybWFsaXplZC5sYXN0SW5kZXhPZignXFxcXCcpKTtcbiAgcmV0dXJuIG5vcm1hbGl6ZWQuc2xpY2UobGFzdFNlcGFyYXRvciArIDEpO1xufVxuXG4vKiB2OCBpZ25vcmUgc3RvcCAqL1xuIl0sCiAgIm1hcHBpbmdzIjogIkFBNENBLFNBQVMsa0JBQWtCO0FBQzNCO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxjQUFjO0FBQ3ZCLFNBQVMsWUFBWTtBQWdCckI7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFDUDtBQUFBLEVBQ0U7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
|