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

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 (317) hide show
  1. package/README.md +5 -0
  2. package/dist/attribute-changes.d.ts +5 -0
  3. package/dist/attribute-changes.d.ts.map +1 -0
  4. package/dist/attribute-changes.js +25 -0
  5. package/dist/capabilities.d.ts +35 -2
  6. package/dist/capabilities.d.ts.map +1 -1
  7. package/dist/capabilities.js +74 -5
  8. package/dist/capture-stack.d.ts +1 -1
  9. package/dist/capture-stack.js +2 -2
  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 +19 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +98 -6
  16. package/dist/context-violation-error.d.ts +5 -5
  17. package/dist/context-violation-error.d.ts.map +1 -1
  18. package/dist/context-violation-error.js +8 -6
  19. package/dist/create-hook.d.ts +72 -7
  20. package/dist/create-hook.d.ts.map +1 -1
  21. package/dist/create-hook.js +1 -1
  22. package/dist/define-hook.js +2 -2
  23. package/dist/describe-error.d.ts +7 -7
  24. package/dist/describe-error.d.ts.map +1 -1
  25. package/dist/describe-error.js +97 -12
  26. package/dist/encryption.d.ts +38 -4
  27. package/dist/encryption.d.ts.map +1 -1
  28. package/dist/encryption.js +96 -14
  29. package/dist/events-consumer.d.ts +297 -0
  30. package/dist/events-consumer.d.ts.map +1 -1
  31. package/dist/events-consumer.js +673 -42
  32. package/dist/flushable-stream.d.ts +97 -1
  33. package/dist/flushable-stream.d.ts.map +1 -1
  34. package/dist/flushable-stream.js +291 -11
  35. package/dist/global.d.ts +36 -2
  36. package/dist/global.d.ts.map +1 -1
  37. package/dist/global.js +21 -6
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3 -2
  41. package/dist/log-format.d.ts +2 -2
  42. package/dist/log-format.js +19 -12
  43. package/dist/logger.d.ts +1 -0
  44. package/dist/logger.d.ts.map +1 -1
  45. package/dist/logger.js +10 -6
  46. package/dist/private.d.ts +226 -9
  47. package/dist/private.d.ts.map +1 -1
  48. package/dist/private.js +626 -7
  49. package/dist/replay-divergence.d.ts +25 -0
  50. package/dist/replay-divergence.d.ts.map +1 -0
  51. package/dist/replay-divergence.js +61 -0
  52. package/dist/replay-payload-cache.d.ts +64 -0
  53. package/dist/replay-payload-cache.d.ts.map +1 -0
  54. package/dist/replay-payload-cache.js +158 -0
  55. package/dist/runtime/compute-instance.d.ts +13 -0
  56. package/dist/runtime/compute-instance.d.ts.map +1 -0
  57. package/dist/runtime/compute-instance.js +14 -0
  58. package/dist/runtime/constants.d.ts +315 -0
  59. package/dist/runtime/constants.d.ts.map +1 -1
  60. package/dist/runtime/constants.js +502 -16
  61. package/dist/runtime/count-step-started-events.d.ts +52 -0
  62. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  63. package/dist/runtime/count-step-started-events.js +72 -0
  64. package/dist/runtime/deployment-guard.d.ts +99 -0
  65. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  66. package/dist/runtime/deployment-guard.js +154 -0
  67. package/dist/runtime/get-port-lazy.d.ts +15 -0
  68. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  69. package/dist/runtime/get-port-lazy.js +75 -6
  70. package/dist/runtime/get-world-lazy.d.ts +5 -14
  71. package/dist/runtime/get-world-lazy.d.ts.map +1 -1
  72. package/dist/runtime/get-world-lazy.js +19 -29
  73. package/dist/runtime/helpers.d.ts +415 -29
  74. package/dist/runtime/helpers.d.ts.map +1 -1
  75. package/dist/runtime/helpers.js +686 -57
  76. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  77. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  78. package/dist/runtime/quickjs-assets.generated.js +30 -0
  79. package/dist/runtime/quickjs-entrypoint.d.ts +158 -0
  80. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  81. package/dist/runtime/quickjs-entrypoint.js +1863 -0
  82. package/dist/runtime/quickjs-log-view.d.ts +129 -0
  83. package/dist/runtime/quickjs-log-view.d.ts.map +1 -0
  84. package/dist/runtime/quickjs-log-view.js +229 -0
  85. package/dist/runtime/quickjs-runtime.d.ts +244 -0
  86. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  87. package/dist/runtime/quickjs-runtime.js +2427 -0
  88. package/dist/runtime/quickjs-serde.d.ts +107 -0
  89. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  90. package/dist/runtime/quickjs-serde.js +2159 -0
  91. package/dist/runtime/replay-budget.d.ts +97 -0
  92. package/dist/runtime/replay-budget.d.ts.map +1 -0
  93. package/dist/runtime/replay-budget.js +139 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  95. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  96. package/dist/runtime/replay-recovery-reporter.js +64 -0
  97. package/dist/runtime/resume-hook.d.ts +91 -8
  98. package/dist/runtime/resume-hook.d.ts.map +1 -1
  99. package/dist/runtime/resume-hook.js +512 -89
  100. package/dist/runtime/resume-latency.d.ts +150 -0
  101. package/dist/runtime/resume-latency.d.ts.map +1 -0
  102. package/dist/runtime/resume-latency.js +155 -0
  103. package/dist/runtime/run-id-time.d.ts +19 -0
  104. package/dist/runtime/run-id-time.d.ts.map +1 -0
  105. package/dist/runtime/run-id-time.js +42 -0
  106. package/dist/runtime/run.d.ts +72 -7
  107. package/dist/runtime/run.d.ts.map +1 -1
  108. package/dist/runtime/run.js +280 -53
  109. package/dist/runtime/runs.d.ts +54 -3
  110. package/dist/runtime/runs.d.ts.map +1 -1
  111. package/dist/runtime/runs.js +126 -16
  112. package/dist/runtime/start.d.ts +101 -2
  113. package/dist/runtime/start.d.ts.map +1 -1
  114. package/dist/runtime/start.js +352 -61
  115. package/dist/runtime/step-executor.d.ts +186 -5
  116. package/dist/runtime/step-executor.d.ts.map +1 -1
  117. package/dist/runtime/step-executor.js +768 -130
  118. package/dist/runtime/step-latency.d.ts +220 -0
  119. package/dist/runtime/step-latency.d.ts.map +1 -0
  120. package/dist/runtime/step-latency.js +215 -0
  121. package/dist/runtime/step-ownership.d.ts +72 -0
  122. package/dist/runtime/step-ownership.d.ts.map +1 -0
  123. package/dist/runtime/step-ownership.js +114 -0
  124. package/dist/runtime/step-single-flight.d.ts +12 -0
  125. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  126. package/dist/runtime/step-single-flight.js +75 -0
  127. package/dist/runtime/suspension-handler.d.ts +247 -7
  128. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  129. package/dist/runtime/suspension-handler.js +1304 -125
  130. package/dist/runtime/unserializable-step.d.ts +34 -0
  131. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  132. package/dist/runtime/unserializable-step.js +52 -0
  133. package/dist/runtime/vm-mode.d.ts +44 -0
  134. package/dist/runtime/vm-mode.d.ts.map +1 -0
  135. package/dist/runtime/vm-mode.js +62 -0
  136. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  137. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  138. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  139. package/dist/runtime/wait-continuation.d.ts +106 -0
  140. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  141. package/dist/runtime/wait-continuation.js +136 -0
  142. package/dist/runtime/wait-until.d.ts +18 -0
  143. package/dist/runtime/wait-until.d.ts.map +1 -0
  144. package/dist/runtime/wait-until.js +42 -0
  145. package/dist/runtime/world-compatibility.d.ts +32 -0
  146. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  147. package/dist/runtime/world-compatibility.js +44 -0
  148. package/dist/runtime/world-init.d.ts +17 -42
  149. package/dist/runtime/world-init.d.ts.map +1 -1
  150. package/dist/runtime/world-init.js +18 -43
  151. package/dist/runtime/world.d.ts +14 -2
  152. package/dist/runtime/world.d.ts.map +1 -1
  153. package/dist/runtime/world.js +75 -19
  154. package/dist/runtime.d.ts +10 -6
  155. package/dist/runtime.d.ts.map +1 -1
  156. package/dist/runtime.js +3911 -489
  157. package/dist/sealed-box.d.ts +167 -0
  158. package/dist/sealed-box.d.ts.map +1 -0
  159. package/dist/sealed-box.js +571 -0
  160. package/dist/serialization/client.d.ts +3 -3
  161. package/dist/serialization/client.d.ts.map +1 -1
  162. package/dist/serialization/client.js +8 -4
  163. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  164. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  165. package/dist/serialization/codec-devalue-vm.js +148 -0
  166. package/dist/serialization/codec-devalue.d.ts +1 -1
  167. package/dist/serialization/codec-devalue.d.ts.map +1 -1
  168. package/dist/serialization/codec-devalue.js +24 -6
  169. package/dist/serialization/codec.d.ts +37 -2
  170. package/dist/serialization/codec.d.ts.map +1 -1
  171. package/dist/serialization/codec.js +2 -2
  172. package/dist/serialization/compression.d.ts +105 -0
  173. package/dist/serialization/compression.d.ts.map +1 -0
  174. package/dist/serialization/compression.js +261 -0
  175. package/dist/serialization/encryption.d.ts +119 -17
  176. package/dist/serialization/encryption.d.ts.map +1 -1
  177. package/dist/serialization/encryption.js +152 -17
  178. package/dist/serialization/errors.d.ts +13 -0
  179. package/dist/serialization/errors.d.ts.map +1 -1
  180. package/dist/serialization/errors.js +20 -2
  181. package/dist/serialization/format.d.ts +6 -6
  182. package/dist/serialization/format.js +7 -7
  183. package/dist/serialization/hardened.d.ts +156 -0
  184. package/dist/serialization/hardened.d.ts.map +1 -0
  185. package/dist/serialization/hardened.js +538 -0
  186. package/dist/serialization/index.d.ts +10 -8
  187. package/dist/serialization/index.d.ts.map +1 -1
  188. package/dist/serialization/index.js +10 -8
  189. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  190. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class-vm.js +77 -0
  192. package/dist/serialization/reducers/class.d.ts.map +1 -1
  193. package/dist/serialization/reducers/class.js +11 -6
  194. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  195. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  196. package/dist/serialization/reducers/common-vm.js +616 -0
  197. package/dist/serialization/reducers/common.d.ts +1 -1
  198. package/dist/serialization/reducers/common.d.ts.map +1 -1
  199. package/dist/serialization/reducers/common.js +202 -62
  200. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  201. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  202. package/dist/serialization/reducers/step-function-vm.js +97 -0
  203. package/dist/serialization/reducers/step-function.d.ts.map +1 -1
  204. package/dist/serialization/reducers/step-function.js +25 -9
  205. package/dist/serialization/step.d.ts +4 -4
  206. package/dist/serialization/step.d.ts.map +1 -1
  207. package/dist/serialization/step.js +9 -5
  208. package/dist/serialization/types.d.ts +80 -1
  209. package/dist/serialization/types.d.ts.map +1 -1
  210. package/dist/serialization/types.js +15 -1
  211. package/dist/serialization/workflow-vm.d.ts +29 -0
  212. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  213. package/dist/serialization/workflow-vm.js +74 -0
  214. package/dist/serialization-format.d.ts +64 -8
  215. package/dist/serialization-format.d.ts.map +1 -1
  216. package/dist/serialization-format.js +225 -73
  217. package/dist/serialization.d.ts +262 -34
  218. package/dist/serialization.d.ts.map +1 -1
  219. package/dist/serialization.js +1885 -277
  220. package/dist/set-attributes.d.ts +13 -0
  221. package/dist/set-attributes.d.ts.map +1 -0
  222. package/dist/set-attributes.js +60 -0
  223. package/dist/source-map.d.ts +25 -0
  224. package/dist/source-map.d.ts.map +1 -1
  225. package/dist/source-map.js +154 -10
  226. package/dist/step/context-storage.d.ts +63 -2
  227. package/dist/step/context-storage.d.ts.map +1 -1
  228. package/dist/step/context-storage.js +7 -5
  229. package/dist/step/writable-stream.d.ts +3 -3
  230. package/dist/step/writable-stream.d.ts.map +1 -1
  231. package/dist/step/writable-stream.js +80 -13
  232. package/dist/step.d.ts.map +1 -1
  233. package/dist/step.js +148 -27
  234. package/dist/symbols.d.ts +50 -0
  235. package/dist/symbols.d.ts.map +1 -1
  236. package/dist/symbols.js +51 -1
  237. package/dist/telemetry/semantic-conventions.d.ts +433 -2
  238. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  239. package/dist/telemetry/semantic-conventions.js +319 -3
  240. package/dist/telemetry.d.ts +91 -0
  241. package/dist/telemetry.d.ts.map +1 -1
  242. package/dist/telemetry.js +244 -17
  243. package/dist/test-support/orchestrator-context.d.ts +25 -0
  244. package/dist/test-support/orchestrator-context.d.ts.map +1 -0
  245. package/dist/test-support/orchestrator-context.js +107 -0
  246. package/dist/types.d.ts +6 -0
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/types.js +23 -1
  249. package/dist/util.d.ts +0 -5
  250. package/dist/util.d.ts.map +1 -1
  251. package/dist/util.js +1 -15
  252. package/dist/version.d.ts +1 -1
  253. package/dist/version.d.ts.map +1 -1
  254. package/dist/version.js +2 -2
  255. package/dist/vm/index.d.ts.map +1 -1
  256. package/dist/vm/index.js +84 -14
  257. package/dist/vm/script-cache.d.ts +26 -0
  258. package/dist/vm/script-cache.d.ts.map +1 -0
  259. package/dist/vm/script-cache.js +131 -0
  260. package/dist/vm/uint8array-base64.js +1 -1
  261. package/dist/workflow/abort-controller.d.ts +2 -2
  262. package/dist/workflow/abort-controller.d.ts.map +1 -1
  263. package/dist/workflow/abort-controller.js +88 -21
  264. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  265. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  266. package/dist/workflow/attribute-dispatcher.js +45 -0
  267. package/dist/workflow/create-hook.d.ts.map +1 -1
  268. package/dist/workflow/create-hook.js +24 -3
  269. package/dist/workflow/get-workflow-metadata.js +2 -2
  270. package/dist/workflow/hook.d.ts.map +1 -1
  271. package/dist/workflow/hook.js +304 -47
  272. package/dist/workflow/index.d.ts +1 -0
  273. package/dist/workflow/index.d.ts.map +1 -1
  274. package/dist/workflow/index.js +2 -1
  275. package/dist/workflow/set-attributes.d.ts +68 -0
  276. package/dist/workflow/set-attributes.d.ts.map +1 -0
  277. package/dist/workflow/set-attributes.js +60 -0
  278. package/dist/workflow/sleep.d.ts.map +1 -1
  279. package/dist/workflow/sleep.js +58 -12
  280. package/dist/workflow/world-init-stub.d.ts +3 -3
  281. package/dist/workflow/world-init-stub.js +4 -4
  282. package/dist/workflow.d.ts +95 -3
  283. package/dist/workflow.d.ts.map +1 -1
  284. package/dist/workflow.js +900 -561
  285. package/docs/api-reference/create-hook.mdx +89 -10
  286. package/docs/api-reference/create-webhook.mdx +16 -15
  287. package/docs/api-reference/define-hook.mdx +35 -33
  288. package/docs/api-reference/fatal-error.mdx +30 -8
  289. package/docs/api-reference/fetch.mdx +14 -10
  290. package/docs/api-reference/get-step-metadata.mdx +2 -2
  291. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  292. package/docs/api-reference/get-writable.mdx +7 -7
  293. package/docs/api-reference/index.mdx +4 -1
  294. package/docs/api-reference/retryable-error.mdx +1 -1
  295. package/docs/api-reference/set-attributes.mdx +61 -0
  296. package/docs/api-reference/sleep.mdx +4 -4
  297. package/docs/foundations/cancellation.mdx +31 -32
  298. package/docs/foundations/errors-and-retries.mdx +42 -11
  299. package/docs/foundations/hooks.mdx +64 -35
  300. package/docs/foundations/idempotency.mdx +244 -12
  301. package/docs/foundations/index.mdx +1 -23
  302. package/docs/foundations/meta.json +2 -1
  303. package/docs/foundations/serialization.mdx +21 -22
  304. package/docs/foundations/starting-workflows.mdx +106 -30
  305. package/docs/foundations/streaming.mdx +108 -60
  306. package/docs/foundations/versioning.mdx +263 -0
  307. package/docs/foundations/workflows-and-steps.mdx +9 -9
  308. package/docs/how-it-works/cancellation.mdx +63 -63
  309. package/docs/how-it-works/code-transform.mdx +83 -67
  310. package/docs/how-it-works/encryption.mdx +30 -26
  311. package/docs/how-it-works/event-sourcing.mdx +125 -34
  312. package/docs/how-it-works/framework-integrations.mdx +96 -337
  313. package/docs/how-it-works/understanding-directives.mdx +22 -22
  314. package/package.json +24 -15
  315. package/dist/runtime/step-handler.d.ts +0 -2
  316. package/dist/runtime/step-handler.d.ts.map +0 -1
  317. package/dist/runtime/step-handler.js +0 -776
@@ -1,135 +1,386 @@
1
- import { waitUntil } from '@vercel/functions';
2
- import { EntityConflictError, HookNotFoundError, RunExpiredError, } from '@workflow/errors';
3
- import { SPEC_VERSION_CURRENT, } from '@workflow/world';
1
+ import { EntityConflictError, FatalError, HookNotFoundError, PreconditionFailedError, RunExpiredError, SerializationError, WorkflowWorldError, } from '@workflow/errors';
2
+ import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY, } from '@workflow/world';
3
+ import { isRetryableWorldError } from '../classify-error.js';
4
4
  import { importKey } from '../encryption.js';
5
5
  import { runtimeLogger } from '../logger.js';
6
- import { dehydrateStepArguments } from '../serialization.js';
7
- import { getAbortStreamIdFromToken } from '../util.js';
6
+ import { GUEST_CODE_EXECUTION_SAMPLE_LIMIT, } from '../serialization/hardened.js';
7
+ import { dehydrateStepArguments, dehydrateStepError, } from '../serialization.js';
8
8
  import * as Attribute from '../telemetry/semantic-conventions.js';
9
+ import { getAbortStreamIdFromToken } from '../util.js';
10
+ import { COMPUTE_INSTANCE_ID } from './compute-instance.js';
11
+ import { getMaxInlineSteps, isBatchTransitionsEnabled, isResilientStepDispatchEnabled, MAX_BATCH_FANOUT_EVENTS, MAX_RESILIENT_STEP_INPUT_BYTES, } from './constants.js';
12
+ import { absorbSkippedSlotReport, appendEventLog, maxEventSlot, queueMessage, queueMessages, runDispatchContext, slotSnapshotParams, stepDispatchIdempotencyKey, } from './helpers.js';
13
+ import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
14
+ import { unserializableStepInputPlaceholder } from './unserializable-step.js';
15
+ async function createHookEvent({ runId, hookEvent, queueItem, requestId, sinceCursor, createEvent, }) {
16
+ try {
17
+ const result = await createEvent(hookEvent, {
18
+ requestId,
19
+ ...(sinceCursor === undefined ? {} : { sinceCursor }),
20
+ });
21
+ // Check if the world returned a hook_conflict event instead of hook_created.
22
+ // The hook_conflict event is stored in the event log and is what the next
23
+ // pass consumes to settle the hook's awaiters — rejecting a payload await,
24
+ // resolving a `hook.getConflict()` with the conflicting run. An inline
25
+ // delta asked for above carries it just as it would have carried the
26
+ // hook_created, so the caller can advance over it without a re-invocation.
27
+ if (result.event?.eventType === 'hook_conflict') {
28
+ return {
29
+ hasHookConflict: true,
30
+ hasAwaitedHookCreation: false,
31
+ };
32
+ }
33
+ return {
34
+ hasHookConflict: false,
35
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
36
+ };
37
+ }
38
+ catch (err) {
39
+ if (EntityConflictError.is(err)) {
40
+ runtimeLogger.info('Hook already exists, continuing', {
41
+ workflowRunId: runId,
42
+ message: err.message,
43
+ });
44
+ return {
45
+ hasHookConflict: false,
46
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
47
+ };
48
+ }
49
+ if (RunExpiredError.is(err)) {
50
+ runtimeLogger.info('Workflow run already completed, skipping hook', {
51
+ workflowRunId: runId,
52
+ message: err.message,
53
+ });
54
+ return {
55
+ hasHookConflict: false,
56
+ hasAwaitedHookCreation: false,
57
+ };
58
+ }
59
+ if (isWorldValidationFailure(err)) {
60
+ const fatal = new FatalError(`createHook failed World validation: ${err instanceof Error ? err.message : String(err)}`);
61
+ fatal.cause = err;
62
+ throw fatal;
63
+ }
64
+ throw err;
65
+ }
66
+ }
9
67
  /**
10
68
  * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
11
- * Creates events for all operations but does NOT queue step messages returns the pending
69
+ * Creates events for all operations but does NOT queue step messages; returns the pending
12
70
  * steps so the caller can decide which to execute inline vs queue to background.
13
71
  *
14
72
  * Processing order:
15
73
  * 1. Hooks are processed first to prevent race conditions with webhook receivers
16
74
  * 2. Step events and wait events are created in parallel
17
75
  */
18
- export async function handleSuspension({ suspension, world, run, span, requestId, }) {
76
+ export async function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, stepDispatch, ownerMessageId, allowDeferredBatchWork, }) {
19
77
  const runId = run.runId;
78
+ // Turbo mode: hold every world write below until the backgrounded
79
+ // `run_started` has *settled*, so we never write a step/hook/wait event for a
80
+ // run that does not exist yet. A no-op outside turbo (barrier undefined) and
81
+ // on the pure inline hot path, which defers all steps and writes nothing.
82
+ // Awaiting the same (usually already-settled) promise more than once is cheap.
83
+ // A barrier rejection is swallowed for ordering only: if `run_started` truly
84
+ // failed the run does not exist, so the subsequent write surfaces the real
85
+ // error (run not found / gone) and the message redelivers.
86
+ const ensureRunReady = async () => {
87
+ if (runReadyBarrier) {
88
+ try {
89
+ await runReadyBarrier;
90
+ }
91
+ catch {
92
+ // intentional: ordering barrier only, see above.
93
+ }
94
+ }
95
+ };
96
+ /**
97
+ * Await every operation in a suspension phase before letting a failure
98
+ * escape, preferring a stale-snapshot (412) rejection when one occurred.
99
+ *
100
+ * `Promise.all` rejects as soon as one operation does and leaves its siblings
101
+ * in flight. That matters for a 412: the caller reacts by reloading the event
102
+ * log and restarting the replay, so a sibling create that lands after the
103
+ * rejection escaped commits an event whose correlation id came from the
104
+ * abandoned replay's seeded sequence (an event the fresh replay never
105
+ * produces), and it races the restart's reload while doing so. Settling first
106
+ * makes this phase's write set final before the caller acts on the failure.
107
+ * It mirrors the runtime's inline step claim, which settles the in-flight
108
+ * step executions before escalating a 412.
109
+ *
110
+ * A 412 is preferred over any other rejection in the same phase because it
111
+ * has a defined, cheap recovery (replay from a corrected log) while the
112
+ * others do not. A deterministic failure such as an attribute-validation
113
+ * `FatalError` recurs on the restart and fails the run then, at the cost of
114
+ * one extra replay.
115
+ */
116
+ const settlePhase = async (ops) => {
117
+ const reasons = (await Promise.allSettled(ops))
118
+ .filter((r) => r.status === 'rejected')
119
+ .map((r) => r.reason);
120
+ if (reasons.length === 0)
121
+ return;
122
+ throw reasons.find((r) => PreconditionFailedError.is(r)) ?? reasons[0];
123
+ };
124
+ // Every suspension write carries replay-recovery telemetry on the first one
125
+ // that commits after replay recovered. All suspension events are
126
+ // non-run_created events on this run's `runId`.
127
+ const reporter = replayRecoveryReporter ?? ReplayRecoveryReporter.inert();
128
+ const createEvent = (data, params) => reporter.withEventCreate(params, (p) => world.events.create(runId, data, p));
129
+ // Adds the optimistic-concurrency guard when the caller supplied a loaded
130
+ // event log; without one it creates directly (callers with no replay
131
+ // snapshot, e.g. tests). A stale (412) rejection propagates to the caller,
132
+ // which restarts the replay from a corrected log. It is not retried here,
133
+ // because the event's correlation id was minted by *this* replay's seeded
134
+ // sequence, so re-committing it against a corrected log would persist an
135
+ // event no correct replay produces.
136
+ let reportedEvents = 0;
137
+ // Writes this suspension issued, and whether one of them handed back a
138
+ // complete inline delta that was folded into the caller's log. Together they
139
+ // answer `eventLogCarriedForward`: the delta covers the log up to the write
140
+ // that returned it, so it accounts for every event this suspension committed
141
+ // only if that write was the only one.
142
+ let guardedWrites = 0;
143
+ let deltaAbsorbed = false;
144
+ const createGuarded = async (data, params) => {
145
+ guardedWrites++;
146
+ if (!eventLog) {
147
+ return createEvent(data, params);
148
+ }
149
+ const log = eventLog;
150
+ const result = await createEvent(data, {
151
+ ...params,
152
+ ...slotSnapshotParams(log.events),
153
+ });
154
+ // An inline delta this call asked for (`sinceCursor`) is everything the
155
+ // log gained since that cursor, this write included, so it is folded onto
156
+ // the tail and carries the cursor with it — unlike a skipped-slot report,
157
+ // which is a window strictly below the write and has to be sorted back
158
+ // into place. A World returns one or the other, never both (the delta is a
159
+ // strict superset), so the two are handled apart rather than merged.
160
+ //
161
+ // Declining is always safe — an unabsorbed delta is one the next read
162
+ // returns — so the guards match the replay loop's `absorbCreateDelta`: a
163
+ // truncated page (`hasMore`) is dropped whole rather than advancing the
164
+ // cursor past events it did not carry, and the log must still be where the
165
+ // request was computed from, since appending does not re-sort.
166
+ if (typeof params?.sinceCursor === 'string') {
167
+ if (log.cursor === params.sinceCursor &&
168
+ result.events !== undefined &&
169
+ result.hasMore !== true) {
170
+ appendEventLog(log, { events: result.events, cursor: result.cursor });
171
+ deltaAbsorbed = true;
172
+ }
173
+ return result;
174
+ }
175
+ // Bump-and-report: the write landed above the slot it asked for, so the
176
+ // report holds the events it was decided without. Absorbing here rather
177
+ // than at each call site means the rest of this phase's writes (which read
178
+ // the same array to build their own snapshot) ask for a slot above them,
179
+ // and the replay that resumes from this log sees them without a reload.
180
+ const report = absorbSkippedSlotReport(log.events, result);
181
+ reportedEvents += report.added;
182
+ if (report.truncated) {
183
+ runtimeLogger.debug('Dropped a truncated skipped-slot report', {
184
+ workflowRunId: runId,
185
+ eventType: data.eventType,
186
+ eventId: result.event?.eventId,
187
+ offered: report.offered,
188
+ });
189
+ }
190
+ else if (report.added > 0) {
191
+ runtimeLogger.debug('Suspension write skipped occupied slots', {
192
+ workflowRunId: runId,
193
+ eventType: data.eventType,
194
+ eventId: result.event?.eventId,
195
+ reported: report.added,
196
+ });
197
+ }
198
+ return result;
199
+ };
20
200
  // Separate queue items by type
21
- const stepItems = suspension.steps.filter((item) => item.type === 'step');
22
- const allHookItems = suspension.steps.filter((item) => item.type === 'hook');
23
- const waitItems = suspension.steps.filter((item) => item.type === 'wait');
24
- // Split hooks by what actions they need
201
+ const stepItems = suspension.items.filter((item) => item.type === 'step');
202
+ const allHookItems = suspension.items.filter((item) => item.type === 'hook');
203
+ const waitItems = suspension.items.filter((item) => item.type === 'wait');
204
+ const attributeItems = suspension.items.filter((item) => item.type === 'attribute');
25
205
  const hooksNeedingCreation = allHookItems.filter((item) => !item.hasCreatedEvent);
26
- const hooksNeedingDisposal = allHookItems.filter((item) => item.disposed);
206
+ // Group hook items that need work by token, preserving queue-insertion
207
+ // (workflow code) order within each token. Operations on one token must
208
+ // apply in code order: a dispose() of an earlier hook releases the token
209
+ // before a later same-token hook's creation is validated (otherwise the
210
+ // new hook records a spurious hook_conflict against the run's own
211
+ // disposed hook), while a hook created and disposed within the same
212
+ // suspension is still created before it is disposed. Different tokens
213
+ // have no claim interaction, so token groups are processed in parallel.
214
+ const hookItemsByToken = new Map();
215
+ for (const item of allHookItems) {
216
+ if (item.hasCreatedEvent && !item.disposed) {
217
+ continue; // already committed and still live: nothing to do
218
+ }
219
+ const group = hookItemsByToken.get(item.token);
220
+ if (group) {
221
+ group.push(item);
222
+ }
223
+ else {
224
+ hookItemsByToken.set(item.token, [item]);
225
+ }
226
+ }
27
227
  // Resolve encryption key for this run
28
228
  const rawKey = await world.getEncryptionKeyForRun?.(run);
29
229
  const encryptionKey = rawKey ? await importKey(rawKey) : undefined;
30
- // Build and process hook_created events (same as V1)
31
- const hookEvents = await Promise.all(hooksNeedingCreation.map(async (queueItem) => {
32
- const hookMetadata = typeof queueItem.metadata === 'undefined'
33
- ? undefined
34
- : (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis));
35
- return {
36
- eventType: 'hook_created',
230
+ // Gate payload compression on the run's specVersion.
231
+ const compression = (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION;
232
+ let serializationBlockerCount = 0;
233
+ const serializationBlockers = [];
234
+ async function dehydrateInput(value, context) {
235
+ const stats = { executions: [] };
236
+ try {
237
+ return (await dehydrateStepArguments(value, runId, encryptionKey, suspension.globalThis, false, compression, stats));
238
+ }
239
+ finally {
240
+ serializationBlockerCount +=
241
+ stats.totalExecutions ?? stats.executions.length;
242
+ serializationBlockers.push(...stats.executions
243
+ .slice(0, GUEST_CODE_EXECUTION_SAMPLE_LIMIT - serializationBlockers.length)
244
+ .map((execution) => ({ ...context, ...execution })));
245
+ }
246
+ }
247
+ async function disposeHook(queueItem) {
248
+ const hookDisposedEvent = {
249
+ eventType: 'hook_disposed',
37
250
  specVersion: SPEC_VERSION_CURRENT,
38
251
  correlationId: queueItem.correlationId,
39
252
  eventData: {
40
253
  token: queueItem.token,
41
- metadata: hookMetadata,
42
- isWebhook: queueItem.isWebhook ?? false,
43
- ...(queueItem.isSystem && { isSystem: true }),
44
254
  },
45
255
  };
46
- }));
47
- // Process hooks first to prevent race conditions with webhook receivers.
48
- // All hook creations run in parallel.
49
- // Track any hook conflicts that occur — these are returned to the caller
50
- // so the V2 handler can re-invoke immediately.
51
- let hasHookConflict = false;
52
- if (hookEvents.length > 0) {
53
- await Promise.all(hookEvents.map(async (hookEvent) => {
54
- try {
55
- const result = await world.events.create(runId, hookEvent, {
56
- requestId,
256
+ try {
257
+ await createGuarded(hookDisposedEvent, { requestId });
258
+ }
259
+ catch (err) {
260
+ if (EntityConflictError.is(err)) {
261
+ // Hook was already disposed by a concurrent invocation, safe to skip
262
+ runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
263
+ workflowRunId: runId,
264
+ correlationId: queueItem.correlationId,
265
+ message: err.message,
57
266
  });
58
- // Check if the world returned a hook_conflict event instead of hook_created.
59
- // The hook_conflict event is stored in the event log and will be replayed
60
- // on the next workflow invocation, causing the hook's promise to reject.
61
- // Note: hook events always create an event (legacy runs throw, not return undefined)
62
- if (result.event.eventType === 'hook_conflict') {
63
- hasHookConflict = true;
64
- }
65
267
  }
66
- catch (err) {
67
- if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
68
- runtimeLogger.info('Workflow run already completed, skipping hook', {
69
- workflowRunId: runId,
70
- message: err.message,
71
- });
72
- }
73
- else {
74
- throw err;
75
- }
268
+ else if (RunExpiredError.is(err)) {
269
+ runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
270
+ workflowRunId: runId,
271
+ correlationId: queueItem.correlationId,
272
+ message: err.message,
273
+ });
76
274
  }
77
- }));
78
- }
79
- // Process hook disposals — these release hook tokens for reuse by other workflows.
80
- if (hooksNeedingDisposal.length > 0) {
81
- await Promise.all(hooksNeedingDisposal.map(async (queueItem) => {
82
- const hookDisposedEvent = {
83
- eventType: 'hook_disposed',
84
- specVersion: SPEC_VERSION_CURRENT,
85
- correlationId: queueItem.correlationId,
86
- };
87
- try {
88
- await world.events.create(runId, hookDisposedEvent, { requestId });
275
+ else if (HookNotFoundError.is(err)) {
276
+ // Hook may have already been disposed or never created
277
+ runtimeLogger.info('Hook not found for disposal, continuing', {
278
+ workflowRunId: runId,
279
+ correlationId: queueItem.correlationId,
280
+ message: err.message,
281
+ });
89
282
  }
90
- catch (err) {
91
- if (EntityConflictError.is(err)) {
92
- // Hook was already disposed by a concurrent invocation — safe to skip
93
- runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
94
- workflowRunId: runId,
95
- correlationId: queueItem.correlationId,
96
- message: err.message,
97
- });
98
- }
99
- else if (RunExpiredError.is(err)) {
100
- runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
101
- workflowRunId: runId,
102
- correlationId: queueItem.correlationId,
103
- message: err.message,
104
- });
105
- }
106
- else if (HookNotFoundError.is(err)) {
107
- // Hook may have already been disposed or never created
108
- runtimeLogger.info('Hook not found for disposal, continuing', {
109
- workflowRunId: runId,
283
+ else {
284
+ throw err;
285
+ }
286
+ }
287
+ }
288
+ // Process hooks first to prevent race conditions with webhook receivers.
289
+ // Track any hook conflicts that occur — these are returned to the caller so
290
+ // it can advance the workflow over the committed `hook_conflict` before
291
+ // anything else this suspension scheduled runs.
292
+ const hookConflictCorrelationIds = [];
293
+ const awaitedHookCorrelationIds = [];
294
+ let hookCreationMs = 0;
295
+ // Ask the hook create for the event-log delta since the cursor the caller's
296
+ // log was read at. The hook's awaiters are settled by the event this write
297
+ // commits and by nothing else — a `hook_created` for a clean registration,
298
+ // a `hook_conflict` when the token was already claimed — so the caller can
299
+ // continue the workflow in its own process on either outcome, but only over
300
+ // a log that holds that event, and this write is the one request that can
301
+ // hand it back together with anything another writer landed in the meantime.
302
+ // Optional by contract: a World that ignores `sinceCursor` returns no delta
303
+ // and the caller reads instead.
304
+ //
305
+ // Asked for on the single-hook suspension only. Two creates issued from one
306
+ // snapshot each diff against the same cursor, and only the first delta back
307
+ // can be folded in (the cursor moves with it), so the log would end up short
308
+ // of the other's event with nothing to say so.
309
+ const hookDeltaCursor = hooksNeedingCreation.length === 1 && typeof eventLog?.cursor === 'string'
310
+ ? eventLog.cursor
311
+ : undefined;
312
+ if (hookItemsByToken.size > 0) {
313
+ const hookPhaseStart = Date.now();
314
+ await ensureRunReady();
315
+ await settlePhase([...hookItemsByToken.values()].map(async (items) => {
316
+ for (const queueItem of items) {
317
+ let creationConflicted = false;
318
+ if (!queueItem.hasCreatedEvent) {
319
+ const hookMetadata = typeof queueItem.metadata === 'undefined'
320
+ ? undefined
321
+ : await dehydrateInput(queueItem.metadata, {
322
+ source: 'hook_metadata',
323
+ correlationId: queueItem.correlationId,
324
+ });
325
+ const hookEvent = {
326
+ eventType: 'hook_created',
327
+ specVersion: SPEC_VERSION_CURRENT,
110
328
  correlationId: queueItem.correlationId,
111
- message: err.message,
329
+ eventData: {
330
+ token: queueItem.token,
331
+ tokenRetentionUntil: queueItem.tokenRetentionUntil,
332
+ metadata: hookMetadata,
333
+ isWebhook: queueItem.isWebhook ?? false,
334
+ ...(queueItem.isSystem && { isSystem: true }),
335
+ },
336
+ };
337
+ const result = await createHookEvent({
338
+ runId,
339
+ hookEvent,
340
+ queueItem,
341
+ requestId,
342
+ sinceCursor: hookDeltaCursor,
343
+ createEvent: createGuarded,
112
344
  });
345
+ if (result.hasHookConflict) {
346
+ hookConflictCorrelationIds.push(queueItem.correlationId);
347
+ }
348
+ if (result.hasAwaitedHookCreation) {
349
+ awaitedHookCorrelationIds.push(queueItem.correlationId);
350
+ }
351
+ creationConflicted = result.hasHookConflict;
113
352
  }
114
- else {
115
- throw err;
353
+ // Dispose after creation for hooks born and disposed within this
354
+ // batch. A hook whose creation conflicted was never created, so
355
+ // there is nothing to dispose.
356
+ if (queueItem.disposed && !creationConflicted) {
357
+ await disposeHook(queueItem);
116
358
  }
117
359
  }
118
360
  }));
361
+ hookCreationMs = Date.now() - hookPhaseStart;
119
362
  }
120
- // Process abort requests resume the hook with abort payload and write stream packet
363
+ // Process abort requests: resume the hook with abort payload and write stream packet
121
364
  const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
122
365
  if (hooksNeedingAbort.length > 0) {
123
- await Promise.all(hooksNeedingAbort.map(async (queueItem) => {
366
+ await ensureRunReady();
367
+ await settlePhase(hooksNeedingAbort.map(async (queueItem) => {
124
368
  try {
125
369
  // Dehydrate the abort payload for storage
126
- const abortPayload = await dehydrateStepArguments({ aborted: true, reason: queueItem.abortReason }, runId, encryptionKey, suspension.globalThis);
370
+ const abortPayload = await dehydrateInput({
371
+ aborted: true,
372
+ reason: queueItem.abortReason,
373
+ }, {
374
+ source: 'hook_abort',
375
+ correlationId: queueItem.correlationId,
376
+ });
127
377
  // Create hook_received event with abort payload
128
- await world.events.create(runId, {
378
+ await createGuarded({
129
379
  eventType: 'hook_received',
130
380
  specVersion: SPEC_VERSION_CURRENT,
131
381
  correlationId: queueItem.correlationId,
132
382
  eventData: {
383
+ token: queueItem.token,
133
384
  payload: abortPayload,
134
385
  },
135
386
  });
@@ -146,7 +397,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
146
397
  await world.streams.close(runId, streamName);
147
398
  }
148
399
  catch {
149
- // Best-effort stream write hook event provides the durable fallback
400
+ // Best-effort stream write: hook event provides the durable fallback
150
401
  runtimeLogger.debug('Failed to write abort stream packet, hook event will provide fallback', {
151
402
  workflowRunId: runId,
152
403
  correlationId: queueItem.correlationId,
@@ -168,7 +419,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
168
419
  }));
169
420
  }
170
421
  // Create step events for steps that don't have them yet.
171
- // Unlike V1, we do NOT queue step messages from here the caller
422
+ // Unlike V1, we do NOT queue step messages from here: the caller
172
423
  // decides which steps to execute inline vs. queue to background.
173
424
  // Wait events are also created in parallel below.
174
425
  const stepsNeedingCreation = new Set(stepItems
@@ -176,30 +427,422 @@ export async function handleSuspension({ suspension, world, run, span, requestId
176
427
  .map((queueItem) => queueItem.correlationId));
177
428
  // Correlation IDs for which THIS suspension call actually wrote the
178
429
  // step_created event. Populated by the ops below after a successful
179
- // events.create used by the caller to claim ownership and avoid
430
+ // events.create, used by the caller to claim ownership and avoid
180
431
  // racing with concurrent handlers on step execution.
181
432
  const createdStepCorrelationIds = new Set();
433
+ // Correlation IDs of steps finalized as failed because their arguments
434
+ // refused to serialize: see finalizeUnserializableStep below.
435
+ const failedStepCorrelationIds = new Set();
436
+ /**
437
+ * A step whose arguments fail to serialize is deterministic: every replay
438
+ * re-derives the same unserializable value, so redelivering the
439
+ * orchestrator message can never succeed. Instead of rejecting the whole
440
+ * suspension (which fails the run from the outside, where no user code can
441
+ * observe it), treat it exactly like a step-body failure: write
442
+ * `step_created` with a placeholder input (every World requires the step
443
+ * entity to exist before a terminal step event, and the real input is
444
+ * precisely what refused to serialize) followed by `step_failed` carrying
445
+ * the SerializationError. The next replay rejects the step's promise with
446
+ * it, so a try/catch around the step call observes the error; uncaught, it
447
+ * propagates out of the workflow body and fails the run as a USER_ERROR,
448
+ * without burning queue redeliveries either way.
449
+ */
450
+ const finalizeUnserializableStep = async (queueItem, error) => {
451
+ runtimeLogger.warn('Step arguments failed to serialize; failing the step so the ' +
452
+ 'workflow can observe the error', {
453
+ workflowRunId: runId,
454
+ correlationId: queueItem.correlationId,
455
+ stepName: queueItem.stepName,
456
+ error: error.message,
457
+ });
458
+ await ensureRunReady();
459
+ // Marker placeholder (not empty args): byte-identical-to-zero-args would
460
+ // make `workflow inspect steps` show "no arguments" for the one step
461
+ // whose entire problem was its arguments.
462
+ const placeholderInput = (await dehydrateStepArguments(unserializableStepInputPlaceholder(), runId, encryptionKey, suspension.globalThis, false, compression));
463
+ try {
464
+ await createGuarded({
465
+ eventType: 'step_created',
466
+ specVersion: SPEC_VERSION_CURRENT,
467
+ correlationId: queueItem.correlationId,
468
+ eventData: {
469
+ stepName: queueItem.stepName,
470
+ workflowName: run.workflowName,
471
+ input: placeholderInput,
472
+ },
473
+ }, { requestId });
474
+ }
475
+ catch (createErr) {
476
+ if (EntityConflictError.is(createErr)) {
477
+ // A concurrent handler already created the step: the failure is
478
+ // deterministic, so it is racing toward the same step_failed below.
479
+ runtimeLogger.info('Step already exists, continuing', {
480
+ workflowRunId: runId,
481
+ correlationId: queueItem.correlationId,
482
+ message: createErr.message,
483
+ });
484
+ }
485
+ else if (RunExpiredError.is(createErr)) {
486
+ // Run already finished: nothing to observe the failure.
487
+ return;
488
+ }
489
+ else {
490
+ throw createErr;
491
+ }
492
+ }
493
+ try {
494
+ await createGuarded({
495
+ eventType: 'step_failed',
496
+ specVersion: SPEC_VERSION_CURRENT,
497
+ correlationId: queueItem.correlationId,
498
+ eventData: {
499
+ stepName: queueItem.stepName,
500
+ // The error itself is a plain WorkflowError (name, message with
501
+ // framed hint, cause chain), serializable even though the step
502
+ // input was not. Error detection is realm-independent
503
+ // (types.isNativeError), so the host-created error serializes
504
+ // the same under either global; the VM global is passed for
505
+ // consistency with every other dehydration in this file and so
506
+ // any VM-realm values guest code threw into the cause chain
507
+ // (getters/proxies executed during the failed dehydration) are
508
+ // detected by the realm-sensitive reducers.
509
+ error: await dehydrateStepError(error, runId, encryptionKey, [], suspension.globalThis, compression),
510
+ },
511
+ }, { requestId });
512
+ }
513
+ catch (failErr) {
514
+ if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
515
+ // Step already terminal (a concurrent handler wrote the same
516
+ // deterministic failure) or the run already finished.
517
+ runtimeLogger.info('Tried failing step, but step or run has already finished.', {
518
+ workflowRunId: runId,
519
+ correlationId: queueItem.correlationId,
520
+ message: failErr.message,
521
+ });
522
+ }
523
+ else {
524
+ throw failErr;
525
+ }
526
+ }
527
+ failedStepCorrelationIds.add(queueItem.correlationId);
528
+ // Release the inline slot bookkeeping: the step never runs, so it must
529
+ // not appear in the rebuilt `lazyInlineSteps`. (Its slot in the first-N
530
+ // selection and in `inlinePairFoldEligible`'s count was consumed
531
+ // before dehydration could reveal the failure, inherent to selecting
532
+ // before serializing, and bounded to one wasted slot on a pass that
533
+ // ends in a forced replay anyway.)
534
+ lazyInlineCorrelationIds.delete(queueItem.correlationId);
535
+ };
536
+ // Lazy inline start: defer the step_created write for up to
537
+ // `getMaxInlineSteps()` steps the caller will run inline (in parallel). Each
538
+ // step is created on the fly by the lazy `step_started` executeStep sends
539
+ // (saving a round-trip per step). We never defer when a `hook.getConflict()`
540
+ // awaiter is present, because in that case the caller executes nothing inline
541
+ // (it continues the workflow to resolve the awaiter instead), so deferring
542
+ // would leave the steps uncreated and unqueued. We pick the first N uncreated
543
+ // steps — matching the caller's inline-candidate selection — and dehydrate
544
+ // their input here so executeStep can ship it as the step_started payload.
545
+ const lazyInlineCorrelationIds = new Set(awaitedHookCorrelationIds.length === 0
546
+ ? stepItems
547
+ .filter((item) => stepsNeedingCreation.has(item.correlationId))
548
+ .slice(0, getMaxInlineSteps())
549
+ .map((item) => item.correlationId)
550
+ : []);
551
+ // Collected by correlationId because the per-step ops below run concurrently
552
+ // and settle out of order. We rebuild the array in deterministic
553
+ // `lazyInlineCorrelationIds` order (the ordered slice above) after the ops
554
+ // settle, so the inline batch order is stable regardless of dehydration timing.
555
+ const lazyInlineByCorrelationId = new Map();
182
556
  const ops = [];
183
- // Steps: create step_created events (no queuing V2 returns pending steps to caller)
557
+ // Correlation IDs of steps whose step-execution queue message was already
558
+ // published by the resilient-dispatch ops below (alongside the step_created
559
+ // write). Reported to the caller so its dispatch pass skips them.
560
+ const queuedStepCorrelationIds = new Set();
561
+ // Resilient step dispatch eligibility, shared by every step op below (the
562
+ // per-step input-size check is applied inside the op). All must hold:
563
+ //
564
+ // - The caller provided a dispatch target (`stepDispatch`): terminal
565
+ // drains and other create-only callers never queue.
566
+ // - The feature is enabled (`WORKFLOW_RESILIENT_STEP_DISPATCH` opt-in).
567
+ // It is off by default because the publish races the create's verdict,
568
+ // and a create can come back refused: as a duplicate the replay should
569
+ // stop pursuing, or (on a World that would rather refuse a stale write
570
+ // than report what it missed) as a 412. Either way the queue message
571
+ // carrying the payload is already out, and the consumer can materialize a
572
+ // step whose create was refused. Nothing orders that verdict before the
573
+ // consumer's redelivery re-ensure, so no backend-side revocation
574
+ // bookkeeping can close the window: a best-effort marker that fails open
575
+ // cannot carry a correctness property. The sequential path is the only
576
+ // thing that gives the message a happens-after edge over the verdict.
577
+ // - The run's queue transport preserves binary payloads (CBOR,
578
+ // specVersion >= 3): `stepInput.input` is the serialized (possibly
579
+ // encrypted) input bytes, which the JSON transport would mangle.
580
+ const resilientDispatchEligible = stepDispatch !== undefined &&
581
+ isResilientStepDispatchEnabled() &&
582
+ (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT;
583
+ // Batched fan-out: fold this suspension's step_created + wait_created
584
+ // writes into one `events.createBatch` call (one durable write, per-event
585
+ // outcomes) instead of one write per event. Engages only for a CLEAN
586
+ // fan-out (no attribute writes, no hook writes, no resilient dispatch
587
+ // whose creates are each paired with a queue publish) on a World that
588
+ // implements the optional method and a run whose events are slot-numbered.
589
+ // Everything outside the gate keeps the single-event path byte-for-byte.
590
+ const batchFanoutEligible = isBatchTransitionsEnabled() &&
591
+ typeof world.events.createBatch === 'function' &&
592
+ (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_SLOT_IDENTITY &&
593
+ !resilientDispatchEligible &&
594
+ allHookItems.length === 0 &&
595
+ attributeItems.length === 0;
596
+ /**
597
+ * The fold's collection, in scheduling order (steps in stepItems order,
598
+ * then waits). Step entries are enqueued by their prep promises (input
599
+ * dehydration runs concurrently, so entries are ordered by `order`, not by
600
+ * completion); the single flush op below awaits every prep, sorts, and
601
+ * commits the whole set through `createBatch`.
602
+ */
603
+ const batchQueue = [];
604
+ const batchPreps = [];
605
+ // Pre-claimed inline pairs: fold each lazy-inline step's deferred
606
+ // `step_created` (carrying its input) AND its `step_started` claim (bare,
607
+ // ownership-stamped) into the batch, so the inline steps' claims commit in
608
+ // one durable write (the pair chunk, see the flush below) and the caller
609
+ // starts the bodies straight off that commit instead of posting one claim
610
+ // per inline step. Requires TWO or more inline steps, and nothing else:
611
+ // the pairs commit in a chunk of their own, so plain creates alongside
612
+ // them share no round trip with the pairs and cannot make a lone pair
613
+ // worth folding. A lone inline step is better served by the lazy
614
+ // `step_started`: one row instead of two, optimistic-start capable (the
615
+ // claim overlaps the body), with the slot-snapshot params and
616
+ // bump-and-report `createGuarded` provides, all of which a pair-only
617
+ // batch of one pair gives up for the same round trip. Two or more inline
618
+ // steps become ONE pair chunk instead of N parallel lazy claims, which is
619
+ // the saving. A lone inline step alongside eager creates therefore takes
620
+ // the lazy path while the creates still batch. Also requires the caller's
621
+ // `ownerMessageId`: the started row must stamp ownership exactly like the
622
+ // lazy claim it replaces (and a caller that does not inline-execute never
623
+ // provides one).
624
+ const inlinePairFoldEligible = batchFanoutEligible &&
625
+ ownerMessageId !== undefined &&
626
+ lazyInlineCorrelationIds.size >= 2;
627
+ const inlineClaims = new Map();
628
+ // The trace carrier for resilient step dispatches, resolved at most once per
629
+ // suspension (the per-step ops run concurrently and share it).
630
+ let stepDispatchTraceCarrier;
631
+ const getStepDispatchTraceCarrier = () => {
632
+ stepDispatchTraceCarrier ??=
633
+ stepDispatch?.getTraceCarrier() ?? Promise.resolve({});
634
+ return stepDispatchTraceCarrier;
635
+ };
636
+ // Producer-side resilient recovery count for the suspension span attribute.
637
+ let resilientDispatchRecovered = 0;
638
+ // Steps: create step_created events (no queuing, V2 returns pending steps
639
+ // to caller, EXCEPT on the resilient dispatch path, which parallelizes the
640
+ // create with the step's queue publish and reports it in
641
+ // `queuedStepCorrelationIds`).
642
+ let batchOrderCounter = 0;
184
643
  for (const queueItem of stepItems) {
185
644
  if (stepsNeedingCreation.has(queueItem.correlationId)) {
186
- ops.push((async () => {
187
- const dehydratedInput = await dehydrateStepArguments({
188
- args: queueItem.args,
189
- closureVars: queueItem.closureVars,
190
- thisVal: queueItem.thisVal,
191
- }, runId, encryptionKey, suspension.globalThis);
645
+ // Deterministic position in the batched fold (assigned in stepItems
646
+ // order, before the concurrent dehydration runs). A pair-folded inline
647
+ // step occupies two consecutive positions (created row then started
648
+ // row), which the flush keeps adjacent, never splits across chunks,
649
+ // and commits in a pair-only chunk ahead of the plain creates, so a
650
+ // World can fold them into one born-running create.
651
+ const pairFolded = inlinePairFoldEligible &&
652
+ lazyInlineCorrelationIds.has(queueItem.correlationId);
653
+ const stepOrder = batchOrderCounter;
654
+ batchOrderCounter += pairFolded ? 2 : 1;
655
+ const stepOp = (async () => {
656
+ let dehydratedInput;
657
+ try {
658
+ dehydratedInput = await dehydrateInput({
659
+ args: queueItem.args,
660
+ closureVars: queueItem.closureVars,
661
+ thisVal: queueItem.thisVal,
662
+ }, {
663
+ source: 'step_input',
664
+ correlationId: queueItem.correlationId,
665
+ });
666
+ }
667
+ catch (err) {
668
+ if (!SerializationError.is(err)) {
669
+ // e.g. RuntimeDecryptionError: an SDK fault, not a user value
670
+ // problem. Keep its identity (RUNTIME_ERROR) and current
671
+ // fail-the-suspension behavior.
672
+ throw err;
673
+ }
674
+ if (!stepDispatch) {
675
+ // No dispatch target means no replay will observe a
676
+ // finalization: this is the terminal drain (or a create-only
677
+ // test caller). The run is already completing/failing, so
678
+ // writing step_created + step_failed here would leave e.g. a
679
+ // COMPLETED run carrying a failed step nothing can ever
680
+ // observe, reading as a bug from the dashboard. Rethrow
681
+ // instead; the drain's own catch swallows it, preserving its
682
+ // pre-existing behavior (no rows for the unawaited step).
683
+ throw err;
684
+ }
685
+ await finalizeUnserializableStep(queueItem, err);
686
+ return;
687
+ }
688
+ // Deferred (lazy) inline step: skip the step_created write — the
689
+ // caller's inline executeStep will send a lazy step_started carrying
690
+ // this input, and the world creates the step (entity + synthetic
691
+ // step_created event) atomically. We do NOT add it to
692
+ // createdStepCorrelationIds; ownership is decided by that lazy
693
+ // step_started's atomic create-claim instead.
694
+ if (lazyInlineCorrelationIds.has(queueItem.correlationId)) {
695
+ lazyInlineByCorrelationId.set(queueItem.correlationId, {
696
+ correlationId: queueItem.correlationId,
697
+ stepName: queueItem.stepName,
698
+ dehydratedInput,
699
+ });
700
+ if (pairFolded) {
701
+ // Enqueue the pair the deferral would otherwise leave to the
702
+ // caller's lazy `step_started`: the created row carries the
703
+ // input (payloads ride creates in a batch), the started row is
704
+ // bare and stamps this invocation's ownership, the same claim
705
+ // shape the lazy start would have sent, settled by the batch.
706
+ batchQueue.push({
707
+ order: stepOrder,
708
+ kind: 'inline-created',
709
+ correlationId: queueItem.correlationId,
710
+ event: {
711
+ eventType: 'step_created',
712
+ specVersion: SPEC_VERSION_CURRENT,
713
+ correlationId: queueItem.correlationId,
714
+ eventData: {
715
+ stepName: queueItem.stepName,
716
+ workflowName: run.workflowName,
717
+ input: dehydratedInput,
718
+ },
719
+ },
720
+ });
721
+ batchQueue.push({
722
+ order: stepOrder + 1,
723
+ kind: 'inline-started',
724
+ correlationId: queueItem.correlationId,
725
+ event: {
726
+ eventType: 'step_started',
727
+ specVersion: SPEC_VERSION_CURRENT,
728
+ correlationId: queueItem.correlationId,
729
+ eventData: {
730
+ stepName: queueItem.stepName,
731
+ // Checked by inlinePairFoldEligible; spread keeps the
732
+ // narrow-through-closure problem away from the type.
733
+ ...(ownerMessageId !== undefined ? { ownerMessageId } : {}),
734
+ },
735
+ },
736
+ });
737
+ }
738
+ return;
739
+ }
192
740
  const stepEvent = {
193
741
  eventType: 'step_created',
194
742
  specVersion: SPEC_VERSION_CURRENT,
195
743
  correlationId: queueItem.correlationId,
196
744
  eventData: {
197
745
  stepName: queueItem.stepName,
746
+ workflowName: run.workflowName,
198
747
  input: dehydratedInput,
199
748
  },
200
749
  };
750
+ // Resilient step dispatch: fire the step_created write and the
751
+ // step-execution queue publish in parallel: the message carries the
752
+ // same serialized input (`stepInput`) so the consumer can
753
+ // idempotently re-ensure the event if the direct write failed
754
+ // transiently. Mirrors the resilient start (`runInput`) and
755
+ // resilient hook resume (`hookInput`) patterns. Only for inputs the
756
+ // queue message can safely carry (binary, under the VQS size cap).
757
+ if (resilientDispatchEligible &&
758
+ dehydratedInput instanceof Uint8Array &&
759
+ dehydratedInput.byteLength <= MAX_RESILIENT_STEP_INPUT_BYTES) {
760
+ await ensureRunReady();
761
+ const traceCarrier = await getStepDispatchTraceCarrier();
762
+ const [createResult, queueResult] = await Promise.allSettled([
763
+ createGuarded(stepEvent, { requestId }),
764
+ queueMessage(world,
765
+ // biome-ignore lint/style/noNonNullAssertion: implied by resilientDispatchEligible
766
+ stepDispatch.queueName, {
767
+ runId,
768
+ stepId: queueItem.correlationId,
769
+ stepName: queueItem.stepName,
770
+ traceCarrier,
771
+ requestedAt: new Date(),
772
+ stepInput: { input: dehydratedInput },
773
+ runContext: runDispatchContext(run),
774
+ },
775
+ // Same key as the caller's dispatch pass and any concurrent
776
+ // handler's, so redundant publishes for this step dedupe. The
777
+ // key is step-identity-scoped so a revoked message for a
778
+ // reassigned correlation id cannot absorb the corrected
779
+ // schedule's dispatch: see stepDispatchIdempotencyKey.
780
+ {
781
+ idempotencyKey: stepDispatchIdempotencyKey(queueItem.correlationId, queueItem.stepName),
782
+ }),
783
+ ]);
784
+ // Queue failure is always fatal for this suspension pass: without
785
+ // the message the step would rely on the create alone, and if the
786
+ // create ALSO failed there would be no durable record at all.
787
+ // Propagating redelivers the orchestrator message, which
788
+ // re-creates the (idempotent) step_created and re-dispatches,
789
+ // the same recovery as the sequential path.
790
+ if (queueResult.status === 'rejected') {
791
+ throw queueResult.reason;
792
+ }
793
+ queuedStepCorrelationIds.add(queueItem.correlationId);
794
+ if (createResult.status === 'rejected') {
795
+ const err = createResult.reason;
796
+ if (EntityConflictError.is(err)) {
797
+ // Concurrent handler wrote it first, same as the sequential
798
+ // path. The step message is already out; a duplicate publish
799
+ // by that handler dedupes on the shared idempotency key.
800
+ runtimeLogger.info('Step already exists, continuing', {
801
+ workflowRunId: runId,
802
+ correlationId: queueItem.correlationId,
803
+ message: err.message,
804
+ });
805
+ }
806
+ else if (isRetryableWorldError(err)) {
807
+ // Resilient: the write failed transiently (429 / 5xx /
808
+ // transport) but the step message (carrying the same
809
+ // serialized input) was published, so the consumer
810
+ // idempotently re-ensures the step_created before executing.
811
+ resilientDispatchRecovered++;
812
+ runtimeLogger.warn('Step creation event write failed, but the step was ' +
813
+ 'dispatched via the queue. The step_created event will ' +
814
+ 'be ensured by the queue consumer.', {
815
+ workflowRunId: runId,
816
+ correlationId: queueItem.correlationId,
817
+ stepName: queueItem.stepName,
818
+ error: err instanceof Error ? err.message : String(err),
819
+ });
820
+ }
821
+ else {
822
+ throw err;
823
+ }
824
+ }
825
+ else {
826
+ createdStepCorrelationIds.add(queueItem.correlationId);
827
+ }
828
+ return;
829
+ }
830
+ if (batchFanoutEligible) {
831
+ // Fold into the batch instead of writing here. The enclosing
832
+ // promise joins `batchPreps` (see the loop below), so the flush
833
+ // op cannot run before this step's input finished dehydrating.
834
+ batchQueue.push({
835
+ order: stepOrder,
836
+ kind: 'step',
837
+ correlationId: queueItem.correlationId,
838
+ stepName: queueItem.stepName,
839
+ event: stepEvent,
840
+ });
841
+ return;
842
+ }
201
843
  try {
202
- await world.events.create(runId, stepEvent, { requestId });
844
+ await ensureRunReady();
845
+ await createGuarded(stepEvent, { requestId });
203
846
  createdStepCorrelationIds.add(queueItem.correlationId);
204
847
  }
205
848
  catch (err) {
@@ -214,23 +857,44 @@ export async function handleSuspension({ suspension, world, run, span, requestId
214
857
  throw err;
215
858
  }
216
859
  }
217
- })());
860
+ })();
861
+ ops.push(stepOp);
862
+ if (batchFanoutEligible) {
863
+ // The flush op waits for every prep before committing; a prep that
864
+ // rejected already surfaces through `ops`, so the flush's own wait
865
+ // swallows it and commits whatever was successfully enqueued,
866
+ // preserving today's per-op independence.
867
+ batchPreps.push(stepOp.catch(() => { }));
868
+ }
218
869
  }
219
870
  }
220
871
  // Create wait events (same as V1)
221
872
  for (const queueItem of waitItems) {
222
873
  if (!queueItem.hasCreatedEvent) {
223
- ops.push((async () => {
224
- const waitEvent = {
225
- eventType: 'wait_created',
226
- specVersion: SPEC_VERSION_CURRENT,
874
+ const waitEvent = {
875
+ eventType: 'wait_created',
876
+ specVersion: SPEC_VERSION_CURRENT,
877
+ correlationId: queueItem.correlationId,
878
+ eventData: {
879
+ resumeAt: queueItem.resumeAt,
880
+ },
881
+ };
882
+ if (batchFanoutEligible) {
883
+ // Waits need no dehydration, so they enqueue synchronously, after
884
+ // every step's order slot, preserving steps-then-waits scheduling
885
+ // order in the log.
886
+ batchQueue.push({
887
+ order: batchOrderCounter++,
888
+ kind: 'wait',
227
889
  correlationId: queueItem.correlationId,
228
- eventData: {
229
- resumeAt: queueItem.resumeAt,
230
- },
231
- };
890
+ event: waitEvent,
891
+ });
892
+ continue;
893
+ }
894
+ ops.push((async () => {
232
895
  try {
233
- await world.events.create(runId, waitEvent, { requestId });
896
+ await ensureRunReady();
897
+ await createGuarded(waitEvent, { requestId });
234
898
  }
235
899
  catch (err) {
236
900
  if (EntityConflictError.is(err)) {
@@ -247,33 +911,548 @@ export async function handleSuspension({ suspension, world, run, span, requestId
247
911
  })());
248
912
  }
249
913
  }
250
- waitUntil(Promise.all(ops).catch((opErr) => {
251
- const isAbortError = opErr?.name === 'AbortError' || opErr?.name === 'ResponseAborted';
252
- if (!isAbortError)
253
- throw opErr;
254
- }));
255
- await Promise.all(ops);
256
- // Calculate minimum timeout from waits
914
+ // The batched fold's flush: the clean fan-out commits through
915
+ // `createBatch` in chunks of MAX_BATCH_FANOUT_EVENTS, all chunks IN
916
+ // FLIGHT CONCURRENTLY. Slot assignment is the server's, so parallel
917
+ // chunks race for slot ranges exactly like the pre-fold path's parallel
918
+ // single writes did; entity conditions, not commit order, carry
919
+ // correctness (sibling fan-out events have no cross-order the replay
920
+ // depends on; it matches by correlation id). Each event reports the
921
+ // outcome its own single create would have had: a 409 is the same
922
+ // already-exists tolerance as the single path, anything else fails the
923
+ // delivery the way a single-path rejection would.
924
+ //
925
+ // Latency shape: only the chunk carrying the pre-claimed inline pairs
926
+ // gates the handler's return (the caller starts bodies off its claims),
927
+ // and that chunk carries NOTHING else, so its commit is as small as the
928
+ // inline slice (see the chunking below).
929
+ // Every other chunk's commit (and every chunk's step-message publishes,
930
+ // which fire the moment ITS creates are durable) rides
931
+ // `deferredBatchWork` when the caller opted in, joined before ack. A slow
932
+ // sibling chunk therefore delays neither the inline bodies nor another
933
+ // chunk's queue messages, while publish-after-create still holds per
934
+ // step: a step's message is only ever sent after the chunk carrying its
935
+ // create has committed.
936
+ let deferredBatchWork;
937
+ if (batchFanoutEligible) {
938
+ ops.push((async () => {
939
+ // Preps that rejected already surface through their own `ops`
940
+ // entries; the fold commits whatever was successfully enqueued,
941
+ // preserving today's per-op independence.
942
+ await Promise.all(batchPreps);
943
+ if (batchQueue.length === 0) {
944
+ return;
945
+ }
946
+ const entries = [...batchQueue].sort((a, b) => a.order - b.order);
947
+ await ensureRunReady();
948
+ // The ordinary single path for a lone plain entry: a batch of ONE
949
+ // gains nothing over the single write (same round trip) and loses
950
+ // the slot-snapshot params + bump-and-report that createGuarded
951
+ // provides, so a lone eager event is written the way it would have
952
+ // been without the fold, with the same conflict tolerance and
953
+ // ownership bookkeeping. Used when the whole fold is one entry
954
+ // (below) and when the plain partition beside the pairs is one
955
+ // entry (the chunking further down). Beside a pair chunk it commits
956
+ // concurrently with the handler's return, like a trailing chunk; the
957
+ // inline bodies do not depend on it (executor writes carry no slot
958
+ // snapshot, so there is no position for it to move).
959
+ const commitSingle = async (entry) => {
960
+ try {
961
+ await createGuarded(entry.event, { requestId });
962
+ if (entry.kind === 'step') {
963
+ createdStepCorrelationIds.add(entry.correlationId);
964
+ }
965
+ }
966
+ catch (err) {
967
+ if (EntityConflictError.is(err)) {
968
+ runtimeLogger.info(entry.kind === 'step'
969
+ ? 'Step already exists, continuing'
970
+ : 'Wait already exists, continuing', {
971
+ workflowRunId: runId,
972
+ correlationId: entry.correlationId,
973
+ message: err.message,
974
+ });
975
+ }
976
+ else {
977
+ throw err;
978
+ }
979
+ }
980
+ };
981
+ if (entries.length === 1) {
982
+ await commitSingle(entries[0]);
983
+ return;
984
+ }
985
+ // Seed for the foreign-interleaving diagnostic below. With chunks
986
+ // committing in parallel there is no per-chunk "expected next slot";
987
+ // the whole fold's committed span is compared against the seed
988
+ // once every chunk has settled: committed slots are dense per the
989
+ // World's invariant, so any excess of (max committed slot − seed +
990
+ // 1) over the fold's own committed count is events OTHER writers
991
+ // landed in between.
992
+ const expectedFirstSlot = eventLog
993
+ ? (maxEventSlot(eventLog.events) ?? 0) + 1
994
+ : undefined;
995
+ // Pair-aware chunking. Two rules:
996
+ //
997
+ // 1. A pre-claimed pair's two rows must land in the same createBatch
998
+ // call (adjacent, so a World can fold them into one born-running
999
+ // create) and never straddle a chunk boundary, which would turn
1000
+ // the started row into a standalone claim racing its own
1001
+ // create's commit.
1002
+ // 2. The pairs commit in chunk(s) of THEIR OWN, ahead of the plain
1003
+ // `step`/`wait` creates, which fill the subsequent chunks. The
1004
+ // pair chunk is the one commit the inline bodies wait for (see
1005
+ // `pairCommits` below), and on the Vercel backend its latency
1006
+ // scales with the transaction's item count: measured on 32-branch
1007
+ // fan-outs, batches of <=8 events commit in ~56 ms p50 server-side
1008
+ // where batches of 24-32 events take ~110 ms. Padding the pair
1009
+ // chunk with plain creates up to the cap therefore held the
1010
+ // bodies for the plain creates' commit, which nothing else
1011
+ // needed: a plain create gates only its own queue publish, and
1012
+ // that fires off whichever sibling chunk carries it. Splitting
1013
+ // them keeps the pair chunk small (two rows per inline step) and
1014
+ // lets the plain creates commit concurrently beside it.
1015
+ const chunkEntries = (list) => {
1016
+ const out = [];
1017
+ let current = [];
1018
+ for (let index = 0; index < list.length; index++) {
1019
+ const entry = list[index];
1020
+ const next = list[index + 1];
1021
+ const pairLead = entry.kind === 'inline-created' &&
1022
+ next?.kind === 'inline-started' &&
1023
+ next.correlationId === entry.correlationId;
1024
+ const take = pairLead ? 2 : 1;
1025
+ if (current.length > 0 &&
1026
+ current.length + take > MAX_BATCH_FANOUT_EVENTS) {
1027
+ out.push(current);
1028
+ current = [];
1029
+ }
1030
+ current.push(entry);
1031
+ if (pairLead) {
1032
+ current.push(next);
1033
+ index++;
1034
+ }
1035
+ }
1036
+ if (current.length > 0)
1037
+ out.push(current);
1038
+ return out;
1039
+ };
1040
+ // Both partitions keep `entries`' order, so a pair's two rows
1041
+ // (consecutive `order` values, enqueued together) stay adjacent in
1042
+ // the pair partition.
1043
+ const isPairRow = (entry) => entry.kind === 'inline-created' || entry.kind === 'inline-started';
1044
+ const pairChunks = chunkEntries(entries.filter((entry) => isPairRow(entry)));
1045
+ const plainEntries = entries.filter((entry) => !isPairRow(entry));
1046
+ // A plain partition of exactly ONE entry is the batch-of-one case
1047
+ // again, now that the pairs no longer share its chunk: it takes the
1048
+ // single path (`commitSingle`) rather than a one-row createBatch,
1049
+ // and is carried as a one-entry chunk so the per-chunk publish and
1050
+ // settle machinery below treats it like any sibling. (A one-row
1051
+ // remainder of a LARGER plain partition still batches: it is the
1052
+ // pre-split behavior, unchanged here.)
1053
+ const plainChunks = plainEntries.length === 1
1054
+ ? [plainEntries]
1055
+ : chunkEntries(plainEntries);
1056
+ const singleChunk = plainEntries.length === 1 ? plainChunks[0] : undefined;
1057
+ const chunks = [...pairChunks, ...plainChunks];
1058
+ // Steps whose queue messages THIS FLUSH will publish (the eager
1059
+ // creates), recorded before any chunk settles so the caller's
1060
+ // dispatch pass (which runs off the handler's return) skips them.
1061
+ // The sends are guaranteed-or-failed by the trailing work the
1062
+ // caller joins before acking, so "will be published by this flush"
1063
+ // and "already published" are equivalent from the caller's side.
1064
+ const publishEagerSteps = stepDispatch !== undefined;
1065
+ if (publishEagerSteps) {
1066
+ for (const entry of entries) {
1067
+ if (entry.kind === 'step') {
1068
+ queuedStepCorrelationIds.add(entry.correlationId);
1069
+ }
1070
+ }
1071
+ }
1072
+ // Tallies for the foreign-interleaving diagnostic, folded across
1073
+ // the concurrent chunks and read once all of them settled.
1074
+ let committedCount = 0;
1075
+ let maxCommittedSlot;
1076
+ const commitChunk = async (chunk) => {
1077
+ // Anchors for the pre-claimed steps' telemetry: the POST instant
1078
+ // is the claim's "start POST sent" (RSFS's end), the return is the
1079
+ // claim's completion (TTR's T6), the same two instants the lazy
1080
+ // claim's own POST would have produced.
1081
+ const batchPostSentAtMs = Date.now();
1082
+ // biome-ignore lint/style/noNonNullAssertion: batchFanoutEligible implies presence
1083
+ const { results } = await world.events.createBatch(runId, chunk.map((entry) => ({
1084
+ event: entry.event,
1085
+ // The started row is the step's executing claim, so it carries
1086
+ // the compute-instance attribution the single claim sends via
1087
+ // CreateEventParams.
1088
+ ...(entry.kind === 'inline-started'
1089
+ ? { computeInstanceId: COMPUTE_INSTANCE_ID }
1090
+ : {}),
1091
+ })),
1092
+ // Per-write request attribution, same as the single path's
1093
+ // createGuarded(…, { requestId }).
1094
+ { requestId });
1095
+ const claimCompletedAtMs = Date.now();
1096
+ for (const [index, item] of results.entries()) {
1097
+ const entry = chunk[index];
1098
+ if (item.error === undefined) {
1099
+ if (entry.kind === 'step') {
1100
+ createdStepCorrelationIds.add(entry.correlationId);
1101
+ }
1102
+ else if (entry.kind === 'inline-started') {
1103
+ // The pair committed: this invocation owns the step and the
1104
+ // caller runs the body with no claim of its own. The
1105
+ // readback entity is authoritative where present; a World
1106
+ // that omitted it gets the same locally synthesized running
1107
+ // attempt-1 the optimistic path executes against. Either
1108
+ // way the input is re-attached locally: batch responses
1109
+ // return refs lazily, and the body's hydration wants the
1110
+ // exact bytes the pair's created row carried. (The created
1111
+ // row's success is deliberately NOT membership in
1112
+ // createdStepCorrelationIds: for inline steps ownership is
1113
+ // the started row's verdict, and the caller's dispatch pass
1114
+ // skips inline correlation ids regardless.)
1115
+ const dehydrated = lazyInlineByCorrelationId.get(entry.correlationId);
1116
+ if (dehydrated === undefined) {
1117
+ // Unreachable: the same prep op that enqueued the pair set
1118
+ // this entry, and the flush awaited every prep above.
1119
+ //
1120
+ // Not free if it ever fires, though: the pair is already
1121
+ // durable here, so this throws with the step claimed and
1122
+ // its body never run. The delivery fails, and redelivery
1123
+ // recovers it through owned-recovery (the step carries this
1124
+ // message's ownership stamp) rather than the request just
1125
+ // failing cleanly.
1126
+ throw new WorkflowWorldError(`no dehydrated input for pre-claimed step ${entry.correlationId}`, { status: 500 });
1127
+ }
1128
+ const now = new Date();
1129
+ const startedStep = item.step?.startedAt
1130
+ ? { ...item.step, startedAt: item.step.startedAt }
1131
+ : {
1132
+ runId,
1133
+ stepId: entry.correlationId,
1134
+ stepName: dehydrated.stepName,
1135
+ status: 'running',
1136
+ attempt: 1,
1137
+ createdAt: now,
1138
+ updatedAt: now,
1139
+ startedAt: now,
1140
+ };
1141
+ inlineClaims.set(entry.correlationId, {
1142
+ owned: true,
1143
+ step: {
1144
+ ...startedStep,
1145
+ input: dehydrated.dehydratedInput,
1146
+ },
1147
+ batchPostSentAtMs,
1148
+ claimCompletedAtMs,
1149
+ });
1150
+ }
1151
+ continue;
1152
+ }
1153
+ if (item.status === 409) {
1154
+ if (entry.kind === 'inline-created' ||
1155
+ entry.kind === 'inline-started') {
1156
+ // The pair lost its atomic create-claim: a concurrent writer
1157
+ // already owns this step (an earlier delivery's create, or a
1158
+ // racing handler's claim). Recorded as a lost claim: the
1159
+ // caller's executeStep returns `skipped` without running the
1160
+ // body, the same outcome as losing the lazy claim. A World
1161
+ // that folds the pair reports the 409 on both rows (set
1162
+ // twice, harmless); one that evaluates rows independently
1163
+ // has the started row (processed second) decide, which is
1164
+ // exactly the single path's semantics (create lost + claim
1165
+ // won still runs the body; create won + claim lost skips).
1166
+ inlineClaims.set(entry.correlationId, { owned: false });
1167
+ runtimeLogger.info('Inline step pre-claim lost, continuing', {
1168
+ workflowRunId: runId,
1169
+ correlationId: entry.correlationId,
1170
+ message: item.message,
1171
+ });
1172
+ continue;
1173
+ }
1174
+ // Same tolerance as the single path's EntityConflictError: a
1175
+ // concurrent or earlier delivery already created it.
1176
+ runtimeLogger.info(entry.kind === 'step'
1177
+ ? 'Step already exists, continuing'
1178
+ : 'Wait already exists, continuing', {
1179
+ workflowRunId: runId,
1180
+ correlationId: entry.correlationId,
1181
+ message: item.message,
1182
+ });
1183
+ continue;
1184
+ }
1185
+ throw new WorkflowWorldError(`batched ${entry.event.eventType} for ${entry.correlationId} ` +
1186
+ `failed: ${item.error}: ${item.message}`, { status: item.status });
1187
+ }
1188
+ // Highest slot this chunk committed: one input of the interleaving
1189
+ // diagnostic.
1190
+ const chunkMaxSlot = maxEventSlot(results.flatMap((item) => item.error === undefined && item.event ? [item.event] : []));
1191
+ committedCount += results.filter((item) => item.error === undefined).length;
1192
+ if (chunkMaxSlot !== undefined &&
1193
+ (maxCommittedSlot === undefined || chunkMaxSlot > maxCommittedSlot)) {
1194
+ maxCommittedSlot = chunkMaxSlot;
1195
+ }
1196
+ };
1197
+ // Publish the chunk's eager steps' queue messages the moment ITS
1198
+ // creates are durable, the per-chunk half of publish-after-create.
1199
+ // Same message shape and step-identity-scoped idempotency key as the
1200
+ // caller's dispatch pass, so anything double-published dedupes.
1201
+ const publishChunkSteps = async (chunk) => {
1202
+ if (!publishEagerSteps)
1203
+ return;
1204
+ const stepEntries = chunk.filter((entry) => entry.kind === 'step');
1205
+ if (stepEntries.length === 0)
1206
+ return;
1207
+ const traceCarrier = await getStepDispatchTraceCarrier();
1208
+ // One batched publish per chunk instead of one round trip per step.
1209
+ // The publishes are the fan-out's serialization point: they ride the
1210
+ // shared 8-connection HTTP/1.1 agent (see `getQueueDispatcher` in
1211
+ // world-vercel), and the caller awaits all of them before running
1212
+ // the first inline step body, so N round trips land directly on
1213
+ // time-to-first-step. `queueMessages` falls back to concurrent
1214
+ // single sends on a World with no batch support.
1215
+ await queueMessages(world,
1216
+ // biome-ignore lint/style/noNonNullAssertion: publishEagerSteps implies presence
1217
+ stepDispatch.queueName, stepEntries.map((entry) => ({
1218
+ message: {
1219
+ runId,
1220
+ stepId: entry.correlationId,
1221
+ // biome-ignore lint/style/noNonNullAssertion: set on every 'step' entry at enqueue
1222
+ stepName: entry.stepName,
1223
+ traceCarrier,
1224
+ requestedAt: new Date(),
1225
+ runContext: runDispatchContext(run),
1226
+ },
1227
+ opts: {
1228
+ idempotencyKey: stepDispatchIdempotencyKey(entry.correlationId,
1229
+ // biome-ignore lint/style/noNonNullAssertion: set on every 'step' entry at enqueue
1230
+ entry.stepName),
1231
+ },
1232
+ })));
1233
+ };
1234
+ // Launch every chunk's POST now (the lone plain entry's guarded
1235
+ // single create included); chain each chunk's publishes on its OWN
1236
+ // commit, so publish-after-create holds for the single too. A chunk
1237
+ // whose commit rejected keeps its messages unsent (the rejection
1238
+ // fails the delivery; redelivery re-creates and re-dispatches,
1239
+ // deduped by the idempotency keys).
1240
+ const commits = chunks.map((chunk) => chunk === singleChunk ? commitSingle(chunk[0]) : commitChunk(chunk));
1241
+ const publishes = chunks.map(async (chunk, index) => {
1242
+ await commits[index];
1243
+ await publishChunkSteps(chunk);
1244
+ });
1245
+ const trailing = (async () => {
1246
+ // Let every sibling settle before surfacing the first failure: a
1247
+ // chunk that committed must still get its publishes out even when
1248
+ // another chunk failed, and the caller acks only after this
1249
+ // resolves.
1250
+ const settled = await Promise.allSettled([...commits, ...publishes]);
1251
+ // Foreign-interleaving visibility: the batch endpoint has no
1252
+ // bump-and-report, so events other writers landed between the
1253
+ // snapshot and these commits pushed the fold to higher slots
1254
+ // WITHOUT handing us the skipped events. Same accepted exposure
1255
+ // as a dropped truncated report on the single path: the local
1256
+ // log stays a strict prefix and the next reload observes them.
1257
+ // Logged so a bump is diagnosable rather than silent.
1258
+ if (expectedFirstSlot !== undefined &&
1259
+ maxCommittedSlot !== undefined) {
1260
+ const interleaved = maxCommittedSlot - expectedFirstSlot + 1 - committedCount;
1261
+ if (interleaved > 0) {
1262
+ runtimeLogger.debug('Batched fan-out committed above snapshot', {
1263
+ workflowRunId: runId,
1264
+ expectedFirstSlot,
1265
+ maxCommittedSlot,
1266
+ committedCount,
1267
+ interleaved,
1268
+ });
1269
+ }
1270
+ }
1271
+ const failure = settled.find((outcome) => outcome.status === 'rejected');
1272
+ if (failure)
1273
+ throw failure.reason;
1274
+ })();
1275
+ // EVERY chunk carrying pairs gates the return, not just the first:
1276
+ // a pair whose commit the caller has not seen yields no
1277
+ // `inlineClaims` entry, so the caller falls back to a lazy
1278
+ // `step_started` that would race this same fold's still-in-flight
1279
+ // pair for the same step. The pairs occupy their own leading
1280
+ // chunk(s), and today that is exactly ONE chunk (two rows per
1281
+ // inline step fit inside one chunk, pinned by constants.test.ts),
1282
+ // so this is at most one commit; the filter is what keeps the
1283
+ // property true if either cap moves.
1284
+ const pairCommits = chunks.flatMap((chunk, index) => chunk.some((entry) => entry.kind === 'inline-started')
1285
+ ? [commits[index]]
1286
+ : []);
1287
+ if (allowDeferredBatchWork) {
1288
+ // The trailing work is the caller's to join before ack. Attach a
1289
+ // handler now so a rejection that races that join (or a foreground
1290
+ // failure that prevents the caller from ever reaching it) is never
1291
+ // an unhandledRejection; awaiting the promise still observes it.
1292
+ trailing.catch(() => { });
1293
+ deferredBatchWork = trailing;
1294
+ // Only the pair chunks gate the return: their claims are what the
1295
+ // caller starts the inline bodies from. With no pairs there is
1296
+ // nothing the caller's post-return work reads from the commits,
1297
+ // so nothing gates.
1298
+ if (pairCommits.length > 0) {
1299
+ try {
1300
+ await Promise.all(pairCommits);
1301
+ }
1302
+ catch (err) {
1303
+ // A pair chunk failed, so this phase's write set is NOT the
1304
+ // caller's to join any more: `deferredBatchWork` never
1305
+ // reaches it once handleSuspension throws. Settle the rest
1306
+ // before the rejection escapes, for the reason `settlePhase`
1307
+ // gives: a sibling create landing after the throw commits an
1308
+ // event from the abandoned replay's seeded sequence and races
1309
+ // the caller's restart reload while doing so.
1310
+ await trailing.catch(() => { });
1311
+ throw err;
1312
+ }
1313
+ }
1314
+ }
1315
+ else {
1316
+ await trailing;
1317
+ }
1318
+ })());
1319
+ }
1320
+ for (const queueItem of attributeItems) {
1321
+ ops.push((async () => {
1322
+ try {
1323
+ await ensureRunReady();
1324
+ // Guarded like every other suspension write: an attr_set is a
1325
+ // replay-derived event with a correlation id from this replay's
1326
+ // seeded sequence, so it must not land on a log the replay never
1327
+ // saw. Rejecting it is cheap: a run with attribute events already
1328
+ // forces an in-process replay, so the restart costs the replay it
1329
+ // was going to do anyway.
1330
+ await createGuarded({
1331
+ eventType: 'attr_set',
1332
+ specVersion: SPEC_VERSION_CURRENT,
1333
+ correlationId: queueItem.correlationId,
1334
+ eventData: {
1335
+ changes: queueItem.changes,
1336
+ writer: { type: 'workflow' },
1337
+ ...(queueItem.allowReservedAttributes
1338
+ ? { allowReservedAttributes: true }
1339
+ : {}),
1340
+ },
1341
+ }, { requestId });
1342
+ }
1343
+ catch (err) {
1344
+ if (EntityConflictError.is(err)) {
1345
+ runtimeLogger.info('Workflow attribute event already exists, continuing', {
1346
+ workflowRunId: runId,
1347
+ correlationId: queueItem.correlationId,
1348
+ message: err.message,
1349
+ });
1350
+ }
1351
+ else if (isWorldValidationFailure(err)) {
1352
+ // Deterministic validation rejection from the World, e.g. the
1353
+ // cumulative per-run attribute cap, which only the World can
1354
+ // check against the run's existing attributes. Redelivering the
1355
+ // orchestrator message replays the workflow into the exact same
1356
+ // write and the exact same rejection, so retrying can never
1357
+ // succeed. Surface it as a FatalError so the caller fails the
1358
+ // run with a clear error instead of wedging it in redelivery.
1359
+ const fatal = new FatalError(`setAttributes failed World validation: ${err instanceof Error ? err.message : String(err)}`);
1360
+ fatal.cause = err;
1361
+ throw fatal;
1362
+ }
1363
+ else {
1364
+ throw err;
1365
+ }
1366
+ }
1367
+ })());
1368
+ }
1369
+ // Await the step_created / wait_created event creates before returning.
1370
+ // The caller (workflowEntrypoint) only enqueues the step-dispatch queue
1371
+ // messages AFTER handleSuspension resolves, and the queue handler acks
1372
+ // the orchestrator message only after the caller resolves. So the step_created
1373
+ // events must be durable here, and the dispatch sends must complete in the caller,
1374
+ // all before ack. If the process crashes before this resolves, the orchestrator
1375
+ // message is not acked and VQS redelivers, re-creates the (idempotent)
1376
+ // step_created and re-dispatches, and recovers the run instead of orphaning it.
1377
+ await settlePhase(ops);
1378
+ // Rebuild the inline batch in deterministic order. `lazyInlineCorrelationIds`
1379
+ // is a Set seeded from the ordered first-N slice, so iterating it preserves
1380
+ // stepItems order; every id in it was set by the lazy branch above.
1381
+ const lazyInlineSteps = [];
1382
+ for (const correlationId of lazyInlineCorrelationIds) {
1383
+ const lazyStep = lazyInlineByCorrelationId.get(correlationId);
1384
+ if (lazyStep)
1385
+ lazyInlineSteps.push(lazyStep);
1386
+ }
1387
+ // Find the soonest pending wait (minimum timeout)
257
1388
  const now = Date.now();
258
- const minTimeoutSeconds = waitItems.reduce((min, queueItem) => {
1389
+ let soonestWait;
1390
+ for (const queueItem of waitItems) {
259
1391
  const resumeAtMs = queueItem.resumeAt.getTime();
260
1392
  const delayMs = Math.max(1000, resumeAtMs - now);
261
1393
  const timeoutSeconds = Math.ceil(delayMs / 1000);
262
- if (min === null)
263
- return timeoutSeconds;
264
- return Math.min(min, timeoutSeconds);
265
- }, null);
1394
+ if (!soonestWait || timeoutSeconds < soonestWait.seconds) {
1395
+ soonestWait = {
1396
+ seconds: timeoutSeconds,
1397
+ correlationId: queueItem.correlationId,
1398
+ };
1399
+ }
1400
+ }
266
1401
  span?.setAttributes({
267
1402
  ...Attribute.WorkflowRunStatus('workflow_suspended'),
268
1403
  ...Attribute.WorkflowStepsCreated(stepItems.length),
269
1404
  ...Attribute.WorkflowHooksCreated(hooksNeedingCreation.length),
270
1405
  ...Attribute.WorkflowWaitsCreated(waitItems.length),
1406
+ ...(failedStepCorrelationIds.size > 0
1407
+ ? Attribute.WorkflowStepsFailedSerialization(failedStepCorrelationIds.size)
1408
+ : {}),
1409
+ ...(resilientDispatchRecovered > 0
1410
+ ? Attribute.StepResilientDispatchRecovered(resilientDispatchRecovered)
1411
+ : {}),
271
1412
  });
272
1413
  return {
273
1414
  pendingSteps: stepItems,
274
1415
  createdStepCorrelationIds,
275
- timeoutSeconds: hasHookConflict ? 0 : (minTimeoutSeconds ?? undefined),
276
- hasHookConflict,
1416
+ failedStepCorrelationIds,
1417
+ queuedStepCorrelationIds,
1418
+ lazyInlineSteps,
1419
+ inlineClaims,
1420
+ deferredBatchWork,
1421
+ // On hook conflict the caller advances the workflow over the conflict
1422
+ // before scheduling anything and never reads the wait timeout, so don't
1423
+ // report one. The next pass, which sees the conflict settled, reports it.
1424
+ waitTimeout: hookConflictCorrelationIds.length > 0 ? undefined : soonestWait,
1425
+ hasHookConflict: hookConflictCorrelationIds.length > 0,
1426
+ hookConflictCorrelationIds,
1427
+ hasAwaitedHookCreation: awaitedHookCorrelationIds.length > 0,
1428
+ awaitedHookCorrelationIds,
1429
+ // The delta accounts for the whole log only if the write that returned it
1430
+ // was this suspension's only one — anything written after it landed above
1431
+ // the delta and is missing from the caller's log.
1432
+ eventLogCarriedForward: deltaAbsorbed && guardedWrites === 1,
1433
+ hasAttributeEvents: attributeItems.length > 0,
1434
+ hasHookEvents: hooksNeedingCreation.length > 0,
1435
+ hookCreationMs,
1436
+ serializationBlockerCount,
1437
+ serializationBlockers,
1438
+ reportedEventCount: reportedEvents,
277
1439
  };
278
1440
  }
279
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixlQUFlLEdBQ2hCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUdMLG9CQUFvQixHQUdyQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU83QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN2RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBZ0NsRTs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsRUFDckMsVUFBVSxFQUNWLEtBQUssRUFDTCxHQUFHLEVBQ0gsSUFBSSxFQUNKLFNBQVMsR0FDZTtJQUN4QixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDO0lBQ3hCLCtCQUErQjtJQUMvQixNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FDdkMsQ0FBQyxJQUFJLEVBQW1DLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FDaEUsQ0FBQztJQUNGLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUMxQyxDQUFDLElBQUksRUFBbUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUNoRSxDQUFDO0lBQ0YsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQ3ZDLENBQUMsSUFBSSxFQUFtQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQ2hFLENBQUM7SUFFRix3Q0FBd0M7SUFDeEMsTUFBTSxvQkFBb0IsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUM5QyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUNoQyxDQUFDO0lBQ0YsTUFBTSxvQkFBb0IsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFMUUsc0NBQXNDO0lBQ3RDLE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBRW5FLHFEQUFxRDtJQUNyRCxNQUFNLFVBQVUsR0FBeUIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUN4RCxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFO1FBQzNDLE1BQU0sWUFBWSxHQUNoQixPQUFPLFNBQVMsQ0FBQyxRQUFRLEtBQUssV0FBVztZQUN2QyxDQUFDLENBQUMsU0FBUztZQUNYLENBQUMsQ0FBRSxDQUFDLE1BQU0sc0JBQXNCLENBQzVCLFNBQVMsQ0FBQyxRQUFRLEVBQ2xCLEtBQUssRUFDTCxhQUFhLEVBQ2IsVUFBVSxDQUFDLFVBQVUsQ0FDdEIsQ0FBb0IsQ0FBQztRQUM1QixPQUFPO1lBQ0wsU0FBUyxFQUFFLGNBQXVCO1lBQ2xDLFdBQVcsRUFBRSxvQkFBb0I7WUFDakMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxhQUFhO1lBQ3RDLFNBQVMsRUFBRTtnQkFDVCxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7Z0JBQ3RCLFFBQVEsRUFBRSxZQUFZO2dCQUN0QixTQUFTLEVBQUUsU0FBUyxDQUFDLFNBQVMsSUFBSSxLQUFLO2dCQUN2QyxHQUFHLENBQUMsU0FBUyxDQUFDLFFBQVEsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQzthQUM5QztTQUNGLENBQUM7SUFDSixDQUFDLENBQUMsQ0FDSCxDQUFDO0lBRUYseUVBQXlFO0lBQ3pFLHNDQUFzQztJQUN0Qyx5RUFBeUU7SUFDekUsK0NBQStDO0lBQy9DLElBQUksZUFBZSxHQUFHLEtBQUssQ0FBQztJQUU1QixJQUFJLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDMUIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNmLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFO1lBQ2pDLElBQUksQ0FBQztnQkFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUU7b0JBQ3pELFNBQVM7aUJBQ1YsQ0FBQyxDQUFDO2dCQUNILDZFQUE2RTtnQkFDN0UsMEVBQTBFO2dCQUMxRSx5RUFBeUU7Z0JBQ3pFLHFGQUFxRjtnQkFDckYsSUFBSSxNQUFNLENBQUMsS0FBTSxDQUFDLFNBQVMsS0FBSyxlQUFlLEVBQUUsQ0FBQztvQkFDaEQsZUFBZSxHQUFHLElBQUksQ0FBQztnQkFDekIsQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLElBQUksbUJBQW1CLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDM0QsYUFBYSxDQUFDLElBQUksQ0FDaEIsK0NBQStDLEVBQy9DO3dCQUNFLGFBQWEsRUFBRSxLQUFLO3dCQUNwQixPQUFPLEVBQUUsR0FBRyxDQUFDLE9BQU87cUJBQ3JCLENBQ0YsQ0FBQztnQkFDSixDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxHQUFHLENBQUM7Z0JBQ1osQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVELG1GQUFtRjtJQUNuRixJQUFJLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNwQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ2Ysb0JBQW9CLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRTtZQUMzQyxNQUFNLGlCQUFpQixHQUF1QjtnQkFDNUMsU0FBUyxFQUFFLGVBQXdCO2dCQUNuQyxXQUFXLEVBQUUsb0JBQW9CO2dCQUNqQyxhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7YUFDdkMsQ0FBQztZQUNGLElBQUksQ0FBQztnQkFDSCxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7WUFDckUsQ0FBQztZQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7Z0JBQ2IsSUFBSSxtQkFBbUIsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDaEMsc0VBQXNFO29CQUN0RSxhQUFhLENBQUMsSUFBSSxDQUNoQixvREFBb0QsRUFDcEQ7d0JBQ0UsYUFBYSxFQUFFLEtBQUs7d0JBQ3BCLGFBQWEsRUFBRSxTQUFTLENBQUMsYUFBYTt3QkFDdEMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO3FCQUNyQixDQUNGLENBQUM7Z0JBQ0osQ0FBQztxQkFBTSxJQUFJLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDbkMsYUFBYSxDQUFDLElBQUksQ0FDaEIsd0RBQXdELEVBQ3hEO3dCQUNFLGFBQWEsRUFBRSxLQUFLO3dCQUNwQixhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7d0JBQ3RDLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztxQkFDckIsQ0FDRixDQUFDO2dCQUNKLENBQUM7cUJBQU0sSUFBSSxpQkFBaUIsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDckMsdURBQXVEO29CQUN2RCxhQUFhLENBQUMsSUFBSSxDQUFDLHlDQUF5QyxFQUFFO3dCQUM1RCxhQUFhLEVBQUUsS0FBSzt3QkFDcEIsYUFBYSxFQUFFLFNBQVMsQ0FBQyxhQUFhO3dCQUN0QyxPQUFPLEVBQUUsR0FBRyxDQUFDLE9BQU87cUJBQ3JCLENBQUMsQ0FBQztnQkFDTCxDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxHQUFHLENBQUM7Z0JBQ1osQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVELHNGQUFzRjtJQUN0RixNQUFNLGlCQUFpQixHQUFHLFlBQVksQ0FBQyxNQUFNLENBQzNDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FDaEQsQ0FBQztJQUVGLElBQUksaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixpQkFBaUIsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFO1lBQ3hDLElBQUksQ0FBQztnQkFDSCwwQ0FBMEM7Z0JBQzFDLE1BQU0sWUFBWSxHQUFHLE1BQU0sc0JBQXNCLENBQy9DLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLFdBQVcsRUFBRSxFQUNoRCxLQUFLLEVBQ0wsYUFBYSxFQUNiLFVBQVUsQ0FBQyxVQUFVLENBQ3RCLENBQUM7Z0JBRUYsZ0RBQWdEO2dCQUNoRCxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtvQkFDL0IsU0FBUyxFQUFFLGVBQXdCO29CQUNuQyxXQUFXLEVBQUUsb0JBQW9CO29CQUNqQyxhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7b0JBQ3RDLFNBQVMsRUFBRTt3QkFDVCxPQUFPLEVBQUUsWUFBWTtxQkFDdEI7aUJBQ0YsQ0FBQyxDQUFDO2dCQUVILG1FQUFtRTtnQkFDbkUsb0VBQW9FO2dCQUNwRSx3RUFBd0U7Z0JBQ3hFLHFFQUFxRTtnQkFDckUsd0VBQXdFO2dCQUN4RSxzRUFBc0U7Z0JBQ3RFLHNDQUFzQztnQkFDdEMsSUFBSSxDQUFDO29CQUNILE1BQU0sVUFBVSxHQUFHLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDOUQsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FDdkIsS0FBSyxFQUNMLFVBQVUsRUFDVixZQUEwQixDQUMzQixDQUFDO29CQUNGLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUMvQyxDQUFDO2dCQUFDLE1BQU0sQ0FBQztvQkFDUCxzRUFBc0U7b0JBQ3RFLGFBQWEsQ0FBQyxLQUFLLENBQ2pCLHVFQUF1RSxFQUN2RTt3QkFDRSxhQUFhLEVBQUUsS0FBSzt3QkFDcEIsYUFBYSxFQUFFLFNBQVMsQ0FBQyxhQUFhO3FCQUN2QyxDQUNGLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLElBQUksbUJBQW1CLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDM0QsYUFBYSxDQUFDLElBQUksQ0FDaEIsZ0RBQWdELEVBQ2hEO3dCQUNFLGFBQWEsRUFBRSxLQUFLO3dCQUNwQixhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7d0JBQ3RDLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztxQkFDckIsQ0FDRixDQUFDO2dCQUNKLENBQUM7cUJBQU0sQ0FBQztvQkFDTixNQUFNLEdBQUcsQ0FBQztnQkFDWixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7SUFDSixDQUFDO0lBRUQseURBQXlEO0lBQ3pELGtFQUFrRTtJQUNsRSxpRUFBaUU7SUFDakUsa0RBQWtEO0lBQ2xELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQ2xDLFNBQVM7U0FDTixNQUFNLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQztTQUNqRCxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FDL0MsQ0FBQztJQUVGLG9FQUFvRTtJQUNwRSxvRUFBb0U7SUFDcEUsa0VBQWtFO0lBQ2xFLHFEQUFxRDtJQUNyRCxNQUFNLHlCQUF5QixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFFcEQsTUFBTSxHQUFHLEdBQW9CLEVBQUUsQ0FBQztJQUVoQyxzRkFBc0Y7SUFDdEYsS0FBSyxNQUFNLFNBQVMsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUNsQyxJQUFJLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUN0RCxHQUFHLENBQUMsSUFBSSxDQUNOLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ1YsTUFBTSxlQUFlLEdBQUcsTUFBTSxzQkFBc0IsQ0FDbEQ7b0JBQ0UsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO29CQUNwQixXQUFXLEVBQUUsU0FBUyxDQUFDLFdBQVc7b0JBQ2xDLE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTztpQkFDM0IsRUFDRCxLQUFLLEVBQ0wsYUFBYSxFQUNiLFVBQVUsQ0FBQyxVQUFVLENBQ3RCLENBQUM7Z0JBQ0YsTUFBTSxTQUFTLEdBQXVCO29CQUNwQyxTQUFTLEVBQUUsY0FBdUI7b0JBQ2xDLFdBQVcsRUFBRSxvQkFBb0I7b0JBQ2pDLGFBQWEsRUFBRSxTQUFTLENBQUMsYUFBYTtvQkFDdEMsU0FBUyxFQUFFO3dCQUNULFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTt3QkFDNUIsS0FBSyxFQUFFLGVBQWlDO3FCQUN6QztpQkFDRixDQUFDO2dCQUNGLElBQUksQ0FBQztvQkFDSCxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO29CQUMzRCx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUN6RCxDQUFDO2dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7b0JBQ2IsSUFBSSxtQkFBbUIsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQzt3QkFDaEMsYUFBYSxDQUFDLElBQUksQ0FBQyxpQ0FBaUMsRUFBRTs0QkFDcEQsYUFBYSxFQUFFLEtBQUs7NEJBQ3BCLGFBQWEsRUFBRSxTQUFTLENBQUMsYUFBYTs0QkFDdEMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO3lCQUNyQixDQUFDLENBQUM7b0JBQ0wsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLE1BQU0sR0FBRyxDQUFDO29CQUNaLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUMsQ0FBQyxFQUFFLENBQ0wsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsa0NBQWtDO0lBQ2xDLEtBQUssTUFBTSxTQUFTLElBQUksU0FBUyxFQUFFLENBQUM7UUFDbEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUMvQixHQUFHLENBQUMsSUFBSSxDQUNOLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ1YsTUFBTSxTQUFTLEdBQXVCO29CQUNwQyxTQUFTLEVBQUUsY0FBdUI7b0JBQ2xDLFdBQVcsRUFBRSxvQkFBb0I7b0JBQ2pDLGFBQWEsRUFBRSxTQUFTLENBQUMsYUFBYTtvQkFDdEMsU0FBUyxFQUFFO3dCQUNULFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTtxQkFDN0I7aUJBQ0YsQ0FBQztnQkFDRixJQUFJLENBQUM7b0JBQ0gsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztnQkFDN0QsQ0FBQztnQkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO29CQUNiLElBQUksbUJBQW1CLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7d0JBQ2hDLGFBQWEsQ0FBQyxJQUFJLENBQUMsaUNBQWlDLEVBQUU7NEJBQ3BELGFBQWEsRUFBRSxLQUFLOzRCQUNwQixhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7NEJBQ3RDLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTzt5QkFDckIsQ0FBQyxDQUFDO29CQUNMLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixNQUFNLEdBQUcsQ0FBQztvQkFDWixDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDLENBQUMsRUFBRSxDQUNMLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELFNBQVMsQ0FDUCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQy9CLE1BQU0sWUFBWSxHQUNoQixLQUFLLEVBQUUsSUFBSSxLQUFLLFlBQVksSUFBSSxLQUFLLEVBQUUsSUFBSSxLQUFLLGlCQUFpQixDQUFDO1FBQ3BFLElBQUksQ0FBQyxZQUFZO1lBQUUsTUFBTSxLQUFLLENBQUM7SUFDakMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNGLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUV2Qix1Q0FBdUM7SUFDdkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLE1BQU0saUJBQWlCLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FDeEMsQ0FBQyxHQUFHLEVBQUUsU0FBUyxFQUFFLEVBQUU7UUFDakIsTUFBTSxVQUFVLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxVQUFVLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDakQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDakQsSUFBSSxHQUFHLEtBQUssSUFBSTtZQUFFLE9BQU8sY0FBYyxDQUFDO1FBQ3hDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDdkMsQ0FBQyxFQUNELElBQUksQ0FDTCxDQUFDO0lBRUYsSUFBSSxFQUFFLGFBQWEsQ0FBQztRQUNsQixHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQztRQUNwRCxHQUFHLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ25ELEdBQUcsU0FBUyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQztRQUM5RCxHQUFHLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO0tBQ3BELENBQUMsQ0FBQztJQUVILE9BQU87UUFDTCxZQUFZLEVBQUUsU0FBUztRQUN2Qix5QkFBeUI7UUFDekIsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixJQUFJLFNBQVMsQ0FBQztRQUN0RSxlQUFlO0tBQ2hCLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBTcGFuIH0gZnJvbSAnQG9wZW50ZWxlbWV0cnkvYXBpJztcbmltcG9ydCB7IHdhaXRVbnRpbCB9IGZyb20gJ0B2ZXJjZWwvZnVuY3Rpb25zJztcbmltcG9ydCB7XG4gIEVudGl0eUNvbmZsaWN0RXJyb3IsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgdHlwZSBDcmVhdGVFdmVudFJlcXVlc3QsXG4gIHR5cGUgU2VyaWFsaXplZERhdGEsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICB0eXBlIFdvcmtmbG93UnVuLFxuICB0eXBlIFdvcmxkLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgaW1wb3J0S2V5IH0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFdvcmtmbG93U3VzcGVuc2lvbixcbn0gZnJvbSAnLi4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbiB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0ICogYXMgQXR0cmlidXRlIGZyb20gJy4uL3RlbGVtZXRyeS9zZW1hbnRpYy1jb252ZW50aW9ucy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgaGFuZGxpbmcgYSBzdXNwZW5zaW9uLiBSZXR1cm5zIHBlbmRpbmcgc3RlcCBpdGVtcyBzbyB0aGUgY2FsbGVyXG4gKiBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQge1xuICAvKiogUGVuZGluZyBzdGVwIGl0ZW1zIHdpdGggZXZlbnRzIGNyZWF0ZWQgYnV0IE5PVCBxdWV1ZWQgKi9cbiAgcGVuZGluZ1N0ZXBzOiBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbVtdO1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gSURzIGZvciB3aGljaCB0aGlzIHN1c3BlbnNpb24gY2FsbCBhY3R1YWxseSB3cm90ZSB0aGVcbiAgICogc3RlcF9jcmVhdGVkIGV2ZW50IChhcyBvcHBvc2VkIHRvIGNhdGNoaW5nIEVudGl0eUNvbmZsaWN0RXJyb3IgYmVjYXVzZVxuICAgKiBhIGNvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSBpdCBmaXJzdCkuIE9ubHkgdGhlIGhhbmRsZXIgdGhhdCB3cm90ZSB0aGVcbiAgICogc3RlcF9jcmVhdGVkIGV2ZW50IHNob3VsZCBxdWV1ZSAvIGlubGluZS1leGVjdXRlIHRoZSBzdGVwIOKAlCB0aGlzXG4gICAqIGd1YXJhbnRlZXMgYSBzaW5nbGUgb3duZXIgcGVyIHN0ZXAsIGV2ZW4gd2hlbiBtdWx0aXBsZSBoYW5kbGVycyByYWNlXG4gICAqIGludG8gdGhlIHNhbWUgYmF0Y2ggYm91bmRhcnkuXG4gICAqL1xuICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOiBTZXQ8c3RyaW5nPjtcbiAgLyoqIFRpbWVvdXQgZnJvbSB3YWl0cywgaWYgYW55ICovXG4gIHRpbWVvdXRTZWNvbmRzPzogbnVtYmVyO1xuICAvKiogV2hldGhlciBhIGhvb2sgY29uZmxpY3Qgd2FzIGRldGVjdGVkIChzaG91bGQgcmUtaW52b2tlIGltbWVkaWF0ZWx5KSAqL1xuICBoYXNIb29rQ29uZmxpY3Q6IGJvb2xlYW47XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIHdvcmtmbG93IHN1c3BlbnNpb24gYnkgcHJvY2Vzc2luZyBhbGwgcGVuZGluZyBvcGVyYXRpb25zIChob29rcywgc3RlcHMsIHdhaXRzKS5cbiAqIENyZWF0ZXMgZXZlbnRzIGZvciBhbGwgb3BlcmF0aW9ucyBidXQgZG9lcyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlcyDigJQgcmV0dXJucyB0aGUgcGVuZGluZ1xuICogc3RlcHMgc28gdGhlIGNhbGxlciBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKlxuICogUHJvY2Vzc2luZyBvcmRlcjpcbiAqIDEuIEhvb2tzIGFyZSBwcm9jZXNzZWQgZmlyc3QgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnMgd2l0aCB3ZWJob29rIHJlY2VpdmVyc1xuICogMi4gU3RlcCBldmVudHMgYW5kIHdhaXQgZXZlbnRzIGFyZSBjcmVhdGVkIGluIHBhcmFsbGVsXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVTdXNwZW5zaW9uKHtcbiAgc3VzcGVuc2lvbixcbiAgd29ybGQsXG4gIHJ1bixcbiAgc3BhbixcbiAgcmVxdWVzdElkLFxufTogU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMpOiBQcm9taXNlPFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0PiB7XG4gIGNvbnN0IHJ1bklkID0gcnVuLnJ1bklkO1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG5cbiAgLy8gU3BsaXQgaG9va3MgYnkgd2hhdCBhY3Rpb25zIHRoZXkgbmVlZFxuICBjb25zdCBob29rc05lZWRpbmdDcmVhdGlvbiA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApO1xuICBjb25zdCBob29rc05lZWRpbmdEaXNwb3NhbCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uZGlzcG9zZWQpO1xuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gQnVpbGQgYW5kIHByb2Nlc3MgaG9va19jcmVhdGVkIGV2ZW50cyAoc2FtZSBhcyBWMSlcbiAgY29uc3QgaG9va0V2ZW50czogQ3JlYXRlRXZlbnRSZXF1ZXN0W10gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICBob29rc05lZWRpbmdDcmVhdGlvbi5tYXAoYXN5bmMgKHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgaG9va01ldGFkYXRhOiBTZXJpYWxpemVkRGF0YSB8IHVuZGVmaW5lZCA9XG4gICAgICAgIHR5cGVvZiBxdWV1ZUl0ZW0ubWV0YWRhdGEgPT09ICd1bmRlZmluZWQnXG4gICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICA6ICgoYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgICAgcXVldWVJdGVtLm1ldGFkYXRhLFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzXG4gICAgICAgICAgICApKSBhcyBTZXJpYWxpemVkRGF0YSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBldmVudFR5cGU6ICdob29rX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgIG1ldGFkYXRhOiBob29rTWV0YWRhdGEsXG4gICAgICAgICAgaXNXZWJob29rOiBxdWV1ZUl0ZW0uaXNXZWJob29rID8/IGZhbHNlLFxuICAgICAgICAgIC4uLihxdWV1ZUl0ZW0uaXNTeXN0ZW0gJiYgeyBpc1N5c3RlbTogdHJ1ZSB9KSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSlcbiAgKTtcblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIEFsbCBob29rIGNyZWF0aW9ucyBydW4gaW4gcGFyYWxsZWwuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyIOKAlCB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlclxuICAvLyBzbyB0aGUgVjIgaGFuZGxlciBjYW4gcmUtaW52b2tlIGltbWVkaWF0ZWx5LlxuICBsZXQgaGFzSG9va0NvbmZsaWN0ID0gZmFsc2U7XG5cbiAgaWYgKGhvb2tFdmVudHMubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaG9va0V2ZW50cy5tYXAoYXN5bmMgKGhvb2tFdmVudCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIGhvb2tFdmVudCwge1xuICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgICAgICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAgICAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3QuXG4gICAgICAgICAgLy8gTm90ZTogaG9vayBldmVudHMgYWx3YXlzIGNyZWF0ZSBhbiBldmVudCAobGVnYWN5IHJ1bnMgdGhyb3csIG5vdCByZXR1cm4gdW5kZWZpbmVkKVxuICAgICAgICAgIGlmIChyZXN1bHQuZXZlbnQhLmV2ZW50VHlwZSA9PT0gJ2hvb2tfY29uZmxpY3QnKSB7XG4gICAgICAgICAgICBoYXNIb29rQ29uZmxpY3QgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBob29rJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2sgZGlzcG9zYWxzIOKAlCB0aGVzZSByZWxlYXNlIGhvb2sgdG9rZW5zIGZvciByZXVzZSBieSBvdGhlciB3b3JrZmxvd3MuXG4gIGlmIChob29rc05lZWRpbmdEaXNwb3NhbC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBob29rc05lZWRpbmdEaXNwb3NhbC5tYXAoYXN5bmMgKHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgICBjb25zdCBob29rRGlzcG9zZWRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfZGlzcG9zZWQnIGFzIGNvbnN0LFxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgfTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24g4oCUIHNhZmUgdG8gc2tpcFxuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnSG9vayBhbHJlYWR5IGRpc3Bvc2VkLCBza2lwcGluZyBkdXBsaWNhdGUgZGlzcG9zYWwnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBob29rIGRpc3Bvc2FsJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgLy8gSG9vayBtYXkgaGF2ZSBhbHJlYWR5IGJlZW4gZGlzcG9zZWQgb3IgbmV2ZXIgY3JlYXRlZFxuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdIb29rIG5vdCBmb3VuZCBmb3IgZGlzcG9zYWwsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLy8gUHJvY2VzcyBhYm9ydCByZXF1ZXN0cyDigJQgcmVzdW1lIHRoZSBob29rIHdpdGggYWJvcnQgcGF5bG9hZCBhbmQgd3JpdGUgc3RyZWFtIHBhY2tldFxuICBjb25zdCBob29rc05lZWRpbmdBYm9ydCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+IGl0ZW0uYWJvcnRSZXF1ZXN0ZWQgJiYgIWl0ZW0uZGlzcG9zZWRcbiAgKTtcblxuICBpZiAoaG9va3NOZWVkaW5nQWJvcnQubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaG9va3NOZWVkaW5nQWJvcnQubWFwKGFzeW5jIChxdWV1ZUl0ZW0pID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBEZWh5ZHJhdGUgdGhlIGFib3J0IHBheWxvYWQgZm9yIHN0b3JhZ2VcbiAgICAgICAgICBjb25zdCBhYm9ydFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgeyBhYm9ydGVkOiB0cnVlLCByZWFzb246IHF1ZXVlSXRlbS5hYm9ydFJlYXNvbiB9LFxuICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIENyZWF0ZSBob29rX3JlY2VpdmVkIGV2ZW50IHdpdGggYWJvcnQgcGF5bG9hZFxuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfcmVjZWl2ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgcGF5bG9hZDogYWJvcnRQYXlsb2FkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIFdyaXRlIHN0cmVhbSBjYW5jZWxsYXRpb24gcGFja2V0IGZvciByZWFsLXRpbWUgc3RlcCBwcm9wYWdhdGlvbi5cbiAgICAgICAgICAvLyBSZXVzZSB0aGUgc2FtZSBkZWh5ZHJhdGVkIHBheWxvYWQgYXMgdGhlIGhvb2sgZXZlbnQgc28gdGhlIHJlYXNvblxuICAgICAgICAgIC8vIHJvdW5kLXRyaXBzIHRocm91Z2ggYGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHNgIC8gYGh5ZHJhdGVTdGVwQXJndW1lbnRzYFxuICAgICAgICAgIC8vIChoYW5kbGVzIERPTUV4Y2VwdGlvbiwgY3VzdG9tIGVycm9ycywgZW5jcnlwdGlvbiwgZXRjLikgaW5zdGVhZCBvZlxuICAgICAgICAgIC8vIGJhcmUgSlNPTi5zdHJpbmdpZnkgd2hpY2ggbG9zZXMgdHlwZSBpbmZvcm1hdGlvbiBhbmQgZHJvcHMgdW5kZWZpbmVkLlxuICAgICAgICAgIC8vIHN0cmVhbU5hbWUgaXMgc2V0IG9uIHRoZSBxdWV1ZSBpdGVtIGF0IGNvbnRyb2xsZXIgY29uc3RydWN0aW9uIHRpbWVcbiAgICAgICAgICAvLyAoc2VlIHdvcmtmbG93L2Fib3J0LWNvbnRyb2xsZXIudHMpLlxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1OYW1lID0gZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbihxdWV1ZUl0ZW0udG9rZW4pO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuc3RyZWFtcy53cml0ZShcbiAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgIHN0cmVhbU5hbWUsXG4gICAgICAgICAgICAgIGFib3J0UGF5bG9hZCBhcyBVaW50OEFycmF5XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuc3RyZWFtcy5jbG9zZShydW5JZCwgc3RyZWFtTmFtZSk7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBCZXN0LWVmZm9ydCBzdHJlYW0gd3JpdGUg4oCUIGhvb2sgZXZlbnQgcHJvdmlkZXMgdGhlIGR1cmFibGUgZmFsbGJhY2tcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICdGYWlsZWQgdG8gd3JpdGUgYWJvcnQgc3RyZWFtIHBhY2tldCwgaG9vayBldmVudCB3aWxsIHByb3ZpZGUgZmFsbGJhY2snLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGFib3J0JyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBDcmVhdGUgc3RlcCBldmVudHMgZm9yIHN0ZXBzIHRoYXQgZG9uJ3QgaGF2ZSB0aGVtIHlldC5cbiAgLy8gVW5saWtlIFYxLCB3ZSBkbyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlcyBmcm9tIGhlcmUg4oCUIHRoZSBjYWxsZXJcbiAgLy8gZGVjaWRlcyB3aGljaCBzdGVwcyB0byBleGVjdXRlIGlubGluZSB2cy4gcXVldWUgdG8gYmFja2dyb3VuZC5cbiAgLy8gV2FpdCBldmVudHMgYXJlIGFsc28gY3JlYXRlZCBpbiBwYXJhbGxlbCBiZWxvdy5cbiAgY29uc3Qgc3RlcHNOZWVkaW5nQ3JlYXRpb24gPSBuZXcgU2V0KFxuICAgIHN0ZXBJdGVtc1xuICAgICAgLmZpbHRlcigocXVldWVJdGVtKSA9PiAhcXVldWVJdGVtLmhhc0NyZWF0ZWRFdmVudClcbiAgICAgIC5tYXAoKHF1ZXVlSXRlbSkgPT4gcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpXG4gICk7XG5cbiAgLy8gQ29ycmVsYXRpb24gSURzIGZvciB3aGljaCBUSElTIHN1c3BlbnNpb24gY2FsbCBhY3R1YWxseSB3cm90ZSB0aGVcbiAgLy8gc3RlcF9jcmVhdGVkIGV2ZW50LiBQb3B1bGF0ZWQgYnkgdGhlIG9wcyBiZWxvdyBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgLy8gZXZlbnRzLmNyZWF0ZSDigJQgdXNlZCBieSB0aGUgY2FsbGVyIHRvIGNsYWltIG93bmVyc2hpcCBhbmQgYXZvaWRcbiAgLy8gcmFjaW5nIHdpdGggY29uY3VycmVudCBoYW5kbGVycyBvbiBzdGVwIGV4ZWN1dGlvbi5cbiAgY29uc3QgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGNvbnN0IG9wczogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgLy8gU3RlcHM6IGNyZWF0ZSBzdGVwX2NyZWF0ZWQgZXZlbnRzIChubyBxdWV1aW5nIOKAlCBWMiByZXR1cm5zIHBlbmRpbmcgc3RlcHMgdG8gY2FsbGVyKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBzdGVwSXRlbXMpIHtcbiAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgb3BzLnB1c2goXG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgZGVoeWRyYXRlZElucHV0ID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYXJnczogcXVldWVJdGVtLmFyZ3MsXG4gICAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBxdWV1ZUl0ZW0uY2xvc3VyZVZhcnMsXG4gICAgICAgICAgICAgIHRoaXNWYWw6IHF1ZXVlSXRlbS50aGlzVmFsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpc1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3Qgc3RlcEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgaW5wdXQ6IGRlaHlkcmF0ZWRJbnB1dCBhcyBTZXJpYWxpemVkRGF0YSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pKClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHdhaXQgZXZlbnRzIChzYW1lIGFzIFYxKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBpZiAoIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdhaXRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHJlc3VtZUF0OiBxdWV1ZUl0ZW0ucmVzdW1lQXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHdhaXRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnV2FpdCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHdhaXRVbnRpbChcbiAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChvcEVycikgPT4ge1xuICAgICAgY29uc3QgaXNBYm9ydEVycm9yID1cbiAgICAgICAgb3BFcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBvcEVycj8ubmFtZSA9PT0gJ1Jlc3BvbnNlQWJvcnRlZCc7XG4gICAgICBpZiAoIWlzQWJvcnRFcnJvcikgdGhyb3cgb3BFcnI7XG4gICAgfSlcbiAgKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwob3BzKTtcblxuICAvLyBDYWxjdWxhdGUgbWluaW11bSB0aW1lb3V0IGZyb20gd2FpdHNcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgbWluVGltZW91dFNlY29uZHMgPSB3YWl0SXRlbXMucmVkdWNlPG51bWJlciB8IG51bGw+KFxuICAgIChtaW4sIHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgICBjb25zdCBkZWxheU1zID0gTWF0aC5tYXgoMTAwMCwgcmVzdW1lQXRNcyAtIG5vdyk7XG4gICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgICBpZiAobWluID09PSBudWxsKSByZXR1cm4gdGltZW91dFNlY29uZHM7XG4gICAgICByZXR1cm4gTWF0aC5taW4obWluLCB0aW1lb3V0U2Vjb25kcyk7XG4gICAgfSxcbiAgICBudWxsXG4gICk7XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHBlbmRpbmdTdGVwczogc3RlcEl0ZW1zLFxuICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgdGltZW91dFNlY29uZHM6IGhhc0hvb2tDb25mbGljdCA/IDAgOiAobWluVGltZW91dFNlY29uZHMgPz8gdW5kZWZpbmVkKSxcbiAgICBoYXNIb29rQ29uZmxpY3QsXG4gIH07XG59XG4iXX0=
1441
+ /**
1442
+ * Whether an `events.create` rejection is deterministic World validation
1443
+ * rather than a transient/storage error. Local Worlds
1444
+ * (world-local, world-postgres) throw `AttributeValidationError` directly;
1445
+ * remote Worlds surface the equivalent server-side rejection as a
1446
+ * `WorkflowWorldError` with HTTP status 400. The name check covers
1447
+ * `AttributeValidationError` instances from a different copy of
1448
+ * `@workflow/world` than the one this package resolved.
1449
+ */
1450
+ function isWorldValidationFailure(err) {
1451
+ if (err instanceof AttributeValidationError)
1452
+ return true;
1453
+ if (err instanceof Error && err.name === 'AttributeValidationError') {
1454
+ return true;
1455
+ }
1456
+ return WorkflowWorldError.is(err) && err.status === 400;
1457
+ }
1458
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZUFBZSxFQUNmLGtCQUFrQixFQUNsQixrQkFBa0IsR0FDbkIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsd0JBQXdCLEVBS3hCLG9CQUFvQixFQUNwQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEVBQ2pDLG1DQUFtQyxHQU1wQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQVE3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFDTCxpQ0FBaUMsR0FHbEMsTUFBTSw4QkFBOEIsQ0FBQztBQUN0QyxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLGtCQUFrQixHQUNuQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVELE9BQU8sRUFDTCxpQkFBaUIsRUFDakIseUJBQXlCLEVBQ3pCLDhCQUE4QixFQUM5Qix1QkFBdUIsRUFDdkIsOEJBQThCLEdBQy9CLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixjQUFjLEVBR2QsWUFBWSxFQUNaLFlBQVksRUFDWixhQUFhLEVBQ2Isa0JBQWtCLEVBQ2xCLGtCQUFrQixF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QUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BvcGVudGVsZW1ldHJ5L2FwaSc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBIb29rTm90Rm91bmRFcnJvcixcbiAgUHJlY29uZGl0aW9uRmFpbGVkRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgU2VyaWFsaXphdGlvbkVycm9yLFxuICBXb3JrZmxvd1dvcmxkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yLFxuICB0eXBlIENyZWF0ZUV2ZW50UGFyYW1zLFxuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBFdmVudFJlc3VsdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVCxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OLFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfU0xPVF9JREVOVElUWSxcbiAgdHlwZSBTdGFydGVkU3RlcCxcbiAgdHlwZSBUcmFjZUNhcnJpZXIsXG4gIHR5cGUgVmFsaWRRdWV1ZU5hbWUsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG4gIHR5cGUgV29ybGQsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBpc1JldHJ5YWJsZVdvcmxkRXJyb3IgfSBmcm9tICcuLi9jbGFzc2lmeS1lcnJvci5qcyc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV29ya2Zsb3dTdXNwZW5zaW9uLFxufSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQge1xuICBHVUVTVF9DT0RFX0VYRUNVVElPTl9TQU1QTEVfTElNSVQsXG4gIHR5cGUgR3Vlc3RDb2RlRXhlY3V0aW9uLFxuICB0eXBlIEd1ZXN0Q29kZVN0YXRzLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uL2hhcmRlbmVkLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIGRlaHlkcmF0ZVN0ZXBFcnJvcixcbn0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IGdldEFib3J0U3RyZWFtSWRGcm9tVG9rZW4gfSBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCB7IENPTVBVVEVfSU5TVEFOQ0VfSUQgfSBmcm9tICcuL2NvbXB1dGUtaW5zdGFuY2UuanMnO1xuaW1wb3J0IHtcbiAgZ2V0TWF4SW5saW5lU3RlcHMsXG4gIGlzQmF0Y2hUcmFuc2l0aW9uc0VuYWJsZWQsXG4gIGlzUmVzaWxpZW50U3RlcERpc3BhdGNoRW5hYmxlZCxcbiAgTUFYX0JBVENIX0ZBTk9VVF9FVkVOVFMsXG4gIE1BWF9SRVNJTElFTlRfU1RFUF9JTlBVVF9CWVRFUyxcbn0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHtcbiAgYWJzb3JiU2tpcHBlZFNsb3RSZXBvcnQsXG4gIGFwcGVuZEV2ZW50TG9nLFxuICB0eXBlIEV2ZW50Q3JlYXRvcixcbiAgdHlwZSBMb2FkZWRFdmVudExvZyxcbiAgbWF4RXZlbnRTbG90LFxuICBxdWV1ZU1lc3NhZ2UsXG4gIHF1ZXVlTWVzc2FnZXMsXG4gIHJ1bkRpc3BhdGNoQ29udGV4dCxcbiAgc2xvdFNuYXBzaG90UGFyYW1zLFxuICBzdGVwRGlzcGF0Y2hJZGVtcG90ZW5jeUtleSxcbn0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXIgfSBmcm9tICcuL3JlcGxheS1yZWNvdmVyeS1yZXBvcnRlci5qcyc7XG5pbXBvcnQgdHlwZSB7IFByZWNsYWltZWRJbmxpbmVTdGFydCB9IGZyb20gJy4vc3RlcC1leGVjdXRvci5qcyc7XG5pbXBvcnQgeyB1bnNlcmlhbGl6YWJsZVN0ZXBJbnB1dFBsYWNlaG9sZGVyIH0gZnJvbSAnLi91bnNlcmlhbGl6YWJsZS1zdGVwLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcyB7XG4gIHN1c3BlbnNpb246IFdvcmtmbG93U3VzcGVuc2lvbjtcbiAgd29ybGQ6IFdvcmxkO1xuICBydW46IFdvcmtmbG93UnVuO1xuICBzcGFuPzogU3BhbjtcbiAgcmVxdWVzdElkPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHJ1bnRpbWUncyBsb2FkZWQgZXZlbnQgbG9nLiBFdmVyeSBldmVudCBjcmVhdGlvbiB0aGlzIHN1c3BlbnNpb24gbWFrZXNcbiAgICogbmFtZXMgdGhlIHBvc2l0aW9uIGl0IHdhcyBkZXJpdmVkIGZyb20sIHNvIGEgYmFja2VuZCB0aGF0IGhhcyByZWNvcmRlZFxuICAgKiBldmVudHMgdGhlIHJlcGxheSBkaWQgbm90IHNlZSBjYW4gcmVwb3J0IHRoZW0gYmFjayBvbiB0aGUgd3JpdGUsIG9yLCBpZlxuICAgKiBpdCB3b3VsZCByYXRoZXIgcmVmdXNlIHRoYW4gcmVwb3J0LCByZWplY3QgaXQgd2l0aCBhIDQxMi4gQSByZWplY3Rpb24gaXNcbiAgICogbm90IHJldHJpZWQgaGVyZTogdGhlIGV2ZW50J3MgY29ycmVsYXRpb24gaWQgd2FzIG1pbnRlZCBieSAqdGhpcyogcmVwbGF5J3NcbiAgICogc2VlZGVkIHNlcXVlbmNlLCBzbyByZS1jb21taXR0aW5nIGl0IGFnYWluc3QgYSBjb3JyZWN0ZWQgbG9nIHdvdWxkIHBlcnNpc3RcbiAgICogYW4gZXZlbnQgbm8gY29ycmVjdCByZXBsYXkgcHJvZHVjZXMuIFRoZSBjYWxsZXIgcmVzdGFydHMgdGhlIHJlcGxheVxuICAgKiBpbnN0ZWFkLlxuICAgKlxuICAgKiBFeHRlbmRlZCBpbiBwbGFjZSBieSB3aGF0IHRob3NlIHdyaXRlcyByZXBvcnQgYmFjayDigJQgdGhlIGV2ZW50cyBvbiBzbG90c1xuICAgKiB0aGV5IHNraXBwZWQgb3ZlciwgYW5kIChvbiB0aGUgaG9vayBjcmVhdGUpIHRoZSBpbmxpbmUgZGVsdGEgc2luY2UgaXRzXG4gICAqIGN1cnNvci4gV2hldGhlciB0aGUgbG9nIGlzIGNvbXBsZXRlIGFmdGVyd2FyZHMgaXMgYW5zd2VyZWQgYnlcbiAgICoge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0LmV2ZW50TG9nQ2FycmllZEZvcndhcmR9LlxuICAgKi9cbiAgZXZlbnRMb2c/OiBMb2FkZWRFdmVudExvZztcbiAgLyoqXG4gICAqIFR1cmJvIG1vZGUgb25seTogYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgb25jZSB0aGUgYmFja2dyb3VuZGVkXG4gICAqIGBydW5fc3RhcnRlZGAgaGFzIGxhbmRlZCAodGhlIHJ1biBleGlzdHMpLiBXaGVuIHByZXNlbnQsIGV2ZXJ5IHdvcmxkIHdyaXRlXG4gICAqIHRoaXMgc3VzcGVuc2lvbiBwZXJmb3JtcyAoYGhvb2tfY3JlYXRlZGAsIGB3YWl0X2NyZWF0ZWRgLCBlYWdlciBvdmVyZmxvd1xuICAgKiBgc3RlcF9jcmVhdGVkYCwg4oCmKSBpcyBnYXRlZCBvbiBpdCBzbyB0aGUgd3JpdGUgbmV2ZXIgcmFjZXMgYWhlYWQgb2YgdGhlXG4gICAqIHJ1bidzIGNyZWF0aW9uLiBUaGUgcHVyZSBpbmxpbmUgaG90IHBhdGggZGVmZXJzIGFsbCBvZiBpdHMgc3RlcHMgYW5kIHdyaXRlc1xuICAgKiBub3RoaW5nIGhlcmUsIHNvIGl0IG5ldmVyIGF3YWl0cyB0aGlzIGJhcnJpZXIuIGB1bmRlZmluZWRgIG91dHNpZGUgdHVyYm8sXG4gICAqIHdoZXJlIGBydW5fc3RhcnRlZGAgd2FzIGFscmVhZHkgYXdhaXRlZCB1cCBmcm9udC5cbiAgICovXG4gIHJ1blJlYWR5QmFycmllcj86IFByb21pc2U8dW5rbm93bj47XG4gIC8qKiBPbmUtc2hvdCB0ZWxlbWV0cnkgcmVwb3J0ZXIsIGFjdGl2YXRlZCBvbmx5IGFmdGVyIHJlcGxheSBoYXMgcmVjb3ZlcmVkLiAqL1xuICByZXBsYXlSZWNvdmVyeVJlcG9ydGVyPzogUmVwbGF5UmVjb3ZlcnlSZXBvcnRlcjtcbiAgLyoqXG4gICAqIFJlc2lsaWVudCBzdGVwIGRpc3BhdGNoOiB3aGVuIHByb3ZpZGVkIChhbmQgdGhlIHBlci1zdGVwIGVsaWdpYmlsaXR5IGdhdGVzXG4gICAqIHBhc3MsIHNlZSB0aGUgc3RlcCBvcHMgYmVsb3cpLCBlYWNoIG5ld2x5IGNyZWF0ZWQgbm9uLWlubGluZSBzdGVwJ3NcbiAgICogYHN0ZXBfY3JlYXRlZGAgd3JpdGUgaXMgcGFyYWxsZWxpemVkIHdpdGggaXRzIHN0ZXAtZXhlY3V0aW9uIHF1ZXVlXG4gICAqIHB1Ymxpc2gsIGFuZCB0aGUgcXVldWUgbWVzc2FnZSBjYXJyaWVzIHRoZSBzZXJpYWxpemVkIHN0ZXAgaW5wdXRcbiAgICogKGBzdGVwSW5wdXRgKSBzbyB0aGUgY29uc3VtZXIgY2FuIGlkZW1wb3RlbnRseSByZS1lbnN1cmUgdGhlIGV2ZW50IGlmIHRoZVxuICAgKiBkaXJlY3Qgd3JpdGUgZmFpbGVkIHRyYW5zaWVudGx5LiBTdGVwcyBxdWV1ZWQgdGhpcyB3YXkgYXJlIHJlcG9ydGVkIGluXG4gICAqIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdC5xdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHN9IHNvIHRoZSBjYWxsZXJcbiAgICogc2tpcHMgdGhlbSBpbiBpdHMgb3duIGRpc3BhdGNoIHBhc3MuIE9taXR0ZWQgYnkgY2FsbGVycyB0aGF0IG11c3Qgbm90XG4gICAqIHF1ZXVlICh0ZXJtaW5hbCBkcmFpbiwgdGVzdHMpOyBjcmVhdGVzIHRoZW4gYmVoYXZlIGV4YWN0bHkgYXMgYmVmb3JlLlxuICAgKi9cbiAgc3RlcERpc3BhdGNoPzoge1xuICAgIC8qKiBUaGUgdW5pZmllZCB3b3JrZmxvdyBxdWV1ZSB0aGlzIHJ1bidzIHN0ZXAgbWVzc2FnZXMgYXJlIHB1Ymxpc2hlZCB0by4gKi9cbiAgICBxdWV1ZU5hbWU6IFZhbGlkUXVldWVOYW1lO1xuICAgIC8qKlxuICAgICAqIExhemlseSByZXNvbHZlcyB0aGUgdHJhY2UgY2FycmllciB0byBzdGFtcCBvbiB0aGUgc3RlcCBtZXNzYWdlcy5cbiAgICAgKiBDYWxsZWQgYXQgbW9zdCBvbmNlIHBlciBzdXNwZW5zaW9uIChtZW1vaXplZCBoZXJlKS5cbiAgICAgKi9cbiAgICBnZXRUcmFjZUNhcnJpZXI6ICgpID0+IFByb21pc2U8VHJhY2VDYXJyaWVyPjtcbiAgfTtcbiAgLyoqXG4gICAqIElubGluZSBzdGVwIG93bmVyc2hpcDogdGhlIHF1ZXVlIG1lc3NhZ2UgSUQgb2YgdGhlIGludm9jYXRpb24gdGhpc1xuICAgKiBzdXNwZW5zaW9uIHJ1bnMgaW4gKHRoZSBxdWV1ZSBoYW5kbGVyJ3MgbWV0YSkuIFdoZW4gcHJlc2VudCBBTkQgdGhlXG4gICAqIGJhdGNoZWQgZmFuLW91dCBlbmdhZ2VzLCB0aGUgbGF6eS1pbmxpbmUgc3RlcHMnIGRlZmVycmVkIHdyaXRlcyBhcmVcbiAgICogZm9sZGVkIGludG8gdGhlIGJhdGNoIGFzIGBzdGVwX2NyZWF0ZWRgICsgYHN0ZXBfc3RhcnRlZGAgcGFpcnMgKHRoZVxuICAgKiBzdGFydGVkIHJvdyBzdGFtcGVkIHdpdGggdGhpcyBJRCwgZXhhY3RseSBsaWtlIHRoZSBsYXp5IGNsYWltIGl0XG4gICAqIHJlcGxhY2VzKSwgcHJlLWNsYWltaW5nIHRoZSBzdGVwcyB0aGUgY2FsbGVyIGlzIGFib3V0IHRvIHJ1biBpbmxpbmUuIFNlZVxuICAgKiB7QGxpbmsgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQuaW5saW5lQ2xhaW1zfS4gQ2FsbGVycyB0aGF0IG5ldmVyXG4gICAqIGlubGluZS1leGVjdXRlICh0ZXJtaW5hbCBkcmFpbikgb21pdCBpdCwga2VlcGluZyB0aGVpciBsYXp5IHN0ZXBzIG9uIHRoZVxuICAgKiBwbGFpbiBkZWZlcnJlZCBwYXRoLlxuICAgKi9cbiAgb3duZXJNZXNzYWdlSWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBMZXRzIHRoZSBiYXRjaGVkIGZhbi1vdXQgcmV0dXJuIGJlZm9yZSBldmVyeSBjaHVuayBoYXMgY29tbWl0dGVkOiBvbmx5XG4gICAqIHRoZSBjaHVuayBjYXJyeWluZyB0aGUgcHJlLWNsYWltZWQgaW5saW5lIHBhaXJzIGdhdGVzIHRoZSBoYW5kbGVyJ3NcbiAgICogcmV0dXJuIChpdHMgY2xhaW1zIGFyZSB3aGF0IHRoZSBjYWxsZXIgc3RhcnRzIGJvZGllcyBmcm9tKSwgd2hpbGUgdGhlXG4gICAqIHRyYWlsaW5nIGNodW5rcycgY29tbWl0cyAoYW5kIGV2ZXJ5IGNodW5rJ3MgaW4tZmx1c2ggc3RlcC1tZXNzYWdlXG4gICAqIHB1Ymxpc2hlcykgcmlkZSB7QGxpbmsgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQuZGVmZXJyZWRCYXRjaFdvcmt9LiBBXG4gICAqIGNhbGxlciB0aGF0IG9wdHMgaW4gTVVTVCBhd2FpdCB0aGF0IHByb21pc2UgYmVmb3JlIGFja2luZyBpdHMgZGVsaXZlcnk6XG4gICAqIHRoZSBkdXJhYmlsaXR5IGNvbnRyYWN0IChcImV2ZXJ5IGNyZWF0ZSBkdXJhYmxlIGJlZm9yZSBhY2tcIikgbW92ZXMgZnJvbVxuICAgKiB0aGUgaGFuZGxlcidzIHJldHVybiB0byB0aGF0IGpvaW4sIGFuZCBub3RoaW5nIGVsc2UgcmUtZHJpdmVzIGEgbG9zdFxuICAgKiB0cmFpbGluZyBjaHVuay4gQ2FsbGVycyB0aGF0IGRvbid0IG9wdCBpbiAodGVybWluYWwgZHJhaW4sIGRlZmF1bHQpXG4gICAqIGtlZXAgdGhlIGV2ZXJ5dGhpbmctZHVyYWJsZS1hdC1yZXR1cm4gYmVoYXZpb3IuXG4gICAqL1xuICBhbGxvd0RlZmVycmVkQmF0Y2hXb3JrPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgaGFuZGxpbmcgYSBzdXNwZW5zaW9uLiBSZXR1cm5zIHBlbmRpbmcgc3RlcCBpdGVtcyBzbyB0aGUgY2FsbGVyXG4gKiBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQge1xuICAvKiogUGVuZGluZyBzdGVwIGl0ZW1zIHdpdGggZXZlbnRzIGNyZWF0ZWQgYnV0IE5PVCBxdWV1ZWQgKi9cbiAgcGVuZGluZ1N0ZXBzOiBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbVtdO1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gSURzIGZvciB3aGljaCB0aGlzIHN1c3BlbnNpb24gY2FsbCBhY3R1YWxseSB3cm90ZSB0aGVcbiAgICogc3RlcF9jcmVhdGVkIGV2ZW50IChhcyBvcHBvc2VkIHRvIGNhdGNoaW5nIEVudGl0eUNvbmZsaWN0RXJyb3IgYmVjYXVzZVxuICAgKiBhIGNvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSBpdCBmaXJzdCkuIE9ubHkgdGhlIGhhbmRsZXIgdGhhdCB3cm90ZSB0aGVcbiAgICogc3RlcF9jcmVhdGVkIGV2ZW50IHNob3VsZCBxdWV1ZSAvIGlubGluZS1leGVjdXRlIHRoZSBzdGVwOyB0aGlzXG4gICAqIGd1YXJhbnRlZXMgYSBzaW5nbGUgb3duZXIgcGVyIHN0ZXAsIGV2ZW4gd2hlbiBtdWx0aXBsZSBoYW5kbGVycyByYWNlXG4gICAqIGludG8gdGhlIHNhbWUgYmF0Y2ggYm91bmRhcnkuXG4gICAqL1xuICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOiBTZXQ8c3RyaW5nPjtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIElEcyBvZiBzdGVwcyB3aG9zZSBhcmd1bWVudHMgZmFpbGVkIHRvIHNlcmlhbGl6ZS4gRWFjaCB3YXNcbiAgICogZmluYWxpemVkIGhlcmUgYXMgYHN0ZXBfY3JlYXRlZGAgKHdpdGggYSBwbGFjZWhvbGRlciBpbnB1dDsgdGhlIHJlYWxcbiAgICogaW5wdXQgaXMgcHJlY2lzZWx5IHdoYXQgcmVmdXNlZCB0byBzZXJpYWxpemUpIGZvbGxvd2VkIGJ5IGBzdGVwX2ZhaWxlZGBcbiAgICogY2FycnlpbmcgdGhlIFNlcmlhbGl6YXRpb25FcnJvciwgc28gdGhlIG5leHQgcmVwbGF5IHJlamVjdHMgdGhlIHN0ZXAnc1xuICAgKiBwcm9taXNlIGFuZCBhIHRyeS9jYXRjaCBhcm91bmQgdGhlIHN0ZXAgY2FsbCBvYnNlcnZlcyB0aGUgZXJyb3IsXG4gICAqIGV4YWN0bHkgbGlrZSBhIHN0ZXAtYm9keSBmYWlsdXJlLiBObyBzdGVwLWV4ZWN1dGlvbiBtZXNzYWdlIGlzXG4gICAqIGRpc3BhdGNoZWQgZm9yIHRoZXNlLCBzbyB0aGUgY2FsbGVyIE1VU1QgZm9yY2UgYW4gaW4tcHJvY2VzcyByZXBsYXk6XG4gICAqIHdoZW4gdGhlIGZhaWxlZCBzdGVwIHdhcyB0aGUgb25seSBwZW5kaW5nIHdvcmssIG5vdGhpbmcgZWxzZSB3aWxsIGV2ZXJcbiAgICogcmUtaW52b2tlIHRoZSBydW4gdG8gb2JzZXJ2ZSB0aGUgdGVybWluYWwgZXZlbnQuXG4gICAqL1xuICBmYWlsZWRTdGVwQ29ycmVsYXRpb25JZHM6IFNldDxzdHJpbmc+O1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gSURzIG9mIHN0ZXBzIHRoaXMgc3VzcGVuc2lvbiBjYWxsIGFscmVhZHkgcHVibGlzaGVkXG4gICAqIHN0ZXAtZXhlY3V0aW9uIHF1ZXVlIG1lc3NhZ2VzIGZvciwgdmlhIHJlc2lsaWVudCBzdGVwIGRpc3BhdGNoICh0aGVcbiAgICogYHN0ZXBfY3JlYXRlZGAgd3JpdGUgcGFyYWxsZWxpemVkIHdpdGggYSBgc3RlcElucHV0YC1jYXJyeWluZyBxdWV1ZVxuICAgKiBwdWJsaXNoKS4gVGhlIGNhbGxlciBNVVNUIE5PVCBkaXNwYXRjaCB0aGVzZSBhZ2FpbjogdGhlIG1lc3NhZ2UgaXNcbiAgICogYWxyZWFkeSBvdXQgKGEgZHVwbGljYXRlIHdvdWxkIGJlIGRlZHVwZWQgYnkgaXRzIGlkZW1wb3RlbmN5IGtleSwgYnV0XG4gICAqIGNvc3RzIGEgd2FzdGVkIHJvdW5kLXRyaXApLiBFbXB0eSB3aGVuIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcy5zdGVwRGlzcGF0Y2h9XG4gICAqIHdhcyBub3QgcHJvdmlkZWQgb3Igbm8gc3RlcCB3YXMgZWxpZ2libGUuXG4gICAqL1xuICBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHM6IFNldDxzdHJpbmc+O1xuICAvKipcbiAgICogSG93IG1hbnkgZXZlbnRzIHRoaXMgcGhhc2UncyB3cml0ZXMgcmVwb3J0ZWQgYmFjayBhcyBvY2N1cHlpbmcgc2xvdHMgdGhleVxuICAgKiBza2lwcGVkIG92ZXIsIGFscmVhZHkgbWVyZ2VkIGludG8gdGhlIGNhbGxlcidzIGBldmVudExvZy5ldmVudHNgLiBOb256ZXJvXG4gICAqIG1lYW5zIHRoZSBhcnJheSB3YXMgcmVvcmRlcmVkIHRvIHJlc3RvcmUgc2xvdCBvcmRlciwgc28gYW55IGluZGV4IHRoZVxuICAgKiBjYWxsZXIgY2FjaGVkIGludG8gaXQgKHBheWxvYWQgcHJld2FybSBzY2FuIHBvc2l0aW9uKSBpcyBzdGFsZS5cbiAgICovXG4gIHJlcG9ydGVkRXZlbnRDb3VudDogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIHN0ZXBzIHdob3NlIGBzdGVwX2NyZWF0ZWRgIHdyaXRlcyB3ZXJlIGludGVudGlvbmFsbHkgZGVmZXJyZWQgc28gdGhlXG4gICAqIGNhbGxlciBjYW4gcnVuIHRoZW0gaW5saW5lIHZpYSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV2ZW50cyAod2hpY2ggY3JlYXRlXG4gICAqIHRoZSBzdGVwIG9uIHRoZSBmbHkpLCBzYXZpbmcgb25lIHdvcmxkIHJvdW5kLXRyaXAgcGVyIGlubGluZSBzdGVwLiBVcCB0b1xuICAgKiBgZ2V0TWF4SW5saW5lU3RlcHMoKWAgc3RlcHMgYXJlIGRlZmVycmVkOyB0aGUgY2FsbGVyIHJ1bnMgdGhlbSBpbmxpbmUgaW5cbiAgICogcGFyYWxsZWwgYW5kIHF1ZXVlcyB0aGUgcmVzdC4gRW1wdHkgd2hlbiBubyBzdGVwIHdhcyBkZWZlcnJlZCAobm90aGluZ1xuICAgKiBwZW5kaW5nLCBvciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgaXMgcHJlc2VudCBzbyBub3RoaW5nIGlzXG4gICAqIGV4ZWN1dGVkIGlubGluZSkuIFRoZSBjYWxsZXIgcGFzc2VzIGVhY2ggYGRlaHlkcmF0ZWRJbnB1dGAgc3RyYWlnaHQgdG9cbiAgICogYGV4ZWN1dGVTdGVwYCwgd2hpY2ggc2VuZHMgaXQgYXMgdGhlIGBzdGVwX3N0YXJ0ZWRgIHBheWxvYWQuIFRoZSBhdG9taWNcbiAgICogY3JlYXRlLWNsYWltIGluc2lkZSBlYWNoIGBzdGVwX3N0YXJ0ZWRgIGlzIHRoZSBleGFjdGx5LW9uZS1vd25lciBnYXRlIHRoYXRcbiAgICogdGhlIHN0YW5kYWxvbmUgYHN0ZXBfY3JlYXRlZGAgcHJvdmlkZWQgYmVmb3JlOiB0aGUgbG9zZXIgb2YgdGhlIHJhY2UgZ2V0c1xuICAgKiBgRW50aXR5Q29uZmxpY3RFcnJvcmAg4oaSIGBza2lwcGVkYCBhbmQgZG9lcyBub3QgcnVuIHRoZSBib2R5LlxuICAgKi9cbiAgbGF6eUlubGluZVN0ZXBzOiBBcnJheTx7XG4gICAgY29ycmVsYXRpb25JZDogc3RyaW5nO1xuICAgIHN0ZXBOYW1lOiBzdHJpbmc7XG4gICAgZGVoeWRyYXRlZElucHV0OiBTZXJpYWxpemVkRGF0YTtcbiAgfT47XG4gIC8qKlxuICAgKiBQcmUtY2xhaW1lZCBpbmxpbmUgc3RhcnRzLCBieSBjb3JyZWxhdGlvbiBpZDogdGhlIHBlci1zdGVwIHZlcmRpY3RzIG9mXG4gICAqIHRoZSBgc3RlcF9jcmVhdGVkYCArIGBzdGVwX3N0YXJ0ZWRgIHBhaXJzIHRoZSBiYXRjaGVkIGZhbi1vdXQgY29tbWl0dGVkXG4gICAqIGZvciB0aGUgbGF6eS1pbmxpbmUgc3RlcHMuIEEgc3RlcCB3aXRoIGFuIGVudHJ5IGhlcmUgaXMgcGFzc2VkIHRvXG4gICAqIGBleGVjdXRlU3RlcGAgYXMgYHByZWNsYWltZWRTdGFydGAgSU5TVEVBRCBvZiBgbGF6eVN0ZXBJbnB1dGA6IGl0c1xuICAgKiBpbnB1dCBhbHJlYWR5IHJvZGUgdGhlIHBhaXIsIGFuZCB0aGUgY2xhaW0gaXMgc2V0dGxlZDogYG93bmVkOiB0cnVlYFxuICAgKiBjYXJyaWVzIHRoZSBzdGFydGVkIGF0dGVtcHQtMSBlbnRpdHkgKGlucHV0IHJlLWF0dGFjaGVkKSBzbyB0aGUgYm9keVxuICAgKiBydW5zIHN0cmFpZ2h0IG9mZiB0aGUgYmF0Y2ggY29tbWl0IHdpdGggbm8gc3RhcnQgd3JpdGUgb2YgaXRzIG93bjtcbiAgICogYG93bmVkOiBmYWxzZWAgbG9zdCB0aGUgcGFpcidzIGF0b21pYyBjcmVhdGUtY2xhaW0gdG8gYSBjb25jdXJyZW50XG4gICAqIHdyaXRlciwgYW5kIGV4ZWN1dGVTdGVwIHJldHVybnMgYHNraXBwZWRgIHdpdGhvdXQgcnVubmluZyB0aGUgYm9keSxcbiAgICogdGhlIHNhbWUgb3V0Y29tZSBhcyBsb3NpbmcgdGhlIGxhenkgY2xhaW0uIEVtcHR5IHdoZW5ldmVyIHRoZSBmb2xkIGRpZFxuICAgKiBub3QgZW5nYWdlIChiYXRjaGluZyBvZmYsIG5vIGBvd25lck1lc3NhZ2VJZGAsIG9yIHRoZSBsb25lLWlubGluZSBjYXNlLFxuICAgKiB3aGljaCBrZWVwcyB0aGUgb3B0aW1pc3RpYyBsYXp5IHBhdGggYW5kIGl0cyBjbGFpbS9ib2R5IG92ZXJsYXApLlxuICAgKlxuICAgKiBDcmFzaCB3aW5kb3c6IHRoZSBwYWlyIGNvbW1pdHMgYmVmb3JlIHRoZSBjYWxsZXIgcnVucyB0aGUgYm9keSwgc28gYVxuICAgKiBjcmFzaCBiZXR3ZWVuIHRoZW0gbGVhdmVzIGEgc3RhcnRlZCBzdGVwIHN0YW1wZWQgd2l0aCB0aGlzIG1lc3NhZ2Unc1xuICAgKiBJRC4gUmVkZWxpdmVyeSBvZiB0aGUgc2FtZSBtZXNzYWdlIHJlLWV4ZWN1dGVzIGl0IHZpYSB0aGUgb3duZWQtcmVjb3ZlcnlcbiAgICogcGF0aCwgdGhlIGV4YWN0IG1hY2hpbmVyeSB0aGUgbGF6eSBjbGFpbSdzIGNyYXNoIHdpbmRvdyBhbHJlYWR5IHVzZXMuXG4gICAqL1xuICBpbmxpbmVDbGFpbXM6IE1hcDxzdHJpbmcsIFByZWNsYWltZWRJbmxpbmVTdGFydD47XG4gIC8qKlxuICAgKiBUaGUgYmF0Y2hlZCBmYW4tb3V0J3MgZGVmZXJyZWQgd29yaywgcHJlc2VudCBvbmx5IHdoZW4gdGhlIGNhbGxlciBvcHRlZFxuICAgKiBpbiB2aWEge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zLmFsbG93RGVmZXJyZWRCYXRjaFdvcmt9IGFuZFxuICAgKiB0cmFpbGluZyB3b3JrIGV4aXN0czogdGhlIGNvbW1pdHMgb2YgZXZlcnkgY2h1bmsgZXhjZXB0IHRoZSBwYWlyIGNodW5rLFxuICAgKiBwbHVzIGV2ZXJ5IGNodW5rJ3Mgc3RlcC1tZXNzYWdlIHB1Ymxpc2hlcyAoZWFjaCBjaGFpbmVkIG9uIElUUyBPV05cbiAgICogY2h1bmsncyBjb21taXQsIHNvIHB1Ymxpc2gtYWZ0ZXItY3JlYXRlIGhvbGRzIHBlciBzdGVwKS4gVGhlIGNhbGxlclxuICAgKiBNVVNUIGF3YWl0IGl0IGJlZm9yZSBhY2tpbmc6IGEgcmVqZWN0aW9uIGhlcmUgaXMgYSBmYWlsZWQgc3VzcGVuc2lvblxuICAgKiB3cml0ZSBhbmQgZmFpbHMgdGhlIGRlbGl2ZXJ5IGV4YWN0bHkgYXMgaXQgd291bGQgaGF2ZSBhdCB0aGUgaGFuZGxlcidzXG4gICAqIHJldHVybi4gU3RlcHMgd2hvc2UgbWVzc2FnZXMgdGhpcyB3b3JrIHB1Ymxpc2hlcyBhcmUgYWxyZWFkeSBpblxuICAgKiB7QGxpbmsgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzfSBhdCByZXR1cm4gdGltZS5cbiAgICovXG4gIGRlZmVycmVkQmF0Y2hXb3JrPzogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCwgaWYgYW55OiBzZWNvbmRzIHVudGlsIGl0IGVsYXBzZXMgYW5kIHRoZVxuICAgKiBjb3JyZWxhdGlvbklkIG9mIHRoZSB3YWl0IHRoYXQgcHJvZHVjZWQgdGhhdCB0aW1lb3V0LiBUaGVcbiAgICogY29ycmVsYXRpb25JZCBzZWVkcyB0aGUgaWRlbXBvdGVuY3kga2V5IGZvciB0aGUgd2FpdC1jb250aW51YXRpb25cbiAgICogcXVldWUgbWVzc2FnZSBzbyB0aGF0IHJlcGVhdGVkIHN1c3BlbnNpb24gcGFzc2VzIG92ZXIgdGhlIHNhbWVcbiAgICogcGVuZGluZyB3YWl0IGNvbGxhcHNlIGludG8gYSBzaW5nbGUgZGVsYXllZCBjb250aW51YXRpb24uXG4gICAqL1xuICB3YWl0VGltZW91dD86IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfTtcbiAgLyoqXG4gICAqIFdoZXRoZXIgYSBob29rIGNyZWF0ZSBjb21taXR0ZWQgYSBgaG9va19jb25mbGljdGAg4oCUIHRoZSB0b2tlbiB3YXMgYWxyZWFkeVxuICAgKiBjbGFpbWVkLCBzbyB0aGlzIHJ1bidzIGhvb2sgd2FzIG5ldmVyIGNyZWF0ZWQgYW5kIHRoZSB3b3JrZmxvdyBtdXN0XG4gICAqIG9ic2VydmUgdGhlIGNvbmZsaWN0IGJlZm9yZSBhbnl0aGluZyBlbHNlIHRoaXMgc3VzcGVuc2lvbiBzY2hlZHVsZWQgcnVucy5cbiAgICogVGhlIGNhbGxlciBhbnN3ZXJzIGl0IGJ5IGFkdmFuY2luZyB0aGUgd29ya2Zsb3cgb3ZlciB0aGUgY29tbWl0dGVkIGV2ZW50LlxuICAgKi9cbiAgaGFzSG9va0NvbmZsaWN0OiBib29sZWFuO1xuICAvKiogV2hldGhlciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgbmVlZHMgdGhlIHdvcmtmbG93IHRvIGNvbnRpbnVlIGltbWVkaWF0ZWx5ICovXG4gIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDb3JyZWxhdGlvbiBpZHMgb2YgdGhlIGhvb2tzIHRoaXMgc3VzcGVuc2lvbiBjb21taXR0ZWQgYSBgaG9va19jcmVhdGVkYFxuICAgKiBmb3Igd2hpbGUgYSBgaG9vay5nZXRDb25mbGljdCgpYCBhd2FpdGVyIHdhcyB3YWl0aW5nIG9uIGl0IOKAlCB0aGUgZXZlbnRzXG4gICAqIHRoYXQgcmVzb2x2ZSB0aG9zZSBhd2FpdGVycyBvbiB0aGUgbmV4dCBwYXNzLiBFbXB0eSBleGFjdGx5IHdoZW5cbiAgICoge0BsaW5rIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb259IGlzIGZhbHNlLlxuICAgKlxuICAgKiBSZXBvcnRlZCBieSBpZCwgbm90IGp1c3QgY291bnRlZCwgc28gYSBjYWxsZXIgdGhhdCBjb250aW51ZXMgaW4gdGhpc1xuICAgKiBwcm9jZXNzIGNhbiB0ZWxsIGEgY29udGludWF0aW9uIHRoYXQgZ290IHNvbWV3aGVyZSBmcm9tIG9uZSB0aGF0IGlzXG4gICAqIHJlcGVhdGluZzogYSB3b3JrZmxvdyBtYXkgY3JlYXRlIG9uZSBhd2FpdGVkIGhvb2sgYWZ0ZXIgYW5vdGhlciwgYW5kIGVhY2hcbiAgICogbmV3IGlkIGlzIGEgcGFzcyB0aGF0IG1hZGUgcHJvZ3Jlc3MsIHdoaWxlIHRoZSBzYW1lIGlkIGNvbWluZyBiYWNrIG1lYW5zXG4gICAqIHRoZSBwYXNzIHJhbiBvdmVyIGEgbG9nIHRoYXQgc3RpbGwgZGlkIG5vdCBob2xkIGl0cyBldmVudCBhbmQgY29udGludWluZ1xuICAgKiBhZ2FpbiBjYW5ub3QgY2hhbmdlIHRoYXQuXG4gICAqL1xuICBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzOiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIGlkcyBvZiB0aGUgaG9va3Mgd2hvc2UgY3JlYXRlIGNvbW1pdHRlZCBhIGBob29rX2NvbmZsaWN0YC5cbiAgICogRW1wdHkgZXhhY3RseSB3aGVuIHtAbGluayBoYXNIb29rQ29uZmxpY3R9IGlzIGZhbHNlLlxuICAgKlxuICAgKiBCeSBpZCBmb3IgdGhlIHNhbWUgcmVhc29uIGFzIHtAbGluayBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzfSwgYW5kXG4gICAqIGFnYWluc3QgdGhlIHNhbWUgaGF6YXJkOiBhIGNvbmZsaWN0IGlzIHJlc29sdmVkIGJ5IHRoZSBgaG9va19jb25mbGljdGBcbiAgICogdGhpcyBzdXNwZW5zaW9uIGNvbW1pdHRlZCwgYW5kIHVudGlsIHRoZSB3b3JrZmxvdyBvYnNlcnZlcyBpdCB0aGUgaG9va1xuICAgKiBzdGF5cyBpbiB0aGUgaW52b2NhdGlvbnMgcXVldWUgYW5kIHRoZSBuZXh0IHBhc3Mgd3JpdGVzIHRoZSBjcmVhdGUgYWdhaW4uXG4gICAqIEEgZnJlc2ggaWQgaXMgcHJvZ3Jlc3M7IHRoZSBzYW1lIGlkIGNvbWluZyBiYWNrIGlzIGEgcGFzcyB0aGF0IHJhbiBvdmVyIGFcbiAgICogbG9nIHdoaWNoIHN0aWxsIGRpZCBub3QgaG9sZCB0aGUgZXZlbnQsIHNvIGNvbnRpbnVpbmcgYWdhaW4gY2Fubm90IGNoYW5nZVxuICAgKiB0aGF0LlxuICAgKi9cbiAgaG9va0NvbmZsaWN0Q29ycmVsYXRpb25JZHM6IHN0cmluZ1tdO1xuICAvKipcbiAgICogV2hldGhlciB0aGUgY2FsbGVyJ3MgYGV2ZW50TG9nYCBub3cgaG9sZHMgZXZlcnkgZXZlbnQgdGhpcyBzdXNwZW5zaW9uXG4gICAqIGNvbW1pdHRlZCwgc28gYSBjYWxsZXIgdGhhdCBjb250aW51ZXMgaW4gdGhpcyBwcm9jZXNzIGNhbiByZXBsYXkg4oCUIG9yXG4gICAqIHJlc3VtZSBhIHJldGFpbmVkIFZNIOKAlCBzdHJhaWdodCBvZmYgaXQgd2l0aCBubyByZWFkLlxuICAgKlxuICAgKiBUcnVlIG9ubHkgd2hlbiB0aGUgaG9vayBjcmVhdGUncyBpbmxpbmUgZGVsdGEgY2FtZSBiYWNrIGNvbXBsZXRlIGFuZCB3YXNcbiAgICogZm9sZGVkIGluIChzZWUgYGhvb2tEZWx0YUN1cnNvcmAgYmVsb3cpLCBhbmQgbm90aGluZyBlbHNlIGluIHRoaXNcbiAgICogc3VzcGVuc2lvbiB3cm90ZSBhbiBldmVudC4gRmFsc2Ugd2hlbmV2ZXIgYSByZWFkIGlzIG5lZWRlZCBmaXJzdDogbm9cbiAgICogZGVsdGEgd2FzIGFza2VkIGZvciBvciByZXR1cm5lZCwgaXQgd2FzIHRydW5jYXRlZCwgb3IgYSBzdGVwIC8gd2FpdCAvXG4gICAqIGF0dHJpYnV0ZSAvIGFib3J0IHdyaXRlIGxhbmRlZCBhYm92ZSBpdCBhbmQgaXMgdGhlcmVmb3JlIG5vdCBpbiBpdC5cbiAgICpcbiAgICogSW5kaWZmZXJlbnQgdG8gd2hpY2ggZXZlbnQgdGhlIGNyZWF0ZSBjb21taXR0ZWQ6IHRoZSBkZWx0YSBpcyB0aGUgc2xpY2VcbiAgICogb2YgdGhlIGxvZyBhZnRlciB0aGUgY2FsbGVyJ3MgY3Vyc29yIGVpdGhlciB3YXksIHNvIGl0IGNhcnJpZXMgYVxuICAgKiBgaG9va19jb25mbGljdGAgZXhhY3RseSBhcyBpdCBjYXJyaWVzIGEgYGhvb2tfY3JlYXRlZGAuXG4gICAqL1xuICBldmVudExvZ0NhcnJpZWRGb3J3YXJkOiBib29sZWFuO1xuICAvKiogV2hldGhlciBuYXRpdmUgd29ya2Zsb3cgYXR0cmlidXRlIGV2ZW50cyB3ZXJlIHdyaXR0ZW4gZm9yIHJlcGxheS4gKi9cbiAgaGFzQXR0cmlidXRlRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2hldGhlciB0aGlzIHN1c3BlbnNpb24gY3JlYXRlZCBhbnkgaG9vayAoYGhvb2tfY3JlYXRlZGApIGV2ZW50cy4gVW5saWtlXG4gICAqIGBoYXNIb29rQ29uZmxpY3RgIC8gYGhhc0F3YWl0ZWRIb29rQ3JlYXRpb25gLCB0aGlzIGlzIHRydWUgZXZlbiBmb3IgYSBwbGFpblxuICAgKiBmaXJlLWFuZC1mb3JnZXQgaG9vayB3aXRoIG5vIGNvbmZsaWN0IGFuZCBubyBhd2FpdGVyLiBUdXJibyBtb2RlIHVzZXMgaXQgdG9cbiAgICogZGV0ZWN0IFwiYSBob29rIHdhcyBjcmVhdGVkIHRoaXMgc3VzcGVuc2lvblwiIGFuZCBzdG9wIGZvcmNpbmcgb3B0aW1pc3RpY1xuICAgKiBpbmxpbmUgc3RhcnQgKGEgaG9vayBpbnRyb2R1Y2VzIGxhdGVyIHJlc3VtZSBpbnZvY2F0aW9ucyB0aGF0IGNvdWxkIHJhY2UpLlxuICAgKi9cbiAgaGFzSG9va0V2ZW50czogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFdhbGwtY2xvY2sgbXMgc3BlbnQgY29tbWl0dGluZyB0aGlzIHN1c3BlbnNpb24ncyBgaG9va19jcmVhdGVkYCBldmVudHNcbiAgICogKDAgd2hlbiBpdCBjcmVhdGVkIG5vbmUpLiBUaGUgY2FsbGVyIGFjY3VtdWxhdGVzIHRoaXMgYWNyb3NzIGl0ZXJhdGlvbnNcbiAgICogYW5kIHN1YnRyYWN0cyBpdCBmcm9tIHRoZSBUVEZTIGxhdGVuY3kgbWVhc3VyZW1lbnQsIHNvIHRpbWUgc3BlbnRcbiAgICogZHVyYWJseSBjcmVhdGluZyB0aGUgdXNlcidzIGhvb2tzIGRvZXNuJ3QgY291bnQgYXMgcnVudGltZSBvdmVyaGVhZC5cbiAgICovXG4gIGhvb2tDcmVhdGlvbk1zOiBudW1iZXI7XG4gIC8qKiBFeGFjdCBudW1iZXIgb2Ygd29ya2Zsb3ctY29kZSBleGVjdXRpb25zIG9ic2VydmVkIGR1cmluZyBzZXJpYWxpemF0aW9uLiAqL1xuICBzZXJpYWxpemF0aW9uQmxvY2tlckNvdW50OiBudW1iZXI7XG4gIC8qKiBCb3VuZGVkIHNhbXBsZSB1c2VkIG9ubHkgZm9yIHJldGVudGlvbiBkaWFnbm9zdGljcy4gKi9cbiAgc2VyaWFsaXphdGlvbkJsb2NrZXJzOiBTdXNwZW5zaW9uU2VyaWFsaXphdGlvbkJsb2NrZXJbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uU2VyaWFsaXphdGlvbkJsb2NrZXIgZXh0ZW5kcyBHdWVzdENvZGVFeGVjdXRpb24ge1xuICBzb3VyY2U6ICdzdGVwX2lucHV0JyB8ICdob29rX21ldGFkYXRhJyB8ICdob29rX2Fib3J0JztcbiAgY29ycmVsYXRpb25JZDogc3RyaW5nO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVIb29rRXZlbnQoe1xuICBydW5JZCxcbiAgaG9va0V2ZW50LFxuICBxdWV1ZUl0ZW0sXG4gIHJlcXVlc3RJZCxcbiAgc2luY2VDdXJzb3IsXG4gIGNyZWF0ZUV2ZW50LFxufToge1xuICBydW5JZDogc3RyaW5nO1xuICBob29rRXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdDtcbiAgcXVldWVJdGVtOiBIb29rSW52b2NhdGlvblF1ZXVlSXRlbTtcbiAgcmVxdWVzdElkPzogc3RyaW5nO1xuICAvKipcbiAgICogQ3Vyc29yIHRvIGFzayB0aGUgV29ybGQgZm9yIHRoZSBldmVudC1sb2cgZGVsdGEgYWdhaW5zdCwgb3IgdW5kZWZpbmVkIHRvXG4gICAqIG5vdCBhc2suIFNlZSBgaG9va0RlbHRhQ3Vyc29yYCBpbiB7QGxpbmsgaGFuZGxlU3VzcGVuc2lvbn0gZm9yIHdoZW4gaXQgaXNcbiAgICogc2V0IGFuZCB3aHkgaXQgaXMgYXQgbW9zdCBvbmUgd3JpdGUgcGVyIHN1c3BlbnNpb24uXG4gICAqL1xuICBzaW5jZUN1cnNvcj86IHN0cmluZztcbiAgY3JlYXRlRXZlbnQ6IChcbiAgICBkYXRhOiBDcmVhdGVFdmVudFJlcXVlc3QsXG4gICAgcGFyYW1zPzogQ3JlYXRlRXZlbnRQYXJhbXNcbiAgKSA9PiBQcm9taXNlPEV2ZW50UmVzdWx0Pjtcbn0pOiBQcm9taXNlPHtcbiAgaGFzSG9va0NvbmZsaWN0OiBib29sZWFuO1xuICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBib29sZWFuO1xufT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUV2ZW50KGhvb2tFdmVudCwge1xuICAgICAgcmVxdWVzdElkLFxuICAgICAgLi4uKHNpbmNlQ3Vyc29yID09PSB1bmRlZmluZWQgPyB7fSA6IHsgc2luY2VDdXJzb3IgfSksXG4gICAgfSk7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgd29ybGQgcmV0dXJuZWQgYSBob29rX2NvbmZsaWN0IGV2ZW50IGluc3RlYWQgb2YgaG9va19jcmVhdGVkLlxuICAgIC8vIFRoZSBob29rX2NvbmZsaWN0IGV2ZW50IGlzIHN0b3JlZCBpbiB0aGUgZXZlbnQgbG9nIGFuZCBpcyB3aGF0IHRoZSBuZXh0XG4gICAgLy8gcGFzcyBjb25zdW1lcyB0byBzZXR0bGUgdGhlIGhvb2sncyBhd2FpdGVycyDigJQgcmVqZWN0aW5nIGEgcGF5bG9hZCBhd2FpdCxcbiAgICAvLyByZXNvbHZpbmcgYSBgaG9vay5nZXRDb25mbGljdCgpYCB3aXRoIHRoZSBjb25mbGljdGluZyBydW4uIEFuIGlubGluZVxuICAgIC8vIGRlbHRhIGFza2VkIGZvciBhYm92ZSBjYXJyaWVzIGl0IGp1c3QgYXMgaXQgd291bGQgaGF2ZSBjYXJyaWVkIHRoZVxuICAgIC8vIGhvb2tfY3JlYXRlZCwgc28gdGhlIGNhbGxlciBjYW4gYWR2YW5jZSBvdmVyIGl0IHdpdGhvdXQgYSByZS1pbnZvY2F0aW9uLlxuICAgIGlmIChyZXN1bHQuZXZlbnQ/LmV2ZW50VHlwZSA9PT0gJ2hvb2tfY29uZmxpY3QnKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IHRydWUsXG4gICAgICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGZhbHNlLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IHF1ZXVlSXRlbS5oYXNDb25mbGljdEF3YWl0ZXIgPT09IHRydWUsXG4gICAgfTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdIb29rIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogZmFsc2UsXG4gICAgICAgIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IHF1ZXVlSXRlbS5oYXNDb25mbGljdEF3YWl0ZXIgPT09IHRydWUsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2snLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChpc1dvcmxkVmFsaWRhdGlvbkZhaWx1cmUoZXJyKSkge1xuICAgICAgY29uc3QgZmF0YWwgPSBuZXcgRmF0YWxFcnJvcihcbiAgICAgICAgYGNyZWF0ZUhvb2sgZmFpbGVkIFdvcmxkIHZhbGlkYXRpb246ICR7XG4gICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpXG4gICAgICAgIH1gXG4gICAgICApO1xuICAgICAgZmF0YWwuY2F1c2UgPSBlcnI7XG4gICAgICB0aHJvdyBmYXRhbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlcnI7XG4gIH1cbn1cblxuLyoqXG4gKiBIYW5kbGVzIGEgd29ya2Zsb3cgc3VzcGVuc2lvbiBieSBwcm9jZXNzaW5nIGFsbCBwZW5kaW5nIG9wZXJhdGlvbnMgKGhvb2tzLCBzdGVwcywgd2FpdHMpLlxuICogQ3JlYXRlcyBldmVudHMgZm9yIGFsbCBvcGVyYXRpb25zIGJ1dCBkb2VzIE5PVCBxdWV1ZSBzdGVwIG1lc3NhZ2VzOyByZXR1cm5zIHRoZSBwZW5kaW5nXG4gKiBzdGVwcyBzbyB0aGUgY2FsbGVyIGNhbiBkZWNpZGUgd2hpY2ggdG8gZXhlY3V0ZSBpbmxpbmUgdnMgcXVldWUgdG8gYmFja2dyb3VuZC5cbiAqXG4gKiBQcm9jZXNzaW5nIG9yZGVyOlxuICogMS4gSG9va3MgYXJlIHByb2Nlc3NlZCBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gKiAyLiBTdGVwIGV2ZW50cyBhbmQgd2FpdCBldmVudHMgYXJlIGNyZWF0ZWQgaW4gcGFyYWxsZWxcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVN1c3BlbnNpb24oe1xuICBzdXNwZW5zaW9uLFxuICB3b3JsZCxcbiAgcnVuLFxuICBzcGFuLFxuICByZXF1ZXN0SWQsXG4gIGV2ZW50TG9nLFxuICBydW5SZWFkeUJhcnJpZXIsXG4gIHJlcGxheVJlY292ZXJ5UmVwb3J0ZXIsXG4gIHN0ZXBEaXNwYXRjaCxcbiAgb3duZXJNZXNzYWdlSWQsXG4gIGFsbG93RGVmZXJyZWRCYXRjaFdvcmssXG59OiBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcyk6IFByb21pc2U8U3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQ+IHtcbiAgY29uc3QgcnVuSWQgPSBydW4ucnVuSWQ7XG5cbiAgLy8gVHVyYm8gbW9kZTogaG9sZCBldmVyeSB3b3JsZCB3cml0ZSBiZWxvdyB1bnRpbCB0aGUgYmFja2dyb3VuZGVkXG4gIC8vIGBydW5fc3RhcnRlZGAgaGFzICpzZXR0bGVkKiwgc28gd2UgbmV2ZXIgd3JpdGUgYSBzdGVwL2hvb2svd2FpdCBldmVudCBmb3IgYVxuICAvLyBydW4gdGhhdCBkb2VzIG5vdCBleGlzdCB5ZXQuIEEgbm8tb3Agb3V0c2lkZSB0dXJibyAoYmFycmllciB1bmRlZmluZWQpIGFuZFxuICAvLyBvbiB0aGUgcHVyZSBpbmxpbmUgaG90IHBhdGgsIHdoaWNoIGRlZmVycyBhbGwgc3RlcHMgYW5kIHdyaXRlcyBub3RoaW5nLlxuICAvLyBBd2FpdGluZyB0aGUgc2FtZSAodXN1YWxseSBhbHJlYWR5LXNldHRsZWQpIHByb21pc2UgbW9yZSB0aGFuIG9uY2UgaXMgY2hlYXAuXG4gIC8vIEEgYmFycmllciByZWplY3Rpb24gaXMgc3dhbGxvd2VkIGZvciBvcmRlcmluZyBvbmx5OiBpZiBgcnVuX3N0YXJ0ZWRgIHRydWx5XG4gIC8vIGZhaWxlZCB0aGUgcnVuIGRvZXMgbm90IGV4aXN0LCBzbyB0aGUgc3Vic2VxdWVudCB3cml0ZSBzdXJmYWNlcyB0aGUgcmVhbFxuICAvLyBlcnJvciAocnVuIG5vdCBmb3VuZCAvIGdvbmUpIGFuZCB0aGUgbWVzc2FnZSByZWRlbGl2ZXJzLlxuICBjb25zdCBlbnN1cmVSdW5SZWFkeSA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBpZiAocnVuUmVhZHlCYXJyaWVyKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBydW5SZWFkeUJhcnJpZXI7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gaW50ZW50aW9uYWw6IG9yZGVyaW5nIGJhcnJpZXIgb25seSwgc2VlIGFib3ZlLlxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQXdhaXQgZXZlcnkgb3BlcmF0aW9uIGluIGEgc3VzcGVuc2lvbiBwaGFzZSBiZWZvcmUgbGV0dGluZyBhIGZhaWx1cmVcbiAgICogZXNjYXBlLCBwcmVmZXJyaW5nIGEgc3RhbGUtc25hcHNob3QgKDQxMikgcmVqZWN0aW9uIHdoZW4gb25lIG9jY3VycmVkLlxuICAgKlxuICAgKiBgUHJvbWlzZS5hbGxgIHJlamVjdHMgYXMgc29vbiBhcyBvbmUgb3BlcmF0aW9uIGRvZXMgYW5kIGxlYXZlcyBpdHMgc2libGluZ3NcbiAgICogaW4gZmxpZ2h0LiBUaGF0IG1hdHRlcnMgZm9yIGEgNDEyOiB0aGUgY2FsbGVyIHJlYWN0cyBieSByZWxvYWRpbmcgdGhlIGV2ZW50XG4gICAqIGxvZyBhbmQgcmVzdGFydGluZyB0aGUgcmVwbGF5LCBzbyBhIHNpYmxpbmcgY3JlYXRlIHRoYXQgbGFuZHMgYWZ0ZXIgdGhlXG4gICAqIHJlamVjdGlvbiBlc2NhcGVkIGNvbW1pdHMgYW4gZXZlbnQgd2hvc2UgY29ycmVsYXRpb24gaWQgY2FtZSBmcm9tIHRoZVxuICAgKiBhYmFuZG9uZWQgcmVwbGF5J3Mgc2VlZGVkIHNlcXVlbmNlIChhbiBldmVudCB0aGUgZnJlc2ggcmVwbGF5IG5ldmVyXG4gICAqIHByb2R1Y2VzKSwgYW5kIGl0IHJhY2VzIHRoZSByZXN0YXJ0J3MgcmVsb2FkIHdoaWxlIGRvaW5nIHNvLiBTZXR0bGluZyBmaXJzdFxuICAgKiBtYWtlcyB0aGlzIHBoYXNlJ3Mgd3JpdGUgc2V0IGZpbmFsIGJlZm9yZSB0aGUgY2FsbGVyIGFjdHMgb24gdGhlIGZhaWx1cmUuXG4gICAqIEl0IG1pcnJvcnMgdGhlIHJ1bnRpbWUncyBpbmxpbmUgc3RlcCBjbGFpbSwgd2hpY2ggc2V0dGxlcyB0aGUgaW4tZmxpZ2h0XG4gICAqIHN0ZXAgZXhlY3V0aW9ucyBiZWZvcmUgZXNjYWxhdGluZyBhIDQxMi5cbiAgICpcbiAgICogQSA0MTIgaXMgcHJlZmVycmVkIG92ZXIgYW55IG90aGVyIHJlamVjdGlvbiBpbiB0aGUgc2FtZSBwaGFzZSBiZWNhdXNlIGl0XG4gICAqIGhhcyBhIGRlZmluZWQsIGNoZWFwIHJlY292ZXJ5IChyZXBsYXkgZnJvbSBhIGNvcnJlY3RlZCBsb2cpIHdoaWxlIHRoZVxuICAgKiBvdGhlcnMgZG8gbm90LiBBIGRldGVybWluaXN0aWMgZmFpbHVyZSBzdWNoIGFzIGFuIGF0dHJpYnV0ZS12YWxpZGF0aW9uXG4gICAqIGBGYXRhbEVycm9yYCByZWN1cnMgb24gdGhlIHJlc3RhcnQgYW5kIGZhaWxzIHRoZSBydW4gdGhlbiwgYXQgdGhlIGNvc3Qgb2ZcbiAgICogb25lIGV4dHJhIHJlcGxheS5cbiAgICovXG4gIGNvbnN0IHNldHRsZVBoYXNlID0gYXN5bmMgKG9wczogUHJvbWlzZTx1bmtub3duPltdKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgY29uc3QgcmVhc29ucyA9IChhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQob3BzKSlcbiAgICAgIC5maWx0ZXIoKHIpOiByIGlzIFByb21pc2VSZWplY3RlZFJlc3VsdCA9PiByLnN0YXR1cyA9PT0gJ3JlamVjdGVkJylcbiAgICAgIC5tYXAoKHIpID0+IHIucmVhc29uKTtcbiAgICBpZiAocmVhc29ucy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aHJvdyByZWFzb25zLmZpbmQoKHIpID0+IFByZWNvbmRpdGlvbkZhaWxlZEVycm9yLmlzKHIpKSA/PyByZWFzb25zWzBdO1xuICB9O1xuXG4gIC8vIEV2ZXJ5IHN1c3BlbnNpb24gd3JpdGUgY2FycmllcyByZXBsYXktcmVjb3ZlcnkgdGVsZW1ldHJ5IG9uIHRoZSBmaXJzdCBvbmVcbiAgLy8gdGhhdCBjb21taXRzIGFmdGVyIHJlcGxheSByZWNvdmVyZWQuIEFsbCBzdXNwZW5zaW9uIGV2ZW50cyBhcmVcbiAgLy8gbm9uLXJ1bl9jcmVhdGVkIGV2ZW50cyBvbiB0aGlzIHJ1bidzIGBydW5JZGAuXG4gIGNvbnN0IHJlcG9ydGVyID0gcmVwbGF5UmVjb3ZlcnlSZXBvcnRlciA/PyBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyLmluZXJ0KCk7XG4gIGNvbnN0IGNyZWF0ZUV2ZW50ID0gKGRhdGE6IENyZWF0ZUV2ZW50UmVxdWVzdCwgcGFyYW1zPzogQ3JlYXRlRXZlbnRQYXJhbXMpID0+XG4gICAgcmVwb3J0ZXIud2l0aEV2ZW50Q3JlYXRlKHBhcmFtcywgKHApID0+XG4gICAgICB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBkYXRhLCBwKVxuICAgICk7XG4gIC8vIEFkZHMgdGhlIG9wdGltaXN0aWMtY29uY3VycmVuY3kgZ3VhcmQgd2hlbiB0aGUgY2FsbGVyIHN1cHBsaWVkIGEgbG9hZGVkXG4gIC8vIGV2ZW50IGxvZzsgd2l0aG91dCBvbmUgaXQgY3JlYXRlcyBkaXJlY3RseSAoY2FsbGVycyB3aXRoIG5vIHJlcGxheVxuICAvLyBzbmFwc2hvdCwgZS5nLiB0ZXN0cykuIEEgc3RhbGUgKDQxMikgcmVqZWN0aW9uIHByb3BhZ2F0ZXMgdG8gdGhlIGNhbGxlcixcbiAgLy8gd2hpY2ggcmVzdGFydHMgdGhlIHJlcGxheSBmcm9tIGEgY29ycmVjdGVkIGxvZy4gSXQgaXMgbm90IHJldHJpZWQgaGVyZSxcbiAgLy8gYmVjYXVzZSB0aGUgZXZlbnQncyBjb3JyZWxhdGlvbiBpZCB3YXMgbWludGVkIGJ5ICp0aGlzKiByZXBsYXkncyBzZWVkZWRcbiAgLy8gc2VxdWVuY2UsIHNvIHJlLWNvbW1pdHRpbmcgaXQgYWdhaW5zdCBhIGNvcnJlY3RlZCBsb2cgd291bGQgcGVyc2lzdCBhblxuICAvLyBldmVudCBubyBjb3JyZWN0IHJlcGxheSBwcm9kdWNlcy5cbiAgbGV0IHJlcG9ydGVkRXZlbnRzID0gMDtcbiAgLy8gV3JpdGVzIHRoaXMgc3VzcGVuc2lvbiBpc3N1ZWQsIGFuZCB3aGV0aGVyIG9uZSBvZiB0aGVtIGhhbmRlZCBiYWNrIGFcbiAgLy8gY29tcGxldGUgaW5saW5lIGRlbHRhIHRoYXQgd2FzIGZvbGRlZCBpbnRvIHRoZSBjYWxsZXIncyBsb2cuIFRvZ2V0aGVyIHRoZXlcbiAgLy8gYW5zd2VyIGBldmVudExvZ0NhcnJpZWRGb3J3YXJkYDogdGhlIGRlbHRhIGNvdmVycyB0aGUgbG9nIHVwIHRvIHRoZSB3cml0ZVxuICAvLyB0aGF0IHJldHVybmVkIGl0LCBzbyBpdCBhY2NvdW50cyBmb3IgZXZlcnkgZXZlbnQgdGhpcyBzdXNwZW5zaW9uIGNvbW1pdHRlZFxuICAvLyBvbmx5IGlmIHRoYXQgd3JpdGUgd2FzIHRoZSBvbmx5IG9uZS5cbiAgbGV0IGd1YXJkZWRXcml0ZXMgPSAwO1xuICBsZXQgZGVsdGFBYnNvcmJlZCA9IGZhbHNlO1xuICBjb25zdCBjcmVhdGVHdWFyZGVkOiBFdmVudENyZWF0b3IgPSBhc3luYyAoZGF0YSwgcGFyYW1zKSA9PiB7XG4gICAgZ3VhcmRlZFdyaXRlcysrO1xuICAgIGlmICghZXZlbnRMb2cpIHtcbiAgICAgIHJldHVybiBjcmVhdGVFdmVudChkYXRhLCBwYXJhbXMpO1xuICAgIH1cbiAgICBjb25zdCBsb2cgPSBldmVudExvZztcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVFdmVudChkYXRhLCB7XG4gICAgICAuLi5wYXJhbXMsXG4gICAgICAuLi5zbG90U25hcHNob3RQYXJhbXMobG9nLmV2ZW50cyksXG4gICAgfSk7XG4gICAgLy8gQW4gaW5saW5lIGRlbHRhIHRoaXMgY2FsbCBhc2tlZCBmb3IgKGBzaW5jZUN1cnNvcmApIGlzIGV2ZXJ5dGhpbmcgdGhlXG4gICAgLy8gbG9nIGdhaW5lZCBzaW5jZSB0aGF0IGN1cnNvciwgdGhpcyB3cml0ZSBpbmNsdWRlZCwgc28gaXQgaXMgZm9sZGVkIG9udG9cbiAgICAvLyB0aGUgdGFpbCBhbmQgY2FycmllcyB0aGUgY3Vyc29yIHdpdGggaXQg4oCUIHVubGlrZSBhIHNraXBwZWQtc2xvdCByZXBvcnQsXG4gICAgLy8gd2hpY2ggaXMgYSB3aW5kb3cgc3RyaWN0bHkgYmVsb3cgdGhlIHdyaXRlIGFuZCBoYXMgdG8gYmUgc29ydGVkIGJhY2tcbiAgICAvLyBpbnRvIHBsYWNlLiBBIFdvcmxkIHJldHVybnMgb25lIG9yIHRoZSBvdGhlciwgbmV2ZXIgYm90aCAodGhlIGRlbHRhIGlzIGFcbiAgICAvLyBzdHJpY3Qgc3VwZXJzZXQpLCBzbyB0aGUgdHdvIGFyZSBoYW5kbGVkIGFwYXJ0IHJhdGhlciB0aGFuIG1lcmdlZC5cbiAgICAvL1xuICAgIC8vIERlY2xpbmluZyBpcyBhbHdheXMgc2FmZSDigJQgYW4gdW5hYnNvcmJlZCBkZWx0YSBpcyBvbmUgdGhlIG5leHQgcmVhZFxuICAgIC8vIHJldHVybnMg4oCUIHNvIHRoZSBndWFyZHMgbWF0Y2ggdGhlIHJlcGxheSBsb29wJ3MgYGFic29yYkNyZWF0ZURlbHRhYDogYVxuICAgIC8vIHRydW5jYXRlZCBwYWdlIChgaGFzTW9yZWApIGlzIGRyb3BwZWQgd2hvbGUgcmF0aGVyIHRoYW4gYWR2YW5jaW5nIHRoZVxuICAgIC8vIGN1cnNvciBwYXN0IGV2ZW50cyBpdCBkaWQgbm90IGNhcnJ5LCBhbmQgdGhlIGxvZyBtdXN0IHN0aWxsIGJlIHdoZXJlIHRoZVxuICAgIC8vIHJlcXVlc3Qgd2FzIGNvbXB1dGVkIGZyb20sIHNpbmNlIGFwcGVuZGluZyBkb2VzIG5vdCByZS1zb3J0LlxuICAgIGlmICh0eXBlb2YgcGFyYW1zPy5zaW5jZUN1cnNvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmIChcbiAgICAgICAgbG9nLmN1cnNvciA9PT0gcGFyYW1zLnNpbmNlQ3Vyc29yICYmXG4gICAgICAgIHJlc3VsdC5ldmVudHMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICByZXN1bHQuaGFzTW9yZSAhPT0gdHJ1ZVxuICAgICAgKSB7XG4gICAgICAgIGFwcGVuZEV2ZW50TG9nKGxvZywgeyBldmVudHM6IHJlc3VsdC5ldmVudHMsIGN1cnNvcjogcmVzdWx0LmN1cnNvciB9KTtcbiAgICAgICAgZGVsdGFBYnNvcmJlZCA9IHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICAvLyBCdW1wLWFuZC1yZXBvcnQ6IHRoZSB3cml0ZSBsYW5kZWQgYWJvdmUgdGhlIHNsb3QgaXQgYXNrZWQgZm9yLCBzbyB0aGVcbiAgICAvLyByZXBvcnQgaG9sZHMgdGhlIGV2ZW50cyBpdCB3YXMgZGVjaWRlZCB3aXRob3V0LiBBYnNvcmJpbmcgaGVyZSByYXRoZXJcbiAgICAvLyB0aGFuIGF0IGVhY2ggY2FsbCBzaXRlIG1lYW5zIHRoZSByZXN0IG9mIHRoaXMgcGhhc2UncyB3cml0ZXMgKHdoaWNoIHJlYWRcbiAgICAvLyB0aGUgc2FtZSBhcnJheSB0byBidWlsZCB0aGVpciBvd24gc25hcHNob3QpIGFzayBmb3IgYSBzbG90IGFib3ZlIHRoZW0sXG4gICAgLy8gYW5kIHRoZSByZXBsYXkgdGhhdCByZXN1bWVzIGZyb20gdGhpcyBsb2cgc2VlcyB0aGVtIHdpdGhvdXQgYSByZWxvYWQuXG4gICAgY29uc3QgcmVwb3J0ID0gYWJzb3JiU2tpcHBlZFNsb3RSZXBvcnQobG9nLmV2ZW50cywgcmVzdWx0KTtcbiAgICByZXBvcnRlZEV2ZW50cyArPSByZXBvcnQuYWRkZWQ7XG4gICAgaWYgKHJlcG9ydC50cnVuY2F0ZWQpIHtcbiAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ0Ryb3BwZWQgYSB0cnVuY2F0ZWQgc2tpcHBlZC1zbG90IHJlcG9ydCcsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIGV2ZW50VHlwZTogZGF0YS5ldmVudFR5cGUsXG4gICAgICAgIGV2ZW50SWQ6IHJlc3VsdC5ldmVudD8uZXZlbnRJZCxcbiAgICAgICAgb2ZmZXJlZDogcmVwb3J0Lm9mZmVyZWQsXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHJlcG9ydC5hZGRlZCA+IDApIHtcbiAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1N1c3BlbnNpb24gd3JpdGUgc2tpcHBlZCBvY2N1cGllZCBzbG90cycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIGV2ZW50VHlwZTogZGF0YS5ldmVudFR5cGUsXG4gICAgICAgIGV2ZW50SWQ6IHJlc3VsdC5ldmVudD8uZXZlbnRJZCxcbiAgICAgICAgcmVwb3J0ZWQ6IHJlcG9ydC5hZGRlZCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uaXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLml0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5pdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG4gIGNvbnN0IGF0dHJpYnV0ZUl0ZW1zID0gc3VzcGVuc2lvbi5pdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIEF0dHJpYnV0ZUludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnYXR0cmlidXRlJ1xuICApO1xuXG4gIGNvbnN0IGhvb2tzTmVlZGluZ0NyZWF0aW9uID0gYWxsSG9va0l0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gIWl0ZW0uaGFzQ3JlYXRlZEV2ZW50XG4gICk7XG5cbiAgLy8gR3JvdXAgaG9vayBpdGVtcyB0aGF0IG5lZWQgd29yayBieSB0b2tlbiwgcHJlc2VydmluZyBxdWV1ZS1pbnNlcnRpb25cbiAgLy8gKHdvcmtmbG93IGNvZGUpIG9yZGVyIHdpdGhpbiBlYWNoIHRva2VuLiBPcGVyYXRpb25zIG9uIG9uZSB0b2tlbiBtdXN0XG4gIC8vIGFwcGx5IGluIGNvZGUgb3JkZXI6IGEgZGlzcG9zZSgpIG9mIGFuIGVhcmxpZXIgaG9vayByZWxlYXNlcyB0aGUgdG9rZW5cbiAgLy8gYmVmb3JlIGEgbGF0ZXIgc2FtZS10b2tlbiBob29rJ3MgY3JlYXRpb24gaXMgdmFsaWRhdGVkIChvdGhlcndpc2UgdGhlXG4gIC8vIG5ldyBob29rIHJlY29yZHMgYSBzcHVyaW91cyBob29rX2NvbmZsaWN0IGFnYWluc3QgdGhlIHJ1bidzIG93blxuICAvLyBkaXNwb3NlZCBob29rKSwgd2hpbGUgYSBob29rIGNyZWF0ZWQgYW5kIGRpc3Bvc2VkIHdpdGhpbiB0aGUgc2FtZVxuICAvLyBzdXNwZW5zaW9uIGlzIHN0aWxsIGNyZWF0ZWQgYmVmb3JlIGl0IGlzIGRpc3Bvc2VkLiBEaWZmZXJlbnQgdG9rZW5zXG4gIC8vIGhhdmUgbm8gY2xhaW0gaW50ZXJhY3Rpb24sIHNvIHRva2VuIGdyb3VwcyBhcmUgcHJvY2Vzc2VkIGluIHBhcmFsbGVsLlxuICBjb25zdCBob29rSXRlbXNCeVRva2VuID0gbmV3IE1hcDxzdHJpbmcsIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtW10+KCk7XG4gIGZvciAoY29uc3QgaXRlbSBvZiBhbGxIb29rSXRlbXMpIHtcbiAgICBpZiAoaXRlbS5oYXNDcmVhdGVkRXZlbnQgJiYgIWl0ZW0uZGlzcG9zZWQpIHtcbiAgICAgIGNvbnRpbnVlOyAvLyBhbHJlYWR5IGNvbW1pdHRlZCBhbmQgc3RpbGwgbGl2ZTogbm90aGluZyB0byBkb1xuICAgIH1cbiAgICBjb25zdCBncm91cCA9IGhvb2tJdGVtc0J5VG9rZW4uZ2V0KGl0ZW0udG9rZW4pO1xuICAgIGlmIChncm91cCkge1xuICAgICAgZ3JvdXAucHVzaChpdGVtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaG9va0l0ZW1zQnlUb2tlbi5zZXQoaXRlbS50b2tlbiwgW2l0ZW1dKTtcbiAgICB9XG4gIH1cblxuICAvLyBSZXNvbHZlIGVuY3J5cHRpb24ga2V5IGZvciB0aGlzIHJ1blxuICBjb25zdCByYXdLZXkgPSBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4ocnVuKTtcbiAgY29uc3QgZW5jcnlwdGlvbktleSA9IHJhd0tleSA/IGF3YWl0IGltcG9ydEtleShyYXdLZXkpIDogdW5kZWZpbmVkO1xuXG4gIC8vIEdhdGUgcGF5bG9hZCBjb21wcmVzc2lvbiBvbiB0aGUgcnVuJ3Mgc3BlY1ZlcnNpb24uXG4gIGNvbnN0IGNvbXByZXNzaW9uID1cbiAgICAocnVuLnNwZWNWZXJzaW9uID8/IDApID49IFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTjtcblxuICBsZXQgc2VyaWFsaXphdGlvbkJsb2NrZXJDb3VudCA9IDA7XG4gIGNvbnN0IHNlcmlhbGl6YXRpb25CbG9ja2VyczogU3VzcGVuc2lvblNlcmlhbGl6YXRpb25CbG9ja2VyW10gPSBbXTtcbiAgYXN5bmMgZnVuY3Rpb24gZGVoeWRyYXRlSW5wdXQoXG4gICAgdmFsdWU6IHVua25vd24sXG4gICAgY29udGV4dDogUGljazxTdXNwZW5zaW9uU2VyaWFsaXphdGlvbkJsb2NrZXIsICdzb3VyY2UnIHwgJ2NvcnJlbGF0aW9uSWQnPlxuICApOiBQcm9taXNlPFNlcmlhbGl6ZWREYXRhPiB7XG4gICAgY29uc3Qgc3RhdHM6IEd1ZXN0Q29kZVN0YXRzID0geyBleGVjdXRpb25zOiBbXSB9O1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gKGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgIHZhbHVlLFxuICAgICAgICBydW5JZCxcbiAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzLFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgY29tcHJlc3Npb24sXG4gICAgICAgIHN0YXRzXG4gICAgICApKSBhcyBTZXJpYWxpemVkRGF0YTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc2VyaWFsaXphdGlvbkJsb2NrZXJDb3VudCArPVxuICAgICAgICBzdGF0cy50b3RhbEV4ZWN1dGlvbnMgPz8gc3RhdHMuZXhlY3V0aW9ucy5sZW5ndGg7XG4gICAgICBzZXJpYWxpemF0aW9uQmxvY2tlcnMucHVzaChcbiAgICAgICAgLi4uc3RhdHMuZXhlY3V0aW9uc1xuICAgICAgICAgIC5zbGljZShcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBHVUVTVF9DT0RFX0VYRUNVVElPTl9TQU1QTEVfTElNSVQgLSBzZXJpYWxpemF0aW9uQmxvY2tlcnMubGVuZ3RoXG4gICAgICAgICAgKVxuICAgICAgICAgIC5tYXAoKGV4ZWN1dGlvbikgPT4gKHsgLi4uY29udGV4dCwgLi4uZXhlY3V0aW9uIH0pKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBkaXNwb3NlSG9vayhcbiAgICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGhvb2tEaXNwb3NlZEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICBldmVudFR5cGU6ICdob29rX2Rpc3Bvc2VkJyBhcyBjb25zdCxcbiAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICB9LFxuICAgIH07XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoaG9va0Rpc3Bvc2VkRXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIHdhcyBhbHJlYWR5IGRpc3Bvc2VkIGJ5IGEgY29uY3VycmVudCBpbnZvY2F0aW9uLCBzYWZlIHRvIHNraXBcbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICdIb29rIGFscmVhZHkgZGlzcG9zZWQsIHNraXBwaW5nIGR1cGxpY2F0ZSBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2sgZGlzcG9zYWwnLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKEhvb2tOb3RGb3VuZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgLy8gSG9vayBtYXkgaGF2ZSBhbHJlYWR5IGJlZW4gZGlzcG9zZWQgb3IgbmV2ZXIgY3JlYXRlZFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgbm90IGZvdW5kIGZvciBkaXNwb3NhbCwgY29udGludWluZycsIHtcbiAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUHJvY2VzcyBob29rcyBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzLlxuICAvLyBUcmFjayBhbnkgaG9vayBjb25mbGljdHMgdGhhdCBvY2N1ciDigJQgdGhlc2UgYXJlIHJldHVybmVkIHRvIHRoZSBjYWxsZXIgc29cbiAgLy8gaXQgY2FuIGFkdmFuY2UgdGhlIHdvcmtmbG93IG92ZXIgdGhlIGNvbW1pdHRlZCBgaG9va19jb25mbGljdGAgYmVmb3JlXG4gIC8vIGFueXRoaW5nIGVsc2UgdGhpcyBzdXNwZW5zaW9uIHNjaGVkdWxlZCBydW5zLlxuICBjb25zdCBob29rQ29uZmxpY3RDb3JyZWxhdGlvbklkczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgYXdhaXRlZEhvb2tDb3JyZWxhdGlvbklkczogc3RyaW5nW10gPSBbXTtcbiAgbGV0IGhvb2tDcmVhdGlvbk1zID0gMDtcblxuICAvLyBBc2sgdGhlIGhvb2sgY3JlYXRlIGZvciB0aGUgZXZlbnQtbG9nIGRlbHRhIHNpbmNlIHRoZSBjdXJzb3IgdGhlIGNhbGxlcidzXG4gIC8vIGxvZyB3YXMgcmVhZCBhdC4gVGhlIGhvb2sncyBhd2FpdGVycyBhcmUgc2V0dGxlZCBieSB0aGUgZXZlbnQgdGhpcyB3cml0ZVxuICAvLyBjb21taXRzIGFuZCBieSBub3RoaW5nIGVsc2Ug4oCUIGEgYGhvb2tfY3JlYXRlZGAgZm9yIGEgY2xlYW4gcmVnaXN0cmF0aW9uLFxuICAvLyBhIGBob29rX2NvbmZsaWN0YCB3aGVuIHRoZSB0b2tlbiB3YXMgYWxyZWFkeSBjbGFpbWVkIOKAlCBzbyB0aGUgY2FsbGVyIGNhblxuICAvLyBjb250aW51ZSB0aGUgd29ya2Zsb3cgaW4gaXRzIG93biBwcm9jZXNzIG9uIGVpdGhlciBvdXRjb21lLCBidXQgb25seSBvdmVyXG4gIC8vIGEgbG9nIHRoYXQgaG9sZHMgdGhhdCBldmVudCwgYW5kIHRoaXMgd3JpdGUgaXMgdGhlIG9uZSByZXF1ZXN0IHRoYXQgY2FuXG4gIC8vIGhhbmQgaXQgYmFjayB0b2dldGhlciB3aXRoIGFueXRoaW5nIGFub3RoZXIgd3JpdGVyIGxhbmRlZCBpbiB0aGUgbWVhbnRpbWUuXG4gIC8vIE9wdGlvbmFsIGJ5IGNvbnRyYWN0OiBhIFdvcmxkIHRoYXQgaWdub3JlcyBgc2luY2VDdXJzb3JgIHJldHVybnMgbm8gZGVsdGFcbiAgLy8gYW5kIHRoZSBjYWxsZXIgcmVhZHMgaW5zdGVhZC5cbiAgLy9cbiAgLy8gQXNrZWQgZm9yIG9uIHRoZSBzaW5nbGUtaG9vayBzdXNwZW5zaW9uIG9ubHkuIFR3byBjcmVhdGVzIGlzc3VlZCBmcm9tIG9uZVxuICAvLyBzbmFwc2hvdCBlYWNoIGRpZmYgYWdhaW5zdCB0aGUgc2FtZSBjdXJzb3IsIGFuZCBvbmx5IHRoZSBmaXJzdCBkZWx0YSBiYWNrXG4gIC8vIGNhbiBiZSBmb2xkZWQgaW4gKHRoZSBjdXJzb3IgbW92ZXMgd2l0aCBpdCksIHNvIHRoZSBsb2cgd291bGQgZW5kIHVwIHNob3J0XG4gIC8vIG9mIHRoZSBvdGhlcidzIGV2ZW50IHdpdGggbm90aGluZyB0byBzYXkgc28uXG4gIGNvbnN0IGhvb2tEZWx0YUN1cnNvciA9XG4gICAgaG9va3NOZWVkaW5nQ3JlYXRpb24ubGVuZ3RoID09PSAxICYmIHR5cGVvZiBldmVudExvZz8uY3Vyc29yID09PSAnc3RyaW5nJ1xuICAgICAgPyBldmVudExvZy5jdXJzb3JcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gIGlmIChob29rSXRlbXNCeVRva2VuLnNpemUgPiAwKSB7XG4gICAgY29uc3QgaG9va1BoYXNlU3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgYXdhaXQgc2V0dGxlUGhhc2UoXG4gICAgICBbLi4uaG9va0l0ZW1zQnlUb2tlbi52YWx1ZXMoKV0ubWFwKGFzeW5jIChpdGVtcykgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBpdGVtcykge1xuICAgICAgICAgIGxldCBjcmVhdGlvbkNvbmZsaWN0ZWQgPSBmYWxzZTtcblxuICAgICAgICAgIGlmICghcXVldWVJdGVtLmhhc0NyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaG9va01ldGFkYXRhID1cbiAgICAgICAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIDogYXdhaXQgZGVoeWRyYXRlSW5wdXQocXVldWVJdGVtLm1ldGFkYXRhLCB7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ2hvb2tfbWV0YWRhdGEnLFxuICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgaG9va0V2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgICAgdG9rZW5SZXRlbnRpb25VbnRpbDogcXVldWVJdGVtLnRva2VuUmV0ZW50aW9uVW50aWwsXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5pc1N5c3RlbSAmJiB7IGlzU3lzdGVtOiB0cnVlIH0pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUhvb2tFdmVudCh7XG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBob29rRXZlbnQsXG4gICAgICAgICAgICAgIHF1ZXVlSXRlbSxcbiAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICBzaW5jZUN1cnNvcjogaG9va0RlbHRhQ3Vyc29yLFxuICAgICAgICAgICAgICBjcmVhdGVFdmVudDogY3JlYXRlR3VhcmRlZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHJlc3VsdC5oYXNIb29rQ29uZmxpY3QpIHtcbiAgICAgICAgICAgICAgaG9va0NvbmZsaWN0Q29ycmVsYXRpb25JZHMucHVzaChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb24pIHtcbiAgICAgICAgICAgICAgYXdhaXRlZEhvb2tDb3JyZWxhdGlvbklkcy5wdXNoKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNyZWF0aW9uQ29uZmxpY3RlZCA9IHJlc3VsdC5oYXNIb29rQ29uZmxpY3Q7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gRGlzcG9zZSBhZnRlciBjcmVhdGlvbiBmb3IgaG9va3MgYm9ybiBhbmQgZGlzcG9zZWQgd2l0aGluIHRoaXNcbiAgICAgICAgICAvLyBiYXRjaC4gQSBob29rIHdob3NlIGNyZWF0aW9uIGNvbmZsaWN0ZWQgd2FzIG5ldmVyIGNyZWF0ZWQsIHNvXG4gICAgICAgICAgLy8gdGhlcmUgaXMgbm90aGluZyB0byBkaXNwb3NlLlxuICAgICAgICAgIGlmIChxdWV1ZUl0ZW0uZGlzcG9zZWQgJiYgIWNyZWF0aW9uQ29uZmxpY3RlZCkge1xuICAgICAgICAgICAgYXdhaXQgZGlzcG9zZUhvb2socXVldWVJdGVtKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgICBob29rQ3JlYXRpb25NcyA9IERhdGUubm93KCkgLSBob29rUGhhc2VTdGFydDtcbiAgfVxuXG4gIC8vIFByb2Nlc3MgYWJvcnQgcmVxdWVzdHM6IHJlc3VtZSB0aGUgaG9vayB3aXRoIGFib3J0IHBheWxvYWQgYW5kIHdyaXRlIHN0cmVhbSBwYWNrZXRcbiAgY29uc3QgaG9va3NOZWVkaW5nQWJvcnQgPSBhbGxIb29rSXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKSA9PiBpdGVtLmFib3J0UmVxdWVzdGVkICYmICFpdGVtLmRpc3Bvc2VkXG4gICk7XG5cbiAgaWYgKGhvb2tzTmVlZGluZ0Fib3J0Lmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgIGF3YWl0IHNldHRsZVBoYXNlKFxuICAgICAgaG9va3NOZWVkaW5nQWJvcnQubWFwKGFzeW5jIChxdWV1ZUl0ZW0pID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBEZWh5ZHJhdGUgdGhlIGFib3J0IHBheWxvYWQgZm9yIHN0b3JhZ2VcbiAgICAgICAgICBjb25zdCBhYm9ydFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVJbnB1dChcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWJvcnRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgcmVhc29uOiBxdWV1ZUl0ZW0uYWJvcnRSZWFzb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzb3VyY2U6ICdob29rX2Fib3J0JyxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIENyZWF0ZSBob29rX3JlY2VpdmVkIGV2ZW50IHdpdGggYWJvcnQgcGF5bG9hZFxuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoe1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgICAgICBwYXlsb2FkOiBhYm9ydFBheWxvYWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gV3JpdGUgc3RyZWFtIGNhbmNlbGxhdGlvbiBwYWNrZXQgZm9yIHJlYWwtdGltZSBzdGVwIHByb3BhZ2F0aW9uLlxuICAgICAgICAgIC8vIFJldXNlIHRoZSBzYW1lIGRlaHlkcmF0ZWQgcGF5bG9hZCBhcyB0aGUgaG9vayBldmVudCBzbyB0aGUgcmVhc29uXG4gICAgICAgICAgLy8gcm91bmQtdHJpcHMgdGhyb3VnaCBgZGVoeWRyYXRlU3RlcEFyZ3VtZW50c2AgLyBgaHlkcmF0ZVN0ZXBBcmd1bWVudHNgXG4gICAgICAgICAgLy8gKGhhbmRsZXMgRE9NRXhjZXB0aW9uLCBjdXN0b20gZXJyb3JzLCBlbmNyeXB0aW9uLCBldGMuKSBpbnN0ZWFkIG9mXG4gICAgICAgICAgLy8gYmFyZSBKU09OLnN0cmluZ2lmeSB3aGljaCBsb3NlcyB0eXBlIGluZm9ybWF0aW9uIGFuZCBkcm9wcyB1bmRlZmluZWQuXG4gICAgICAgICAgLy8gc3RyZWFtTmFtZSBpcyBzZXQgb24gdGhlIHF1ZXVlIGl0ZW0gYXQgY29udHJvbGxlciBjb25zdHJ1Y3Rpb24gdGltZVxuICAgICAgICAgIC8vIChzZWUgd29ya2Zsb3cvYWJvcnQtY29udHJvbGxlci50cykuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU5hbWUgPSBnZXRBYm9ydFN0cmVhbUlkRnJvbVRva2VuKHF1ZXVlSXRlbS50b2tlbik7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLndyaXRlKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgc3RyZWFtTmFtZSxcbiAgICAgICAgICAgICAgYWJvcnRQYXlsb2FkIGFzIFVpbnQ4QXJyYXlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLmNsb3NlKHJ1bklkLCBzdHJlYW1OYW1lKTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIEJlc3QtZWZmb3J0IHN0cmVhbSB3cml0ZTogaG9vayBldmVudCBwcm92aWRlcyB0aGUgZHVyYWJsZSBmYWxsYmFja1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgJ0ZhaWxlZCB0byB3cml0ZSBhYm9ydCBzdHJlYW0gcGFja2V0LCBob29rIGV2ZW50IHdpbGwgcHJvdmlkZSBmYWxsYmFjaycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgYWJvcnQnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBzdGVwIGV2ZW50cyBmb3Igc3RlcHMgdGhhdCBkb24ndCBoYXZlIHRoZW0geWV0LlxuICAvLyBVbmxpa2UgVjEsIHdlIGRvIE5PVCBxdWV1ZSBzdGVwIG1lc3NhZ2VzIGZyb20gaGVyZTogdGhlIGNhbGxlclxuICAvLyBkZWNpZGVzIHdoaWNoIHN0ZXBzIHRvIGV4ZWN1dGUgaW5saW5lIHZzLiBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICAvLyBXYWl0IGV2ZW50cyBhcmUgYWxzbyBjcmVhdGVkIGluIHBhcmFsbGVsIGJlbG93LlxuICBjb25zdCBzdGVwc05lZWRpbmdDcmVhdGlvbiA9IG5ldyBTZXQoXG4gICAgc3RlcEl0ZW1zXG4gICAgICAuZmlsdGVyKChxdWV1ZUl0ZW0pID0+ICFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KVxuICAgICAgLm1hcCgocXVldWVJdGVtKSA9PiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZClcbiAgKTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIFRISVMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQuIFBvcHVsYXRlZCBieSB0aGUgb3BzIGJlbG93IGFmdGVyIGEgc3VjY2Vzc2Z1bFxuICAvLyBldmVudHMuY3JlYXRlLCB1c2VkIGJ5IHRoZSBjYWxsZXIgdG8gY2xhaW0gb3duZXJzaGlwIGFuZCBhdm9pZFxuICAvLyByYWNpbmcgd2l0aCBjb25jdXJyZW50IGhhbmRsZXJzIG9uIHN0ZXAgZXhlY3V0aW9uLlxuICBjb25zdCBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gQ29ycmVsYXRpb24gSURzIG9mIHN0ZXBzIGZpbmFsaXplZCBhcyBmYWlsZWQgYmVjYXVzZSB0aGVpciBhcmd1bWVudHNcbiAgLy8gcmVmdXNlZCB0byBzZXJpYWxpemU6IHNlZSBmaW5hbGl6ZVVuc2VyaWFsaXphYmxlU3RlcCBiZWxvdy5cbiAgY29uc3QgZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLyoqXG4gICAqIEEgc3RlcCB3aG9zZSBhcmd1bWVudHMgZmFpbCB0byBzZXJpYWxpemUgaXMgZGV0ZXJtaW5pc3RpYzogZXZlcnkgcmVwbGF5XG4gICAqIHJlLWRlcml2ZXMgdGhlIHNhbWUgdW5zZXJpYWxpemFibGUgdmFsdWUsIHNvIHJlZGVsaXZlcmluZyB0aGVcbiAgICogb3JjaGVzdHJhdG9yIG1lc3NhZ2UgY2FuIG5ldmVyIHN1Y2NlZWQuIEluc3RlYWQgb2YgcmVqZWN0aW5nIHRoZSB3aG9sZVxuICAgKiBzdXNwZW5zaW9uICh3aGljaCBmYWlscyB0aGUgcnVuIGZyb20gdGhlIG91dHNpZGUsIHdoZXJlIG5vIHVzZXIgY29kZSBjYW5cbiAgICogb2JzZXJ2ZSBpdCksIHRyZWF0IGl0IGV4YWN0bHkgbGlrZSBhIHN0ZXAtYm9keSBmYWlsdXJlOiB3cml0ZVxuICAgKiBgc3RlcF9jcmVhdGVkYCB3aXRoIGEgcGxhY2Vob2xkZXIgaW5wdXQgKGV2ZXJ5IFdvcmxkIHJlcXVpcmVzIHRoZSBzdGVwXG4gICAqIGVudGl0eSB0byBleGlzdCBiZWZvcmUgYSB0ZXJtaW5hbCBzdGVwIGV2ZW50LCBhbmQgdGhlIHJlYWwgaW5wdXQgaXNcbiAgICogcHJlY2lzZWx5IHdoYXQgcmVmdXNlZCB0byBzZXJpYWxpemUpIGZvbGxvd2VkIGJ5IGBzdGVwX2ZhaWxlZGAgY2FycnlpbmdcbiAgICogdGhlIFNlcmlhbGl6YXRpb25FcnJvci4gVGhlIG5leHQgcmVwbGF5IHJlamVjdHMgdGhlIHN0ZXAncyBwcm9taXNlIHdpdGhcbiAgICogaXQsIHNvIGEgdHJ5L2NhdGNoIGFyb3VuZCB0aGUgc3RlcCBjYWxsIG9ic2VydmVzIHRoZSBlcnJvcjsgdW5jYXVnaHQsIGl0XG4gICAqIHByb3BhZ2F0ZXMgb3V0IG9mIHRoZSB3b3JrZmxvdyBib2R5IGFuZCBmYWlscyB0aGUgcnVuIGFzIGEgVVNFUl9FUlJPUixcbiAgICogd2l0aG91dCBidXJuaW5nIHF1ZXVlIHJlZGVsaXZlcmllcyBlaXRoZXIgd2F5LlxuICAgKi9cbiAgY29uc3QgZmluYWxpemVVbnNlcmlhbGl6YWJsZVN0ZXAgPSBhc3luYyAoXG4gICAgcXVldWVJdGVtOiBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgICBlcnJvcjogU2VyaWFsaXphdGlvbkVycm9yXG4gICk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICdTdGVwIGFyZ3VtZW50cyBmYWlsZWQgdG8gc2VyaWFsaXplOyBmYWlsaW5nIHRoZSBzdGVwIHNvIHRoZSAnICtcbiAgICAgICAgJ3dvcmtmbG93IGNhbiBvYnNlcnZlIHRoZSBlcnJvcicsXG4gICAgICB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgZXJyb3I6IGVycm9yLm1lc3NhZ2UsXG4gICAgICB9XG4gICAgKTtcbiAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgIC8vIE1hcmtlciBwbGFjZWhvbGRlciAobm90IGVtcHR5IGFyZ3MpOiBieXRlLWlkZW50aWNhbC10by16ZXJvLWFyZ3Mgd291bGRcbiAgICAvLyBtYWtlIGB3b3JrZmxvdyBpbnNwZWN0IHN0ZXBzYCBzaG93IFwibm8gYXJndW1lbnRzXCIgZm9yIHRoZSBvbmUgc3RlcFxuICAgIC8vIHdob3NlIGVudGlyZSBwcm9ibGVtIHdhcyBpdHMgYXJndW1lbnRzLlxuICAgIGNvbnN0IHBsYWNlaG9sZGVySW5wdXQgPSAoYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgIHVuc2VyaWFsaXphYmxlU3RlcElucHV0UGxhY2Vob2xkZXIoKSxcbiAgICAgIHJ1bklkLFxuICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgIGZhbHNlLFxuICAgICAgY29tcHJlc3Npb25cbiAgICApKSBhcyBTZXJpYWxpemVkRGF0YTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZChcbiAgICAgICAge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIGlucHV0OiBwbGFjZWhvbGRlcklucHV0LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICk7XG4gICAgfSBjYXRjaCAoY3JlYXRlRXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhjcmVhdGVFcnIpKSB7XG4gICAgICAgIC8vIEEgY29uY3VycmVudCBoYW5kbGVyIGFscmVhZHkgY3JlYXRlZCB0aGUgc3RlcDogdGhlIGZhaWx1cmUgaXNcbiAgICAgICAgLy8gZGV0ZXJtaW5pc3RpYywgc28gaXQgaXMgcmFjaW5nIHRvd2FyZCB0aGUgc2FtZSBzdGVwX2ZhaWxlZCBiZWxvdy5cbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2U6IGNyZWF0ZUVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoUnVuRXhwaXJlZEVycm9yLmlzKGNyZWF0ZUVycikpIHtcbiAgICAgICAgLy8gUnVuIGFscmVhZHkgZmluaXNoZWQ6IG5vdGhpbmcgdG8gb2JzZXJ2ZSB0aGUgZmFpbHVyZS5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgY3JlYXRlRXJyO1xuICAgICAgfVxuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZChcbiAgICAgICAge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfZmFpbGVkJyBhcyBjb25zdCxcbiAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICBzdGVwTmFtZTogcXVldWVJdGVtLnN0ZXBOYW1lLFxuICAgICAgICAgICAgLy8gVGhlIGVycm9yIGl0c2VsZiBpcyBhIHBsYWluIFdvcmtmbG93RXJyb3IgKG5hbWUsIG1lc3NhZ2Ugd2l0aFxuICAgICAgICAgICAgLy8gZnJhbWVkIGhpbnQsIGNhdXNlIGNoYWluKSwgc2VyaWFsaXphYmxlIGV2ZW4gdGhvdWdoIHRoZSBzdGVwXG4gICAgICAgICAgICAvLyBpbnB1dCB3YXMgbm90LiBFcnJvciBkZXRlY3Rpb24gaXMgcmVhbG0taW5kZXBlbmRlbnRcbiAgICAgICAgICAgIC8vICh0eXBlcy5pc05hdGl2ZUVycm9yKSwgc28gdGhlIGhvc3QtY3JlYXRlZCBlcnJvciBzZXJpYWxpemVzXG4gICAgICAgICAgICAvLyB0aGUgc2FtZSB1bmRlciBlaXRoZXIgZ2xvYmFsOyB0aGUgVk0gZ2xvYmFsIGlzIHBhc3NlZCBmb3JcbiAgICAgICAgICAgIC8vIGNvbnNpc3RlbmN5IHdpdGggZXZlcnkgb3RoZXIgZGVoeWRyYXRpb24gaW4gdGhpcyBmaWxlIGFuZCBzb1xuICAgICAgICAgICAgLy8gYW55IFZNLXJlYWxtIHZhbHVlcyBndWVzdCBjb2RlIHRocmV3IGludG8gdGhlIGNhdXNlIGNoYWluXG4gICAgICAgICAgICAvLyAoZ2V0dGVycy9wcm94aWVzIGV4ZWN1dGVkIGR1cmluZyB0aGUgZmFpbGVkIGRlaHlkcmF0aW9uKSBhcmVcbiAgICAgICAgICAgIC8vIGRldGVjdGVkIGJ5IHRoZSByZWFsbS1zZW5zaXRpdmUgcmVkdWNlcnMuXG4gICAgICAgICAgICBlcnJvcjogYXdhaXQgZGVoeWRyYXRlU3RlcEVycm9yKFxuICAgICAgICAgICAgICBlcnJvcixcbiAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICAgICApLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZmFpbEVycikge1xuICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZmFpbEVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGZhaWxFcnIpKSB7XG4gICAgICAgIC8vIFN0ZXAgYWxyZWFkeSB0ZXJtaW5hbCAoYSBjb25jdXJyZW50IGhhbmRsZXIgd3JvdGUgdGhlIHNhbWVcbiAgICAgICAgLy8gZGV0ZXJtaW5pc3RpYyBmYWlsdXJlKSBvciB0aGUgcnVuIGFscmVhZHkgZmluaXNoZWQuXG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAnVHJpZWQgZmFpbGluZyBzdGVwLCBidXQgc3RlcCBvciBydW4gaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgbWVzc2FnZTogZmFpbEVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGZhaWxFcnI7XG4gICAgICB9XG4gICAgfVxuICAgIGZhaWxlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpO1xuICAgIC8vIFJlbGVhc2UgdGhlIGlubGluZSBzbG90IGJvb2trZWVwaW5nOiB0aGUgc3RlcCBuZXZlciBydW5zLCBzbyBpdCBtdXN0XG4gICAgLy8gbm90IGFwcGVhciBpbiB0aGUgcmVidWlsdCBgbGF6eUlubGluZVN0ZXBzYC4gKEl0cyBzbG90IGluIHRoZSBmaXJzdC1OXG4gICAgLy8gc2VsZWN0aW9uIGFuZCBpbiBgaW5saW5lUGFpckZvbGRFbGlnaWJsZWAncyBjb3VudCB3YXMgY29uc3VtZWRcbiAgICAvLyBiZWZvcmUgZGVoeWRyYXRpb24gY291bGQgcmV2ZWFsIHRoZSBmYWlsdXJlLCBpbmhlcmVudCB0byBzZWxlY3RpbmdcbiAgICAvLyBiZWZvcmUgc2VyaWFsaXppbmcsIGFuZCBib3VuZGVkIHRvIG9uZSB3YXN0ZWQgc2xvdCBvbiBhIHBhc3MgdGhhdFxuICAgIC8vIGVuZHMgaW4gYSBmb3JjZWQgcmVwbGF5IGFueXdheS4pXG4gICAgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzLmRlbGV0ZShxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gIH07XG5cbiAgLy8gTGF6eSBpbmxpbmUgc3RhcnQ6IGRlZmVyIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUgZm9yIHVwIHRvXG4gIC8vIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyB0aGUgY2FsbGVyIHdpbGwgcnVuIGlubGluZSAoaW4gcGFyYWxsZWwpLiBFYWNoXG4gIC8vIHN0ZXAgaXMgY3JlYXRlZCBvbiB0aGUgZmx5IGJ5IHRoZSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV4ZWN1dGVTdGVwIHNlbmRzXG4gIC8vIChzYXZpbmcgYSByb3VuZC10cmlwIHBlciBzdGVwKS4gV2UgbmV2ZXIgZGVmZXIgd2hlbiBhIGBob29rLmdldENvbmZsaWN0KClgXG4gIC8vIGF3YWl0ZXIgaXMgcHJlc2VudCwgYmVjYXVzZSBpbiB0aGF0IGNhc2UgdGhlIGNhbGxlciBleGVjdXRlcyBub3RoaW5nIGlubGluZVxuICAvLyAoaXQgY29udGludWVzIHRoZSB3b3JrZmxvdyB0byByZXNvbHZlIHRoZSBhd2FpdGVyIGluc3RlYWQpLCBzbyBkZWZlcnJpbmdcbiAgLy8gd291bGQgbGVhdmUgdGhlIHN0ZXBzIHVuY3JlYXRlZCBhbmQgdW5xdWV1ZWQuIFdlIHBpY2sgdGhlIGZpcnN0IE4gdW5jcmVhdGVkXG4gIC8vIHN0ZXBzIOKAlCBtYXRjaGluZyB0aGUgY2FsbGVyJ3MgaW5saW5lLWNhbmRpZGF0ZSBzZWxlY3Rpb24g4oCUIGFuZCBkZWh5ZHJhdGVcbiAgLy8gdGhlaXIgaW5wdXQgaGVyZSBzbyBleGVjdXRlU3RlcCBjYW4gc2hpcCBpdCBhcyB0aGUgc3RlcF9zdGFydGVkIHBheWxvYWQuXG4gIGNvbnN0IGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcyA9IG5ldyBTZXQ8c3RyaW5nPihcbiAgICBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzLmxlbmd0aCA9PT0gMFxuICAgICAgPyBzdGVwSXRlbXNcbiAgICAgICAgICAuZmlsdGVyKChpdGVtKSA9PiBzdGVwc05lZWRpbmdDcmVhdGlvbi5oYXMoaXRlbS5jb3JyZWxhdGlvbklkKSlcbiAgICAgICAgICAuc2xpY2UoMCwgZ2V0TWF4SW5saW5lU3RlcHMoKSlcbiAgICAgICAgICAubWFwKChpdGVtKSA9PiBpdGVtLmNvcnJlbGF0aW9uSWQpXG4gICAgICA6IFtdXG4gICk7XG4gIC8vIENvbGxlY3RlZCBieSBjb3JyZWxhdGlvbklkIGJlY2F1c2UgdGhlIHBlci1zdGVwIG9wcyBiZWxvdyBydW4gY29uY3VycmVudGx5XG4gIC8vIGFuZCBzZXR0bGUgb3V0IG9mIG9yZGVyLiBXZSByZWJ1aWxkIHRoZSBhcnJheSBpbiBkZXRlcm1pbmlzdGljXG4gIC8vIGBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHNgIG9yZGVyICh0aGUgb3JkZXJlZCBzbGljZSBhYm92ZSkgYWZ0ZXIgdGhlIG9wc1xuICAvLyBzZXR0bGUsIHNvIHRoZSBpbmxpbmUgYmF0Y2ggb3JkZXIgaXMgc3RhYmxlIHJlZ2FyZGxlc3Mgb2YgZGVoeWRyYXRpb24gdGltaW5nLlxuICBjb25zdCBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkID0gbmV3IE1hcDxcbiAgICBzdHJpbmcsXG4gICAgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHRbJ2xhenlJbmxpbmVTdGVwcyddW251bWJlcl1cbiAgPigpO1xuXG4gIGNvbnN0IG9wczogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgLy8gQ29ycmVsYXRpb24gSURzIG9mIHN0ZXBzIHdob3NlIHN0ZXAtZXhlY3V0aW9uIHF1ZXVlIG1lc3NhZ2Ugd2FzIGFscmVhZHlcbiAgLy8gcHVibGlzaGVkIGJ5IHRoZSByZXNpbGllbnQtZGlzcGF0Y2ggb3BzIGJlbG93IChhbG9uZ3NpZGUgdGhlIHN0ZXBfY3JlYXRlZFxuICAvLyB3cml0ZSkuIFJlcG9ydGVkIHRvIHRoZSBjYWxsZXIgc28gaXRzIGRpc3BhdGNoIHBhc3Mgc2tpcHMgdGhlbS5cbiAgY29uc3QgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gUmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2ggZWxpZ2liaWxpdHksIHNoYXJlZCBieSBldmVyeSBzdGVwIG9wIGJlbG93ICh0aGVcbiAgLy8gcGVyLXN0ZXAgaW5wdXQtc2l6ZSBjaGVjayBpcyBhcHBsaWVkIGluc2lkZSB0aGUgb3ApLiBBbGwgbXVzdCBob2xkOlxuICAvL1xuICAvLyAgLSBUaGUgY2FsbGVyIHByb3ZpZGVkIGEgZGlzcGF0Y2ggdGFyZ2V0IChgc3RlcERpc3BhdGNoYCk6IHRlcm1pbmFsXG4gIC8vICAgIGRyYWlucyBhbmQgb3RoZXIgY3JlYXRlLW9ubHkgY2FsbGVycyBuZXZlciBxdWV1ZS5cbiAgLy8gIC0gVGhlIGZlYXR1cmUgaXMgZW5hYmxlZCAoYFdPUktGTE9XX1JFU0lMSUVOVF9TVEVQX0RJU1BBVENIYCBvcHQtaW4pLlxuICAvLyAgICBJdCBpcyBvZmYgYnkgZGVmYXVsdCBiZWNhdXNlIHRoZSBwdWJsaXNoIHJhY2VzIHRoZSBjcmVhdGUncyB2ZXJkaWN0LFxuICAvLyAgICBhbmQgYSBjcmVhdGUgY2FuIGNvbWUgYmFjayByZWZ1c2VkOiBhcyBhIGR1cGxpY2F0ZSB0aGUgcmVwbGF5IHNob3VsZFxuICAvLyAgICBzdG9wIHB1cnN1aW5nLCBvciAob24gYSBXb3JsZCB0aGF0IHdvdWxkIHJhdGhlciByZWZ1c2UgYSBzdGFsZSB3cml0ZVxuICAvLyAgICB0aGFuIHJlcG9ydCB3aGF0IGl0IG1pc3NlZCkgYXMgYSA0MTIuIEVpdGhlciB3YXkgdGhlIHF1ZXVlIG1lc3NhZ2VcbiAgLy8gICAgY2FycnlpbmcgdGhlIHBheWxvYWQgaXMgYWxyZWFkeSBvdXQsIGFuZCB0aGUgY29uc3VtZXIgY2FuIG1hdGVyaWFsaXplIGFcbiAgLy8gICAgc3RlcCB3aG9zZSBjcmVhdGUgd2FzIHJlZnVzZWQuIE5vdGhpbmcgb3JkZXJzIHRoYXQgdmVyZGljdCBiZWZvcmUgdGhlXG4gIC8vICAgIGNvbnN1bWVyJ3MgcmVkZWxpdmVyeSByZS1lbnN1cmUsIHNvIG5vIGJhY2tlbmQtc2lkZSByZXZvY2F0aW9uXG4gIC8vICAgIGJvb2trZWVwaW5nIGNhbiBjbG9zZSB0aGUgd2luZG93OiBhIGJlc3QtZWZmb3J0IG1hcmtlciB0aGF0IGZhaWxzIG9wZW5cbiAgLy8gICAgY2Fubm90IGNhcnJ5IGEgY29ycmVjdG5lc3MgcHJvcGVydHkuIFRoZSBzZXF1ZW50aWFsIHBhdGggaXMgdGhlIG9ubHlcbiAgLy8gICAgdGhpbmcgdGhhdCBnaXZlcyB0aGUgbWVzc2FnZSBhIGhhcHBlbnMtYWZ0ZXIgZWRnZSBvdmVyIHRoZSB2ZXJkaWN0LlxuICAvLyAgLSBUaGUgcnVuJ3MgcXVldWUgdHJhbnNwb3J0IHByZXNlcnZlcyBiaW5hcnkgcGF5bG9hZHMgKENCT1IsXG4gIC8vICAgIHNwZWNWZXJzaW9uID49IDMpOiBgc3RlcElucHV0LmlucHV0YCBpcyB0aGUgc2VyaWFsaXplZCAocG9zc2libHlcbiAgLy8gICAgZW5jcnlwdGVkKSBpbnB1dCBieXRlcywgd2hpY2ggdGhlIEpTT04gdHJhbnNwb3J0IHdvdWxkIG1hbmdsZS5cbiAgY29uc3QgcmVzaWxpZW50RGlzcGF0Y2hFbGlnaWJsZSA9XG4gICAgc3RlcERpc3BhdGNoICE9PSB1bmRlZmluZWQgJiZcbiAgICBpc1Jlc2lsaWVudFN0ZXBEaXNwYXRjaEVuYWJsZWQoKSAmJlxuICAgIChydW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NCT1JfUVVFVUVfVFJBTlNQT1JUO1xuXG4gIC8vIEJhdGNoZWQgZmFuLW91dDogZm9sZCB0aGlzIHN1c3BlbnNpb24ncyBzdGVwX2NyZWF0ZWQgKyB3YWl0X2NyZWF0ZWRcbiAgLy8gd3JpdGVzIGludG8gb25lIGBldmVudHMuY3JlYXRlQmF0Y2hgIGNhbGwgKG9uZSBkdXJhYmxlIHdyaXRlLCBwZXItZXZlbnRcbiAgLy8gb3V0Y29tZXMpIGluc3RlYWQgb2Ygb25lIHdyaXRlIHBlciBldmVudC4gRW5nYWdlcyBvbmx5IGZvciBhIENMRUFOXG4gIC8vIGZhbi1vdXQgKG5vIGF0dHJpYnV0ZSB3cml0ZXMsIG5vIGhvb2sgd3JpdGVzLCBubyByZXNpbGllbnQgZGlzcGF0Y2hcbiAgLy8gd2hvc2UgY3JlYXRlcyBhcmUgZWFjaCBwYWlyZWQgd2l0aCBhIHF1ZXVlIHB1Ymxpc2gpIG9uIGEgV29ybGQgdGhhdFxuICAvLyBpbXBsZW1lbnRzIHRoZSBvcHRpb25hbCBtZXRob2QgYW5kIGEgcnVuIHdob3NlIGV2ZW50cyBhcmUgc2xvdC1udW1iZXJlZC5cbiAgLy8gRXZlcnl0aGluZyBvdXRzaWRlIHRoZSBnYXRlIGtlZXBzIHRoZSBzaW5nbGUtZXZlbnQgcGF0aCBieXRlLWZvci1ieXRlLlxuICBjb25zdCBiYXRjaEZhbm91dEVsaWdpYmxlID1cbiAgICBpc0JhdGNoVHJhbnNpdGlvbnNFbmFibGVkKCkgJiZcbiAgICB0eXBlb2Ygd29ybGQuZXZlbnRzLmNyZWF0ZUJhdGNoID09PSAnZnVuY3Rpb24nICYmXG4gICAgKHJ1bi5zcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfU0xPVF9JREVOVElUWSAmJlxuICAgICFyZXNpbGllbnREaXNwYXRjaEVsaWdpYmxlICYmXG4gICAgYWxsSG9va0l0ZW1zLmxlbmd0aCA9PT0gMCAmJlxuICAgIGF0dHJpYnV0ZUl0ZW1zLmxlbmd0aCA9PT0gMDtcbiAgLyoqXG4gICAqIFRoZSBmb2xkJ3MgY29sbGVjdGlvbiwgaW4gc2NoZWR1bGluZyBvcmRlciAoc3RlcHMgaW4gc3RlcEl0ZW1zIG9yZGVyLFxuICAgKiB0aGVuIHdhaXRzKS4gU3RlcCBlbnRyaWVzIGFyZSBlbnF1ZXVlZCBieSB0aGVpciBwcmVwIHByb21pc2VzIChpbnB1dFxuICAgKiBkZWh5ZHJhdGlvbiBydW5zIGNvbmN1cnJlbnRseSwgc28gZW50cmllcyBhcmUgb3JkZXJlZCBieSBgb3JkZXJgLCBub3QgYnlcbiAgICogY29tcGxldGlvbik7IHRoZSBzaW5nbGUgZmx1c2ggb3AgYmVsb3cgYXdhaXRzIGV2ZXJ5IHByZXAsIHNvcnRzLCBhbmRcbiAgICogY29tbWl0cyB0aGUgd2hvbGUgc2V0IHRocm91Z2ggYGNyZWF0ZUJhdGNoYC5cbiAgICovXG4gIGNvbnN0IGJhdGNoUXVldWU6IHtcbiAgICBvcmRlcjogbnVtYmVyO1xuICAgIGtpbmQ6ICdzdGVwJyB8ICd3YWl0JyB8ICdpbmxpbmUtY3JlYXRlZCcgfCAnaW5saW5lLXN0YXJ0ZWQnO1xuICAgIGNvcnJlbGF0aW9uSWQ6IHN0cmluZztcbiAgICAvKiogVGhlIHN0ZXAncyBuYW1lLCBzZXQgb24gc3RlcC1jYXJyeWluZyBraW5kcyAodGhlIGluLWZsdXNoIHB1Ymxpc2hlc1xuICAgICAqICBhbmQgdGhlIGRpc3BhdGNoIGlkZW1wb3RlbmN5IGtleSBuZWVkIGl0KS4gKi9cbiAgICBzdGVwTmFtZT86IHN0cmluZztcbiAgICBldmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICB9W10gPSBbXTtcbiAgY29uc3QgYmF0Y2hQcmVwczogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgLy8gUHJlLWNsYWltZWQgaW5saW5lIHBhaXJzOiBmb2xkIGVhY2ggbGF6eS1pbmxpbmUgc3RlcCdzIGRlZmVycmVkXG4gIC8vIGBzdGVwX2NyZWF0ZWRgIChjYXJyeWluZyBpdHMgaW5wdXQpIEFORCBpdHMgYHN0ZXBfc3RhcnRlZGAgY2xhaW0gKGJhcmUsXG4gIC8vIG93bmVyc2hpcC1zdGFtcGVkKSBpbnRvIHRoZSBiYXRjaCwgc28gdGhlIGlubGluZSBzdGVwcycgY2xhaW1zIGNvbW1pdCBpblxuICAvLyBvbmUgZHVyYWJsZSB3cml0ZSAodGhlIHBhaXIgY2h1bmssIHNlZSB0aGUgZmx1c2ggYmVsb3cpIGFuZCB0aGUgY2FsbGVyXG4gIC8vIHN0YXJ0cyB0aGUgYm9kaWVzIHN0cmFpZ2h0IG9mZiB0aGF0IGNvbW1pdCBpbnN0ZWFkIG9mIHBvc3Rpbmcgb25lIGNsYWltXG4gIC8vIHBlciBpbmxpbmUgc3RlcC4gUmVxdWlyZXMgVFdPIG9yIG1vcmUgaW5saW5lIHN0ZXBzLCBhbmQgbm90aGluZyBlbHNlOlxuICAvLyB0aGUgcGFpcnMgY29tbWl0IGluIGEgY2h1bmsgb2YgdGhlaXIgb3duLCBzbyBwbGFpbiBjcmVhdGVzIGFsb25nc2lkZVxuICAvLyB0aGVtIHNoYXJlIG5vIHJvdW5kIHRyaXAgd2l0aCB0aGUgcGFpcnMgYW5kIGNhbm5vdCBtYWtlIGEgbG9uZSBwYWlyXG4gIC8vIHdvcnRoIGZvbGRpbmcuIEEgbG9uZSBpbmxpbmUgc3RlcCBpcyBiZXR0ZXIgc2VydmVkIGJ5IHRoZSBsYXp5XG4gIC8vIGBzdGVwX3N0YXJ0ZWRgOiBvbmUgcm93IGluc3RlYWQgb2YgdHdvLCBvcHRpbWlzdGljLXN0YXJ0IGNhcGFibGUgKHRoZVxuICAvLyBjbGFpbSBvdmVybGFwcyB0aGUgYm9keSksIHdpdGggdGhlIHNsb3Qtc25hcHNob3QgcGFyYW1zIGFuZFxuICAvLyBidW1wLWFuZC1yZXBvcnQgYGNyZWF0ZUd1YXJkZWRgIHByb3ZpZGVzLCBhbGwgb2Ygd2hpY2ggYSBwYWlyLW9ubHlcbiAgLy8gYmF0Y2ggb2Ygb25lIHBhaXIgZ2l2ZXMgdXAgZm9yIHRoZSBzYW1lIHJvdW5kIHRyaXAuIFR3byBvciBtb3JlIGlubGluZVxuICAvLyBzdGVwcyBiZWNvbWUgT05FIHBhaXIgY2h1bmsgaW5zdGVhZCBvZiBOIHBhcmFsbGVsIGxhenkgY2xhaW1zLCB3aGljaCBpc1xuICAvLyB0aGUgc2F2aW5nLiBBIGxvbmUgaW5saW5lIHN0ZXAgYWxvbmdzaWRlIGVhZ2VyIGNyZWF0ZXMgdGhlcmVmb3JlIHRha2VzXG4gIC8vIHRoZSBsYXp5IHBhdGggd2hpbGUgdGhlIGNyZWF0ZXMgc3RpbGwgYmF0Y2guIEFsc28gcmVxdWlyZXMgdGhlIGNhbGxlcidzXG4gIC8vIGBvd25lck1lc3NhZ2VJZGA6IHRoZSBzdGFydGVkIHJvdyBtdXN0IHN0YW1wIG93bmVyc2hpcCBleGFjdGx5IGxpa2UgdGhlXG4gIC8vIGxhenkgY2xhaW0gaXQgcmVwbGFjZXMgKGFuZCBhIGNhbGxlciB0aGF0IGRvZXMgbm90IGlubGluZS1leGVjdXRlIG5ldmVyXG4gIC8vIHByb3ZpZGVzIG9uZSkuXG4gIGNvbnN0IGlubGluZVBhaXJGb2xkRWxpZ2libGUgPVxuICAgIGJhdGNoRmFub3V0RWxpZ2libGUgJiZcbiAgICBvd25lck1lc3NhZ2VJZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzLnNpemUgPj0gMjtcbiAgY29uc3QgaW5saW5lQ2xhaW1zOiBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdFsnaW5saW5lQ2xhaW1zJ10gPSBuZXcgTWFwKCk7XG5cbiAgLy8gVGhlIHRyYWNlIGNhcnJpZXIgZm9yIHJlc2lsaWVudCBzdGVwIGRpc3BhdGNoZXMsIHJlc29sdmVkIGF0IG1vc3Qgb25jZSBwZXJcbiAgLy8gc3VzcGVuc2lvbiAodGhlIHBlci1zdGVwIG9wcyBydW4gY29uY3VycmVudGx5IGFuZCBzaGFyZSBpdCkuXG4gIGxldCBzdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXI6IFByb21pc2U8VHJhY2VDYXJyaWVyPiB8IHVuZGVmaW5lZDtcbiAgY29uc3QgZ2V0U3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyID0gKCk6IFByb21pc2U8VHJhY2VDYXJyaWVyPiA9PiB7XG4gICAgc3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyID8/PVxuICAgICAgc3RlcERpc3BhdGNoPy5nZXRUcmFjZUNhcnJpZXIoKSA/PyBQcm9taXNlLnJlc29sdmUoe30pO1xuICAgIHJldHVybiBzdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXI7XG4gIH07XG5cbiAgLy8gUHJvZHVjZXItc2lkZSByZXNpbGllbnQgcmVjb3ZlcnkgY291bnQgZm9yIHRoZSBzdXNwZW5zaW9uIHNwYW4gYXR0cmlidXRlLlxuICBsZXQgcmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQgPSAwO1xuXG4gIC8vIFN0ZXBzOiBjcmVhdGUgc3RlcF9jcmVhdGVkIGV2ZW50cyAobm8gcXVldWluZywgVjIgcmV0dXJucyBwZW5kaW5nIHN0ZXBzXG4gIC8vIHRvIGNhbGxlciwgRVhDRVBUIG9uIHRoZSByZXNpbGllbnQgZGlzcGF0Y2ggcGF0aCwgd2hpY2ggcGFyYWxsZWxpemVzIHRoZVxuICAvLyBjcmVhdGUgd2l0aCB0aGUgc3RlcCdzIHF1ZXVlIHB1Ymxpc2ggYW5kIHJlcG9ydHMgaXQgaW5cbiAgLy8gYHF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkc2ApLlxuICBsZXQgYmF0Y2hPcmRlckNvdW50ZXIgPSAwO1xuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBzdGVwSXRlbXMpIHtcbiAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgLy8gRGV0ZXJtaW5pc3RpYyBwb3NpdGlvbiBpbiB0aGUgYmF0Y2hlZCBmb2xkIChhc3NpZ25lZCBpbiBzdGVwSXRlbXNcbiAgICAgIC8vIG9yZGVyLCBiZWZvcmUgdGhlIGNvbmN1cnJlbnQgZGVoeWRyYXRpb24gcnVucykuIEEgcGFpci1mb2xkZWQgaW5saW5lXG4gICAgICAvLyBzdGVwIG9jY3VwaWVzIHR3byBjb25zZWN1dGl2ZSBwb3NpdGlvbnMgKGNyZWF0ZWQgcm93IHRoZW4gc3RhcnRlZFxuICAgICAgLy8gcm93KSwgd2hpY2ggdGhlIGZsdXNoIGtlZXBzIGFkamFjZW50LCBuZXZlciBzcGxpdHMgYWNyb3NzIGNodW5rcyxcbiAgICAgIC8vIGFuZCBjb21taXRzIGluIGEgcGFpci1vbmx5IGNodW5rIGFoZWFkIG9mIHRoZSBwbGFpbiBjcmVhdGVzLCBzbyBhXG4gICAgICAvLyBXb3JsZCBjYW4gZm9sZCB0aGVtIGludG8gb25lIGJvcm4tcnVubmluZyBjcmVhdGUuXG4gICAgICBjb25zdCBwYWlyRm9sZGVkID1cbiAgICAgICAgaW5saW5lUGFpckZvbGRFbGlnaWJsZSAmJlxuICAgICAgICBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgIGNvbnN0IHN0ZXBPcmRlciA9IGJhdGNoT3JkZXJDb3VudGVyO1xuICAgICAgYmF0Y2hPcmRlckNvdW50ZXIgKz0gcGFpckZvbGRlZCA/IDIgOiAxO1xuICAgICAgY29uc3Qgc3RlcE9wID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgbGV0IGRlaHlkcmF0ZWRJbnB1dDogU2VyaWFsaXplZERhdGE7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGVoeWRyYXRlZElucHV0ID0gYXdhaXQgZGVoeWRyYXRlSW5wdXQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNvdXJjZTogJ3N0ZXBfaW5wdXQnLFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoIVNlcmlhbGl6YXRpb25FcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBlLmcuIFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3I6IGFuIFNESyBmYXVsdCwgbm90IGEgdXNlciB2YWx1ZVxuICAgICAgICAgICAgLy8gcHJvYmxlbS4gS2VlcCBpdHMgaWRlbnRpdHkgKFJVTlRJTUVfRVJST1IpIGFuZCBjdXJyZW50XG4gICAgICAgICAgICAvLyBmYWlsLXRoZS1zdXNwZW5zaW9uIGJlaGF2aW9yLlxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXN0ZXBEaXNwYXRjaCkge1xuICAgICAgICAgICAgLy8gTm8gZGlzcGF0Y2ggdGFyZ2V0IG1lYW5zIG5vIHJlcGxheSB3aWxsIG9ic2VydmUgYVxuICAgICAgICAgICAgLy8gZmluYWxpemF0aW9uOiB0aGlzIGlzIHRoZSB0ZXJtaW5hbCBkcmFpbiAob3IgYSBjcmVhdGUtb25seVxuICAgICAgICAgICAgLy8gdGVzdCBjYWxsZXIpLiBUaGUgcnVuIGlzIGFscmVhZHkgY29tcGxldGluZy9mYWlsaW5nLCBzb1xuICAgICAgICAgICAgLy8gd3JpdGluZyBzdGVwX2NyZWF0ZWQgKyBzdGVwX2ZhaWxlZCBoZXJlIHdvdWxkIGxlYXZlIGUuZy4gYVxuICAgICAgICAgICAgLy8gQ09NUExFVEVEIHJ1biBjYXJyeWluZyBhIGZhaWxlZCBzdGVwIG5vdGhpbmcgY2FuIGV2ZXJcbiAgICAgICAgICAgIC8vIG9ic2VydmUsIHJlYWRpbmcgYXMgYSBidWcgZnJvbSB0aGUgZGFzaGJvYXJkLiBSZXRocm93XG4gICAgICAgICAgICAvLyBpbnN0ZWFkOyB0aGUgZHJhaW4ncyBvd24gY2F0Y2ggc3dhbGxvd3MgaXQsIHByZXNlcnZpbmcgaXRzXG4gICAgICAgICAgICAvLyBwcmUtZXhpc3RpbmcgYmVoYXZpb3IgKG5vIHJvd3MgZm9yIHRoZSB1bmF3YWl0ZWQgc3RlcCkuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IGZpbmFsaXplVW5zZXJpYWxpemFibGVTdGVwKHF1ZXVlSXRlbSwgZXJyKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gRGVmZXJyZWQgKGxhenkpIGlubGluZSBzdGVwOiBza2lwIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUg4oCUIHRoZVxuICAgICAgICAvLyBjYWxsZXIncyBpbmxpbmUgZXhlY3V0ZVN0ZXAgd2lsbCBzZW5kIGEgbGF6eSBzdGVwX3N0YXJ0ZWQgY2FycnlpbmdcbiAgICAgICAgLy8gdGhpcyBpbnB1dCwgYW5kIHRoZSB3b3JsZCBjcmVhdGVzIHRoZSBzdGVwIChlbnRpdHkgKyBzeW50aGV0aWNcbiAgICAgICAgLy8gc3RlcF9jcmVhdGVkIGV2ZW50KSBhdG9taWNhbGx5LiBXZSBkbyBOT1QgYWRkIGl0IHRvXG4gICAgICAgIC8vIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM7IG93bmVyc2hpcCBpcyBkZWNpZGVkIGJ5IHRoYXQgbGF6eVxuICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQncyBhdG9taWMgY3JlYXRlLWNsYWltIGluc3RlYWQuXG4gICAgICAgIGlmIChsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgIGxhenlJbmxpbmVCeUNvcnJlbGF0aW9uSWQuc2V0KHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLCB7XG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHBhaXJGb2xkZWQpIHtcbiAgICAgICAgICAgIC8vIEVucXVldWUgdGhlIHBhaXIgdGhlIGRlZmVycmFsIHdvdWxkIG90aGVyd2lzZSBsZWF2ZSB0byB0aGVcbiAgICAgICAgICAgIC8vIGNhbGxlcidzIGxhenkgYHN0ZXBfc3RhcnRlZGA6IHRoZSBjcmVhdGVkIHJvdyBjYXJyaWVzIHRoZVxuICAgICAgICAgICAgLy8gaW5wdXQgKHBheWxvYWRzIHJpZGUgY3JlYXRlcyBpbiBhIGJhdGNoKSwgdGhlIHN0YXJ0ZWQgcm93IGlzXG4gICAgICAgICAgICAvLyBiYXJlIGFuZCBzdGFtcHMgdGhpcyBpbnZvY2F0aW9uJ3Mgb3duZXJzaGlwLCB0aGUgc2FtZSBjbGFpbVxuICAgICAgICAgICAgLy8gc2hhcGUgdGhlIGxhenkgc3RhcnQgd291bGQgaGF2ZSBzZW50LCBzZXR0bGVkIGJ5IHRoZSBiYXRjaC5cbiAgICAgICAgICAgIGJhdGNoUXVldWUucHVzaCh7XG4gICAgICAgICAgICAgIG9yZGVyOiBzdGVwT3JkZXIsXG4gICAgICAgICAgICAgIGtpbmQ6ICdpbmxpbmUtY3JlYXRlZCcsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYmF0Y2hRdWV1ZS5wdXNoKHtcbiAgICAgICAgICAgICAgb3JkZXI6IHN0ZXBPcmRlciArIDEsXG4gICAgICAgICAgICAgIGtpbmQ6ICdpbmxpbmUtc3RhcnRlZCcsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfc3RhcnRlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIC8vIENoZWNrZWQgYnkgaW5saW5lUGFpckZvbGRFbGlnaWJsZTsgc3ByZWFkIGtlZXBzIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gbmFycm93LXRocm91Z2gtY2xvc3VyZSBwcm9ibGVtIGF3YXkgZnJvbSB0aGUgdHlwZS5cbiAgICAgICAgICAgICAgICAgIC4uLihvd25lck1lc3NhZ2VJZCAhPT0gdW5kZWZpbmVkID8geyBvd25lck1lc3NhZ2VJZCB9IDoge30pLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXNpbGllbnQgc3RlcCBkaXNwYXRjaDogZmlyZSB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlIGFuZCB0aGVcbiAgICAgICAgLy8gc3RlcC1leGVjdXRpb24gcXVldWUgcHVibGlzaCBpbiBwYXJhbGxlbDogdGhlIG1lc3NhZ2UgY2FycmllcyB0aGVcbiAgICAgICAgLy8gc2FtZSBzZXJpYWxpemVkIGlucHV0IChgc3RlcElucHV0YCkgc28gdGhlIGNvbnN1bWVyIGNhblxuICAgICAgICAvLyBpZGVtcG90ZW50bHkgcmUtZW5zdXJlIHRoZSBldmVudCBpZiB0aGUgZGlyZWN0IHdyaXRlIGZhaWxlZFxuICAgICAgICAvLyB0cmFuc2llbnRseS4gTWlycm9ycyB0aGUgcmVzaWxpZW50IHN0YXJ0IChgcnVuSW5wdXRgKSBhbmRcbiAgICAgICAgLy8gcmVzaWxpZW50IGhvb2sgcmVzdW1lIChgaG9va0lucHV0YCkgcGF0dGVybnMuIE9ubHkgZm9yIGlucHV0cyB0aGVcbiAgICAgICAgLy8gcXVldWUgbWVzc2FnZSBjYW4gc2FmZWx5IGNhcnJ5IChiaW5hcnksIHVuZGVyIHRoZSBWUVMgc2l6ZSBjYXApLlxuICAgICAgICBpZiAoXG4gICAgICAgICAgcmVzaWxpZW50RGlzcGF0Y2hFbGlnaWJsZSAmJlxuICAgICAgICAgIGRlaHlkcmF0ZWRJbnB1dCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiZcbiAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQuYnl0ZUxlbmd0aCA8PSBNQVhfUkVTSUxJRU5UX1NURVBfSU5QVVRfQllURVNcbiAgICAgICAgKSB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICAgICAgICBjb25zdCB0cmFjZUNhcnJpZXIgPSBhd2FpdCBnZXRTdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIoKTtcbiAgICAgICAgICBjb25zdCBbY3JlYXRlUmVzdWx0LCBxdWV1ZVJlc3VsdF0gPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW1xuICAgICAgICAgICAgY3JlYXRlR3VhcmRlZChzdGVwRXZlbnQsIHsgcmVxdWVzdElkIH0pLFxuICAgICAgICAgICAgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBpbXBsaWVkIGJ5IHJlc2lsaWVudERpc3BhdGNoRWxpZ2libGVcbiAgICAgICAgICAgICAgc3RlcERpc3BhdGNoIS5xdWV1ZU5hbWUsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIHN0ZXBJbnB1dDogeyBpbnB1dDogZGVoeWRyYXRlZElucHV0IH0sXG4gICAgICAgICAgICAgICAgcnVuQ29udGV4dDogcnVuRGlzcGF0Y2hDb250ZXh0KHJ1biksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIC8vIFNhbWUga2V5IGFzIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzIGFuZCBhbnkgY29uY3VycmVudFxuICAgICAgICAgICAgICAvLyBoYW5kbGVyJ3MsIHNvIHJlZHVuZGFudCBwdWJsaXNoZXMgZm9yIHRoaXMgc3RlcCBkZWR1cGUuIFRoZVxuICAgICAgICAgICAgICAvLyBrZXkgaXMgc3RlcC1pZGVudGl0eS1zY29wZWQgc28gYSByZXZva2VkIG1lc3NhZ2UgZm9yIGFcbiAgICAgICAgICAgICAgLy8gcmVhc3NpZ25lZCBjb3JyZWxhdGlvbiBpZCBjYW5ub3QgYWJzb3JiIHRoZSBjb3JyZWN0ZWRcbiAgICAgICAgICAgICAgLy8gc2NoZWR1bGUncyBkaXNwYXRjaDogc2VlIHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5LlxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5KFxuICAgICAgICAgICAgICAgICAgcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0uc3RlcE5hbWVcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0pO1xuICAgICAgICAgIC8vIFF1ZXVlIGZhaWx1cmUgaXMgYWx3YXlzIGZhdGFsIGZvciB0aGlzIHN1c3BlbnNpb24gcGFzczogd2l0aG91dFxuICAgICAgICAgIC8vIHRoZSBtZXNzYWdlIHRoZSBzdGVwIHdvdWxkIHJlbHkgb24gdGhlIGNyZWF0ZSBhbG9uZSwgYW5kIGlmIHRoZVxuICAgICAgICAgIC8vIGNyZWF0ZSBBTFNPIGZhaWxlZCB0aGVyZSB3b3VsZCBiZSBubyBkdXJhYmxlIHJlY29yZCBhdCBhbGwuXG4gICAgICAgICAgLy8gUHJvcGFnYXRpbmcgcmVkZWxpdmVycyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2UsIHdoaWNoXG4gICAgICAgICAgLy8gcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcyxcbiAgICAgICAgICAvLyB0aGUgc2FtZSByZWNvdmVyeSBhcyB0aGUgc2VxdWVudGlhbCBwYXRoLlxuICAgICAgICAgIGlmIChxdWV1ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgIHRocm93IHF1ZXVlUmVzdWx0LnJlYXNvbjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgaWYgKGNyZWF0ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgIGNvbnN0IGVyciA9IGNyZWF0ZVJlc3VsdC5yZWFzb247XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIC8vIENvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSBpdCBmaXJzdCwgc2FtZSBhcyB0aGUgc2VxdWVudGlhbFxuICAgICAgICAgICAgICAvLyBwYXRoLiBUaGUgc3RlcCBtZXNzYWdlIGlzIGFscmVhZHkgb3V0OyBhIGR1cGxpY2F0ZSBwdWJsaXNoXG4gICAgICAgICAgICAgIC8vIGJ5IHRoYXQgaGFuZGxlciBkZWR1cGVzIG9uIHRoZSBzaGFyZWQgaWRlbXBvdGVuY3kga2V5LlxuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc1JldHJ5YWJsZVdvcmxkRXJyb3IoZXJyKSkge1xuICAgICAgICAgICAgICAvLyBSZXNpbGllbnQ6IHRoZSB3cml0ZSBmYWlsZWQgdHJhbnNpZW50bHkgKDQyOSAvIDV4eCAvXG4gICAgICAgICAgICAgIC8vIHRyYW5zcG9ydCkgYnV0IHRoZSBzdGVwIG1lc3NhZ2UgKGNhcnJ5aW5nIHRoZSBzYW1lXG4gICAgICAgICAgICAgIC8vIHNlcmlhbGl6ZWQgaW5wdXQpIHdhcyBwdWJsaXNoZWQsIHNvIHRoZSBjb25zdW1lclxuICAgICAgICAgICAgICAvLyBpZGVtcG90ZW50bHkgcmUtZW5zdXJlcyB0aGUgc3RlcF9jcmVhdGVkIGJlZm9yZSBleGVjdXRpbmcuXG4gICAgICAgICAgICAgIHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkKys7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAnU3RlcCBjcmVhdGlvbiBldmVudCB3cml0ZSBmYWlsZWQsIGJ1dCB0aGUgc3RlcCB3YXMgJyArXG4gICAgICAgICAgICAgICAgICAnZGlzcGF0Y2hlZCB2aWEgdGhlIHF1ZXVlLiBUaGUgc3RlcF9jcmVhdGVkIGV2ZW50IHdpbGwgJyArXG4gICAgICAgICAgICAgICAgICAnYmUgZW5zdXJlZCBieSB0aGUgcXVldWUgY29uc3VtZXIuJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgICAgICAgLy8gRm9sZCBpbnRvIHRoZSBiYXRjaCBpbnN0ZWFkIG9mIHdyaXRpbmcgaGVyZS4gVGhlIGVuY2xvc2luZ1xuICAgICAgICAgIC8vIHByb21pc2Ugam9pbnMgYGJhdGNoUHJlcHNgIChzZWUgdGhlIGxvb3AgYmVsb3cpLCBzbyB0aGUgZmx1c2hcbiAgICAgICAgICAvLyBvcCBjYW5ub3QgcnVuIGJlZm9yZSB0aGlzIHN0ZXAncyBpbnB1dCBmaW5pc2hlZCBkZWh5ZHJhdGluZy5cbiAgICAgICAgICBiYXRjaFF1ZXVlLnB1c2goe1xuICAgICAgICAgICAgb3JkZXI6IHN0ZXBPcmRlcixcbiAgICAgICAgICAgIGtpbmQ6ICdzdGVwJyxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIGV2ZW50OiBzdGVwRXZlbnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpO1xuICAgICAgb3BzLnB1c2goc3RlcE9wKTtcbiAgICAgIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgICAgIC8vIFRoZSBmbHVzaCBvcCB3YWl0cyBmb3IgZXZlcnkgcHJlcCBiZWZvcmUgY29tbWl0dGluZzsgYSBwcmVwIHRoYXRcbiAgICAgICAgLy8gcmVqZWN0ZWQgYWxyZWFkeSBzdXJmYWNlcyB0aHJvdWdoIGBvcHNgLCBzbyB0aGUgZmx1c2gncyBvd24gd2FpdFxuICAgICAgICAvLyBzd2FsbG93cyBpdCBhbmQgY29tbWl0cyB3aGF0ZXZlciB3YXMgc3VjY2Vzc2Z1bGx5IGVucXVldWVkLFxuICAgICAgICAvLyBwcmVzZXJ2aW5nIHRvZGF5J3MgcGVyLW9wIGluZGVwZW5kZW5jZS5cbiAgICAgICAgYmF0Y2hQcmVwcy5wdXNoKHN0ZXBPcC5jYXRjaCgoKSA9PiB7fSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSB3YWl0IGV2ZW50cyAoc2FtZSBhcyBWMSlcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICBjb25zdCB3YWl0RXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgcmVzdW1lQXQ6IHF1ZXVlSXRlbS5yZXN1bWVBdCxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBpZiAoYmF0Y2hGYW5vdXRFbGlnaWJsZSkge1xuICAgICAgICAvLyBXYWl0cyBuZWVkIG5vIGRlaHlkcmF0aW9uLCBzbyB0aGV5IGVucXVldWUgc3luY2hyb25vdXNseSwgYWZ0ZXJcbiAgICAgICAgLy8gZXZlcnkgc3RlcCdzIG9yZGVyIHNsb3QsIHByZXNlcnZpbmcgc3RlcHMtdGhlbi13YWl0cyBzY2hlZHVsaW5nXG4gICAgICAgIC8vIG9yZGVyIGluIHRoZSBsb2cuXG4gICAgICAgIGJhdGNoUXVldWUucHVzaCh7XG4gICAgICAgICAgb3JkZXI6IGJhdGNoT3JkZXJDb3VudGVyKyssXG4gICAgICAgICAga2luZDogJ3dhaXQnLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50OiB3YWl0RXZlbnQsXG4gICAgICAgIH0pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZCh3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBUaGUgYmF0Y2hlZCBmb2xkJ3MgZmx1c2g6IHRoZSBjbGVhbiBmYW4tb3V0IGNvbW1pdHMgdGhyb3VnaFxuICAvLyBgY3JlYXRlQmF0Y2hgIGluIGNodW5rcyBvZiBNQVhfQkFUQ0hfRkFOT1VUX0VWRU5UUywgYWxsIGNodW5rcyBJTlxuICAvLyBGTElHSFQgQ09OQ1VSUkVOVExZLiBTbG90IGFzc2lnbm1lbnQgaXMgdGhlIHNlcnZlcidzLCBzbyBwYXJhbGxlbFxuICAvLyBjaHVua3MgcmFjZSBmb3Igc2xvdCByYW5nZXMgZXhhY3RseSBsaWtlIHRoZSBwcmUtZm9sZCBwYXRoJ3MgcGFyYWxsZWxcbiAgLy8gc2luZ2xlIHdyaXRlcyBkaWQ7IGVudGl0eSBjb25kaXRpb25zLCBub3QgY29tbWl0IG9yZGVyLCBjYXJyeVxuICAvLyBjb3JyZWN0bmVzcyAoc2libGluZyBmYW4tb3V0IGV2ZW50cyBoYXZlIG5vIGNyb3NzLW9yZGVyIHRoZSByZXBsYXlcbiAgLy8gZGVwZW5kcyBvbjsgaXQgbWF0Y2hlcyBieSBjb3JyZWxhdGlvbiBpZCkuIEVhY2ggZXZlbnQgcmVwb3J0cyB0aGVcbiAgLy8gb3V0Y29tZSBpdHMgb3duIHNpbmdsZSBjcmVhdGUgd291bGQgaGF2ZSBoYWQ6IGEgNDA5IGlzIHRoZSBzYW1lXG4gIC8vIGFscmVhZHktZXhpc3RzIHRvbGVyYW5jZSBhcyB0aGUgc2luZ2xlIHBhdGgsIGFueXRoaW5nIGVsc2UgZmFpbHMgdGhlXG4gIC8vIGRlbGl2ZXJ5IHRoZSB3YXkgYSBzaW5nbGUtcGF0aCByZWplY3Rpb24gd291bGQuXG4gIC8vXG4gIC8vIExhdGVuY3kgc2hhcGU6IG9ubHkgdGhlIGNodW5rIGNhcnJ5aW5nIHRoZSBwcmUtY2xhaW1lZCBpbmxpbmUgcGFpcnNcbiAgLy8gZ2F0ZXMgdGhlIGhhbmRsZXIncyByZXR1cm4gKHRoZSBjYWxsZXIgc3RhcnRzIGJvZGllcyBvZmYgaXRzIGNsYWltcyksXG4gIC8vIGFuZCB0aGF0IGNodW5rIGNhcnJpZXMgTk9USElORyBlbHNlLCBzbyBpdHMgY29tbWl0IGlzIGFzIHNtYWxsIGFzIHRoZVxuICAvLyBpbmxpbmUgc2xpY2UgKHNlZSB0aGUgY2h1bmtpbmcgYmVsb3cpLlxuICAvLyBFdmVyeSBvdGhlciBjaHVuaydzIGNvbW1pdCAoYW5kIGV2ZXJ5IGNodW5rJ3Mgc3RlcC1tZXNzYWdlIHB1Ymxpc2hlcyxcbiAgLy8gd2hpY2ggZmlyZSB0aGUgbW9tZW50IElUUyBjcmVhdGVzIGFyZSBkdXJhYmxlKSByaWRlc1xuICAvLyBgZGVmZXJyZWRCYXRjaFdvcmtgIHdoZW4gdGhlIGNhbGxlciBvcHRlZCBpbiwgam9pbmVkIGJlZm9yZSBhY2suIEEgc2xvd1xuICAvLyBzaWJsaW5nIGNodW5rIHRoZXJlZm9yZSBkZWxheXMgbmVpdGhlciB0aGUgaW5saW5lIGJvZGllcyBub3IgYW5vdGhlclxuICAvLyBjaHVuaydzIHF1ZXVlIG1lc3NhZ2VzLCB3aGlsZSBwdWJsaXNoLWFmdGVyLWNyZWF0ZSBzdGlsbCBob2xkcyBwZXJcbiAgLy8gc3RlcDogYSBzdGVwJ3MgbWVzc2FnZSBpcyBvbmx5IGV2ZXIgc2VudCBhZnRlciB0aGUgY2h1bmsgY2FycnlpbmcgaXRzXG4gIC8vIGNyZWF0ZSBoYXMgY29tbWl0dGVkLlxuICBsZXQgZGVmZXJyZWRCYXRjaFdvcms6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG4gIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgb3BzLnB1c2goXG4gICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAvLyBQcmVwcyB0aGF0IHJlamVjdGVkIGFscmVhZHkgc3VyZmFjZSB0aHJvdWdoIHRoZWlyIG93biBgb3BzYFxuICAgICAgICAvLyBlbnRyaWVzOyB0aGUgZm9sZCBjb21taXRzIHdoYXRldmVyIHdhcyBzdWNjZXNzZnVsbHkgZW5xdWV1ZWQsXG4gICAgICAgIC8vIHByZXNlcnZpbmcgdG9kYXkncyBwZXItb3AgaW5kZXBlbmRlbmNlLlxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChiYXRjaFByZXBzKTtcbiAgICAgICAgaWYgKGJhdGNoUXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBbLi4uYmF0Y2hRdWV1ZV0uc29ydCgoYSwgYikgPT4gYS5vcmRlciAtIGIub3JkZXIpO1xuICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAvLyBUaGUgb3JkaW5hcnkgc2luZ2xlIHBhdGggZm9yIGEgbG9uZSBwbGFpbiBlbnRyeTogYSBiYXRjaCBvZiBPTkVcbiAgICAgICAgLy8gZ2FpbnMgbm90aGluZyBvdmVyIHRoZSBzaW5nbGUgd3JpdGUgKHNhbWUgcm91bmQgdHJpcCkgYW5kIGxvc2VzXG4gICAgICAgIC8vIHRoZSBzbG90LXNuYXBzaG90IHBhcmFtcyArIGJ1bXAtYW5kLXJlcG9ydCB0aGF0IGNyZWF0ZUd1YXJkZWRcbiAgICAgICAgLy8gcHJvdmlkZXMsIHNvIGEgbG9uZSBlYWdlciBldmVudCBpcyB3cml0dGVuIHRoZSB3YXkgaXQgd291bGQgaGF2ZVxuICAgICAgICAvLyBiZWVuIHdpdGhvdXQgdGhlIGZvbGQsIHdpdGggdGhlIHNhbWUgY29uZmxpY3QgdG9sZXJhbmNlIGFuZFxuICAgICAgICAvLyBvd25lcnNoaXAgYm9va2tlZXBpbmcuIFVzZWQgd2hlbiB0aGUgd2hvbGUgZm9sZCBpcyBvbmUgZW50cnlcbiAgICAgICAgLy8gKGJlbG93KSBhbmQgd2hlbiB0aGUgcGxhaW4gcGFydGl0aW9uIGJlc2lkZSB0aGUgcGFpcnMgaXMgb25lXG4gICAgICAgIC8vIGVudHJ5ICh0aGUgY2h1bmtpbmcgZnVydGhlciBkb3duKS4gQmVzaWRlIGEgcGFpciBjaHVuayBpdCBjb21taXRzXG4gICAgICAgIC8vIGNvbmN1cnJlbnRseSB3aXRoIHRoZSBoYW5kbGVyJ3MgcmV0dXJuLCBsaWtlIGEgdHJhaWxpbmcgY2h1bms7IHRoZVxuICAgICAgICAvLyBpbmxpbmUgYm9kaWVzIGRvIG5vdCBkZXBlbmQgb24gaXQgKGV4ZWN1dG9yIHdyaXRlcyBjYXJyeSBubyBzbG90XG4gICAgICAgIC8vIHNuYXBzaG90LCBzbyB0aGVyZSBpcyBubyBwb3NpdGlvbiBmb3IgaXQgdG8gbW92ZSkuXG4gICAgICAgIGNvbnN0IGNvbW1pdFNpbmdsZSA9IGFzeW5jIChcbiAgICAgICAgICBlbnRyeTogKHR5cGVvZiBlbnRyaWVzKVtudW1iZXJdXG4gICAgICAgICk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKGVudHJ5LmV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kID09PSAnc3RlcCcpIHtcbiAgICAgICAgICAgICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQoZW50cnkuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICBlbnRyeS5raW5kID09PSAnc3RlcCdcbiAgICAgICAgICAgICAgICAgID8gJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnXG4gICAgICAgICAgICAgICAgICA6ICdXYWl0IGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAoZW50cmllcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICBhd2FpdCBjb21taXRTaW5nbGUoZW50cmllc1swXSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNlZWQgZm9yIHRoZSBmb3JlaWduLWludGVybGVhdmluZyBkaWFnbm9zdGljIGJlbG93LiBXaXRoIGNodW5rc1xuICAgICAgICAvLyBjb21taXR0aW5nIGluIHBhcmFsbGVsIHRoZXJlIGlzIG5vIHBlci1jaHVuayBcImV4cGVjdGVkIG5leHQgc2xvdFwiO1xuICAgICAgICAvLyB0aGUgd2hvbGUgZm9sZCdzIGNvbW1pdHRlZCBzcGFuIGlzIGNvbXBhcmVkIGFnYWluc3QgdGhlIHNlZWRcbiAgICAgICAgLy8gb25jZSBldmVyeSBjaHVuayBoYXMgc2V0dGxlZDogY29tbWl0dGVkIHNsb3RzIGFyZSBkZW5zZSBwZXIgdGhlXG4gICAgICAgIC8vIFdvcmxkJ3MgaW52YXJpYW50LCBzbyBhbnkgZXhjZXNzIG9mIChtYXggY29tbWl0dGVkIHNsb3Qg4oiSIHNlZWQgK1xuICAgICAgICAvLyAxKSBvdmVyIHRoZSBmb2xkJ3Mgb3duIGNvbW1pdHRlZCBjb3VudCBpcyBldmVudHMgT1RIRVIgd3JpdGVyc1xuICAgICAgICAvLyBsYW5kZWQgaW4gYmV0d2Vlbi5cbiAgICAgICAgY29uc3QgZXhwZWN0ZWRGaXJzdFNsb3QgPSBldmVudExvZ1xuICAgICAgICAgID8gKG1heEV2ZW50U2xvdChldmVudExvZy5ldmVudHMpID8/IDApICsgMVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICAvLyBQYWlyLWF3YXJlIGNodW5raW5nLiBUd28gcnVsZXM6XG4gICAgICAgIC8vXG4gICAgICAgIC8vIDEuIEEgcHJlLWNsYWltZWQgcGFpcidzIHR3byByb3dzIG11c3QgbGFuZCBpbiB0aGUgc2FtZSBjcmVhdGVCYXRjaFxuICAgICAgICAvLyAgICBjYWxsIChhZGphY2VudCwgc28gYSBXb3JsZCBjYW4gZm9sZCB0aGVtIGludG8gb25lIGJvcm4tcnVubmluZ1xuICAgICAgICAvLyAgICBjcmVhdGUpIGFuZCBuZXZlciBzdHJhZGRsZSBhIGNodW5rIGJvdW5kYXJ5LCB3aGljaCB3b3VsZCB0dXJuXG4gICAgICAgIC8vICAgIHRoZSBzdGFydGVkIHJvdyBpbnRvIGEgc3RhbmRhbG9uZSBjbGFpbSByYWNpbmcgaXRzIG93blxuICAgICAgICAvLyAgICBjcmVhdGUncyBjb21taXQuXG4gICAgICAgIC8vIDIuIFRoZSBwYWlycyBjb21taXQgaW4gY2h1bmsocykgb2YgVEhFSVIgT1dOLCBhaGVhZCBvZiB0aGUgcGxhaW5cbiAgICAgICAgLy8gICAgYHN0ZXBgL2B3YWl0YCBjcmVhdGVzLCB3aGljaCBmaWxsIHRoZSBzdWJzZXF1ZW50IGNodW5rcy4gVGhlXG4gICAgICAgIC8vICAgIHBhaXIgY2h1bmsgaXMgdGhlIG9uZSBjb21taXQgdGhlIGlubGluZSBib2RpZXMgd2FpdCBmb3IgKHNlZVxuICAgICAgICAvLyAgICBgcGFpckNvbW1pdHNgIGJlbG93KSwgYW5kIG9uIHRoZSBWZXJjZWwgYmFja2VuZCBpdHMgbGF0ZW5jeVxuICAgICAgICAvLyAgICBzY2FsZXMgd2l0aCB0aGUgdHJhbnNhY3Rpb24ncyBpdGVtIGNvdW50OiBtZWFzdXJlZCBvbiAzMi1icmFuY2hcbiAgICAgICAgLy8gICAgZmFuLW91dHMsIGJhdGNoZXMgb2YgPD04IGV2ZW50cyBjb21taXQgaW4gfjU2IG1zIHA1MCBzZXJ2ZXItc2lkZVxuICAgICAgICAvLyAgICB3aGVyZSBiYXRjaGVzIG9mIDI0LTMyIGV2ZW50cyB0YWtlIH4xMTAgbXMuIFBhZGRpbmcgdGhlIHBhaXJcbiAgICAgICAgLy8gICAgY2h1bmsgd2l0aCBwbGFpbiBjcmVhdGVzIHVwIHRvIHRoZSBjYXAgdGhlcmVmb3JlIGhlbGQgdGhlXG4gICAgICAgIC8vICAgIGJvZGllcyBmb3IgdGhlIHBsYWluIGNyZWF0ZXMnIGNvbW1pdCwgd2hpY2ggbm90aGluZyBlbHNlXG4gICAgICAgIC8vICAgIG5lZWRlZDogYSBwbGFpbiBjcmVhdGUgZ2F0ZXMgb25seSBpdHMgb3duIHF1ZXVlIHB1Ymxpc2gsIGFuZFxuICAgICAgICAvLyAgICB0aGF0IGZpcmVzIG9mZiB3aGljaGV2ZXIgc2libGluZyBjaHVuayBjYXJyaWVzIGl0LiBTcGxpdHRpbmdcbiAgICAgICAgLy8gICAgdGhlbSBrZWVwcyB0aGUgcGFpciBjaHVuayBzbWFsbCAodHdvIHJvd3MgcGVyIGlubGluZSBzdGVwKSBhbmRcbiAgICAgICAgLy8gICAgbGV0cyB0aGUgcGxhaW4gY3JlYXRlcyBjb21taXQgY29uY3VycmVudGx5IGJlc2lkZSBpdC5cbiAgICAgICAgY29uc3QgY2h1bmtFbnRyaWVzID0gKGxpc3Q6IHR5cGVvZiBlbnRyaWVzKTogKHR5cGVvZiBlbnRyaWVzKVtdID0+IHtcbiAgICAgICAgICBjb25zdCBvdXQ6ICh0eXBlb2YgZW50cmllcylbXSA9IFtdO1xuICAgICAgICAgIGxldCBjdXJyZW50OiB0eXBlb2YgZW50cmllcyA9IFtdO1xuICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBsaXN0Lmxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICAgICAgY29uc3QgZW50cnkgPSBsaXN0W2luZGV4XTtcbiAgICAgICAgICAgIGNvbnN0IG5leHQgPSBsaXN0W2luZGV4ICsgMV07XG4gICAgICAgICAgICBjb25zdCBwYWlyTGVhZCA9XG4gICAgICAgICAgICAgIGVudHJ5LmtpbmQgPT09ICdpbmxpbmUtY3JlYXRlZCcgJiZcbiAgICAgICAgICAgICAgbmV4dD8ua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJyAmJlxuICAgICAgICAgICAgICBuZXh0LmNvcnJlbGF0aW9uSWQgPT09IGVudHJ5LmNvcnJlbGF0aW9uSWQ7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gcGFpckxlYWQgPyAyIDogMTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgY3VycmVudC5sZW5ndGggPiAwICYmXG4gICAgICAgICAgICAgIGN1cnJlbnQubGVuZ3RoICsgdGFrZSA+IE1BWF9CQVRDSF9GQU5PVVRfRVZFTlRTXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgb3V0LnB1c2goY3VycmVudCk7XG4gICAgICAgICAgICAgIGN1cnJlbnQgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnQucHVzaChlbnRyeSk7XG4gICAgICAgICAgICBpZiAocGFpckxlYWQpIHtcbiAgICAgICAgICAgICAgY3VycmVudC5wdXNoKG5leHQpO1xuICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY3VycmVudC5sZW5ndGggPiAwKSBvdXQucHVzaChjdXJyZW50KTtcbiAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgICAgICAvLyBCb3RoIHBhcnRpdGlvbnMga2VlcCBgZW50cmllc2AnIG9yZGVyLCBzbyBhIHBhaXIncyB0d28gcm93c1xuICAgICAgICAvLyAoY29uc2VjdXRpdmUgYG9yZGVyYCB2YWx1ZXMsIGVucXVldWVkIHRvZ2V0aGVyKSBzdGF5IGFkamFjZW50IGluXG4gICAgICAgIC8vIHRoZSBwYWlyIHBhcnRpdGlvbi5cbiAgICAgICAgY29uc3QgaXNQYWlyUm93ID0gKGVudHJ5OiAodHlwZW9mIGVudHJpZXMpW251bWJlcl0pOiBib29sZWFuID0+XG4gICAgICAgICAgZW50cnkua2luZCA9PT0gJ2lubGluZS1jcmVhdGVkJyB8fCBlbnRyeS5raW5kID09PSAnaW5saW5lLXN0YXJ0ZWQnO1xuICAgICAgICBjb25zdCBwYWlyQ2h1bmtzID0gY2h1bmtFbnRyaWVzKFxuICAgICAgICAgIGVudHJpZXMuZmlsdGVyKChlbnRyeSkgPT4gaXNQYWlyUm93KGVudHJ5KSlcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcGxhaW5FbnRyaWVzID0gZW50cmllcy5maWx0ZXIoKGVudHJ5KSA9PiAhaXNQYWlyUm93KGVudHJ5KSk7XG4gICAgICAgIC8vIEEgcGxhaW4gcGFydGl0aW9uIG9mIGV4YWN0bHkgT05FIGVudHJ5IGlzIHRoZSBiYXRjaC1vZi1vbmUgY2FzZVxuICAgICAgICAvLyBhZ2Fpbiwgbm93IHRoYXQgdGhlIHBhaXJzIG5vIGxvbmdlciBzaGFyZSBpdHMgY2h1bms6IGl0IHRha2VzIHRoZVxuICAgICAgICAvLyBzaW5nbGUgcGF0aCAoYGNvbW1pdFNpbmdsZWApIHJhdGhlciB0aGFuIGEgb25lLXJvdyBjcmVhdGVCYXRjaCxcbiAgICAgICAgLy8gYW5kIGlzIGNhcnJpZWQgYXMgYSBvbmUtZW50cnkgY2h1bmsgc28gdGhlIHBlci1jaHVuayBwdWJsaXNoIGFuZFxuICAgICAgICAvLyBzZXR0bGUgbWFjaGluZXJ5IGJlbG93IHRyZWF0cyBpdCBsaWtlIGFueSBzaWJsaW5nLiAoQSBvbmUtcm93XG4gICAgICAgIC8vIHJlbWFpbmRlciBvZiBhIExBUkdFUiBwbGFpbiBwYXJ0aXRpb24gc3RpbGwgYmF0Y2hlczogaXQgaXMgdGhlXG4gICAgICAgIC8vIHByZS1zcGxpdCBiZWhhdmlvciwgdW5jaGFuZ2VkIGhlcmUuKVxuICAgICAgICBjb25zdCBwbGFpbkNodW5rcyA9XG4gICAgICAgICAgcGxhaW5FbnRyaWVzLmxlbmd0aCA9PT0gMVxuICAgICAgICAgICAgPyBbcGxhaW5FbnRyaWVzXVxuICAgICAgICAgICAgOiBjaHVua0VudHJpZXMocGxhaW5FbnRyaWVzKTtcbiAgICAgICAgY29uc3Qgc2luZ2xlQ2h1bmsgPVxuICAgICAgICAgIHBsYWluRW50cmllcy5sZW5ndGggPT09IDEgPyBwbGFpbkNodW5rc1swXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgY2h1bmtzOiAodHlwZW9mIGVudHJpZXMpW10gPSBbLi4ucGFpckNodW5rcywgLi4ucGxhaW5DaHVua3NdO1xuICAgICAgICAvLyBTdGVwcyB3aG9zZSBxdWV1ZSBtZXNzYWdlcyBUSElTIEZMVVNIIHdpbGwgcHVibGlzaCAodGhlIGVhZ2VyXG4gICAgICAgIC8vIGNyZWF0ZXMpLCByZWNvcmRlZCBiZWZvcmUgYW55IGNodW5rIHNldHRsZXMgc28gdGhlIGNhbGxlcidzXG4gICAgICAgIC8vIGRpc3BhdGNoIHBhc3MgKHdoaWNoIHJ1bnMgb2ZmIHRoZSBoYW5kbGVyJ3MgcmV0dXJuKSBza2lwcyB0aGVtLlxuICAgICAgICAvLyBUaGUgc2VuZHMgYXJlIGd1YXJhbnRlZWQtb3ItZmFpbGVkIGJ5IHRoZSB0cmFpbGluZyB3b3JrIHRoZVxuICAgICAgICAvLyBjYWxsZXIgam9pbnMgYmVmb3JlIGFja2luZywgc28gXCJ3aWxsIGJlIHB1Ymxpc2hlZCBieSB0aGlzIGZsdXNoXCJcbiAgICAgICAgLy8gYW5kIFwiYWxyZWFkeSBwdWJsaXNoZWRcIiBhcmUgZXF1aXZhbGVudCBmcm9tIHRoZSBjYWxsZXIncyBzaWRlLlxuICAgICAgICBjb25zdCBwdWJsaXNoRWFnZXJTdGVwcyA9IHN0ZXBEaXNwYXRjaCAhPT0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAocHVibGlzaEVhZ2VyU3RlcHMpIHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kID09PSAnc3RlcCcpIHtcbiAgICAgICAgICAgICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChlbnRyeS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUYWxsaWVzIGZvciB0aGUgZm9yZWlnbi1pbnRlcmxlYXZpbmcgZGlhZ25vc3RpYywgZm9sZGVkIGFjcm9zc1xuICAgICAgICAvLyB0aGUgY29uY3VycmVudCBjaHVua3MgYW5kIHJlYWQgb25jZSBhbGwgb2YgdGhlbSBzZXR0bGVkLlxuICAgICAgICBsZXQgY29tbWl0dGVkQ291bnQgPSAwO1xuICAgICAgICBsZXQgbWF4Q29tbWl0dGVkU2xvdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGNvbnN0IGNvbW1pdENodW5rID0gYXN5bmMgKGNodW5rOiB0eXBlb2YgZW50cmllcyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgIC8vIEFuY2hvcnMgZm9yIHRoZSBwcmUtY2xhaW1lZCBzdGVwcycgdGVsZW1ldHJ5OiB0aGUgUE9TVCBpbnN0YW50XG4gICAgICAgICAgLy8gaXMgdGhlIGNsYWltJ3MgXCJzdGFydCBQT1NUIHNlbnRcIiAoUlNGUydzIGVuZCksIHRoZSByZXR1cm4gaXMgdGhlXG4gICAgICAgICAgLy8gY2xhaW0ncyBjb21wbGV0aW9uIChUVFIncyBUNiksIHRoZSBzYW1lIHR3byBpbnN0YW50cyB0aGUgbGF6eVxuICAgICAgICAgIC8vIGNsYWltJ3Mgb3duIFBPU1Qgd291bGQgaGF2ZSBwcm9kdWNlZC5cbiAgICAgICAgICBjb25zdCBiYXRjaFBvc3RTZW50QXRNcyA9IERhdGUubm93KCk7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBiYXRjaEZhbm91dEVsaWdpYmxlIGltcGxpZXMgcHJlc2VuY2VcbiAgICAgICAgICBjb25zdCB7IHJlc3VsdHMgfSA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGVCYXRjaCEoXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGNodW5rLm1hcCgoZW50cnkpID0+ICh7XG4gICAgICAgICAgICAgIGV2ZW50OiBlbnRyeS5ldmVudCxcbiAgICAgICAgICAgICAgLy8gVGhlIHN0YXJ0ZWQgcm93IGlzIHRoZSBzdGVwJ3MgZXhlY3V0aW5nIGNsYWltLCBzbyBpdCBjYXJyaWVzXG4gICAgICAgICAgICAgIC8vIHRoZSBjb21wdXRlLWluc3RhbmNlIGF0dHJpYnV0aW9uIHRoZSBzaW5nbGUgY2xhaW0gc2VuZHMgdmlhXG4gICAgICAgICAgICAgIC8vIENyZWF0ZUV2ZW50UGFyYW1zLlxuICAgICAgICAgICAgICAuLi4oZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJ1xuICAgICAgICAgICAgICAgID8geyBjb21wdXRlSW5zdGFuY2VJZDogQ09NUFVURV9JTlNUQU5DRV9JRCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICB9KSksXG4gICAgICAgICAgICAvLyBQZXItd3JpdGUgcmVxdWVzdCBhdHRyaWJ1dGlvbiwgc2FtZSBhcyB0aGUgc2luZ2xlIHBhdGgnc1xuICAgICAgICAgICAgLy8gY3JlYXRlR3VhcmRlZCjigKYsIHsgcmVxdWVzdElkIH0pLlxuICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgY2xhaW1Db21wbGV0ZWRBdE1zID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgaXRlbV0gb2YgcmVzdWx0cy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gY2h1bmtbaW5kZXhdO1xuICAgICAgICAgICAgaWYgKGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBpZiAoZW50cnkua2luZCA9PT0gJ3N0ZXAnKSB7XG4gICAgICAgICAgICAgICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQoZW50cnkuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJykge1xuICAgICAgICAgICAgICAgIC8vIFRoZSBwYWlyIGNvbW1pdHRlZDogdGhpcyBpbnZvY2F0aW9uIG93bnMgdGhlIHN0ZXAgYW5kIHRoZVxuICAgICAgICAgICAgICAgIC8vIGNhbGxlciBydW5zIHRoZSBib2R5IHdpdGggbm8gY2xhaW0gb2YgaXRzIG93bi4gVGhlXG4gICAgICAgICAgICAgICAgLy8gcmVhZGJhY2sgZW50aXR5IGlzIGF1dGhvcml0YXRpdmUgd2hlcmUgcHJlc2VudDsgYSBXb3JsZFxuICAgICAgICAgICAgICAgIC8vIHRoYXQgb21pdHRlZCBpdCBnZXRzIHRoZSBzYW1lIGxvY2FsbHkgc3ludGhlc2l6ZWQgcnVubmluZ1xuICAgICAgICAgICAgICAgIC8vIGF0dGVtcHQtMSB0aGUgb3B0aW1pc3RpYyBwYXRoIGV4ZWN1dGVzIGFnYWluc3QuIEVpdGhlclxuICAgICAgICAgICAgICAgIC8vIHdheSB0aGUgaW5wdXQgaXMgcmUtYXR0YWNoZWQgbG9jYWxseTogYmF0Y2ggcmVzcG9uc2VzXG4gICAgICAgICAgICAgICAgLy8gcmV0dXJuIHJlZnMgbGF6aWx5LCBhbmQgdGhlIGJvZHkncyBoeWRyYXRpb24gd2FudHMgdGhlXG4gICAgICAgICAgICAgICAgLy8gZXhhY3QgYnl0ZXMgdGhlIHBhaXIncyBjcmVhdGVkIHJvdyBjYXJyaWVkLiAoVGhlIGNyZWF0ZWRcbiAgICAgICAgICAgICAgICAvLyByb3cncyBzdWNjZXNzIGlzIGRlbGliZXJhdGVseSBOT1QgbWVtYmVyc2hpcCBpblxuICAgICAgICAgICAgICAgIC8vIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM6IGZvciBpbmxpbmUgc3RlcHMgb3duZXJzaGlwIGlzXG4gICAgICAgICAgICAgICAgLy8gdGhlIHN0YXJ0ZWQgcm93J3MgdmVyZGljdCwgYW5kIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzXG4gICAgICAgICAgICAgICAgLy8gc2tpcHMgaW5saW5lIGNvcnJlbGF0aW9uIGlkcyByZWdhcmRsZXNzLilcbiAgICAgICAgICAgICAgICBjb25zdCBkZWh5ZHJhdGVkID0gbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5nZXQoXG4gICAgICAgICAgICAgICAgICBlbnRyeS5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAoZGVoeWRyYXRlZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAvLyBVbnJlYWNoYWJsZTogdGhlIHNhbWUgcHJlcCBvcCB0aGF0IGVucXVldWVkIHRoZSBwYWlyIHNldFxuICAgICAgICAgICAgICAgICAgLy8gdGhpcyBlbnRyeSwgYW5kIHRoZSBmbHVzaCBhd2FpdGVkIGV2ZXJ5IHByZXAgYWJvdmUuXG4gICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgLy8gTm90IGZyZWUgaWYgaXQgZXZlciBmaXJlcywgdGhvdWdoOiB0aGUgcGFpciBpcyBhbHJlYWR5XG4gICAgICAgICAgICAgICAgICAvLyBkdXJhYmxlIGhlcmUsIHNvIHRoaXMgdGhyb3dzIHdpdGggdGhlIHN0ZXAgY2xhaW1lZCBhbmRcbiAgICAgICAgICAgICAgICAgIC8vIGl0cyBib2R5IG5ldmVyIHJ1bi4gVGhlIGRlbGl2ZXJ5IGZhaWxzLCBhbmQgcmVkZWxpdmVyeVxuICAgICAgICAgICAgICAgICAgLy8gcmVjb3ZlcnMgaXQgdGhyb3VnaCBvd25lZC1yZWNvdmVyeSAodGhlIHN0ZXAgY2FycmllcyB0aGlzXG4gICAgICAgICAgICAgICAgICAvLyBtZXNzYWdlJ3Mgb3duZXJzaGlwIHN0YW1wKSByYXRoZXIgdGhhbiB0aGUgcmVxdWVzdCBqdXN0XG4gICAgICAgICAgICAgICAgICAvLyBmYWlsaW5nIGNsZWFubHkuXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dXb3JsZEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgbm8gZGVoeWRyYXRlZCBpbnB1dCBmb3IgcHJlLWNsYWltZWQgc3RlcCAke2VudHJ5LmNvcnJlbGF0aW9uSWR9YCxcbiAgICAgICAgICAgICAgICAgICAgeyBzdGF0dXM6IDUwMCB9XG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ZWRTdGVwOiBTdGFydGVkU3RlcCA9IGl0ZW0uc3RlcD8uc3RhcnRlZEF0XG4gICAgICAgICAgICAgICAgICA/IHsgLi4uaXRlbS5zdGVwLCBzdGFydGVkQXQ6IGl0ZW0uc3RlcC5zdGFydGVkQXQgfVxuICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcElkOiBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBkZWh5ZHJhdGVkLnN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogJ3J1bm5pbmcnLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgc3RhcnRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaW5saW5lQ2xhaW1zLnNldChlbnRyeS5jb3JyZWxhdGlvbklkLCB7XG4gICAgICAgICAgICAgICAgICBvd25lZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgIHN0ZXA6IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uc3RhcnRlZFN0ZXAsXG4gICAgICAgICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkLmRlaHlkcmF0ZWRJbnB1dCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBiYXRjaFBvc3RTZW50QXRNcyxcbiAgICAgICAgICAgICAgICAgIGNsYWltQ29tcGxldGVkQXRNcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpdGVtLnN0YXR1cyA9PT0gNDA5KSB7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBlbnRyeS5raW5kID09PSAnaW5saW5lLWNyZWF0ZWQnIHx8XG4gICAgICAgICAgICAgICAgZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJ1xuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgcGFpciBsb3N0IGl0cyBhdG9taWMgY3JlYXRlLWNsYWltOiBhIGNvbmN1cnJlbnQgd3JpdGVyXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBvd25zIHRoaXMgc3RlcCAoYW4gZWFybGllciBkZWxpdmVyeSdzIGNyZWF0ZSwgb3IgYVxuICAgICAgICAgICAgICAgIC8vIHJhY2luZyBoYW5kbGVyJ3MgY2xhaW0pLiBSZWNvcmRlZCBhcyBhIGxvc3QgY2xhaW06IHRoZVxuICAgICAgICAgICAgICAgIC8vIGNhbGxlcidzIGV4ZWN1dGVTdGVwIHJldHVybnMgYHNraXBwZWRgIHdpdGhvdXQgcnVubmluZyB0aGVcbiAgICAgICAgICAgICAgICAvLyBib2R5LCB0aGUgc2FtZSBvdXRjb21lIGFzIGxvc2luZyB0aGUgbGF6eSBjbGFpbS4gQSBXb3JsZFxuICAgICAgICAgICAgICAgIC8vIHRoYXQgZm9sZHMgdGhlIHBhaXIgcmVwb3J0cyB0aGUgNDA5IG9uIGJvdGggcm93cyAoc2V0XG4gICAgICAgICAgICAgICAgLy8gdHdpY2UsIGhhcm1sZXNzKTsgb25lIHRoYXQgZXZhbHVhdGVzIHJvd3MgaW5kZXBlbmRlbnRseVxuICAgICAgICAgICAgICAgIC8vIGhhcyB0aGUgc3RhcnRlZCByb3cgKHByb2Nlc3NlZCBzZWNvbmQpIGRlY2lkZSwgd2hpY2ggaXNcbiAgICAgICAgICAgICAgICAvLyBleGFjdGx5IHRoZSBzaW5nbGUgcGF0aCdzIHNlbWFudGljcyAoY3JlYXRlIGxvc3QgKyBjbGFpbVxuICAgICAgICAgICAgICAgIC8vIHdvbiBzdGlsbCBydW5zIHRoZSBib2R5OyBjcmVhdGUgd29uICsgY2xhaW0gbG9zdCBza2lwcykuXG4gICAgICAgICAgICAgICAgaW5saW5lQ2xhaW1zLnNldChlbnRyeS5jb3JyZWxhdGlvbklkLCB7IG93bmVkOiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0lubGluZSBzdGVwIHByZS1jbGFpbSBsb3N0LCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgbWVzc2FnZTogaXRlbS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIFNhbWUgdG9sZXJhbmNlIGFzIHRoZSBzaW5nbGUgcGF0aCdzIEVudGl0eUNvbmZsaWN0RXJyb3I6IGFcbiAgICAgICAgICAgICAgLy8gY29uY3VycmVudCBvciBlYXJsaWVyIGRlbGl2ZXJ5IGFscmVhZHkgY3JlYXRlZCBpdC5cbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgIGVudHJ5LmtpbmQgPT09ICdzdGVwJ1xuICAgICAgICAgICAgICAgICAgPyAnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZydcbiAgICAgICAgICAgICAgICAgIDogJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogZW50cnkuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGl0ZW0ubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93V29ybGRFcnJvcihcbiAgICAgICAgICAgICAgYGJhdGNoZWQgJHtlbnRyeS5ldmVudC5ldmVudFR5cGV9IGZvciAke2VudHJ5LmNvcnJlbGF0aW9uSWR9IGAgK1xuICAgICAgICAgICAgICAgIGBmYWlsZWQ6ICR7aXRlbS5lcnJvcn06ICR7aXRlbS5tZXNzYWdlfWAsXG4gICAgICAgICAgICAgIHsgc3RhdHVzOiBpdGVtLnN0YXR1cyB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBIaWdoZXN0IHNsb3QgdGhpcyBjaHVuayBjb21taXR0ZWQ6IG9uZSBpbnB1dCBvZiB0aGUgaW50ZXJsZWF2aW5nXG4gICAgICAgICAgLy8gZGlhZ25vc3RpYy5cbiAgICAgICAgICBjb25zdCBjaHVua01heFNsb3QgPSBtYXhFdmVudFNsb3QoXG4gICAgICAgICAgICByZXN1bHRzLmZsYXRNYXAoKGl0ZW0pID0+XG4gICAgICAgICAgICAgIGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZCAmJiBpdGVtLmV2ZW50ID8gW2l0ZW0uZXZlbnRdIDogW11cbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbW1pdHRlZENvdW50ICs9IHJlc3VsdHMuZmlsdGVyKFxuICAgICAgICAgICAgKGl0ZW0pID0+IGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICkubGVuZ3RoO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGNodW5rTWF4U2xvdCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAobWF4Q29tbWl0dGVkU2xvdCA9PT0gdW5kZWZpbmVkIHx8IGNodW5rTWF4U2xvdCA+IG1heENvbW1pdHRlZFNsb3QpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBtYXhDb21taXR0ZWRTbG90ID0gY2h1bmtNYXhTbG90O1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBQdWJsaXNoIHRoZSBjaHVuaydzIGVhZ2VyIHN0ZXBzJyBxdWV1ZSBtZXNzYWdlcyB0aGUgbW9tZW50IElUU1xuICAgICAgICAvLyBjcmVhdGVzIGFyZSBkdXJhYmxlLCB0aGUgcGVyLWNodW5rIGhhbGYgb2YgcHVibGlzaC1hZnRlci1jcmVhdGUuXG4gICAgICAgIC8vIFNhbWUgbWVzc2FnZSBzaGFwZSBhbmQgc3RlcC1pZGVudGl0eS1zY29wZWQgaWRlbXBvdGVuY3kga2V5IGFzIHRoZVxuICAgICAgICAvLyBjYWxsZXIncyBkaXNwYXRjaCBwYXNzLCBzbyBhbnl0aGluZyBkb3VibGUtcHVibGlzaGVkIGRlZHVwZXMuXG4gICAgICAgIGNvbnN0IHB1Ymxpc2hDaHVua1N0ZXBzID0gYXN5bmMgKFxuICAgICAgICAgIGNodW5rOiB0eXBlb2YgZW50cmllc1xuICAgICAgICApOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICBpZiAoIXB1Ymxpc2hFYWdlclN0ZXBzKSByZXR1cm47XG4gICAgICAgICAgY29uc3Qgc3RlcEVudHJpZXMgPSBjaHVuay5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS5raW5kID09PSAnc3RlcCcpO1xuICAgICAgICAgIGlmIChzdGVwRW50cmllcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICAgICAgICBjb25zdCB0cmFjZUNhcnJpZXIgPSBhd2FpdCBnZXRTdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIoKTtcbiAgICAgICAgICAvLyBPbmUgYmF0Y2hlZCBwdWJsaXNoIHBlciBjaHVuayBpbnN0ZWFkIG9mIG9uZSByb3VuZCB0cmlwIHBlciBzdGVwLlxuICAgICAgICAgIC8vIFRoZSBwdWJsaXNoZXMgYXJlIHRoZSBmYW4tb3V0J3Mgc2VyaWFsaXphdGlvbiBwb2ludDogdGhleSByaWRlIHRoZVxuICAgICAgICAgIC8vIHNoYXJlZCA4LWNvbm5lY3Rpb24gSFRUUC8xLjEgYWdlbnQgKHNlZSBgZ2V0UXVldWVEaXNwYXRjaGVyYCBpblxuICAgICAgICAgIC8vIHdvcmxkLXZlcmNlbCksIGFuZCB0aGUgY2FsbGVyIGF3YWl0cyBhbGwgb2YgdGhlbSBiZWZvcmUgcnVubmluZ1xuICAgICAgICAgIC8vIHRoZSBmaXJzdCBpbmxpbmUgc3RlcCBib2R5LCBzbyBOIHJvdW5kIHRyaXBzIGxhbmQgZGlyZWN0bHkgb25cbiAgICAgICAgICAvLyB0aW1lLXRvLWZpcnN0LXN0ZXAuIGBxdWV1ZU1lc3NhZ2VzYCBmYWxscyBiYWNrIHRvIGNvbmN1cnJlbnRcbiAgICAgICAgICAvLyBzaW5nbGUgc2VuZHMgb24gYSBXb3JsZCB3aXRoIG5vIGJhdGNoIHN1cHBvcnQuXG4gICAgICAgICAgYXdhaXQgcXVldWVNZXNzYWdlcyhcbiAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBwdWJsaXNoRWFnZXJTdGVwcyBpbXBsaWVzIHByZXNlbmNlXG4gICAgICAgICAgICBzdGVwRGlzcGF0Y2ghLnF1ZXVlTmFtZSxcbiAgICAgICAgICAgIHN0ZXBFbnRyaWVzLm1hcCgoZW50cnkpID0+ICh7XG4gICAgICAgICAgICAgIG1lc3NhZ2U6IHtcbiAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQ6IGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBzZXQgb24gZXZlcnkgJ3N0ZXAnIGVudHJ5IGF0IGVucXVldWVcbiAgICAgICAgICAgICAgICBzdGVwTmFtZTogZW50cnkuc3RlcE5hbWUhLFxuICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICBydW5Db250ZXh0OiBydW5EaXNwYXRjaENvbnRleHQocnVuKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgb3B0czoge1xuICAgICAgICAgICAgICAgIGlkZW1wb3RlbmN5S2V5OiBzdGVwRGlzcGF0Y2hJZGVtcG90ZW5jeUtleShcbiAgICAgICAgICAgICAgICAgIGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IHNldCBvbiBldmVyeSAnc3RlcCcgZW50cnkgYXQgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgZW50cnkuc3RlcE5hbWUhXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gTGF1bmNoIGV2ZXJ5IGNodW5rJ3MgUE9TVCBub3cgKHRoZSBsb25lIHBsYWluIGVudHJ5J3MgZ3VhcmRlZFxuICAgICAgICAvLyBzaW5nbGUgY3JlYXRlIGluY2x1ZGVkKTsgY2hhaW4gZWFjaCBjaHVuaydzIHB1Ymxpc2hlcyBvbiBpdHMgT1dOXG4gICAgICAgIC8vIGNvbW1pdCwgc28gcHVibGlzaC1hZnRlci1jcmVhdGUgaG9sZHMgZm9yIHRoZSBzaW5nbGUgdG9vLiBBIGNodW5rXG4gICAgICAgIC8vIHdob3NlIGNvbW1pdCByZWplY3RlZCBrZWVwcyBpdHMgbWVzc2FnZXMgdW5zZW50ICh0aGUgcmVqZWN0aW9uXG4gICAgICAgIC8vIGZhaWxzIHRoZSBkZWxpdmVyeTsgcmVkZWxpdmVyeSByZS1jcmVhdGVzIGFuZCByZS1kaXNwYXRjaGVzLFxuICAgICAgICAvLyBkZWR1cGVkIGJ5IHRoZSBpZGVtcG90ZW5jeSBrZXlzKS5cbiAgICAgICAgY29uc3QgY29tbWl0cyA9IGNodW5rcy5tYXAoKGNodW5rKSA9PlxuICAgICAgICAgIGNodW5rID09PSBzaW5nbGVDaHVuayA/IGNvbW1pdFNpbmdsZShjaHVua1swXSkgOiBjb21taXRDaHVuayhjaHVuaylcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcHVibGlzaGVzID0gY2h1bmtzLm1hcChhc3luYyAoY2h1bmssIGluZGV4KSA9PiB7XG4gICAgICAgICAgYXdhaXQgY29tbWl0c1tpbmRleF07XG4gICAgICAgICAgYXdhaXQgcHVibGlzaENodW5rU3RlcHMoY2h1bmspO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0cmFpbGluZyA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgLy8gTGV0IGV2ZXJ5IHNpYmxpbmcgc2V0dGxlIGJlZm9yZSBzdXJmYWNpbmcgdGhlIGZpcnN0IGZhaWx1cmU6IGFcbiAgICAgICAgICAvLyBjaHVuayB0aGF0IGNvbW1pdHRlZCBtdXN0IHN0aWxsIGdldCBpdHMgcHVibGlzaGVzIG91dCBldmVuIHdoZW5cbiAgICAgICAgICAvLyBhbm90aGVyIGNodW5rIGZhaWxlZCwgYW5kIHRoZSBjYWxsZXIgYWNrcyBvbmx5IGFmdGVyIHRoaXNcbiAgICAgICAgICAvLyByZXNvbHZlcy5cbiAgICAgICAgICBjb25zdCBzZXR0bGVkID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFsuLi5jb21taXRzLCAuLi5wdWJsaXNoZXNdKTtcbiAgICAgICAgICAvLyBGb3JlaWduLWludGVybGVhdmluZyB2aXNpYmlsaXR5OiB0aGUgYmF0Y2ggZW5kcG9pbnQgaGFzIG5vXG4gICAgICAgICAgLy8gYnVtcC1hbmQtcmVwb3J0LCBzbyBldmVudHMgb3RoZXIgd3JpdGVycyBsYW5kZWQgYmV0d2VlbiB0aGVcbiAgICAgICAgICAvLyBzbmFwc2hvdCBhbmQgdGhlc2UgY29tbWl0cyBwdXNoZWQgdGhlIGZvbGQgdG8gaGlnaGVyIHNsb3RzXG4gICAgICAgICAgLy8gV0lUSE9VVCBoYW5kaW5nIHVzIHRoZSBza2lwcGVkIGV2ZW50cy4gU2FtZSBhY2NlcHRlZCBleHBvc3VyZVxuICAgICAgICAgIC8vIGFzIGEgZHJvcHBlZCB0cnVuY2F0ZWQgcmVwb3J0IG9uIHRoZSBzaW5nbGUgcGF0aDogdGhlIGxvY2FsXG4gICAgICAgICAgLy8gbG9nIHN0YXlzIGEgc3RyaWN0IHByZWZpeCBhbmQgdGhlIG5leHQgcmVsb2FkIG9ic2VydmVzIHRoZW0uXG4gICAgICAgICAgLy8gTG9nZ2VkIHNvIGEgYnVtcCBpcyBkaWFnbm9zYWJsZSByYXRoZXIgdGhhbiBzaWxlbnQuXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgZXhwZWN0ZWRGaXJzdFNsb3QgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgbWF4Q29tbWl0dGVkU2xvdCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBpbnRlcmxlYXZlZCA9XG4gICAgICAgICAgICAgIG1heENvbW1pdHRlZFNsb3QgLSBleHBlY3RlZEZpcnN0U2xvdCArIDEgLSBjb21taXR0ZWRDb3VudDtcbiAgICAgICAgICAgIGlmIChpbnRlcmxlYXZlZCA+IDApIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnQmF0Y2hlZCBmYW4tb3V0IGNvbW1pdHRlZCBhYm92ZSBzbmFwc2hvdCcsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBleHBlY3RlZEZpcnN0U2xvdCxcbiAgICAgICAgICAgICAgICBtYXhDb21taXR0ZWRTbG90LFxuICAgICAgICAgICAgICAgIGNvbW1pdHRlZENvdW50LFxuICAgICAgICAgICAgICAgIGludGVybGVhdmVkLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgZmFpbHVyZSA9IHNldHRsZWQuZmluZChcbiAgICAgICAgICAgIChvdXRjb21lKTogb3V0Y29tZSBpcyBQcm9taXNlUmVqZWN0ZWRSZXN1bHQgPT5cbiAgICAgICAgICAgICAgb3V0Y29tZS5zdGF0dXMgPT09ICdyZWplY3RlZCdcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChmYWlsdXJlKSB0aHJvdyBmYWlsdXJlLnJlYXNvbjtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICAvLyBFVkVSWSBjaHVuayBjYXJyeWluZyBwYWlycyBnYXRlcyB0aGUgcmV0dXJuLCBub3QganVzdCB0aGUgZmlyc3Q6XG4gICAgICAgIC8vIGEgcGFpciB3aG9zZSBjb21taXQgdGhlIGNhbGxlciBoYXMgbm90IHNlZW4geWllbGRzIG5vXG4gICAgICAgIC8vIGBpbmxpbmVDbGFpbXNgIGVudHJ5LCBzbyB0aGUgY2FsbGVyIGZhbGxzIGJhY2sgdG8gYSBsYXp5XG4gICAgICAgIC8vIGBzdGVwX3N0YXJ0ZWRgIHRoYXQgd291bGQgcmFjZSB0aGlzIHNhbWUgZm9sZCdzIHN0aWxsLWluLWZsaWdodFxuICAgICAgICAvLyBwYWlyIGZvciB0aGUgc2FtZSBzdGVwLiBUaGUgcGFpcnMgb2NjdXB5IHRoZWlyIG93biBsZWFkaW5nXG4gICAgICAgIC8vIGNodW5rKHMpLCBhbmQgdG9kYXkgdGhhdCBpcyBleGFjdGx5IE9ORSBjaHVuayAodHdvIHJvd3MgcGVyXG4gICAgICAgIC8vIGlubGluZSBzdGVwIGZpdCBpbnNpZGUgb25lIGNodW5rLCBwaW5uZWQgYnkgY29uc3RhbnRzLnRlc3QudHMpLFxuICAgICAgICAvLyBzbyB0aGlzIGlzIGF0IG1vc3Qgb25lIGNvbW1pdDsgdGhlIGZpbHRlciBpcyB3aGF0IGtlZXBzIHRoZVxuICAgICAgICAvLyBwcm9wZXJ0eSB0cnVlIGlmIGVpdGhlciBjYXAgbW92ZXMuXG4gICAgICAgIGNvbnN0IHBhaXJDb21taXRzID0gY2h1bmtzLmZsYXRNYXAoKGNodW5rLCBpbmRleCkgPT5cbiAgICAgICAgICBjaHVuay5zb21lKChlbnRyeSkgPT4gZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJylcbiAgICAgICAgICAgID8gW2NvbW1pdHNbaW5kZXhdXVxuICAgICAgICAgICAgOiBbXVxuICAgICAgICApO1xuICAgICAgICBpZiAoYWxsb3dEZWZlcnJlZEJhdGNoV29yaykge1xuICAgICAgICAgIC8vIFRoZSB0cmFpbGluZyB3b3JrIGlzIHRoZSBjYWxsZXIncyB0byBqb2luIGJlZm9yZSBhY2suIEF0dGFjaCBhXG4gICAgICAgICAgLy8gaGFuZGxlciBub3cgc28gYSByZWplY3Rpb24gdGhhdCByYWNlcyB0aGF0IGpvaW4gKG9yIGEgZm9yZWdyb3VuZFxuICAgICAgICAgIC8vIGZhaWx1cmUgdGhhdCBwcmV2ZW50cyB0aGUgY2FsbGVyIGZyb20gZXZlciByZWFjaGluZyBpdCkgaXMgbmV2ZXJcbiAgICAgICAgICAvLyBhbiB1bmhhbmRsZWRSZWplY3Rpb247IGF3YWl0aW5nIHRoZSBwcm9taXNlIHN0aWxsIG9ic2VydmVzIGl0LlxuICAgICAgICAgIHRyYWlsaW5nLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICBkZWZlcnJlZEJhdGNoV29yayA9IHRyYWlsaW5nO1xuICAgICAgICAgIC8vIE9ubHkgdGhlIHBhaXIgY2h1bmtzIGdhdGUgdGhlIHJldHVybjogdGhlaXIgY2xhaW1zIGFyZSB3aGF0IHRoZVxuICAgICAgICAgIC8vIGNhbGxlciBzdGFydHMgdGhlIGlubGluZSBib2RpZXMgZnJvbS4gV2l0aCBubyBwYWlycyB0aGVyZSBpc1xuICAgICAgICAgIC8vIG5vdGhpbmcgdGhlIGNhbGxlcidzIHBvc3QtcmV0dXJuIHdvcmsgcmVhZHMgZnJvbSB0aGUgY29tbWl0cyxcbiAgICAgICAgICAvLyBzbyBub3RoaW5nIGdhdGVzLlxuICAgICAgICAgIGlmIChwYWlyQ29tbWl0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwYWlyQ29tbWl0cyk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgLy8gQSBwYWlyIGNodW5rIGZhaWxlZCwgc28gdGhpcyBwaGFzZSdzIHdyaXRlIHNldCBpcyBOT1QgdGhlXG4gICAgICAgICAgICAgIC8vIGNhbGxlcidzIHRvIGpvaW4gYW55IG1vcmU6IGBkZWZlcnJlZEJhdGNoV29ya2AgbmV2ZXJcbiAgICAgICAgICAgICAgLy8gcmVhY2hlcyBpdCBvbmNlIGhhbmRsZVN1c3BlbnNpb24gdGhyb3dzLiBTZXR0bGUgdGhlIHJlc3RcbiAgICAgICAgICAgICAgLy8gYmVmb3JlIHRoZSByZWplY3Rpb24gZXNjYXBlcywgZm9yIHRoZSByZWFzb24gYHNldHRsZVBoYXNlYFxuICAgICAgICAgICAgICAvLyBnaXZlczogYSBzaWJsaW5nIGNyZWF0ZSBsYW5kaW5nIGFmdGVyIHRoZSB0aHJvdyBjb21taXRzIGFuXG4gICAgICAgICAgICAgIC8vIGV2ZW50IGZyb20gdGhlIGFiYW5kb25lZCByZXBsYXkncyBzZWVkZWQgc2VxdWVuY2UgYW5kIHJhY2VzXG4gICAgICAgICAgICAgIC8vIHRoZSBjYWxsZXIncyByZXN0YXJ0IHJlbG9hZCB3aGlsZSBkb2luZyBzby5cbiAgICAgICAgICAgICAgYXdhaXQgdHJhaWxpbmcuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0IHRyYWlsaW5nO1xuICAgICAgICB9XG4gICAgICB9KSgpXG4gICAgKTtcbiAgfVxuXG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGF0dHJpYnV0ZUl0ZW1zKSB7XG4gICAgb3BzLnB1c2goXG4gICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgLy8gR3VhcmRlZCBsaWtlIGV2ZXJ5IG90aGVyIHN1c3BlbnNpb24gd3JpdGU6IGFuIGF0dHJfc2V0IGlzIGFcbiAgICAgICAgICAvLyByZXBsYXktZGVyaXZlZCBldmVudCB3aXRoIGEgY29ycmVsYXRpb24gaWQgZnJvbSB0aGlzIHJlcGxheSdzXG4gICAgICAgICAgLy8gc2VlZGVkIHNlcXVlbmNlLCBzbyBpdCBtdXN0IG5vdCBsYW5kIG9uIGEgbG9nIHRoZSByZXBsYXkgbmV2ZXJcbiAgICAgICAgICAvLyBzYXcuIFJlamVjdGluZyBpdCBpcyBjaGVhcDogYSBydW4gd2l0aCBhdHRyaWJ1dGUgZXZlbnRzIGFscmVhZHlcbiAgICAgICAgICAvLyBmb3JjZXMgYW4gaW4tcHJvY2VzcyByZXBsYXksIHNvIHRoZSByZXN0YXJ0IGNvc3RzIHRoZSByZXBsYXkgaXRcbiAgICAgICAgICAvLyB3YXMgZ29pbmcgdG8gZG8gYW55d2F5LlxuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2F0dHJfc2V0JyxcbiAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgY2hhbmdlczogcXVldWVJdGVtLmNoYW5nZXMsXG4gICAgICAgICAgICAgICAgd3JpdGVyOiB7IHR5cGU6ICd3b3JrZmxvdycgfSxcbiAgICAgICAgICAgICAgICAuLi4ocXVldWVJdGVtLmFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgICA/IHsgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXM6IHRydWUgfVxuICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IGF0dHJpYnV0ZSBldmVudCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmlzdGljIHZhbGlkYXRpb24gcmVqZWN0aW9uIGZyb20gdGhlIFdvcmxkLCBlLmcuIHRoZVxuICAgICAgICAgICAgLy8gY3VtdWxhdGl2ZSBwZXItcnVuIGF0dHJpYnV0ZSBjYXAsIHdoaWNoIG9ubHkgdGhlIFdvcmxkIGNhblxuICAgICAgICAgICAgLy8gY2hlY2sgYWdhaW5zdCB0aGUgcnVuJ3MgZXhpc3RpbmcgYXR0cmlidXRlcy4gUmVkZWxpdmVyaW5nIHRoZVxuICAgICAgICAgICAgLy8gb3JjaGVzdHJhdG9yIG1lc3NhZ2UgcmVwbGF5cyB0aGUgd29ya2Zsb3cgaW50byB0aGUgZXhhY3Qgc2FtZVxuICAgICAgICAgICAgLy8gd3JpdGUgYW5kIHRoZSBleGFjdCBzYW1lIHJlamVjdGlvbiwgc28gcmV0cnlpbmcgY2FuIG5ldmVyXG4gICAgICAgICAgICAvLyBzdWNjZWVkLiBTdXJmYWNlIGl0IGFzIGEgRmF0YWxFcnJvciBzbyB0aGUgY2FsbGVyIGZhaWxzIHRoZVxuICAgICAgICAgICAgLy8gcnVuIHdpdGggYSBjbGVhciBlcnJvciBpbnN0ZWFkIG9mIHdlZGdpbmcgaXQgaW4gcmVkZWxpdmVyeS5cbiAgICAgICAgICAgIGNvbnN0IGZhdGFsID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgICAgICAgIGBzZXRBdHRyaWJ1dGVzIGZhaWxlZCBXb3JsZCB2YWxpZGF0aW9uOiAke1xuICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKVxuICAgICAgICAgICAgICB9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGZhdGFsLmNhdXNlID0gZXJyO1xuICAgICAgICAgICAgdGhyb3cgZmF0YWw7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pKClcbiAgICApO1xuICB9XG5cbiAgLy8gQXdhaXQgdGhlIHN0ZXBfY3JlYXRlZCAvIHdhaXRfY3JlYXRlZCBldmVudCBjcmVhdGVzIGJlZm9yZSByZXR1cm5pbmcuXG4gIC8vIFRoZSBjYWxsZXIgKHdvcmtmbG93RW50cnlwb2ludCkgb25seSBlbnF1ZXVlcyB0aGUgc3RlcC1kaXNwYXRjaCBxdWV1ZVxuICAvLyBtZXNzYWdlcyBBRlRFUiBoYW5kbGVTdXNwZW5zaW9uIHJlc29sdmVzLCBhbmQgdGhlIHF1ZXVlIGhhbmRsZXIgYWNrc1xuICAvLyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2Ugb25seSBhZnRlciB0aGUgY2FsbGVyIHJlc29sdmVzLiBTbyB0aGUgc3RlcF9jcmVhdGVkXG4gIC8vIGV2ZW50cyBtdXN0IGJlIGR1cmFibGUgaGVyZSwgYW5kIHRoZSBkaXNwYXRjaCBzZW5kcyBtdXN0IGNvbXBsZXRlIGluIHRoZSBjYWxsZXIsXG4gIC8vIGFsbCBiZWZvcmUgYWNrLiBJZiB0aGUgcHJvY2VzcyBjcmFzaGVzIGJlZm9yZSB0aGlzIHJlc29sdmVzLCB0aGUgb3JjaGVzdHJhdG9yXG4gIC8vIG1lc3NhZ2UgaXMgbm90IGFja2VkIGFuZCBWUVMgcmVkZWxpdmVycywgcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpXG4gIC8vIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcywgYW5kIHJlY292ZXJzIHRoZSBydW4gaW5zdGVhZCBvZiBvcnBoYW5pbmcgaXQuXG4gIGF3YWl0IHNldHRsZVBoYXNlKG9wcyk7XG5cbiAgLy8gUmVidWlsZCB0aGUgaW5saW5lIGJhdGNoIGluIGRldGVybWluaXN0aWMgb3JkZXIuIGBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHNgXG4gIC8vIGlzIGEgU2V0IHNlZWRlZCBmcm9tIHRoZSBvcmRlcmVkIGZpcnN0LU4gc2xpY2UsIHNvIGl0ZXJhdGluZyBpdCBwcmVzZXJ2ZXNcbiAgLy8gc3RlcEl0ZW1zIG9yZGVyOyBldmVyeSBpZCBpbiBpdCB3YXMgc2V0IGJ5IHRoZSBsYXp5IGJyYW5jaCBhYm92ZS5cbiAgY29uc3QgbGF6eUlubGluZVN0ZXBzOiBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdFsnbGF6eUlubGluZVN0ZXBzJ10gPSBbXTtcbiAgZm9yIChjb25zdCBjb3JyZWxhdGlvbklkIG9mIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcykge1xuICAgIGNvbnN0IGxhenlTdGVwID0gbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5nZXQoY29ycmVsYXRpb25JZCk7XG4gICAgaWYgKGxhenlTdGVwKSBsYXp5SW5saW5lU3RlcHMucHVzaChsYXp5U3RlcCk7XG4gIH1cblxuICAvLyBGaW5kIHRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCAobWluaW11bSB0aW1lb3V0KVxuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICBsZXQgc29vbmVzdFdhaXQ6IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfSB8IHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgY29uc3QgZGVsYXlNcyA9IE1hdGgubWF4KDEwMDAsIHJlc3VtZUF0TXMgLSBub3cpO1xuICAgIGNvbnN0IHRpbWVvdXRTZWNvbmRzID0gTWF0aC5jZWlsKGRlbGF5TXMgLyAxMDAwKTtcbiAgICBpZiAoIXNvb25lc3RXYWl0IHx8IHRpbWVvdXRTZWNvbmRzIDwgc29vbmVzdFdhaXQuc2Vjb25kcykge1xuICAgICAgc29vbmVzdFdhaXQgPSB7XG4gICAgICAgIHNlY29uZHM6IHRpbWVvdXRTZWNvbmRzLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICAgIC4uLihmYWlsZWRTdGVwQ29ycmVsYXRpb25JZHMuc2l6ZSA+IDBcbiAgICAgID8gQXR0cmlidXRlLldvcmtmbG93U3RlcHNGYWlsZWRTZXJpYWxpemF0aW9uKFxuICAgICAgICAgIGZhaWxlZFN0ZXBDb3JyZWxhdGlvbklkcy5zaXplXG4gICAgICAgIClcbiAgICAgIDoge30pLFxuICAgIC4uLihyZXNpbGllbnREaXNwYXRjaFJlY292ZXJlZCA+IDBcbiAgICAgID8gQXR0cmlidXRlLlN0ZXBSZXNpbGllbnREaXNwYXRjaFJlY292ZXJlZChyZXNpbGllbnREaXNwYXRjaFJlY292ZXJlZClcbiAgICAgIDoge30pLFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHBlbmRpbmdTdGVwczogc3RlcEl0ZW1zLFxuICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzLFxuICAgIHF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkcyxcbiAgICBsYXp5SW5saW5lU3RlcHMsXG4gICAgaW5saW5lQ2xhaW1zLFxuICAgIGRlZmVycmVkQmF0Y2hXb3JrLFxuICAgIC8vIE9uIGhvb2sgY29uZmxpY3QgdGhlIGNhbGxlciBhZHZhbmNlcyB0aGUgd29ya2Zsb3cgb3ZlciB0aGUgY29uZmxpY3RcbiAgICAvLyBiZWZvcmUgc2NoZWR1bGluZyBhbnl0aGluZyBhbmQgbmV2ZXIgcmVhZHMgdGhlIHdhaXQgdGltZW91dCwgc28gZG9uJ3RcbiAgICAvLyByZXBvcnQgb25lLiBUaGUgbmV4dCBwYXNzLCB3aGljaCBzZWVzIHRoZSBjb25mbGljdCBzZXR0bGVkLCByZXBvcnRzIGl0LlxuICAgIHdhaXRUaW1lb3V0OlxuICAgICAgaG9va0NvbmZsaWN0Q29ycmVsYXRpb25JZHMubGVuZ3RoID4gMCA/IHVuZGVmaW5lZCA6IHNvb25lc3RXYWl0LFxuICAgIGhhc0hvb2tDb25mbGljdDogaG9va0NvbmZsaWN0Q29ycmVsYXRpb25JZHMubGVuZ3RoID4gMCxcbiAgICBob29rQ29uZmxpY3RDb3JyZWxhdGlvbklkcyxcbiAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzLmxlbmd0aCA+IDAsXG4gICAgYXdhaXRlZEhvb2tDb3JyZWxhdGlvbklkcyxcbiAgICAvLyBUaGUgZGVsdGEgYWNjb3VudHMgZm9yIHRoZSB3aG9sZSBsb2cgb25seSBpZiB0aGUgd3JpdGUgdGhhdCByZXR1cm5lZCBpdFxuICAgIC8vIHdhcyB0aGlzIHN1c3BlbnNpb24ncyBvbmx5IG9uZSDigJQgYW55dGhpbmcgd3JpdHRlbiBhZnRlciBpdCBsYW5kZWQgYWJvdmVcbiAgICAvLyB0aGUgZGVsdGEgYW5kIGlzIG1pc3NpbmcgZnJvbSB0aGUgY2FsbGVyJ3MgbG9nLlxuICAgIGV2ZW50TG9nQ2FycmllZEZvcndhcmQ6IGRlbHRhQWJzb3JiZWQgJiYgZ3VhcmRlZFdyaXRlcyA9PT0gMSxcbiAgICBoYXNBdHRyaWJ1dGVFdmVudHM6IGF0dHJpYnV0ZUl0ZW1zLmxlbmd0aCA+IDAsXG4gICAgaGFzSG9va0V2ZW50czogaG9va3NOZWVkaW5nQ3JlYXRpb24ubGVuZ3RoID4gMCxcbiAgICBob29rQ3JlYXRpb25NcyxcbiAgICBzZXJpYWxpemF0aW9uQmxvY2tlckNvdW50LFxuICAgIHNlcmlhbGl6YXRpb25CbG9ja2VycyxcbiAgICByZXBvcnRlZEV2ZW50Q291bnQ6IHJlcG9ydGVkRXZlbnRzLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gYGV2ZW50cy5jcmVhdGVgIHJlamVjdGlvbiBpcyBkZXRlcm1pbmlzdGljIFdvcmxkIHZhbGlkYXRpb25cbiAqIHJhdGhlciB0aGFuIGEgdHJhbnNpZW50L3N0b3JhZ2UgZXJyb3IuIExvY2FsIFdvcmxkc1xuICogKHdvcmxkLWxvY2FsLCB3b3JsZC1wb3N0Z3JlcykgdGhyb3cgYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgZGlyZWN0bHk7XG4gKiByZW1vdGUgV29ybGRzIHN1cmZhY2UgdGhlIGVxdWl2YWxlbnQgc2VydmVyLXNpZGUgcmVqZWN0aW9uIGFzIGFcbiAqIGBXb3JrZmxvd1dvcmxkRXJyb3JgIHdpdGggSFRUUCBzdGF0dXMgNDAwLiBUaGUgbmFtZSBjaGVjayBjb3ZlcnNcbiAqIGBBdHRyaWJ1dGVWYWxpZGF0aW9uRXJyb3JgIGluc3RhbmNlcyBmcm9tIGEgZGlmZmVyZW50IGNvcHkgb2ZcbiAqIGBAd29ya2Zsb3cvd29ybGRgIHRoYW4gdGhlIG9uZSB0aGlzIHBhY2thZ2UgcmVzb2x2ZWQuXG4gKi9cbmZ1bmN0aW9uIGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnI6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcikgcmV0dXJuIHRydWU7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0F0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gV29ya2Zsb3dXb3JsZEVycm9yLmlzKGVycikgJiYgZXJyLnN0YXR1cyA9PT0gNDAwO1xufVxuIl19