@workflow/core 5.0.0-beta.5 → 5.0.0-beta.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/dist/attribute-changes.d.ts +5 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +35 -2
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +74 -5
  7. package/dist/capture-stack.d.ts +1 -1
  8. package/dist/capture-stack.js +2 -2
  9. package/dist/class-serialization.d.ts +32 -0
  10. package/dist/class-serialization.d.ts.map +1 -1
  11. package/dist/class-serialization.js +37 -1
  12. package/dist/classify-error.d.ts +19 -3
  13. package/dist/classify-error.d.ts.map +1 -1
  14. package/dist/classify-error.js +98 -6
  15. package/dist/context-violation-error.d.ts +5 -5
  16. package/dist/context-violation-error.d.ts.map +1 -1
  17. package/dist/context-violation-error.js +8 -6
  18. package/dist/create-hook.d.ts +72 -7
  19. package/dist/create-hook.d.ts.map +1 -1
  20. package/dist/create-hook.js +1 -1
  21. package/dist/define-hook.js +2 -2
  22. package/dist/describe-error.d.ts +7 -7
  23. package/dist/describe-error.d.ts.map +1 -1
  24. package/dist/describe-error.js +97 -12
  25. package/dist/encryption.d.ts +38 -4
  26. package/dist/encryption.d.ts.map +1 -1
  27. package/dist/encryption.js +96 -14
  28. package/dist/events-consumer.d.ts +271 -0
  29. package/dist/events-consumer.d.ts.map +1 -1
  30. package/dist/events-consumer.js +646 -42
  31. package/dist/flushable-stream.d.ts +56 -1
  32. package/dist/flushable-stream.d.ts.map +1 -1
  33. package/dist/flushable-stream.js +123 -11
  34. package/dist/global.d.ts +36 -2
  35. package/dist/global.d.ts.map +1 -1
  36. package/dist/global.js +21 -6
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -2
  40. package/dist/log-format.d.ts +2 -2
  41. package/dist/log-format.js +7 -7
  42. package/dist/logger.d.ts +1 -0
  43. package/dist/logger.d.ts.map +1 -1
  44. package/dist/logger.js +10 -6
  45. package/dist/private.d.ts +226 -9
  46. package/dist/private.d.ts.map +1 -1
  47. package/dist/private.js +626 -7
  48. package/dist/replay-payload-cache.d.ts +64 -0
  49. package/dist/replay-payload-cache.d.ts.map +1 -0
  50. package/dist/replay-payload-cache.js +158 -0
  51. package/dist/runtime/compute-instance.d.ts +13 -0
  52. package/dist/runtime/compute-instance.d.ts.map +1 -0
  53. package/dist/runtime/compute-instance.js +14 -0
  54. package/dist/runtime/constants.d.ts +315 -0
  55. package/dist/runtime/constants.d.ts.map +1 -1
  56. package/dist/runtime/constants.js +502 -16
  57. package/dist/runtime/count-step-started-events.d.ts +52 -0
  58. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  59. package/dist/runtime/count-step-started-events.js +72 -0
  60. package/dist/runtime/deployment-guard.d.ts +99 -0
  61. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  62. package/dist/runtime/deployment-guard.js +154 -0
  63. package/dist/runtime/get-port-lazy.d.ts +15 -0
  64. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  65. package/dist/runtime/get-port-lazy.js +75 -6
  66. package/dist/runtime/get-world-lazy.d.ts +5 -14
  67. package/dist/runtime/get-world-lazy.d.ts.map +1 -1
  68. package/dist/runtime/get-world-lazy.js +19 -29
  69. package/dist/runtime/helpers.d.ts +341 -29
  70. package/dist/runtime/helpers.d.ts.map +1 -1
  71. package/dist/runtime/helpers.js +559 -57
  72. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  73. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  74. package/dist/runtime/quickjs-assets.generated.js +30 -0
  75. package/dist/runtime/quickjs-entrypoint.d.ts +136 -0
  76. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  77. package/dist/runtime/quickjs-entrypoint.js +1686 -0
  78. package/dist/runtime/quickjs-runtime.d.ts +244 -0
  79. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  80. package/dist/runtime/quickjs-runtime.js +2427 -0
  81. package/dist/runtime/quickjs-serde.d.ts +107 -0
  82. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-serde.js +2159 -0
  84. package/dist/runtime/replay-budget.d.ts +97 -0
  85. package/dist/runtime/replay-budget.d.ts.map +1 -0
  86. package/dist/runtime/replay-budget.js +139 -0
  87. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  88. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  89. package/dist/runtime/replay-recovery-reporter.js +64 -0
  90. package/dist/runtime/resume-hook.d.ts +91 -8
  91. package/dist/runtime/resume-hook.d.ts.map +1 -1
  92. package/dist/runtime/resume-hook.js +512 -89
  93. package/dist/runtime/resume-latency.d.ts +150 -0
  94. package/dist/runtime/resume-latency.d.ts.map +1 -0
  95. package/dist/runtime/resume-latency.js +155 -0
  96. package/dist/runtime/run-id-time.d.ts +19 -0
  97. package/dist/runtime/run-id-time.d.ts.map +1 -0
  98. package/dist/runtime/run-id-time.js +42 -0
  99. package/dist/runtime/run.d.ts +72 -7
  100. package/dist/runtime/run.d.ts.map +1 -1
  101. package/dist/runtime/run.js +280 -53
  102. package/dist/runtime/runs.d.ts +54 -3
  103. package/dist/runtime/runs.d.ts.map +1 -1
  104. package/dist/runtime/runs.js +126 -16
  105. package/dist/runtime/start.d.ts +101 -2
  106. package/dist/runtime/start.d.ts.map +1 -1
  107. package/dist/runtime/start.js +352 -61
  108. package/dist/runtime/step-executor.d.ts +205 -5
  109. package/dist/runtime/step-executor.d.ts.map +1 -1
  110. package/dist/runtime/step-executor.js +760 -127
  111. package/dist/runtime/step-latency.d.ts +220 -0
  112. package/dist/runtime/step-latency.d.ts.map +1 -0
  113. package/dist/runtime/step-latency.js +215 -0
  114. package/dist/runtime/step-ownership.d.ts +72 -0
  115. package/dist/runtime/step-ownership.d.ts.map +1 -0
  116. package/dist/runtime/step-ownership.js +114 -0
  117. package/dist/runtime/step-single-flight.d.ts +12 -0
  118. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  119. package/dist/runtime/step-single-flight.js +75 -0
  120. package/dist/runtime/suspension-handler.d.ts +269 -7
  121. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  122. package/dist/runtime/suspension-handler.js +1253 -125
  123. package/dist/runtime/unserializable-step.d.ts +34 -0
  124. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  125. package/dist/runtime/unserializable-step.js +52 -0
  126. package/dist/runtime/vm-mode.d.ts +44 -0
  127. package/dist/runtime/vm-mode.d.ts.map +1 -0
  128. package/dist/runtime/vm-mode.js +62 -0
  129. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  130. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  131. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  132. package/dist/runtime/wait-continuation.d.ts +106 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +136 -0
  135. package/dist/runtime/wait-until.d.ts +18 -0
  136. package/dist/runtime/wait-until.d.ts.map +1 -0
  137. package/dist/runtime/wait-until.js +42 -0
  138. package/dist/runtime/world-compatibility.d.ts +32 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +44 -0
  141. package/dist/runtime/world-init.d.ts +17 -42
  142. package/dist/runtime/world-init.d.ts.map +1 -1
  143. package/dist/runtime/world-init.js +18 -43
  144. package/dist/runtime/world.d.ts +14 -2
  145. package/dist/runtime/world.d.ts.map +1 -1
  146. package/dist/runtime/world.js +75 -19
  147. package/dist/runtime.d.ts +10 -6
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3741 -490
  150. package/dist/sealed-box.d.ts +167 -0
  151. package/dist/sealed-box.d.ts.map +1 -0
  152. package/dist/sealed-box.js +571 -0
  153. package/dist/serialization/client.d.ts +3 -3
  154. package/dist/serialization/client.d.ts.map +1 -1
  155. package/dist/serialization/client.js +8 -4
  156. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  157. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  158. package/dist/serialization/codec-devalue-vm.js +148 -0
  159. package/dist/serialization/codec-devalue.d.ts +1 -1
  160. package/dist/serialization/codec-devalue.d.ts.map +1 -1
  161. package/dist/serialization/codec-devalue.js +24 -6
  162. package/dist/serialization/codec.d.ts +37 -2
  163. package/dist/serialization/codec.d.ts.map +1 -1
  164. package/dist/serialization/codec.js +2 -2
  165. package/dist/serialization/compression.d.ts +105 -0
  166. package/dist/serialization/compression.d.ts.map +1 -0
  167. package/dist/serialization/compression.js +261 -0
  168. package/dist/serialization/encryption.d.ts +119 -17
  169. package/dist/serialization/encryption.d.ts.map +1 -1
  170. package/dist/serialization/encryption.js +152 -17
  171. package/dist/serialization/errors.d.ts +13 -0
  172. package/dist/serialization/errors.d.ts.map +1 -1
  173. package/dist/serialization/errors.js +20 -2
  174. package/dist/serialization/format.d.ts +6 -6
  175. package/dist/serialization/format.js +7 -7
  176. package/dist/serialization/hardened.d.ts +156 -0
  177. package/dist/serialization/hardened.d.ts.map +1 -0
  178. package/dist/serialization/hardened.js +538 -0
  179. package/dist/serialization/index.d.ts +10 -8
  180. package/dist/serialization/index.d.ts.map +1 -1
  181. package/dist/serialization/index.js +10 -8
  182. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  183. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  184. package/dist/serialization/reducers/class-vm.js +77 -0
  185. package/dist/serialization/reducers/class.d.ts.map +1 -1
  186. package/dist/serialization/reducers/class.js +11 -6
  187. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  188. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  189. package/dist/serialization/reducers/common-vm.js +616 -0
  190. package/dist/serialization/reducers/common.d.ts +1 -1
  191. package/dist/serialization/reducers/common.d.ts.map +1 -1
  192. package/dist/serialization/reducers/common.js +202 -62
  193. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  194. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  195. package/dist/serialization/reducers/step-function-vm.js +97 -0
  196. package/dist/serialization/reducers/step-function.d.ts.map +1 -1
  197. package/dist/serialization/reducers/step-function.js +25 -9
  198. package/dist/serialization/step.d.ts +4 -4
  199. package/dist/serialization/step.d.ts.map +1 -1
  200. package/dist/serialization/step.js +9 -5
  201. package/dist/serialization/types.d.ts +80 -1
  202. package/dist/serialization/types.d.ts.map +1 -1
  203. package/dist/serialization/types.js +15 -1
  204. package/dist/serialization/workflow-vm.d.ts +29 -0
  205. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  206. package/dist/serialization/workflow-vm.js +74 -0
  207. package/dist/serialization-format.d.ts +64 -8
  208. package/dist/serialization-format.d.ts.map +1 -1
  209. package/dist/serialization-format.js +225 -73
  210. package/dist/serialization.d.ts +262 -34
  211. package/dist/serialization.d.ts.map +1 -1
  212. package/dist/serialization.js +1879 -274
  213. package/dist/set-attributes.d.ts +13 -0
  214. package/dist/set-attributes.d.ts.map +1 -0
  215. package/dist/set-attributes.js +60 -0
  216. package/dist/source-map.d.ts +25 -0
  217. package/dist/source-map.d.ts.map +1 -1
  218. package/dist/source-map.js +154 -10
  219. package/dist/step/context-storage.d.ts +61 -2
  220. package/dist/step/context-storage.d.ts.map +1 -1
  221. package/dist/step/context-storage.js +7 -5
  222. package/dist/step/writable-stream.d.ts +3 -3
  223. package/dist/step/writable-stream.d.ts.map +1 -1
  224. package/dist/step/writable-stream.js +72 -9
  225. package/dist/step.d.ts.map +1 -1
  226. package/dist/step.js +148 -27
  227. package/dist/symbols.d.ts +50 -0
  228. package/dist/symbols.d.ts.map +1 -1
  229. package/dist/symbols.js +51 -1
  230. package/dist/telemetry/semantic-conventions.d.ts +397 -2
  231. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  232. package/dist/telemetry/semantic-conventions.js +297 -3
  233. package/dist/telemetry.d.ts +91 -0
  234. package/dist/telemetry.d.ts.map +1 -1
  235. package/dist/telemetry.js +244 -17
  236. package/dist/test-support/orchestrator-context.d.ts +25 -0
  237. package/dist/test-support/orchestrator-context.d.ts.map +1 -0
  238. package/dist/test-support/orchestrator-context.js +101 -0
  239. package/dist/types.d.ts +6 -0
  240. package/dist/types.d.ts.map +1 -1
  241. package/dist/types.js +23 -1
  242. package/dist/util.d.ts +0 -5
  243. package/dist/util.d.ts.map +1 -1
  244. package/dist/util.js +1 -15
  245. package/dist/version.d.ts +1 -1
  246. package/dist/version.d.ts.map +1 -1
  247. package/dist/version.js +2 -2
  248. package/dist/vm/index.d.ts.map +1 -1
  249. package/dist/vm/index.js +84 -14
  250. package/dist/vm/script-cache.d.ts +26 -0
  251. package/dist/vm/script-cache.d.ts.map +1 -0
  252. package/dist/vm/script-cache.js +131 -0
  253. package/dist/vm/uint8array-base64.js +1 -1
  254. package/dist/workflow/abort-controller.d.ts +2 -2
  255. package/dist/workflow/abort-controller.d.ts.map +1 -1
  256. package/dist/workflow/abort-controller.js +88 -21
  257. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  258. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  259. package/dist/workflow/attribute-dispatcher.js +45 -0
  260. package/dist/workflow/create-hook.d.ts.map +1 -1
  261. package/dist/workflow/create-hook.js +24 -3
  262. package/dist/workflow/get-workflow-metadata.js +2 -2
  263. package/dist/workflow/hook.d.ts.map +1 -1
  264. package/dist/workflow/hook.js +304 -47
  265. package/dist/workflow/index.d.ts +1 -0
  266. package/dist/workflow/index.d.ts.map +1 -1
  267. package/dist/workflow/index.js +2 -1
  268. package/dist/workflow/set-attributes.d.ts +68 -0
  269. package/dist/workflow/set-attributes.d.ts.map +1 -0
  270. package/dist/workflow/set-attributes.js +60 -0
  271. package/dist/workflow/sleep.d.ts.map +1 -1
  272. package/dist/workflow/sleep.js +58 -12
  273. package/dist/workflow/world-init-stub.d.ts +3 -3
  274. package/dist/workflow/world-init-stub.js +4 -4
  275. package/dist/workflow.d.ts +95 -3
  276. package/dist/workflow.d.ts.map +1 -1
  277. package/dist/workflow.js +895 -561
  278. package/docs/api-reference/create-hook.mdx +89 -10
  279. package/docs/api-reference/create-webhook.mdx +16 -15
  280. package/docs/api-reference/define-hook.mdx +35 -33
  281. package/docs/api-reference/fatal-error.mdx +30 -8
  282. package/docs/api-reference/fetch.mdx +14 -10
  283. package/docs/api-reference/get-step-metadata.mdx +2 -2
  284. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  285. package/docs/api-reference/get-writable.mdx +7 -7
  286. package/docs/api-reference/index.mdx +4 -1
  287. package/docs/api-reference/retryable-error.mdx +1 -1
  288. package/docs/api-reference/set-attributes.mdx +61 -0
  289. package/docs/api-reference/sleep.mdx +4 -4
  290. package/docs/foundations/cancellation.mdx +31 -32
  291. package/docs/foundations/errors-and-retries.mdx +42 -11
  292. package/docs/foundations/hooks.mdx +64 -35
  293. package/docs/foundations/idempotency.mdx +244 -12
  294. package/docs/foundations/index.mdx +1 -23
  295. package/docs/foundations/meta.json +2 -1
  296. package/docs/foundations/serialization.mdx +21 -22
  297. package/docs/foundations/starting-workflows.mdx +106 -30
  298. package/docs/foundations/streaming.mdx +107 -59
  299. package/docs/foundations/versioning.mdx +263 -0
  300. package/docs/foundations/workflows-and-steps.mdx +9 -9
  301. package/docs/how-it-works/cancellation.mdx +63 -63
  302. package/docs/how-it-works/code-transform.mdx +83 -67
  303. package/docs/how-it-works/encryption.mdx +30 -26
  304. package/docs/how-it-works/event-sourcing.mdx +98 -34
  305. package/docs/how-it-works/framework-integrations.mdx +96 -337
  306. package/docs/how-it-works/understanding-directives.mdx +22 -22
  307. package/package.json +24 -15
  308. package/dist/runtime/step-handler.d.ts +0 -2
  309. package/dist/runtime/step-handler.d.ts.map +0 -1
  310. package/dist/runtime/step-handler.js +0 -776
package/dist/workflow.js CHANGED
@@ -1,51 +1,55 @@
1
- import { runInContext } from 'node:vm';
2
- import { ERROR_SLUGS, WorkflowNotRegisteredError, WorkflowRuntimeError, } from '@workflow/errors';
3
- import { withResolvers } from '@workflow/utils';
4
- import { getPortLazy } from './runtime/get-port-lazy.js';
1
+ import { ERROR_SLUGS, ReplayDivergenceError, WorkflowNotRegisteredError, WorkflowRuntimeError, } from '@workflow/errors';
2
+ import { createWorkflowBaseUrl, withResolvers, } from '@workflow/utils';
5
3
  import { parseWorkflowName } from '@workflow/utils/parse-name';
4
+ import { SPEC_VERSION_SUPPORTS_COMPRESSION } from '@workflow/world/spec-version';
6
5
  import * as nanoid from 'nanoid';
7
6
  import { monotonicFactory } from 'ulid';
8
7
  import { EventConsumerResult, EventsConsumer } from './events-consumer.js';
9
8
  import { ENOTSUP, WorkflowSuspension } from './global.js';
10
9
  import { runtimeLogger } from './logger.js';
10
+ import { isDeliveryIdle } from './private.js';
11
+ import { ReplayPayloadCache } from './replay-payload-cache.js';
12
+ import { getPortLazy } from './runtime/get-port-lazy.js';
13
+ import { runIdCreatedAt } from './runtime/run-id-time.js';
11
14
  import { handleSuspension } from './runtime/suspension-handler.js';
12
15
  import { getWorld } from './runtime/world.js';
13
16
  import { dehydrateWorkflowReturnValue, hydrateWorkflowArguments, } from './serialization.js';
14
17
  import { createUseStep } from './step.js';
15
- import { BODY_INIT_SYMBOL, STABLE_ULID, WORKFLOW_CREATE_HOOK, WORKFLOW_GET_STREAM_ID, WORKFLOW_SLEEP, WORKFLOW_USE_STEP, } from './symbols.js';
18
+ import { BODY_INIT_SYMBOL, STABLE_ULID, WORKFLOW_CREATE_HOOK, WORKFLOW_GET_STREAM_ID, WORKFLOW_SET_ATTRIBUTES, WORKFLOW_SLEEP, WORKFLOW_USE_STEP, } from './symbols.js';
16
19
  import * as Attribute from './telemetry/semantic-conventions.js';
17
- import { trace } from './telemetry.js';
20
+ import { applyWorkflowSuspensionToSpan, createRefreshableTraceContext, startTraceSpan, trace, } from './telemetry.js';
18
21
  import { getWorkflowRunStreamId } from './util.js';
19
22
  import { createContext } from './vm/index.js';
20
- import { WORKFLOW_CONTEXT_SYMBOL } from './workflow/get-workflow-metadata.js';
23
+ import { getCachedWorkflowScript } from './vm/script-cache.js';
21
24
  import { createAbortSignalStatics, createCreateAbortController, } from './workflow/abort-controller.js';
25
+ import { createSetAttributes } from './workflow/attribute-dispatcher.js';
26
+ import { WORKFLOW_CONTEXT_SYMBOL } from './workflow/get-workflow-metadata.js';
22
27
  import { createCreateHook } from './workflow/hook.js';
23
28
  import { createSleep } from './workflow/sleep.js';
24
29
  /**
25
30
  * Drain pending queue items at workflow completion (success or failure).
26
31
  *
27
- * Treats end-of-run like a final suspension: any operation the workflow code
28
- * spawned but didn't `await` abort hook resumes, hook creations/disposals,
29
- * sleep waits, step queueings gets committed to the event log via the
30
- * suspension handler before the run is marked terminal.
32
+ * Treats completion as a final suspension so unawaited hook, wait, and
33
+ * attribute operations are recorded before the run becomes terminal. This
34
+ * also lets a final `controller.abort()` reach in-flight steps.
31
35
  *
32
- * This matches normal JS semantics where `setTimeout(fn, ...)` etc. continue
33
- * running after the surrounding function returns. Most importantly, it ensures
34
- * `controller.abort()` called as the last statement of a workflow actually
35
- * propagates to in-flight steps on other compute instances — without this,
36
- * the abort hook is created but never resumed and the cancellation never
37
- * reaches the running step.
36
+ * It records `*_created` and native attribute events, but never executes step
37
+ * bodies: `step_started` is rejected after the run becomes terminal. A
38
+ * fire-and-forget step therefore needs a later suspension to be scheduled.
38
39
  *
39
- * Drain failures are swallowed: the workflow's own outcome (the user's return
40
- * value or thrown error) is the source of truth; secondary cleanup that fails
41
- * shouldn't change the run's terminal state.
40
+ * Drain failures do not change the workflow's terminal outcome.
41
+ */
42
+ async function drainPendingQueueItems(runId, pendingQueue, vmGlobalThis, workflowRun, outcome,
43
+ /**
44
+ * In turbo mode, gates final `*_created` writes on backgrounded
45
+ * `run_started`. Undefined when `run_started` is awaited.
42
46
  */
43
- async function drainPendingQueueItems(runId, pendingQueue, vmGlobalThis, workflowRun, outcome) {
47
+ runReadyBarrier) {
44
48
  if (pendingQueue.size === 0)
45
49
  return;
46
50
  // Implicitly dispose any abort hooks (system hooks) that are still alive at
47
51
  // workflow completion so they don't leak rows in the hooks table for the
48
- // run's lifetime. Skip hooks that already have an abort in flight those
52
+ // run's lifetime. Skip hooks that already have an abort in flight; those
49
53
  // will emit hook_received via the abort processing path. User hooks
50
54
  // (isSystem !== true) are intentionally left alone: their lifetime is
51
55
  // managed by the user's code, not the runtime.
@@ -64,6 +68,7 @@ async function drainPendingQueueItems(runId, pendingQueue, vmGlobalThis, workflo
64
68
  suspension: synthesized,
65
69
  world,
66
70
  run: workflowRun,
71
+ runReadyBarrier,
67
72
  });
68
73
  }
69
74
  catch (err) {
@@ -73,221 +78,447 @@ async function drainPendingQueueItems(runId, pendingQueue, vmGlobalThis, workflo
73
78
  });
74
79
  }
75
80
  }
76
- export async function runWorkflow(workflowCode, workflowRun, events, encryptionKey) {
77
- return trace(`workflow.run ${workflowRun.workflowName}`, async (span) => {
81
+ /**
82
+ * Compile the workflow bundle before its run snapshot is available.
83
+ *
84
+ * Compilation depends only on the route's bundle string and the workflow name
85
+ * persisted on the run, not the event log or VM context. The runtime starts
86
+ * this promise while `run_started` loads the replay snapshot, then evaluates
87
+ * the scripts only after it has created the fresh context.
88
+ */
89
+ export function compileWorkflowBundle(workflowCode, workflowName) {
90
+ const parsedName = parseWorkflowName(workflowName);
91
+ const filename = parsedName?.moduleSpecifier || workflowName;
92
+ const workflowLookupCode = `globalThis.__private_workflows?.get(${JSON.stringify(workflowName)})`;
93
+ return trace('workflow.bundle.compile', async (span) => {
94
+ const bundle = getCachedWorkflowScript(workflowCode, filename);
95
+ const lookup = getCachedWorkflowScript(workflowLookupCode, filename);
96
+ span?.setAttributes({
97
+ // This attribute intentionally describes the workflow bundle. The tiny
98
+ // lookup script may miss when another workflow from the same source file
99
+ // runs, but that does not mean V8 recompiled the application bundle.
100
+ ...Attribute.WorkflowBundleCompileCacheHit(bundle.cacheHit),
101
+ });
102
+ return {
103
+ bundleScript: bundle.script,
104
+ workflowLookupScript: lookup.script,
105
+ };
106
+ });
107
+ }
108
+ /** Cold-start: build a fresh VM session and replay it over `events`. */
109
+ export function replayWorkflow(options) {
110
+ return traceExecution('replay', options.workflowRun, options.events, async (span) => {
111
+ const { session, execution } = await createWorkflowSession(options);
112
+ span?.setAttributes({
113
+ ...Attribute.WorkflowArgumentsCount(session.argumentCount),
114
+ });
115
+ return recordResult(await execution, span);
116
+ });
117
+ }
118
+ /** Warm-start: advance a retained session by appending events. */
119
+ export function resumeWorkflow(session, events) {
120
+ return traceExecution('retained', session.workflowRun, events, async (span) => {
121
+ span?.setAttributes({
122
+ ...Attribute.WorkflowArgumentsCount(session.argumentCount),
123
+ });
124
+ const result = await session.resume(events);
125
+ return result.type === 'replay' ? result : recordResult(result, span);
126
+ });
127
+ }
128
+ function traceExecution(mode, workflowRun, events, fn) {
129
+ return trace(`workflow.run ${workflowRun.workflowName}`, (span) => {
78
130
  span?.setAttributes({
79
131
  ...Attribute.WorkflowName(workflowRun.workflowName),
80
132
  ...Attribute.WorkflowRunId(workflowRun.runId),
81
133
  ...Attribute.WorkflowRunStatus(workflowRun.status),
82
134
  ...Attribute.WorkflowEventsCount(events.length),
135
+ ...Attribute.WorkflowExecutionMode(mode),
83
136
  });
84
- const startedAt = workflowRun.startedAt;
85
- if (!startedAt) {
86
- throw new WorkflowRuntimeError(`Workflow run "${workflowRun.runId}" has no "startedAt" timestamp (should not happen)`);
87
- }
88
- // Get the port before creating VM context to avoid async operations
89
- // affecting the deterministic timestamp
90
- const isVercel = process.env.VERCEL_URL !== undefined;
91
- // Load getPort lazily to prevent Turbopack from tracing get-port's
92
- // fs ops (readdir, readFile) into the flow route bundle.
93
- // Uses globalThis.__wkf_getPort as a lazy-initialized cache to avoid
94
- // bundler static analysis while staying compatible with CJS/ESM/VM.
95
- const port = isVercel ? undefined : await getPortLazy();
96
- const { context, globalThis: vmGlobalThis, updateTimestamp, } = createContext({
97
- seed: `${workflowRun.runId}:${workflowRun.workflowName}:${+startedAt}`,
98
- fixedTimestamp: +startedAt,
99
- });
100
- const workflowDiscontinuation = withResolvers();
101
- const ulid = monotonicFactory(() => vmGlobalThis.Math.random());
102
- const generateNanoid = nanoid.customRandom(nanoid.urlAlphabet, 21, (size) => new Uint8Array(size).map(() => 256 * vmGlobalThis.Math.random()));
103
- // Create a mutable holder for the promise queue so the EventsConsumer
104
- // can access the current queue state via a getter. The queue is mutated
105
- // by step/hook/sleep callbacks as events are processed.
106
- const promiseQueueHolder = { current: Promise.resolve() };
107
- const eventsConsumer = new EventsConsumer(events, {
108
- onUnconsumedEvent: (event) => {
109
- workflowDiscontinuation.reject(new WorkflowRuntimeError(`Unconsumed event in event log: eventType=${event.eventType}, correlationId=${event.correlationId}, eventId=${event.eventId}. This indicates a corrupted or invalid event log.`, { slug: ERROR_SLUGS.CORRUPTED_EVENT_LOG }));
110
- },
111
- getPromiseQueue: () => promiseQueueHolder.current,
137
+ return fn(span);
138
+ });
139
+ }
140
+ function recordResult(result, span) {
141
+ if (result.type === 'completed') {
142
+ span?.setAttributes({
143
+ ...Attribute.WorkflowResultType(result.resultType),
112
144
  });
113
- const workflowContext = {
114
- runId: workflowRun.runId,
115
- encryptionKey,
116
- globalThis: vmGlobalThis,
117
- onWorkflowError: workflowDiscontinuation.reject,
118
- eventsConsumer,
119
- generateUlid: () => ulid(+startedAt),
120
- generateNanoid,
121
- invocationsQueue: new Map(),
122
- // Use getter/setter so the EventsConsumer's getPromiseQueue() always
123
- // sees the latest queue state as it's mutated by step/hook/sleep callbacks.
124
- get promiseQueue() {
125
- return promiseQueueHolder.current;
126
- },
127
- set promiseQueue(value) {
128
- promiseQueueHolder.current = value;
129
- },
130
- pendingDeliveries: 0,
131
- };
132
- // Subscribe to the events log to update the timestamp in the vm context
133
- workflowContext.eventsConsumer.subscribe((event) => {
134
- const createdAt = event?.createdAt;
135
- if (createdAt) {
136
- updateTimestamp(+createdAt);
137
- }
138
- // Never consume events - this is only a passive subscriber
145
+ }
146
+ else if (span) {
147
+ applyWorkflowSuspensionToSpan(result.suspension, span);
148
+ // Events this pass walked past unclaimed and is still holding. Ordinary on
149
+ // a suspension: an out-of-band delivery that landed ahead of the code that
150
+ // reads it waits for the pass that reaches that code, and failing here
151
+ // would fail exactly the runs that tolerance exists for. The case that is
152
+ // not ordinary (the same event still held pass after pass) is a shape
153
+ // across these spans, which is why the eventId is on each one and no pass
154
+ // tries to rule on it alone.
155
+ if (result.parked) {
156
+ span.setAttributes({
157
+ ...Attribute.WorkflowParkedEventsCount(result.parked.count),
158
+ ...Attribute.WorkflowParkedEventId(result.parked.eventId),
159
+ ...Attribute.WorkflowParkedEventType(result.parked.eventType),
160
+ });
161
+ }
162
+ }
163
+ return result;
164
+ }
165
+ /**
166
+ * Single-shot replay: execute the workflow over `events` and either return
167
+ * its output or throw its suspension. Kept for the extensive existing test
168
+ * suites; production code goes through `replayWorkflow`/`resumeWorkflow`.
169
+ */
170
+ export async function runWorkflow(workflowCode, workflowRun, events, encryptionKey,
171
+ /**
172
+ * Optional per-run cache for replay payload preparation and immutable final
173
+ * values. Owned by the inline execution loop for this invocation.
174
+ */
175
+ replayPayloadCache = new ReplayPayloadCache(encryptionKey),
176
+ /**
177
+ * Turbo mode only: resolves once the backgrounded `run_started` has landed.
178
+ * Threaded into the end-of-run drain so fire-and-forget `*_created` writes
179
+ * committed at workflow completion order after the run's creation. Undefined
180
+ * outside turbo, where `run_started` is awaited up front.
181
+ */
182
+ runReadyBarrier,
183
+ /**
184
+ * Features supported by the World executing this workflow. Missing
185
+ * capabilities are treated as unsupported.
186
+ */
187
+ worldCapabilities) {
188
+ const result = await replayWorkflow({
189
+ workflowCode,
190
+ workflowRun,
191
+ events,
192
+ encryptionKey,
193
+ replayPayloadCache,
194
+ runReadyBarrier,
195
+ worldCapabilities,
196
+ });
197
+ if (result.type === 'suspended')
198
+ throw result.suspension;
199
+ return result.output;
200
+ }
201
+ async function createWorkflowSession(options) {
202
+ const vmTrace = await startTraceSpan('workflow.vm.create_context');
203
+ return createWorkflowSessionInner(options, vmTrace.end).catch((error) => {
204
+ vmTrace.fail(error);
205
+ throw error;
206
+ });
207
+ }
208
+ async function createWorkflowSessionInner({ workflowCode, workflowRun, events, encryptionKey, replayPayloadCache, compiledWorkflowScripts, runReadyBarrier, worldCapabilities, }, endVmTrace) {
209
+ const startedAt = workflowRun.startedAt;
210
+ if (!startedAt) {
211
+ throw new WorkflowRuntimeError(`Workflow run "${workflowRun.runId}" has no "startedAt" timestamp (should not happen)`);
212
+ }
213
+ // Seed and initial clock must be available before I/O and remain stable on
214
+ // replay. After the first event, EventsConsumer advances the VM clock from
215
+ // each event's `createdAt`.
216
+ const fixedTimestamp = runIdCreatedAt(workflowRun.runId) ?? +workflowRun.createdAt;
217
+ // Truthiness, not presence: `vercel env pull` writes `VERCEL_URL=""` into
218
+ // `.env.local`, and a framework that loads that file locally would otherwise
219
+ // put us on the Vercel branch with nothing to build a host from, making
220
+ // `https://` the base URL of every run.
221
+ const isVercel = Boolean(process.env.VERCEL_URL);
222
+ // Load getPort lazily to prevent Turbopack from tracing get-port's
223
+ // fs ops (readdir, readFile) into the flow route bundle. The resolved
224
+ // port is cached per process (see get-port-lazy.ts), so this is cheap
225
+ // on replays after the first.
226
+ const workflowBaseUrl = createWorkflowBaseUrl(isVercel
227
+ ? `https://${process.env.VERCEL_URL}`
228
+ : `http://localhost:${(await getPortLazy()) ?? 3000}`);
229
+ // Include both node:vm's context creation and the host-side sandbox wiring
230
+ // below. Most of the bootstrap lives in this function (EventsConsumer,
231
+ // workflow globals, Web API shims), so tracing createContext() alone would
232
+ // materially under-report VM startup.
233
+ const { context, globalThis: vmGlobalThis, updateTimestamp, } = createContext({
234
+ seed: `${workflowRun.runId}:${workflowRun.workflowName}:${workflowRun.deploymentId}`,
235
+ fixedTimestamp,
236
+ });
237
+ const initialInterruption = withResolvers();
238
+ let state = {
239
+ type: 'running',
240
+ interruption: initialInterruption,
241
+ };
242
+ const onWorkflowError = (error) => {
243
+ switch (state.type) {
244
+ case 'running': {
245
+ const { interruption } = state;
246
+ state = WorkflowSuspension.is(error)
247
+ ? { type: 'suspended', suspension: error }
248
+ : { type: 'replay' };
249
+ // Step, hook, wait, and attribute consumers can schedule the same
250
+ // suspension. The first signal advances the generation so the rest
251
+ // no-op.
252
+ workflowContext.suspensionGeneration++;
253
+ interruption.reject(error);
254
+ return;
255
+ }
256
+ case 'suspended':
257
+ // Same-boundary duplicates were staled by the generation bump above,
258
+ // so anything landing here is out-of-band or a divergence. Fall back
259
+ // to replay rather than resuming a potentially inconsistent session.
260
+ state = { type: 'replay' };
261
+ return;
262
+ case 'replay':
263
+ case 'completed':
264
+ return;
265
+ }
266
+ state;
267
+ };
268
+ const ulid = monotonicFactory(() => vmGlobalThis.Math.random());
269
+ // Correlation IDs must be replay-stable. `startedAt` differs between a turbo
270
+ // delivery and a later server-backed replay, so use fixedTimestamp.
271
+ // The draw counter is the progress metric for `quiesceEarlierCascades`
272
+ // (WORKFLOW_LOG_ORDER_DRAWS): a quiet turn is one that drew nothing. It
273
+ // counts EVERY draw from this sequence. This same function is installed as
274
+ // the `STABLE_ULID` global below, which serialization draws stream ids
275
+ // from during dehydration. This is deliberate because quiescence must also
276
+ // wait out serialization-driven draws, and counting extra draws only extends
277
+ // the wait (see the termination note on `quiesceEarlierCascades`).
278
+ let mintCount = 0;
279
+ const generateUlid = () => {
280
+ mintCount += 1;
281
+ return ulid(fixedTimestamp);
282
+ };
283
+ const generateNanoid = nanoid.customRandom(nanoid.urlAlphabet, 21, (size) => new Uint8Array(size).map(() => 256 * vmGlobalThis.Math.random()));
284
+ // Create a mutable holder for the promise queue so the EventsConsumer
285
+ // can access the current queue state via a getter. The queue is mutated
286
+ // by step/hook/sleep callbacks as events are processed.
287
+ const promiseQueueHolder = { current: Promise.resolve() };
288
+ // Same reason as the queue holder: the consumer is built before the context
289
+ // whose delivery state it has to read. Idle until the context exists, which
290
+ // is before any delivery can be registered against it.
291
+ const deliveryIdleHolder = { current: () => true };
292
+ // The VM clock only ever moves forward. Consumption order is log order for
293
+ // everything whose order the replay decides, but an event the consumer
294
+ // parked is delivered after the walk has already passed events written after
295
+ // it, and letting its `createdAt` set the clock would make `Date.now()` go
296
+ // backwards inside a single replay.
297
+ let clock = fixedTimestamp;
298
+ const eventsConsumer = new EventsConsumer(events, {
299
+ onConsumedEvent: (event) => {
300
+ const at = +event.createdAt;
301
+ if (at > clock) {
302
+ clock = at;
303
+ updateTimestamp(at);
304
+ }
305
+ },
306
+ onUnconsumedEvent: (event) => {
307
+ onWorkflowError(new ReplayDivergenceError(`Replay could not consume event: eventType=${event.eventType}, correlationId=${event.correlationId}, eventId=${event.eventId}.`, { eventId: event.eventId }));
308
+ },
309
+ // Both branches log at `debug`, so neither reaches the console unless
310
+ // `DEBUG` matches. A duplicate is a permanent feature of the log: every
311
+ // later replay re-reads it and lands here again, so anything the logger
312
+ // prints unconditionally would print once per replay for the life of the
313
+ // run. There is also nothing to act on. Ignoring the event is the correct
314
+ // outcome, not a degraded one, and no user change makes the straggler go
315
+ // away. What the levels are for is diagnosis after the fact, which is
316
+ // exactly what `DEBUG=workflow:runtime:debug` is for.
317
+ onDuplicateEvent: (event, firstEventType) => {
318
+ const details = {
319
+ workflowRunId: workflowRun.runId,
320
+ eventId: event.eventId,
321
+ eventType: event.eventType,
322
+ firstEventType,
323
+ correlationId: event.correlationId,
324
+ };
325
+ if (firstEventType !== event.eventType) {
326
+ // Two writers reached opposite conclusions about one entity: a
327
+ // `step_failed` behind a `step_completed`, or the reverse. Ignoring it
328
+ // is still correct and still deterministic (replay reads the first one
329
+ // at the same position every time), but unlike a re-commit of the same
330
+ // outcome there is no reading of this where both writers were right,
331
+ // so the discarded outcome gets its own message.
332
+ runtimeLogger.debug('Ignoring inert event that decides an already-decided outcome differently', details);
333
+ return;
334
+ }
335
+ // The first event of this class decided the outcome at a lower log
336
+ // position and replay reads that one. Recorded because a straggler is
337
+ // still evidence of two replays writing for the same entity, which is
338
+ // worth seeing when diagnosing a run.
339
+ runtimeLogger.debug('Ignoring inert event that repeats a class already in the event log', details);
340
+ },
341
+ getPromiseQueue: () => promiseQueueHolder.current,
342
+ isDeliveryIdle: () => deliveryIdleHolder.current(),
343
+ });
344
+ const workflowContext = {
345
+ runId: workflowRun.runId,
346
+ encryptionKey,
347
+ worldCapabilities,
348
+ globalThis: vmGlobalThis,
349
+ onWorkflowError,
350
+ eventsConsumer,
351
+ generateUlid,
352
+ generateNanoid,
353
+ get mintCount() {
354
+ return mintCount;
355
+ },
356
+ invocationsQueue: new Map(),
357
+ // Use getter/setter so the EventsConsumer's getPromiseQueue() always
358
+ // sees the latest queue state as it's mutated by step/hook/sleep callbacks.
359
+ get promiseQueue() {
360
+ return promiseQueueHolder.current;
361
+ },
362
+ set promiseQueue(value) {
363
+ promiseQueueHolder.current = value;
364
+ },
365
+ pendingDeliveries: 0,
366
+ suspensionGeneration: 0,
367
+ pendingDeliveryBarriers: new Map(),
368
+ replayPayloadCache,
369
+ };
370
+ deliveryIdleHolder.current = () => isDeliveryIdle(workflowContext);
371
+ // Consume run lifecycle events - these are structural events that don't
372
+ // need special handling in the workflow, but must be consumed to advance
373
+ // past them in the event log
374
+ let consumedRunStarted = false;
375
+ workflowContext.eventsConsumer.subscribe((event) => {
376
+ if (!event) {
139
377
  return EventConsumerResult.NotConsumed;
140
- });
141
- // Consume run lifecycle events - these are structural events that don't
142
- // need special handling in the workflow, but must be consumed to advance
143
- // past them in the event log
144
- workflowContext.eventsConsumer.subscribe((event) => {
145
- if (!event) {
378
+ }
379
+ // Consume run_created - every run has exactly one
380
+ if (event.eventType === 'run_created') {
381
+ return EventConsumerResult.Consumed;
382
+ }
383
+ // Consume the first run_started. Two replays can each write one (the
384
+ // create is idempotent for a run already running, which makes the write
385
+ // safe, not single-shot); the first is the one the replay observes, and
386
+ // the consumer skips the rest rather than advancing the workflow clock
387
+ // twice.
388
+ if (event.eventType === 'run_started') {
389
+ if (consumedRunStarted) {
146
390
  return EventConsumerResult.NotConsumed;
147
391
  }
148
- // Consume run_created - every run has exactly one
149
- if (event.eventType === 'run_created') {
150
- return EventConsumerResult.Consumed;
151
- }
152
- // Consume run_started - every run has exactly one
153
- if (event.eventType === 'run_started') {
154
- return EventConsumerResult.Consumed;
155
- }
156
- return EventConsumerResult.NotConsumed;
392
+ consumedRunStarted = true;
393
+ return EventConsumerResult.Consumed;
394
+ }
395
+ // Attribute writes performed from a step have no workflow-body call to
396
+ // consume them during replay; they are already reflected in the run
397
+ // snapshot and remain structural until a read API is introduced.
398
+ if (event.eventType === 'attr_set' &&
399
+ event.eventData.writer.type === 'step') {
400
+ return EventConsumerResult.Consumed;
401
+ }
402
+ return EventConsumerResult.NotConsumed;
403
+ });
404
+ const useStep = createUseStep(workflowContext);
405
+ const createHook = createCreateHook(workflowContext);
406
+ const sleep = createSleep(workflowContext);
407
+ const setAttributes = createSetAttributes(workflowContext);
408
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
409
+ vmGlobalThis[WORKFLOW_USE_STEP] = useStep;
410
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
411
+ vmGlobalThis[WORKFLOW_SET_ATTRIBUTES] = setAttributes;
412
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
413
+ vmGlobalThis[WORKFLOW_CREATE_HOOK] = createHook;
414
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
415
+ vmGlobalThis[WORKFLOW_SLEEP] = sleep;
416
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
417
+ vmGlobalThis[WORKFLOW_GET_STREAM_ID] = (namespace) => getWorkflowRunStreamId(workflowRun.runId, namespace);
418
+ // For the workflow VM, we store the context in a symbol on the `globalThis` object
419
+ const ctx = {
420
+ workflowName: workflowRun.workflowName,
421
+ workflowRunId: workflowRun.runId,
422
+ workflowStartedAt: new vmGlobalThis.Date(+startedAt),
423
+ url: workflowBaseUrl,
424
+ features: { encryption: !!encryptionKey },
425
+ };
426
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
427
+ vmGlobalThis[WORKFLOW_CONTEXT_SYMBOL] = ctx;
428
+ // Serialization mints stream ids through this symbol, and calls it with no
429
+ // seed time. `monotonicFactory` returns `encodeTime(lastTime)` on its
430
+ // increment branch, so one such call latches the *host* wall clock into
431
+ // `lastTime`, and every id the run mints afterwards carries that timestamp
432
+ // instead of `fixedTimestamp`, a value that differs on every replay. Binding
433
+ // the seed time here keeps the whole run on one replay-stable clock.
434
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
435
+ vmGlobalThis[STABLE_ULID] = generateUlid;
436
+ // Workflow code must import the deterministic `fetch` step from `workflow`.
437
+ vmGlobalThis.fetch = () => {
438
+ throw new vmGlobalThis.Error(`Global "fetch" is unavailable in workflow functions. Use the "fetch" step function from "workflow" to make HTTP requests.\n\nLearn more: https://workflow-sdk.dev/err/${ERROR_SLUGS.FETCH_IN_WORKFLOW_FUNCTION}`);
439
+ };
440
+ // Override timeout/interval functions to throw helpful errors
441
+ // These are not supported in workflow functions because they rely on
442
+ // asynchronous scheduling which breaks deterministic replay
443
+ const timeoutErrorMessage = 'Timeout functions like "setTimeout" and "setInterval" are not supported in workflow functions. Use the "sleep" function from "workflow" for time-based delays.';
444
+ vmGlobalThis.setTimeout = () => {
445
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
446
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
157
447
  });
158
- const useStep = createUseStep(workflowContext);
159
- const createHook = createCreateHook(workflowContext);
160
- const sleep = createSleep(workflowContext);
161
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
162
- vmGlobalThis[WORKFLOW_USE_STEP] = useStep;
163
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
164
- vmGlobalThis[WORKFLOW_CREATE_HOOK] = createHook;
165
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
166
- vmGlobalThis[WORKFLOW_SLEEP] = sleep;
167
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
168
- vmGlobalThis[WORKFLOW_GET_STREAM_ID] = (namespace) => getWorkflowRunStreamId(workflowRun.runId, namespace);
169
- // TODO: there should be a getUrl method on the world interface itself. This
170
- // solution only works for vercel + local worlds.
171
- const url = isVercel
172
- ? `https://${process.env.VERCEL_URL}`
173
- : `http://localhost:${port ?? 3000}`;
174
- // For the workflow VM, we store the context in a symbol on the `globalThis` object
175
- const ctx = {
176
- workflowName: workflowRun.workflowName,
177
- workflowRunId: workflowRun.runId,
178
- workflowStartedAt: new vmGlobalThis.Date(+startedAt),
179
- url,
180
- features: { encryption: !!encryptionKey },
181
- };
182
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
183
- vmGlobalThis[WORKFLOW_CONTEXT_SYMBOL] = ctx;
184
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
185
- vmGlobalThis[STABLE_ULID] = ulid;
186
- // NOTE: Will have a config override to use the custom fetch step.
187
- // For now `fetch` must be explicitly imported from `workflow`.
188
- vmGlobalThis.fetch = () => {
189
- throw new vmGlobalThis.Error(`Global "fetch" is unavailable in workflow functions. Use the "fetch" step function from "workflow" to make HTTP requests.\n\nLearn more: https://workflow-sdk.dev/err/${ERROR_SLUGS.FETCH_IN_WORKFLOW_FUNCTION}`);
190
- };
191
- // Override timeout/interval functions to throw helpful errors
192
- // These are not supported in workflow functions because they rely on
193
- // asynchronous scheduling which breaks deterministic replay
194
- const timeoutErrorMessage = 'Timeout functions like "setTimeout" and "setInterval" are not supported in workflow functions. Use the "sleep" function from "workflow" for time-based delays.';
195
- vmGlobalThis.setTimeout = () => {
196
- throw new WorkflowRuntimeError(timeoutErrorMessage, {
197
- slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
198
- });
199
- };
200
- vmGlobalThis.setInterval = () => {
201
- throw new WorkflowRuntimeError(timeoutErrorMessage, {
202
- slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
203
- });
204
- };
205
- vmGlobalThis.clearTimeout = () => {
206
- throw new WorkflowRuntimeError(timeoutErrorMessage, {
207
- slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
208
- });
209
- };
210
- vmGlobalThis.clearInterval = () => {
211
- throw new WorkflowRuntimeError(timeoutErrorMessage, {
212
- slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
213
- });
214
- };
215
- vmGlobalThis.setImmediate = () => {
216
- throw new WorkflowRuntimeError(timeoutErrorMessage, {
217
- slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
218
- });
219
- };
220
- vmGlobalThis.clearImmediate = () => {
221
- throw new WorkflowRuntimeError(timeoutErrorMessage, {
222
- slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
223
- });
224
- };
225
- // `AbortController` and `AbortSignal` in the workflow VM are hook-backed
226
- // for deterministic replay. The controller's abort() queues a hook resumption,
227
- // and signal.aborted is updated when the hook event is processed during replay.
228
- vmGlobalThis.AbortController =
229
- createCreateAbortController(workflowContext);
230
- const abortSignalStatics = createAbortSignalStatics();
231
- vmGlobalThis.AbortSignal = {
232
- abort: abortSignalStatics.abort,
233
- any: abortSignalStatics.any,
234
- timeout: abortSignalStatics.timeout,
235
- };
236
- // `Request` and `Response` are special built-in classes that invoke steps
237
- // for the `json()`, `text()` and `arrayBuffer()` instance methods
238
- class Request {
239
- cache;
240
- credentials;
241
- destination;
242
- headers;
243
- integrity;
244
- method;
245
- mode;
246
- redirect;
247
- referrer;
248
- referrerPolicy;
249
- url;
250
- keepalive;
251
- signal;
252
- duplex;
253
- body;
254
- constructor(input, init) {
255
- // Handle URL input
256
- if (typeof input === 'string' || input instanceof vmGlobalThis.URL) {
257
- const urlString = String(input);
258
- // Validate URL format
259
- try {
260
- new vmGlobalThis.URL(urlString);
261
- this.url = urlString;
262
- }
263
- catch (cause) {
264
- throw new TypeError(`Failed to parse URL from ${urlString}`, {
265
- cause,
266
- });
267
- }
448
+ };
449
+ vmGlobalThis.setInterval = () => {
450
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
451
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
452
+ });
453
+ };
454
+ vmGlobalThis.clearTimeout = () => {
455
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
456
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
457
+ });
458
+ };
459
+ vmGlobalThis.clearInterval = () => {
460
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
461
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
462
+ });
463
+ };
464
+ vmGlobalThis.setImmediate = () => {
465
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
466
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
467
+ });
468
+ };
469
+ vmGlobalThis.clearImmediate = () => {
470
+ throw new WorkflowRuntimeError(timeoutErrorMessage, {
471
+ slug: ERROR_SLUGS.TIMEOUT_FUNCTIONS_IN_WORKFLOW,
472
+ });
473
+ };
474
+ // `AbortController` and `AbortSignal` in the workflow VM are hook-backed
475
+ // for deterministic replay. The controller's abort() queues a hook resumption,
476
+ // and signal.aborted is updated when the hook event is processed during replay.
477
+ vmGlobalThis.AbortController =
478
+ createCreateAbortController(workflowContext);
479
+ const abortSignalStatics = createAbortSignalStatics();
480
+ vmGlobalThis.AbortSignal = {
481
+ abort: abortSignalStatics.abort,
482
+ any: abortSignalStatics.any,
483
+ timeout: abortSignalStatics.timeout,
484
+ };
485
+ // `Request` and `Response` are special built-in classes that invoke steps
486
+ // for the `json()`, `text()` and `arrayBuffer()` instance methods
487
+ class Request {
488
+ cache;
489
+ credentials;
490
+ destination;
491
+ headers;
492
+ integrity;
493
+ method;
494
+ mode;
495
+ redirect;
496
+ referrer;
497
+ referrerPolicy;
498
+ url;
499
+ keepalive;
500
+ signal;
501
+ duplex;
502
+ body;
503
+ constructor(input, init) {
504
+ // Handle URL input
505
+ if (typeof input === 'string' || input instanceof vmGlobalThis.URL) {
506
+ const urlString = String(input);
507
+ // Validate URL format
508
+ try {
509
+ new vmGlobalThis.URL(urlString);
510
+ this.url = urlString;
511
+ }
512
+ catch (cause) {
513
+ throw new TypeError(`Failed to parse URL from ${urlString}`, {
514
+ cause,
515
+ });
268
516
  }
269
- else {
270
- // Input is a Request object - clone its properties
271
- this.url = input.url;
272
- if (!init) {
273
- this.method = input.method;
274
- this.headers = new vmGlobalThis.Headers(input.headers);
275
- this.body = input.body;
276
- this.mode = input.mode;
277
- this.credentials = input.credentials;
278
- this.cache = input.cache;
279
- this.redirect = input.redirect;
280
- this.referrer = input.referrer;
281
- this.referrerPolicy = input.referrerPolicy;
282
- this.integrity = input.integrity;
283
- this.keepalive = input.keepalive;
284
- this.signal = input.signal;
285
- this.duplex = input.duplex;
286
- this.destination = input.destination;
287
- return;
288
- }
289
- // If init is provided, merge: use source properties, then override with init
290
- // Copy all properties from the source Request first
517
+ }
518
+ else {
519
+ // Input is a Request object - clone its properties
520
+ this.url = input.url;
521
+ if (!init) {
291
522
  this.method = input.method;
292
523
  this.headers = new vmGlobalThis.Headers(input.headers);
293
524
  this.body = input.body;
@@ -302,354 +533,457 @@ export async function runWorkflow(workflowCode, workflowRun, events, encryptionK
302
533
  this.signal = input.signal;
303
534
  this.duplex = input.duplex;
304
535
  this.destination = input.destination;
536
+ return;
305
537
  }
306
- // Override with init options if provided
307
- // Set method
308
- if (init?.method) {
309
- this.method = init.method.toUpperCase();
310
- }
311
- else if (typeof this.method !== 'string') {
312
- // Fallback to default for string input case
313
- this.method = 'GET';
314
- }
315
- // Set headers
316
- if (init?.headers) {
317
- this.headers = new vmGlobalThis.Headers(init.headers);
318
- }
319
- else if (typeof input === 'string' ||
320
- input instanceof vmGlobalThis.URL) {
321
- // For string/URL input, create empty headers
322
- this.headers = new vmGlobalThis.Headers();
323
- }
324
- // Set other properties with init values or defaults
325
- if (init?.mode !== undefined) {
326
- this.mode = init.mode;
327
- }
328
- else if (typeof this.mode !== 'string') {
329
- this.mode = 'cors';
330
- }
331
- if (init?.credentials !== undefined) {
332
- this.credentials = init.credentials;
333
- }
334
- else if (typeof this.credentials !== 'string') {
335
- this.credentials = 'same-origin';
336
- }
337
- // `any` cast here because @types/node v22 does not yet have `cache`
338
- if (init?.cache !== undefined) {
339
- this.cache = init.cache;
340
- }
341
- else if (typeof this.cache !== 'string') {
342
- this.cache = 'default';
343
- }
344
- if (init?.redirect !== undefined) {
345
- this.redirect = init.redirect;
346
- }
347
- else if (typeof this.redirect !== 'string') {
348
- this.redirect = 'follow';
349
- }
350
- if (init?.referrer !== undefined) {
351
- this.referrer = init.referrer;
352
- }
353
- else if (typeof this.referrer !== 'string') {
354
- this.referrer = 'about:client';
355
- }
356
- if (init?.referrerPolicy !== undefined) {
357
- this.referrerPolicy = init.referrerPolicy;
358
- }
359
- else if (typeof this.referrerPolicy !== 'string') {
360
- this.referrerPolicy = '';
361
- }
362
- if (init?.integrity !== undefined) {
363
- this.integrity = init.integrity;
364
- }
365
- else if (typeof this.integrity !== 'string') {
366
- this.integrity = '';
367
- }
368
- if (init?.keepalive !== undefined) {
369
- this.keepalive = init.keepalive;
370
- }
371
- else if (typeof this.keepalive !== 'boolean') {
372
- this.keepalive = false;
373
- }
374
- if (init?.signal !== undefined) {
375
- // @ts-expect-error - AbortSignal stub
376
- this.signal = init.signal;
377
- }
378
- else if (!this.signal) {
379
- // @ts-expect-error - AbortSignal stub
380
- this.signal = { aborted: false };
381
- }
382
- if (!this.duplex) {
383
- this.duplex = 'half';
384
- }
385
- if (!this.destination) {
386
- this.destination = 'document';
387
- }
388
- const body = init?.body;
389
- // Validate that GET/HEAD methods don't have a body
390
- if (body !== null &&
391
- body !== undefined &&
392
- (this.method === 'GET' || this.method === 'HEAD')) {
393
- throw new TypeError(`Request with GET/HEAD method cannot have body.`);
394
- }
395
- // Store the original BodyInit for serialization
396
- if (body !== null && body !== undefined) {
397
- // Create a "fake" ReadableStream that stores the original body
398
- // This avoids doing async work during workflow replay
399
- this.body = Object.create(vmGlobalThis.ReadableStream.prototype, {
400
- [BODY_INIT_SYMBOL]: {
401
- value: body,
402
- writable: false,
403
- },
404
- });
405
- }
406
- else {
407
- this.body = null;
408
- }
538
+ // If init is provided, merge: use source properties, then override with init
539
+ // Copy all properties from the source Request first
540
+ this.method = input.method;
541
+ this.headers = new vmGlobalThis.Headers(input.headers);
542
+ this.body = input.body;
543
+ this.mode = input.mode;
544
+ this.credentials = input.credentials;
545
+ this.cache = input.cache;
546
+ this.redirect = input.redirect;
547
+ this.referrer = input.referrer;
548
+ this.referrerPolicy = input.referrerPolicy;
549
+ this.integrity = input.integrity;
550
+ this.keepalive = input.keepalive;
551
+ this.signal = input.signal;
552
+ this.duplex = input.duplex;
553
+ this.destination = input.destination;
554
+ }
555
+ // Override with init options if provided
556
+ // Set method
557
+ if (init?.method) {
558
+ this.method = init.method.toUpperCase();
559
+ }
560
+ else if (typeof this.method !== 'string') {
561
+ // Fallback to default for string input case
562
+ this.method = 'GET';
563
+ }
564
+ // Set headers
565
+ if (init?.headers) {
566
+ this.headers = new vmGlobalThis.Headers(init.headers);
567
+ }
568
+ else if (typeof input === 'string' ||
569
+ input instanceof vmGlobalThis.URL) {
570
+ // For string/URL input, create empty headers
571
+ this.headers = new vmGlobalThis.Headers();
572
+ }
573
+ // Set other properties with init values or defaults
574
+ if (init?.mode !== undefined) {
575
+ this.mode = init.mode;
576
+ }
577
+ else if (typeof this.mode !== 'string') {
578
+ this.mode = 'cors';
579
+ }
580
+ if (init?.credentials !== undefined) {
581
+ this.credentials = init.credentials;
582
+ }
583
+ else if (typeof this.credentials !== 'string') {
584
+ this.credentials = 'same-origin';
585
+ }
586
+ // `any` cast here because @types/node v22 does not yet have `cache`
587
+ if (init?.cache !== undefined) {
588
+ this.cache = init.cache;
589
+ }
590
+ else if (typeof this.cache !== 'string') {
591
+ this.cache = 'default';
592
+ }
593
+ if (init?.redirect !== undefined) {
594
+ this.redirect = init.redirect;
595
+ }
596
+ else if (typeof this.redirect !== 'string') {
597
+ this.redirect = 'follow';
598
+ }
599
+ if (init?.referrer !== undefined) {
600
+ this.referrer = init.referrer;
601
+ }
602
+ else if (typeof this.referrer !== 'string') {
603
+ this.referrer = 'about:client';
604
+ }
605
+ if (init?.referrerPolicy !== undefined) {
606
+ this.referrerPolicy = init.referrerPolicy;
607
+ }
608
+ else if (typeof this.referrerPolicy !== 'string') {
609
+ this.referrerPolicy = '';
610
+ }
611
+ if (init?.integrity !== undefined) {
612
+ this.integrity = init.integrity;
613
+ }
614
+ else if (typeof this.integrity !== 'string') {
615
+ this.integrity = '';
616
+ }
617
+ if (init?.keepalive !== undefined) {
618
+ this.keepalive = init.keepalive;
619
+ }
620
+ else if (typeof this.keepalive !== 'boolean') {
621
+ this.keepalive = false;
622
+ }
623
+ if (init?.signal !== undefined) {
624
+ // @ts-expect-error - AbortSignal stub
625
+ this.signal = init.signal;
626
+ }
627
+ else if (!this.signal) {
628
+ // @ts-expect-error - AbortSignal stub
629
+ this.signal = { aborted: false };
630
+ }
631
+ if (!this.duplex) {
632
+ this.duplex = 'half';
633
+ }
634
+ if (!this.destination) {
635
+ this.destination = 'document';
636
+ }
637
+ const body = init?.body;
638
+ // Validate that GET/HEAD methods don't have a body
639
+ if (body !== null &&
640
+ body !== undefined &&
641
+ (this.method === 'GET' || this.method === 'HEAD')) {
642
+ throw new TypeError(`Request with GET/HEAD method cannot have body.`);
409
643
  }
410
- clone() {
411
- ENOTSUP();
412
- }
413
- get bodyUsed() {
414
- return false;
415
- }
416
- // TODO: implement these
417
- blob;
418
- formData;
419
- arrayBuffer;
420
- json;
421
- text;
422
- async bytes() {
423
- return new Uint8Array(await this.arrayBuffer());
424
- }
425
- }
426
- vmGlobalThis.Request = Request;
427
- Object.defineProperties(Request.prototype, {
428
- arrayBuffer: {
429
- value: useStep('__builtin_response_array_buffer'),
430
- writable: true,
431
- configurable: true,
432
- },
433
- json: {
434
- value: useStep('__builtin_response_json'),
435
- writable: true,
436
- configurable: true,
437
- },
438
- text: {
439
- value: useStep('__builtin_response_text'),
440
- writable: true,
441
- configurable: true,
442
- },
443
- });
444
- class Response {
445
- type;
446
- url;
447
- status;
448
- statusText;
449
- body;
450
- headers;
451
- redirected;
452
- constructor(body, init) {
453
- this.status = init?.status ?? 200;
454
- this.statusText = init?.statusText ?? '';
455
- this.headers = new vmGlobalThis.Headers(init?.headers);
456
- this.type = 'default';
457
- this.url = '';
458
- this.redirected = false;
459
- // Validate that null-body status codes don't have a body
460
- // Per HTTP spec: 204 (No Content), 205 (Reset Content), and 304 (Not Modified)
461
- if (body !== null &&
462
- body !== undefined &&
463
- (this.status === 204 || this.status === 205 || this.status === 304)) {
464
- throw new TypeError(`Response constructor: Invalid response status code ${this.status}`);
465
- }
466
- // Store the original BodyInit for serialization
467
- if (body !== null && body !== undefined) {
468
- // Create a "fake" ReadableStream that stores the original body
469
- // This avoids doing async work during workflow replay
470
- this.body = Object.create(vmGlobalThis.ReadableStream.prototype, {
471
- [BODY_INIT_SYMBOL]: {
472
- value: body,
473
- writable: false,
474
- },
475
- });
476
- }
477
- else {
478
- this.body = null;
479
- }
480
- }
481
- // TODO: implement these
482
- clone;
483
- blob;
484
- formData;
485
- get ok() {
486
- return this.status >= 200 && this.status < 300;
487
- }
488
- get bodyUsed() {
489
- return false;
490
- }
491
- arrayBuffer;
492
- json;
493
- text;
494
- async bytes() {
495
- return new Uint8Array(await this.arrayBuffer());
496
- }
497
- static json(data, init) {
498
- const body = JSON.stringify(data);
499
- const headers = new vmGlobalThis.Headers(init?.headers);
500
- if (!headers.has('content-type')) {
501
- headers.set('content-type', 'application/json');
502
- }
503
- return new Response(body, { ...init, headers });
504
- }
505
- static error() {
506
- ENOTSUP();
507
- }
508
- static redirect(url, status = 302) {
509
- // Validate status code - only specific redirect codes are allowed
510
- if (![301, 302, 303, 307, 308].includes(status)) {
511
- throw new RangeError(`Invalid redirect status code: ${status}. Must be one of: 301, 302, 303, 307, 308`);
512
- }
513
- // Create response with Location header
514
- const headers = new vmGlobalThis.Headers();
515
- headers.set('Location', String(url));
516
- const response = Object.create(Response.prototype);
517
- response.status = status;
518
- response.statusText = '';
519
- response.headers = headers;
520
- response.body = null;
521
- response.type = 'default';
522
- response.url = '';
523
- response.redirected = false;
524
- return response;
525
- }
526
- }
527
- vmGlobalThis.Response = Response;
528
- Object.defineProperties(Response.prototype, {
529
- arrayBuffer: {
530
- value: useStep('__builtin_response_array_buffer'),
531
- writable: true,
532
- configurable: true,
533
- },
534
- json: {
535
- value: useStep('__builtin_response_json'),
536
- writable: true,
537
- configurable: true,
538
- },
539
- text: {
540
- value: useStep('__builtin_response_text'),
541
- writable: true,
542
- configurable: true,
543
- },
544
- });
545
- class ReadableStream {
546
- constructor() {
547
- ENOTSUP();
548
- }
549
- get locked() {
550
- return false;
644
+ // Store the original BodyInit for serialization
645
+ if (body !== null && body !== undefined) {
646
+ // Create a "fake" ReadableStream that stores the original body
647
+ // This avoids doing async work during workflow replay
648
+ this.body = Object.create(vmGlobalThis.ReadableStream.prototype, {
649
+ [BODY_INIT_SYMBOL]: {
650
+ value: body,
651
+ writable: false,
652
+ },
653
+ });
551
654
  }
552
- cancel() {
553
- ENOTSUP();
554
- }
555
- getReader() {
556
- ENOTSUP();
557
- }
558
- pipeThrough() {
559
- ENOTSUP();
560
- }
561
- pipeTo() {
562
- ENOTSUP();
563
- }
564
- tee() {
565
- ENOTSUP();
566
- }
567
- values() {
568
- ENOTSUP();
569
- }
570
- static from() {
571
- ENOTSUP();
572
- }
573
- [Symbol.asyncIterator]() {
574
- ENOTSUP();
655
+ else {
656
+ this.body = null;
575
657
  }
576
658
  }
577
- vmGlobalThis.ReadableStream = ReadableStream;
578
- class WritableStream {
579
- constructor() {
580
- ENOTSUP();
581
- }
582
- get locked() {
583
- return false;
584
- }
585
- abort() {
586
- ENOTSUP();
587
- }
588
- close() {
589
- ENOTSUP();
590
- }
591
- getWriter() {
592
- ENOTSUP();
659
+ clone() {
660
+ ENOTSUP();
661
+ }
662
+ get bodyUsed() {
663
+ return false;
664
+ }
665
+ // TODO: implement these
666
+ blob;
667
+ formData;
668
+ arrayBuffer;
669
+ json;
670
+ text;
671
+ async bytes() {
672
+ return new Uint8Array(await this.arrayBuffer());
673
+ }
674
+ }
675
+ vmGlobalThis.Request = Request;
676
+ Object.defineProperties(Request.prototype, {
677
+ arrayBuffer: {
678
+ value: useStep('__builtin_response_array_buffer'),
679
+ writable: true,
680
+ configurable: true,
681
+ },
682
+ json: {
683
+ value: useStep('__builtin_response_json'),
684
+ writable: true,
685
+ configurable: true,
686
+ },
687
+ text: {
688
+ value: useStep('__builtin_response_text'),
689
+ writable: true,
690
+ configurable: true,
691
+ },
692
+ });
693
+ class Response {
694
+ type;
695
+ url;
696
+ status;
697
+ statusText;
698
+ body;
699
+ headers;
700
+ redirected;
701
+ constructor(body, init) {
702
+ this.status = init?.status ?? 200;
703
+ this.statusText = init?.statusText ?? '';
704
+ this.headers = new vmGlobalThis.Headers(init?.headers);
705
+ this.type = 'default';
706
+ this.url = '';
707
+ this.redirected = false;
708
+ // Validate that null-body status codes don't have a body
709
+ // Per HTTP spec: 204 (No Content), 205 (Reset Content), and 304 (Not Modified)
710
+ if (body !== null &&
711
+ body !== undefined &&
712
+ (this.status === 204 || this.status === 205 || this.status === 304)) {
713
+ throw new TypeError(`Response constructor: Invalid response status code ${this.status}`);
714
+ }
715
+ // Store the original BodyInit for serialization
716
+ if (body !== null && body !== undefined) {
717
+ // Create a "fake" ReadableStream that stores the original body
718
+ // This avoids doing async work during workflow replay
719
+ this.body = Object.create(vmGlobalThis.ReadableStream.prototype, {
720
+ [BODY_INIT_SYMBOL]: {
721
+ value: body,
722
+ writable: false,
723
+ },
724
+ });
725
+ }
726
+ else {
727
+ this.body = null;
593
728
  }
594
729
  }
595
- vmGlobalThis.WritableStream = WritableStream;
596
- class TransformStream {
597
- readable;
598
- writable;
599
- constructor() {
600
- ENOTSUP();
730
+ // TODO: implement these
731
+ clone;
732
+ blob;
733
+ formData;
734
+ get ok() {
735
+ return this.status >= 200 && this.status < 300;
736
+ }
737
+ get bodyUsed() {
738
+ return false;
739
+ }
740
+ arrayBuffer;
741
+ json;
742
+ text;
743
+ async bytes() {
744
+ return new Uint8Array(await this.arrayBuffer());
745
+ }
746
+ static json(data, init) {
747
+ const body = JSON.stringify(data);
748
+ const headers = new vmGlobalThis.Headers(init?.headers);
749
+ if (!headers.has('content-type')) {
750
+ headers.set('content-type', 'application/json');
601
751
  }
752
+ return new Response(body, { ...init, headers });
602
753
  }
603
- vmGlobalThis.TransformStream = TransformStream;
604
- // Eventually we'll probably want to provide our own `console` object,
605
- // but for now we'll just expose the global one.
606
- vmGlobalThis.console = globalThis.console;
607
- // HACK: propagate symbol needed for AI gateway usage
608
- const SYMBOL_FOR_REQ_CONTEXT = Symbol.for('@vercel/request-context');
609
- // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
610
- vmGlobalThis[SYMBOL_FOR_REQ_CONTEXT] = globalThis[SYMBOL_FOR_REQ_CONTEXT];
611
- // Get a reference to the user-defined workflow function.
612
- // The filename parameter ensures stack traces show a meaningful name
613
- // (e.g., "example/workflows/99_e2e.ts") instead of "evalmachine.<anonymous>".
614
- const parsedName = parseWorkflowName(workflowRun.workflowName);
615
- const filename = parsedName?.moduleSpecifier || workflowRun.workflowName;
616
- const workflowFn = runInContext(`${workflowCode}; globalThis.__private_workflows?.get(${JSON.stringify(workflowRun.workflowName)})`, context, { filename });
617
- if (typeof workflowFn !== 'function') {
618
- throw new WorkflowNotRegisteredError(workflowRun.workflowName);
754
+ static error() {
755
+ ENOTSUP();
619
756
  }
620
- // Chain workflow argument hydration onto the promiseQueue so that the
621
- // unconsumed event check (which waits for the queue to drain) doesn't
622
- // fire during the async gap between run_started consumption and the
623
- // workflow function subscribing its first step callbacks.
624
- let args = [];
625
- workflowContext.promiseQueue = workflowContext.promiseQueue.then(async () => {
626
- args = await hydrateWorkflowArguments(workflowRun.input, workflowRun.runId, encryptionKey, vmGlobalThis);
627
- });
628
- await workflowContext.promiseQueue;
629
- span?.setAttributes({
630
- ...Attribute.WorkflowArgumentsCount(args.length),
757
+ static redirect(url, status = 302) {
758
+ // Validate status code - only specific redirect codes are allowed
759
+ if (![301, 302, 303, 307, 308].includes(status)) {
760
+ throw new RangeError(`Invalid redirect status code: ${status}. Must be one of: 301, 302, 303, 307, 308`);
761
+ }
762
+ // Create response with Location header
763
+ const headers = new vmGlobalThis.Headers();
764
+ headers.set('Location', String(url));
765
+ const response = Object.create(Response.prototype);
766
+ response.status = status;
767
+ response.statusText = '';
768
+ response.headers = headers;
769
+ response.body = null;
770
+ response.type = 'default';
771
+ response.url = '';
772
+ response.redirected = false;
773
+ return response;
774
+ }
775
+ }
776
+ vmGlobalThis.Response = Response;
777
+ Object.defineProperties(Response.prototype, {
778
+ arrayBuffer: {
779
+ value: useStep('__builtin_response_array_buffer'),
780
+ writable: true,
781
+ configurable: true,
782
+ },
783
+ json: {
784
+ value: useStep('__builtin_response_json'),
785
+ writable: true,
786
+ configurable: true,
787
+ },
788
+ text: {
789
+ value: useStep('__builtin_response_text'),
790
+ writable: true,
791
+ configurable: true,
792
+ },
793
+ });
794
+ class ReadableStream {
795
+ constructor() {
796
+ ENOTSUP();
797
+ }
798
+ get locked() {
799
+ return false;
800
+ }
801
+ cancel() {
802
+ ENOTSUP();
803
+ }
804
+ getReader() {
805
+ ENOTSUP();
806
+ }
807
+ pipeThrough() {
808
+ ENOTSUP();
809
+ }
810
+ pipeTo() {
811
+ ENOTSUP();
812
+ }
813
+ tee() {
814
+ ENOTSUP();
815
+ }
816
+ values() {
817
+ ENOTSUP();
818
+ }
819
+ static from() {
820
+ ENOTSUP();
821
+ }
822
+ [Symbol.asyncIterator]() {
823
+ ENOTSUP();
824
+ }
825
+ }
826
+ vmGlobalThis.ReadableStream = ReadableStream;
827
+ class WritableStream {
828
+ constructor() {
829
+ ENOTSUP();
830
+ }
831
+ get locked() {
832
+ return false;
833
+ }
834
+ abort() {
835
+ ENOTSUP();
836
+ }
837
+ close() {
838
+ ENOTSUP();
839
+ }
840
+ getWriter() {
841
+ ENOTSUP();
842
+ }
843
+ }
844
+ vmGlobalThis.WritableStream = WritableStream;
845
+ class TransformStream {
846
+ readable;
847
+ writable;
848
+ constructor() {
849
+ ENOTSUP();
850
+ }
851
+ }
852
+ vmGlobalThis.TransformStream = TransformStream;
853
+ vmGlobalThis.console = globalThis.console;
854
+ // Expose the request-context symbol required by AI Gateway.
855
+ const SYMBOL_FOR_REQ_CONTEXT = Symbol.for('@vercel/request-context');
856
+ // @ts-expect-error - `@types/node` says symbol is not valid, but it does work
857
+ vmGlobalThis[SYMBOL_FOR_REQ_CONTEXT] = globalThis[SYMBOL_FOR_REQ_CONTEXT];
858
+ endVmTrace();
859
+ // Reuse compiled scripts by `(code, filename)`: compilation is deterministic
860
+ // and the filename preserves workflow source attribution in stack traces.
861
+ // The bundle registers workflows on `globalThis.__private_workflows`.
862
+ const { bundleScript, workflowLookupScript } = compiledWorkflowScripts ??
863
+ (await compileWorkflowBundle(workflowCode, workflowRun.workflowName));
864
+ const workflowFn = await trace('workflow.bundle.evaluate', async () => {
865
+ bundleScript.runInContext(context);
866
+ return workflowLookupScript.runInContext(context);
867
+ });
868
+ if (typeof workflowFn !== 'function') {
869
+ throw new WorkflowNotRegisteredError(workflowRun.workflowName);
870
+ }
871
+ // Chain workflow argument hydration onto the promiseQueue so that the
872
+ // unconsumed event check (which waits for the queue to drain) doesn't
873
+ // fire during the async gap between run_started consumption and the
874
+ // workflow function subscribing its first step callbacks.
875
+ let args = [];
876
+ workflowContext.promiseQueue = workflowContext.promiseQueue.then(async () => {
877
+ // Include any residual payload preparation plus VM-local deserialization
878
+ // in the blocking boundary.
879
+ args = await trace('workflow.input.hydrate', async () => {
880
+ const prepared = await replayPayloadCache.prepareWorkflowInput(workflowRun);
881
+ return hydrateWorkflowArguments(workflowRun.input, workflowRun.runId, encryptionKey, vmGlobalThis, {}, prepared);
631
882
  });
632
- // Invoke user workflow
883
+ });
884
+ await workflowContext.promiseQueue;
885
+ const failWorkflow = async (error) => {
886
+ // Control-flow signals are handled by the runtime and do not mean the
887
+ // workflow has terminally failed. `onWorkflowError` usually already moved
888
+ // the state machine, but a divergence can also arrive via a step
889
+ // promise's direct rejection (bypassing `onWorkflowError`); demote so
890
+ // every control-flow path converges on `replay` and a later resume falls
891
+ // back instead of throwing.
892
+ if (WorkflowSuspension.is(error) || ReplayDivergenceError.is(error)) {
893
+ if (state.type === 'running')
894
+ state = { type: 'replay' };
895
+ throw error;
896
+ }
897
+ state = { type: 'completed' };
898
+ await drainPendingQueueItems(workflowRun.runId, workflowContext.invocationsQueue, vmGlobalThis, workflowRun, 'failed', runReadyBarrier);
899
+ throw error;
900
+ };
901
+ const waitForExecution = async (workflowBody, interruption) => {
902
+ let result;
633
903
  try {
634
- const result = await Promise.race([
635
- workflowFn(...args),
636
- workflowDiscontinuation.promise,
637
- ]);
638
- const dehydrated = await dehydrateWorkflowReturnValue(result, workflowRun.runId, encryptionKey, vmGlobalThis);
639
- span?.setAttributes({
640
- ...Attribute.WorkflowResultType(typeof result),
641
- });
642
- await drainPendingQueueItems(workflowRun.runId, workflowContext.invocationsQueue, vmGlobalThis, workflowRun, 'completed');
643
- return dehydrated;
904
+ result = await Promise.race([workflowBody, interruption.promise]);
644
905
  }
645
- catch (err) {
646
- // Let WorkflowSuspension propagate handled separately by the runtime
647
- if (WorkflowSuspension.is(err)) {
648
- throw err;
649
- }
650
- await drainPendingQueueItems(workflowRun.runId, workflowContext.invocationsQueue, vmGlobalThis, workflowRun, 'failed');
651
- throw err;
906
+ catch (error) {
907
+ if (state.type === 'suspended' && error === state.suspension) {
908
+ return {
909
+ type: 'suspended',
910
+ suspension: state.suspension,
911
+ session,
912
+ // A suspension is not a settling point: the consumer for something
913
+ // held may well be registered by the replay that follows this one.
914
+ // So it is carried out for the span instead of being judged here.
915
+ parked: eventsConsumer.parkedSummary,
916
+ };
917
+ }
918
+ return failWorkflow(error);
652
919
  }
653
- });
920
+ state = { type: 'completed' };
921
+ // The consumer walks past events whose type carries no ordering claim and
922
+ // holds them for a consumer it expects a later `subscribe()` to register.
923
+ // The workflow function returning is the point where that expectation is
924
+ // settled: nothing more will subscribe, so anything still held was never
925
+ // anyone's, and completing here would drop it silently.
926
+ const stranded = eventsConsumer.strandedEvent;
927
+ if (stranded) {
928
+ return failWorkflow(new ReplayDivergenceError(`Replay finished without consuming event: eventType=${stranded.eventType}, correlationId=${stranded.correlationId}, eventId=${stranded.eventId}.`, { eventId: stranded.eventId }));
929
+ }
930
+ try {
931
+ const output = await dehydrateWorkflowReturnValue(result, workflowRun.runId, encryptionKey, vmGlobalThis, false,
932
+ // Only compression-capable runs (spec >= 5) may write compressed
933
+ // payloads. The serializer uses zstd when supported and may use gzip.
934
+ (workflowRun.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION);
935
+ await drainPendingQueueItems(workflowRun.runId, workflowContext.invocationsQueue, vmGlobalThis, workflowRun, 'completed', runReadyBarrier);
936
+ return { type: 'completed', output, resultType: typeof result };
937
+ }
938
+ catch (error) {
939
+ return failWorkflow(error);
940
+ }
941
+ };
942
+ const workflowTraceContext = await createRefreshableTraceContext();
943
+ const replayTrace = await startTraceSpan('workflow.replay.execute');
944
+ const workflowBody = workflowTraceContext.run(async () => workflowFn(...args));
945
+ const session = {
946
+ workflowRun,
947
+ argumentCount: args.length,
948
+ async resume(nextEvents) {
949
+ switch (state.type) {
950
+ case 'suspended': {
951
+ // The full O(known events) prefix compare is required: the runtime
952
+ // usually grows one array in place, but its wait-completion and
953
+ // stale-reload paths REPLACE the array with a fresh full fetch, so
954
+ // a rewritten prefix is a real input, not paranoia. The compares
955
+ // are cheap string equality and dwarfed by the replay they avoid.
956
+ const knownEvents = eventsConsumer.events;
957
+ const isStrictExtension = nextEvents.length > knownEvents.length &&
958
+ knownEvents.every((event, index) => event.eventId === nextEvents[index].eventId);
959
+ if (!isStrictExtension) {
960
+ state = { type: 'replay' };
961
+ return { type: 'replay' };
962
+ }
963
+ const interruption = withResolvers();
964
+ state = { type: 'running', interruption };
965
+ workflowContext.suspensionGeneration++;
966
+ workflowTraceContext.refresh();
967
+ eventsConsumer.append(nextEvents.slice(knownEvents.length));
968
+ return waitForExecution(workflowBody, interruption);
969
+ }
970
+ case 'replay':
971
+ return { type: 'replay' };
972
+ case 'completed':
973
+ case 'running':
974
+ throw new WorkflowRuntimeError(`Cannot resume ${state.type} workflow "${workflowRun.runId}"`);
975
+ }
976
+ state;
977
+ },
978
+ };
979
+ // The replay span measures the user function without becoming its ambient
980
+ // context. The workflow promise stays pending across retained resumes, so an
981
+ // active replay span here would remain captured after that span has ended.
982
+ const execution = waitForExecution(workflowBody, initialInterruption);
983
+ void execution.then(replayTrace.end, replayTrace.fail);
984
+ return {
985
+ session,
986
+ execution,
987
+ };
654
988
  }
655
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN2QyxPQUFPLEVBQ0wsV0FBVyxFQUNYLDBCQUEwQixFQUMxQixvQkFBb0IsR0FDckIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRS9ELE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV4QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFM0UsT0FBTyxFQUFFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMxRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU5QyxPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLHdCQUF3QixHQUN6QixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDMUMsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixXQUFXLEVBQ1gsb0JBQW9CLEVBQ3BCLHNCQUFzQixFQUN0QixjQUFjLEVBQ2QsaUJBQWlCLEdBQ2xCLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sS0FBSyxTQUFTLE1BQU0scUNBQXFDLENB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QWdCLEVBQ2hDLFlBQVksRUFDWixXQUFXLEVBQ1gsUUFBUSxDQUNULENBQUM7WUFFRixNQUFNLEdBQUcsQ0FBQztRQUNaLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBydW5JbkNvbnRleHQgfSBmcm9tICdub2RlOnZtJztcbmltcG9ydCB7XG4gIEVSUk9SX1NMVUdTLFxuICBXb3JrZmxvd05vdFJlZ2lzdGVyZWRFcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgd2l0aFJlc29sdmVycyB9IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgeyBnZXRQb3J0TGF6eSB9IGZyb20gJy4vcnVudGltZS9nZXQtcG9ydC1sYXp5LmpzJztcbmltcG9ydCB7IHBhcnNlV29ya2Zsb3dOYW1lIH0gZnJvbSAnQHdvcmtmbG93L3V0aWxzL3BhcnNlLW5hbWUnO1xuaW1wb3J0IHR5cGUgeyBFdmVudCwgV29ya2Zsb3dSdW4gfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0ICogYXMgbmFub2lkIGZyb20gJ25hbm9pZCc7XG5pbXBvcnQgeyBtb25vdG9uaWNGYWN0b3J5IH0gZnJvbSAndWxpZCc7XG5pbXBvcnQgdHlwZSB7IENyeXB0b0tleSB9IGZyb20gJy4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgeyBFdmVudENvbnN1bWVyUmVzdWx0LCBFdmVudHNDb25zdW1lciB9IGZyb20gJy4vZXZlbnRzLWNvbnN1bWVyLmpzJztcbmltcG9ydCB0eXBlIHsgUXVldWVJdGVtIH0gZnJvbSAnLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgRU5PVFNVUCwgV29ya2Zsb3dTdXNwZW5zaW9uIH0gZnJvbSAnLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGhhbmRsZVN1c3BlbnNpb24gfSBmcm9tICcuL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLmpzJztcbmltcG9ydCB7IGdldFdvcmxkIH0gZnJvbSAnLi9ydW50aW1lL3dvcmxkLmpzJztcbmltcG9ydCB0eXBlIHsgV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0IH0gZnJvbSAnLi9wcml2YXRlLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVdvcmtmbG93UmV0dXJuVmFsdWUsXG4gIGh5ZHJhdGVXb3JrZmxvd0FyZ3VtZW50cyxcbn0gZnJvbSAnLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IGNyZWF0ZVVzZVN0ZXAgfSBmcm9tICcuL3N0ZXAuanMnO1xuaW1wb3J0IHtcbiAgQk9EWV9JTklUX1NZTUJPTCxcbiAgU1RBQkxFX1VMSUQsXG4gIFdPUktGTE9XX0NSRUFURV9IT09LLFxuICBXT1JLRkxPV19HRVRfU1RSRUFNX0lELFxuICBXT1JLRkxPV19TTEVFUCxcbiAgV09SS0ZMT1dfVVNFX1NURVAsXG59IGZyb20gJy4vc3ltYm9scy5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgdHJhY2UgfSBmcm9tICcuL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JrZmxvd1J1blN0cmVhbUlkIH0gZnJvbSAnLi91dGlsLmpzJztcbmltcG9ydCB7IGNyZWF0ZUNvbnRleHQgfSBmcm9tICcuL3ZtL2luZGV4LmpzJztcbmltcG9ydCB0eXBlIHsgV29ya2Zsb3dNZXRhZGF0YSB9IGZyb20gJy4vd29ya2Zsb3cvZ2V0LXdvcmtmbG93LW1ldGFkYXRhLmpzJztcbmltcG9ydCB7IFdPUktGTE9XX0NPTlRFWFRfU1lNQk9MIH0gZnJvbSAnLi93b3JrZmxvdy9nZXQtd29ya2Zsb3ctbWV0YWRhdGEuanMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlQWJvcnRTaWduYWxTdGF0aWNzLFxuICBjcmVhdGVDcmVhdGVBYm9ydENvbnRyb2xsZXIsXG59IGZyb20gJy4vd29ya2Zsb3cvYWJvcnQtY29udHJvbGxlci5qcyc7XG5pbXBvcnQgeyBjcmVhdGVDcmVhdGVIb29rIH0gZnJvbSAnLi93b3JrZmxvdy9ob29rLmpzJztcbmltcG9ydCB7IGNyZWF0ZVNsZWVwIH0gZnJvbSAnLi93b3JrZmxvdy9zbGVlcC5qcyc7XG5cbi8qKlxuICogRHJhaW4gcGVuZGluZyBxdWV1ZSBpdGVtcyBhdCB3b3JrZmxvdyBjb21wbGV0aW9uIChzdWNjZXNzIG9yIGZhaWx1cmUpLlxuICpcbiAqIFRyZWF0cyBlbmQtb2YtcnVuIGxpa2UgYSBmaW5hbCBzdXNwZW5zaW9uOiBhbnkgb3BlcmF0aW9uIHRoZSB3b3JrZmxvdyBjb2RlXG4gKiBzcGF3bmVkIGJ1dCBkaWRuJ3QgYGF3YWl0YCDigJQgYWJvcnQgaG9vayByZXN1bWVzLCBob29rIGNyZWF0aW9ucy9kaXNwb3NhbHMsXG4gKiBzbGVlcCB3YWl0cywgc3RlcCBxdWV1ZWluZ3Mg4oCUIGdldHMgY29tbWl0dGVkIHRvIHRoZSBldmVudCBsb2cgdmlhIHRoZVxuICogc3VzcGVuc2lvbiBoYW5kbGVyIGJlZm9yZSB0aGUgcnVuIGlzIG1hcmtlZCB0ZXJtaW5hbC5cbiAqXG4gKiBUaGlzIG1hdGNoZXMgbm9ybWFsIEpTIHNlbWFudGljcyB3aGVyZSBgc2V0VGltZW91dChmbiwgLi4uKWAgZXRjLiBjb250aW51ZVxuICogcnVubmluZyBhZnRlciB0aGUgc3Vycm91bmRpbmcgZnVuY3Rpb24gcmV0dXJucy4gTW9zdCBpbXBvcnRhbnRseSwgaXQgZW5zdXJlc1xuICogYGNvbnRyb2xsZXIuYWJvcnQoKWAgY2FsbGVkIGFzIHRoZSBsYXN0IHN0YXRlbWVudCBvZiBhIHdvcmtmbG93IGFjdHVhbGx5XG4gKiBwcm9wYWdhdGVzIHRvIGluLWZsaWdodCBzdGVwcyBvbiBvdGhlciBjb21wdXRlIGluc3RhbmNlcyDigJQgd2l0aG91dCB0aGlzLFxuICogdGhlIGFib3J0IGhvb2sgaXMgY3JlYXRlZCBidXQgbmV2ZXIgcmVzdW1lZCBhbmQgdGhlIGNhbmNlbGxhdGlvbiBuZXZlclxuICogcmVhY2hlcyB0aGUgcnVubmluZyBzdGVwLlxuICpcbiAqIERyYWluIGZhaWx1cmVzIGFyZSBzd2FsbG93ZWQ6IHRoZSB3b3JrZmxvdydzIG93biBvdXRjb21lICh0aGUgdXNlcidzIHJldHVyblxuICogdmFsdWUgb3IgdGhyb3duIGVycm9yKSBpcyB0aGUgc291cmNlIG9mIHRydXRoOyBzZWNvbmRhcnkgY2xlYW51cCB0aGF0IGZhaWxzXG4gKiBzaG91bGRuJ3QgY2hhbmdlIHRoZSBydW4ncyB0ZXJtaW5hbCBzdGF0ZS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZHJhaW5QZW5kaW5nUXVldWVJdGVtcyhcbiAgcnVuSWQ6IHN0cmluZyxcbiAgcGVuZGluZ1F1ZXVlOiBNYXA8c3RyaW5nLCBRdWV1ZUl0ZW0+LFxuICB2bUdsb2JhbFRoaXM6IHR5cGVvZiBnbG9iYWxUaGlzLFxuICB3b3JrZmxvd1J1bjogV29ya2Zsb3dSdW4sXG4gIG91dGNvbWU6ICdjb21wbGV0ZWQnIHwgJ2ZhaWxlZCdcbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAocGVuZGluZ1F1ZXVlLnNpemUgPT09IDApIHJldHVybjtcbiAgLy8gSW1wbGljaXRseSBkaXNwb3NlIGFueSBhYm9ydCBob29rcyAoc3lzdGVtIGhvb2tzKSB0aGF0IGFyZSBzdGlsbCBhbGl2ZSBhdFxuICAvLyB3b3JrZmxvdyBjb21wbGV0aW9uIHNvIHRoZXkgZG9uJ3QgbGVhayByb3dzIGluIHRoZSBob29rcyB0YWJsZSBmb3IgdGhlXG4gIC8vIHJ1bidzIGxpZmV0aW1lLiBTa2lwIGhvb2tzIHRoYXQgYWxyZWFkeSBoYXZlIGFuIGFib3J0IGluIGZsaWdodCDigJQgdGhvc2VcbiAgLy8gd2lsbCBlbWl0IGhvb2tfcmVjZWl2ZWQgdmlhIHRoZSBhYm9ydCBwcm9jZXNzaW5nIHBhdGguIFVzZXIgaG9va3NcbiAgLy8gKGlzU3lzdGVtICE9PSB0cnVlKSBhcmUgaW50ZW50aW9uYWxseSBsZWZ0IGFsb25lOiB0aGVpciBsaWZldGltZSBpc1xuICAvLyBtYW5hZ2VkIGJ5IHRoZSB1c2VyJ3MgY29kZSwgbm90IHRoZSBydW50aW1lLlxuICBmb3IgKGNvbnN0IGl0ZW0gb2YgcGVuZGluZ1F1ZXVlLnZhbHVlcygpKSB7XG4gICAgaWYgKFxuICAgICAgaXRlbS50eXBlID09PSAnaG9vaycgJiZcbiAgICAgIGl0ZW0uaXNTeXN0ZW0gJiZcbiAgICAgICFpdGVtLmRpc3Bvc2VkICYmXG4gICAgICAhaXRlbS5hYm9ydFJlcXVlc3RlZFxuICAgICkge1xuICAgICAgaXRlbS5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuICB9XG4gIHRyeSB7XG4gICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgIGNvbnN0IHN5bnRoZXNpemVkID0gbmV3IFdvcmtmbG93U3VzcGVuc2lvbihwZW5kaW5nUXVldWUsIHZtR2xvYmFsVGhpcyk7XG4gICAgYXdhaXQgaGFuZGxlU3VzcGVuc2lvbih7XG4gICAgICBzdXNwZW5zaW9uOiBzeW50aGVzaXplZCxcbiAgICAgIHdvcmxkLFxuICAgICAgcnVuOiB3b3JrZmxvd1J1bixcbiAgICB9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgYEZhaWxlZCB0byBkcmFpbiBwZW5kaW5nIHF1ZXVlIGl0ZW1zIGZvciAke291dGNvbWV9IHdvcmtmbG93IHJ1bmAsXG4gICAgICB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuV29ya2Zsb3coXG4gIHdvcmtmbG93Q29kZTogc3RyaW5nLFxuICB3b3JrZmxvd1J1bjogV29ya2Zsb3dSdW4sXG4gIGV2ZW50czogRXZlbnRbXSxcbiAgZW5jcnlwdGlvbktleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIHJldHVybiB0cmFjZShgd29ya2Zsb3cucnVuICR7d29ya2Zsb3dSdW4ud29ya2Zsb3dOYW1lfWAsIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHdvcmtmbG93UnVuLndvcmtmbG93TmFtZSksXG4gICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5JZCh3b3JrZmxvd1J1bi5ydW5JZCksXG4gICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5TdGF0dXMod29ya2Zsb3dSdW4uc3RhdHVzKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0V2ZW50c0NvdW50KGV2ZW50cy5sZW5ndGgpLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc3RhcnRlZEF0ID0gd29ya2Zsb3dSdW4uc3RhcnRlZEF0O1xuICAgIGlmICghc3RhcnRlZEF0KSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgIGBXb3JrZmxvdyBydW4gXCIke3dvcmtmbG93UnVuLnJ1bklkfVwiIGhhcyBubyBcInN0YXJ0ZWRBdFwiIHRpbWVzdGFtcCAoc2hvdWxkIG5vdCBoYXBwZW4pYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgdGhlIHBvcnQgYmVmb3JlIGNyZWF0aW5nIFZNIGNvbnRleHQgdG8gYXZvaWQgYXN5bmMgb3BlcmF0aW9uc1xuICAgIC8vIGFmZmVjdGluZyB0aGUgZGV0ZXJtaW5pc3RpYyB0aW1lc3RhbXBcbiAgICBjb25zdCBpc1ZlcmNlbCA9IHByb2Nlc3MuZW52LlZFUkNFTF9VUkwgIT09IHVuZGVmaW5lZDtcbiAgICAvLyBMb2FkIGdldFBvcnQgbGF6aWx5IHRvIHByZXZlbnQgVHVyYm9wYWNrIGZyb20gdHJhY2luZyBnZXQtcG9ydCdzXG4gICAgLy8gZnMgb3BzIChyZWFkZGlyLCByZWFkRmlsZSkgaW50byB0aGUgZmxvdyByb3V0ZSBidW5kbGUuXG4gICAgLy8gVXNlcyBnbG9iYWxUaGlzLl9fd2tmX2dldFBvcnQgYXMgYSBsYXp5LWluaXRpYWxpemVkIGNhY2hlIHRvIGF2b2lkXG4gICAgLy8gYnVuZGxlciBzdGF0aWMgYW5hbHlzaXMgd2hpbGUgc3RheWluZyBjb21wYXRpYmxlIHdpdGggQ0pTL0VTTS9WTS5cbiAgICBjb25zdCBwb3J0ID0gaXNWZXJjZWwgPyB1bmRlZmluZWQgOiBhd2FpdCBnZXRQb3J0TGF6eSgpO1xuXG4gICAgY29uc3Qge1xuICAgICAgY29udGV4dCxcbiAgICAgIGdsb2JhbFRoaXM6IHZtR2xvYmFsVGhpcyxcbiAgICAgIHVwZGF0ZVRpbWVzdGFtcCxcbiAgICB9ID0gY3JlYXRlQ29udGV4dCh7XG4gICAgICBzZWVkOiBgJHt3b3JrZmxvd1J1bi5ydW5JZH06JHt3b3JrZmxvd1J1bi53b3JrZmxvd05hbWV9OiR7K3N0YXJ0ZWRBdH1gLFxuICAgICAgZml4ZWRUaW1lc3RhbXA6ICtzdGFydGVkQXQsXG4gICAgfSk7XG5cbiAgICBjb25zdCB3b3JrZmxvd0Rpc2NvbnRpbnVhdGlvbiA9IHdpdGhSZXNvbHZlcnM8dm9pZD4oKTtcblxuICAgIGNvbnN0IHVsaWQgPSBtb25vdG9uaWNGYWN0b3J5KCgpID0+IHZtR2xvYmFsVGhpcy5NYXRoLnJhbmRvbSgpKTtcbiAgICBjb25zdCBnZW5lcmF0ZU5hbm9pZCA9IG5hbm9pZC5jdXN0b21SYW5kb20obmFub2lkLnVybEFscGhhYmV0LCAyMSwgKHNpemUpID0+XG4gICAgICBuZXcgVWludDhBcnJheShzaXplKS5tYXAoKCkgPT4gMjU2ICogdm1HbG9iYWxUaGlzLk1hdGgucmFuZG9tKCkpXG4gICAgKTtcblxuICAgIC8vIENyZWF0ZSBhIG11dGFibGUgaG9sZGVyIGZvciB0aGUgcHJvbWlzZSBxdWV1ZSBzbyB0aGUgRXZlbnRzQ29uc3VtZXJcbiAgICAvLyBjYW4gYWNjZXNzIHRoZSBjdXJyZW50IHF1ZXVlIHN0YXRlIHZpYSBhIGdldHRlci4gVGhlIHF1ZXVlIGlzIG11dGF0ZWRcbiAgICAvLyBieSBzdGVwL2hvb2svc2xlZXAgY2FsbGJhY2tzIGFzIGV2ZW50cyBhcmUgcHJvY2Vzc2VkLlxuICAgIGNvbnN0IHByb21pc2VRdWV1ZUhvbGRlciA9IHsgY3VycmVudDogUHJvbWlzZS5yZXNvbHZlKCkgfTtcblxuICAgIGNvbnN0IGV2ZW50c0NvbnN1bWVyID0gbmV3IEV2ZW50c0NvbnN1bWVyKGV2ZW50cywge1xuICAgICAgb25VbmNvbnN1bWVkRXZlbnQ6IChldmVudCkgPT4ge1xuICAgICAgICB3b3JrZmxvd0Rpc2NvbnRpbnVhdGlvbi5yZWplY3QoXG4gICAgICAgICAgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgYFVuY29uc3VtZWQgZXZlbnQgaW4gZXZlbnQgbG9nOiBldmVudFR5cGU9JHtldmVudC5ldmVudFR5cGV9LCBjb3JyZWxhdGlvbklkPSR7ZXZlbnQuY29ycmVsYXRpb25JZH0sIGV2ZW50SWQ9JHtldmVudC5ldmVudElkfS4gVGhpcyBpbmRpY2F0ZXMgYSBjb3JydXB0ZWQgb3IgaW52YWxpZCBldmVudCBsb2cuYCxcbiAgICAgICAgICAgIHsgc2x1ZzogRVJST1JfU0xVR1MuQ09SUlVQVEVEX0VWRU5UX0xPRyB9XG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIGdldFByb21pc2VRdWV1ZTogKCkgPT4gcHJvbWlzZVF1ZXVlSG9sZGVyLmN1cnJlbnQsXG4gICAgfSk7XG5cbiAgICBjb25zdCB3b3JrZmxvd0NvbnRleHQ6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCA9IHtcbiAgICAgIHJ1bklkOiB3b3JrZmxvd1J1bi5ydW5JZCxcbiAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICBnbG9iYWxUaGlzOiB2bUdsb2JhbFRoaXMsXG4gICAgICBvbldvcmtmbG93RXJyb3I6IHdvcmtmbG93RGlzY29udGludWF0aW9uLnJlamVjdCxcbiAgICAgIGV2ZW50c0NvbnN1bWVyLFxuICAgICAgZ2VuZXJhdGVVbGlkOiAoKSA9PiB1bGlkKCtzdGFydGVkQXQpLFxuICAgICAgZ2VuZXJhdGVOYW5vaWQsXG4gICAgICBpbnZvY2F0aW9uc1F1ZXVlOiBuZXcgTWFwKCksXG4gICAgICAvLyBVc2UgZ2V0dGVyL3NldHRlciBzbyB0aGUgRXZlbnRzQ29uc3VtZXIncyBnZXRQcm9taXNlUXVldWUoKSBhbHdheXNcbiAgICAgIC8vIHNlZXMgdGhlIGxhdGVzdCBxdWV1ZSBzdGF0ZSBhcyBpdCdzIG11dGF0ZWQgYnkgc3RlcC9ob29rL3NsZWVwIGNhbGxiYWNrcy5cbiAgICAgIGdldCBwcm9taXNlUXVldWUoKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNlUXVldWVIb2xkZXIuY3VycmVudDtcbiAgICAgIH0sXG4gICAgICBzZXQgcHJvbWlzZVF1ZXVlKHZhbHVlOiBQcm9taXNlPHZvaWQ+KSB7XG4gICAgICAgIHByb21pc2VRdWV1ZUhvbGRlci5jdXJyZW50ID0gdmFsdWU7XG4gICAgICB9LFxuICAgICAgcGVuZGluZ0RlbGl2ZXJpZXM6IDAsXG4gICAgfTtcblxuICAgIC8vIFN1YnNjcmliZSB0byB0aGUgZXZlbnRzIGxvZyB0byB1cGRhdGUgdGhlIHRpbWVzdGFtcCBpbiB0aGUgdm0gY29udGV4dFxuICAgIHdvcmtmbG93Q29udGV4dC5ldmVudHNDb25zdW1lci5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBjcmVhdGVkQXQgPSBldmVudD8uY3JlYXRlZEF0O1xuICAgICAgaWYgKGNyZWF0ZWRBdCkge1xuICAgICAgICB1cGRhdGVUaW1lc3RhbXAoK2NyZWF0ZWRBdCk7XG4gICAgICB9XG4gICAgICAvLyBOZXZlciBjb25zdW1lIGV2ZW50cyAtIHRoaXMgaXMgb25seSBhIHBhc3NpdmUgc3Vic2NyaWJlclxuICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuTm90Q29uc3VtZWQ7XG4gICAgfSk7XG5cbiAgICAvLyBDb25zdW1lIHJ1biBsaWZlY3ljbGUgZXZlbnRzIC0gdGhlc2UgYXJlIHN0cnVjdHVyYWwgZXZlbnRzIHRoYXQgZG9uJ3RcbiAgICAvLyBuZWVkIHNwZWNpYWwgaGFuZGxpbmcgaW4gdGhlIHdvcmtmbG93LCBidXQgbXVzdCBiZSBjb25zdW1lZCB0byBhZHZhbmNlXG4gICAgLy8gcGFzdCB0aGVtIGluIHRoZSBldmVudCBsb2dcbiAgICB3b3JrZmxvd0NvbnRleHQuZXZlbnRzQ29uc3VtZXIuc3Vic2NyaWJlKChldmVudCkgPT4ge1xuICAgICAgaWYgKCFldmVudCkge1xuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Ob3RDb25zdW1lZDtcbiAgICAgIH1cblxuICAgICAgLy8gQ29uc3VtZSBydW5fY3JlYXRlZCAtIGV2ZXJ5IHJ1biBoYXMgZXhhY3RseSBvbmVcbiAgICAgIGlmIChldmVudC5ldmVudFR5cGUgPT09ICdydW5fY3JlYXRlZCcpIHtcbiAgICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuQ29uc3VtZWQ7XG4gICAgICB9XG5cbiAgICAgIC8vIENvbnN1bWUgcnVuX3N0YXJ0ZWQgLSBldmVyeSBydW4gaGFzIGV4YWN0bHkgb25lXG4gICAgICBpZiAoZXZlbnQuZXZlbnRUeXBlID09PSAncnVuX3N0YXJ0ZWQnKSB7XG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0LkNvbnN1bWVkO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Ob3RDb25zdW1lZDtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZVN0ZXAgPSBjcmVhdGVVc2VTdGVwKHdvcmtmbG93Q29udGV4dCk7XG4gICAgY29uc3QgY3JlYXRlSG9vayA9IGNyZWF0ZUNyZWF0ZUhvb2sod29ya2Zsb3dDb250ZXh0KTtcbiAgICBjb25zdCBzbGVlcCA9IGNyZWF0ZVNsZWVwKHdvcmtmbG93Q29udGV4dCk7XG5cbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgICB2bUdsb2JhbFRoaXNbV09SS0ZMT1dfVVNFX1NURVBdID0gdXNlU3RlcDtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgICB2bUdsb2JhbFRoaXNbV09SS0ZMT1dfQ1JFQVRFX0hPT0tdID0gY3JlYXRlSG9vaztcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgICB2bUdsb2JhbFRoaXNbV09SS0ZMT1dfU0xFRVBdID0gc2xlZXA7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIGBAdHlwZXMvbm9kZWAgc2F5cyBzeW1ib2wgaXMgbm90IHZhbGlkLCBidXQgaXQgZG9lcyB3b3JrXG4gICAgdm1HbG9iYWxUaGlzW1dPUktGTE9XX0dFVF9TVFJFQU1fSURdID0gKG5hbWVzcGFjZT86IHN0cmluZykgPT5cbiAgICAgIGdldFdvcmtmbG93UnVuU3RyZWFtSWQod29ya2Zsb3dSdW4ucnVuSWQsIG5hbWVzcGFjZSk7XG5cbiAgICAvLyBUT0RPOiB0aGVyZSBzaG91bGQgYmUgYSBnZXRVcmwgbWV0aG9kIG9uIHRoZSB3b3JsZCBpbnRlcmZhY2UgaXRzZWxmLiBUaGlzXG4gICAgLy8gc29sdXRpb24gb25seSB3b3JrcyBmb3IgdmVyY2VsICsgbG9jYWwgd29ybGRzLlxuICAgIGNvbnN0IHVybCA9IGlzVmVyY2VsXG4gICAgICA/IGBodHRwczovLyR7cHJvY2Vzcy5lbnYuVkVSQ0VMX1VSTH1gXG4gICAgICA6IGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydCA/PyAzMDAwfWA7XG5cbiAgICAvLyBGb3IgdGhlIHdvcmtmbG93IFZNLCB3ZSBzdG9yZSB0aGUgY29udGV4dCBpbiBhIHN5bWJvbCBvbiB0aGUgYGdsb2JhbFRoaXNgIG9iamVjdFxuICAgIGNvbnN0IGN0eDogV29ya2Zsb3dNZXRhZGF0YSA9IHtcbiAgICAgIHdvcmtmbG93TmFtZTogd29ya2Zsb3dSdW4ud29ya2Zsb3dOYW1lLFxuICAgICAgd29ya2Zsb3dSdW5JZDogd29ya2Zsb3dSdW4ucnVuSWQsXG4gICAgICB3b3JrZmxvd1N0YXJ0ZWRBdDogbmV3IHZtR2xvYmFsVGhpcy5EYXRlKCtzdGFydGVkQXQpLFxuICAgICAgdXJsLFxuICAgICAgZmVhdHVyZXM6IHsgZW5jcnlwdGlvbjogISFlbmNyeXB0aW9uS2V5IH0sXG4gICAgfTtcblxuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBgQHR5cGVzL25vZGVgIHNheXMgc3ltYm9sIGlzIG5vdCB2YWxpZCwgYnV0IGl0IGRvZXMgd29ya1xuICAgIHZtR2xvYmFsVGhpc1tXT1JLRkxPV19DT05URVhUX1NZTUJPTF0gPSBjdHg7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIGBAdHlwZXMvbm9kZWAgc2F5cyBzeW1ib2wgaXMgbm90IHZhbGlkLCBidXQgaXQgZG9lcyB3b3JrXG4gICAgdm1HbG9iYWxUaGlzW1NUQUJMRV9VTElEXSA9IHVsaWQ7XG5cbiAgICAvLyBOT1RFOiBXaWxsIGhhdmUgYSBjb25maWcgb3ZlcnJpZGUgdG8gdXNlIHRoZSBjdXN0b20gZmV0Y2ggc3RlcC5cbiAgICAvLyAgICAgICBGb3Igbm93IGBmZXRjaGAgbXVzdCBiZSBleHBsaWNpdGx5IGltcG9ydGVkIGZyb20gYHdvcmtmbG93YC5cbiAgICB2bUdsb2JhbFRoaXMuZmV0Y2ggPSAoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgdm1HbG9iYWxUaGlzLkVycm9yKFxuICAgICAgICBgR2xvYmFsIFwiZmV0Y2hcIiBpcyB1bmF2YWlsYWJsZSBpbiB3b3JrZmxvdyBmdW5jdGlvbnMuIFVzZSB0aGUgXCJmZXRjaFwiIHN0ZXAgZnVuY3Rpb24gZnJvbSBcIndvcmtmbG93XCIgdG8gbWFrZSBIVFRQIHJlcXVlc3RzLlxcblxcbkxlYXJuIG1vcmU6IGh0dHBzOi8vd29ya2Zsb3ctc2RrLmRldi9lcnIvJHtFUlJPUl9TTFVHUy5GRVRDSF9JTl9XT1JLRkxPV19GVU5DVElPTn1gXG4gICAgICApO1xuICAgIH07XG5cbiAgICAvLyBPdmVycmlkZSB0aW1lb3V0L2ludGVydmFsIGZ1bmN0aW9ucyB0byB0aHJvdyBoZWxwZnVsIGVycm9yc1xuICAgIC8vIFRoZXNlIGFyZSBub3Qgc3VwcG9ydGVkIGluIHdvcmtmbG93IGZ1bmN0aW9ucyBiZWNhdXNlIHRoZXkgcmVseSBvblxuICAgIC8vIGFzeW5jaHJvbm91cyBzY2hlZHVsaW5nIHdoaWNoIGJyZWFrcyBkZXRlcm1pbmlzdGljIHJlcGxheVxuICAgIGNvbnN0IHRpbWVvdXRFcnJvck1lc3NhZ2UgPVxuICAgICAgJ1RpbWVvdXQgZnVuY3Rpb25zIGxpa2UgXCJzZXRUaW1lb3V0XCIgYW5kIFwic2V0SW50ZXJ2YWxcIiBhcmUgbm90IHN1cHBvcnRlZCBpbiB3b3JrZmxvdyBmdW5jdGlvbnMuIFVzZSB0aGUgXCJzbGVlcFwiIGZ1bmN0aW9uIGZyb20gXCJ3b3JrZmxvd1wiIGZvciB0aW1lLWJhc2VkIGRlbGF5cy4nO1xuXG4gICAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLnNldFRpbWVvdXQgPSAoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IodGltZW91dEVycm9yTWVzc2FnZSwge1xuICAgICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLnNldEludGVydmFsID0gKCkgPT4ge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKHRpbWVvdXRFcnJvck1lc3NhZ2UsIHtcbiAgICAgICAgc2x1ZzogRVJST1JfU0xVR1MuVElNRU9VVF9GVU5DVElPTlNfSU5fV09SS0ZMT1csXG4gICAgICB9KTtcbiAgICB9O1xuICAgICh2bUdsb2JhbFRoaXMgYXMgYW55KS5jbGVhclRpbWVvdXQgPSAoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IodGltZW91dEVycm9yTWVzc2FnZSwge1xuICAgICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLmNsZWFySW50ZXJ2YWwgPSAoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IodGltZW91dEVycm9yTWVzc2FnZSwge1xuICAgICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLnNldEltbWVkaWF0ZSA9ICgpID0+IHtcbiAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcih0aW1lb3V0RXJyb3JNZXNzYWdlLCB7XG4gICAgICAgIHNsdWc6IEVSUk9SX1NMVUdTLlRJTUVPVVRfRlVOQ1RJT05TX0lOX1dPUktGTE9XLFxuICAgICAgfSk7XG4gICAgfTtcbiAgICAodm1HbG9iYWxUaGlzIGFzIGFueSkuY2xlYXJJbW1lZGlhdGUgPSAoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IodGltZW91dEVycm9yTWVzc2FnZSwge1xuICAgICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyBgQWJvcnRDb250cm9sbGVyYCBhbmQgYEFib3J0U2lnbmFsYCBpbiB0aGUgd29ya2Zsb3cgVk0gYXJlIGhvb2stYmFja2VkXG4gICAgLy8gZm9yIGRldGVybWluaXN0aWMgcmVwbGF5LiBUaGUgY29udHJvbGxlcidzIGFib3J0KCkgcXVldWVzIGEgaG9vayByZXN1bXB0aW9uLFxuICAgIC8vIGFuZCBzaWduYWwuYWJvcnRlZCBpcyB1cGRhdGVkIHdoZW4gdGhlIGhvb2sgZXZlbnQgaXMgcHJvY2Vzc2VkIGR1cmluZyByZXBsYXkuXG4gICAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLkFib3J0Q29udHJvbGxlciA9XG4gICAgICBjcmVhdGVDcmVhdGVBYm9ydENvbnRyb2xsZXIod29ya2Zsb3dDb250ZXh0KTtcbiAgICBjb25zdCBhYm9ydFNpZ25hbFN0YXRpY3MgPSBjcmVhdGVBYm9ydFNpZ25hbFN0YXRpY3MoKTtcbiAgICAodm1HbG9iYWxUaGlzIGFzIGFueSkuQWJvcnRTaWduYWwgPSB7XG4gICAgICBhYm9ydDogYWJvcnRTaWduYWxTdGF0aWNzLmFib3J0LFxuICAgICAgYW55OiBhYm9ydFNpZ25hbFN0YXRpY3MuYW55LFxuICAgICAgdGltZW91dDogYWJvcnRTaWduYWxTdGF0aWNzLnRpbWVvdXQsXG4gICAgfTtcblxuICAgIC8vIGBSZXF1ZXN0YCBhbmQgYFJlc3BvbnNlYCBhcmUgc3BlY2lhbCBidWlsdC1pbiBjbGFzc2VzIHRoYXQgaW52b2tlIHN0ZXBzXG4gICAgLy8gZm9yIHRoZSBganNvbigpYCwgYHRleHQoKWAgYW5kIGBhcnJheUJ1ZmZlcigpYCBpbnN0YW5jZSBtZXRob2RzXG4gICAgY2xhc3MgUmVxdWVzdCBpbXBsZW1lbnRzIGdsb2JhbFRoaXMuUmVxdWVzdCB7XG4gICAgICBjYWNoZSE6IGdsb2JhbFRoaXMuUmVxdWVzdFsnY2FjaGUnXTtcbiAgICAgIGNyZWRlbnRpYWxzITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydjcmVkZW50aWFscyddO1xuICAgICAgZGVzdGluYXRpb24hOiBnbG9iYWxUaGlzLlJlcXVlc3RbJ2Rlc3RpbmF0aW9uJ107XG4gICAgICBoZWFkZXJzITogSGVhZGVycztcbiAgICAgIGludGVncml0eSE6IHN0cmluZztcbiAgICAgIG1ldGhvZCE6IHN0cmluZztcbiAgICAgIG1vZGUhOiBnbG9iYWxUaGlzLlJlcXVlc3RbJ21vZGUnXTtcbiAgICAgIHJlZGlyZWN0ITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydyZWRpcmVjdCddO1xuICAgICAgcmVmZXJyZXIhOiBzdHJpbmc7XG4gICAgICByZWZlcnJlclBvbGljeSE6IGdsb2JhbFRoaXMuUmVxdWVzdFsncmVmZXJyZXJQb2xpY3knXTtcbiAgICAgIHVybCE6IHN0cmluZztcbiAgICAgIGtlZXBhbGl2ZSE6IGJvb2xlYW47XG4gICAgICBzaWduYWwhOiBBYm9ydFNpZ25hbDtcbiAgICAgIGR1cGxleCE6ICdoYWxmJztcbiAgICAgIGJvZHkhOiBSZWFkYWJsZVN0cmVhbTxhbnk+IHwgbnVsbDtcblxuICAgICAgY29uc3RydWN0b3IoaW5wdXQ6IGFueSwgaW5pdD86IFJlcXVlc3RJbml0KSB7XG4gICAgICAgIC8vIEhhbmRsZSBVUkwgaW5wdXRcbiAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgfHwgaW5wdXQgaW5zdGFuY2VvZiB2bUdsb2JhbFRoaXMuVVJMKSB7XG4gICAgICAgICAgY29uc3QgdXJsU3RyaW5nID0gU3RyaW5nKGlucHV0KTtcbiAgICAgICAgICAvLyBWYWxpZGF0ZSBVUkwgZm9ybWF0XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG5ldyB2bUdsb2JhbFRoaXMuVVJMKHVybFN0cmluZyk7XG4gICAgICAgICAgICB0aGlzLnVybCA9IHVybFN0cmluZztcbiAgICAgICAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgRmFpbGVkIHRvIHBhcnNlIFVSTCBmcm9tICR7dXJsU3RyaW5nfWAsIHtcbiAgICAgICAgICAgICAgY2F1c2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gSW5wdXQgaXMgYSBSZXF1ZXN0IG9iamVjdCAtIGNsb25lIGl0cyBwcm9wZXJ0aWVzXG4gICAgICAgICAgdGhpcy51cmwgPSBpbnB1dC51cmw7XG4gICAgICAgICAgaWYgKCFpbml0KSB7XG4gICAgICAgICAgICB0aGlzLm1ldGhvZCA9IGlucHV0Lm1ldGhvZDtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycyhpbnB1dC5oZWFkZXJzKTtcbiAgICAgICAgICAgIHRoaXMuYm9keSA9IGlucHV0LmJvZHk7XG4gICAgICAgICAgICB0aGlzLm1vZGUgPSBpbnB1dC5tb2RlO1xuICAgICAgICAgICAgdGhpcy5jcmVkZW50aWFscyA9IGlucHV0LmNyZWRlbnRpYWxzO1xuICAgICAgICAgICAgdGhpcy5jYWNoZSA9IGlucHV0LmNhY2hlO1xuICAgICAgICAgICAgdGhpcy5yZWRpcmVjdCA9IGlucHV0LnJlZGlyZWN0O1xuICAgICAgICAgICAgdGhpcy5yZWZlcnJlciA9IGlucHV0LnJlZmVycmVyO1xuICAgICAgICAgICAgdGhpcy5yZWZlcnJlclBvbGljeSA9IGlucHV0LnJlZmVycmVyUG9saWN5O1xuICAgICAgICAgICAgdGhpcy5pbnRlZ3JpdHkgPSBpbnB1dC5pbnRlZ3JpdHk7XG4gICAgICAgICAgICB0aGlzLmtlZXBhbGl2ZSA9IGlucHV0LmtlZXBhbGl2ZTtcbiAgICAgICAgICAgIHRoaXMuc2lnbmFsID0gaW5wdXQuc2lnbmFsO1xuICAgICAgICAgICAgdGhpcy5kdXBsZXggPSBpbnB1dC5kdXBsZXg7XG4gICAgICAgICAgICB0aGlzLmRlc3RpbmF0aW9uID0gaW5wdXQuZGVzdGluYXRpb247XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIElmIGluaXQgaXMgcHJvdmlkZWQsIG1lcmdlOiB1c2Ugc291cmNlIHByb3BlcnRpZXMsIHRoZW4gb3ZlcnJpZGUgd2l0aCBpbml0XG4gICAgICAgICAgLy8gQ29weSBhbGwgcHJvcGVydGllcyBmcm9tIHRoZSBzb3VyY2UgUmVxdWVzdCBmaXJzdFxuICAgICAgICAgIHRoaXMubWV0aG9kID0gaW5wdXQubWV0aG9kO1xuICAgICAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycyhpbnB1dC5oZWFkZXJzKTtcbiAgICAgICAgICB0aGlzLmJvZHkgPSBpbnB1dC5ib2R5O1xuICAgICAgICAgIHRoaXMubW9kZSA9IGlucHV0Lm1vZGU7XG4gICAgICAgICAgdGhpcy5jcmVkZW50aWFscyA9IGlucHV0LmNyZWRlbnRpYWxzO1xuICAgICAgICAgIHRoaXMuY2FjaGUgPSBpbnB1dC5jYWNoZTtcbiAgICAgICAgICB0aGlzLnJlZGlyZWN0ID0gaW5wdXQucmVkaXJlY3Q7XG4gICAgICAgICAgdGhpcy5yZWZlcnJlciA9IGlucHV0LnJlZmVycmVyO1xuICAgICAgICAgIHRoaXMucmVmZXJyZXJQb2xpY3kgPSBpbnB1dC5yZWZlcnJlclBvbGljeTtcbiAgICAgICAgICB0aGlzLmludGVncml0eSA9IGlucHV0LmludGVncml0eTtcbiAgICAgICAgICB0aGlzLmtlZXBhbGl2ZSA9IGlucHV0LmtlZXBhbGl2ZTtcbiAgICAgICAgICB0aGlzLnNpZ25hbCA9IGlucHV0LnNpZ25hbDtcbiAgICAgICAgICB0aGlzLmR1cGxleCA9IGlucHV0LmR1cGxleDtcbiAgICAgICAgICB0aGlzLmRlc3RpbmF0aW9uID0gaW5wdXQuZGVzdGluYXRpb247XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPdmVycmlkZSB3aXRoIGluaXQgb3B0aW9ucyBpZiBwcm92aWRlZFxuICAgICAgICAvLyBTZXQgbWV0aG9kXG4gICAgICAgIGlmIChpbml0Py5tZXRob2QpIHtcbiAgICAgICAgICB0aGlzLm1ldGhvZCA9IGluaXQubWV0aG9kLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMubWV0aG9kICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIC8vIEZhbGxiYWNrIHRvIGRlZmF1bHQgZm9yIHN0cmluZyBpbnB1dCBjYXNlXG4gICAgICAgICAgdGhpcy5tZXRob2QgPSAnR0VUJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBoZWFkZXJzXG4gICAgICAgIGlmIChpbml0Py5oZWFkZXJzKSB7XG4gICAgICAgICAgdGhpcy5oZWFkZXJzID0gbmV3IHZtR2xvYmFsVGhpcy5IZWFkZXJzKGluaXQuaGVhZGVycyk7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgdHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJyB8fFxuICAgICAgICAgIGlucHV0IGluc3RhbmNlb2Ygdm1HbG9iYWxUaGlzLlVSTFxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBGb3Igc3RyaW5nL1VSTCBpbnB1dCwgY3JlYXRlIGVtcHR5IGhlYWRlcnNcbiAgICAgICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgdm1HbG9iYWxUaGlzLkhlYWRlcnMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBvdGhlciBwcm9wZXJ0aWVzIHdpdGggaW5pdCB2YWx1ZXMgb3IgZGVmYXVsdHNcbiAgICAgICAgaWYgKGluaXQ/Lm1vZGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMubW9kZSA9IGluaXQubW9kZTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5tb2RlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRoaXMubW9kZSA9ICdjb3JzJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbml0Py5jcmVkZW50aWFscyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5jcmVkZW50aWFscyA9IGluaXQuY3JlZGVudGlhbHM7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuY3JlZGVudGlhbHMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5jcmVkZW50aWFscyA9ICdzYW1lLW9yaWdpbic7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBgYW55YCBjYXN0IGhlcmUgYmVjYXVzZSBAdHlwZXMvbm9kZSB2MjIgZG9lcyBub3QgeWV0IGhhdmUgYGNhY2hlYFxuICAgICAgICBpZiAoKGluaXQgYXMgYW55KT8uY2FjaGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMuY2FjaGUgPSAoaW5pdCBhcyBhbnkpLmNhY2hlO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLmNhY2hlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRoaXMuY2FjaGUgPSAnZGVmYXVsdCc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaW5pdD8ucmVkaXJlY3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMucmVkaXJlY3QgPSBpbml0LnJlZGlyZWN0O1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLnJlZGlyZWN0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRoaXMucmVkaXJlY3QgPSAnZm9sbG93JztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbml0Py5yZWZlcnJlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5yZWZlcnJlciA9IGluaXQucmVmZXJyZXI7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMucmVmZXJyZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5yZWZlcnJlciA9ICdhYm91dDpjbGllbnQnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluaXQ/LnJlZmVycmVyUG9saWN5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLnJlZmVycmVyUG9saWN5ID0gaW5pdC5yZWZlcnJlclBvbGljeTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5yZWZlcnJlclBvbGljeSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aGlzLnJlZmVycmVyUG9saWN5ID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaW5pdD8uaW50ZWdyaXR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLmludGVncml0eSA9IGluaXQuaW50ZWdyaXR5O1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLmludGVncml0eSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aGlzLmludGVncml0eSA9ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluaXQ/LmtlZXBhbGl2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5rZWVwYWxpdmUgPSBpbml0LmtlZXBhbGl2ZTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5rZWVwYWxpdmUgIT09ICdib29sZWFuJykge1xuICAgICAgICAgIHRoaXMua2VlcGFsaXZlID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaW5pdD8uc2lnbmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gQWJvcnRTaWduYWwgc3R1YlxuICAgICAgICAgIHRoaXMuc2lnbmFsID0gaW5pdC5zaWduYWw7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuc2lnbmFsKSB7XG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIEFib3J0U2lnbmFsIHN0dWJcbiAgICAgICAgICB0aGlzLnNpZ25hbCA9IHsgYWJvcnRlZDogZmFsc2UgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5kdXBsZXgpIHtcbiAgICAgICAgICB0aGlzLmR1cGxleCA9ICdoYWxmJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5kZXN0aW5hdGlvbikge1xuICAgICAgICAgIHRoaXMuZGVzdGluYXRpb24gPSAnZG9jdW1lbnQnO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYm9keSA9IGluaXQ/LmJvZHk7XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgdGhhdCBHRVQvSEVBRCBtZXRob2RzIGRvbid0IGhhdmUgYSBib2R5XG4gICAgICAgIGlmIChcbiAgICAgICAgICBib2R5ICE9PSBudWxsICYmXG4gICAgICAgICAgYm9keSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgKHRoaXMubWV0aG9kID09PSAnR0VUJyB8fCB0aGlzLm1ldGhvZCA9PT0gJ0hFQUQnKVxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBSZXF1ZXN0IHdpdGggR0VUL0hFQUQgbWV0aG9kIGNhbm5vdCBoYXZlIGJvZHkuYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSB0aGUgb3JpZ2luYWwgQm9keUluaXQgZm9yIHNlcmlhbGl6YXRpb25cbiAgICAgICAgaWYgKGJvZHkgIT09IG51bGwgJiYgYm9keSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIGEgXCJmYWtlXCIgUmVhZGFibGVTdHJlYW0gdGhhdCBzdG9yZXMgdGhlIG9yaWdpbmFsIGJvZHlcbiAgICAgICAgICAvLyBUaGlzIGF2b2lkcyBkb2luZyBhc3luYyB3b3JrIGR1cmluZyB3b3JrZmxvdyByZXBsYXlcbiAgICAgICAgICB0aGlzLmJvZHkgPSBPYmplY3QuY3JlYXRlKHZtR2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbS5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIFtCT0RZX0lOSVRfU1lNQk9MXToge1xuICAgICAgICAgICAgICB2YWx1ZTogYm9keSxcbiAgICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmJvZHkgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNsb25lKCk6IFJlcXVlc3Qge1xuICAgICAgICBFTk9UU1VQKCk7XG4gICAgICB9XG5cbiAgICAgIGdldCBib2R5VXNlZCgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBUT0RPOiBpbXBsZW1lbnQgdGhlc2VcbiAgICAgIGJsb2IhOiAoKSA9PiBQcm9taXNlPEJsb2I+O1xuICAgICAgZm9ybURhdGEhOiAoKSA9PiBQcm9taXNlPEZvcm1EYXRhPjtcblxuICAgICAgYXJyYXlCdWZmZXIhOiAoKSA9PiBQcm9taXNlPEFycmF5QnVmZmVyPjtcbiAgICAgIGpzb24hOiAoKSA9PiBQcm9taXNlPGFueT47XG4gICAgICB0ZXh0ITogKCkgPT4gUHJvbWlzZTxzdHJpbmc+O1xuXG4gICAgICBhc3luYyBieXRlcygpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHRoaXMuYXJyYXlCdWZmZXIoKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHZtR2xvYmFsVGhpcy5SZXF1ZXN0ID0gUmVxdWVzdDtcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFJlcXVlc3QucHJvdG90eXBlLCB7XG4gICAgICBhcnJheUJ1ZmZlcjoge1xuICAgICAgICB2YWx1ZTogdXNlU3RlcDxbXSwgQXJyYXlCdWZmZXI+KCdfX2J1aWx0aW5fcmVzcG9uc2VfYXJyYXlfYnVmZmVyJyksXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB9LFxuICAgICAganNvbjoge1xuICAgICAgICB2YWx1ZTogdXNlU3RlcDxbXSwgYW55PignX19idWlsdGluX3Jlc3BvbnNlX2pzb24nKSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICB0ZXh0OiB7XG4gICAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBzdHJpbmc+KCdfX2J1aWx0aW5fcmVzcG9uc2VfdGV4dCcpLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNsYXNzIFJlc3BvbnNlIGltcGxlbWVudHMgZ2xvYmFsVGhpcy5SZXNwb25zZSB7XG4gICAgICB0eXBlITogZ2xvYmFsVGhpcy5SZXNwb25zZVsndHlwZSddO1xuICAgICAgdXJsITogc3RyaW5nO1xuICAgICAgc3RhdHVzITogbnVtYmVyO1xuICAgICAgc3RhdHVzVGV4dCE6IHN0cmluZztcbiAgICAgIGJvZHkhOiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB8IG51bGw7XG4gICAgICBoZWFkZXJzITogSGVhZGVycztcbiAgICAgIHJlZGlyZWN0ZWQhOiBib29sZWFuO1xuXG4gICAgICBjb25zdHJ1Y3Rvcihib2R5PzogYW55LCBpbml0PzogUmVzcG9uc2VJbml0KSB7XG4gICAgICAgIHRoaXMuc3RhdHVzID0gaW5pdD8uc3RhdHVzID8/IDIwMDtcbiAgICAgICAgdGhpcy5zdGF0dXNUZXh0ID0gaW5pdD8uc3RhdHVzVGV4dCA/PyAnJztcbiAgICAgICAgdGhpcy5oZWFkZXJzID0gbmV3IHZtR2xvYmFsVGhpcy5IZWFkZXJzKGluaXQ/LmhlYWRlcnMpO1xuICAgICAgICB0aGlzLnR5cGUgPSAnZGVmYXVsdCc7XG4gICAgICAgIHRoaXMudXJsID0gJyc7XG4gICAgICAgIHRoaXMucmVkaXJlY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgIC8vIFZhbGlkYXRlIHRoYXQgbnVsbC1ib2R5IHN0YXR1cyBjb2RlcyBkb24ndCBoYXZlIGEgYm9keVxuICAgICAgICAvLyBQZXIgSFRUUCBzcGVjOiAyMDQgKE5vIENvbnRlbnQpLCAyMDUgKFJlc2V0IENvbnRlbnQpLCBhbmQgMzA0IChOb3QgTW9kaWZpZWQpXG4gICAgICAgIGlmIChcbiAgICAgICAgICBib2R5ICE9PSBudWxsICYmXG4gICAgICAgICAgYm9keSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgKHRoaXMuc3RhdHVzID09PSAyMDQgfHwgdGhpcy5zdGF0dXMgPT09IDIwNSB8fCB0aGlzLnN0YXR1cyA9PT0gMzA0KVxuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgYFJlc3BvbnNlIGNvbnN0cnVjdG9yOiBJbnZhbGlkIHJlc3BvbnNlIHN0YXR1cyBjb2RlICR7dGhpcy5zdGF0dXN9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSB0aGUgb3JpZ2luYWwgQm9keUluaXQgZm9yIHNlcmlhbGl6YXRpb25cbiAgICAgICAgaWYgKGJvZHkgIT09IG51bGwgJiYgYm9keSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIGEgXCJmYWtlXCIgUmVhZGFibGVTdHJlYW0gdGhhdCBzdG9yZXMgdGhlIG9yaWdpbmFsIGJvZHlcbiAgICAgICAgICAvLyBUaGlzIGF2b2lkcyBkb2luZyBhc3luYyB3b3JrIGR1cmluZyB3b3JrZmxvdyByZXBsYXlcbiAgICAgICAgICB0aGlzLmJvZHkgPSBPYmplY3QuY3JlYXRlKHZtR2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbS5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIFtCT0RZX0lOSVRfU1lNQk9MXToge1xuICAgICAgICAgICAgICB2YWx1ZTogYm9keSxcbiAgICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmJvZHkgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFRPRE86IGltcGxlbWVudCB0aGVzZVxuICAgICAgY2xvbmUhOiAoKSA9PiBSZXNwb25zZTtcbiAgICAgIGJsb2IhOiAoKSA9PiBQcm9taXNlPGdsb2JhbFRoaXMuQmxvYj47XG4gICAgICBmb3JtRGF0YSE6ICgpID0+IFByb21pc2U8Z2xvYmFsVGhpcy5Gb3JtRGF0YT47XG5cbiAgICAgIGdldCBvaygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdHVzID49IDIwMCAmJiB0aGlzLnN0YXR1cyA8IDMwMDtcbiAgICAgIH1cblxuICAgICAgZ2V0IGJvZHlVc2VkKCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGFycmF5QnVmZmVyITogKCkgPT4gUHJvbWlzZTxBcnJheUJ1ZmZlcj47XG4gICAgICBqc29uITogKCkgPT4gUHJvbWlzZTxhbnk+O1xuICAgICAgdGV4dCE6ICgpID0+IFByb21pc2U8c3RyaW5nPjtcblxuICAgICAgYXN5bmMgYnl0ZXMoKSB7XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCB0aGlzLmFycmF5QnVmZmVyKCkpO1xuICAgICAgfVxuXG4gICAgICBzdGF0aWMganNvbihkYXRhOiBhbnksIGluaXQ/OiBSZXNwb25zZUluaXQpOiBSZXNwb25zZSB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgICAgICAgY29uc3QgaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycyhpbml0Py5oZWFkZXJzKTtcbiAgICAgICAgaWYgKCFoZWFkZXJzLmhhcygnY29udGVudC10eXBlJykpIHtcbiAgICAgICAgICBoZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKGJvZHksIHsgLi4uaW5pdCwgaGVhZGVycyB9KTtcbiAgICAgIH1cblxuICAgICAgc3RhdGljIGVycm9yKCk6IFJlc3BvbnNlIHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICBzdGF0aWMgcmVkaXJlY3QodXJsOiBzdHJpbmcgfCBVUkwsIHN0YXR1czogbnVtYmVyID0gMzAyKTogUmVzcG9uc2Uge1xuICAgICAgICAvLyBWYWxpZGF0ZSBzdGF0dXMgY29kZSAtIG9ubHkgc3BlY2lmaWMgcmVkaXJlY3QgY29kZXMgYXJlIGFsbG93ZWRcbiAgICAgICAgaWYgKCFbMzAxLCAzMDIsIDMwMywgMzA3LCAzMDhdLmluY2x1ZGVzKHN0YXR1cykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcbiAgICAgICAgICAgIGBJbnZhbGlkIHJlZGlyZWN0IHN0YXR1cyBjb2RlOiAke3N0YXR1c30uIE11c3QgYmUgb25lIG9mOiAzMDEsIDMwMiwgMzAzLCAzMDcsIDMwOGBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIHJlc3BvbnNlIHdpdGggTG9jYXRpb24gaGVhZGVyXG4gICAgICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgdm1HbG9iYWxUaGlzLkhlYWRlcnMoKTtcbiAgICAgICAgaGVhZGVycy5zZXQoJ0xvY2F0aW9uJywgU3RyaW5nKHVybCkpO1xuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gT2JqZWN0LmNyZWF0ZShSZXNwb25zZS5wcm90b3R5cGUpO1xuICAgICAgICByZXNwb25zZS5zdGF0dXMgPSBzdGF0dXM7XG4gICAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgPSAnJztcbiAgICAgICAgcmVzcG9uc2UuaGVhZGVycyA9IGhlYWRlcnM7XG4gICAgICAgIHJlc3BvbnNlLmJvZHkgPSBudWxsO1xuICAgICAgICByZXNwb25zZS50eXBlID0gJ2RlZmF1bHQnO1xuICAgICAgICByZXNwb25zZS51cmwgPSAnJztcbiAgICAgICAgcmVzcG9uc2UucmVkaXJlY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgIH1cbiAgICB9XG4gICAgdm1HbG9iYWxUaGlzLlJlc3BvbnNlID0gUmVzcG9uc2U7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhSZXNwb25zZS5wcm90b3R5cGUsIHtcbiAgICAgIGFycmF5QnVmZmVyOiB7XG4gICAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBBcnJheUJ1ZmZlcj4oJ19fYnVpbHRpbl9yZXNwb25zZV9hcnJheV9idWZmZXInKSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICBqc29uOiB7XG4gICAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBhbnk+KCdfX2J1aWx0aW5fcmVzcG9uc2VfanNvbicpLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgfSxcbiAgICAgIHRleHQ6IHtcbiAgICAgICAgdmFsdWU6IHVzZVN0ZXA8W10sIHN0cmluZz4oJ19fYnVpbHRpbl9yZXNwb25zZV90ZXh0JyksXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY2xhc3MgUmVhZGFibGVTdHJlYW08VD4gaW1wbGVtZW50cyBnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtPFQ+IHtcbiAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBFTk9UU1VQKCk7XG4gICAgICB9XG5cbiAgICAgIGdldCBsb2NrZWQoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY2FuY2VsKCk6IGFueSB7XG4gICAgICAgIEVOT1RTVVAoKTtcbiAgICAgIH1cblxuICAgICAgZ2V0UmVhZGVyKCk6IGFueSB7XG4gICAgICAgIEVOT1RTVVAoKTtcbiAgICAgIH1cblxuICAgICAgcGlwZVRocm91Z2goKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICBwaXBlVG8oKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICB0ZWUoKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICB2YWx1ZXMoKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICBzdGF0aWMgZnJvbSgpOiBhbnkge1xuICAgICAgICBFTk9UU1VQKCk7XG4gICAgICB9XG5cbiAgICAgIFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuICAgIH1cbiAgICB2bUdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0gPSBSZWFkYWJsZVN0cmVhbTtcblxuICAgIGNsYXNzIFdyaXRhYmxlU3RyZWFtPFQ+IGltcGxlbWVudHMgZ2xvYmFsVGhpcy5Xcml0YWJsZVN0cmVhbTxUPiB7XG4gICAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICBnZXQgbG9ja2VkKCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGFib3J0KCk6IGFueSB7XG4gICAgICAgIEVOT1RTVVAoKTtcbiAgICAgIH1cblxuICAgICAgY2xvc2UoKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuXG4gICAgICBnZXRXcml0ZXIoKTogYW55IHtcbiAgICAgICAgRU5PVFNVUCgpO1xuICAgICAgfVxuICAgIH1cbiAgICB2bUdsb2JhbFRoaXMuV3JpdGFibGVTdHJlYW0gPSBXcml0YWJsZVN0cmVhbTtcblxuICAgIGNsYXNzIFRyYW5zZm9ybVN0cmVhbTxJLCBPPiBpbXBsZW1lbnRzIGdsb2JhbFRoaXMuVHJhbnNmb3JtU3RyZWFtPEksIE8+IHtcbiAgICAgIHJlYWRhYmxlOiBnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtPE8+O1xuICAgICAgd3JpdGFibGU6IGdsb2JhbFRoaXMuV3JpdGFibGVTdHJlYW08ST47XG5cbiAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBFTk9UU1VQKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHZtR2xvYmFsVGhpcy5UcmFuc2Zvcm1TdHJlYW0gPSBUcmFuc2Zvcm1TdHJlYW07XG5cbiAgICAvLyBFdmVudHVhbGx5IHdlJ2xsIHByb2JhYmx5IHdhbnQgdG8gcHJvdmlkZSBvdXIgb3duIGBjb25zb2xlYCBvYmplY3QsXG4gICAgLy8gYnV0IGZvciBub3cgd2UnbGwganVzdCBleHBvc2UgdGhlIGdsb2JhbCBvbmUuXG4gICAgdm1HbG9iYWxUaGlzLmNvbnNvbGUgPSBnbG9iYWxUaGlzLmNvbnNvbGU7XG5cbiAgICAvLyBIQUNLOiBwcm9wYWdhdGUgc3ltYm9sIG5lZWRlZCBmb3IgQUkgZ2F0ZXdheSB1c2FnZVxuICAgIGNvbnN0IFNZTUJPTF9GT1JfUkVRX0NPTlRFWFQgPSBTeW1ib2wuZm9yKCdAdmVyY2VsL3JlcXVlc3QtY29udGV4dCcpO1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBgQHR5cGVzL25vZGVgIHNheXMgc3ltYm9sIGlzIG5vdCB2YWxpZCwgYnV0IGl0IGRvZXMgd29ya1xuICAgIHZtR2xvYmFsVGhpc1tTWU1CT0xfRk9SX1JFUV9DT05URVhUXSA9IChnbG9iYWxUaGlzIGFzIGFueSlbXG4gICAgICBTWU1CT0xfRk9SX1JFUV9DT05URVhUXG4gICAgXTtcblxuICAgIC8vIEdldCBhIHJlZmVyZW5jZSB0byB0aGUgdXNlci1kZWZpbmVkIHdvcmtmbG93IGZ1bmN0aW9uLlxuICAgIC8vIFRoZSBmaWxlbmFtZSBwYXJhbWV0ZXIgZW5zdXJlcyBzdGFjayB0cmFjZXMgc2hvdyBhIG1lYW5pbmdmdWwgbmFtZVxuICAgIC8vIChlLmcuLCBcImV4YW1wbGUvd29ya2Zsb3dzLzk5X2UyZS50c1wiKSBpbnN0ZWFkIG9mIFwiZXZhbG1hY2hpbmUuPGFub255bW91cz5cIi5cbiAgICBjb25zdCBwYXJzZWROYW1lID0gcGFyc2VXb3JrZmxvd05hbWUod29ya2Zsb3dSdW4ud29ya2Zsb3dOYW1lKTtcbiAgICBjb25zdCBmaWxlbmFtZSA9IHBhcnNlZE5hbWU/Lm1vZHVsZVNwZWNpZmllciB8fCB3b3JrZmxvd1J1bi53b3JrZmxvd05hbWU7XG5cbiAgICBjb25zdCB3b3JrZmxvd0ZuID0gcnVuSW5Db250ZXh0KFxuICAgICAgYCR7d29ya2Zsb3dDb2RlfTsgZ2xvYmFsVGhpcy5fX3ByaXZhdGVfd29ya2Zsb3dzPy5nZXQoJHtKU09OLnN0cmluZ2lmeSh3b3JrZmxvd1J1bi53b3JrZmxvd05hbWUpfSlgLFxuICAgICAgY29udGV4dCxcbiAgICAgIHsgZmlsZW5hbWUgfVxuICAgICk7XG5cbiAgICBpZiAodHlwZW9mIHdvcmtmbG93Rm4gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBXb3JrZmxvd05vdFJlZ2lzdGVyZWRFcnJvcih3b3JrZmxvd1J1bi53b3JrZmxvd05hbWUpO1xuICAgIH1cblxuICAgIC8vIENoYWluIHdvcmtmbG93IGFyZ3VtZW50IGh5ZHJhdGlvbiBvbnRvIHRoZSBwcm9taXNlUXVldWUgc28gdGhhdCB0aGVcbiAgICAvLyB1bmNvbnN1bWVkIGV2ZW50IGNoZWNrICh3aGljaCB3YWl0cyBmb3IgdGhlIHF1ZXVlIHRvIGRyYWluKSBkb2Vzbid0XG4gICAgLy8gZmlyZSBkdXJpbmcgdGhlIGFzeW5jIGdhcCBiZXR3ZWVuIHJ1bl9zdGFydGVkIGNvbnN1bXB0aW9uIGFuZCB0aGVcbiAgICAvLyB3b3JrZmxvdyBmdW5jdGlvbiBzdWJzY3JpYmluZyBpdHMgZmlyc3Qgc3RlcCBjYWxsYmFja3MuXG4gICAgbGV0IGFyZ3M6IHVua25vd25bXSA9IFtdO1xuICAgIHdvcmtmbG93Q29udGV4dC5wcm9taXNlUXVldWUgPSB3b3JrZmxvd0NvbnRleHQucHJvbWlzZVF1ZXVlLnRoZW4oXG4gICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgIGFyZ3MgPSBhd2FpdCBoeWRyYXRlV29ya2Zsb3dBcmd1bWVudHMoXG4gICAgICAgICAgd29ya2Zsb3dSdW4uaW5wdXQsXG4gICAgICAgICAgd29ya2Zsb3dSdW4ucnVuSWQsXG4gICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICB2bUdsb2JhbFRoaXNcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIGF3YWl0IHdvcmtmbG93Q29udGV4dC5wcm9taXNlUXVldWU7XG5cbiAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0FyZ3VtZW50c0NvdW50KGFyZ3MubGVuZ3RoKSxcbiAgICB9KTtcblxuICAgIC8vIEludm9rZSB1c2VyIHdvcmtmbG93XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICAgIHdvcmtmbG93Rm4oLi4uYXJncyksXG4gICAgICAgIHdvcmtmbG93RGlzY29udGludWF0aW9uLnByb21pc2UsXG4gICAgICBdKTtcblxuICAgICAgY29uc3QgZGVoeWRyYXRlZCA9IGF3YWl0IGRlaHlkcmF0ZVdvcmtmbG93UmV0dXJuVmFsdWUoXG4gICAgICAgIHJlc3VsdCxcbiAgICAgICAgd29ya2Zsb3dSdW4ucnVuSWQsXG4gICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgIHZtR2xvYmFsVGhpc1xuICAgICAgKTtcblxuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1Jlc3VsdFR5cGUodHlwZW9mIHJlc3VsdCksXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgZHJhaW5QZW5kaW5nUXVldWVJdGVtcyhcbiAgICAgICAgd29ya2Zsb3dSdW4ucnVuSWQsXG4gICAgICAgIHdvcmtmbG93Q29udGV4dC5pbnZvY2F0aW9uc1F1ZXVlLFxuICAgICAgICB2bUdsb2JhbFRoaXMsXG4gICAgICAgIHdvcmtmbG93UnVuLFxuICAgICAgICAnY29tcGxldGVkJ1xuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGRlaHlkcmF0ZWQ7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBMZXQgV29ya2Zsb3dTdXNwZW5zaW9uIHByb3BhZ2F0ZSDigJQgaGFuZGxlZCBzZXBhcmF0ZWx5IGJ5IHRoZSBydW50aW1lXG4gICAgICBpZiAoV29ya2Zsb3dTdXNwZW5zaW9uLmlzKGVycikpIHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCBkcmFpblBlbmRpbmdRdWV1ZUl0ZW1zKFxuICAgICAgICB3b3JrZmxvd1J1bi5ydW5JZCxcbiAgICAgICAgd29ya2Zsb3dDb250ZXh0Lmludm9jYXRpb25zUXVldWUsXG4gICAgICAgIHZtR2xvYmFsVGhpcyxcbiAgICAgICAgd29ya2Zsb3dSdW4sXG4gICAgICAgICdmYWlsZWQnXG4gICAgICApO1xuXG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9KTtcbn1cbiJdfQ==
989
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUNMLFdBQVcsRUFDWCxxQkFBcUIsRUFDckIsMEJBQTBCLEVBQzFCLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxxQkFBcUIsRUFFckIsYUFBYSxHQUNkLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFL0QsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDakYsT0FBTyxLQUFLLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDakMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUUzRSxPQUFPLEVBQUUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFNUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUM5QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU5QyxPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLHdCQUF3QixHQUN6QixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxhQUFh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LG9CQUFvQixFQUFFLENBQUM7b0JBQ3ZDLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUMvQixjQUFjLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7b0JBQzVELE9BQU8sZ0JBQWdCLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN0RCxDQUFDO2dCQUNELEtBQUssUUFBUTtvQkFDWCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDO2dCQUM1QixLQUFLLFdBQVcsQ0FBQztnQkFDakIsS0FBSyxTQUFTO29CQUNaLE1BQU0sSUFBSSxvQkFBb0IsQ0FDNUIsaUJBQWlCLEtBQUssQ0FBQyxJQUFJLGNBQWMsV0FBVyxDQUFDLEtBQUssR0FBRyxDQUM5RCxDQUFDO1lBQ04sQ0FBQztZQUNELEtBQXFCLENBQUM7UUFDeEIsQ0FBQztLQUNGLENBQUM7SUFFRiwwRUFBMEU7SUFDMUUsNkVBQTZFO0lBQzdFLDJFQUEyRTtJQUMzRSxNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztJQUN0RSxLQUFLLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFdkQsT0FBTztRQUNMLE9BQU87UUFDUCxTQUFTO0tBQ1YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNjcmlwdCB9IGZyb20gJ25vZGU6dm0nO1xuaW1wb3J0IHR5cGUgeyBTcGFuIH0gZnJvbSAnQG9wZW50ZWxlbWV0cnkvYXBpJztcbmltcG9ydCB7XG4gIEVSUk9SX1NMVUdTLFxuICBSZXBsYXlEaXZlcmdlbmNlRXJyb3IsXG4gIFdvcmtmbG93Tm90UmVnaXN0ZXJlZEVycm9yLFxuICBXb3JrZmxvd1J1bnRpbWVFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICBjcmVhdGVXb3JrZmxvd0Jhc2VVcmwsXG4gIHR5cGUgUHJvbWlzZVdpdGhSZXNvbHZlcnMsXG4gIHdpdGhSZXNvbHZlcnMsXG59IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgeyBwYXJzZVdvcmtmbG93TmFtZSB9IGZyb20gJ0B3b3JrZmxvdy91dGlscy9wYXJzZS1uYW1lJztcbmltcG9ydCB0eXBlIHsgRXZlbnQsIFdvcmtmbG93UnVuLCBXb3JsZENhcGFiaWxpdGllcyB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04gfSBmcm9tICdAd29ya2Zsb3cvd29ybGQvc3BlYy12ZXJzaW9uJztcbmltcG9ydCAqIGFzIG5hbm9pZCBmcm9tICduYW5vaWQnO1xuaW1wb3J0IHsgbW9ub3RvbmljRmFjdG9yeSB9IGZyb20gJ3VsaWQnO1xuaW1wb3J0IHsgRXZlbnRDb25zdW1lclJlc3VsdCwgRXZlbnRzQ29uc3VtZXIgfSBmcm9tICcuL2V2ZW50cy1jb25zdW1lci5qcyc7XG5pbXBvcnQgdHlwZSB7IFF1ZXVlSXRlbSB9IGZyb20gJy4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IEVOT1RTVVAsIFdvcmtmbG93U3VzcGVuc2lvbiB9IGZyb20gJy4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuL2xvZ2dlci5qcyc7XG5pbXBvcnQgdHlwZSB7IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCB9IGZyb20gJy4vcHJpdmF0ZS5qcyc7XG5pbXBvcnQgeyBpc0RlbGl2ZXJ5SWRsZSB9IGZyb20gJy4vcHJpdmF0ZS5qcyc7XG5pbXBvcnQgeyBSZXBsYXlQYXlsb2FkQ2FjaGUgfSBmcm9tICcuL3JlcGxheS1wYXlsb2FkLWNhY2hlLmpzJztcbmltcG9ydCB7IGdldFBvcnRMYXp5IH0gZnJvbSAnLi9ydW50aW1lL2dldC1wb3J0LWxhenkuanMnO1xuaW1wb3J0IHsgcnVuSWRDcmVhdGVkQXQgfSBmcm9tICcuL3J1bnRpbWUvcnVuLWlkLXRpbWUuanMnO1xuaW1wb3J0IHsgaGFuZGxlU3VzcGVuc2lvbiB9IGZyb20gJy4vcnVudGltZS9zdXNwZW5zaW9uLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgZ2V0V29ybGQgfSBmcm9tICcuL3J1bnRpbWUvd29ybGQuanMnO1xuaW1wb3J0IHR5cGUgeyBQYXlsb2FkS2V5IH0gZnJvbSAnLi9zZXJpYWxpemF0aW9uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHtcbiAgZGVoeWRyYXRlV29ya2Zsb3dSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVdvcmtmbG93QXJndW1lbnRzLFxufSBmcm9tICcuL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgY3JlYXRlVXNlU3RlcCB9IGZyb20gJy4vc3RlcC5qcyc7XG5pbXBvcnQge1xuICBCT0RZX0lOSVRfU1lNQk9MLFxuICBTVEFCTEVfVUxJRCxcbiAgV09SS0ZMT1dfQ1JFQVRFX0hPT0ssXG4gIFdPUktGTE9XX0dFVF9TVFJFQU1fSUQsXG4gIFdPUktGTE9XX1NFVF9BVFRSSUJVVEVTLFxuICBXT1JLRkxPV19TTEVFUCxcbiAgV09SS0ZMT1dfVVNFX1NURVAsXG59IGZyb20gJy4vc3ltYm9scy5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHtcbiAgYXBwbHlXb3JrZmxvd1N1c3BlbnNpb25Ub1NwYW4sXG4gIGNyZWF0ZVJlZnJlc2hhYmxlVHJhY2VDb250ZXh0LFxuICBzdGFydFRyYWNlU3BhbixcbiAgdHJhY2UsXG59IGZyb20gJy4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7IGdldFdvcmtmbG93UnVuU3RyZWFtSWQgfSBmcm9tICcuL3V0aWwuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ29udGV4dCB9IGZyb20gJy4vdm0vaW5kZXguanMnO1xuaW1wb3J0IHsgZ2V0Q2FjaGVkV29ya2Zsb3dTY3JpcHQgfSBmcm9tICcuL3ZtL3NjcmlwdC1jYWNoZS5qcyc7XG5pbXBvcnQge1xuICBjcmVhdGVBYm9ydFNpZ25hbFN0YXRpY3MsXG4gIGNyZWF0ZUNyZWF0ZUFib3J0Q29udHJvbGxlcixcbn0gZnJvbSAnLi93b3JrZmxvdy9hYm9ydC1jb250cm9sbGVyLmpzJztcbmltcG9ydCB7IGNyZWF0ZVNldEF0dHJpYnV0ZXMgfSBmcm9tICcuL3dvcmtmbG93L2F0dHJpYnV0ZS1kaXNwYXRjaGVyLmpzJztcbmltcG9ydCB0eXBlIHsgV29ya2Zsb3dNZXRhZGF0YSB9IGZyb20gJy4vd29ya2Zsb3cvZ2V0LXdvcmtmbG93LW1ldGFkYXRhLmpzJztcbmltcG9ydCB7IFdPUktGTE9XX0NPTlRFWFRfU1lNQk9MIH0gZnJvbSAnLi93b3JrZmxvdy9nZXQtd29ya2Zsb3ctbWV0YWRhdGEuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ3JlYXRlSG9vayB9IGZyb20gJy4vd29ya2Zsb3cvaG9vay5qcyc7XG5pbXBvcnQgeyBjcmVhdGVTbGVlcCB9IGZyb20gJy4vd29ya2Zsb3cvc2xlZXAuanMnO1xuXG4vKipcbiAqIERyYWluIHBlbmRpbmcgcXVldWUgaXRlbXMgYXQgd29ya2Zsb3cgY29tcGxldGlvbiAoc3VjY2VzcyBvciBmYWlsdXJlKS5cbiAqXG4gKiBUcmVhdHMgY29tcGxldGlvbiBhcyBhIGZpbmFsIHN1c3BlbnNpb24gc28gdW5hd2FpdGVkIGhvb2ssIHdhaXQsIGFuZFxuICogYXR0cmlidXRlIG9wZXJhdGlvbnMgYXJlIHJlY29yZGVkIGJlZm9yZSB0aGUgcnVuIGJlY29tZXMgdGVybWluYWwuIFRoaXNcbiAqIGFsc28gbGV0cyBhIGZpbmFsIGBjb250cm9sbGVyLmFib3J0KClgIHJlYWNoIGluLWZsaWdodCBzdGVwcy5cbiAqXG4gKiBJdCByZWNvcmRzIGAqX2NyZWF0ZWRgIGFuZCBuYXRpdmUgYXR0cmlidXRlIGV2ZW50cywgYnV0IG5ldmVyIGV4ZWN1dGVzIHN0ZXBcbiAqIGJvZGllczogYHN0ZXBfc3RhcnRlZGAgaXMgcmVqZWN0ZWQgYWZ0ZXIgdGhlIHJ1biBiZWNvbWVzIHRlcm1pbmFsLiBBXG4gKiBmaXJlLWFuZC1mb3JnZXQgc3RlcCB0aGVyZWZvcmUgbmVlZHMgYSBsYXRlciBzdXNwZW5zaW9uIHRvIGJlIHNjaGVkdWxlZC5cbiAqXG4gKiBEcmFpbiBmYWlsdXJlcyBkbyBub3QgY2hhbmdlIHRoZSB3b3JrZmxvdydzIHRlcm1pbmFsIG91dGNvbWUuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRyYWluUGVuZGluZ1F1ZXVlSXRlbXMoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIHBlbmRpbmdRdWV1ZTogTWFwPHN0cmluZywgUXVldWVJdGVtPixcbiAgdm1HbG9iYWxUaGlzOiB0eXBlb2YgZ2xvYmFsVGhpcyxcbiAgd29ya2Zsb3dSdW46IFdvcmtmbG93UnVuLFxuICBvdXRjb21lOiAnY29tcGxldGVkJyB8ICdmYWlsZWQnLFxuICAvKipcbiAgICogSW4gdHVyYm8gbW9kZSwgZ2F0ZXMgZmluYWwgYCpfY3JlYXRlZGAgd3JpdGVzIG9uIGJhY2tncm91bmRlZFxuICAgKiBgcnVuX3N0YXJ0ZWRgLiBVbmRlZmluZWQgd2hlbiBgcnVuX3N0YXJ0ZWRgIGlzIGF3YWl0ZWQuXG4gICAqL1xuICBydW5SZWFkeUJhcnJpZXI/OiBQcm9taXNlPHVua25vd24+XG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHBlbmRpbmdRdWV1ZS5zaXplID09PSAwKSByZXR1cm47XG4gIC8vIEltcGxpY2l0bHkgZGlzcG9zZSBhbnkgYWJvcnQgaG9va3MgKHN5c3RlbSBob29rcykgdGhhdCBhcmUgc3RpbGwgYWxpdmUgYXRcbiAgLy8gd29ya2Zsb3cgY29tcGxldGlvbiBzbyB0aGV5IGRvbid0IGxlYWsgcm93cyBpbiB0aGUgaG9va3MgdGFibGUgZm9yIHRoZVxuICAvLyBydW4ncyBsaWZldGltZS4gU2tpcCBob29rcyB0aGF0IGFscmVhZHkgaGF2ZSBhbiBhYm9ydCBpbiBmbGlnaHQ7IHRob3NlXG4gIC8vIHdpbGwgZW1pdCBob29rX3JlY2VpdmVkIHZpYSB0aGUgYWJvcnQgcHJvY2Vzc2luZyBwYXRoLiBVc2VyIGhvb2tzXG4gIC8vIChpc1N5c3RlbSAhPT0gdHJ1ZSkgYXJlIGludGVudGlvbmFsbHkgbGVmdCBhbG9uZTogdGhlaXIgbGlmZXRpbWUgaXNcbiAgLy8gbWFuYWdlZCBieSB0aGUgdXNlcidzIGNvZGUsIG5vdCB0aGUgcnVudGltZS5cbiAgZm9yIChjb25zdCBpdGVtIG9mIHBlbmRpbmdRdWV1ZS52YWx1ZXMoKSkge1xuICAgIGlmIChcbiAgICAgIGl0ZW0udHlwZSA9PT0gJ2hvb2snICYmXG4gICAgICBpdGVtLmlzU3lzdGVtICYmXG4gICAgICAhaXRlbS5kaXNwb3NlZCAmJlxuICAgICAgIWl0ZW0uYWJvcnRSZXF1ZXN0ZWRcbiAgICApIHtcbiAgICAgIGl0ZW0uZGlzcG9zZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuICB0cnkge1xuICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGQoKTtcbiAgICBjb25zdCBzeW50aGVzaXplZCA9IG5ldyBXb3JrZmxvd1N1c3BlbnNpb24ocGVuZGluZ1F1ZXVlLCB2bUdsb2JhbFRoaXMpO1xuICAgIGF3YWl0IGhhbmRsZVN1c3BlbnNpb24oe1xuICAgICAgc3VzcGVuc2lvbjogc3ludGhlc2l6ZWQsXG4gICAgICB3b3JsZCxcbiAgICAgIHJ1bjogd29ya2Zsb3dSdW4sXG4gICAgICBydW5SZWFkeUJhcnJpZXIsXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgIGBGYWlsZWQgdG8gZHJhaW4gcGVuZGluZyBxdWV1ZSBpdGVtcyBmb3IgJHtvdXRjb21lfSB3b3JrZmxvdyBydW5gLFxuICAgICAge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgbWVzc2FnZTogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgfVxuICAgICk7XG4gIH1cbn1cblxuLyoqIEV2ZXJ5dGhpbmcgbmVlZGVkIHRvIGNvbGQtc3RhcnQgYSB3b3JrZmxvdyBWTSBvdmVyIGFuIGV2ZW50IGxvZy4gKi9cbmludGVyZmFjZSBXb3JrZmxvd1Nlc3Npb25PcHRpb25zIHtcbiAgcmVhZG9ubHkgd29ya2Zsb3dDb2RlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHdvcmtmbG93UnVuOiBXb3JrZmxvd1J1bjtcbiAgcmVhZG9ubHkgZXZlbnRzOiBFdmVudFtdO1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICByZWFkb25seSByZXBsYXlQYXlsb2FkQ2FjaGU6IFJlcGxheVBheWxvYWRDYWNoZTtcbiAgcmVhZG9ubHkgY29tcGlsZWRXb3JrZmxvd1NjcmlwdHM/OiBDb21waWxlZFdvcmtmbG93U2NyaXB0cztcbiAgcmVhZG9ubHkgcnVuUmVhZHlCYXJyaWVyPzogUHJvbWlzZTx1bmtub3duPjtcbiAgcmVhZG9ubHkgd29ybGRDYXBhYmlsaXRpZXM/OiBXb3JsZENhcGFiaWxpdGllcztcbn1cblxuLyoqIENvbnRleHQtaW5kZXBlbmRlbnQgVjggc2NyaXB0cyB0aGF0IGNhbiBiZSBldmFsdWF0ZWQgaW4gYW55IGZyZXNoIFZNLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb21waWxlZFdvcmtmbG93U2NyaXB0cyB7XG4gIHJlYWRvbmx5IGJ1bmRsZVNjcmlwdDogU2NyaXB0O1xuICByZWFkb25seSB3b3JrZmxvd0xvb2t1cFNjcmlwdDogU2NyaXB0O1xufVxuXG4vKipcbiAqIENvbXBpbGUgdGhlIHdvcmtmbG93IGJ1bmRsZSBiZWZvcmUgaXRzIHJ1biBzbmFwc2hvdCBpcyBhdmFpbGFibGUuXG4gKlxuICogQ29tcGlsYXRpb24gZGVwZW5kcyBvbmx5IG9uIHRoZSByb3V0ZSdzIGJ1bmRsZSBzdHJpbmcgYW5kIHRoZSB3b3JrZmxvdyBuYW1lXG4gKiBwZXJzaXN0ZWQgb24gdGhlIHJ1biwgbm90IHRoZSBldmVudCBsb2cgb3IgVk0gY29udGV4dC4gVGhlIHJ1bnRpbWUgc3RhcnRzXG4gKiB0aGlzIHByb21pc2Ugd2hpbGUgYHJ1bl9zdGFydGVkYCBsb2FkcyB0aGUgcmVwbGF5IHNuYXBzaG90LCB0aGVuIGV2YWx1YXRlc1xuICogdGhlIHNjcmlwdHMgb25seSBhZnRlciBpdCBoYXMgY3JlYXRlZCB0aGUgZnJlc2ggY29udGV4dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBpbGVXb3JrZmxvd0J1bmRsZShcbiAgd29ya2Zsb3dDb2RlOiBzdHJpbmcsXG4gIHdvcmtmbG93TmFtZTogc3RyaW5nXG4pOiBQcm9taXNlPENvbXBpbGVkV29ya2Zsb3dTY3JpcHRzPiB7XG4gIGNvbnN0IHBhcnNlZE5hbWUgPSBwYXJzZVdvcmtmbG93TmFtZSh3b3JrZmxvd05hbWUpO1xuICBjb25zdCBmaWxlbmFtZSA9IHBhcnNlZE5hbWU/Lm1vZHVsZVNwZWNpZmllciB8fCB3b3JrZmxvd05hbWU7XG4gIGNvbnN0IHdvcmtmbG93TG9va3VwQ29kZSA9IGBnbG9iYWxUaGlzLl9fcHJpdmF0ZV93b3JrZmxvd3M/LmdldCgke0pTT04uc3RyaW5naWZ5KHdvcmtmbG93TmFtZSl9KWA7XG5cbiAgcmV0dXJuIHRyYWNlKCd3b3JrZmxvdy5idW5kbGUuY29tcGlsZScsIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgY29uc3QgYnVuZGxlID0gZ2V0Q2FjaGVkV29ya2Zsb3dTY3JpcHQod29ya2Zsb3dDb2RlLCBmaWxlbmFtZSk7XG4gICAgY29uc3QgbG9va3VwID0gZ2V0Q2FjaGVkV29ya2Zsb3dTY3JpcHQod29ya2Zsb3dMb29rdXBDb2RlLCBmaWxlbmFtZSk7XG4gICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAvLyBUaGlzIGF0dHJpYnV0ZSBpbnRlbnRpb25hbGx5IGRlc2NyaWJlcyB0aGUgd29ya2Zsb3cgYnVuZGxlLiBUaGUgdGlueVxuICAgICAgLy8gbG9va3VwIHNjcmlwdCBtYXkgbWlzcyB3aGVuIGFub3RoZXIgd29ya2Zsb3cgZnJvbSB0aGUgc2FtZSBzb3VyY2UgZmlsZVxuICAgICAgLy8gcnVucywgYnV0IHRoYXQgZG9lcyBub3QgbWVhbiBWOCByZWNvbXBpbGVkIHRoZSBhcHBsaWNhdGlvbiBidW5kbGUuXG4gICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dCdW5kbGVDb21waWxlQ2FjaGVIaXQoYnVuZGxlLmNhY2hlSGl0KSxcbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgYnVuZGxlU2NyaXB0OiBidW5kbGUuc2NyaXB0LFxuICAgICAgd29ya2Zsb3dMb29rdXBTY3JpcHQ6IGxvb2t1cC5zY3JpcHQsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogQSBsaXZlIHdvcmtmbG93IFZNLCBwYXJrZWQgYXQgYSBzdXNwZW5zaW9uIGJvdW5kYXJ5LiBgcmVzdW1lYCBhZHZhbmNlcyBpdFxuICogYnkgYXBwZW5kaW5nIGV2ZW50cyBpbnN0ZWFkIG9mIHJlcGxheWluZyBmcm9tIHNjcmF0Y2guXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV29ya2Zsb3dTZXNzaW9uIHtcbiAgcmVhZG9ubHkgd29ya2Zsb3dSdW46IFdvcmtmbG93UnVuO1xuICByZWFkb25seSBhcmd1bWVudENvdW50OiBudW1iZXI7XG4gIHJlc3VtZShldmVudHM6IEV2ZW50W10pOiBQcm9taXNlPFdvcmtmbG93UmVzdW1lUmVzdWx0Pjtcbn1cblxuLyoqIEEgZmluaXNoZWQgZXhlY3V0aW9uIGF0dGVtcHQ6IHRoZSB3b3JrZmxvdydzIG91dHB1dCBvciBhIGxpdmUgYm91bmRhcnkuICovXG5leHBvcnQgdHlwZSBXb3JrZmxvd1Jlc3VsdCA9XG4gIHwge1xuICAgICAgcmVhZG9ubHkgdHlwZTogJ2NvbXBsZXRlZCc7XG4gICAgICByZWFkb25seSBvdXRwdXQ6IHVua25vd247XG4gICAgICAvKiogYHR5cGVvZmAgdGhlIHJhdyByZXR1cm4gdmFsdWUsIGZvciB0ZWxlbWV0cnkuICovXG4gICAgICByZWFkb25seSByZXN1bHRUeXBlOiBzdHJpbmc7XG4gICAgfVxuICB8IHtcbiAgICAgIHJlYWRvbmx5IHR5cGU6ICdzdXNwZW5kZWQnO1xuICAgICAgcmVhZG9ubHkgc3VzcGVuc2lvbjogV29ya2Zsb3dTdXNwZW5zaW9uO1xuICAgICAgcmVhZG9ubHkgc2Vzc2lvbjogV29ya2Zsb3dTZXNzaW9uO1xuICAgICAgLyoqXG4gICAgICAgKiBFdmVudHMgdGhlIHJlcGxheSB3YWxrZWQgcGFzdCB1bmNsYWltZWQgYW5kIGlzIHN0aWxsIGhvbGRpbmcsIGlmIGFueS5cbiAgICAgICAqIE9yZGluYXJ5IG9uIGEgc3VzcGVuc2lvbiwgYW5kIG9ubHkgYWN0aW9uYWJsZSBhY3Jvc3MgYSBydW4nc1xuICAgICAgICogc3VzcGVuc2lvbnMsIHNvIGl0IGlzIHJlcG9ydGVkIGZvciB0ZWxlbWV0cnkgcmF0aGVyIHRoYW4gYWN0ZWQgb24gaGVyZS5cbiAgICAgICAqL1xuICAgICAgcmVhZG9ubHkgcGFya2VkPzoge1xuICAgICAgICByZWFkb25seSBjb3VudDogbnVtYmVyO1xuICAgICAgICByZWFkb25seSBldmVudElkOiBzdHJpbmc7XG4gICAgICAgIHJlYWRvbmx5IGV2ZW50VHlwZTogc3RyaW5nO1xuICAgICAgfTtcbiAgICB9O1xuXG4vKipcbiAqIGByZXN1bWVgIGNhbiBhZGRpdGlvbmFsbHkgZGVjbGluZTogYHsgdHlwZTogJ3JlcGxheScgfWAgbWVhbnMgXCJ0aGlzXG4gKiBzZXNzaW9uIGlzIHVudXNhYmxlLCBjb2xkLXJlcGxheSBpbnN0ZWFkXCIuIEEgZnJlc2ggcmVwbGF5IG5ldmVyIGRlY2xpbmVzLlxuICovXG5leHBvcnQgdHlwZSBXb3JrZmxvd1Jlc3VtZVJlc3VsdCA9IFdvcmtmbG93UmVzdWx0IHwgeyByZWFkb25seSB0eXBlOiAncmVwbGF5JyB9O1xuXG4vKiogVGhlIHNlc3Npb24ncyBwcml2YXRlIHN0YXRlIG1hY2hpbmUuICovXG50eXBlIFdvcmtmbG93U2Vzc2lvblN0YXRlID1cbiAgfCB7XG4gICAgICByZWFkb25seSB0eXBlOiAncnVubmluZyc7XG4gICAgICByZWFkb25seSBpbnRlcnJ1cHRpb246IFByb21pc2VXaXRoUmVzb2x2ZXJzPG5ldmVyPjtcbiAgICB9XG4gIHwgeyByZWFkb25seSB0eXBlOiAnc3VzcGVuZGVkJzsgcmVhZG9ubHkgc3VzcGVuc2lvbjogV29ya2Zsb3dTdXNwZW5zaW9uIH1cbiAgfCB7IHJlYWRvbmx5IHR5cGU6ICdyZXBsYXknIH1cbiAgfCB7IHJlYWRvbmx5IHR5cGU6ICdjb21wbGV0ZWQnIH07XG5cbi8qKiBDb2xkLXN0YXJ0OiBidWlsZCBhIGZyZXNoIFZNIHNlc3Npb24gYW5kIHJlcGxheSBpdCBvdmVyIGBldmVudHNgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxheVdvcmtmbG93KFxuICBvcHRpb25zOiBXb3JrZmxvd1Nlc3Npb25PcHRpb25zXG4pOiBQcm9taXNlPFdvcmtmbG93UmVzdWx0PiB7XG4gIHJldHVybiB0cmFjZUV4ZWN1dGlvbihcbiAgICAncmVwbGF5JyxcbiAgICBvcHRpb25zLndvcmtmbG93UnVuLFxuICAgIG9wdGlvbnMuZXZlbnRzLFxuICAgIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgICBjb25zdCB7IHNlc3Npb24sIGV4ZWN1dGlvbiB9ID0gYXdhaXQgY3JlYXRlV29ya2Zsb3dTZXNzaW9uKG9wdGlvbnMpO1xuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0FyZ3VtZW50c0NvdW50KHNlc3Npb24uYXJndW1lbnRDb3VudCksXG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZWNvcmRSZXN1bHQoYXdhaXQgZXhlY3V0aW9uLCBzcGFuKTtcbiAgICB9XG4gICk7XG59XG5cbi8qKiBXYXJtLXN0YXJ0OiBhZHZhbmNlIGEgcmV0YWluZWQgc2Vzc2lvbiBieSBhcHBlbmRpbmcgZXZlbnRzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc3VtZVdvcmtmbG93KFxuICBzZXNzaW9uOiBXb3JrZmxvd1Nlc3Npb24sXG4gIGV2ZW50czogRXZlbnRbXVxuKTogUHJvbWlzZTxXb3JrZmxvd1Jlc3VtZVJlc3VsdD4ge1xuICByZXR1cm4gdHJhY2VFeGVjdXRpb24oXG4gICAgJ3JldGFpbmVkJyxcbiAgICBzZXNzaW9uLndvcmtmbG93UnVuLFxuICAgIGV2ZW50cyxcbiAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0FyZ3VtZW50c0NvdW50KHNlc3Npb24uYXJndW1lbnRDb3VudCksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlc3Npb24ucmVzdW1lKGV2ZW50cyk7XG4gICAgICByZXR1cm4gcmVzdWx0LnR5cGUgPT09ICdyZXBsYXknID8gcmVzdWx0IDogcmVjb3JkUmVzdWx0KHJlc3VsdCwgc3Bhbik7XG4gICAgfVxuICApO1xufVxuXG5mdW5jdGlvbiB0cmFjZUV4ZWN1dGlvbjxUPihcbiAgbW9kZTogJ3JlcGxheScgfCAncmV0YWluZWQnLFxuICB3b3JrZmxvd1J1bjogV29ya2Zsb3dSdW4sXG4gIGV2ZW50czogRXZlbnRbXSxcbiAgZm46IChzcGFuOiBTcGFuIHwgdW5kZWZpbmVkKSA9PiBQcm9taXNlPFQ+XG4pOiBQcm9taXNlPFQ+IHtcbiAgcmV0dXJuIHRyYWNlKGB3b3JrZmxvdy5ydW4gJHt3b3JrZmxvd1J1bi53b3JrZmxvd05hbWV9YCwgKHNwYW4pID0+IHtcbiAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUod29ya2Zsb3dSdW4ud29ya2Zsb3dOYW1lKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKHdvcmtmbG93UnVuLnJ1bklkKSxcbiAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cyh3b3JrZmxvd1J1bi5zdGF0dXMpLFxuICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93RXZlbnRzQ291bnQoZXZlbnRzLmxlbmd0aCksXG4gICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFeGVjdXRpb25Nb2RlKG1vZGUpLFxuICAgIH0pO1xuICAgIHJldHVybiBmbihzcGFuKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlY29yZFJlc3VsdChcbiAgcmVzdWx0OiBXb3JrZmxvd1Jlc3VsdCxcbiAgc3BhbjogU3BhbiB8IHVuZGVmaW5lZFxuKTogV29ya2Zsb3dSZXN1bHQge1xuICBpZiAocmVzdWx0LnR5cGUgPT09ICdjb21wbGV0ZWQnKSB7XG4gICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSZXN1bHRUeXBlKHJlc3VsdC5yZXN1bHRUeXBlKSxcbiAgICB9KTtcbiAgfSBlbHNlIGlmIChzcGFuKSB7XG4gICAgYXBwbHlXb3JrZmxvd1N1c3BlbnNpb25Ub1NwYW4ocmVzdWx0LnN1c3BlbnNpb24sIHNwYW4pO1xuICAgIC8vIEV2ZW50cyB0aGlzIHBhc3Mgd2Fsa2VkIHBhc3QgdW5jbGFpbWVkIGFuZCBpcyBzdGlsbCBob2xkaW5nLiBPcmRpbmFyeSBvblxuICAgIC8vIGEgc3VzcGVuc2lvbjogYW4gb3V0LW9mLWJhbmQgZGVsaXZlcnkgdGhhdCBsYW5kZWQgYWhlYWQgb2YgdGhlIGNvZGUgdGhhdFxuICAgIC8vIHJlYWRzIGl0IHdhaXRzIGZvciB0aGUgcGFzcyB0aGF0IHJlYWNoZXMgdGhhdCBjb2RlLCBhbmQgZmFpbGluZyBoZXJlXG4gICAgLy8gd291bGQgZmFpbCBleGFjdGx5IHRoZSBydW5zIHRoYXQgdG9sZXJhbmNlIGV4aXN0cyBmb3IuIFRoZSBjYXNlIHRoYXQgaXNcbiAgICAvLyBub3Qgb3JkaW5hcnkgKHRoZSBzYW1lIGV2ZW50IHN0aWxsIGhlbGQgcGFzcyBhZnRlciBwYXNzKSBpcyBhIHNoYXBlXG4gICAgLy8gYWNyb3NzIHRoZXNlIHNwYW5zLCB3aGljaCBpcyB3aHkgdGhlIGV2ZW50SWQgaXMgb24gZWFjaCBvbmUgYW5kIG5vIHBhc3NcbiAgICAvLyB0cmllcyB0byBydWxlIG9uIGl0IGFsb25lLlxuICAgIGlmIChyZXN1bHQucGFya2VkKSB7XG4gICAgICBzcGFuLnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dQYXJrZWRFdmVudHNDb3VudChyZXN1bHQucGFya2VkLmNvdW50KSxcbiAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UGFya2VkRXZlbnRJZChyZXN1bHQucGFya2VkLmV2ZW50SWQpLFxuICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dQYXJrZWRFdmVudFR5cGUocmVzdWx0LnBhcmtlZC5ldmVudFR5cGUpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogU2luZ2xlLXNob3QgcmVwbGF5OiBleGVjdXRlIHRoZSB3b3JrZmxvdyBvdmVyIGBldmVudHNgIGFuZCBlaXRoZXIgcmV0dXJuXG4gKiBpdHMgb3V0cHV0IG9yIHRocm93IGl0cyBzdXNwZW5zaW9uLiBLZXB0IGZvciB0aGUgZXh0ZW5zaXZlIGV4aXN0aW5nIHRlc3RcbiAqIHN1aXRlczsgcHJvZHVjdGlvbiBjb2RlIGdvZXMgdGhyb3VnaCBgcmVwbGF5V29ya2Zsb3dgL2ByZXN1bWVXb3JrZmxvd2AuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5Xb3JrZmxvdyhcbiAgd29ya2Zsb3dDb2RlOiBzdHJpbmcsXG4gIHdvcmtmbG93UnVuOiBXb3JrZmxvd1J1bixcbiAgZXZlbnRzOiBFdmVudFtdLFxuICBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkLFxuICAvKipcbiAgICogT3B0aW9uYWwgcGVyLXJ1biBjYWNoZSBmb3IgcmVwbGF5IHBheWxvYWQgcHJlcGFyYXRpb24gYW5kIGltbXV0YWJsZSBmaW5hbFxuICAgKiB2YWx1ZXMuIE93bmVkIGJ5IHRoZSBpbmxpbmUgZXhlY3V0aW9uIGxvb3AgZm9yIHRoaXMgaW52b2NhdGlvbi5cbiAgICovXG4gIHJlcGxheVBheWxvYWRDYWNoZTogUmVwbGF5UGF5bG9hZENhY2hlID0gbmV3IFJlcGxheVBheWxvYWRDYWNoZShcbiAgICBlbmNyeXB0aW9uS2V5XG4gICksXG4gIC8qKlxuICAgKiBUdXJibyBtb2RlIG9ubHk6IHJlc29sdmVzIG9uY2UgdGhlIGJhY2tncm91bmRlZCBgcnVuX3N0YXJ0ZWRgIGhhcyBsYW5kZWQuXG4gICAqIFRocmVhZGVkIGludG8gdGhlIGVuZC1vZi1ydW4gZHJhaW4gc28gZmlyZS1hbmQtZm9yZ2V0IGAqX2NyZWF0ZWRgIHdyaXRlc1xuICAgKiBjb21taXR0ZWQgYXQgd29ya2Zsb3cgY29tcGxldGlvbiBvcmRlciBhZnRlciB0aGUgcnVuJ3MgY3JlYXRpb24uIFVuZGVmaW5lZFxuICAgKiBvdXRzaWRlIHR1cmJvLCB3aGVyZSBgcnVuX3N0YXJ0ZWRgIGlzIGF3YWl0ZWQgdXAgZnJvbnQuXG4gICAqL1xuICBydW5SZWFkeUJhcnJpZXI/OiBQcm9taXNlPHVua25vd24+LFxuICAvKipcbiAgICogRmVhdHVyZXMgc3VwcG9ydGVkIGJ5IHRoZSBXb3JsZCBleGVjdXRpbmcgdGhpcyB3b3JrZmxvdy4gTWlzc2luZ1xuICAgKiBjYXBhYmlsaXRpZXMgYXJlIHRyZWF0ZWQgYXMgdW5zdXBwb3J0ZWQuXG4gICAqL1xuICB3b3JsZENhcGFiaWxpdGllcz86IFdvcmxkQ2FwYWJpbGl0aWVzXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJlcGxheVdvcmtmbG93KHtcbiAgICB3b3JrZmxvd0NvZGUsXG4gICAgd29ya2Zsb3dSdW4sXG4gICAgZXZlbnRzLFxuICAgIGVuY3J5cHRpb25LZXksXG4gICAgcmVwbGF5UGF5bG9hZENhY2hlLFxuICAgIHJ1blJlYWR5QmFycmllcixcbiAgICB3b3JsZENhcGFiaWxpdGllcyxcbiAgfSk7XG4gIGlmIChyZXN1bHQudHlwZSA9PT0gJ3N1c3BlbmRlZCcpIHRocm93IHJlc3VsdC5zdXNwZW5zaW9uO1xuICByZXR1cm4gcmVzdWx0Lm91dHB1dDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlV29ya2Zsb3dTZXNzaW9uKG9wdGlvbnM6IFdvcmtmbG93U2Vzc2lvbk9wdGlvbnMpIHtcbiAgY29uc3Qgdm1UcmFjZSA9IGF3YWl0IHN0YXJ0VHJhY2VTcGFuKCd3b3JrZmxvdy52bS5jcmVhdGVfY29udGV4dCcpO1xuICByZXR1cm4gY3JlYXRlV29ya2Zsb3dTZXNzaW9uSW5uZXIob3B0aW9ucywgdm1UcmFjZS5lbmQpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgIHZtVHJhY2UuZmFpbChlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVXb3JrZmxvd1Nlc3Npb25Jbm5lcihcbiAge1xuICAgIHdvcmtmbG93Q29kZSxcbiAgICB3b3JrZmxvd1J1bixcbiAgICBldmVudHMsXG4gICAgZW5jcnlwdGlvbktleSxcbiAgICByZXBsYXlQYXlsb2FkQ2FjaGUsXG4gICAgY29tcGlsZWRXb3JrZmxvd1NjcmlwdHMsXG4gICAgcnVuUmVhZHlCYXJyaWVyLFxuICAgIHdvcmxkQ2FwYWJpbGl0aWVzLFxuICB9OiBXb3JrZmxvd1Nlc3Npb25PcHRpb25zLFxuICBlbmRWbVRyYWNlOiAoKSA9PiB2b2lkXG4pOiBQcm9taXNlPHtcbiAgc2Vzc2lvbjogV29ya2Zsb3dTZXNzaW9uO1xuICBleGVjdXRpb246IFByb21pc2U8V29ya2Zsb3dSZXN1bHQ+O1xufT4ge1xuICBjb25zdCBzdGFydGVkQXQgPSB3b3JrZmxvd1J1bi5zdGFydGVkQXQ7XG4gIGlmICghc3RhcnRlZEF0KSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgYFdvcmtmbG93IHJ1biBcIiR7d29ya2Zsb3dSdW4ucnVuSWR9XCIgaGFzIG5vIFwic3RhcnRlZEF0XCIgdGltZXN0YW1wIChzaG91bGQgbm90IGhhcHBlbilgXG4gICAgKTtcbiAgfVxuXG4gIC8vIFNlZWQgYW5kIGluaXRpYWwgY2xvY2sgbXVzdCBiZSBhdmFpbGFibGUgYmVmb3JlIEkvTyBhbmQgcmVtYWluIHN0YWJsZSBvblxuICAvLyByZXBsYXkuIEFmdGVyIHRoZSBmaXJzdCBldmVudCwgRXZlbnRzQ29uc3VtZXIgYWR2YW5jZXMgdGhlIFZNIGNsb2NrIGZyb21cbiAgLy8gZWFjaCBldmVudCdzIGBjcmVhdGVkQXRgLlxuICBjb25zdCBmaXhlZFRpbWVzdGFtcCA9XG4gICAgcnVuSWRDcmVhdGVkQXQod29ya2Zsb3dSdW4ucnVuSWQpID8/ICt3b3JrZmxvd1J1bi5jcmVhdGVkQXQ7XG5cbiAgLy8gVHJ1dGhpbmVzcywgbm90IHByZXNlbmNlOiBgdmVyY2VsIGVudiBwdWxsYCB3cml0ZXMgYFZFUkNFTF9VUkw9XCJcImAgaW50b1xuICAvLyBgLmVudi5sb2NhbGAsIGFuZCBhIGZyYW1ld29yayB0aGF0IGxvYWRzIHRoYXQgZmlsZSBsb2NhbGx5IHdvdWxkIG90aGVyd2lzZVxuICAvLyBwdXQgdXMgb24gdGhlIFZlcmNlbCBicmFuY2ggd2l0aCBub3RoaW5nIHRvIGJ1aWxkIGEgaG9zdCBmcm9tLCBtYWtpbmdcbiAgLy8gYGh0dHBzOi8vYCB0aGUgYmFzZSBVUkwgb2YgZXZlcnkgcnVuLlxuICBjb25zdCBpc1ZlcmNlbCA9IEJvb2xlYW4ocHJvY2Vzcy5lbnYuVkVSQ0VMX1VSTCk7XG4gIC8vIExvYWQgZ2V0UG9ydCBsYXppbHkgdG8gcHJldmVudCBUdXJib3BhY2sgZnJvbSB0cmFjaW5nIGdldC1wb3J0J3NcbiAgLy8gZnMgb3BzIChyZWFkZGlyLCByZWFkRmlsZSkgaW50byB0aGUgZmxvdyByb3V0ZSBidW5kbGUuIFRoZSByZXNvbHZlZFxuICAvLyBwb3J0IGlzIGNhY2hlZCBwZXIgcHJvY2VzcyAoc2VlIGdldC1wb3J0LWxhenkudHMpLCBzbyB0aGlzIGlzIGNoZWFwXG4gIC8vIG9uIHJlcGxheXMgYWZ0ZXIgdGhlIGZpcnN0LlxuICBjb25zdCB3b3JrZmxvd0Jhc2VVcmwgPSBjcmVhdGVXb3JrZmxvd0Jhc2VVcmwoXG4gICAgaXNWZXJjZWxcbiAgICAgID8gYGh0dHBzOi8vJHtwcm9jZXNzLmVudi5WRVJDRUxfVVJMfWBcbiAgICAgIDogYGh0dHA6Ly9sb2NhbGhvc3Q6JHsoYXdhaXQgZ2V0UG9ydExhenkoKSkgPz8gMzAwMH1gXG4gICk7XG4gIC8vIEluY2x1ZGUgYm90aCBub2RlOnZtJ3MgY29udGV4dCBjcmVhdGlvbiBhbmQgdGhlIGhvc3Qtc2lkZSBzYW5kYm94IHdpcmluZ1xuICAvLyBiZWxvdy4gTW9zdCBvZiB0aGUgYm9vdHN0cmFwIGxpdmVzIGluIHRoaXMgZnVuY3Rpb24gKEV2ZW50c0NvbnN1bWVyLFxuICAvLyB3b3JrZmxvdyBnbG9iYWxzLCBXZWIgQVBJIHNoaW1zKSwgc28gdHJhY2luZyBjcmVhdGVDb250ZXh0KCkgYWxvbmUgd291bGRcbiAgLy8gbWF0ZXJpYWxseSB1bmRlci1yZXBvcnQgVk0gc3RhcnR1cC5cbiAgY29uc3Qge1xuICAgIGNvbnRleHQsXG4gICAgZ2xvYmFsVGhpczogdm1HbG9iYWxUaGlzLFxuICAgIHVwZGF0ZVRpbWVzdGFtcCxcbiAgfSA9IGNyZWF0ZUNvbnRleHQoe1xuICAgIHNlZWQ6IGAke3dvcmtmbG93UnVuLnJ1bklkfToke3dvcmtmbG93UnVuLndvcmtmbG93TmFtZX06JHt3b3JrZmxvd1J1bi5kZXBsb3ltZW50SWR9YCxcbiAgICBmaXhlZFRpbWVzdGFtcCxcbiAgfSk7XG5cbiAgY29uc3QgaW5pdGlhbEludGVycnVwdGlvbiA9IHdpdGhSZXNvbHZlcnM8bmV2ZXI+KCk7XG4gIGxldCBzdGF0ZTogV29ya2Zsb3dTZXNzaW9uU3RhdGUgPSB7XG4gICAgdHlwZTogJ3J1bm5pbmcnLFxuICAgIGludGVycnVwdGlvbjogaW5pdGlhbEludGVycnVwdGlvbixcbiAgfTtcblxuICBjb25zdCBvbldvcmtmbG93RXJyb3IgPSAoZXJyb3I6IEVycm9yKTogdm9pZCA9PiB7XG4gICAgc3dpdGNoIChzdGF0ZS50eXBlKSB7XG4gICAgICBjYXNlICdydW5uaW5nJzoge1xuICAgICAgICBjb25zdCB7IGludGVycnVwdGlvbiB9ID0gc3RhdGU7XG4gICAgICAgIHN0YXRlID0gV29ya2Zsb3dTdXNwZW5zaW9uLmlzKGVycm9yKVxuICAgICAgICAgID8geyB0eXBlOiAnc3VzcGVuZGVkJywgc3VzcGVuc2lvbjogZXJyb3IgfVxuICAgICAgICAgIDogeyB0eXBlOiAncmVwbGF5JyB9O1xuICAgICAgICAvLyBTdGVwLCBob29rLCB3YWl0LCBhbmQgYXR0cmlidXRlIGNvbnN1bWVycyBjYW4gc2NoZWR1bGUgdGhlIHNhbWVcbiAgICAgICAgLy8gc3VzcGVuc2lvbi4gVGhlIGZpcnN0IHNpZ25hbCBhZHZhbmNlcyB0aGUgZ2VuZXJhdGlvbiBzbyB0aGUgcmVzdFxuICAgICAgICAvLyBuby1vcC5cbiAgICAgICAgd29ya2Zsb3dDb250ZXh0LnN1c3BlbnNpb25HZW5lcmF0aW9uKys7XG4gICAgICAgIGludGVycnVwdGlvbi5yZWplY3QoZXJyb3IpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjYXNlICdzdXNwZW5kZWQnOlxuICAgICAgICAvLyBTYW1lLWJvdW5kYXJ5IGR1cGxpY2F0ZXMgd2VyZSBzdGFsZWQgYnkgdGhlIGdlbmVyYXRpb24gYnVtcCBhYm92ZSxcbiAgICAgICAgLy8gc28gYW55dGhpbmcgbGFuZGluZyBoZXJlIGlzIG91dC1vZi1iYW5kIG9yIGEgZGl2ZXJnZW5jZS4gRmFsbCBiYWNrXG4gICAgICAgIC8vIHRvIHJlcGxheSByYXRoZXIgdGhhbiByZXN1bWluZyBhIHBvdGVudGlhbGx5IGluY29uc2lzdGVudCBzZXNzaW9uLlxuICAgICAgICBzdGF0ZSA9IHsgdHlwZTogJ3JlcGxheScgfTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgY2FzZSAncmVwbGF5JzpcbiAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3RhdGUgc2F0aXNmaWVzIG5ldmVyO1xuICB9O1xuXG4gIGNvbnN0IHVsaWQgPSBtb25vdG9uaWNGYWN0b3J5KCgpID0+IHZtR2xvYmFsVGhpcy5NYXRoLnJhbmRvbSgpKTtcbiAgLy8gQ29ycmVsYXRpb24gSURzIG11c3QgYmUgcmVwbGF5LXN0YWJsZS4gYHN0YXJ0ZWRBdGAgZGlmZmVycyBiZXR3ZWVuIGEgdHVyYm9cbiAgLy8gZGVsaXZlcnkgYW5kIGEgbGF0ZXIgc2VydmVyLWJhY2tlZCByZXBsYXksIHNvIHVzZSBmaXhlZFRpbWVzdGFtcC5cbiAgLy8gVGhlIGRyYXcgY291bnRlciBpcyB0aGUgcHJvZ3Jlc3MgbWV0cmljIGZvciBgcXVpZXNjZUVhcmxpZXJDYXNjYWRlc2BcbiAgLy8gKFdPUktGTE9XX0xPR19PUkRFUl9EUkFXUyk6IGEgcXVpZXQgdHVybiBpcyBvbmUgdGhhdCBkcmV3IG5vdGhpbmcuIEl0XG4gIC8vIGNvdW50cyBFVkVSWSBkcmF3IGZyb20gdGhpcyBzZXF1ZW5jZS4gVGhpcyBzYW1lIGZ1bmN0aW9uIGlzIGluc3RhbGxlZCBhc1xuICAvLyB0aGUgYFNUQUJMRV9VTElEYCBnbG9iYWwgYmVsb3csIHdoaWNoIHNlcmlhbGl6YXRpb24gZHJhd3Mgc3RyZWFtIGlkc1xuICAvLyBmcm9tIGR1cmluZyBkZWh5ZHJhdGlvbi4gVGhpcyBpcyBkZWxpYmVyYXRlIGJlY2F1c2UgcXVpZXNjZW5jZSBtdXN0IGFsc29cbiAgLy8gd2FpdCBvdXQgc2VyaWFsaXphdGlvbi1kcml2ZW4gZHJhd3MsIGFuZCBjb3VudGluZyBleHRyYSBkcmF3cyBvbmx5IGV4dGVuZHNcbiAgLy8gdGhlIHdhaXQgKHNlZSB0aGUgdGVybWluYXRpb24gbm90ZSBvbiBgcXVpZXNjZUVhcmxpZXJDYXNjYWRlc2ApLlxuICBsZXQgbWludENvdW50ID0gMDtcbiAgY29uc3QgZ2VuZXJhdGVVbGlkID0gKCkgPT4ge1xuICAgIG1pbnRDb3VudCArPSAxO1xuICAgIHJldHVybiB1bGlkKGZpeGVkVGltZXN0YW1wKTtcbiAgfTtcbiAgY29uc3QgZ2VuZXJhdGVOYW5vaWQgPSBuYW5vaWQuY3VzdG9tUmFuZG9tKG5hbm9pZC51cmxBbHBoYWJldCwgMjEsIChzaXplKSA9PlxuICAgIG5ldyBVaW50OEFycmF5KHNpemUpLm1hcCgoKSA9PiAyNTYgKiB2bUdsb2JhbFRoaXMuTWF0aC5yYW5kb20oKSlcbiAgKTtcblxuICAvLyBDcmVhdGUgYSBtdXRhYmxlIGhvbGRlciBmb3IgdGhlIHByb21pc2UgcXVldWUgc28gdGhlIEV2ZW50c0NvbnN1bWVyXG4gIC8vIGNhbiBhY2Nlc3MgdGhlIGN1cnJlbnQgcXVldWUgc3RhdGUgdmlhIGEgZ2V0dGVyLiBUaGUgcXVldWUgaXMgbXV0YXRlZFxuICAvLyBieSBzdGVwL2hvb2svc2xlZXAgY2FsbGJhY2tzIGFzIGV2ZW50cyBhcmUgcHJvY2Vzc2VkLlxuICBjb25zdCBwcm9taXNlUXVldWVIb2xkZXIgPSB7IGN1cnJlbnQ6IFByb21pc2UucmVzb2x2ZSgpIH07XG5cbiAgLy8gU2FtZSByZWFzb24gYXMgdGhlIHF1ZXVlIGhvbGRlcjogdGhlIGNvbnN1bWVyIGlzIGJ1aWx0IGJlZm9yZSB0aGUgY29udGV4dFxuICAvLyB3aG9zZSBkZWxpdmVyeSBzdGF0ZSBpdCBoYXMgdG8gcmVhZC4gSWRsZSB1bnRpbCB0aGUgY29udGV4dCBleGlzdHMsIHdoaWNoXG4gIC8vIGlzIGJlZm9yZSBhbnkgZGVsaXZlcnkgY2FuIGJlIHJlZ2lzdGVyZWQgYWdhaW5zdCBpdC5cbiAgY29uc3QgZGVsaXZlcnlJZGxlSG9sZGVyID0geyBjdXJyZW50OiAoKTogYm9vbGVhbiA9PiB0cnVlIH07XG5cbiAgLy8gVGhlIFZNIGNsb2NrIG9ubHkgZXZlciBtb3ZlcyBmb3J3YXJkLiBDb25zdW1wdGlvbiBvcmRlciBpcyBsb2cgb3JkZXIgZm9yXG4gIC8vIGV2ZXJ5dGhpbmcgd2hvc2Ugb3JkZXIgdGhlIHJlcGxheSBkZWNpZGVzLCBidXQgYW4gZXZlbnQgdGhlIGNvbnN1bWVyXG4gIC8vIHBhcmtlZCBpcyBkZWxpdmVyZWQgYWZ0ZXIgdGhlIHdhbGsgaGFzIGFscmVhZHkgcGFzc2VkIGV2ZW50cyB3cml0dGVuIGFmdGVyXG4gIC8vIGl0LCBhbmQgbGV0dGluZyBpdHMgYGNyZWF0ZWRBdGAgc2V0IHRoZSBjbG9jayB3b3VsZCBtYWtlIGBEYXRlLm5vdygpYCBnb1xuICAvLyBiYWNrd2FyZHMgaW5zaWRlIGEgc2luZ2xlIHJlcGxheS5cbiAgbGV0IGNsb2NrID0gZml4ZWRUaW1lc3RhbXA7XG5cbiAgY29uc3QgZXZlbnRzQ29uc3VtZXIgPSBuZXcgRXZlbnRzQ29uc3VtZXIoZXZlbnRzLCB7XG4gICAgb25Db25zdW1lZEV2ZW50OiAoZXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IGF0ID0gK2V2ZW50LmNyZWF0ZWRBdDtcbiAgICAgIGlmIChhdCA+IGNsb2NrKSB7XG4gICAgICAgIGNsb2NrID0gYXQ7XG4gICAgICAgIHVwZGF0ZVRpbWVzdGFtcChhdCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBvblVuY29uc3VtZWRFdmVudDogKGV2ZW50KSA9PiB7XG4gICAgICBvbldvcmtmbG93RXJyb3IoXG4gICAgICAgIG5ldyBSZXBsYXlEaXZlcmdlbmNlRXJyb3IoXG4gICAgICAgICAgYFJlcGxheSBjb3VsZCBub3QgY29uc3VtZSBldmVudDogZXZlbnRUeXBlPSR7ZXZlbnQuZXZlbnRUeXBlfSwgY29ycmVsYXRpb25JZD0ke2V2ZW50LmNvcnJlbGF0aW9uSWR9LCBldmVudElkPSR7ZXZlbnQuZXZlbnRJZH0uYCxcbiAgICAgICAgICB7IGV2ZW50SWQ6IGV2ZW50LmV2ZW50SWQgfVxuICAgICAgICApXG4gICAgICApO1xuICAgIH0sXG4gICAgLy8gQm90aCBicmFuY2hlcyBsb2cgYXQgYGRlYnVnYCwgc28gbmVpdGhlciByZWFjaGVzIHRoZSBjb25zb2xlIHVubGVzc1xuICAgIC8vIGBERUJVR2AgbWF0Y2hlcy4gQSBkdXBsaWNhdGUgaXMgYSBwZXJtYW5lbnQgZmVhdHVyZSBvZiB0aGUgbG9nOiBldmVyeVxuICAgIC8vIGxhdGVyIHJlcGxheSByZS1yZWFkcyBpdCBhbmQgbGFuZHMgaGVyZSBhZ2Fpbiwgc28gYW55dGhpbmcgdGhlIGxvZ2dlclxuICAgIC8vIHByaW50cyB1bmNvbmRpdGlvbmFsbHkgd291bGQgcHJpbnQgb25jZSBwZXIgcmVwbGF5IGZvciB0aGUgbGlmZSBvZiB0aGVcbiAgICAvLyBydW4uIFRoZXJlIGlzIGFsc28gbm90aGluZyB0byBhY3Qgb24uIElnbm9yaW5nIHRoZSBldmVudCBpcyB0aGUgY29ycmVjdFxuICAgIC8vIG91dGNvbWUsIG5vdCBhIGRlZ3JhZGVkIG9uZSwgYW5kIG5vIHVzZXIgY2hhbmdlIG1ha2VzIHRoZSBzdHJhZ2dsZXIgZ29cbiAgICAvLyBhd2F5LiBXaGF0IHRoZSBsZXZlbHMgYXJlIGZvciBpcyBkaWFnbm9zaXMgYWZ0ZXIgdGhlIGZhY3QsIHdoaWNoIGlzXG4gICAgLy8gZXhhY3RseSB3aGF0IGBERUJVRz13b3JrZmxvdzpydW50aW1lOmRlYnVnYCBpcyBmb3IuXG4gICAgb25EdXBsaWNhdGVFdmVudDogKGV2ZW50LCBmaXJzdEV2ZW50VHlwZSkgPT4ge1xuICAgICAgY29uc3QgZGV0YWlscyA9IHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogd29ya2Zsb3dSdW4ucnVuSWQsXG4gICAgICAgIGV2ZW50SWQ6IGV2ZW50LmV2ZW50SWQsXG4gICAgICAgIGV2ZW50VHlwZTogZXZlbnQuZXZlbnRUeXBlLFxuICAgICAgICBmaXJzdEV2ZW50VHlwZSxcbiAgICAgICAgY29ycmVsYXRpb25JZDogZXZlbnQuY29ycmVsYXRpb25JZCxcbiAgICAgIH07XG4gICAgICBpZiAoZmlyc3RFdmVudFR5cGUgIT09IGV2ZW50LmV2ZW50VHlwZSkge1xuICAgICAgICAvLyBUd28gd3JpdGVycyByZWFjaGVkIG9wcG9zaXRlIGNvbmNsdXNpb25zIGFib3V0IG9uZSBlbnRpdHk6IGFcbiAgICAgICAgLy8gYHN0ZXBfZmFpbGVkYCBiZWhpbmQgYSBgc3RlcF9jb21wbGV0ZWRgLCBvciB0aGUgcmV2ZXJzZS4gSWdub3JpbmcgaXRcbiAgICAgICAgLy8gaXMgc3RpbGwgY29ycmVjdCBhbmQgc3RpbGwgZGV0ZXJtaW5pc3RpYyAocmVwbGF5IHJlYWRzIHRoZSBmaXJzdCBvbmVcbiAgICAgICAgLy8gYXQgdGhlIHNhbWUgcG9zaXRpb24gZXZlcnkgdGltZSksIGJ1dCB1bmxpa2UgYSByZS1jb21taXQgb2YgdGhlIHNhbWVcbiAgICAgICAgLy8gb3V0Y29tZSB0aGVyZSBpcyBubyByZWFkaW5nIG9mIHRoaXMgd2hlcmUgYm90aCB3cml0ZXJzIHdlcmUgcmlnaHQsXG4gICAgICAgIC8vIHNvIHRoZSBkaXNjYXJkZWQgb3V0Y29tZSBnZXRzIGl0cyBvd24gbWVzc2FnZS5cbiAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAnSWdub3JpbmcgaW5lcnQgZXZlbnQgdGhhdCBkZWNpZGVzIGFuIGFscmVhZHktZGVjaWRlZCBvdXRjb21lIGRpZmZlcmVudGx5JyxcbiAgICAgICAgICBkZXRhaWxzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIFRoZSBmaXJzdCBldmVudCBvZiB0aGlzIGNsYXNzIGRlY2lkZWQgdGhlIG91dGNvbWUgYXQgYSBsb3dlciBsb2dcbiAgICAgIC8vIHBvc2l0aW9uIGFuZCByZXBsYXkgcmVhZHMgdGhhdCBvbmUuIFJlY29yZGVkIGJlY2F1c2UgYSBzdHJhZ2dsZXIgaXNcbiAgICAgIC8vIHN0aWxsIGV2aWRlbmNlIG9mIHR3byByZXBsYXlzIHdyaXRpbmcgZm9yIHRoZSBzYW1lIGVudGl0eSwgd2hpY2ggaXNcbiAgICAgIC8vIHdvcnRoIHNlZWluZyB3aGVuIGRpYWdub3NpbmcgYSBydW4uXG4gICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAnSWdub3JpbmcgaW5lcnQgZXZlbnQgdGhhdCByZXBlYXRzIGEgY2xhc3MgYWxyZWFkeSBpbiB0aGUgZXZlbnQgbG9nJyxcbiAgICAgICAgZGV0YWlsc1xuICAgICAgKTtcbiAgICB9LFxuICAgIGdldFByb21pc2VRdWV1ZTogKCkgPT4gcHJvbWlzZVF1ZXVlSG9sZGVyLmN1cnJlbnQsXG4gICAgaXNEZWxpdmVyeUlkbGU6ICgpID0+IGRlbGl2ZXJ5SWRsZUhvbGRlci5jdXJyZW50KCksXG4gIH0pO1xuXG4gIGNvbnN0IHdvcmtmbG93Q29udGV4dDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0ID0ge1xuICAgIHJ1bklkOiB3b3JrZmxvd1J1bi5ydW5JZCxcbiAgICBlbmNyeXB0aW9uS2V5LFxuICAgIHdvcmxkQ2FwYWJpbGl0aWVzLFxuICAgIGdsb2JhbFRoaXM6IHZtR2xvYmFsVGhpcyxcbiAgICBvbldvcmtmbG93RXJyb3IsXG4gICAgZXZlbnRzQ29uc3VtZXIsXG4gICAgZ2VuZXJhdGVVbGlkLFxuICAgIGdlbmVyYXRlTmFub2lkLFxuICAgIGdldCBtaW50Q291bnQoKSB7XG4gICAgICByZXR1cm4gbWludENvdW50O1xuICAgIH0sXG4gICAgaW52b2NhdGlvbnNRdWV1ZTogbmV3IE1hcCgpLFxuICAgIC8vIFVzZSBnZXR0ZXIvc2V0dGVyIHNvIHRoZSBFdmVudHNDb25zdW1lcidzIGdldFByb21pc2VRdWV1ZSgpIGFsd2F5c1xuICAgIC8vIHNlZXMgdGhlIGxhdGVzdCBxdWV1ZSBzdGF0ZSBhcyBpdCdzIG11dGF0ZWQgYnkgc3RlcC9ob29rL3NsZWVwIGNhbGxiYWNrcy5cbiAgICBnZXQgcHJvbWlzZVF1ZXVlKCkge1xuICAgICAgcmV0dXJuIHByb21pc2VRdWV1ZUhvbGRlci5jdXJyZW50O1xuICAgIH0sXG4gICAgc2V0IHByb21pc2VRdWV1ZSh2YWx1ZTogUHJvbWlzZTx2b2lkPikge1xuICAgICAgcHJvbWlzZVF1ZXVlSG9sZGVyLmN1cnJlbnQgPSB2YWx1ZTtcbiAgICB9LFxuICAgIHBlbmRpbmdEZWxpdmVyaWVzOiAwLFxuICAgIHN1c3BlbnNpb25HZW5lcmF0aW9uOiAwLFxuICAgIHBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzOiBuZXcgTWFwKCksXG4gICAgcmVwbGF5UGF5bG9hZENhY2hlLFxuICB9O1xuXG4gIGRlbGl2ZXJ5SWRsZUhvbGRlci5jdXJyZW50ID0gKCkgPT4gaXNEZWxpdmVyeUlkbGUod29ya2Zsb3dDb250ZXh0KTtcblxuICAvLyBDb25zdW1lIHJ1biBsaWZlY3ljbGUgZXZlbnRzIC0gdGhlc2UgYXJlIHN0cnVjdHVyYWwgZXZlbnRzIHRoYXQgZG9uJ3RcbiAgLy8gbmVlZCBzcGVjaWFsIGhhbmRsaW5nIGluIHRoZSB3b3JrZmxvdywgYnV0IG11c3QgYmUgY29uc3VtZWQgdG8gYWR2YW5jZVxuICAvLyBwYXN0IHRoZW0gaW4gdGhlIGV2ZW50IGxvZ1xuICBsZXQgY29uc3VtZWRSdW5TdGFydGVkID0gZmFsc2U7XG4gIHdvcmtmbG93Q29udGV4dC5ldmVudHNDb25zdW1lci5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgaWYgKCFldmVudCkge1xuICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuTm90Q29uc3VtZWQ7XG4gICAgfVxuXG4gICAgLy8gQ29uc3VtZSBydW5fY3JlYXRlZCAtIGV2ZXJ5IHJ1biBoYXMgZXhhY3RseSBvbmVcbiAgICBpZiAoZXZlbnQuZXZlbnRUeXBlID09PSAncnVuX2NyZWF0ZWQnKSB7XG4gICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZDtcbiAgICB9XG5cbiAgICAvLyBDb25zdW1lIHRoZSBmaXJzdCBydW5fc3RhcnRlZC4gVHdvIHJlcGxheXMgY2FuIGVhY2ggd3JpdGUgb25lICh0aGVcbiAgICAvLyBjcmVhdGUgaXMgaWRlbXBvdGVudCBmb3IgYSBydW4gYWxyZWFkeSBydW5uaW5nLCB3aGljaCBtYWtlcyB0aGUgd3JpdGVcbiAgICAvLyBzYWZlLCBub3Qgc2luZ2xlLXNob3QpOyB0aGUgZmlyc3QgaXMgdGhlIG9uZSB0aGUgcmVwbGF5IG9ic2VydmVzLCBhbmRcbiAgICAvLyB0aGUgY29uc3VtZXIgc2tpcHMgdGhlIHJlc3QgcmF0aGVyIHRoYW4gYWR2YW5jaW5nIHRoZSB3b3JrZmxvdyBjbG9ja1xuICAgIC8vIHR3aWNlLlxuICAgIGlmIChldmVudC5ldmVudFR5cGUgPT09ICdydW5fc3RhcnRlZCcpIHtcbiAgICAgIGlmIChjb25zdW1lZFJ1blN0YXJ0ZWQpIHtcbiAgICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuTm90Q29uc3VtZWQ7XG4gICAgICB9XG4gICAgICBjb25zdW1lZFJ1blN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuQ29uc3VtZWQ7XG4gICAgfVxuXG4gICAgLy8gQXR0cmlidXRlIHdyaXRlcyBwZXJmb3JtZWQgZnJvbSBhIHN0ZXAgaGF2ZSBubyB3b3JrZmxvdy1ib2R5IGNhbGwgdG9cbiAgICAvLyBjb25zdW1lIHRoZW0gZHVyaW5nIHJlcGxheTsgdGhleSBhcmUgYWxyZWFkeSByZWZsZWN0ZWQgaW4gdGhlIHJ1blxuICAgIC8vIHNuYXBzaG90IGFuZCByZW1haW4gc3RydWN0dXJhbCB1bnRpbCBhIHJlYWQgQVBJIGlzIGludHJvZHVjZWQuXG4gICAgaWYgKFxuICAgICAgZXZlbnQuZXZlbnRUeXBlID09PSAnYXR0cl9zZXQnICYmXG4gICAgICBldmVudC5ldmVudERhdGEud3JpdGVyLnR5cGUgPT09ICdzdGVwJ1xuICAgICkge1xuICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuQ29uc3VtZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuTm90Q29uc3VtZWQ7XG4gIH0pO1xuXG4gIGNvbnN0IHVzZVN0ZXAgPSBjcmVhdGVVc2VTdGVwKHdvcmtmbG93Q29udGV4dCk7XG4gIGNvbnN0IGNyZWF0ZUhvb2sgPSBjcmVhdGVDcmVhdGVIb29rKHdvcmtmbG93Q29udGV4dCk7XG4gIGNvbnN0IHNsZWVwID0gY3JlYXRlU2xlZXAod29ya2Zsb3dDb250ZXh0KTtcbiAgY29uc3Qgc2V0QXR0cmlidXRlcyA9IGNyZWF0ZVNldEF0dHJpYnV0ZXMod29ya2Zsb3dDb250ZXh0KTtcblxuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgdm1HbG9iYWxUaGlzW1dPUktGTE9XX1VTRV9TVEVQXSA9IHVzZVN0ZXA7XG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBgQHR5cGVzL25vZGVgIHNheXMgc3ltYm9sIGlzIG5vdCB2YWxpZCwgYnV0IGl0IGRvZXMgd29ya1xuICB2bUdsb2JhbFRoaXNbV09SS0ZMT1dfU0VUX0FUVFJJQlVURVNdID0gc2V0QXR0cmlidXRlcztcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIGBAdHlwZXMvbm9kZWAgc2F5cyBzeW1ib2wgaXMgbm90IHZhbGlkLCBidXQgaXQgZG9lcyB3b3JrXG4gIHZtR2xvYmFsVGhpc1tXT1JLRkxPV19DUkVBVEVfSE9PS10gPSBjcmVhdGVIb29rO1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgdm1HbG9iYWxUaGlzW1dPUktGTE9XX1NMRUVQXSA9IHNsZWVwO1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgdm1HbG9iYWxUaGlzW1dPUktGTE9XX0dFVF9TVFJFQU1fSURdID0gKG5hbWVzcGFjZT86IHN0cmluZykgPT5cbiAgICBnZXRXb3JrZmxvd1J1blN0cmVhbUlkKHdvcmtmbG93UnVuLnJ1bklkLCBuYW1lc3BhY2UpO1xuXG4gIC8vIEZvciB0aGUgd29ya2Zsb3cgVk0sIHdlIHN0b3JlIHRoZSBjb250ZXh0IGluIGEgc3ltYm9sIG9uIHRoZSBgZ2xvYmFsVGhpc2Agb2JqZWN0XG4gIGNvbnN0IGN0eDogV29ya2Zsb3dNZXRhZGF0YSA9IHtcbiAgICB3b3JrZmxvd05hbWU6IHdvcmtmbG93UnVuLndvcmtmbG93TmFtZSxcbiAgICB3b3JrZmxvd1J1bklkOiB3b3JrZmxvd1J1bi5ydW5JZCxcbiAgICB3b3JrZmxvd1N0YXJ0ZWRBdDogbmV3IHZtR2xvYmFsVGhpcy5EYXRlKCtzdGFydGVkQXQpLFxuICAgIHVybDogd29ya2Zsb3dCYXNlVXJsLFxuICAgIGZlYXR1cmVzOiB7IGVuY3J5cHRpb246ICEhZW5jcnlwdGlvbktleSB9LFxuICB9O1xuXG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBgQHR5cGVzL25vZGVgIHNheXMgc3ltYm9sIGlzIG5vdCB2YWxpZCwgYnV0IGl0IGRvZXMgd29ya1xuICB2bUdsb2JhbFRoaXNbV09SS0ZMT1dfQ09OVEVYVF9TWU1CT0xdID0gY3R4O1xuICAvLyBTZXJpYWxpemF0aW9uIG1pbnRzIHN0cmVhbSBpZHMgdGhyb3VnaCB0aGlzIHN5bWJvbCwgYW5kIGNhbGxzIGl0IHdpdGggbm9cbiAgLy8gc2VlZCB0aW1lLiBgbW9ub3RvbmljRmFjdG9yeWAgcmV0dXJucyBgZW5jb2RlVGltZShsYXN0VGltZSlgIG9uIGl0c1xuICAvLyBpbmNyZW1lbnQgYnJhbmNoLCBzbyBvbmUgc3VjaCBjYWxsIGxhdGNoZXMgdGhlICpob3N0KiB3YWxsIGNsb2NrIGludG9cbiAgLy8gYGxhc3RUaW1lYCwgYW5kIGV2ZXJ5IGlkIHRoZSBydW4gbWludHMgYWZ0ZXJ3YXJkcyBjYXJyaWVzIHRoYXQgdGltZXN0YW1wXG4gIC8vIGluc3RlYWQgb2YgYGZpeGVkVGltZXN0YW1wYCwgYSB2YWx1ZSB0aGF0IGRpZmZlcnMgb24gZXZlcnkgcmVwbGF5LiBCaW5kaW5nXG4gIC8vIHRoZSBzZWVkIHRpbWUgaGVyZSBrZWVwcyB0aGUgd2hvbGUgcnVuIG9uIG9uZSByZXBsYXktc3RhYmxlIGNsb2NrLlxuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gYEB0eXBlcy9ub2RlYCBzYXlzIHN5bWJvbCBpcyBub3QgdmFsaWQsIGJ1dCBpdCBkb2VzIHdvcmtcbiAgdm1HbG9iYWxUaGlzW1NUQUJMRV9VTElEXSA9IGdlbmVyYXRlVWxpZDtcblxuICAvLyBXb3JrZmxvdyBjb2RlIG11c3QgaW1wb3J0IHRoZSBkZXRlcm1pbmlzdGljIGBmZXRjaGAgc3RlcCBmcm9tIGB3b3JrZmxvd2AuXG4gIHZtR2xvYmFsVGhpcy5mZXRjaCA9ICgpID0+IHtcbiAgICB0aHJvdyBuZXcgdm1HbG9iYWxUaGlzLkVycm9yKFxuICAgICAgYEdsb2JhbCBcImZldGNoXCIgaXMgdW5hdmFpbGFibGUgaW4gd29ya2Zsb3cgZnVuY3Rpb25zLiBVc2UgdGhlIFwiZmV0Y2hcIiBzdGVwIGZ1bmN0aW9uIGZyb20gXCJ3b3JrZmxvd1wiIHRvIG1ha2UgSFRUUCByZXF1ZXN0cy5cXG5cXG5MZWFybiBtb3JlOiBodHRwczovL3dvcmtmbG93LXNkay5kZXYvZXJyLyR7RVJST1JfU0xVR1MuRkVUQ0hfSU5fV09SS0ZMT1dfRlVOQ1RJT059YFxuICAgICk7XG4gIH07XG5cbiAgLy8gT3ZlcnJpZGUgdGltZW91dC9pbnRlcnZhbCBmdW5jdGlvbnMgdG8gdGhyb3cgaGVscGZ1bCBlcnJvcnNcbiAgLy8gVGhlc2UgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gd29ya2Zsb3cgZnVuY3Rpb25zIGJlY2F1c2UgdGhleSByZWx5IG9uXG4gIC8vIGFzeW5jaHJvbm91cyBzY2hlZHVsaW5nIHdoaWNoIGJyZWFrcyBkZXRlcm1pbmlzdGljIHJlcGxheVxuICBjb25zdCB0aW1lb3V0RXJyb3JNZXNzYWdlID1cbiAgICAnVGltZW91dCBmdW5jdGlvbnMgbGlrZSBcInNldFRpbWVvdXRcIiBhbmQgXCJzZXRJbnRlcnZhbFwiIGFyZSBub3Qgc3VwcG9ydGVkIGluIHdvcmtmbG93IGZ1bmN0aW9ucy4gVXNlIHRoZSBcInNsZWVwXCIgZnVuY3Rpb24gZnJvbSBcIndvcmtmbG93XCIgZm9yIHRpbWUtYmFzZWQgZGVsYXlzLic7XG5cbiAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLnNldFRpbWVvdXQgPSAoKSA9PiB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKHRpbWVvdXRFcnJvck1lc3NhZ2UsIHtcbiAgICAgIHNsdWc6IEVSUk9SX1NMVUdTLlRJTUVPVVRfRlVOQ1RJT05TX0lOX1dPUktGTE9XLFxuICAgIH0pO1xuICB9O1xuICAodm1HbG9iYWxUaGlzIGFzIGFueSkuc2V0SW50ZXJ2YWwgPSAoKSA9PiB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKHRpbWVvdXRFcnJvck1lc3NhZ2UsIHtcbiAgICAgIHNsdWc6IEVSUk9SX1NMVUdTLlRJTUVPVVRfRlVOQ1RJT05TX0lOX1dPUktGTE9XLFxuICAgIH0pO1xuICB9O1xuICAodm1HbG9iYWxUaGlzIGFzIGFueSkuY2xlYXJUaW1lb3V0ID0gKCkgPT4ge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcih0aW1lb3V0RXJyb3JNZXNzYWdlLCB7XG4gICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICB9KTtcbiAgfTtcbiAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLmNsZWFySW50ZXJ2YWwgPSAoKSA9PiB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKHRpbWVvdXRFcnJvck1lc3NhZ2UsIHtcbiAgICAgIHNsdWc6IEVSUk9SX1NMVUdTLlRJTUVPVVRfRlVOQ1RJT05TX0lOX1dPUktGTE9XLFxuICAgIH0pO1xuICB9O1xuICAodm1HbG9iYWxUaGlzIGFzIGFueSkuc2V0SW1tZWRpYXRlID0gKCkgPT4ge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcih0aW1lb3V0RXJyb3JNZXNzYWdlLCB7XG4gICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICB9KTtcbiAgfTtcbiAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLmNsZWFySW1tZWRpYXRlID0gKCkgPT4ge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcih0aW1lb3V0RXJyb3JNZXNzYWdlLCB7XG4gICAgICBzbHVnOiBFUlJPUl9TTFVHUy5USU1FT1VUX0ZVTkNUSU9OU19JTl9XT1JLRkxPVyxcbiAgICB9KTtcbiAgfTtcblxuICAvLyBgQWJvcnRDb250cm9sbGVyYCBhbmQgYEFib3J0U2lnbmFsYCBpbiB0aGUgd29ya2Zsb3cgVk0gYXJlIGhvb2stYmFja2VkXG4gIC8vIGZvciBkZXRlcm1pbmlzdGljIHJlcGxheS4gVGhlIGNvbnRyb2xsZXIncyBhYm9ydCgpIHF1ZXVlcyBhIGhvb2sgcmVzdW1wdGlvbixcbiAgLy8gYW5kIHNpZ25hbC5hYm9ydGVkIGlzIHVwZGF0ZWQgd2hlbiB0aGUgaG9vayBldmVudCBpcyBwcm9jZXNzZWQgZHVyaW5nIHJlcGxheS5cbiAgKHZtR2xvYmFsVGhpcyBhcyBhbnkpLkFib3J0Q29udHJvbGxlciA9XG4gICAgY3JlYXRlQ3JlYXRlQWJvcnRDb250cm9sbGVyKHdvcmtmbG93Q29udGV4dCk7XG4gIGNvbnN0IGFib3J0U2lnbmFsU3RhdGljcyA9IGNyZWF0ZUFib3J0U2lnbmFsU3RhdGljcygpO1xuICAodm1HbG9iYWxUaGlzIGFzIGFueSkuQWJvcnRTaWduYWwgPSB7XG4gICAgYWJvcnQ6IGFib3J0U2lnbmFsU3RhdGljcy5hYm9ydCxcbiAgICBhbnk6IGFib3J0U2lnbmFsU3RhdGljcy5hbnksXG4gICAgdGltZW91dDogYWJvcnRTaWduYWxTdGF0aWNzLnRpbWVvdXQsXG4gIH07XG5cbiAgLy8gYFJlcXVlc3RgIGFuZCBgUmVzcG9uc2VgIGFyZSBzcGVjaWFsIGJ1aWx0LWluIGNsYXNzZXMgdGhhdCBpbnZva2Ugc3RlcHNcbiAgLy8gZm9yIHRoZSBganNvbigpYCwgYHRleHQoKWAgYW5kIGBhcnJheUJ1ZmZlcigpYCBpbnN0YW5jZSBtZXRob2RzXG4gIGNsYXNzIFJlcXVlc3QgaW1wbGVtZW50cyBnbG9iYWxUaGlzLlJlcXVlc3Qge1xuICAgIGNhY2hlITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydjYWNoZSddO1xuICAgIGNyZWRlbnRpYWxzITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydjcmVkZW50aWFscyddO1xuICAgIGRlc3RpbmF0aW9uITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydkZXN0aW5hdGlvbiddO1xuICAgIGhlYWRlcnMhOiBIZWFkZXJzO1xuICAgIGludGVncml0eSE6IHN0cmluZztcbiAgICBtZXRob2QhOiBzdHJpbmc7XG4gICAgbW9kZSE6IGdsb2JhbFRoaXMuUmVxdWVzdFsnbW9kZSddO1xuICAgIHJlZGlyZWN0ITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydyZWRpcmVjdCddO1xuICAgIHJlZmVycmVyITogc3RyaW5nO1xuICAgIHJlZmVycmVyUG9saWN5ITogZ2xvYmFsVGhpcy5SZXF1ZXN0WydyZWZlcnJlclBvbGljeSddO1xuICAgIHVybCE6IHN0cmluZztcbiAgICBrZWVwYWxpdmUhOiBib29sZWFuO1xuICAgIHNpZ25hbCE6IEFib3J0U2lnbmFsO1xuICAgIGR1cGxleCE6ICdoYWxmJztcbiAgICBib2R5ITogUmVhZGFibGVTdHJlYW08YW55PiB8IG51bGw7XG5cbiAgICBjb25zdHJ1Y3RvcihpbnB1dDogYW55LCBpbml0PzogUmVxdWVzdEluaXQpIHtcbiAgICAgIC8vIEhhbmRsZSBVUkwgaW5wdXRcbiAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnIHx8IGlucHV0IGluc3RhbmNlb2Ygdm1HbG9iYWxUaGlzLlVSTCkge1xuICAgICAgICBjb25zdCB1cmxTdHJpbmcgPSBTdHJpbmcoaW5wdXQpO1xuICAgICAgICAvLyBWYWxpZGF0ZSBVUkwgZm9ybWF0XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbmV3IHZtR2xvYmFsVGhpcy5VUkwodXJsU3RyaW5nKTtcbiAgICAgICAgICB0aGlzLnVybCA9IHVybFN0cmluZztcbiAgICAgICAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBGYWlsZWQgdG8gcGFyc2UgVVJMIGZyb20gJHt1cmxTdHJpbmd9YCwge1xuICAgICAgICAgICAgY2F1c2UsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIElucHV0IGlzIGEgUmVxdWVzdCBvYmplY3QgLSBjbG9uZSBpdHMgcHJvcGVydGllc1xuICAgICAgICB0aGlzLnVybCA9IGlucHV0LnVybDtcbiAgICAgICAgaWYgKCFpbml0KSB7XG4gICAgICAgICAgdGhpcy5tZXRob2QgPSBpbnB1dC5tZXRob2Q7XG4gICAgICAgICAgdGhpcy5oZWFkZXJzID0gbmV3IHZtR2xvYmFsVGhpcy5IZWFkZXJzKGlucHV0LmhlYWRlcnMpO1xuICAgICAgICAgIHRoaXMuYm9keSA9IGlucHV0LmJvZHk7XG4gICAgICAgICAgdGhpcy5tb2RlID0gaW5wdXQubW9kZTtcbiAgICAgICAgICB0aGlzLmNyZWRlbnRpYWxzID0gaW5wdXQuY3JlZGVudGlhbHM7XG4gICAgICAgICAgdGhpcy5jYWNoZSA9IGlucHV0LmNhY2hlO1xuICAgICAgICAgIHRoaXMucmVkaXJlY3QgPSBpbnB1dC5yZWRpcmVjdDtcbiAgICAgICAgICB0aGlzLnJlZmVycmVyID0gaW5wdXQucmVmZXJyZXI7XG4gICAgICAgICAgdGhpcy5yZWZlcnJlclBvbGljeSA9IGlucHV0LnJlZmVycmVyUG9saWN5O1xuICAgICAgICAgIHRoaXMuaW50ZWdyaXR5ID0gaW5wdXQuaW50ZWdyaXR5O1xuICAgICAgICAgIHRoaXMua2VlcGFsaXZlID0gaW5wdXQua2VlcGFsaXZlO1xuICAgICAgICAgIHRoaXMuc2lnbmFsID0gaW5wdXQuc2lnbmFsO1xuICAgICAgICAgIHRoaXMuZHVwbGV4ID0gaW5wdXQuZHVwbGV4O1xuICAgICAgICAgIHRoaXMuZGVzdGluYXRpb24gPSBpbnB1dC5kZXN0aW5hdGlvbjtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgaW5pdCBpcyBwcm92aWRlZCwgbWVyZ2U6IHVzZSBzb3VyY2UgcHJvcGVydGllcywgdGhlbiBvdmVycmlkZSB3aXRoIGluaXRcbiAgICAgICAgLy8gQ29weSBhbGwgcHJvcGVydGllcyBmcm9tIHRoZSBzb3VyY2UgUmVxdWVzdCBmaXJzdFxuICAgICAgICB0aGlzLm1ldGhvZCA9IGlucHV0Lm1ldGhvZDtcbiAgICAgICAgdGhpcy5oZWFkZXJzID0gbmV3IHZtR2xvYmFsVGhpcy5IZWFkZXJzKGlucHV0LmhlYWRlcnMpO1xuICAgICAgICB0aGlzLmJvZHkgPSBpbnB1dC5ib2R5O1xuICAgICAgICB0aGlzLm1vZGUgPSBpbnB1dC5tb2RlO1xuICAgICAgICB0aGlzLmNyZWRlbnRpYWxzID0gaW5wdXQuY3JlZGVudGlhbHM7XG4gICAgICAgIHRoaXMuY2FjaGUgPSBpbnB1dC5jYWNoZTtcbiAgICAgICAgdGhpcy5yZWRpcmVjdCA9IGlucHV0LnJlZGlyZWN0O1xuICAgICAgICB0aGlzLnJlZmVycmVyID0gaW5wdXQucmVmZXJyZXI7XG4gICAgICAgIHRoaXMucmVmZXJyZXJQb2xpY3kgPSBpbnB1dC5yZWZlcnJlclBvbGljeTtcbiAgICAgICAgdGhpcy5pbnRlZ3JpdHkgPSBpbnB1dC5pbnRlZ3JpdHk7XG4gICAgICAgIHRoaXMua2VlcGFsaXZlID0gaW5wdXQua2VlcGFsaXZlO1xuICAgICAgICB0aGlzLnNpZ25hbCA9IGlucHV0LnNpZ25hbDtcbiAgICAgICAgdGhpcy5kdXBsZXggPSBpbnB1dC5kdXBsZXg7XG4gICAgICAgIHRoaXMuZGVzdGluYXRpb24gPSBpbnB1dC5kZXN0aW5hdGlvbjtcbiAgICAgIH1cblxuICAgICAgLy8gT3ZlcnJpZGUgd2l0aCBpbml0IG9wdGlvbnMgaWYgcHJvdmlkZWRcbiAgICAgIC8vIFNldCBtZXRob2RcbiAgICAgIGlmIChpbml0Py5tZXRob2QpIHtcbiAgICAgICAgdGhpcy5tZXRob2QgPSBpbml0Lm1ldGhvZC50b1VwcGVyQ2FzZSgpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5tZXRob2QgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIC8vIEZhbGxiYWNrIHRvIGRlZmF1bHQgZm9yIHN0cmluZyBpbnB1dCBjYXNlXG4gICAgICAgIHRoaXMubWV0aG9kID0gJ0dFVCc7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCBoZWFkZXJzXG4gICAgICBpZiAoaW5pdD8uaGVhZGVycykge1xuICAgICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgdm1HbG9iYWxUaGlzLkhlYWRlcnMoaW5pdC5oZWFkZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgaW5wdXQgaW5zdGFuY2VvZiB2bUdsb2JhbFRoaXMuVVJMXG4gICAgICApIHtcbiAgICAgICAgLy8gRm9yIHN0cmluZy9VUkwgaW5wdXQsIGNyZWF0ZSBlbXB0eSBoZWFkZXJzXG4gICAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycygpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXQgb3RoZXIgcHJvcGVydGllcyB3aXRoIGluaXQgdmFsdWVzIG9yIGRlZmF1bHRzXG4gICAgICBpZiAoaW5pdD8ubW9kZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubW9kZSA9IGluaXQubW9kZTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMubW9kZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5tb2RlID0gJ2NvcnMnO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5pdD8uY3JlZGVudGlhbHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmNyZWRlbnRpYWxzID0gaW5pdC5jcmVkZW50aWFscztcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuY3JlZGVudGlhbHMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMuY3JlZGVudGlhbHMgPSAnc2FtZS1vcmlnaW4nO1xuICAgICAgfVxuXG4gICAgICAvLyBgYW55YCBjYXN0IGhlcmUgYmVjYXVzZSBAdHlwZXMvbm9kZSB2MjIgZG9lcyBub3QgeWV0IGhhdmUgYGNhY2hlYFxuICAgICAgaWYgKChpbml0IGFzIGFueSk/LmNhY2hlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5jYWNoZSA9IChpbml0IGFzIGFueSkuY2FjaGU7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLmNhY2hlICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLmNhY2hlID0gJ2RlZmF1bHQnO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5pdD8ucmVkaXJlY3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLnJlZGlyZWN0ID0gaW5pdC5yZWRpcmVjdDtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMucmVkaXJlY3QgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMucmVkaXJlY3QgPSAnZm9sbG93JztcbiAgICAgIH1cblxuICAgICAgaWYgKGluaXQ/LnJlZmVycmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5yZWZlcnJlciA9IGluaXQucmVmZXJyZXI7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLnJlZmVycmVyICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLnJlZmVycmVyID0gJ2Fib3V0OmNsaWVudCc7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbml0Py5yZWZlcnJlclBvbGljeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMucmVmZXJyZXJQb2xpY3kgPSBpbml0LnJlZmVycmVyUG9saWN5O1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5yZWZlcnJlclBvbGljeSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5yZWZlcnJlclBvbGljeSA9ICcnO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5pdD8uaW50ZWdyaXR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5pbnRlZ3JpdHkgPSBpbml0LmludGVncml0eTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuaW50ZWdyaXR5ICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLmludGVncml0eSA9ICcnO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5pdD8ua2VlcGFsaXZlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5rZWVwYWxpdmUgPSBpbml0LmtlZXBhbGl2ZTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMua2VlcGFsaXZlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhpcy5rZWVwYWxpdmUgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGluaXQ/LnNpZ25hbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBBYm9ydFNpZ25hbCBzdHViXG4gICAgICAgIHRoaXMuc2lnbmFsID0gaW5pdC5zaWduYWw7XG4gICAgICB9IGVsc2UgaWYgKCF0aGlzLnNpZ25hbCkge1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gQWJvcnRTaWduYWwgc3R1YlxuICAgICAgICB0aGlzLnNpZ25hbCA9IHsgYWJvcnRlZDogZmFsc2UgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLmR1cGxleCkge1xuICAgICAgICB0aGlzLmR1cGxleCA9ICdoYWxmJztcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLmRlc3RpbmF0aW9uKSB7XG4gICAgICAgIHRoaXMuZGVzdGluYXRpb24gPSAnZG9jdW1lbnQnO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBib2R5ID0gaW5pdD8uYm9keTtcblxuICAgICAgLy8gVmFsaWRhdGUgdGhhdCBHRVQvSEVBRCBtZXRob2RzIGRvbid0IGhhdmUgYSBib2R5XG4gICAgICBpZiAoXG4gICAgICAgIGJvZHkgIT09IG51bGwgJiZcbiAgICAgICAgYm9keSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICh0aGlzLm1ldGhvZCA9PT0gJ0dFVCcgfHwgdGhpcy5tZXRob2QgPT09ICdIRUFEJylcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBSZXF1ZXN0IHdpdGggR0VUL0hFQUQgbWV0aG9kIGNhbm5vdCBoYXZlIGJvZHkuYCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0b3JlIHRoZSBvcmlnaW5hbCBCb2R5SW5pdCBmb3Igc2VyaWFsaXphdGlvblxuICAgICAgaWYgKGJvZHkgIT09IG51bGwgJiYgYm9keSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIENyZWF0ZSBhIFwiZmFrZVwiIFJlYWRhYmxlU3RyZWFtIHRoYXQgc3RvcmVzIHRoZSBvcmlnaW5hbCBib2R5XG4gICAgICAgIC8vIFRoaXMgYXZvaWRzIGRvaW5nIGFzeW5jIHdvcmsgZHVyaW5nIHdvcmtmbG93IHJlcGxheVxuICAgICAgICB0aGlzLmJvZHkgPSBPYmplY3QuY3JlYXRlKHZtR2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbS5wcm90b3R5cGUsIHtcbiAgICAgICAgICBbQk9EWV9JTklUX1NZTUJPTF06IHtcbiAgICAgICAgICAgIHZhbHVlOiBib2R5LFxuICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5ib2R5ID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjbG9uZSgpOiBSZXF1ZXN0IHtcbiAgICAgIEVOT1RTVVAoKTtcbiAgICB9XG5cbiAgICBnZXQgYm9keVVzZWQoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogaW1wbGVtZW50IHRoZXNlXG4gICAgYmxvYiE6ICgpID0+IFByb21pc2U8QmxvYj47XG4gICAgZm9ybURhdGEhOiAoKSA9PiBQcm9taXNlPEZvcm1EYXRhPjtcblxuICAgIGFycmF5QnVmZmVyITogKCkgPT4gUHJvbWlzZTxBcnJheUJ1ZmZlcj47XG4gICAganNvbiE6ICgpID0+IFByb21pc2U8YW55PjtcbiAgICB0ZXh0ITogKCkgPT4gUHJvbWlzZTxzdHJpbmc+O1xuXG4gICAgYXN5bmMgYnl0ZXMoKSB7XG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXdhaXQgdGhpcy5hcnJheUJ1ZmZlcigpKTtcbiAgICB9XG4gIH1cbiAgdm1HbG9iYWxUaGlzLlJlcXVlc3QgPSBSZXF1ZXN0O1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFJlcXVlc3QucHJvdG90eXBlLCB7XG4gICAgYXJyYXlCdWZmZXI6IHtcbiAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBBcnJheUJ1ZmZlcj4oJ19fYnVpbHRpbl9yZXNwb25zZV9hcnJheV9idWZmZXInKSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIH0sXG4gICAganNvbjoge1xuICAgICAgdmFsdWU6IHVzZVN0ZXA8W10sIGFueT4oJ19fYnVpbHRpbl9yZXNwb25zZV9qc29uJyksXG4gICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9LFxuICAgIHRleHQ6IHtcbiAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBzdHJpbmc+KCdfX2J1aWx0aW5fcmVzcG9uc2VfdGV4dCcpLFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgfSxcbiAgfSk7XG5cbiAgY2xhc3MgUmVzcG9uc2UgaW1wbGVtZW50cyBnbG9iYWxUaGlzLlJlc3BvbnNlIHtcbiAgICB0eXBlITogZ2xvYmFsVGhpcy5SZXNwb25zZVsndHlwZSddO1xuICAgIHVybCE6IHN0cmluZztcbiAgICBzdGF0dXMhOiBudW1iZXI7XG4gICAgc3RhdHVzVGV4dCE6IHN0cmluZztcbiAgICBib2R5ITogUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4gfCBudWxsO1xuICAgIGhlYWRlcnMhOiBIZWFkZXJzO1xuICAgIHJlZGlyZWN0ZWQhOiBib29sZWFuO1xuXG4gICAgY29uc3RydWN0b3IoYm9keT86IGFueSwgaW5pdD86IFJlc3BvbnNlSW5pdCkge1xuICAgICAgdGhpcy5zdGF0dXMgPSBpbml0Py5zdGF0dXMgPz8gMjAwO1xuICAgICAgdGhpcy5zdGF0dXNUZXh0ID0gaW5pdD8uc3RhdHVzVGV4dCA/PyAnJztcbiAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycyhpbml0Py5oZWFkZXJzKTtcbiAgICAgIHRoaXMudHlwZSA9ICdkZWZhdWx0JztcbiAgICAgIHRoaXMudXJsID0gJyc7XG4gICAgICB0aGlzLnJlZGlyZWN0ZWQgPSBmYWxzZTtcblxuICAgICAgLy8gVmFsaWRhdGUgdGhhdCBudWxsLWJvZHkgc3RhdHVzIGNvZGVzIGRvbid0IGhhdmUgYSBib2R5XG4gICAgICAvLyBQZXIgSFRUUCBzcGVjOiAyMDQgKE5vIENvbnRlbnQpLCAyMDUgKFJlc2V0IENvbnRlbnQpLCBhbmQgMzA0IChOb3QgTW9kaWZpZWQpXG4gICAgICBpZiAoXG4gICAgICAgIGJvZHkgIT09IG51bGwgJiZcbiAgICAgICAgYm9keSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICh0aGlzLnN0YXR1cyA9PT0gMjA0IHx8IHRoaXMuc3RhdHVzID09PSAyMDUgfHwgdGhpcy5zdGF0dXMgPT09IDMwNClcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgIGBSZXNwb25zZSBjb25zdHJ1Y3RvcjogSW52YWxpZCByZXNwb25zZSBzdGF0dXMgY29kZSAke3RoaXMuc3RhdHVzfWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gU3RvcmUgdGhlIG9yaWdpbmFsIEJvZHlJbml0IGZvciBzZXJpYWxpemF0aW9uXG4gICAgICBpZiAoYm9keSAhPT0gbnVsbCAmJiBib2R5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgXCJmYWtlXCIgUmVhZGFibGVTdHJlYW0gdGhhdCBzdG9yZXMgdGhlIG9yaWdpbmFsIGJvZHlcbiAgICAgICAgLy8gVGhpcyBhdm9pZHMgZG9pbmcgYXN5bmMgd29yayBkdXJpbmcgd29ya2Zsb3cgcmVwbGF5XG4gICAgICAgIHRoaXMuYm9keSA9IE9iamVjdC5jcmVhdGUodm1HbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtLnByb3RvdHlwZSwge1xuICAgICAgICAgIFtCT0RZX0lOSVRfU1lNQk9MXToge1xuICAgICAgICAgICAgdmFsdWU6IGJvZHksXG4gICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmJvZHkgPSBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE86IGltcGxlbWVudCB0aGVzZVxuICAgIGNsb25lITogKCkgPT4gUmVzcG9uc2U7XG4gICAgYmxvYiE6ICgpID0+IFByb21pc2U8Z2xvYmFsVGhpcy5CbG9iPjtcbiAgICBmb3JtRGF0YSE6ICgpID0+IFByb21pc2U8Z2xvYmFsVGhpcy5Gb3JtRGF0YT47XG5cbiAgICBnZXQgb2soKSB7XG4gICAgICByZXR1cm4gdGhpcy5zdGF0dXMgPj0gMjAwICYmIHRoaXMuc3RhdHVzIDwgMzAwO1xuICAgIH1cblxuICAgIGdldCBib2R5VXNlZCgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBhcnJheUJ1ZmZlciE6ICgpID0+IFByb21pc2U8QXJyYXlCdWZmZXI+O1xuICAgIGpzb24hOiAoKSA9PiBQcm9taXNlPGFueT47XG4gICAgdGV4dCE6ICgpID0+IFByb21pc2U8c3RyaW5nPjtcblxuICAgIGFzeW5jIGJ5dGVzKCkge1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHRoaXMuYXJyYXlCdWZmZXIoKSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGpzb24oZGF0YTogYW55LCBpbml0PzogUmVzcG9uc2VJbml0KTogUmVzcG9uc2Uge1xuICAgICAgY29uc3QgYm9keSA9IEpTT04uc3RyaW5naWZ5KGRhdGEpO1xuICAgICAgY29uc3QgaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycyhpbml0Py5oZWFkZXJzKTtcbiAgICAgIGlmICghaGVhZGVycy5oYXMoJ2NvbnRlbnQtdHlwZScpKSB7XG4gICAgICAgIGhlYWRlcnMuc2V0KCdjb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBSZXNwb25zZShib2R5LCB7IC4uLmluaXQsIGhlYWRlcnMgfSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGVycm9yKCk6IFJlc3BvbnNlIHtcbiAgICAgIEVOT1RTVVAoKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgcmVkaXJlY3QodXJsOiBzdHJpbmcgfCBVUkwsIHN0YXR1czogbnVtYmVyID0gMzAyKTogUmVzcG9uc2Uge1xuICAgICAgLy8gVmFsaWRhdGUgc3RhdHVzIGNvZGUgLSBvbmx5IHNwZWNpZmljIHJlZGlyZWN0IGNvZGVzIGFyZSBhbGxvd2VkXG4gICAgICBpZiAoIVszMDEsIDMwMiwgMzAzLCAzMDcsIDMwOF0uaW5jbHVkZXMoc3RhdHVzKSkge1xuICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcbiAgICAgICAgICBgSW52YWxpZCByZWRpcmVjdCBzdGF0dXMgY29kZTogJHtzdGF0dXN9LiBNdXN0IGJlIG9uZSBvZjogMzAxLCAzMDIsIDMwMywgMzA3LCAzMDhgXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIENyZWF0ZSByZXNwb25zZSB3aXRoIExvY2F0aW9uIGhlYWRlclxuICAgICAgY29uc3QgaGVhZGVycyA9IG5ldyB2bUdsb2JhbFRoaXMuSGVhZGVycygpO1xuICAgICAgaGVhZGVycy5zZXQoJ0xvY2F0aW9uJywgU3RyaW5nKHVybCkpO1xuXG4gICAgICBjb25zdCByZXNwb25zZSA9IE9iamVjdC5jcmVhdGUoUmVzcG9uc2UucHJvdG90eXBlKTtcbiAgICAgIHJlc3BvbnNlLnN0YXR1cyA9IHN0YXR1cztcbiAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgPSAnJztcbiAgICAgIHJlc3BvbnNlLmhlYWRlcnMgPSBoZWFkZXJzO1xuICAgICAgcmVzcG9uc2UuYm9keSA9IG51bGw7XG4gICAgICByZXNwb25zZS50eXBlID0gJ2RlZmF1bHQnO1xuICAgICAgcmVzcG9uc2UudXJsID0gJyc7XG4gICAgICByZXNwb25zZS5yZWRpcmVjdGVkID0gZmFsc2U7XG5cbiAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9XG4gIH1cbiAgdm1HbG9iYWxUaGlzLlJlc3BvbnNlID0gUmVzcG9uc2U7XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoUmVzcG9uc2UucHJvdG90eXBlLCB7XG4gICAgYXJyYXlCdWZmZXI6IHtcbiAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBBcnJheUJ1ZmZlcj4oJ19fYnVpbHRpbl9yZXNwb25zZV9hcnJheV9idWZmZXInKSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIH0sXG4gICAganNvbjoge1xuICAgICAgdmFsdWU6IHVzZVN0ZXA8W10sIGFueT4oJ19fYnVpbHRpbl9yZXNwb25zZV9qc29uJyksXG4gICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9LFxuICAgIHRleHQ6IHtcbiAgICAgIHZhbHVlOiB1c2VTdGVwPFtdLCBzdHJpbmc+KCdfX2J1aWx0aW5fcmVzcG9uc2VfdGV4dCcpLFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgfSxcbiAgfSk7XG5cbiAgY2xhc3MgUmVhZGFibGVTdHJlYW08VD4gaW1wbGVtZW50cyBnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtPFQ+IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgIEVOT1RTVVAoKTtcbiAgICB9XG5cbiAgICBnZXQgbG9ja2VkKCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNhbmNlbCgpOiBhbnkge1xuICAgICAgRU5PVFNVUCgpO1xuICAgIH1cblxuICAgIGdldFJlYWRlcigpOiBhbnkge1xuICAgICAgRU5PVFNVUCgpO1xuICAgIH1cblxuICAgIHBpcGVUaHJvdWdoKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuXG4gICAgcGlwZVRvKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuXG4gICAgdGVlKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuXG4gICAgdmFsdWVzKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGZyb20oKTogYW55IHtcbiAgICAgIEVOT1RTVVAoKTtcbiAgICB9XG5cbiAgICBbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuICB9XG4gIHZtR2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbSA9IFJlYWRhYmxlU3RyZWFtO1xuXG4gIGNsYXNzIFdyaXRhYmxlU3RyZWFtPFQ+IGltcGxlbWVudHMgZ2xvYmFsVGhpcy5Xcml0YWJsZVN0cmVhbTxUPiB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuXG4gICAgZ2V0IGxvY2tlZCgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBhYm9ydCgpOiBhbnkge1xuICAgICAgRU5PVFNVUCgpO1xuICAgIH1cblxuICAgIGNsb3NlKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuXG4gICAgZ2V0V3JpdGVyKCk6IGFueSB7XG4gICAgICBFTk9UU1VQKCk7XG4gICAgfVxuICB9XG4gIHZtR2xvYmFsVGhpcy5Xcml0YWJsZVN0cmVhbSA9IFdyaXRhYmxlU3RyZWFtO1xuXG4gIGNsYXNzIFRyYW5zZm9ybVN0cmVhbTxJLCBPPiBpbXBsZW1lbnRzIGdsb2JhbFRoaXMuVHJhbnNmb3JtU3RyZWFtPEksIE8+IHtcbiAgICByZWFkYWJsZTogZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTxPPjtcbiAgICB3cml0YWJsZTogZ2xvYmFsVGhpcy5Xcml0YWJsZVN0cmVhbTxJPjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgRU5PVFNVUCgpO1xuICAgIH1cbiAgfVxuICB2bUdsb2JhbFRoaXMuVHJhbnNmb3JtU3RyZWFtID0gVHJhbnNmb3JtU3RyZWFtO1xuXG4gIHZtR2xvYmFsVGhpcy5jb25zb2xlID0gZ2xvYmFsVGhpcy5jb25zb2xlO1xuXG4gIC8vIEV4cG9zZSB0aGUgcmVxdWVzdC1jb250ZXh0IHN5bWJvbCByZXF1aXJlZCBieSBBSSBHYXRld2F5LlxuICBjb25zdCBTWU1CT0xfRk9SX1JFUV9DT05URVhUID0gU3ltYm9sLmZvcignQHZlcmNlbC9yZXF1ZXN0LWNvbnRleHQnKTtcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIGBAdHlwZXMvbm9kZWAgc2F5cyBzeW1ib2wgaXMgbm90IHZhbGlkLCBidXQgaXQgZG9lcyB3b3JrXG4gIHZtR2xvYmFsVGhpc1tTWU1CT0xfRk9SX1JFUV9DT05URVhUXSA9IChnbG9iYWxUaGlzIGFzIGFueSlbXG4gICAgU1lNQk9MX0ZPUl9SRVFfQ09OVEVYVFxuICBdO1xuICBlbmRWbVRyYWNlKCk7XG5cbiAgLy8gUmV1c2UgY29tcGlsZWQgc2NyaXB0cyBieSBgKGNvZGUsIGZpbGVuYW1lKWA6IGNvbXBpbGF0aW9uIGlzIGRldGVybWluaXN0aWNcbiAgLy8gYW5kIHRoZSBmaWxlbmFtZSBwcmVzZXJ2ZXMgd29ya2Zsb3cgc291cmNlIGF0dHJpYnV0aW9uIGluIHN0YWNrIHRyYWNlcy5cbiAgLy8gVGhlIGJ1bmRsZSByZWdpc3RlcnMgd29ya2Zsb3dzIG9uIGBnbG9iYWxUaGlzLl9fcHJpdmF0ZV93b3JrZmxvd3NgLlxuICBjb25zdCB7IGJ1bmRsZVNjcmlwdCwgd29ya2Zsb3dMb29rdXBTY3JpcHQgfSA9XG4gICAgY29tcGlsZWRXb3JrZmxvd1NjcmlwdHMgPz9cbiAgICAoYXdhaXQgY29tcGlsZVdvcmtmbG93QnVuZGxlKHdvcmtmbG93Q29kZSwgd29ya2Zsb3dSdW4ud29ya2Zsb3dOYW1lKSk7XG4gIGNvbnN0IHdvcmtmbG93Rm4gPSBhd2FpdCB0cmFjZSgnd29ya2Zsb3cuYnVuZGxlLmV2YWx1YXRlJywgYXN5bmMgKCkgPT4ge1xuICAgIGJ1bmRsZVNjcmlwdC5ydW5JbkNvbnRleHQoY29udGV4dCk7XG4gICAgcmV0dXJuIHdvcmtmbG93TG9va3VwU2NyaXB0LnJ1bkluQ29udGV4dChjb250ZXh0KTtcbiAgfSk7XG5cbiAgaWYgKHR5cGVvZiB3b3JrZmxvd0ZuICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93Tm90UmVnaXN0ZXJlZEVycm9yKHdvcmtmbG93UnVuLndvcmtmbG93TmFtZSk7XG4gIH1cblxuICAvLyBDaGFpbiB3b3JrZmxvdyBhcmd1bWVudCBoeWRyYXRpb24gb250byB0aGUgcHJvbWlzZVF1ZXVlIHNvIHRoYXQgdGhlXG4gIC8vIHVuY29uc3VtZWQgZXZlbnQgY2hlY2sgKHdoaWNoIHdhaXRzIGZvciB0aGUgcXVldWUgdG8gZHJhaW4pIGRvZXNuJ3RcbiAgLy8gZmlyZSBkdXJpbmcgdGhlIGFzeW5jIGdhcCBiZXR3ZWVuIHJ1bl9zdGFydGVkIGNvbnN1bXB0aW9uIGFuZCB0aGVcbiAgLy8gd29ya2Zsb3cgZnVuY3Rpb24gc3Vic2NyaWJpbmcgaXRzIGZpcnN0IHN0ZXAgY2FsbGJhY2tzLlxuICBsZXQgYXJnczogdW5rbm93bltdID0gW107XG4gIHdvcmtmbG93Q29udGV4dC5wcm9taXNlUXVldWUgPSB3b3JrZmxvd0NvbnRleHQucHJvbWlzZVF1ZXVlLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgIC8vIEluY2x1ZGUgYW55IHJlc2lkdWFsIHBheWxvYWQgcHJlcGFyYXRpb24gcGx1cyBWTS1sb2NhbCBkZXNlcmlhbGl6YXRpb25cbiAgICAvLyBpbiB0aGUgYmxvY2tpbmcgYm91bmRhcnkuXG4gICAgYXJncyA9IGF3YWl0IHRyYWNlKCd3b3JrZmxvdy5pbnB1dC5oeWRyYXRlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcHJlcGFyZWQgPVxuICAgICAgICBhd2FpdCByZXBsYXlQYXlsb2FkQ2FjaGUucHJlcGFyZVdvcmtmbG93SW5wdXQod29ya2Zsb3dSdW4pO1xuICAgICAgcmV0dXJuIGh5ZHJhdGVXb3JrZmxvd0FyZ3VtZW50cyhcbiAgICAgICAgd29ya2Zsb3dSdW4uaW5wdXQsXG4gICAgICAgIHdvcmtmbG93UnVuLnJ1bklkLFxuICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICB2bUdsb2JhbFRoaXMsXG4gICAgICAgIHt9LFxuICAgICAgICBwcmVwYXJlZFxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG4gIGF3YWl0IHdvcmtmbG93Q29udGV4dC5wcm9taXNlUXVldWU7XG5cbiAgY29uc3QgZmFpbFdvcmtmbG93ID0gYXN5bmMgKGVycm9yOiB1bmtub3duKTogUHJvbWlzZTxuZXZlcj4gPT4ge1xuICAgIC8vIENvbnRyb2wtZmxvdyBzaWduYWxzIGFyZSBoYW5kbGVkIGJ5IHRoZSBydW50aW1lIGFuZCBkbyBub3QgbWVhbiB0aGVcbiAgICAvLyB3b3JrZmxvdyBoYXMgdGVybWluYWxseSBmYWlsZWQuIGBvbldvcmtmbG93RXJyb3JgIHVzdWFsbHkgYWxyZWFkeSBtb3ZlZFxuICAgIC8vIHRoZSBzdGF0ZSBtYWNoaW5lLCBidXQgYSBkaXZlcmdlbmNlIGNhbiBhbHNvIGFycml2ZSB2aWEgYSBzdGVwXG4gICAgLy8gcHJvbWlzZSdzIGRpcmVjdCByZWplY3Rpb24gKGJ5cGFzc2luZyBgb25Xb3JrZmxvd0Vycm9yYCk7IGRlbW90ZSBzb1xuICAgIC8vIGV2ZXJ5IGNvbnRyb2wtZmxvdyBwYXRoIGNvbnZlcmdlcyBvbiBgcmVwbGF5YCBhbmQgYSBsYXRlciByZXN1bWUgZmFsbHNcbiAgICAvLyBiYWNrIGluc3RlYWQgb2YgdGhyb3dpbmcuXG4gICAgaWYgKFdvcmtmbG93U3VzcGVuc2lvbi5pcyhlcnJvcikgfHwgUmVwbGF5RGl2ZXJnZW5jZUVycm9yLmlzKGVycm9yKSkge1xuICAgICAgaWYgKHN0YXRlLnR5cGUgPT09ICdydW5uaW5nJykgc3RhdGUgPSB7IHR5cGU6ICdyZXBsYXknIH07XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gICAgc3RhdGUgPSB7IHR5cGU6ICdjb21wbGV0ZWQnIH07XG5cbiAgICBhd2FpdCBkcmFpblBlbmRpbmdRdWV1ZUl0ZW1zKFxuICAgICAgd29ya2Zsb3dSdW4ucnVuSWQsXG4gICAgICB3b3JrZmxvd0NvbnRleHQuaW52b2NhdGlvbnNRdWV1ZSxcbiAgICAgIHZtR2xvYmFsVGhpcyxcbiAgICAgIHdvcmtmbG93UnVuLFxuICAgICAgJ2ZhaWxlZCcsXG4gICAgICBydW5SZWFkeUJhcnJpZXJcbiAgICApO1xuXG4gICAgdGhyb3cgZXJyb3I7XG4gIH07XG5cbiAgY29uc3Qgd2FpdEZvckV4ZWN1dGlvbiA9IGFzeW5jIChcbiAgICB3b3JrZmxvd0JvZHk6IFByb21pc2U8dW5rbm93bj4sXG4gICAgaW50ZXJydXB0aW9uOiBQcm9taXNlV2l0aFJlc29sdmVyczxuZXZlcj5cbiAgKTogUHJvbWlzZTxXb3JrZmxvd1Jlc3VsdD4gPT4ge1xuICAgIGxldCByZXN1bHQ6IHVua25vd247XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IFByb21pc2UucmFjZShbd29ya2Zsb3dCb2R5LCBpbnRlcnJ1cHRpb24ucHJvbWlzZV0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoc3RhdGUudHlwZSA9PT0gJ3N1c3BlbmRlZCcgJiYgZXJyb3IgPT09IHN0YXRlLnN1c3BlbnNpb24pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiAnc3VzcGVuZGVkJyxcbiAgICAgICAgICBzdXNwZW5zaW9uOiBzdGF0ZS5zdXNwZW5zaW9uLFxuICAgICAgICAgIHNlc3Npb24sXG4gICAgICAgICAgLy8gQSBzdXNwZW5zaW9uIGlzIG5vdCBhIHNldHRsaW5nIHBvaW50OiB0aGUgY29uc3VtZXIgZm9yIHNvbWV0aGluZ1xuICAgICAgICAgIC8vIGhlbGQgbWF5IHdlbGwgYmUgcmVnaXN0ZXJlZCBieSB0aGUgcmVwbGF5IHRoYXQgZm9sbG93cyB0aGlzIG9uZS5cbiAgICAgICAgICAvLyBTbyBpdCBpcyBjYXJyaWVkIG91dCBmb3IgdGhlIHNwYW4gaW5zdGVhZCBvZiBiZWluZyBqdWRnZWQgaGVyZS5cbiAgICAgICAgICBwYXJrZWQ6IGV2ZW50c0NvbnN1bWVyLnBhcmtlZFN1bW1hcnksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFpbFdvcmtmbG93KGVycm9yKTtcbiAgICB9XG5cbiAgICBzdGF0ZSA9IHsgdHlwZTogJ2NvbXBsZXRlZCcgfTtcbiAgICAvLyBUaGUgY29uc3VtZXIgd2Fsa3MgcGFzdCBldmVudHMgd2hvc2UgdHlwZSBjYXJyaWVzIG5vIG9yZGVyaW5nIGNsYWltIGFuZFxuICAgIC8vIGhvbGRzIHRoZW0gZm9yIGEgY29uc3VtZXIgaXQgZXhwZWN0cyBhIGxhdGVyIGBzdWJzY3JpYmUoKWAgdG8gcmVnaXN0ZXIuXG4gICAgLy8gVGhlIHdvcmtmbG93IGZ1bmN0aW9uIHJldHVybmluZyBpcyB0aGUgcG9pbnQgd2hlcmUgdGhhdCBleHBlY3RhdGlvbiBpc1xuICAgIC8vIHNldHRsZWQ6IG5vdGhpbmcgbW9yZSB3aWxsIHN1YnNjcmliZSwgc28gYW55dGhpbmcgc3RpbGwgaGVsZCB3YXMgbmV2ZXJcbiAgICAvLyBhbnlvbmUncywgYW5kIGNvbXBsZXRpbmcgaGVyZSB3b3VsZCBkcm9wIGl0IHNpbGVudGx5LlxuICAgIGNvbnN0IHN0cmFuZGVkID0gZXZlbnRzQ29uc3VtZXIuc3RyYW5kZWRFdmVudDtcbiAgICBpZiAoc3RyYW5kZWQpIHtcbiAgICAgIHJldHVybiBmYWlsV29ya2Zsb3coXG4gICAgICAgIG5ldyBSZXBsYXlEaXZlcmdlbmNlRXJyb3IoXG4gICAgICAgICAgYFJlcGxheSBmaW5pc2hlZCB3aXRob3V0IGNvbnN1bWluZyBldmVudDogZXZlbnRUeXBlPSR7c3RyYW5kZWQuZXZlbnRUeXBlfSwgY29ycmVsYXRpb25JZD0ke3N0cmFuZGVkLmNvcnJlbGF0aW9uSWR9LCBldmVudElkPSR7c3RyYW5kZWQuZXZlbnRJZH0uYCxcbiAgICAgICAgICB7IGV2ZW50SWQ6IHN0cmFuZGVkLmV2ZW50SWQgfVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgZGVoeWRyYXRlV29ya2Zsb3dSZXR1cm5WYWx1ZShcbiAgICAgICAgcmVzdWx0LFxuICAgICAgICB3b3JrZmxvd1J1bi5ydW5JZCxcbiAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgdm1HbG9iYWxUaGlzLFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgLy8gT25seSBjb21wcmVzc2lvbi1jYXBhYmxlIHJ1bnMgKHNwZWMgPj0gNSkgbWF5IHdyaXRlIGNvbXByZXNzZWRcbiAgICAgICAgLy8gcGF5bG9hZHMuIFRoZSBzZXJpYWxpemVyIHVzZXMgenN0ZCB3aGVuIHN1cHBvcnRlZCBhbmQgbWF5IHVzZSBnemlwLlxuICAgICAgICAod29ya2Zsb3dSdW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OXG4gICAgICApO1xuXG4gICAgICBhd2FpdCBkcmFpblBlbmRpbmdRdWV1ZUl0ZW1zKFxuICAgICAgICB3b3JrZmxvd1J1bi5ydW5JZCxcbiAgICAgICAgd29ya2Zsb3dDb250ZXh0Lmludm9jYXRpb25zUXVldWUsXG4gICAgICAgIHZtR2xvYmFsVGhpcyxcbiAgICAgICAgd29ya2Zsb3dSdW4sXG4gICAgICAgICdjb21wbGV0ZWQnLFxuICAgICAgICBydW5SZWFkeUJhcnJpZXJcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiB7IHR5cGU6ICdjb21wbGV0ZWQnLCBvdXRwdXQsIHJlc3VsdFR5cGU6IHR5cGVvZiByZXN1bHQgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhaWxXb3JrZmxvdyhlcnJvcik7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IHdvcmtmbG93VHJhY2VDb250ZXh0ID0gYXdhaXQgY3JlYXRlUmVmcmVzaGFibGVUcmFjZUNvbnRleHQoKTtcbiAgY29uc3QgcmVwbGF5VHJhY2UgPSBhd2FpdCBzdGFydFRyYWNlU3Bhbignd29ya2Zsb3cucmVwbGF5LmV4ZWN1dGUnKTtcbiAgY29uc3Qgd29ya2Zsb3dCb2R5ID0gd29ya2Zsb3dUcmFjZUNvbnRleHQucnVuKGFzeW5jICgpID0+XG4gICAgd29ya2Zsb3dGbiguLi5hcmdzKVxuICApO1xuXG4gIGNvbnN0IHNlc3Npb246IFdvcmtmbG93U2Vzc2lvbiA9IHtcbiAgICB3b3JrZmxvd1J1bixcbiAgICBhcmd1bWVudENvdW50OiBhcmdzLmxlbmd0aCxcbiAgICBhc3luYyByZXN1bWUobmV4dEV2ZW50cykge1xuICAgICAgc3dpdGNoIChzdGF0ZS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ3N1c3BlbmRlZCc6IHtcbiAgICAgICAgICAvLyBUaGUgZnVsbCBPKGtub3duIGV2ZW50cykgcHJlZml4IGNvbXBhcmUgaXMgcmVxdWlyZWQ6IHRoZSBydW50aW1lXG4gICAgICAgICAgLy8gdXN1YWxseSBncm93cyBvbmUgYXJyYXkgaW4gcGxhY2UsIGJ1dCBpdHMgd2FpdC1jb21wbGV0aW9uIGFuZFxuICAgICAgICAgIC8vIHN0YWxlLXJlbG9hZCBwYXRocyBSRVBMQUNFIHRoZSBhcnJheSB3aXRoIGEgZnJlc2ggZnVsbCBmZXRjaCwgc29cbiAgICAgICAgICAvLyBhIHJld3JpdHRlbiBwcmVmaXggaXMgYSByZWFsIGlucHV0LCBub3QgcGFyYW5vaWEuIFRoZSBjb21wYXJlc1xuICAgICAgICAgIC8vIGFyZSBjaGVhcCBzdHJpbmcgZXF1YWxpdHkgYW5kIGR3YXJmZWQgYnkgdGhlIHJlcGxheSB0aGV5IGF2b2lkLlxuICAgICAgICAgIGNvbnN0IGtub3duRXZlbnRzID0gZXZlbnRzQ29uc3VtZXIuZXZlbnRzO1xuICAgICAgICAgIGNvbnN0IGlzU3RyaWN0RXh0ZW5zaW9uID1cbiAgICAgICAgICAgIG5leHRFdmVudHMubGVuZ3RoID4ga25vd25FdmVudHMubGVuZ3RoICYmXG4gICAgICAgICAgICBrbm93bkV2ZW50cy5ldmVyeShcbiAgICAgICAgICAgICAgKGV2ZW50LCBpbmRleCkgPT4gZXZlbnQuZXZlbnRJZCA9PT0gbmV4dEV2ZW50c1tpbmRleF0uZXZlbnRJZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoIWlzU3RyaWN0RXh0ZW5zaW9uKSB7XG4gICAgICAgICAgICBzdGF0ZSA9IHsgdHlwZTogJ3JlcGxheScgfTtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdyZXBsYXknIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGludGVycnVwdGlvbiA9IHdpdGhSZXNvbHZlcnM8bmV2ZXI+KCk7XG4gICAgICAgICAgc3RhdGUgPSB7IHR5cGU6ICdydW5uaW5nJywgaW50ZXJydXB0aW9uIH07XG4gICAgICAgICAgd29ya2Zsb3dDb250ZXh0LnN1c3BlbnNpb25HZW5lcmF0aW9uKys7XG4gICAgICAgICAgd29ya2Zsb3dUcmFjZUNvbnRleHQucmVmcmVzaCgpO1xuICAgICAgICAgIGV2ZW50c0NvbnN1bWVyLmFwcGVuZChuZXh0RXZlbnRzLnNsaWNlKGtub3duRXZlbnRzLmxlbmd0aCkpO1xuICAgICAgICAgIHJldHVybiB3YWl0Rm9yRXhlY3V0aW9uKHdvcmtmbG93Qm9keSwgaW50ZXJydXB0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdyZXBsYXknOlxuICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdyZXBsYXknIH07XG4gICAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgIGNhc2UgJ3J1bm5pbmcnOlxuICAgICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgIGBDYW5ub3QgcmVzdW1lICR7c3RhdGUudHlwZX0gd29ya2Zsb3cgXCIke3dvcmtmbG93UnVuLnJ1bklkfVwiYFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgICBzdGF0ZSBzYXRpc2ZpZXMgbmV2ZXI7XG4gICAgfSxcbiAgfTtcblxuICAvLyBUaGUgcmVwbGF5IHNwYW4gbWVhc3VyZXMgdGhlIHVzZXIgZnVuY3Rpb24gd2l0aG91dCBiZWNvbWluZyBpdHMgYW1iaWVudFxuICAvLyBjb250ZXh0LiBUaGUgd29ya2Zsb3cgcHJvbWlzZSBzdGF5cyBwZW5kaW5nIGFjcm9zcyByZXRhaW5lZCByZXN1bWVzLCBzbyBhblxuICAvLyBhY3RpdmUgcmVwbGF5IHNwYW4gaGVyZSB3b3VsZCByZW1haW4gY2FwdHVyZWQgYWZ0ZXIgdGhhdCBzcGFuIGhhcyBlbmRlZC5cbiAgY29uc3QgZXhlY3V0aW9uID0gd2FpdEZvckV4ZWN1dGlvbih3b3JrZmxvd0JvZHksIGluaXRpYWxJbnRlcnJ1cHRpb24pO1xuICB2b2lkIGV4ZWN1dGlvbi50aGVuKHJlcGxheVRyYWNlLmVuZCwgcmVwbGF5VHJhY2UuZmFpbCk7XG5cbiAgcmV0dXJuIHtcbiAgICBzZXNzaW9uLFxuICAgIGV4ZWN1dGlvbixcbiAgfTtcbn1cbiJdfQ==