@workflow/core 5.0.0-beta.4 → 5.0.0-beta.40

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 (325) hide show
  1. package/dist/attribute-changes.d.ts +7 -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 +33 -1
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +71 -4
  7. package/dist/capture-stack.d.ts +16 -0
  8. package/dist/capture-stack.d.ts.map +1 -0
  9. package/dist/capture-stack.js +21 -0
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +26 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +109 -6
  16. package/dist/context-errors.d.ts +27 -0
  17. package/dist/context-errors.d.ts.map +1 -0
  18. package/dist/context-errors.js +101 -0
  19. package/dist/context-violation-error.d.ts +97 -0
  20. package/dist/context-violation-error.d.ts.map +1 -0
  21. package/dist/context-violation-error.js +149 -0
  22. package/dist/correlation-id.d.ts +109 -0
  23. package/dist/correlation-id.d.ts.map +1 -0
  24. package/dist/correlation-id.js +139 -0
  25. package/dist/create-hook.d.ts +62 -4
  26. package/dist/create-hook.d.ts.map +1 -1
  27. package/dist/create-hook.js +4 -3
  28. package/dist/define-hook.d.ts.map +1 -1
  29. package/dist/define-hook.js +20 -5
  30. package/dist/describe-error.d.ts +70 -0
  31. package/dist/describe-error.d.ts.map +1 -0
  32. package/dist/describe-error.js +189 -0
  33. package/dist/encryption.d.ts +37 -3
  34. package/dist/encryption.d.ts.map +1 -1
  35. package/dist/encryption.js +97 -31
  36. package/dist/events-consumer.d.ts +26 -1
  37. package/dist/events-consumer.d.ts.map +1 -1
  38. package/dist/events-consumer.js +105 -18
  39. package/dist/flushable-stream.d.ts +65 -10
  40. package/dist/flushable-stream.d.ts.map +1 -1
  41. package/dist/flushable-stream.js +131 -18
  42. package/dist/global.d.ts +37 -1
  43. package/dist/global.d.ts.map +1 -1
  44. package/dist/global.js +21 -3
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +2 -1
  48. package/dist/log-format.d.ts +25 -0
  49. package/dist/log-format.d.ts.map +1 -0
  50. package/dist/log-format.js +250 -0
  51. package/dist/logger.d.ts +29 -30
  52. package/dist/logger.d.ts.map +1 -1
  53. package/dist/logger.js +82 -32
  54. package/dist/private.d.ts +178 -9
  55. package/dist/private.d.ts.map +1 -1
  56. package/dist/private.js +273 -9
  57. package/dist/replay-payload-cache.d.ts +68 -0
  58. package/dist/replay-payload-cache.d.ts.map +1 -0
  59. package/dist/replay-payload-cache.js +160 -0
  60. package/dist/runtime/compute-instance.d.ts +12 -0
  61. package/dist/runtime/compute-instance.d.ts.map +1 -0
  62. package/dist/runtime/compute-instance.js +13 -0
  63. package/dist/runtime/constants.d.ts +237 -0
  64. package/dist/runtime/constants.d.ts.map +1 -1
  65. package/dist/runtime/constants.js +405 -15
  66. package/dist/runtime/count-step-started-events.d.ts +52 -0
  67. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  68. package/dist/runtime/count-step-started-events.js +72 -0
  69. package/dist/runtime/deployment-guard.d.ts +99 -0
  70. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  71. package/dist/runtime/deployment-guard.js +154 -0
  72. package/dist/runtime/get-port-lazy.d.ts +25 -0
  73. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  74. package/dist/runtime/get-port-lazy.js +92 -0
  75. package/dist/runtime/get-world-lazy.d.ts +23 -0
  76. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  77. package/dist/runtime/get-world-lazy.js +46 -0
  78. package/dist/runtime/helpers.d.ts +219 -10
  79. package/dist/runtime/helpers.d.ts.map +1 -1
  80. package/dist/runtime/helpers.js +414 -40
  81. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  82. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-assets.generated.js +30 -0
  84. package/dist/runtime/quickjs-entrypoint.d.ts +124 -0
  85. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  86. package/dist/runtime/quickjs-entrypoint.js +1429 -0
  87. package/dist/runtime/quickjs-runtime.d.ts +193 -0
  88. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  89. package/dist/runtime/quickjs-runtime.js +1944 -0
  90. package/dist/runtime/replay-budget.d.ts +98 -0
  91. package/dist/runtime/replay-budget.d.ts.map +1 -0
  92. package/dist/runtime/replay-budget.js +192 -0
  93. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  95. package/dist/runtime/replay-recovery-reporter.js +64 -0
  96. package/dist/runtime/resume-hook.d.ts +27 -4
  97. package/dist/runtime/resume-hook.d.ts.map +1 -1
  98. package/dist/runtime/resume-hook.js +448 -76
  99. package/dist/runtime/run-id-time.d.ts +19 -0
  100. package/dist/runtime/run-id-time.d.ts.map +1 -0
  101. package/dist/runtime/run-id-time.js +42 -0
  102. package/dist/runtime/run.d.ts +8 -2
  103. package/dist/runtime/run.d.ts.map +1 -1
  104. package/dist/runtime/run.js +62 -15
  105. package/dist/runtime/runs.d.ts +54 -3
  106. package/dist/runtime/runs.d.ts.map +1 -1
  107. package/dist/runtime/runs.js +117 -10
  108. package/dist/runtime/start.d.ts +70 -1
  109. package/dist/runtime/start.d.ts.map +1 -1
  110. package/dist/runtime/start.js +312 -54
  111. package/dist/runtime/step-executor.d.ts +177 -0
  112. package/dist/runtime/step-executor.d.ts.map +1 -0
  113. package/dist/runtime/step-executor.js +949 -0
  114. package/dist/runtime/step-latency.d.ts +197 -0
  115. package/dist/runtime/step-latency.d.ts.map +1 -0
  116. package/dist/runtime/step-latency.js +207 -0
  117. package/dist/runtime/step-ownership.d.ts +72 -0
  118. package/dist/runtime/step-ownership.d.ts.map +1 -0
  119. package/dist/runtime/step-ownership.js +114 -0
  120. package/dist/runtime/step-single-flight.d.ts +12 -0
  121. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  122. package/dist/runtime/step-single-flight.js +69 -0
  123. package/dist/runtime/suspension-handler.d.ts +102 -7
  124. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  125. package/dist/runtime/suspension-handler.js +439 -140
  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 +84 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +105 -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 +5 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +12 -0
  141. package/dist/runtime/world-init.d.ts +50 -0
  142. package/dist/runtime/world-init.d.ts.map +1 -0
  143. package/dist/runtime/world-init.js +50 -0
  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 +101 -26
  147. package/dist/runtime.d.ts +17 -12
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3078 -327
  150. package/dist/schemas.d.ts +1 -1
  151. package/dist/schemas.d.ts.map +1 -1
  152. package/dist/schemas.js +1 -1
  153. package/dist/sealed-box.d.ts +167 -0
  154. package/dist/sealed-box.d.ts.map +1 -0
  155. package/dist/sealed-box.js +571 -0
  156. package/dist/serialization/client.d.ts +17 -0
  157. package/dist/serialization/client.d.ts.map +1 -0
  158. package/dist/serialization/client.js +48 -0
  159. package/dist/serialization/codec-devalue-vm.d.ts +9 -0
  160. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  161. package/dist/serialization/codec-devalue-vm.js +137 -0
  162. package/dist/serialization/codec-devalue.d.ts +14 -0
  163. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  164. package/dist/serialization/codec-devalue.js +105 -0
  165. package/dist/serialization/codec.d.ts +125 -0
  166. package/dist/serialization/codec.d.ts.map +1 -0
  167. package/dist/serialization/codec.js +17 -0
  168. package/dist/serialization/compression.d.ts +104 -0
  169. package/dist/serialization/compression.d.ts.map +1 -0
  170. package/dist/serialization/compression.js +260 -0
  171. package/dist/serialization/encryption.d.ts +134 -0
  172. package/dist/serialization/encryption.d.ts.map +1 -0
  173. package/dist/serialization/encryption.js +186 -0
  174. package/dist/serialization/errors.d.ts +34 -0
  175. package/dist/serialization/errors.d.ts.map +1 -0
  176. package/dist/serialization/errors.js +59 -0
  177. package/dist/serialization/format.d.ts +60 -0
  178. package/dist/serialization/format.d.ts.map +1 -0
  179. package/dist/serialization/format.js +97 -0
  180. package/dist/serialization/hardened.d.ts +155 -0
  181. package/dist/serialization/hardened.d.ts.map +1 -0
  182. package/dist/serialization/hardened.js +523 -0
  183. package/dist/serialization/index.d.ts +20 -0
  184. package/dist/serialization/index.d.ts.map +1 -0
  185. package/dist/serialization/index.js +22 -0
  186. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  187. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  188. package/dist/serialization/reducers/class-vm.js +77 -0
  189. package/dist/serialization/reducers/class.d.ts +11 -0
  190. package/dist/serialization/reducers/class.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class.js +73 -0
  192. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  193. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  194. package/dist/serialization/reducers/common-vm.js +579 -0
  195. package/dist/serialization/reducers/common.d.ts +16 -0
  196. package/dist/serialization/reducers/common.d.ts.map +1 -0
  197. package/dist/serialization/reducers/common.js +478 -0
  198. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  199. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  200. package/dist/serialization/reducers/step-function-vm.js +97 -0
  201. package/dist/serialization/reducers/step-function.d.ts +35 -0
  202. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  203. package/dist/serialization/reducers/step-function.js +104 -0
  204. package/dist/serialization/step.d.ts +17 -0
  205. package/dist/serialization/step.d.ts.map +1 -0
  206. package/dist/serialization/step.js +48 -0
  207. package/dist/serialization/types.d.ts +273 -0
  208. package/dist/serialization/types.d.ts.map +1 -0
  209. package/dist/serialization/types.js +35 -0
  210. package/dist/serialization/vm-bundle-entry.d.ts +12 -0
  211. package/dist/serialization/vm-bundle-entry.d.ts.map +1 -0
  212. package/dist/serialization/vm-bundle-entry.js +58 -0
  213. package/dist/serialization/workflow-vm.d.ts +24 -0
  214. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  215. package/dist/serialization/workflow-vm.js +66 -0
  216. package/dist/serialization/workflow.d.ts +29 -0
  217. package/dist/serialization/workflow.d.ts.map +1 -0
  218. package/dist/serialization/workflow.js +54 -0
  219. package/dist/serialization-format.d.ts +60 -4
  220. package/dist/serialization-format.d.ts.map +1 -1
  221. package/dist/serialization-format.js +276 -56
  222. package/dist/serialization.d.ts +374 -221
  223. package/dist/serialization.d.ts.map +1 -1
  224. package/dist/serialization.js +2300 -783
  225. package/dist/set-attributes.d.ts +13 -0
  226. package/dist/set-attributes.d.ts.map +1 -0
  227. package/dist/set-attributes.js +60 -0
  228. package/dist/sleep.d.ts.map +1 -1
  229. package/dist/sleep.js +3 -2
  230. package/dist/source-map.d.ts +25 -0
  231. package/dist/source-map.d.ts.map +1 -1
  232. package/dist/source-map.js +148 -10
  233. package/dist/step/context-storage.d.ts +61 -2
  234. package/dist/step/context-storage.d.ts.map +1 -1
  235. package/dist/step/context-storage.js +7 -5
  236. package/dist/step/get-closure-vars.d.ts.map +1 -1
  237. package/dist/step/get-closure-vars.js +3 -2
  238. package/dist/step/get-step-metadata.d.ts.map +1 -1
  239. package/dist/step/get-step-metadata.js +3 -2
  240. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  241. package/dist/step/get-workflow-metadata.js +3 -2
  242. package/dist/step/writable-stream.d.ts.map +1 -1
  243. package/dist/step/writable-stream.js +71 -7
  244. package/dist/step.d.ts.map +1 -1
  245. package/dist/step.js +226 -30
  246. package/dist/symbols.d.ts +54 -0
  247. package/dist/symbols.d.ts.map +1 -1
  248. package/dist/symbols.js +55 -1
  249. package/dist/telemetry/semantic-conventions.d.ts +242 -2
  250. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  251. package/dist/telemetry/semantic-conventions.js +173 -1
  252. package/dist/telemetry.d.ts +73 -0
  253. package/dist/telemetry.d.ts.map +1 -1
  254. package/dist/telemetry.js +153 -16
  255. package/dist/types.d.ts +6 -0
  256. package/dist/types.d.ts.map +1 -1
  257. package/dist/types.js +23 -1
  258. package/dist/util.d.ts +16 -6
  259. package/dist/util.d.ts.map +1 -1
  260. package/dist/util.js +25 -16
  261. package/dist/version.d.ts +1 -1
  262. package/dist/version.d.ts.map +1 -1
  263. package/dist/version.js +2 -2
  264. package/dist/vm/index.d.ts.map +1 -1
  265. package/dist/vm/index.js +77 -9
  266. package/dist/vm/script-cache.d.ts +28 -0
  267. package/dist/vm/script-cache.d.ts.map +1 -0
  268. package/dist/vm/script-cache.js +140 -0
  269. package/dist/workflow/abort-controller.d.ts +65 -0
  270. package/dist/workflow/abort-controller.d.ts.map +1 -0
  271. package/dist/workflow/abort-controller.js +314 -0
  272. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  273. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  274. package/dist/workflow/attribute-dispatcher.js +48 -0
  275. package/dist/workflow/create-hook.d.ts.map +1 -1
  276. package/dist/workflow/create-hook.js +25 -3
  277. package/dist/workflow/define-hook.d.ts +1 -1
  278. package/dist/workflow/define-hook.d.ts.map +1 -1
  279. package/dist/workflow/define-hook.js +8 -4
  280. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  281. package/dist/workflow/get-workflow-metadata.js +14 -3
  282. package/dist/workflow/hook.d.ts.map +1 -1
  283. package/dist/workflow/hook.js +303 -37
  284. package/dist/workflow/index.d.ts +1 -0
  285. package/dist/workflow/index.d.ts.map +1 -1
  286. package/dist/workflow/index.js +5 -3
  287. package/dist/workflow/set-attributes.d.ts +68 -0
  288. package/dist/workflow/set-attributes.d.ts.map +1 -0
  289. package/dist/workflow/set-attributes.js +60 -0
  290. package/dist/workflow/sleep.d.ts.map +1 -1
  291. package/dist/workflow/sleep.js +58 -9
  292. package/dist/workflow/world-init-stub.d.ts +15 -0
  293. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  294. package/dist/workflow/world-init-stub.js +15 -0
  295. package/dist/workflow.d.ts +69 -3
  296. package/dist/workflow.d.ts.map +1 -1
  297. package/dist/workflow.js +791 -554
  298. package/docs/api-reference/create-hook.mdx +79 -0
  299. package/docs/api-reference/create-webhook.mdx +1 -0
  300. package/docs/api-reference/define-hook.mdx +26 -24
  301. package/docs/api-reference/fatal-error.mdx +29 -7
  302. package/docs/api-reference/fetch.mdx +8 -4
  303. package/docs/api-reference/index.mdx +3 -0
  304. package/docs/api-reference/set-attributes.mdx +61 -0
  305. package/docs/api-reference/sleep.mdx +1 -1
  306. package/docs/foundations/cancellation.mdx +459 -0
  307. package/docs/foundations/errors-and-retries.mdx +7 -3
  308. package/docs/foundations/hooks.mdx +29 -0
  309. package/docs/foundations/idempotency.mdx +243 -11
  310. package/docs/foundations/index.mdx +1 -23
  311. package/docs/foundations/meta.json +3 -1
  312. package/docs/foundations/serialization.mdx +77 -41
  313. package/docs/foundations/starting-workflows.mdx +79 -2
  314. package/docs/foundations/streaming.mdx +14 -23
  315. package/docs/foundations/versioning.mdx +263 -0
  316. package/docs/how-it-works/cancellation.mdx +287 -0
  317. package/docs/how-it-works/code-transform.mdx +21 -17
  318. package/docs/how-it-works/encryption.mdx +5 -5
  319. package/docs/how-it-works/event-sourcing.mdx +6 -6
  320. package/docs/how-it-works/framework-integrations.mdx +96 -337
  321. package/docs/how-it-works/meta.json +2 -1
  322. package/package.json +31 -13
  323. package/dist/runtime/step-handler.d.ts +0 -2
  324. package/dist/runtime/step-handler.d.ts.map +0 -1
  325. package/dist/runtime/step-handler.js +0 -678
@@ -1,34 +1,121 @@
1
- import { HookConflictError, WorkflowRuntimeError } from '@workflow/errors';
2
- import { withResolvers } from '@workflow/utils';
1
+ import { FatalError, HookConflictError, ReplayDivergenceError, } from '@workflow/errors';
2
+ import { WORKFLOW_DESERIALIZE } from '@workflow/serde';
3
+ import { parseDurationToDate, withResolvers, } from '@workflow/utils';
4
+ import { getSerializationClass, RUN_CLASS_ID } from '../class-serialization.js';
3
5
  import { EventConsumerResult } from '../events-consumer.js';
4
6
  import { WorkflowSuspension } from '../global.js';
5
7
  import { webhookLogger } from '../logger.js';
6
- import { scheduleWhenIdle, } from '../private.js';
8
+ import { awaitEarlierDeliveries, registerDeliveryBarrier, scheduleWhenIdle, } from '../private.js';
7
9
  import { hydrateStepReturnValue } from '../serialization.js';
10
+ /**
11
+ * Constructs a `Run` handle for the run that owns a conflicting hook
12
+ * token, for resolution through `hook.getConflict()`.
13
+ *
14
+ * The instance is created through the serialization class registry on
15
+ * the VM's globalThis — the same channel that revives serialized `Run`
16
+ * instances (e.g. `start()` return values crossing from a step into the
17
+ * workflow). The registered class is the VM bundle's plugin-compiled
18
+ * `Run`, whose methods are durable step proxies — safe to call from
19
+ * workflow code — and construction goes through its
20
+ * `WORKFLOW_DESERIALIZE` hook, exactly as the `Instance` reviver would.
21
+ *
22
+ * Returns `null` when a real `Run` cannot be constructed: the conflict
23
+ * event lacks `conflictingRunId` (written by an old world), or the VM's
24
+ * registry has no `Run` (a context that never evaluated the
25
+ * workflow-mode `create-hook` module, which aliases it under
26
+ * `RUN_CLASS_ID`). `getConflict` awaiters then reject with
27
+ * `HookConflictError` instead of resolving with a value that doesn't
28
+ * honor the `Run` contract.
29
+ */
30
+ function createConflictingRun(ctx, conflictingRunId) {
31
+ if (typeof conflictingRunId !== 'string') {
32
+ return null;
33
+ }
34
+ const RunClass = getSerializationClass(RUN_CLASS_ID, ctx.globalThis);
35
+ const deserialize = RunClass?.[WORKFLOW_DESERIALIZE];
36
+ if (typeof deserialize !== 'function') {
37
+ return null;
38
+ }
39
+ return deserialize.call(RunClass, { runId: conflictingRunId });
40
+ }
8
41
  export function createCreateHook(ctx) {
9
42
  return function createHookImpl(options = {}) {
43
+ // Reject an explicit empty-string token. A token must either be omitted
44
+ // (or `undefined`/`null`) to get a randomly generated one, or be an
45
+ // explicit non-empty string. An empty string is almost always an
46
+ // accidental value (e.g. an unset variable) and would otherwise slip
47
+ // through the `??` below — which only falls back for nullish values — and
48
+ // be used as a meaningless, non-deterministic token.
49
+ if (options.token === '') {
50
+ throw new Error('`createHook()` was called with an empty string token. Pass a non-empty token, or omit the `token` option to use a randomly generated one.');
51
+ }
52
+ if (options.isWebhook === true &&
53
+ options.experimental_minRetention !== undefined) {
54
+ throw new Error('Webhook hooks do not support `experimental_minRetention`. Use a non-webhook `createHook()` with `resumeHook()`.');
55
+ }
56
+ if (options.experimental_minRetention !== undefined &&
57
+ ctx.worldCapabilities?.hookRetention?.active !== true) {
58
+ throw new FatalError('The configured World does not support `experimental_minRetention` for Hooks.');
59
+ }
10
60
  // Generate hook ID and token
11
- const correlationId = `hook_${ctx.generateUlid()}`;
61
+ const correlationId = `hook_${ctx.generateCorrelationId('hook')}`;
12
62
  const token = options.token ?? ctx.generateNanoid();
63
+ const tokenRetentionUntil = options.experimental_minRetention === undefined
64
+ ? undefined
65
+ : parseDurationToDate(options.experimental_minRetention);
13
66
  // Add hook creation to invocations queue (using Map for O(1) operations)
14
67
  const isWebhook = options.isWebhook ?? false;
15
68
  ctx.invocationsQueue.set(correlationId, {
16
69
  type: 'hook',
17
70
  correlationId,
18
71
  token,
72
+ tokenRetentionUntil,
19
73
  metadata: options.metadata,
20
74
  isWebhook,
21
75
  });
22
- // Queue of hook events that have been received but not yet processed
76
+ // Queue of buffered hook payloads (received before the workflow awaited
77
+ // the hook). Each entry's `claim()` builds the consumer-facing promise
78
+ // from the captured hydration outcome and orders it deterministically by
79
+ // event-log position against any concurrent branch-deciding resolution
80
+ // (see `ctx.pendingDeliveryBarriers`).
23
81
  const payloadsQueue = [];
24
82
  // Queue of promises that resolve to the next hook payload
25
83
  const promises = [];
84
+ // Queue of promises that resolve once hook registration is confirmed
85
+ // (with `null`) or a token conflict is detected (with the conflicting
86
+ // `Run`). These back the `hook.getConflict()` getter.
87
+ const getConflictPromises = [];
26
88
  let eventLogEmpty = false;
89
+ // Track if the event log confirms hook creation happened
90
+ let hasCreated = false;
27
91
  // Track if the event log confirms disposal happened (replay no-op)
28
92
  let hasDisposedEvent = false;
29
93
  // Track if we have a conflict so we can reject future awaits
30
94
  let hasConflict = false;
31
95
  let conflictErrorRef = null;
96
+ // The conflicting run handle, shared by every `getConflict` await so
97
+ // repeated awaits observe the same instance deterministically.
98
+ let conflictRunRef = null;
99
+ // Lazy-resume dedup: `resumeHook()` mints a `resumeId` per resume
100
+ // attempt and stamps it on the `hook_received` event. When the direct
101
+ // event write fails transiently, the runtime materializes the event from
102
+ // the queue payload instead — and because `hook_received` has no
103
+ // storage-level uniqueness constraint, concurrent redelivery of the same
104
+ // queue message can commit that materialization twice. Two rows for ONE
105
+ // resume attempt then share a `resumeId` (distinct resume attempts never
106
+ // do), so replay delivers only the first-in-log occurrence. This is a
107
+ // pure function of the persisted event log, keeping replay deterministic.
108
+ //
109
+ // Scope: this is defense-in-depth over the persisted log, not a
110
+ // cross-invocation exactly-once guarantee — an invocation replaying a
111
+ // snapshot taken before the duplicate row committed only sees one row,
112
+ // so two CONCURRENT invocations can each deliver from their own
113
+ // snapshot. Every replay from a log containing both rows (i.e. all
114
+ // subsequent deliveries) dedups. The correctness boundary that closes
115
+ // the concurrent window is the storage-level (runId, resumeId)
116
+ // constraint arriving with the parallel-resume successor work; this set
117
+ // stays useful after that lands, for logs written before it deployed.
118
+ const seenResumeIds = new Set();
32
119
  webhookLogger.debug('Hook consumer setup', { correlationId, token });
33
120
  ctx.eventsConsumer.subscribe((event) => {
34
121
  // If there are no events and there are promises waiting,
@@ -36,7 +123,8 @@ export function createCreateHook(ctx) {
36
123
  // In this case, the workflow should be suspended until the hook is resumed.
37
124
  if (!event) {
38
125
  eventLogEmpty = true;
39
- if (promises.length > 0 && payloadsQueue.length === 0) {
126
+ if ((promises.length > 0 && payloadsQueue.length === 0) ||
127
+ (getConflictPromises.length > 0 && !hasCreated && !hasConflict)) {
40
128
  scheduleWhenIdle(ctx, () => {
41
129
  ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
42
130
  });
@@ -47,12 +135,30 @@ export function createCreateHook(ctx) {
47
135
  // We're not interested in this event - the correlationId belongs to a different entity
48
136
  return EventConsumerResult.NotConsumed;
49
137
  }
138
+ const eventToken = 'eventData' in event && event.eventData && 'token' in event.eventData
139
+ ? event.eventData.token
140
+ : undefined;
141
+ if (typeof eventToken === 'string' && eventToken !== token) {
142
+ ctx.promiseQueue = ctx.promiseQueue.then(() => {
143
+ ctx.onWorkflowError(new ReplayDivergenceError(`Replay divergence: hook event ${event.eventType} for ${correlationId} belongs to token "${eventToken}", but the current hook consumer expects "${token}"`, { eventId: event.eventId }));
144
+ });
145
+ return EventConsumerResult.Finished;
146
+ }
50
147
  // Check for hook_created event to mark this hook as already created
51
148
  if (event.eventType === 'hook_created') {
52
149
  const queueItem = ctx.invocationsQueue.get(correlationId);
53
150
  if (queueItem && queueItem.type === 'hook') {
54
151
  queueItem.hasCreatedEvent = true;
152
+ queueItem.tokenRetentionUntil = event.eventData.tokenRetentionUntil;
55
153
  }
154
+ hasCreated = true;
155
+ const pendingGetConflictPromises = getConflictPromises.slice();
156
+ getConflictPromises.length = 0;
157
+ ctx.promiseQueue = ctx.promiseQueue.then(() => {
158
+ for (const resolver of pendingGetConflictPromises) {
159
+ resolver.resolve(null);
160
+ }
161
+ });
56
162
  return EventConsumerResult.Consumed;
57
163
  }
58
164
  // Handle hook_conflict event - another workflow is using this token
@@ -62,46 +168,176 @@ export function createCreateHook(ctx) {
62
168
  // Store the conflict event so we can reject any awaited promises.
63
169
  // Chain through promiseQueue to ensure deterministic ordering.
64
170
  const conflictEvent = event;
65
- const conflictError = new HookConflictError(conflictEvent.eventData.token);
171
+ const conflictError = new HookConflictError(conflictEvent.eventData.token, conflictEvent.eventData.conflictingRunId);
66
172
  // Mark that we have a conflict so future awaits also reject
67
173
  hasConflict = true;
68
174
  conflictErrorRef = conflictError;
175
+ conflictRunRef = createConflictingRun(ctx, conflictEvent.eventData.conflictingRunId);
69
176
  // Capture and drain pending promises synchronously so the null event
70
177
  // handler won't see them and trigger a spurious WorkflowSuspension.
71
- // The actual rejections are deferred through promiseQueue for ordering.
178
+ // The actual settlements are deferred through promiseQueue for
179
+ // ordering. Payload awaiters reject with HookConflictError, while
180
+ // `getConflict` awaiters resolve with the conflicting run so the
181
+ // workflow can branch on the conflict without throwing. When no
182
+ // real `Run` can be constructed (see `createConflictingRun`),
183
+ // `getConflict` awaiters reject with the HookConflictError instead
184
+ // of resolving with a value that doesn't honor the `Run` contract.
72
185
  const pendingPromises = promises.slice();
73
186
  promises.length = 0;
187
+ const pendingGetConflictPromises = getConflictPromises.slice();
188
+ getConflictPromises.length = 0;
74
189
  ctx.promiseQueue = ctx.promiseQueue.then(() => {
75
190
  for (const resolver of pendingPromises) {
76
191
  resolver.reject(conflictError);
77
192
  }
193
+ for (const resolver of pendingGetConflictPromises) {
194
+ if (conflictRunRef) {
195
+ resolver.resolve(conflictRunRef);
196
+ }
197
+ else {
198
+ resolver.reject(conflictError);
199
+ }
200
+ }
78
201
  });
79
202
  return EventConsumerResult.Consumed;
80
203
  }
81
204
  if (event.eventType === 'hook_received') {
82
- if (promises.length > 0) {
205
+ // Drop duplicate deliveries of the same resume attempt (same
206
+ // `resumeId` — see `seenResumeIds` above). Events without a
207
+ // `resumeId` (older SDKs, legacy spec versions) are never deduped.
208
+ //
209
+ // Dedup off the top-level `resumeId` the backend hoists onto the event
210
+ // as a first-class column. An earlier unreleased build additionally
211
+ // wrote it nested under `eventData`, but that form never shipped and is
212
+ // stripped by `EventSchema` parsing (the `hook_received` eventData
213
+ // schema does not declare it), so there is no persisted nested form to
214
+ // fall back to.
215
+ const resumeId = event.resumeId;
216
+ if (typeof resumeId === 'string') {
217
+ if (seenResumeIds.has(resumeId)) {
218
+ return EventConsumerResult.Consumed;
219
+ }
220
+ seenResumeIds.add(resumeId);
221
+ }
222
+ // Register a 'hook' delivery barrier at this event's log index so a
223
+ // later-in-log `wait_completed` or step result is delivered only after
224
+ // this hook, and so this hook is delivered only after every
225
+ // earlier-in-log `wait_completed` and step result — keeping any
226
+ // `Promise.race` (or concurrent-branch ULID allocation) deterministic
227
+ // and aligned with the committed event log, regardless of
228
+ // microtask-hop count, hydration time, or race-argument order.
229
+ // See `ctx.pendingDeliveryBarriers`.
230
+ //
231
+ // The barrier is registered ARMED only when a consumer is already
232
+ // awaiting, so this payload is committed to reaching the workflow. A
233
+ // buffered payload is registered unarmed and armed by `claim()`: until
234
+ // a consumer takes it, a later step result must not be ordered behind
235
+ // it (see `awaitEarlierDeliveries`).
236
+ const eventIndex = ctx.eventsConsumer.eventIndex;
237
+ const hasWaitingConsumer = promises.length > 0;
238
+ const barrier = registerDeliveryBarrier(ctx, eventIndex, 'hook', {
239
+ armed: hasWaitingConsumer,
240
+ });
241
+ if (hasWaitingConsumer) {
242
+ // A consumer is already awaiting, so this payload's delivery is
243
+ // pinned to this log position: capture the deferral HERE, while
244
+ // consuming the event, not at the end of the hydration slot below —
245
+ // same reasoning as step.ts. An earlier step or hook whose slot runs
246
+ // first on this serial queue has usually delivered, and so
247
+ // deregistered its barrier, before this slot ends. Read then, it
248
+ // would be invisible and this payload would skip both the gate AND
249
+ // `awaitEarlierDeliveries`' macrotask yield, letting it overtake the
250
+ // branch that earlier delivery just woke. Every event in one drain
251
+ // window is consumed before any slot runs, so capturing at
252
+ // consumption time sees all of them.
253
+ //
254
+ // The BUFFERED branch below deliberately does NOT do this — see the
255
+ // comment on `claim()`.
256
+ const earlierDelivered = awaitEarlierDeliveries(ctx, eventIndex, 'hook');
83
257
  const next = promises.shift();
84
258
  if (next) {
85
- // Reconstruct the payload from the event data.
86
- // Chain through ctx.promiseQueue to ensure that async
87
- // deserialization (e.g., decryption) resolves in event log order.
259
+ // Hydrate through a promiseQueue slot (so async deserialization
260
+ // stays in event-log order), then defer behind earlier waits and
261
+ // steps before resolving. The deferral runs OFF the serial queue
262
+ // (it may wait on an earlier wait or step delivery and blocking a
263
+ // queue slot on that would deadlock the queue).
88
264
  ctx.pendingDeliveries++;
265
+ let hydrateOutcome;
89
266
  ctx.promiseQueue = ctx.promiseQueue.then(async () => {
90
267
  try {
91
- const payload = await hydrateStepReturnValue(event.eventData.payload, ctx.runId, ctx.encryptionKey, ctx.globalThis);
92
- next.resolve(payload);
268
+ const prepared = await ctx.replayPayloadCache.prepareEventPayload(event.eventId, 'payload', event.eventData.payload);
269
+ const payload = await hydrateStepReturnValue(event.eventData.payload, ctx.runId, ctx.encryptionKey, ctx.globalThis, {}, prepared);
270
+ hydrateOutcome = { ok: true, value: payload };
93
271
  }
94
272
  catch (error) {
95
- next.reject(error);
273
+ hydrateOutcome = { ok: false, error };
96
274
  }
97
275
  finally {
98
276
  ctx.pendingDeliveries--;
99
277
  }
278
+ void earlierDelivered.then(() => {
279
+ barrier.markDelivered();
280
+ if (hydrateOutcome.ok) {
281
+ next.resolve(hydrateOutcome.value);
282
+ }
283
+ else {
284
+ next.reject(hydrateOutcome.error);
285
+ }
286
+ });
100
287
  });
101
288
  }
102
289
  }
103
290
  else {
104
- payloadsQueue.push(event);
291
+ // No consumer is awaiting yet. Hydrate through a promiseQueue slot
292
+ // at this log position and park the OUTCOME (value or error) for a
293
+ // later `iterator.next()` / `await hook` claim. We capture the
294
+ // outcome rather than eagerly resolving/rejecting a promise no
295
+ // consumer has attached to — a rejected unclaimed promise (e.g. a
296
+ // buffered encrypted payload with no key) would otherwise surface
297
+ // as an unhandled rejection and crash the process. `claim()` builds
298
+ // the consumer-facing promise on demand.
299
+ let outcome;
300
+ const hydrated = withResolvers();
301
+ const claim = () => {
302
+ // A consumer has taken this payload, so its delivery no longer
303
+ // waits on workflow code: later step results may now be ordered
304
+ // behind it.
305
+ barrier.arm();
306
+ // Unlike every other delivery, the deferral is evaluated HERE, at
307
+ // claim time, rather than when the event was consumed. A buffered
308
+ // payload's delivery genuinely happens when the workflow reads the
309
+ // hook, which may be many deliveries later; a consumption-time
310
+ // snapshot would make the claim wait on — and pay the macrotask
311
+ // yield for — barriers that were relevant to a moment this payload
312
+ // never participated in. That is not theoretical: it stalls the
313
+ // second payload in the e2e `hookWithSleepWorkflow` long enough
314
+ // for the run to suspend before delivering it.
315
+ return hydrated.promise
316
+ .then(() => awaitEarlierDeliveries(ctx, eventIndex, 'hook'))
317
+ .then(() => {
318
+ barrier.markDelivered();
319
+ if (outcome && !outcome.ok) {
320
+ throw outcome.error;
321
+ }
322
+ return outcome.value;
323
+ });
324
+ };
325
+ ctx.pendingDeliveries++;
326
+ ctx.promiseQueue = ctx.promiseQueue.then(async () => {
327
+ try {
328
+ const prepared = await ctx.replayPayloadCache.prepareEventPayload(event.eventId, 'payload', event.eventData.payload);
329
+ const payload = await hydrateStepReturnValue(event.eventData.payload, ctx.runId, ctx.encryptionKey, ctx.globalThis, {}, prepared);
330
+ outcome = { ok: true, value: payload };
331
+ }
332
+ catch (error) {
333
+ outcome = { ok: false, error };
334
+ }
335
+ finally {
336
+ ctx.pendingDeliveries--;
337
+ hydrated.resolve();
338
+ }
339
+ });
340
+ payloadsQueue.push({ claim });
105
341
  }
106
342
  return EventConsumerResult.Consumed;
107
343
  }
@@ -113,9 +349,9 @@ export function createCreateHook(ctx) {
113
349
  // We're done processing any more events for this hook
114
350
  return EventConsumerResult.Finished;
115
351
  }
116
- // An unexpected event type has been received, this event log looks corrupted. Let's fail immediately.
352
+ // This replay installed a different consumer than the stored event needs.
117
353
  ctx.promiseQueue = ctx.promiseQueue.then(() => {
118
- ctx.onWorkflowError(new WorkflowRuntimeError(`Unexpected event type for hook ${correlationId} (token: ${token}) "${event.eventType}"`));
354
+ ctx.onWorkflowError(new ReplayDivergenceError(`Replay divergence: Unexpected event type for hook ${correlationId} (token: ${token}) "${event.eventType}"`, { eventId: event.eventId }));
119
355
  });
120
356
  return EventConsumerResult.Finished;
121
357
  });
@@ -133,24 +369,15 @@ export function createCreateHook(ctx) {
133
369
  return resolvers.promise;
134
370
  }
135
371
  if (payloadsQueue.length > 0) {
136
- const nextPayload = payloadsQueue.shift();
137
- if (nextPayload) {
138
- // Chain through ctx.promiseQueue to ensure that async
139
- // deserialization (e.g., decryption) resolves in event log order.
140
- ctx.pendingDeliveries++;
141
- ctx.promiseQueue = ctx.promiseQueue.then(async () => {
142
- try {
143
- const payload = await hydrateStepReturnValue(nextPayload.eventData.payload, ctx.runId, ctx.encryptionKey, ctx.globalThis);
144
- resolvers.resolve(payload);
145
- }
146
- catch (error) {
147
- resolvers.reject(error);
148
- }
149
- finally {
150
- ctx.pendingDeliveries--;
151
- }
152
- });
153
- return resolvers.promise;
372
+ const nextDelivery = payloadsQueue.shift();
373
+ if (nextDelivery) {
374
+ // The payload was hydrated through a promiseQueue slot at its log
375
+ // position (buffering branch above). `claim()` builds the
376
+ // consumer-facing promise from that outcome, deferring behind any
377
+ // earlier-in-log wait or step and marking this hook delivered — so
378
+ // resolution order stays anchored to the event log, not this later
379
+ // claim site.
380
+ return nextDelivery.claim();
154
381
  }
155
382
  }
156
383
  if (eventLogEmpty) {
@@ -161,6 +388,42 @@ export function createCreateHook(ctx) {
161
388
  promises.push(resolvers);
162
389
  return resolvers.promise;
163
390
  }
391
+ // Helper function to create a promise that resolves with the hook's
392
+ // registration outcome: the conflicting `Run` when the token is owned
393
+ // by another active hook, `null` once this hook's registration is
394
+ // committed. Both fast-paths settle through `ctx.promiseQueue` so
395
+ // resolution order always matches event-log order.
396
+ function createGetConflictPromise() {
397
+ const resolvers = withResolvers();
398
+ if (hasCreated) {
399
+ ctx.promiseQueue = ctx.promiseQueue.then(() => {
400
+ resolvers.resolve(null);
401
+ });
402
+ return resolvers.promise;
403
+ }
404
+ if (hasConflict) {
405
+ ctx.promiseQueue = ctx.promiseQueue.then(() => {
406
+ if (conflictRunRef) {
407
+ resolvers.resolve(conflictRunRef);
408
+ }
409
+ else {
410
+ resolvers.reject(conflictErrorRef);
411
+ }
412
+ });
413
+ return resolvers.promise;
414
+ }
415
+ const queueItem = ctx.invocationsQueue.get(correlationId);
416
+ if (queueItem && queueItem.type === 'hook') {
417
+ queueItem.hasConflictAwaiter = true;
418
+ }
419
+ if (eventLogEmpty) {
420
+ scheduleWhenIdle(ctx, () => {
421
+ ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
422
+ });
423
+ }
424
+ getConflictPromises.push(resolvers);
425
+ return resolvers.promise;
426
+ }
164
427
  // Helper function to dispose the hook
165
428
  function disposeHook() {
166
429
  if (isDisposed) {
@@ -190,6 +453,9 @@ export function createCreateHook(ctx) {
190
453
  }
191
454
  const hook = {
192
455
  token,
456
+ getConflict() {
457
+ return createGetConflictPromise();
458
+ },
193
459
  // biome-ignore lint/suspicious/noThenProperty: Intentionally thenable
194
460
  then(onfulfilled, onrejected) {
195
461
  return createHookPromise().then(onfulfilled, onrejected);
@@ -213,4 +479,4 @@ export function createCreateHook(ctx) {
213
479
  return hook;
214
480
  };
215
481
  }
216
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9vay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93b3JrZmxvdy9ob29rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNFLE9BQU8sRUFBNkIsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHM0UsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxFQUNMLGdCQUFnQixHQUVqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU3RCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsR0FBZ0M7SUFDL0QsT0FBTyxTQUFTLGNBQWMsQ0FBVSxVQUF1QixFQUFFO1FBQy9ELDZCQUE2QjtRQUM3QixNQUFNLGFBQWEsR0FBRyxRQUFRLEdBQUcsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO1FBQ25ELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXBELHlFQUF5RTtRQUN6RSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQztRQUU3QyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRTtZQUN0QyxJQUFJLEVBQUUsTUFBTTtZQUNaLGFBQWE7WUFDYixLQUFLO1lBQ0wsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQzFCLFNBQVM7U0FDVixDQUFDLENBQUM7UUFFSCxxRUFBcUU7UUFDckUsTUFBTSxhQUFhLEdBQXdCLEVBQUUsQ0FBQztRQUU5QywwREFBMEQ7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LENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFdBQVc7U0FDOUIsQ0FBQztRQUVGLHFFQUFxRTtRQUNyRSxvRUFBb0U7UUFDcEUsaUNBQWlDO1FBQ2pDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUNoRCxJQUFJLFNBQVMsSUFBSSxTQUFTLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzdDLElBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxXQUFXLENBQUM7UUFDekMsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEhvb2tDb25mbGljdEVycm9yLCBXb3JrZmxvd1J1bnRpbWVFcnJvciB9IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgdHlwZSBQcm9taXNlV2l0aFJlc29sdmVycywgd2l0aFJlc29sdmVycyB9IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgdHlwZSB7IEhvb2tDb25mbGljdEV2ZW50LCBIb29rUmVjZWl2ZWRFdmVudCB9IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgdHlwZSB7IEhvb2ssIEhvb2tPcHRpb25zIH0gZnJvbSAnLi4vY3JlYXRlLWhvb2suanMnO1xuaW1wb3J0IHsgRXZlbnRDb25zdW1lclJlc3VsdCB9IGZyb20gJy4uL2V2ZW50cy1jb25zdW1lci5qcyc7XG5pbXBvcnQgeyBXb3JrZmxvd1N1c3BlbnNpb24gfSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgd2ViaG9va0xvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQge1xuICBzY2hlZHVsZVdoZW5JZGxlLFxuICB0eXBlIFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbn0gZnJvbSAnLi4vcHJpdmF0ZS5qcyc7XG5pbXBvcnQgeyBoeWRyYXRlU3RlcFJldHVyblZhbHVlIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDcmVhdGVIb29rKGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0KSB7XG4gIHJldHVybiBmdW5jdGlvbiBjcmVhdGVIb29rSW1wbDxUID0gYW55PihvcHRpb25zOiBIb29rT3B0aW9ucyA9IHt9KTogSG9vazxUPiB7XG4gICAgLy8gR2VuZXJhdGUgaG9vayBJRCBhbmQgdG9rZW5cbiAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gYGhvb2tfJHtjdHguZ2VuZXJhdGVVbGlkKCl9YDtcbiAgICBjb25zdCB0b2tlbiA9IG9wdGlvbnMudG9rZW4gPz8gY3R4LmdlbmVyYXRlTmFub2lkKCk7XG5cbiAgICAvLyBBZGQgaG9vayBjcmVhdGlvbiB0byBpbnZvY2F0aW9ucyBxdWV1ZSAodXNpbmcgTWFwIGZvciBPKDEpIG9wZXJhdGlvbnMpXG4gICAgY29uc3QgaXNXZWJob29rID0gb3B0aW9ucy5pc1dlYmhvb2sgPz8gZmFsc2U7XG5cbiAgICBjdHguaW52b2NhdGlvbnNRdWV1ZS5zZXQoY29ycmVsYXRpb25JZCwge1xuICAgICAgdHlwZTogJ2hvb2snLFxuICAgICAgY29ycmVsYXRpb25JZCxcbiAgICAgIHRva2VuLFxuICAgICAgbWV0YWRhdGE6IG9wdGlvbnMubWV0YWRhdGEsXG4gICAgICBpc1dlYmhvb2ssXG4gICAgfSk7XG5cbiAgICAvLyBRdWV1ZSBvZiBob29rIGV2ZW50cyB0aGF0IGhhdmUgYmVlbiByZWNlaXZlZCBidXQgbm90IHlldCBwcm9jZXNzZWRcbiAgICBjb25zdCBwYXlsb2Fkc1F1ZXVlOiBIb29rUmVjZWl2ZWRFdmVudFtdID0gW107XG5cbiAgICAvLyBRdWV1ZSBvZiBwcm9taXNlcyB0aGF0IHJlc29sdmUgdG8gdGhlIG5leHQgaG9vayBwYXlsb2FkXG4gICAgY29uc3QgcHJvbWlzZXM6IFByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+W10gPSBbXTtcblxuICAgIGxldCBldmVudExvZ0VtcHR5ID0gZmFsc2U7XG5cbiAgICAvLyBUcmFjayBpZiB0aGUgZXZlbnQgbG9nIGNvbmZpcm1zIGRpc3Bvc2FsIGhhcHBlbmVkIChyZXBsYXkgbm8tb3ApXG4gICAgbGV0IGhhc0Rpc3Bvc2VkRXZlbnQgPSBmYWxzZTtcblxuICAgIC8vIFRyYWNrIGlmIHdlIGhhdmUgYSBjb25mbGljdCBzbyB3ZSBjYW4gcmVqZWN0IGZ1dHVyZSBhd2FpdHNcbiAgICBsZXQgaGFzQ29uZmxpY3QgPSBmYWxzZTtcbiAgICBsZXQgY29uZmxpY3RFcnJvclJlZjogSG9va0NvbmZsaWN0RXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIHdlYmhvb2tMb2dnZXIuZGVidWcoJ0hvb2sgY29uc3VtZXIgc2V0dXAnLCB7IGNvcnJlbGF0aW9uSWQsIHRva2VuIH0pO1xuICAgIGN0eC5ldmVudHNDb25zdW1lci5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gZXZlbnRzIGFuZCB0aGVyZSBhcmUgcHJvbWlzZXMgd2FpdGluZyxcbiAgICAgIC8vIGl0IG1lYW5zIHRoZSBob29rIGhhcyBiZWVuIGF3YWl0ZWQsIGJ1dCBhbiBpbmNvbWluZyBwYXlsb2FkIGhhcyBub3QgeWV0IGJlZW4gcmVjZWl2ZWQuXG4gICAgICAvLyBJbiB0aGlzIGNhc2UsIHRoZSB3b3JrZmxvdyBzaG91bGQgYmUgc3VzcGVuZGVkIHVudGlsIHRoZSBob29rIGlzIHJlc3VtZWQuXG4gICAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIGV2ZW50TG9nRW1wdHkgPSB0cnVlO1xuXG4gICAgICAgIGlmIChwcm9taXNlcy5sZW5ndGggPiAwICYmIHBheWxvYWRzUXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgc2NoZWR1bGVXaGVuSWRsZShjdHgsICgpID0+IHtcbiAgICAgICAgICAgIGN0eC5vbldvcmtmbG93RXJyb3IoXG4gICAgICAgICAgICAgIG5ldyBXb3JrZmxvd1N1c3BlbnNpb24oY3R4Lmludm9jYXRpb25zUXVldWUsIGN0eC5nbG9iYWxUaGlzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Ob3RDb25zdW1lZDtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50LmNvcnJlbGF0aW9uSWQgIT09IGNvcnJlbGF0aW9uSWQpIHtcbiAgICAgICAgLy8gV2UncmUgbm90IGludGVyZXN0ZWQgaW4gdGhpcyBldmVudCAtIHRoZSBjb3JyZWxhdGlvbklkIGJlbG9uZ3MgdG8gYSBkaWZmZXJlbnQgZW50aXR5XG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0Lk5vdENvbnN1bWVkO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBmb3IgaG9va19jcmVhdGVkIGV2ZW50IHRvIG1hcmsgdGhpcyBob29rIGFzIGFscmVhZHkgY3JlYXRlZFxuICAgICAgaWYgKGV2ZW50LmV2ZW50VHlwZSA9PT0gJ2hvb2tfY3JlYXRlZCcpIHtcbiAgICAgICAgY29uc3QgcXVldWVJdGVtID0gY3R4Lmludm9jYXRpb25zUXVldWUuZ2V0KGNvcnJlbGF0aW9uSWQpO1xuICAgICAgICBpZiAocXVldWVJdGVtICYmIHF1ZXVlSXRlbS50eXBlID09PSAnaG9vaycpIHtcbiAgICAgICAgICBxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZDtcbiAgICAgIH1cblxuICAgICAgLy8gSGFuZGxlIGhvb2tfY29uZmxpY3QgZXZlbnQgLSBhbm90aGVyIHdvcmtmbG93IGlzIHVzaW5nIHRoaXMgdG9rZW5cbiAgICAgIGlmIChldmVudC5ldmVudFR5cGUgPT09ICdob29rX2NvbmZsaWN0Jykge1xuICAgICAgICAvLyBSZW1vdmUgdGhpcyBob29rIGZyb20gdGhlIGludm9jYXRpb25zIHF1ZXVlXG4gICAgICAgIGN0eC5pbnZvY2F0aW9uc1F1ZXVlLmRlbGV0ZShjb3JyZWxhdGlvbklkKTtcblxuICAgICAgICAvLyBTdG9yZSB0aGUgY29uZmxpY3QgZXZlbnQgc28gd2UgY2FuIHJlamVjdCBhbnkgYXdhaXRlZCBwcm9taXNlcy5cbiAgICAgICAgLy8gQ2hhaW4gdGhyb3VnaCBwcm9taXNlUXVldWUgdG8gZW5zdXJlIGRldGVybWluaXN0aWMgb3JkZXJpbmcuXG4gICAgICAgIGNvbnN0IGNvbmZsaWN0RXZlbnQgPSBldmVudCBhcyBIb29rQ29uZmxpY3RFdmVudDtcbiAgICAgICAgY29uc3QgY29uZmxpY3RFcnJvciA9IG5ldyBIb29rQ29uZmxpY3RFcnJvcihcbiAgICAgICAgICBjb25mbGljdEV2ZW50LmV2ZW50RGF0YS50b2tlblxuICAgICAgICApO1xuXG4gICAgICAgIC8vIE1hcmsgdGhhdCB3ZSBoYXZlIGEgY29uZmxpY3Qgc28gZnV0dXJlIGF3YWl0cyBhbHNvIHJlamVjdFxuICAgICAgICBoYXNDb25mbGljdCA9IHRydWU7XG4gICAgICAgIGNvbmZsaWN0RXJyb3JSZWYgPSBjb25mbGljdEVycm9yO1xuXG4gICAgICAgIC8vIENhcHR1cmUgYW5kIGRyYWluIHBlbmRpbmcgcHJvbWlzZXMgc3luY2hyb25vdXNseSBzbyB0aGUgbnVsbCBldmVudFxuICAgICAgICAvLyBoYW5kbGVyIHdvbid0IHNlZSB0aGVtIGFuZCB0cmlnZ2VyIGEgc3B1cmlvdXMgV29ya2Zsb3dTdXNwZW5zaW9uLlxuICAgICAgICAvLyBUaGUgYWN0dWFsIHJlamVjdGlvbnMgYXJlIGRlZmVycmVkIHRocm91Z2ggcHJvbWlzZVF1ZXVlIGZvciBvcmRlcmluZy5cbiAgICAgICAgY29uc3QgcGVuZGluZ1Byb21pc2VzID0gcHJvbWlzZXMuc2xpY2UoKTtcbiAgICAgICAgcHJvbWlzZXMubGVuZ3RoID0gMDtcblxuICAgICAgICBjdHgucHJvbWlzZVF1ZXVlID0gY3R4LnByb21pc2VRdWV1ZS50aGVuKCgpID0+IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IHJlc29sdmVyIG9mIHBlbmRpbmdQcm9taXNlcykge1xuICAgICAgICAgICAgcmVzb2x2ZXIucmVqZWN0KGNvbmZsaWN0RXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuQ29uc3VtZWQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudC5ldmVudFR5cGUgPT09ICdob29rX3JlY2VpdmVkJykge1xuICAgICAgICBpZiAocHJvbWlzZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IG5leHQgPSBwcm9taXNlcy5zaGlmdCgpO1xuICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAvLyBSZWNvbnN0cnVjdCB0aGUgcGF5bG9hZCBmcm9tIHRoZSBldmVudCBkYXRhLlxuICAgICAgICAgICAgLy8gQ2hhaW4gdGhyb3VnaCBjdHgucHJvbWlzZVF1ZXVlIHRvIGVuc3VyZSB0aGF0IGFzeW5jXG4gICAgICAgICAgICAvLyBkZXNlcmlhbGl6YXRpb24gKGUuZy4sIGRlY3J5cHRpb24pIHJlc29sdmVzIGluIGV2ZW50IGxvZyBvcmRlci5cbiAgICAgICAgICAgIGN0eC5wZW5kaW5nRGVsaXZlcmllcysrO1xuICAgICAgICAgICAgY3R4LnByb21pc2VRdWV1ZSA9IGN0eC5wcm9taXNlUXVldWUudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGF3YWl0IGh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgICAgICAgICBldmVudC5ldmVudERhdGEucGF5bG9hZCxcbiAgICAgICAgICAgICAgICAgIGN0eC5ydW5JZCxcbiAgICAgICAgICAgICAgICAgIGN0eC5lbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgY3R4Lmdsb2JhbFRoaXNcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIG5leHQucmVzb2x2ZShwYXlsb2FkIGFzIFQpO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIG5leHQucmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICBjdHgucGVuZGluZ0RlbGl2ZXJpZXMtLTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBheWxvYWRzUXVldWUucHVzaChldmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZDtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50LmV2ZW50VHlwZSA9PT0gJ2hvb2tfZGlzcG9zZWQnKSB7XG4gICAgICAgIC8vIFRlcm1pbmFsIHN0YXRlIC0gcmVtb3ZlIGZyb20gcXVldWUgKGxpa2Ugc3RlcF9jb21wbGV0ZWQvd2FpdF9jb21wbGV0ZWQpXG4gICAgICAgIGN0eC5pbnZvY2F0aW9uc1F1ZXVlLmRlbGV0ZShjb3JyZWxhdGlvbklkKTtcbiAgICAgICAgLy8gTWFyayB0aGF0IHRoZSBldmVudCBsb2cgY29uZmlybXMgZGlzcG9zYWwgaGFwcGVuZWRcbiAgICAgICAgaGFzRGlzcG9zZWRFdmVudCA9IHRydWU7XG4gICAgICAgIC8vIFdlJ3JlIGRvbmUgcHJvY2Vzc2luZyBhbnkgbW9yZSBldmVudHMgZm9yIHRoaXMgaG9va1xuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5GaW5pc2hlZDtcbiAgICAgIH1cblxuICAgICAgLy8gQW4gdW5leHBlY3RlZCBldmVudCB0eXBlIGhhcyBiZWVuIHJlY2VpdmVkLCB0aGlzIGV2ZW50IGxvZyBsb29rcyBjb3JydXB0ZWQuIExldCdzIGZhaWwgaW1tZWRpYXRlbHkuXG4gICAgICBjdHgucHJvbWlzZVF1ZXVlID0gY3R4LnByb21pc2VRdWV1ZS50aGVuKCgpID0+IHtcbiAgICAgICAgY3R4Lm9uV29ya2Zsb3dFcnJvcihcbiAgICAgICAgICBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICBgVW5leHBlY3RlZCBldmVudCB0eXBlIGZvciBob29rICR7Y29ycmVsYXRpb25JZH0gKHRva2VuOiAke3Rva2VufSkgXCIke2V2ZW50LmV2ZW50VHlwZX1cImBcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkO1xuICAgIH0pO1xuXG4gICAgLy8gVHJhY2sgaWYgdGhlIGhvb2sgaGFzIGJlZW4gZGlzcG9zZWRcbiAgICBsZXQgaXNEaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhIG5ldyBwcm9taXNlIHRoYXQgd2FpdHMgZm9yIHRoZSBuZXh0IGhvb2sgcGF5bG9hZFxuICAgIGZ1bmN0aW9uIGNyZWF0ZUhvb2tQcm9taXNlKCk6IFByb21pc2U8VD4ge1xuICAgICAgY29uc3QgcmVzb2x2ZXJzID0gd2l0aFJlc29sdmVyczxUPigpO1xuXG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgY29uZmxpY3QsIHJlamVjdCB0aHJvdWdoIHRoZSBwcm9taXNlUXVldWUgdG8gbWFpbnRhaW5cbiAgICAgIC8vIGRldGVybWluaXN0aWMgb3JkZXJpbmcgd2l0aCBhbnkgcHJpb3IgcXVldWVkIHJlc29sdXRpb25zLlxuICAgICAgaWYgKGhhc0NvbmZsaWN0ICYmIGNvbmZsaWN0RXJyb3JSZWYpIHtcbiAgICAgICAgY3R4LnByb21pc2VRdWV1ZSA9IGN0eC5wcm9taXNlUXVldWUudGhlbigoKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZXJzLnJlamVjdChjb25mbGljdEVycm9yUmVmKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXNvbHZlcnMucHJvbWlzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBheWxvYWRzUXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBuZXh0UGF5bG9hZCA9IHBheWxvYWRzUXVldWUuc2hpZnQoKTtcbiAgICAgICAgaWYgKG5leHRQYXlsb2FkKSB7XG4gICAgICAgICAgLy8gQ2hhaW4gdGhyb3VnaCBjdHgucHJvbWlzZVF1ZXVlIHRvIGVuc3VyZSB0aGF0IGFzeW5jXG4gICAgICAgICAgLy8gZGVzZXJpYWxpemF0aW9uIChlLmcuLCBkZWNyeXB0aW9uKSByZXNvbHZlcyBpbiBldmVudCBsb2cgb3JkZXIuXG4gICAgICAgICAgY3R4LnBlbmRpbmdEZWxpdmVyaWVzKys7XG4gICAgICAgICAgY3R4LnByb21pc2VRdWV1ZSA9IGN0eC5wcm9taXNlUXVldWUudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gYXdhaXQgaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgICAgICAgICAgICAgICBuZXh0UGF5bG9hZC5ldmVudERhdGEucGF5bG9hZCxcbiAgICAgICAgICAgICAgICBjdHgucnVuSWQsXG4gICAgICAgICAgICAgICAgY3R4LmVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICAgICAgY3R4Lmdsb2JhbFRoaXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmVzb2x2ZXJzLnJlc29sdmUocGF5bG9hZCBhcyBUKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIHJlc29sdmVycy5yZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgY3R4LnBlbmRpbmdEZWxpdmVyaWVzLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHJlc29sdmVycy5wcm9taXNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudExvZ0VtcHR5KSB7XG4gICAgICAgIHNjaGVkdWxlV2hlbklkbGUoY3R4LCAoKSA9PiB7XG4gICAgICAgICAgY3R4Lm9uV29ya2Zsb3dFcnJvcihcbiAgICAgICAgICAgIG5ldyBXb3JrZmxvd1N1c3BlbnNpb24oY3R4Lmludm9jYXRpb25zUXVldWUsIGN0eC5nbG9iYWxUaGlzKVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBwcm9taXNlcy5wdXNoKHJlc29sdmVycyk7XG5cbiAgICAgIHJldHVybiByZXNvbHZlcnMucHJvbWlzZTtcbiAgICB9XG5cbiAgICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gZGlzcG9zZSB0aGUgaG9va1xuICAgIGZ1bmN0aW9uIGRpc3Bvc2VIb29rKCk6IHZvaWQge1xuICAgICAgaWYgKGlzRGlzcG9zZWQpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBBbHJlYWR5IGRpc3Bvc2VkLCBub3RoaW5nIHRvIGRvXG4gICAgICB9XG4gICAgICBpc0Rpc3Bvc2VkID0gdHJ1ZTtcblxuICAgICAgLy8gSWYgdGhlIGV2ZW50IGxvZyBhbHJlYWR5IGNvbnRhaW5zIGhvb2tfZGlzcG9zZWQsIHRoaXMgaXMgYSByZXBsYXkg4oCUIG5vLW9wXG4gICAgICBpZiAoaGFzRGlzcG9zZWRFdmVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCBkaXNwb3NlZCBmbGFnIG9uIHRoZSBleGlzdGluZyBxdWV1ZSBpdGVtXG4gICAgICBjb25zdCBxdWV1ZUl0ZW0gPSBjdHguaW52b2NhdGlvbnNRdWV1ZS5nZXQoY29ycmVsYXRpb25JZCk7XG4gICAgICBpZiAocXVldWVJdGVtICYmIHF1ZXVlSXRlbS50eXBlID09PSAnaG9vaycpIHtcbiAgICAgICAgcXVldWVJdGVtLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gRHJhaW4gYW55IHBlbmRpbmcgcHJvbWlzZXMgdGhhdCBhcmUgd2FpdGluZyBmb3IgcGF5bG9hZHMuXG4gICAgICAvLyBXaXRob3V0IHRoaXMsIHByb21pc2VzIGNyZWF0ZWQgYnkgYGF3YWl0IGhvb2tgIG9yIHRoZSBhc3luYyBpdGVyYXRvcidzXG4gICAgICAvLyBgeWllbGQgYXdhaXQgdGhpc2Agd291bGQgaGFuZyBmb3JldmVyIHNpbmNlIHRoZSBldmVudCBjb25zdW1lciB3aWxsXG4gICAgICAvLyBuZXZlciBkZWxpdmVyIGFub3RoZXIgaG9va19yZWNlaXZlZCBhZnRlciBkaXNwb3NhbC5cbiAgICAgIGlmIChwcm9taXNlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHByb21pc2VzLmxlbmd0aCA9IDA7XG4gICAgICAgIHNjaGVkdWxlV2hlbklkbGUoY3R4LCAoKSA9PiB7XG4gICAgICAgICAgY3R4Lm9uV29ya2Zsb3dFcnJvcihcbiAgICAgICAgICAgIG5ldyBXb3JrZmxvd1N1c3BlbnNpb24oY3R4Lmludm9jYXRpb25zUXVldWUsIGN0eC5nbG9iYWxUaGlzKVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB3ZWJob29rTG9nZ2VyLmRlYnVnKCdIb29rIGRpc3Bvc2VkJywgeyBjb3JyZWxhdGlvbklkLCB0b2tlbiB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBob29rOiBIb29rPFQ+ID0ge1xuICAgICAgdG9rZW4sXG5cbiAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UaGVuUHJvcGVydHk6IEludGVudGlvbmFsbHkgdGhlbmFibGVcbiAgICAgIHRoZW48VFJlc3VsdDEgPSBULCBUUmVzdWx0MiA9IG5ldmVyPihcbiAgICAgICAgb25mdWxmaWxsZWQ/OiAoKHZhbHVlOiBUKSA9PiBUUmVzdWx0MSB8IFByb21pc2VMaWtlPFRSZXN1bHQxPikgfCBudWxsLFxuICAgICAgICBvbnJlamVjdGVkPzogKChyZWFzb246IGFueSkgPT4gVFJlc3VsdDIgfCBQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgbnVsbFxuICAgICAgKTogUHJvbWlzZTxUUmVzdWx0MSB8IFRSZXN1bHQyPiB7XG4gICAgICAgIHJldHVybiBjcmVhdGVIb29rUHJvbWlzZSgpLnRoZW4ob25mdWxmaWxsZWQsIG9ucmVqZWN0ZWQpO1xuICAgICAgfSxcblxuICAgICAgLy8gU3VwcG9ydCBgZm9yIGF3YWl0IChjb25zdCBwYXlsb2FkIG9mIGhvb2spIHsg4oCmIH1gIHN5bnRheFxuICAgICAgYXN5bmMgKltTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSB7XG4gICAgICAgIHdoaWxlICghaXNEaXNwb3NlZCkge1xuICAgICAgICAgIHlpZWxkIGF3YWl0IHRoaXM7XG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIGRpc3Bvc2U6IGRpc3Bvc2VIb29rLFxuXG4gICAgICBbU3ltYm9sLmRpc3Bvc2VdOiBkaXNwb3NlSG9vayxcbiAgICB9O1xuXG4gICAgLy8gQWxzbyByZWdpc3RlciB3aXRoIHRoZSBWTSdzIFN5bWJvbC5kaXNwb3NlIHNvIGB1c2luZ2Agd29ya3MgaW5zaWRlXG4gICAgLy8gdGhlIHdvcmtmbG93IHNhbmRib3ggKHRoZSBWTSBtYXkgaGF2ZSBhIHBvbHlmaWxsZWQgU3ltYm9sLmRpc3Bvc2VcbiAgICAvLyB0aGF0IGRpZmZlcnMgZnJvbSB0aGUgaG9zdCdzKS5cbiAgICBjb25zdCB2bURpc3Bvc2UgPSBjdHguZ2xvYmFsVGhpcy5TeW1ib2wuZGlzcG9zZTtcbiAgICBpZiAodm1EaXNwb3NlICYmIHZtRGlzcG9zZSAhPT0gU3ltYm9sLmRpc3Bvc2UpIHtcbiAgICAgIChob29rIGFzIGFueSlbdm1EaXNwb3NlXSA9IGRpc3Bvc2VIb29rO1xuICAgIH1cblxuICAgIHJldHVybiBob29rO1xuICB9O1xufVxuIl19
482
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9vay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93b3JrZmxvdy9ob29rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxVQUFVLEVBQ1YsaUJBQWlCLEVBQ2pCLHFCQUFxQixHQUN0QixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZELE9BQU8sRUFFTCxtQkFBbUIsRUFDbkIsYUFBYSxHQUNkLE1BQU0saUJBQWlCLENBQUM7QUFFekIsT0FBTyxFQUFFLHFCQUFxQixFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRWhGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNsRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsdUJBQXVCLEVBQ3ZCLGdCQUFnQixHQUVqQixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU3RDs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILFNBQVMsb0JBQW9CLENBQzNCLEdBQWdDLEVBQ2hDLGdCQUFvQztJQUVwQyxJQUFJLE9BQU8sZ0JBQWdCLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsTUFBTSxRQUFRLEdBQUcscUJBQXFCLENBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBSXRELENBQUM7SUFDZCxNQUFNLFdBQVcsR0FBSSxRQUFnQixFQUFFLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM5RCxJQUFJLE9BQU8sV0FBVyxLQUFLLFVBQVUsRUFBRSxDQUFDO1FBQ3RDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO0FBQ2pFLENBQUM7QUFFRCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsR0FBZ0M7SUFDL0QsT0FBTyxTQUFTLGNBQWMsQ0FBVSxVQUF1QixFQUFFO1FBQy9ELHdFQUF3RTtRQUN4RSxvRUFBb0U7UUFDcEUsaUVBQWlFO1FBQ2pFLHFFQUFxRTtRQUNyRSwwRUFBMEU7UUFDMUUscURBQXFEO1FBQ3JELElBQUksT0FBTyxDQUFDLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUN6QixNQUFNLElBQUksS0FBSyxDQUNiLDJJQUEySSxDQUM1SSxDQUFDO1FBQ0osQ0FBQztRQUVELElBQ0UsT0FBTyxDQUFDLFNBQVMsS0FBSyxJQUFJO1lBQzFCLE9BQU8sQ0FBQyx5QkFBeUIsS0FBSyxTQUFTLEVBQy9DLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLGlIQUFpSCxDQUNsSCxDQUFDO1FBQ0osQ0FBQztRQUVELElBQ0UsT0FBTyxDQUFDLHlCQUF5QixLQUFLLFNBQVM7WUFDL0MsR0FBRyxDQUFDLGlCQUFpQixFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssSUFBSSxFQUNyRCxDQUFDO1lBQ0QsTUFBTSxJQUFJLFVBQVUsQ0FDbEIsOEVBQThFLENBQy9FLENBQUM7UUFDSixDQUFDO1FBRUQsNkJBQTZCO1FBQzdCLE1BQU0sYUFBYSxHQUFHLFFBQVEsR0FBRyxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDbEUsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDcEQsTUFBTSxtQkFBbUIsR0FDdkIsT0FBTyxDQUFDLHlCQUF5QixLQUFLLFNBQVM7WUFDN0MsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFFN0QseUVBQXlFO1FBQ3pFLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDO1FBRTdDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFO1lBQ3RDLElBQUksRUFBRSxNQUFNO1lBQ1osYUFBYTtZQUNiLEtBQUs7WUFDTCxtQkFBbUI7WUFDbkIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQzFCLFNBQVM7U0FDVixDQUFDLENBQUM7UUFFSCx3RUFBd0U7UUFDeEUsdUVBQXVFO1FBQ3ZFLHlFQUF5RTtRQUN6RSx1RUFBdUU7UUFDdkUsdUNBQXVDO1FBQ3ZDLE1BQU0sYUFBYSxHQUFrQyxFQUFFLENBQUM7UUFFeEQsMERBQTBEO1FBQzFELE1BQU0sUUFBUSxHQUE4QixFQUFFLENBQUM7UUFFL0MscUVBQXFFO1FBQ3JFLHNFQUFzRTtRQUN0RSxzREFBc0Q7UUFDdEQsTUFBTSxtQkFBbUIsR0FBZ0QsRUFBRSxDQUFDO1FBRTVFLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztRQUUxQix5REFBeUQ7UUFDekQsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBRXZCLG1FQUFtRTtRQUNuRSxJQUFJLGdCQUFnQixHQUFHLEtBQUssQ0FBQztRQUU3Qiw2REFBNkQ7UUFDN0QsSUFBSSxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLElBQUksZ0JBQWdCLEdBQTZCLElBQUksQ0FBQztRQUN0RCxxRUFBcUU7UUFDckUsK0RBQStEO1FBQy9ELElBQUksY0FBYyxHQUF3QixJQUFJLENBQUM7UUFFL0Msa0VBQWtFO1FBQ2xFLHNFQUFzRTtRQUN0RSx5RUFBeUU7UUFDekUsaUVBQWlFO1FBQ2pFLHlFQUF5RTtRQUN6RSx3RUFBd0U7UUFDeEUseUVBQXlFO1FBQ3pFLHNFQUFzRTtRQUN0RSwwRUFBMEU7UUFDMUUsRUFBRTtRQUNGLGdFQUFnRTtRQUNoRSxzRUFBc0U7UUFDdEUsdUVBQXVFO1FBQ3ZFLGdFQUFnRTtRQUNoRSxtRUFBbUU7UUFDbkUsc0VBQXNFO1FBQ3RFLCtEQUErRDtRQUMvRCx3RUFBd0U7UUFDeEUsc0VBQXNFO1FBQ3RFLE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFFeEMsYUFBYSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3JFLEdBQUcsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDckMseURBQXlEO1lBQ3pELHlGQUF5RjtZQUN6Riw0RUFBNEU7WUFDNUUsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNYLGFBQWEsR0FBRyxJQUFJLENBQUM7Z0JBRXJCLElBQ0UsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztvQkFDbkQsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQy9ELENBQUM7b0JBQ0QsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRTt3QkFDekIsR0FBRyxDQUFDLGVBQWUsQ0FDakIsSUFBSSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUM3RCxDQUFDO29CQUNKLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUM7Z0JBQ0QsT0FBTyxtQkFBbUIsQ0FBQyxXQUFXLENBQUM7WUFDekMsQ0FBQztZQUVELElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxhQUFhLEVBQUUsQ0FBQztnQkFDMUMsdUZBQXVGO2dCQUN2RixPQUFPLG1CQUFtQixDQUFDLFdBQVcsQ0FBQztZQUN6QyxDQUFDO1lBRUQsTUFBTSxVQUFVLEdBQ2QsV0FBVyxJQUFJLEtBQUssSUFBSSxLQUFLLENBQUMsU0FBUyxJQUFJLE9BQU8sSUFBSSxLQUFLLENBQUMsU0FBUztnQkFDbkUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBSztnQkFDdkIsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUVoQixJQUFJLE9BQU8sVUFBVSxLQUFLLFFBQVEsSUFBSSxVQUFVLEtBQUssS0FBSyxFQUFFLENBQUM7Z0JBQzNELEdBQUcsQ0FBQyxZQUFZLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO29CQUM1QyxHQUFHLENBQUMsZUFBZSxDQUNqQixJQUFJLHFCQUFxQixDQUN2QixpQ0FBaUMsS0FBSyxDQUFDLFNBQVMsUUFBUSxhQUFhLHNCQUFzQixVQUFVLDZDQUE2QyxLQUFLLEdBQUcsRUFDMUosRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUMzQixDQUNGLENBQUM7Z0JBQ0osQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsT0FBTyxtQkFBbUIsQ0FBQyxRQUFRLENBQUM7WUFDdEMsQ0FBQztZQUVELG9FQUFvRTtZQUNwRSxJQUFJLEtBQUssQ0FBQyxTQUFTLEtBQUssY0FBYyxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQzFELElBQUksU0FBUyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7b0JBQzNDLFNBQVMsQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDO29CQUNqQyxTQUFTLENBQUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQztnQkFDdEUsQ0FBQztnQkFDRCxVQUFVLEdBQUcsSUFBSSxDQUFDO2dCQUVsQixNQUFNLDBCQUEwQixHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUMvRCxtQkFBbUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO2dCQUMvQixHQUFHLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtvQkFDNUMsS0FBSyxNQUFNLFFBQVEsSUFBSSwwQkFBMEIsRUFBRSxDQUFDO3dCQUNsRCxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN6QixDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILE9BQU8sbUJBQW1CLENBQUMsUUFBUSxDQUFDO1lBQ3RDLENBQUM7WUFFRCxvRUFBb0U7WUFDcEUsSUFBSSxLQUFLLENBQUMsU0FBUyxLQUFLLGVBQWUsRUFBRSxDQUFDO2dCQUN4Qyw4Q0FBOEM7Z0JBQzlDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBRTNDLGtFQUFrRTtnQkFDbEUsK0RBQStEO2dCQUMvRCxNQUFNLGFBQWEsR0FBRyxLQUEwQixDQUFDO2dCQUNqRCxNQUFNLGFBQWEsR0FBRyxJQUFJLGlCQUFpQixDQUN6QyxhQUFhLENBQUMsU0FBUyxDQUFDLEtBQUssRUFDN0IsYUFBYSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FDekMsQ0FBQztnQkFFRiw0REFBNEQ7Z0JBQzVELFdBQVcsR0FBRyxJQUFJLENBQUM7Z0JBQ25CLGdCQUFnQixHQUFHLGFBQWEsQ0FBQztnQkFDakMsY0FBYyxHQUFHLG9CQUFvQixDQUNuQyxHQUFHLEVBQ0gsYUFBYSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FDekMsQ0FBQztnQkFFRixxRUFBcUU7Z0JBQ3JFLG9FQUFvRTtnQkFDcEUsK0RBQStEO2dCQUMvRCxrRUFBa0U7Z0JBQ2xFLGlFQUFpRTtnQkFDakUsZ0VBQWdFO2dCQUNoRSw4REFBOEQ7Z0JBQzlELG1FQUFtRTtnQkFDbkUsbUVBQW1FO2dCQUNuRSxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3pDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO2dCQUNwQixNQUFNLDBCQUEwQixHQUFHLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUMvRCxtQkFBbUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO2dCQUUvQixHQUFHLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtvQkFDNUMsS0FBSyxNQUFNLFFBQVEsSUFBSSxlQUFlLEVBQUUsQ0FBQzt3QkFDdkMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztvQkFDakMsQ0FBQztvQkFDRCxLQUFLLE1BQU0sUUFBUSxJQUFJLDBCQUEwQixFQUFFLENBQUM7d0JBQ2xELElBQUksY0FBYyxFQUFFLENBQUM7NEJBQ25CLFFBQVEsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7d0JBQ25DLENBQUM7NkJBQU0sQ0FBQzs0QkFDTixRQUFRLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO3dCQUNqQyxDQUFDO29CQUNILENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsT0FBTyxtQkFBbUIsQ0FBQyxRQUFRLENBQUM7WUFDdEMsQ0FBQztZQUVELElBQUksS0FBSyxDQUFDLFNBQVMsS0FBSyxlQUFlLEVBQUUsQ0FBQztnQkFDeEMsNkRBQTZEO2dCQUM3RCw0REFBNEQ7Z0JBQzVELG1FQUFtRTtnQkFDbkUsRUFBRTtnQkFDRix1RUFBdUU7Z0JBQ3ZFLG9FQUFvRTtnQkFDcEUsd0VBQXdFO2dCQUN4RSxtRUFBbUU7Z0JBQ25FLHVFQUF1RTtnQkFDdkUsZ0JBQWdCO2dCQUNoQixNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO2dCQUNoQyxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUNqQyxJQUFJLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQzt3QkFDaEMsT0FBTyxtQkFBbUIsQ0FBQyxRQUFRLENBQUM7b0JBQ3RDLENBQUM7b0JBQ0QsYUFBYSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDOUIsQ0FBQztnQkFFRCxvRUFBb0U7Z0JBQ3BFLHVFQUF1RTtnQkFDdkUsNERBQTREO2dCQUM1RCxnRUFBZ0U7Z0JBQ2hFLHNFQUFzRTtnQkFDdEUsMERBQTBEO2dCQUMxRCwrREFBK0Q7Z0JBQy9ELHFDQUFxQztnQkFDckMsRUFBRTtnQkFDRixrRUFBa0U7Z0JBQ2xFLHFFQUFxRTtnQkFDckUsdUVBQXVFO2dCQUN2RSxzRUFBc0U7Z0JBQ3RFLHFDQUFxQztnQkFDckMsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUM7Z0JBQ2pELE1BQU0sa0JBQWtCLEdBQUcsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7Z0JBQy9DLE1BQU0sT0FBTyxHQUFHLHVCQUF1QixDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFO29CQUMvRCxLQUFLLEVBQUUsa0JBQWtCO2lCQUMxQixDQUFDLENBQUM7Z0JBRUgsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO29CQUN2QixnRUFBZ0U7b0JBQ2hFLGdFQUFnRTtvQkFDaEUsb0VBQW9FO29CQUNwRSxxRUFBcUU7b0JBQ3JFLDJEQUEyRDtvQkFDM0QsaUVBQWlFO29CQUNqRSxtRUFBbUU7b0JBQ25FLHFFQUFxRTtvQkFDckUsbUVBQW1FO29CQUNuRSwyREFBMkQ7b0JBQzNELHFDQUFxQztvQkFDckMsRUFBRTtvQkFDRixvRUFBb0U7b0JBQ3BFLHdCQUF3QjtvQkFDeEIsTUFBTSxnQkFBZ0IsR0FBRyxzQkFBc0IsQ0FDN0MsR0FBRyxFQUNILFVBQVUsRUFDVixNQUFNLENBQ1AsQ0FBQztvQkFDRixNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQzlCLElBQUksSUFBSSxFQUFFLENBQUM7d0JBQ1QsZ0VBQWdFO3dCQUNoRSxpRUFBaUU7d0JBQ2pFLGlFQUFpRTt3QkFDakUsa0VBQWtFO3dCQUNsRSxnREFBZ0Q7d0JBQ2hELEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO3dCQUN4QixJQUFJLGNBRTZCLENBQUM7d0JBQ2xDLEdBQUcsQ0FBQyxZQUFZLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUU7NEJBQ2xELElBQUksQ0FBQztnQ0FDSCxNQUFNLFFBQVEsR0FDWixNQUFNLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FDOUMsS0FBSyxDQUFDLE9BQU8sRUFDYixTQUFTLEVBQ1QsS0FBSyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQ3hCLENBQUM7Z0NBQ0osTUFBTSxPQUFPLEdBQUcsTUFBTSxzQkFBc0IsQ0FDMUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQ3ZCLEdBQUcsQ0FBQyxLQUFLLEVBQ1QsR0FBRyxDQUFDLGFBQWEsRUFDakIsR0FBRyxDQUFDLFVBQVUsRUFDZCxFQUFFLEVBQ0YsUUFBUSxDQUNULENBQUM7Z0NBQ0YsY0FBYyxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBWSxFQUFFLENBQUM7NEJBQ3JELENBQUM7NEJBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQ0FDZixjQUFjLEdBQUcsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDOzRCQUN4QyxDQUFDO29DQUFTLENBQUM7Z0NBQ1QsR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7NEJBQzFCLENBQUM7NEJBQ0QsS0FBSyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO2dDQUM5QixPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7Z0NBQ3hCLElBQUksY0FBYyxDQUFDLEVBQUUsRUFBRSxDQUFDO29DQUN0QixJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQ0FDckMsQ0FBQztxQ0FBTSxDQUFDO29DQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dDQUNwQyxDQUFDOzRCQUNILENBQUMsQ0FBQyxDQUFDO3dCQUNMLENBQUMsQ0FBQyxDQUFDO29CQUNMLENBQUM7Z0JBQ0gsQ0FBQztxQkFBTSxDQUFDO29CQUNOLG1FQUFtRTtvQkFDbkUsbUVBQW1FO29CQUNuRSwrREFBK0Q7b0JBQy9ELCtEQUErRDtvQkFDL0Qsa0VBQWtFO29CQUNsRSxrRUFBa0U7b0JBQ2xFLG9FQUFvRTtvQkFDcEUseUNBQXlDO29CQUN6QyxJQUFJLE9BR1MsQ0FBQztvQkFDZCxNQUFNLFFBQVEsR0FBRyxhQUFhLEVBQVEsQ0FBQztvQkFFdkMsTUFBTSxLQUFLLEdBQUcsR0FBZSxFQUFFO3dCQUM3QiwrREFBK0Q7d0JBQy9ELGdFQUFnRTt3QkFDaEUsYUFBYTt3QkFDYixPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7d0JBQ2Qsa0VBQWtFO3dCQUNsRSxrRUFBa0U7d0JBQ2xFLG1FQUFtRTt3QkFDbkUsK0RBQStEO3dCQUMvRCxnRUFBZ0U7d0JBQ2hFLG1FQUFtRTt3QkFDbkUsZ0VBQWdFO3dCQUNoRSxnRUFBZ0U7d0JBQ2hFLCtDQUErQzt3QkFDL0MsT0FBTyxRQUFRLENBQUMsT0FBTzs2QkFDcEIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7NkJBQzNELElBQUksQ0FBQyxHQUFHLEVBQUU7NEJBQ1QsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDOzRCQUN4QixJQUFJLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQ0FDM0IsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDOzRCQUN0QixDQUFDOzRCQUNELE9BQVEsT0FBa0MsQ0FBQyxLQUFLLENBQUM7d0JBQ25ELENBQUMsQ0FBQyxDQUFDO29CQUNQLENBQUMsQ0FBQztvQkFFRixHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztvQkFDeEIsR0FBRyxDQUFDLFlBQVksR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRTt3QkFDbEQsSUFBSSxDQUFDOzRCQUNILE1BQU0sUUFBUSxHQUFHLE1BQU0sR0FBRyxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUMvRCxLQUFLLENBQUMsT0FBTyxFQUNiLFNBQVMsRUFDVCxLQUFLLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FDeEIsQ0FBQzs0QkFDRixNQUFNLE9BQU8sR0FBRyxNQUFNLHNCQUFzQixDQUMxQyxLQUFLLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFDdkIsR0FBRyxDQUFDLEtBQUssRUFDVCxHQUFHLENBQUMsYUFBYSxFQUNqQixHQUFHLENBQUMsVUFBVSxFQUNkLEVBQUUsRUFDRixRQUFRLENBQ1QsQ0FBQzs0QkFDRixPQUFPLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFZLEVBQUUsQ0FBQzt3QkFDOUMsQ0FBQzt3QkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDOzRCQUNmLE9BQU8sR0FBRyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUM7d0JBQ2pDLENBQUM7Z0NBQVMsQ0FBQzs0QkFDVCxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQzs0QkFDeEIsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO3dCQUNyQixDQUFDO29CQUNILENBQUMsQ0FBQyxDQUFDO29CQUNILGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQyxDQUFDO2dCQUVELE9BQU8sbUJBQW1CLENBQUMsUUFBUSxDQUFDO1lBQ3RDLENBQUM7WUFFRCxJQUFJLEtBQUssQ0FBQyxTQUFTLEtBQUssZUFBZSxFQUFFLENBQUM7Z0JBQ3hDLDBFQUEwRTtnQkFDMUUsR0FBRyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDM0MscURBQXFEO2dCQUNyRCxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7Z0JBQ3hCLHNEQUFzRDtnQkFDdEQsT0FBTyxtQkFBbUIsQ0FBQyxRQUFRLENBQUM7WUFDdEMsQ0FBQztZQUVELDBFQUEwRTtZQUMxRSxHQUFHLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDNUMsR0FBRyxDQUFDLGVBQWUsQ0FDakIsSUFBSSxxQkFBcUIsQ0FDdkIscURBQXFELGFBQWEsWUFBWSxLQUFLLE1BQU0sS0FBSyxDQUFDLFNBQVMsR0FBRyxFQUMzRyxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQzNCLENBQ0YsQ0FBQztZQUNKLENBQUMsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxtQkFBbUIsQ0FBQyxRQUFRLENBQUM7UUFDdEMsQ0FBQyxDQUFDLENBQUM7UUFFSCxzQ0FBc0M7UUFDdEMsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBRXZCLCtFQUErRTtRQUMvRSxTQUFTLGlCQUFpQjtZQUN4QixNQUFNLFNBQVMsR0FBRyxhQUFhLEVBQUssQ0FBQztZQUVyQyxxRUFBcUU7WUFDckUsNERBQTREO1lBQzVELElBQUksV0FBVyxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3BDLEdBQUcsQ0FBQyxZQUFZLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO29CQUM1QyxTQUFTLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7Z0JBQ3JDLENBQUMsQ0FBQyxDQUFDO2dCQUNILE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBQztZQUMzQixDQUFDO1lBRUQsSUFBSSxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUM3QixNQUFNLFlBQVksR0FBRyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzNDLElBQUksWUFBWSxFQUFFLENBQUM7b0JBQ2pCLGtFQUFrRTtvQkFDbEUsMERBQTBEO29CQUMxRCxrRUFBa0U7b0JBQ2xFLG1FQUFtRTtvQkFDbkUsbUVBQW1FO29CQUNuRSxjQUFjO29CQUNkLE9BQU8sWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUM5QixDQUFDO1lBQ0gsQ0FBQztZQUVELElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUU7b0JBQ3pCLEdBQUcsQ0FBQyxlQUFlLENBQ2pCLElBQUksa0JBQWtCLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FDN0QsQ0FBQztnQkFDSixDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRXpCLE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBQztRQUMzQixDQUFDO1FBRUQsb0VBQW9FO1FBQ3BFLHNFQUFzRTtRQUN0RSxrRUFBa0U7UUFDbEUsa0VBQWtFO1FBQ2xFLG1EQUFtRDtRQUNuRCxTQUFTLHdCQUF3QjtZQUMvQixNQUFNLFNBQVMsR0FBRyxhQUFhLEVBQXVCLENBQUM7WUFFdkQsSUFBSSxVQUFVLEVBQUUsQ0FBQztnQkFDZixHQUFHLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtvQkFDNUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDMUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsT0FBTyxTQUFTLENBQUMsT0FBTyxDQUFDO1lBQzNCLENBQUM7WUFFRCxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixHQUFHLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtvQkFDNUMsSUFBSSxjQUFjLEVBQUUsQ0FBQzt3QkFDbkIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztvQkFDcEMsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLFNBQVMsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztvQkFDckMsQ0FBQztnQkFDSCxDQUFDLENBQUMsQ0FBQztnQkFDSCxPQUFPLFNBQVMsQ0FBQyxPQUFPLENBQUM7WUFDM0IsQ0FBQztZQUVELE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDMUQsSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDM0MsU0FBUyxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztZQUN0QyxDQUFDO1lBRUQsSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDbEIsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRTtvQkFDekIsR0FBRyxDQUFDLGVBQWUsQ0FDakIsSUFBSSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUM3RCxDQUFDO2dCQUNKLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELG1CQUFtQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNwQyxPQUFPLFNBQVMsQ0FBQyxPQUFPLENBQUM7UUFDM0IsQ0FBQztRQUVELHNDQUFzQztRQUN0QyxTQUFTLFdBQVc7WUFDbEIsSUFBSSxVQUFVLEVBQUUsQ0FBQztnQkFDZixPQUFPLENBQUMsa0NBQWtDO1lBQzVDLENBQUM7WUFDRCxVQUFVLEdBQUcsSUFBSSxDQUFDO1lBRWxCLDRFQUE0RTtZQUM1RSxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3JCLE9BQU87WUFDVCxDQUFDO1lBRUQsK0NBQStDO1lBQy9DLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDMUQsSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDM0MsU0FBUyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDNUIsQ0FBQztZQUVELDREQUE0RDtZQUM1RCx5RUFBeUU7WUFDekUsc0VBQXNFO1lBQ3RFLHNEQUFzRDtZQUN0RCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO2dCQUNwQixnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO29CQUN6QixHQUFHLENBQUMsZUFBZSxDQUNqQixJQUFJLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLENBQzdELENBQUM7Z0JBQ0osQ0FBQyxDQUFDLENBQUM7WUFDTCxDQUFDO1lBRUQsYUFBYSxDQUFDLEtBQUssQ0FBQyxlQUFlLEVBQUUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNqRSxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQVk7WUFDcEIsS0FBSztZQUVMLFdBQVc7Z0JBQ1QsT0FBTyx3QkFBd0IsRUFBRSxDQUFDO1lBQ3BDLENBQUM7WUFFRCxzRUFBc0U7WUFDdEUsSUFBSSxDQUNGLFdBQXFFLEVBQ3JFLFVBQXVFO2dCQUV2RSxPQUFPLGlCQUFpQixFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBRUQsMkRBQTJEO1lBQzNELEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztnQkFDM0IsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUNuQixNQUFNLE1BQU0sSUFBSSxDQUFDO2dCQUNuQixDQUFDO1lBQ0gsQ0FBQztZQUVELE9BQU8sRUFBRSxXQUFXO1lBRXBCLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFdBQVc7U0FDOUIsQ0FBQztRQUVGLHFFQUFxRTtRQUNyRSxvRUFBb0U7UUFDcEUsaUNBQWlDO1FBQ2pDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUNoRCxJQUFJLFNBQVMsSUFBSSxTQUFTLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzdDLElBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxXQUFXLENBQUM7UUFDekMsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEZhdGFsRXJyb3IsXG4gIEhvb2tDb25mbGljdEVycm9yLFxuICBSZXBsYXlEaXZlcmdlbmNlRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgV09SS0ZMT1dfREVTRVJJQUxJWkUgfSBmcm9tICdAd29ya2Zsb3cvc2VyZGUnO1xuaW1wb3J0IHtcbiAgdHlwZSBQcm9taXNlV2l0aFJlc29sdmVycyxcbiAgcGFyc2VEdXJhdGlvblRvRGF0ZSxcbiAgd2l0aFJlc29sdmVycyxcbn0gZnJvbSAnQHdvcmtmbG93L3V0aWxzJztcbmltcG9ydCB0eXBlIHsgSG9va0NvbmZsaWN0RXZlbnQgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgZ2V0U2VyaWFsaXphdGlvbkNsYXNzLCBSVU5fQ0xBU1NfSUQgfSBmcm9tICcuLi9jbGFzcy1zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB0eXBlIHsgSG9vaywgSG9va09wdGlvbnMgfSBmcm9tICcuLi9jcmVhdGUtaG9vay5qcyc7XG5pbXBvcnQgeyBFdmVudENvbnN1bWVyUmVzdWx0IH0gZnJvbSAnLi4vZXZlbnRzLWNvbnN1bWVyLmpzJztcbmltcG9ydCB7IFdvcmtmbG93U3VzcGVuc2lvbiB9IGZyb20gJy4uL2dsb2JhbC5qcyc7XG5pbXBvcnQgeyB3ZWJob29rTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7XG4gIGF3YWl0RWFybGllckRlbGl2ZXJpZXMsXG4gIHJlZ2lzdGVyRGVsaXZlcnlCYXJyaWVyLFxuICBzY2hlZHVsZVdoZW5JZGxlLFxuICB0eXBlIFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbn0gZnJvbSAnLi4vcHJpdmF0ZS5qcyc7XG5pbXBvcnQgdHlwZSB7IFJ1biB9IGZyb20gJy4uL3J1bnRpbWUvcnVuLmpzJztcbmltcG9ydCB7IGh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUgfSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgYFJ1bmAgaGFuZGxlIGZvciB0aGUgcnVuIHRoYXQgb3ducyBhIGNvbmZsaWN0aW5nIGhvb2tcbiAqIHRva2VuLCBmb3IgcmVzb2x1dGlvbiB0aHJvdWdoIGBob29rLmdldENvbmZsaWN0KClgLlxuICpcbiAqIFRoZSBpbnN0YW5jZSBpcyBjcmVhdGVkIHRocm91Z2ggdGhlIHNlcmlhbGl6YXRpb24gY2xhc3MgcmVnaXN0cnkgb25cbiAqIHRoZSBWTSdzIGdsb2JhbFRoaXMg4oCUIHRoZSBzYW1lIGNoYW5uZWwgdGhhdCByZXZpdmVzIHNlcmlhbGl6ZWQgYFJ1bmBcbiAqIGluc3RhbmNlcyAoZS5nLiBgc3RhcnQoKWAgcmV0dXJuIHZhbHVlcyBjcm9zc2luZyBmcm9tIGEgc3RlcCBpbnRvIHRoZVxuICogd29ya2Zsb3cpLiBUaGUgcmVnaXN0ZXJlZCBjbGFzcyBpcyB0aGUgVk0gYnVuZGxlJ3MgcGx1Z2luLWNvbXBpbGVkXG4gKiBgUnVuYCwgd2hvc2UgbWV0aG9kcyBhcmUgZHVyYWJsZSBzdGVwIHByb3hpZXMg4oCUIHNhZmUgdG8gY2FsbCBmcm9tXG4gKiB3b3JrZmxvdyBjb2RlIOKAlCBhbmQgY29uc3RydWN0aW9uIGdvZXMgdGhyb3VnaCBpdHNcbiAqIGBXT1JLRkxPV19ERVNFUklBTElaRWAgaG9vaywgZXhhY3RseSBhcyB0aGUgYEluc3RhbmNlYCByZXZpdmVyIHdvdWxkLlxuICpcbiAqIFJldHVybnMgYG51bGxgIHdoZW4gYSByZWFsIGBSdW5gIGNhbm5vdCBiZSBjb25zdHJ1Y3RlZDogdGhlIGNvbmZsaWN0XG4gKiBldmVudCBsYWNrcyBgY29uZmxpY3RpbmdSdW5JZGAgKHdyaXR0ZW4gYnkgYW4gb2xkIHdvcmxkKSwgb3IgdGhlIFZNJ3NcbiAqIHJlZ2lzdHJ5IGhhcyBubyBgUnVuYCAoYSBjb250ZXh0IHRoYXQgbmV2ZXIgZXZhbHVhdGVkIHRoZVxuICogd29ya2Zsb3ctbW9kZSBgY3JlYXRlLWhvb2tgIG1vZHVsZSwgd2hpY2ggYWxpYXNlcyBpdCB1bmRlclxuICogYFJVTl9DTEFTU19JRGApLiBgZ2V0Q29uZmxpY3RgIGF3YWl0ZXJzIHRoZW4gcmVqZWN0IHdpdGhcbiAqIGBIb29rQ29uZmxpY3RFcnJvcmAgaW5zdGVhZCBvZiByZXNvbHZpbmcgd2l0aCBhIHZhbHVlIHRoYXQgZG9lc24ndFxuICogaG9ub3IgdGhlIGBSdW5gIGNvbnRyYWN0LlxuICovXG5mdW5jdGlvbiBjcmVhdGVDb25mbGljdGluZ1J1bihcbiAgY3R4OiBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQsXG4gIGNvbmZsaWN0aW5nUnVuSWQ6IHN0cmluZyB8IHVuZGVmaW5lZFxuKTogUnVuPHVua25vd24+IHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgY29uZmxpY3RpbmdSdW5JZCAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCBSdW5DbGFzcyA9IGdldFNlcmlhbGl6YXRpb25DbGFzcyhSVU5fQ0xBU1NfSUQsIGN0eC5nbG9iYWxUaGlzKSBhc1xuICAgIHwgKGFic3RyYWN0IG5ldyAoXG4gICAgICAgIC4uLmFyZ3M6IG5ldmVyXG4gICAgICApID0+IFJ1bjx1bmtub3duPilcbiAgICB8IHVuZGVmaW5lZDtcbiAgY29uc3QgZGVzZXJpYWxpemUgPSAoUnVuQ2xhc3MgYXMgYW55KT8uW1dPUktGTE9XX0RFU0VSSUFMSVpFXTtcbiAgaWYgKHR5cGVvZiBkZXNlcmlhbGl6ZSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiBkZXNlcmlhbGl6ZS5jYWxsKFJ1bkNsYXNzLCB7IHJ1bklkOiBjb25mbGljdGluZ1J1bklkIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3JlYXRlSG9vayhjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCkge1xuICByZXR1cm4gZnVuY3Rpb24gY3JlYXRlSG9va0ltcGw8VCA9IGFueT4ob3B0aW9uczogSG9va09wdGlvbnMgPSB7fSk6IEhvb2s8VD4ge1xuICAgIC8vIFJlamVjdCBhbiBleHBsaWNpdCBlbXB0eS1zdHJpbmcgdG9rZW4uIEEgdG9rZW4gbXVzdCBlaXRoZXIgYmUgb21pdHRlZFxuICAgIC8vIChvciBgdW5kZWZpbmVkYC9gbnVsbGApIHRvIGdldCBhIHJhbmRvbWx5IGdlbmVyYXRlZCBvbmUsIG9yIGJlIGFuXG4gICAgLy8gZXhwbGljaXQgbm9uLWVtcHR5IHN0cmluZy4gQW4gZW1wdHkgc3RyaW5nIGlzIGFsbW9zdCBhbHdheXMgYW5cbiAgICAvLyBhY2NpZGVudGFsIHZhbHVlIChlLmcuIGFuIHVuc2V0IHZhcmlhYmxlKSBhbmQgd291bGQgb3RoZXJ3aXNlIHNsaXBcbiAgICAvLyB0aHJvdWdoIHRoZSBgPz9gIGJlbG93IOKAlCB3aGljaCBvbmx5IGZhbGxzIGJhY2sgZm9yIG51bGxpc2ggdmFsdWVzIOKAlCBhbmRcbiAgICAvLyBiZSB1c2VkIGFzIGEgbWVhbmluZ2xlc3MsIG5vbi1kZXRlcm1pbmlzdGljIHRva2VuLlxuICAgIGlmIChvcHRpb25zLnRva2VuID09PSAnJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnYGNyZWF0ZUhvb2soKWAgd2FzIGNhbGxlZCB3aXRoIGFuIGVtcHR5IHN0cmluZyB0b2tlbi4gUGFzcyBhIG5vbi1lbXB0eSB0b2tlbiwgb3Igb21pdCB0aGUgYHRva2VuYCBvcHRpb24gdG8gdXNlIGEgcmFuZG9tbHkgZ2VuZXJhdGVkIG9uZS4nXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIG9wdGlvbnMuaXNXZWJob29rID09PSB0cnVlICYmXG4gICAgICBvcHRpb25zLmV4cGVyaW1lbnRhbF9taW5SZXRlbnRpb24gIT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnV2ViaG9vayBob29rcyBkbyBub3Qgc3VwcG9ydCBgZXhwZXJpbWVudGFsX21pblJldGVudGlvbmAuIFVzZSBhIG5vbi13ZWJob29rIGBjcmVhdGVIb29rKClgIHdpdGggYHJlc3VtZUhvb2soKWAuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBvcHRpb25zLmV4cGVyaW1lbnRhbF9taW5SZXRlbnRpb24gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgY3R4LndvcmxkQ2FwYWJpbGl0aWVzPy5ob29rUmV0ZW50aW9uPy5hY3RpdmUgIT09IHRydWVcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICAnVGhlIGNvbmZpZ3VyZWQgV29ybGQgZG9lcyBub3Qgc3VwcG9ydCBgZXhwZXJpbWVudGFsX21pblJldGVudGlvbmAgZm9yIEhvb2tzLidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gR2VuZXJhdGUgaG9vayBJRCBhbmQgdG9rZW5cbiAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gYGhvb2tfJHtjdHguZ2VuZXJhdGVDb3JyZWxhdGlvbklkKCdob29rJyl9YDtcbiAgICBjb25zdCB0b2tlbiA9IG9wdGlvbnMudG9rZW4gPz8gY3R4LmdlbmVyYXRlTmFub2lkKCk7XG4gICAgY29uc3QgdG9rZW5SZXRlbnRpb25VbnRpbCA9XG4gICAgICBvcHRpb25zLmV4cGVyaW1lbnRhbF9taW5SZXRlbnRpb24gPT09IHVuZGVmaW5lZFxuICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICA6IHBhcnNlRHVyYXRpb25Ub0RhdGUob3B0aW9ucy5leHBlcmltZW50YWxfbWluUmV0ZW50aW9uKTtcblxuICAgIC8vIEFkZCBob29rIGNyZWF0aW9uIHRvIGludm9jYXRpb25zIHF1ZXVlICh1c2luZyBNYXAgZm9yIE8oMSkgb3BlcmF0aW9ucylcbiAgICBjb25zdCBpc1dlYmhvb2sgPSBvcHRpb25zLmlzV2ViaG9vayA/PyBmYWxzZTtcblxuICAgIGN0eC5pbnZvY2F0aW9uc1F1ZXVlLnNldChjb3JyZWxhdGlvbklkLCB7XG4gICAgICB0eXBlOiAnaG9vaycsXG4gICAgICBjb3JyZWxhdGlvbklkLFxuICAgICAgdG9rZW4sXG4gICAgICB0b2tlblJldGVudGlvblVudGlsLFxuICAgICAgbWV0YWRhdGE6IG9wdGlvbnMubWV0YWRhdGEsXG4gICAgICBpc1dlYmhvb2ssXG4gICAgfSk7XG5cbiAgICAvLyBRdWV1ZSBvZiBidWZmZXJlZCBob29rIHBheWxvYWRzIChyZWNlaXZlZCBiZWZvcmUgdGhlIHdvcmtmbG93IGF3YWl0ZWRcbiAgICAvLyB0aGUgaG9vaykuIEVhY2ggZW50cnkncyBgY2xhaW0oKWAgYnVpbGRzIHRoZSBjb25zdW1lci1mYWNpbmcgcHJvbWlzZVxuICAgIC8vIGZyb20gdGhlIGNhcHR1cmVkIGh5ZHJhdGlvbiBvdXRjb21lIGFuZCBvcmRlcnMgaXQgZGV0ZXJtaW5pc3RpY2FsbHkgYnlcbiAgICAvLyBldmVudC1sb2cgcG9zaXRpb24gYWdhaW5zdCBhbnkgY29uY3VycmVudCBicmFuY2gtZGVjaWRpbmcgcmVzb2x1dGlvblxuICAgIC8vIChzZWUgYGN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVyc2ApLlxuICAgIGNvbnN0IHBheWxvYWRzUXVldWU6IHsgY2xhaW06ICgpID0+IFByb21pc2U8VD4gfVtdID0gW107XG5cbiAgICAvLyBRdWV1ZSBvZiBwcm9taXNlcyB0aGF0IHJlc29sdmUgdG8gdGhlIG5leHQgaG9vayBwYXlsb2FkXG4gICAgY29uc3QgcHJvbWlzZXM6IFByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+W10gPSBbXTtcblxuICAgIC8vIFF1ZXVlIG9mIHByb21pc2VzIHRoYXQgcmVzb2x2ZSBvbmNlIGhvb2sgcmVnaXN0cmF0aW9uIGlzIGNvbmZpcm1lZFxuICAgIC8vICh3aXRoIGBudWxsYCkgb3IgYSB0b2tlbiBjb25mbGljdCBpcyBkZXRlY3RlZCAod2l0aCB0aGUgY29uZmxpY3RpbmdcbiAgICAvLyBgUnVuYCkuIFRoZXNlIGJhY2sgdGhlIGBob29rLmdldENvbmZsaWN0KClgIGdldHRlci5cbiAgICBjb25zdCBnZXRDb25mbGljdFByb21pc2VzOiBQcm9taXNlV2l0aFJlc29sdmVyczxSdW48dW5rbm93bj4gfCBudWxsPltdID0gW107XG5cbiAgICBsZXQgZXZlbnRMb2dFbXB0eSA9IGZhbHNlO1xuXG4gICAgLy8gVHJhY2sgaWYgdGhlIGV2ZW50IGxvZyBjb25maXJtcyBob29rIGNyZWF0aW9uIGhhcHBlbmVkXG4gICAgbGV0IGhhc0NyZWF0ZWQgPSBmYWxzZTtcblxuICAgIC8vIFRyYWNrIGlmIHRoZSBldmVudCBsb2cgY29uZmlybXMgZGlzcG9zYWwgaGFwcGVuZWQgKHJlcGxheSBuby1vcClcbiAgICBsZXQgaGFzRGlzcG9zZWRFdmVudCA9IGZhbHNlO1xuXG4gICAgLy8gVHJhY2sgaWYgd2UgaGF2ZSBhIGNvbmZsaWN0IHNvIHdlIGNhbiByZWplY3QgZnV0dXJlIGF3YWl0c1xuICAgIGxldCBoYXNDb25mbGljdCA9IGZhbHNlO1xuICAgIGxldCBjb25mbGljdEVycm9yUmVmOiBIb29rQ29uZmxpY3RFcnJvciB8IG51bGwgPSBudWxsO1xuICAgIC8vIFRoZSBjb25mbGljdGluZyBydW4gaGFuZGxlLCBzaGFyZWQgYnkgZXZlcnkgYGdldENvbmZsaWN0YCBhd2FpdCBzb1xuICAgIC8vIHJlcGVhdGVkIGF3YWl0cyBvYnNlcnZlIHRoZSBzYW1lIGluc3RhbmNlIGRldGVybWluaXN0aWNhbGx5LlxuICAgIGxldCBjb25mbGljdFJ1blJlZjogUnVuPHVua25vd24+IHwgbnVsbCA9IG51bGw7XG5cbiAgICAvLyBMYXp5LXJlc3VtZSBkZWR1cDogYHJlc3VtZUhvb2soKWAgbWludHMgYSBgcmVzdW1lSWRgIHBlciByZXN1bWVcbiAgICAvLyBhdHRlbXB0IGFuZCBzdGFtcHMgaXQgb24gdGhlIGBob29rX3JlY2VpdmVkYCBldmVudC4gV2hlbiB0aGUgZGlyZWN0XG4gICAgLy8gZXZlbnQgd3JpdGUgZmFpbHMgdHJhbnNpZW50bHksIHRoZSBydW50aW1lIG1hdGVyaWFsaXplcyB0aGUgZXZlbnQgZnJvbVxuICAgIC8vIHRoZSBxdWV1ZSBwYXlsb2FkIGluc3RlYWQg4oCUIGFuZCBiZWNhdXNlIGBob29rX3JlY2VpdmVkYCBoYXMgbm9cbiAgICAvLyBzdG9yYWdlLWxldmVsIHVuaXF1ZW5lc3MgY29uc3RyYWludCwgY29uY3VycmVudCByZWRlbGl2ZXJ5IG9mIHRoZSBzYW1lXG4gICAgLy8gcXVldWUgbWVzc2FnZSBjYW4gY29tbWl0IHRoYXQgbWF0ZXJpYWxpemF0aW9uIHR3aWNlLiBUd28gcm93cyBmb3IgT05FXG4gICAgLy8gcmVzdW1lIGF0dGVtcHQgdGhlbiBzaGFyZSBhIGByZXN1bWVJZGAgKGRpc3RpbmN0IHJlc3VtZSBhdHRlbXB0cyBuZXZlclxuICAgIC8vIGRvKSwgc28gcmVwbGF5IGRlbGl2ZXJzIG9ubHkgdGhlIGZpcnN0LWluLWxvZyBvY2N1cnJlbmNlLiBUaGlzIGlzIGFcbiAgICAvLyBwdXJlIGZ1bmN0aW9uIG9mIHRoZSBwZXJzaXN0ZWQgZXZlbnQgbG9nLCBrZWVwaW5nIHJlcGxheSBkZXRlcm1pbmlzdGljLlxuICAgIC8vXG4gICAgLy8gU2NvcGU6IHRoaXMgaXMgZGVmZW5zZS1pbi1kZXB0aCBvdmVyIHRoZSBwZXJzaXN0ZWQgbG9nLCBub3QgYVxuICAgIC8vIGNyb3NzLWludm9jYXRpb24gZXhhY3RseS1vbmNlIGd1YXJhbnRlZSDigJQgYW4gaW52b2NhdGlvbiByZXBsYXlpbmcgYVxuICAgIC8vIHNuYXBzaG90IHRha2VuIGJlZm9yZSB0aGUgZHVwbGljYXRlIHJvdyBjb21taXR0ZWQgb25seSBzZWVzIG9uZSByb3csXG4gICAgLy8gc28gdHdvIENPTkNVUlJFTlQgaW52b2NhdGlvbnMgY2FuIGVhY2ggZGVsaXZlciBmcm9tIHRoZWlyIG93blxuICAgIC8vIHNuYXBzaG90LiBFdmVyeSByZXBsYXkgZnJvbSBhIGxvZyBjb250YWluaW5nIGJvdGggcm93cyAoaS5lLiBhbGxcbiAgICAvLyBzdWJzZXF1ZW50IGRlbGl2ZXJpZXMpIGRlZHVwcy4gVGhlIGNvcnJlY3RuZXNzIGJvdW5kYXJ5IHRoYXQgY2xvc2VzXG4gICAgLy8gdGhlIGNvbmN1cnJlbnQgd2luZG93IGlzIHRoZSBzdG9yYWdlLWxldmVsIChydW5JZCwgcmVzdW1lSWQpXG4gICAgLy8gY29uc3RyYWludCBhcnJpdmluZyB3aXRoIHRoZSBwYXJhbGxlbC1yZXN1bWUgc3VjY2Vzc29yIHdvcms7IHRoaXMgc2V0XG4gICAgLy8gc3RheXMgdXNlZnVsIGFmdGVyIHRoYXQgbGFuZHMsIGZvciBsb2dzIHdyaXR0ZW4gYmVmb3JlIGl0IGRlcGxveWVkLlxuICAgIGNvbnN0IHNlZW5SZXN1bWVJZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAgIHdlYmhvb2tMb2dnZXIuZGVidWcoJ0hvb2sgY29uc3VtZXIgc2V0dXAnLCB7IGNvcnJlbGF0aW9uSWQsIHRva2VuIH0pO1xuICAgIGN0eC5ldmVudHNDb25zdW1lci5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gZXZlbnRzIGFuZCB0aGVyZSBhcmUgcHJvbWlzZXMgd2FpdGluZyxcbiAgICAgIC8vIGl0IG1lYW5zIHRoZSBob29rIGhhcyBiZWVuIGF3YWl0ZWQsIGJ1dCBhbiBpbmNvbWluZyBwYXlsb2FkIGhhcyBub3QgeWV0IGJlZW4gcmVjZWl2ZWQuXG4gICAgICAvLyBJbiB0aGlzIGNhc2UsIHRoZSB3b3JrZmxvdyBzaG91bGQgYmUgc3VzcGVuZGVkIHVudGlsIHRoZSBob29rIGlzIHJlc3VtZWQuXG4gICAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgIGV2ZW50TG9nRW1wdHkgPSB0cnVlO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAocHJvbWlzZXMubGVuZ3RoID4gMCAmJiBwYXlsb2Fkc1F1ZXVlLmxlbmd0aCA9PT0gMCkgfHxcbiAgICAgICAgICAoZ2V0Q29uZmxpY3RQcm9taXNlcy5sZW5ndGggPiAwICYmICFoYXNDcmVhdGVkICYmICFoYXNDb25mbGljdClcbiAgICAgICAgKSB7XG4gICAgICAgICAgc2NoZWR1bGVXaGVuSWRsZShjdHgsICgpID0+IHtcbiAgICAgICAgICAgIGN0eC5vbldvcmtmbG93RXJyb3IoXG4gICAgICAgICAgICAgIG5ldyBXb3JrZmxvd1N1c3BlbnNpb24oY3R4Lmludm9jYXRpb25zUXVldWUsIGN0eC5nbG9iYWxUaGlzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Ob3RDb25zdW1lZDtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50LmNvcnJlbGF0aW9uSWQgIT09IGNvcnJlbGF0aW9uSWQpIHtcbiAgICAgICAgLy8gV2UncmUgbm90IGludGVyZXN0ZWQgaW4gdGhpcyBldmVudCAtIHRoZSBjb3JyZWxhdGlvbklkIGJlbG9uZ3MgdG8gYSBkaWZmZXJlbnQgZW50aXR5XG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0Lk5vdENvbnN1bWVkO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBldmVudFRva2VuID1cbiAgICAgICAgJ2V2ZW50RGF0YScgaW4gZXZlbnQgJiYgZXZlbnQuZXZlbnREYXRhICYmICd0b2tlbicgaW4gZXZlbnQuZXZlbnREYXRhXG4gICAgICAgICAgPyBldmVudC5ldmVudERhdGEudG9rZW5cbiAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgaWYgKHR5cGVvZiBldmVudFRva2VuID09PSAnc3RyaW5nJyAmJiBldmVudFRva2VuICE9PSB0b2tlbikge1xuICAgICAgICBjdHgucHJvbWlzZVF1ZXVlID0gY3R4LnByb21pc2VRdWV1ZS50aGVuKCgpID0+IHtcbiAgICAgICAgICBjdHgub25Xb3JrZmxvd0Vycm9yKFxuICAgICAgICAgICAgbmV3IFJlcGxheURpdmVyZ2VuY2VFcnJvcihcbiAgICAgICAgICAgICAgYFJlcGxheSBkaXZlcmdlbmNlOiBob29rIGV2ZW50ICR7ZXZlbnQuZXZlbnRUeXBlfSBmb3IgJHtjb3JyZWxhdGlvbklkfSBiZWxvbmdzIHRvIHRva2VuIFwiJHtldmVudFRva2VufVwiLCBidXQgdGhlIGN1cnJlbnQgaG9vayBjb25zdW1lciBleHBlY3RzIFwiJHt0b2tlbn1cImAsXG4gICAgICAgICAgICAgIHsgZXZlbnRJZDogZXZlbnQuZXZlbnRJZCB9XG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBmb3IgaG9va19jcmVhdGVkIGV2ZW50IHRvIG1hcmsgdGhpcyBob29rIGFzIGFscmVhZHkgY3JlYXRlZFxuICAgICAgaWYgKGV2ZW50LmV2ZW50VHlwZSA9PT0gJ2hvb2tfY3JlYXRlZCcpIHtcbiAgICAgICAgY29uc3QgcXVldWVJdGVtID0gY3R4Lmludm9jYXRpb25zUXVldWUuZ2V0KGNvcnJlbGF0aW9uSWQpO1xuICAgICAgICBpZiAocXVldWVJdGVtICYmIHF1ZXVlSXRlbS50eXBlID09PSAnaG9vaycpIHtcbiAgICAgICAgICBxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgICBxdWV1ZUl0ZW0udG9rZW5SZXRlbnRpb25VbnRpbCA9IGV2ZW50LmV2ZW50RGF0YS50b2tlblJldGVudGlvblVudGlsO1xuICAgICAgICB9XG4gICAgICAgIGhhc0NyZWF0ZWQgPSB0cnVlO1xuXG4gICAgICAgIGNvbnN0IHBlbmRpbmdHZXRDb25mbGljdFByb21pc2VzID0gZ2V0Q29uZmxpY3RQcm9taXNlcy5zbGljZSgpO1xuICAgICAgICBnZXRDb25mbGljdFByb21pc2VzLmxlbmd0aCA9IDA7XG4gICAgICAgIGN0eC5wcm9taXNlUXVldWUgPSBjdHgucHJvbWlzZVF1ZXVlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGZvciAoY29uc3QgcmVzb2x2ZXIgb2YgcGVuZGluZ0dldENvbmZsaWN0UHJvbWlzZXMpIHtcbiAgICAgICAgICAgIHJlc29sdmVyLnJlc29sdmUobnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZDtcbiAgICAgIH1cblxuICAgICAgLy8gSGFuZGxlIGhvb2tfY29uZmxpY3QgZXZlbnQgLSBhbm90aGVyIHdvcmtmbG93IGlzIHVzaW5nIHRoaXMgdG9rZW5cbiAgICAgIGlmIChldmVudC5ldmVudFR5cGUgPT09ICdob29rX2NvbmZsaWN0Jykge1xuICAgICAgICAvLyBSZW1vdmUgdGhpcyBob29rIGZyb20gdGhlIGludm9jYXRpb25zIHF1ZXVlXG4gICAgICAgIGN0eC5pbnZvY2F0aW9uc1F1ZXVlLmRlbGV0ZShjb3JyZWxhdGlvbklkKTtcblxuICAgICAgICAvLyBTdG9yZSB0aGUgY29uZmxpY3QgZXZlbnQgc28gd2UgY2FuIHJlamVjdCBhbnkgYXdhaXRlZCBwcm9taXNlcy5cbiAgICAgICAgLy8gQ2hhaW4gdGhyb3VnaCBwcm9taXNlUXVldWUgdG8gZW5zdXJlIGRldGVybWluaXN0aWMgb3JkZXJpbmcuXG4gICAgICAgIGNvbnN0IGNvbmZsaWN0RXZlbnQgPSBldmVudCBhcyBIb29rQ29uZmxpY3RFdmVudDtcbiAgICAgICAgY29uc3QgY29uZmxpY3RFcnJvciA9IG5ldyBIb29rQ29uZmxpY3RFcnJvcihcbiAgICAgICAgICBjb25mbGljdEV2ZW50LmV2ZW50RGF0YS50b2tlbixcbiAgICAgICAgICBjb25mbGljdEV2ZW50LmV2ZW50RGF0YS5jb25mbGljdGluZ1J1bklkXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gTWFyayB0aGF0IHdlIGhhdmUgYSBjb25mbGljdCBzbyBmdXR1cmUgYXdhaXRzIGFsc28gcmVqZWN0XG4gICAgICAgIGhhc0NvbmZsaWN0ID0gdHJ1ZTtcbiAgICAgICAgY29uZmxpY3RFcnJvclJlZiA9IGNvbmZsaWN0RXJyb3I7XG4gICAgICAgIGNvbmZsaWN0UnVuUmVmID0gY3JlYXRlQ29uZmxpY3RpbmdSdW4oXG4gICAgICAgICAgY3R4LFxuICAgICAgICAgIGNvbmZsaWN0RXZlbnQuZXZlbnREYXRhLmNvbmZsaWN0aW5nUnVuSWRcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBDYXB0dXJlIGFuZCBkcmFpbiBwZW5kaW5nIHByb21pc2VzIHN5bmNocm9ub3VzbHkgc28gdGhlIG51bGwgZXZlbnRcbiAgICAgICAgLy8gaGFuZGxlciB3b24ndCBzZWUgdGhlbSBhbmQgdHJpZ2dlciBhIHNwdXJpb3VzIFdvcmtmbG93U3VzcGVuc2lvbi5cbiAgICAgICAgLy8gVGhlIGFjdHVhbCBzZXR0bGVtZW50cyBhcmUgZGVmZXJyZWQgdGhyb3VnaCBwcm9taXNlUXVldWUgZm9yXG4gICAgICAgIC8vIG9yZGVyaW5nLiBQYXlsb2FkIGF3YWl0ZXJzIHJlamVjdCB3aXRoIEhvb2tDb25mbGljdEVycm9yLCB3aGlsZVxuICAgICAgICAvLyBgZ2V0Q29uZmxpY3RgIGF3YWl0ZXJzIHJlc29sdmUgd2l0aCB0aGUgY29uZmxpY3RpbmcgcnVuIHNvIHRoZVxuICAgICAgICAvLyB3b3JrZmxvdyBjYW4gYnJhbmNoIG9uIHRoZSBjb25mbGljdCB3aXRob3V0IHRocm93aW5nLiBXaGVuIG5vXG4gICAgICAgIC8vIHJlYWwgYFJ1bmAgY2FuIGJlIGNvbnN0cnVjdGVkIChzZWUgYGNyZWF0ZUNvbmZsaWN0aW5nUnVuYCksXG4gICAgICAgIC8vIGBnZXRDb25mbGljdGAgYXdhaXRlcnMgcmVqZWN0IHdpdGggdGhlIEhvb2tDb25mbGljdEVycm9yIGluc3RlYWRcbiAgICAgICAgLy8gb2YgcmVzb2x2aW5nIHdpdGggYSB2YWx1ZSB0aGF0IGRvZXNuJ3QgaG9ub3IgdGhlIGBSdW5gIGNvbnRyYWN0LlxuICAgICAgICBjb25zdCBwZW5kaW5nUHJvbWlzZXMgPSBwcm9taXNlcy5zbGljZSgpO1xuICAgICAgICBwcm9taXNlcy5sZW5ndGggPSAwO1xuICAgICAgICBjb25zdCBwZW5kaW5nR2V0Q29uZmxpY3RQcm9taXNlcyA9IGdldENvbmZsaWN0UHJvbWlzZXMuc2xpY2UoKTtcbiAgICAgICAgZ2V0Q29uZmxpY3RQcm9taXNlcy5sZW5ndGggPSAwO1xuXG4gICAgICAgIGN0eC5wcm9taXNlUXVldWUgPSBjdHgucHJvbWlzZVF1ZXVlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGZvciAoY29uc3QgcmVzb2x2ZXIgb2YgcGVuZGluZ1Byb21pc2VzKSB7XG4gICAgICAgICAgICByZXNvbHZlci5yZWplY3QoY29uZmxpY3RFcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGZvciAoY29uc3QgcmVzb2x2ZXIgb2YgcGVuZGluZ0dldENvbmZsaWN0UHJvbWlzZXMpIHtcbiAgICAgICAgICAgIGlmIChjb25mbGljdFJ1blJlZikge1xuICAgICAgICAgICAgICByZXNvbHZlci5yZXNvbHZlKGNvbmZsaWN0UnVuUmVmKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlc29sdmVyLnJlamVjdChjb25mbGljdEVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0LkNvbnN1bWVkO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQuZXZlbnRUeXBlID09PSAnaG9va19yZWNlaXZlZCcpIHtcbiAgICAgICAgLy8gRHJvcCBkdXBsaWNhdGUgZGVsaXZlcmllcyBvZiB0aGUgc2FtZSByZXN1bWUgYXR0ZW1wdCAoc2FtZVxuICAgICAgICAvLyBgcmVzdW1lSWRgIOKAlCBzZWUgYHNlZW5SZXN1bWVJZHNgIGFib3ZlKS4gRXZlbnRzIHdpdGhvdXQgYVxuICAgICAgICAvLyBgcmVzdW1lSWRgIChvbGRlciBTREtzLCBsZWdhY3kgc3BlYyB2ZXJzaW9ucykgYXJlIG5ldmVyIGRlZHVwZWQuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIERlZHVwIG9mZiB0aGUgdG9wLWxldmVsIGByZXN1bWVJZGAgdGhlIGJhY2tlbmQgaG9pc3RzIG9udG8gdGhlIGV2ZW50XG4gICAgICAgIC8vIGFzIGEgZmlyc3QtY2xhc3MgY29sdW1uLiBBbiBlYXJsaWVyIHVucmVsZWFzZWQgYnVpbGQgYWRkaXRpb25hbGx5XG4gICAgICAgIC8vIHdyb3RlIGl0IG5lc3RlZCB1bmRlciBgZXZlbnREYXRhYCwgYnV0IHRoYXQgZm9ybSBuZXZlciBzaGlwcGVkIGFuZCBpc1xuICAgICAgICAvLyBzdHJpcHBlZCBieSBgRXZlbnRTY2hlbWFgIHBhcnNpbmcgKHRoZSBgaG9va19yZWNlaXZlZGAgZXZlbnREYXRhXG4gICAgICAgIC8vIHNjaGVtYSBkb2VzIG5vdCBkZWNsYXJlIGl0KSwgc28gdGhlcmUgaXMgbm8gcGVyc2lzdGVkIG5lc3RlZCBmb3JtIHRvXG4gICAgICAgIC8vIGZhbGwgYmFjayB0by5cbiAgICAgICAgY29uc3QgcmVzdW1lSWQgPSBldmVudC5yZXN1bWVJZDtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bWVJZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAoc2VlblJlc3VtZUlkcy5oYXMocmVzdW1lSWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRDb25zdW1lclJlc3VsdC5Db25zdW1lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2VlblJlc3VtZUlkcy5hZGQocmVzdW1lSWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVnaXN0ZXIgYSAnaG9vaycgZGVsaXZlcnkgYmFycmllciBhdCB0aGlzIGV2ZW50J3MgbG9nIGluZGV4IHNvIGFcbiAgICAgICAgLy8gbGF0ZXItaW4tbG9nIGB3YWl0X2NvbXBsZXRlZGAgb3Igc3RlcCByZXN1bHQgaXMgZGVsaXZlcmVkIG9ubHkgYWZ0ZXJcbiAgICAgICAgLy8gdGhpcyBob29rLCBhbmQgc28gdGhpcyBob29rIGlzIGRlbGl2ZXJlZCBvbmx5IGFmdGVyIGV2ZXJ5XG4gICAgICAgIC8vIGVhcmxpZXItaW4tbG9nIGB3YWl0X2NvbXBsZXRlZGAgYW5kIHN0ZXAgcmVzdWx0IOKAlCBrZWVwaW5nIGFueVxuICAgICAgICAvLyBgUHJvbWlzZS5yYWNlYCAob3IgY29uY3VycmVudC1icmFuY2ggVUxJRCBhbGxvY2F0aW9uKSBkZXRlcm1pbmlzdGljXG4gICAgICAgIC8vIGFuZCBhbGlnbmVkIHdpdGggdGhlIGNvbW1pdHRlZCBldmVudCBsb2csIHJlZ2FyZGxlc3Mgb2ZcbiAgICAgICAgLy8gbWljcm90YXNrLWhvcCBjb3VudCwgaHlkcmF0aW9uIHRpbWUsIG9yIHJhY2UtYXJndW1lbnQgb3JkZXIuXG4gICAgICAgIC8vIFNlZSBgY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzYC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gVGhlIGJhcnJpZXIgaXMgcmVnaXN0ZXJlZCBBUk1FRCBvbmx5IHdoZW4gYSBjb25zdW1lciBpcyBhbHJlYWR5XG4gICAgICAgIC8vIGF3YWl0aW5nLCBzbyB0aGlzIHBheWxvYWQgaXMgY29tbWl0dGVkIHRvIHJlYWNoaW5nIHRoZSB3b3JrZmxvdy4gQVxuICAgICAgICAvLyBidWZmZXJlZCBwYXlsb2FkIGlzIHJlZ2lzdGVyZWQgdW5hcm1lZCBhbmQgYXJtZWQgYnkgYGNsYWltKClgOiB1bnRpbFxuICAgICAgICAvLyBhIGNvbnN1bWVyIHRha2VzIGl0LCBhIGxhdGVyIHN0ZXAgcmVzdWx0IG11c3Qgbm90IGJlIG9yZGVyZWQgYmVoaW5kXG4gICAgICAgIC8vIGl0IChzZWUgYGF3YWl0RWFybGllckRlbGl2ZXJpZXNgKS5cbiAgICAgICAgY29uc3QgZXZlbnRJbmRleCA9IGN0eC5ldmVudHNDb25zdW1lci5ldmVudEluZGV4O1xuICAgICAgICBjb25zdCBoYXNXYWl0aW5nQ29uc3VtZXIgPSBwcm9taXNlcy5sZW5ndGggPiAwO1xuICAgICAgICBjb25zdCBiYXJyaWVyID0gcmVnaXN0ZXJEZWxpdmVyeUJhcnJpZXIoY3R4LCBldmVudEluZGV4LCAnaG9vaycsIHtcbiAgICAgICAgICBhcm1lZDogaGFzV2FpdGluZ0NvbnN1bWVyLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoaGFzV2FpdGluZ0NvbnN1bWVyKSB7XG4gICAgICAgICAgLy8gQSBjb25zdW1lciBpcyBhbHJlYWR5IGF3YWl0aW5nLCBzbyB0aGlzIHBheWxvYWQncyBkZWxpdmVyeSBpc1xuICAgICAgICAgIC8vIHBpbm5lZCB0byB0aGlzIGxvZyBwb3NpdGlvbjogY2FwdHVyZSB0aGUgZGVmZXJyYWwgSEVSRSwgd2hpbGVcbiAgICAgICAgICAvLyBjb25zdW1pbmcgdGhlIGV2ZW50LCBub3QgYXQgdGhlIGVuZCBvZiB0aGUgaHlkcmF0aW9uIHNsb3QgYmVsb3cg4oCUXG4gICAgICAgICAgLy8gc2FtZSByZWFzb25pbmcgYXMgc3RlcC50cy4gQW4gZWFybGllciBzdGVwIG9yIGhvb2sgd2hvc2Ugc2xvdCBydW5zXG4gICAgICAgICAgLy8gZmlyc3Qgb24gdGhpcyBzZXJpYWwgcXVldWUgaGFzIHVzdWFsbHkgZGVsaXZlcmVkLCBhbmQgc29cbiAgICAgICAgICAvLyBkZXJlZ2lzdGVyZWQgaXRzIGJhcnJpZXIsIGJlZm9yZSB0aGlzIHNsb3QgZW5kcy4gUmVhZCB0aGVuLCBpdFxuICAgICAgICAgIC8vIHdvdWxkIGJlIGludmlzaWJsZSBhbmQgdGhpcyBwYXlsb2FkIHdvdWxkIHNraXAgYm90aCB0aGUgZ2F0ZSBBTkRcbiAgICAgICAgICAvLyBgYXdhaXRFYXJsaWVyRGVsaXZlcmllc2AnIG1hY3JvdGFzayB5aWVsZCwgbGV0dGluZyBpdCBvdmVydGFrZSB0aGVcbiAgICAgICAgICAvLyBicmFuY2ggdGhhdCBlYXJsaWVyIGRlbGl2ZXJ5IGp1c3Qgd29rZS4gRXZlcnkgZXZlbnQgaW4gb25lIGRyYWluXG4gICAgICAgICAgLy8gd2luZG93IGlzIGNvbnN1bWVkIGJlZm9yZSBhbnkgc2xvdCBydW5zLCBzbyBjYXB0dXJpbmcgYXRcbiAgICAgICAgICAvLyBjb25zdW1wdGlvbiB0aW1lIHNlZXMgYWxsIG9mIHRoZW0uXG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyBUaGUgQlVGRkVSRUQgYnJhbmNoIGJlbG93IGRlbGliZXJhdGVseSBkb2VzIE5PVCBkbyB0aGlzIOKAlCBzZWUgdGhlXG4gICAgICAgICAgLy8gY29tbWVudCBvbiBgY2xhaW0oKWAuXG4gICAgICAgICAgY29uc3QgZWFybGllckRlbGl2ZXJlZCA9IGF3YWl0RWFybGllckRlbGl2ZXJpZXMoXG4gICAgICAgICAgICBjdHgsXG4gICAgICAgICAgICBldmVudEluZGV4LFxuICAgICAgICAgICAgJ2hvb2snXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBuZXh0ID0gcHJvbWlzZXMuc2hpZnQoKTtcbiAgICAgICAgICBpZiAobmV4dCkge1xuICAgICAgICAgICAgLy8gSHlkcmF0ZSB0aHJvdWdoIGEgcHJvbWlzZVF1ZXVlIHNsb3QgKHNvIGFzeW5jIGRlc2VyaWFsaXphdGlvblxuICAgICAgICAgICAgLy8gc3RheXMgaW4gZXZlbnQtbG9nIG9yZGVyKSwgdGhlbiBkZWZlciBiZWhpbmQgZWFybGllciB3YWl0cyBhbmRcbiAgICAgICAgICAgIC8vIHN0ZXBzIGJlZm9yZSByZXNvbHZpbmcuIFRoZSBkZWZlcnJhbCBydW5zIE9GRiB0aGUgc2VyaWFsIHF1ZXVlXG4gICAgICAgICAgICAvLyAoaXQgbWF5IHdhaXQgb24gYW4gZWFybGllciB3YWl0IG9yIHN0ZXAgZGVsaXZlcnkgYW5kIGJsb2NraW5nIGFcbiAgICAgICAgICAgIC8vIHF1ZXVlIHNsb3Qgb24gdGhhdCB3b3VsZCBkZWFkbG9jayB0aGUgcXVldWUpLlxuICAgICAgICAgICAgY3R4LnBlbmRpbmdEZWxpdmVyaWVzKys7XG4gICAgICAgICAgICBsZXQgaHlkcmF0ZU91dGNvbWU6XG4gICAgICAgICAgICAgIHwgeyBvazogdHJ1ZTsgdmFsdWU6IFQgfVxuICAgICAgICAgICAgICB8IHsgb2s6IGZhbHNlOyBlcnJvcjogdW5rbm93biB9O1xuICAgICAgICAgICAgY3R4LnByb21pc2VRdWV1ZSA9IGN0eC5wcm9taXNlUXVldWUudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcHJlcGFyZWQgPVxuICAgICAgICAgICAgICAgICAgYXdhaXQgY3R4LnJlcGxheVBheWxvYWRDYWNoZS5wcmVwYXJlRXZlbnRQYXlsb2FkKFxuICAgICAgICAgICAgICAgICAgICBldmVudC5ldmVudElkLFxuICAgICAgICAgICAgICAgICAgICAncGF5bG9hZCcsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LmV2ZW50RGF0YS5wYXlsb2FkXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCBoeWRyYXRlU3RlcFJldHVyblZhbHVlKFxuICAgICAgICAgICAgICAgICAgZXZlbnQuZXZlbnREYXRhLnBheWxvYWQsXG4gICAgICAgICAgICAgICAgICBjdHgucnVuSWQsXG4gICAgICAgICAgICAgICAgICBjdHguZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICAgIGN0eC5nbG9iYWxUaGlzLFxuICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICBwcmVwYXJlZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaHlkcmF0ZU91dGNvbWUgPSB7IG9rOiB0cnVlLCB2YWx1ZTogcGF5bG9hZCBhcyBUIH07XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgaHlkcmF0ZU91dGNvbWUgPSB7IG9rOiBmYWxzZSwgZXJyb3IgfTtcbiAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICBjdHgucGVuZGluZ0RlbGl2ZXJpZXMtLTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB2b2lkIGVhcmxpZXJEZWxpdmVyZWQudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgYmFycmllci5tYXJrRGVsaXZlcmVkKCk7XG4gICAgICAgICAgICAgICAgaWYgKGh5ZHJhdGVPdXRjb21lLm9rKSB7XG4gICAgICAgICAgICAgICAgICBuZXh0LnJlc29sdmUoaHlkcmF0ZU91dGNvbWUudmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBuZXh0LnJlamVjdChoeWRyYXRlT3V0Y29tZS5lcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBObyBjb25zdW1lciBpcyBhd2FpdGluZyB5ZXQuIEh5ZHJhdGUgdGhyb3VnaCBhIHByb21pc2VRdWV1ZSBzbG90XG4gICAgICAgICAgLy8gYXQgdGhpcyBsb2cgcG9zaXRpb24gYW5kIHBhcmsgdGhlIE9VVENPTUUgKHZhbHVlIG9yIGVycm9yKSBmb3IgYVxuICAgICAgICAgIC8vIGxhdGVyIGBpdGVyYXRvci5uZXh0KClgIC8gYGF3YWl0IGhvb2tgIGNsYWltLiBXZSBjYXB0dXJlIHRoZVxuICAgICAgICAgIC8vIG91dGNvbWUgcmF0aGVyIHRoYW4gZWFnZXJseSByZXNvbHZpbmcvcmVqZWN0aW5nIGEgcHJvbWlzZSBub1xuICAgICAgICAgIC8vIGNvbnN1bWVyIGhhcyBhdHRhY2hlZCB0byDigJQgYSByZWplY3RlZCB1bmNsYWltZWQgcHJvbWlzZSAoZS5nLiBhXG4gICAgICAgICAgLy8gYnVmZmVyZWQgZW5jcnlwdGVkIHBheWxvYWQgd2l0aCBubyBrZXkpIHdvdWxkIG90aGVyd2lzZSBzdXJmYWNlXG4gICAgICAgICAgLy8gYXMgYW4gdW5oYW5kbGVkIHJlamVjdGlvbiBhbmQgY3Jhc2ggdGhlIHByb2Nlc3MuIGBjbGFpbSgpYCBidWlsZHNcbiAgICAgICAgICAvLyB0aGUgY29uc3VtZXItZmFjaW5nIHByb21pc2Ugb24gZGVtYW5kLlxuICAgICAgICAgIGxldCBvdXRjb21lOlxuICAgICAgICAgICAgfCB7IG9rOiB0cnVlOyB2YWx1ZTogVCB9XG4gICAgICAgICAgICB8IHsgb2s6IGZhbHNlOyBlcnJvcjogdW5rbm93biB9XG4gICAgICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgICAgICBjb25zdCBoeWRyYXRlZCA9IHdpdGhSZXNvbHZlcnM8dm9pZD4oKTtcblxuICAgICAgICAgIGNvbnN0IGNsYWltID0gKCk6IFByb21pc2U8VD4gPT4ge1xuICAgICAgICAgICAgLy8gQSBjb25zdW1lciBoYXMgdGFrZW4gdGhpcyBwYXlsb2FkLCBzbyBpdHMgZGVsaXZlcnkgbm8gbG9uZ2VyXG4gICAgICAgICAgICAvLyB3YWl0cyBvbiB3b3JrZmxvdyBjb2RlOiBsYXRlciBzdGVwIHJlc3VsdHMgbWF5IG5vdyBiZSBvcmRlcmVkXG4gICAgICAgICAgICAvLyBiZWhpbmQgaXQuXG4gICAgICAgICAgICBiYXJyaWVyLmFybSgpO1xuICAgICAgICAgICAgLy8gVW5saWtlIGV2ZXJ5IG90aGVyIGRlbGl2ZXJ5LCB0aGUgZGVmZXJyYWwgaXMgZXZhbHVhdGVkIEhFUkUsIGF0XG4gICAgICAgICAgICAvLyBjbGFpbSB0aW1lLCByYXRoZXIgdGhhbiB3aGVuIHRoZSBldmVudCB3YXMgY29uc3VtZWQuIEEgYnVmZmVyZWRcbiAgICAgICAgICAgIC8vIHBheWxvYWQncyBkZWxpdmVyeSBnZW51aW5lbHkgaGFwcGVucyB3aGVuIHRoZSB3b3JrZmxvdyByZWFkcyB0aGVcbiAgICAgICAgICAgIC8vIGhvb2ssIHdoaWNoIG1heSBiZSBtYW55IGRlbGl2ZXJpZXMgbGF0ZXI7IGEgY29uc3VtcHRpb24tdGltZVxuICAgICAgICAgICAgLy8gc25hcHNob3Qgd291bGQgbWFrZSB0aGUgY2xhaW0gd2FpdCBvbiDigJQgYW5kIHBheSB0aGUgbWFjcm90YXNrXG4gICAgICAgICAgICAvLyB5aWVsZCBmb3Ig4oCUIGJhcnJpZXJzIHRoYXQgd2VyZSByZWxldmFudCB0byBhIG1vbWVudCB0aGlzIHBheWxvYWRcbiAgICAgICAgICAgIC8vIG5ldmVyIHBhcnRpY2lwYXRlZCBpbi4gVGhhdCBpcyBub3QgdGhlb3JldGljYWw6IGl0IHN0YWxscyB0aGVcbiAgICAgICAgICAgIC8vIHNlY29uZCBwYXlsb2FkIGluIHRoZSBlMmUgYGhvb2tXaXRoU2xlZXBXb3JrZmxvd2AgbG9uZyBlbm91Z2hcbiAgICAgICAgICAgIC8vIGZvciB0aGUgcnVuIHRvIHN1c3BlbmQgYmVmb3JlIGRlbGl2ZXJpbmcgaXQuXG4gICAgICAgICAgICByZXR1cm4gaHlkcmF0ZWQucHJvbWlzZVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzKGN0eCwgZXZlbnRJbmRleCwgJ2hvb2snKSlcbiAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGJhcnJpZXIubWFya0RlbGl2ZXJlZCgpO1xuICAgICAgICAgICAgICAgIGlmIChvdXRjb21lICYmICFvdXRjb21lLm9rKSB7XG4gICAgICAgICAgICAgICAgICB0aHJvdyBvdXRjb21lLmVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKG91dGNvbWUgYXMgeyBvazogdHJ1ZTsgdmFsdWU6IFQgfSkudmFsdWU7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBjdHgucGVuZGluZ0RlbGl2ZXJpZXMrKztcbiAgICAgICAgICBjdHgucHJvbWlzZVF1ZXVlID0gY3R4LnByb21pc2VRdWV1ZS50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IHByZXBhcmVkID0gYXdhaXQgY3R4LnJlcGxheVBheWxvYWRDYWNoZS5wcmVwYXJlRXZlbnRQYXlsb2FkKFxuICAgICAgICAgICAgICAgIGV2ZW50LmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgJ3BheWxvYWQnLFxuICAgICAgICAgICAgICAgIGV2ZW50LmV2ZW50RGF0YS5wYXlsb2FkXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBhd2FpdCBoeWRyYXRlU3RlcFJldHVyblZhbHVlKFxuICAgICAgICAgICAgICAgIGV2ZW50LmV2ZW50RGF0YS5wYXlsb2FkLFxuICAgICAgICAgICAgICAgIGN0eC5ydW5JZCxcbiAgICAgICAgICAgICAgICBjdHguZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgICBjdHguZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICBwcmVwYXJlZFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBvdXRjb21lID0geyBvazogdHJ1ZSwgdmFsdWU6IHBheWxvYWQgYXMgVCB9O1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgb3V0Y29tZSA9IHsgb2s6IGZhbHNlLCBlcnJvciB9O1xuICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgY3R4LnBlbmRpbmdEZWxpdmVyaWVzLS07XG4gICAgICAgICAgICAgIGh5ZHJhdGVkLnJlc29sdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBwYXlsb2Fkc1F1ZXVlLnB1c2goeyBjbGFpbSB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0LkNvbnN1bWVkO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQuZXZlbnRUeXBlID09PSAnaG9va19kaXNwb3NlZCcpIHtcbiAgICAgICAgLy8gVGVybWluYWwgc3RhdGUgLSByZW1vdmUgZnJvbSBxdWV1ZSAobGlrZSBzdGVwX2NvbXBsZXRlZC93YWl0X2NvbXBsZXRlZClcbiAgICAgICAgY3R4Lmludm9jYXRpb25zUXVldWUuZGVsZXRlKGNvcnJlbGF0aW9uSWQpO1xuICAgICAgICAvLyBNYXJrIHRoYXQgdGhlIGV2ZW50IGxvZyBjb25maXJtcyBkaXNwb3NhbCBoYXBwZW5lZFxuICAgICAgICBoYXNEaXNwb3NlZEV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgLy8gV2UncmUgZG9uZSBwcm9jZXNzaW5nIGFueSBtb3JlIGV2ZW50cyBmb3IgdGhpcyBob29rXG4gICAgICAgIHJldHVybiBFdmVudENvbnN1bWVyUmVzdWx0LkZpbmlzaGVkO1xuICAgICAgfVxuXG4gICAgICAvLyBUaGlzIHJlcGxheSBpbnN0YWxsZWQgYSBkaWZmZXJlbnQgY29uc3VtZXIgdGhhbiB0aGUgc3RvcmVkIGV2ZW50IG5lZWRzLlxuICAgICAgY3R4LnByb21pc2VRdWV1ZSA9IGN0eC5wcm9taXNlUXVldWUudGhlbigoKSA9PiB7XG4gICAgICAgIGN0eC5vbldvcmtmbG93RXJyb3IoXG4gICAgICAgICAgbmV3IFJlcGxheURpdmVyZ2VuY2VFcnJvcihcbiAgICAgICAgICAgIGBSZXBsYXkgZGl2ZXJnZW5jZTogVW5leHBlY3RlZCBldmVudCB0eXBlIGZvciBob29rICR7Y29ycmVsYXRpb25JZH0gKHRva2VuOiAke3Rva2VufSkgXCIke2V2ZW50LmV2ZW50VHlwZX1cImAsXG4gICAgICAgICAgICB7IGV2ZW50SWQ6IGV2ZW50LmV2ZW50SWQgfVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIEV2ZW50Q29uc3VtZXJSZXN1bHQuRmluaXNoZWQ7XG4gICAgfSk7XG5cbiAgICAvLyBUcmFjayBpZiB0aGUgaG9vayBoYXMgYmVlbiBkaXNwb3NlZFxuICAgIGxldCBpc0Rpc3Bvc2VkID0gZmFsc2U7XG5cbiAgICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY3JlYXRlIGEgbmV3IHByb21pc2UgdGhhdCB3YWl0cyBmb3IgdGhlIG5leHQgaG9vayBwYXlsb2FkXG4gICAgZnVuY3Rpb24gY3JlYXRlSG9va1Byb21pc2UoKTogUHJvbWlzZTxUPiB7XG4gICAgICBjb25zdCByZXNvbHZlcnMgPSB3aXRoUmVzb2x2ZXJzPFQ+KCk7XG5cbiAgICAgIC8vIElmIHdlIGhhdmUgYSBjb25mbGljdCwgcmVqZWN0IHRocm91Z2ggdGhlIHByb21pc2VRdWV1ZSB0byBtYWludGFpblxuICAgICAgLy8gZGV0ZXJtaW5pc3RpYyBvcmRlcmluZyB3aXRoIGFueSBwcmlvciBxdWV1ZWQgcmVzb2x1dGlvbnMuXG4gICAgICBpZiAoaGFzQ29uZmxpY3QgJiYgY29uZmxpY3RFcnJvclJlZikge1xuICAgICAgICBjdHgucHJvbWlzZVF1ZXVlID0gY3R4LnByb21pc2VRdWV1ZS50aGVuKCgpID0+IHtcbiAgICAgICAgICByZXNvbHZlcnMucmVqZWN0KGNvbmZsaWN0RXJyb3JSZWYpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVycy5wcm9taXNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocGF5bG9hZHNRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IG5leHREZWxpdmVyeSA9IHBheWxvYWRzUXVldWUuc2hpZnQoKTtcbiAgICAgICAgaWYgKG5leHREZWxpdmVyeSkge1xuICAgICAgICAgIC8vIFRoZSBwYXlsb2FkIHdhcyBoeWRyYXRlZCB0aHJvdWdoIGEgcHJvbWlzZVF1ZXVlIHNsb3QgYXQgaXRzIGxvZ1xuICAgICAgICAgIC8vIHBvc2l0aW9uIChidWZmZXJpbmcgYnJhbmNoIGFib3ZlKS4gYGNsYWltKClgIGJ1aWxkcyB0aGVcbiAgICAgICAgICAvLyBjb25zdW1lci1mYWNpbmcgcHJvbWlzZSBmcm9tIHRoYXQgb3V0Y29tZSwgZGVmZXJyaW5nIGJlaGluZCBhbnlcbiAgICAgICAgICAvLyBlYXJsaWVyLWluLWxvZyB3YWl0IG9yIHN0ZXAgYW5kIG1hcmtpbmcgdGhpcyBob29rIGRlbGl2ZXJlZCDigJQgc29cbiAgICAgICAgICAvLyByZXNvbHV0aW9uIG9yZGVyIHN0YXlzIGFuY2hvcmVkIHRvIHRoZSBldmVudCBsb2csIG5vdCB0aGlzIGxhdGVyXG4gICAgICAgICAgLy8gY2xhaW0gc2l0ZS5cbiAgICAgICAgICByZXR1cm4gbmV4dERlbGl2ZXJ5LmNsYWltKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50TG9nRW1wdHkpIHtcbiAgICAgICAgc2NoZWR1bGVXaGVuSWRsZShjdHgsICgpID0+IHtcbiAgICAgICAgICBjdHgub25Xb3JrZmxvd0Vycm9yKFxuICAgICAgICAgICAgbmV3IFdvcmtmbG93U3VzcGVuc2lvbihjdHguaW52b2NhdGlvbnNRdWV1ZSwgY3R4Lmdsb2JhbFRoaXMpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHByb21pc2VzLnB1c2gocmVzb2x2ZXJzKTtcblxuICAgICAgcmV0dXJuIHJlc29sdmVycy5wcm9taXNlO1xuICAgIH1cblxuICAgIC8vIEhlbHBlciBmdW5jdGlvbiB0byBjcmVhdGUgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgaG9vaydzXG4gICAgLy8gcmVnaXN0cmF0aW9uIG91dGNvbWU6IHRoZSBjb25mbGljdGluZyBgUnVuYCB3aGVuIHRoZSB0b2tlbiBpcyBvd25lZFxuICAgIC8vIGJ5IGFub3RoZXIgYWN0aXZlIGhvb2ssIGBudWxsYCBvbmNlIHRoaXMgaG9vaydzIHJlZ2lzdHJhdGlvbiBpc1xuICAgIC8vIGNvbW1pdHRlZC4gQm90aCBmYXN0LXBhdGhzIHNldHRsZSB0aHJvdWdoIGBjdHgucHJvbWlzZVF1ZXVlYCBzb1xuICAgIC8vIHJlc29sdXRpb24gb3JkZXIgYWx3YXlzIG1hdGNoZXMgZXZlbnQtbG9nIG9yZGVyLlxuICAgIGZ1bmN0aW9uIGNyZWF0ZUdldENvbmZsaWN0UHJvbWlzZSgpOiBQcm9taXNlPFJ1bjx1bmtub3duPiB8IG51bGw+IHtcbiAgICAgIGNvbnN0IHJlc29sdmVycyA9IHdpdGhSZXNvbHZlcnM8UnVuPHVua25vd24+IHwgbnVsbD4oKTtcblxuICAgICAgaWYgKGhhc0NyZWF0ZWQpIHtcbiAgICAgICAgY3R4LnByb21pc2VRdWV1ZSA9IGN0eC5wcm9taXNlUXVldWUudGhlbigoKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZXJzLnJlc29sdmUobnVsbCk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZXJzLnByb21pc2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChoYXNDb25mbGljdCkge1xuICAgICAgICBjdHgucHJvbWlzZVF1ZXVlID0gY3R4LnByb21pc2VRdWV1ZS50aGVuKCgpID0+IHtcbiAgICAgICAgICBpZiAoY29uZmxpY3RSdW5SZWYpIHtcbiAgICAgICAgICAgIHJlc29sdmVycy5yZXNvbHZlKGNvbmZsaWN0UnVuUmVmKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzb2x2ZXJzLnJlamVjdChjb25mbGljdEVycm9yUmVmKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZXJzLnByb21pc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHF1ZXVlSXRlbSA9IGN0eC5pbnZvY2F0aW9uc1F1ZXVlLmdldChjb3JyZWxhdGlvbklkKTtcbiAgICAgIGlmIChxdWV1ZUl0ZW0gJiYgcXVldWVJdGVtLnR5cGUgPT09ICdob29rJykge1xuICAgICAgICBxdWV1ZUl0ZW0uaGFzQ29uZmxpY3RBd2FpdGVyID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50TG9nRW1wdHkpIHtcbiAgICAgICAgc2NoZWR1bGVXaGVuSWRsZShjdHgsICgpID0+IHtcbiAgICAgICAgICBjdHgub25Xb3JrZmxvd0Vycm9yKFxuICAgICAgICAgICAgbmV3IFdvcmtmbG93U3VzcGVuc2lvbihjdHguaW52b2NhdGlvbnNRdWV1ZSwgY3R4Lmdsb2JhbFRoaXMpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGdldENvbmZsaWN0UHJvbWlzZXMucHVzaChyZXNvbHZlcnMpO1xuICAgICAgcmV0dXJuIHJlc29sdmVycy5wcm9taXNlO1xuICAgIH1cblxuICAgIC8vIEhlbHBlciBmdW5jdGlvbiB0byBkaXNwb3NlIHRoZSBob29rXG4gICAgZnVuY3Rpb24gZGlzcG9zZUhvb2soKTogdm9pZCB7XG4gICAgICBpZiAoaXNEaXNwb3NlZCkge1xuICAgICAgICByZXR1cm47IC8vIEFscmVhZHkgZGlzcG9zZWQsIG5vdGhpbmcgdG8gZG9cbiAgICAgIH1cbiAgICAgIGlzRGlzcG9zZWQgPSB0cnVlO1xuXG4gICAgICAvLyBJZiB0aGUgZXZlbnQgbG9nIGFscmVhZHkgY29udGFpbnMgaG9va19kaXNwb3NlZCwgdGhpcyBpcyBhIHJlcGxheSDigJQgbm8tb3BcbiAgICAgIGlmIChoYXNEaXNwb3NlZEV2ZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IGRpc3Bvc2VkIGZsYWcgb24gdGhlIGV4aXN0aW5nIHF1ZXVlIGl0ZW1cbiAgICAgIGNvbnN0IHF1ZXVlSXRlbSA9IGN0eC5pbnZvY2F0aW9uc1F1ZXVlLmdldChjb3JyZWxhdGlvbklkKTtcbiAgICAgIGlmIChxdWV1ZUl0ZW0gJiYgcXVldWVJdGVtLnR5cGUgPT09ICdob29rJykge1xuICAgICAgICBxdWV1ZUl0ZW0uZGlzcG9zZWQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBEcmFpbiBhbnkgcGVuZGluZyBwcm9taXNlcyB0aGF0IGFyZSB3YWl0aW5nIGZvciBwYXlsb2Fkcy5cbiAgICAgIC8vIFdpdGhvdXQgdGhpcywgcHJvbWlzZXMgY3JlYXRlZCBieSBgYXdhaXQgaG9va2Agb3IgdGhlIGFzeW5jIGl0ZXJhdG9yJ3NcbiAgICAgIC8vIGB5aWVsZCBhd2FpdCB0aGlzYCB3b3VsZCBoYW5nIGZvcmV2ZXIgc2luY2UgdGhlIGV2ZW50IGNvbnN1bWVyIHdpbGxcbiAgICAgIC8vIG5ldmVyIGRlbGl2ZXIgYW5vdGhlciBob29rX3JlY2VpdmVkIGFmdGVyIGRpc3Bvc2FsLlxuICAgICAgaWYgKHByb21pc2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcHJvbWlzZXMubGVuZ3RoID0gMDtcbiAgICAgICAgc2NoZWR1bGVXaGVuSWRsZShjdHgsICgpID0+IHtcbiAgICAgICAgICBjdHgub25Xb3JrZmxvd0Vycm9yKFxuICAgICAgICAgICAgbmV3IFdvcmtmbG93U3VzcGVuc2lvbihjdHguaW52b2NhdGlvbnNRdWV1ZSwgY3R4Lmdsb2JhbFRoaXMpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHdlYmhvb2tMb2dnZXIuZGVidWcoJ0hvb2sgZGlzcG9zZWQnLCB7IGNvcnJlbGF0aW9uSWQsIHRva2VuIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGhvb2s6IEhvb2s8VD4gPSB7XG4gICAgICB0b2tlbixcblxuICAgICAgZ2V0Q29uZmxpY3QoKTogUHJvbWlzZTxSdW48dW5rbm93bj4gfCBudWxsPiB7XG4gICAgICAgIHJldHVybiBjcmVhdGVHZXRDb25mbGljdFByb21pc2UoKTtcbiAgICAgIH0sXG5cbiAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9UaGVuUHJvcGVydHk6IEludGVudGlvbmFsbHkgdGhlbmFibGVcbiAgICAgIHRoZW48VFJlc3VsdDEgPSBULCBUUmVzdWx0MiA9IG5ldmVyPihcbiAgICAgICAgb25mdWxmaWxsZWQ/OiAoKHZhbHVlOiBUKSA9PiBUUmVzdWx0MSB8IFByb21pc2VMaWtlPFRSZXN1bHQxPikgfCBudWxsLFxuICAgICAgICBvbnJlamVjdGVkPzogKChyZWFzb246IGFueSkgPT4gVFJlc3VsdDIgfCBQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgbnVsbFxuICAgICAgKTogUHJvbWlzZTxUUmVzdWx0MSB8IFRSZXN1bHQyPiB7XG4gICAgICAgIHJldHVybiBjcmVhdGVIb29rUHJvbWlzZSgpLnRoZW4ob25mdWxmaWxsZWQsIG9ucmVqZWN0ZWQpO1xuICAgICAgfSxcblxuICAgICAgLy8gU3VwcG9ydCBgZm9yIGF3YWl0IChjb25zdCBwYXlsb2FkIG9mIGhvb2spIHsg4oCmIH1gIHN5bnRheFxuICAgICAgYXN5bmMgKltTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSB7XG4gICAgICAgIHdoaWxlICghaXNEaXNwb3NlZCkge1xuICAgICAgICAgIHlpZWxkIGF3YWl0IHRoaXM7XG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIGRpc3Bvc2U6IGRpc3Bvc2VIb29rLFxuXG4gICAgICBbU3ltYm9sLmRpc3Bvc2VdOiBkaXNwb3NlSG9vayxcbiAgICB9O1xuXG4gICAgLy8gQWxzbyByZWdpc3RlciB3aXRoIHRoZSBWTSdzIFN5bWJvbC5kaXNwb3NlIHNvIGB1c2luZ2Agd29ya3MgaW5zaWRlXG4gICAgLy8gdGhlIHdvcmtmbG93IHNhbmRib3ggKHRoZSBWTSBtYXkgaGF2ZSBhIHBvbHlmaWxsZWQgU3ltYm9sLmRpc3Bvc2VcbiAgICAvLyB0aGF0IGRpZmZlcnMgZnJvbSB0aGUgaG9zdCdzKS5cbiAgICBjb25zdCB2bURpc3Bvc2UgPSBjdHguZ2xvYmFsVGhpcy5TeW1ib2wuZGlzcG9zZTtcbiAgICBpZiAodm1EaXNwb3NlICYmIHZtRGlzcG9zZSAhPT0gU3ltYm9sLmRpc3Bvc2UpIHtcbiAgICAgIChob29rIGFzIGFueSlbdm1EaXNwb3NlXSA9IGRpc3Bvc2VIb29rO1xuICAgIH1cblxuICAgIHJldHVybiBob29rO1xuICB9O1xufVxuIl19